manta_server/service/
migrate.rs1use std::collections::HashMap;
4
5use manta_backend_dispatcher::error::Error;
6use manta_backend_dispatcher::interfaces::{
7 hsm::group::GroupTrait, migrate_backup::MigrateBackupTrait,
8 migrate_restore::MigrateRestoreTrait,
9};
10
11use crate::server::common::{app_context::InfraContext, node_ops};
12
13pub async fn migrate_backup(
15 infra: &InfraContext<'_>,
16 token: &str,
17 bos: Option<&str>,
18 destination: Option<&str>,
19) -> Result<(), Error> {
20 infra
21 .backend
22 .migrate_backup(
23 token,
24 infra.shasta_base_url,
25 infra.shasta_root_cert,
26 bos,
27 destination,
28 )
29 .await
30}
31
32#[allow(clippy::too_many_arguments)]
34pub async fn migrate_restore(
35 infra: &InfraContext<'_>,
36 token: &str,
37 bos_file: Option<&str>,
38 cfs_file: Option<&str>,
39 hsm_file: Option<&str>,
40 ims_file: Option<&str>,
41 image_dir: Option<&str>,
42 overwrite: bool,
43) -> Result<(), Error> {
44 infra
50 .backend
51 .migrate_restore(
52 token,
53 infra.shasta_base_url,
54 infra.shasta_root_cert,
55 bos_file,
56 cfs_file,
57 hsm_file,
58 ims_file,
59 image_dir,
60 overwrite, overwrite, overwrite, overwrite, )
65 .await
66}
67
68#[derive(serde::Serialize)]
70pub struct NodeMigrationResult {
71 pub target_hsm_name: String,
73 pub parent_hsm_name: String,
75 pub target_members: Vec<String>,
77 pub parent_members: Vec<String>,
79}
80
81pub async fn migrate_nodes(
87 infra: &InfraContext<'_>,
88 token: &str,
89 target_hsm_name_vec: &[String],
90 parent_hsm_name_vec: &[String],
91 hosts_expression: &str,
92 dry_run: bool,
93 create_hsm_group: bool,
94) -> Result<(Vec<String>, Vec<NodeMigrationResult>), Error> {
95 let backend = infra.backend;
96
97 let xname_to_move_vec =
99 node_ops::resolve_hosts_expression(backend, token, hosts_expression, false)
100 .await?;
101
102 if xname_to_move_vec.is_empty() {
103 return Err(Error::BadRequest(
104 "The list of nodes to operate is empty. Nothing to do".to_string(),
105 ));
106 }
107
108 let mut hsm_group_summary: HashMap<String, Vec<String>> =
109 node_ops::get_curated_hsm_group_from_xname_hostlist(
110 backend,
111 token,
112 &xname_to_move_vec,
113 )
114 .await?;
115
116 hsm_group_summary
117 .retain(|hsm_name, _| parent_hsm_name_vec.contains(hsm_name));
118
119 tracing::debug!("xnames to move: {:?}", xname_to_move_vec);
120
121 let mut results = Vec::new();
122
123 for target_hsm_name in target_hsm_name_vec {
124 if backend.get_group(token, target_hsm_name).await.is_ok() {
125 tracing::debug!("The group '{target_hsm_name}' exists, good.");
126 } else if create_hsm_group {
127 tracing::info!(
128 "The group {} does not exist, it will be created",
129 target_hsm_name
130 );
131 if dry_run {
132 return Err(Error::BadRequest(format!(
133 "Dry-run selected, the group '{target_hsm_name}' created"
134 )));
135 }
136 } else {
137 return Err(Error::NotFound(format!(
138 "The group '{target_hsm_name}' does not exist and the option \
139 to create the group was not specified"
140 )));
141 }
142
143 for (parent_hsm_name, xnames) in &hsm_group_summary {
144 let (mut target_members, mut parent_members) = backend
145 .migrate_group_members(
146 token,
147 target_hsm_name,
148 parent_hsm_name,
149 &xnames.iter().map(String::as_str).collect::<Vec<&str>>(),
150 dry_run,
151 )
152 .await?;
153
154 target_members.sort();
155 parent_members.sort();
156
157 results.push(NodeMigrationResult {
158 target_hsm_name: target_hsm_name.clone(),
159 parent_hsm_name: parent_hsm_name.clone(),
160 target_members,
161 parent_members,
162 });
163 }
164 }
165
166 Ok((xname_to_move_vec, results))
167}