manta_server/service/
migrate.rs1use std::collections::HashMap;
9
10use manta_backend_dispatcher::error::Error;
11use manta_backend_dispatcher::interfaces::hsm::group::GroupTrait;
12
13use crate::server::common::app_context::InfraContext;
14use crate::service::authorization::validate_user_group_members_access;
15use crate::service::node_ops;
16
17#[derive(serde::Serialize, utoipa::ToSchema)]
19pub struct NodeMigrationResult {
20 pub target_hsm_name: String,
22 pub parent_hsm_name: String,
24 pub target_members: Vec<String>,
26 pub parent_members: Vec<String>,
28}
29
30pub async fn migrate_nodes(
46 infra: &InfraContext<'_>,
47 token: &str,
48 target_group_name_vec: &[String],
49 parent_group_name_vec: &[String],
50 hosts_expression: &str,
51 dry_run: bool,
52 create_group: bool,
53) -> Result<(Vec<String>, Vec<NodeMigrationResult>), Error> {
54 let xname_to_move_vec = node_ops::from_user_hosts_expression_to_xname_vec(
55 infra,
56 token,
57 hosts_expression,
58 false,
59 )
60 .await?;
61
62 if xname_to_move_vec.is_empty() {
63 return Err(Error::BadRequest(
64 "The list of nodes to operate is empty. Nothing to do".to_string(),
65 ));
66 }
67
68 validate_user_group_members_access(infra, token, &xname_to_move_vec).await?;
76
77 let mut group_summary: HashMap<String, Vec<String>> =
78 node_ops::get_curated_group_from_xname_hostlist(
79 infra,
80 token,
81 &xname_to_move_vec,
82 )
83 .await?;
84
85 group_summary.retain(|hsm_name, _| parent_group_name_vec.contains(hsm_name));
86
87 tracing::debug!("xnames to move: {:?}", xname_to_move_vec);
88
89 let mut results = Vec::new();
90
91 for target_name in target_group_name_vec {
92 if infra.backend.get_group(token, target_name).await.is_ok() {
93 tracing::debug!("The group '{target_name}' exists, good.");
94 } else if create_group {
95 tracing::info!(
96 "The group {} does not exist, it will be created",
97 target_name
98 );
99 if dry_run {
100 return Err(Error::BadRequest(format!(
101 "Dry-run selected, the group '{target_name}' created"
102 )));
103 }
104 } else {
105 return Err(Error::NotFound(format!(
106 "The group '{target_name}' does not exist and the option \
107 to create the group was not specified"
108 )));
109 }
110
111 for (parent_group_name, xnames) in &group_summary {
112 let xnames_ref: Vec<&str> = xnames.iter().map(String::as_str).collect();
113 let (mut target_members, mut parent_members) = infra
114 .backend
115 .migrate_group_members(
116 token,
117 target_name,
118 parent_group_name,
119 &xnames_ref,
120 dry_run,
121 )
122 .await?;
123
124 target_members.sort();
125 parent_members.sort();
126
127 results.push(NodeMigrationResult {
128 target_hsm_name: target_name.clone(),
129 parent_hsm_name: parent_group_name.clone(),
130 target_members,
131 parent_members,
132 });
133 }
134 }
135
136 Ok((xname_to_move_vec, results))
137}