use crate::common::{self, app_context::AppContext, audit};
use crate::service::kernel_parameters;
use anyhow::{Context, Error, bail};
use manta_backend_dispatcher::types::ims::Image;
use nodeset::NodeSet;
use std::collections::HashMap;
pub use crate::service::kernel_parameters::KernelParamOperation;
pub async fn exec(
ctx: &AppContext<'_>,
token: &str,
xname_vec: &[String],
operation: &KernelParamOperation<'_>,
assume_yes: bool,
do_not_reboot: bool,
dry_run: bool,
) -> Result<(), Error> {
let verb = operation.verb();
let params = operation.params();
log::info!("{} kernel parameters", verb);
let changeset = kernel_parameters::prepare_kernel_params_changes(
&ctx.infra,
token,
xname_vec,
operation,
)
.await?;
if !changeset.has_changes {
bail!("No changes detected. Nothing to do");
}
let mut images_to_project: HashMap<String, Image> = HashMap::new();
for (image_id, mut image) in changeset.sbps_candidates.clone() {
if common::user_interaction::confirm(
"Kernel parameters using SBPS/iSCSI. \
Do you want to project the boot image \
through SBPS?",
assume_yes,
) {
log::info!(
"Setting 'sbps-project' metadata to \
'true' for image id '{}'",
image_id
);
image.set_boot_image_iscsi_ready();
log::debug!("Image:\n{:#?}", image);
images_to_project.insert(image_id, image);
} else {
log::info!("User chose to not project the image through SBPS");
}
}
let node_group: NodeSet = xname_vec
.join(", ")
.parse()
.context("Failed to parse node list")?;
println!(
"{} kernel params:\n{:?}\nFor nodes:\n{:?}",
verb,
params,
node_group.to_string()
);
if !common::user_interaction::confirm(
operation.confirm_message(),
assume_yes,
) {
bail!("Operation cancelled by user");
}
if dry_run {
println!("Dry-run enabled. No changes persisted into the system");
println!(
"Dry run mode. Would update kernel parameters below:\n{}",
serde_json::to_string_pretty(&changeset.boot_params)
.context("Failed to serialize boot parameters")?
);
if !images_to_project.is_empty() {
println!(
"Dry run mode. Would update images:\n{}",
serde_json::to_string_pretty(&images_to_project)
.context("Failed to serialize image map")?
);
}
} else {
log::info!("Persist changes");
kernel_parameters::apply_kernel_params_changes(
&ctx.infra,
token,
&changeset,
&images_to_project,
)
.await?;
}
audit::maybe_send_audit_with_group_lookup(
ctx.cli.kafka_audit_opt,
ctx.infra.backend,
token,
format!("{} kernel parameters: {}", verb, params),
xname_vec,
)
.await?;
if !do_not_reboot && changeset.has_changes && !dry_run {
log::info!("Restarting nodes");
crate::cli::commands::power_common::exec_nodes(
ctx,
crate::cli::commands::power_common::PowerAction::Reset,
&changeset.xnames_to_reboot.join(","),
true,
assume_yes,
"table",
token,
)
.await?;
}
Ok(())
}
pub use crate::common::node_ops::resolve_target_nodes;