cli: migrate layout remove, apply, revert
This commit is contained in:
parent
69ddaafc60
commit
819f4f0050
3 changed files with 65 additions and 102 deletions
|
@ -1,7 +1,6 @@
|
||||||
use bytesize::ByteSize;
|
use bytesize::ByteSize;
|
||||||
|
|
||||||
use format_table::format_table;
|
use format_table::format_table;
|
||||||
use garage_util::crdt::Crdt;
|
|
||||||
use garage_util::error::*;
|
use garage_util::error::*;
|
||||||
|
|
||||||
use garage_rpc::layout::*;
|
use garage_rpc::layout::*;
|
||||||
|
@ -10,33 +9,6 @@ use garage_rpc::*;
|
||||||
|
|
||||||
use crate::cli::*;
|
use crate::cli::*;
|
||||||
|
|
||||||
pub async fn cmd_remove_role(
|
|
||||||
rpc_cli: &Endpoint<SystemRpc, ()>,
|
|
||||||
rpc_host: NodeID,
|
|
||||||
args: RemoveRoleOpt,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mut layout = fetch_layout(rpc_cli, rpc_host).await?;
|
|
||||||
|
|
||||||
let mut roles = layout.current().roles.clone();
|
|
||||||
roles.merge(&layout.staging.get().roles);
|
|
||||||
|
|
||||||
let deleted_node =
|
|
||||||
find_matching_node(roles.items().iter().map(|(id, _, _)| *id), &args.node_id)?;
|
|
||||||
|
|
||||||
layout
|
|
||||||
.staging
|
|
||||||
.get_mut()
|
|
||||||
.roles
|
|
||||||
.merge(&roles.update_mutator(deleted_node, NodeRoleV(None)));
|
|
||||||
|
|
||||||
send_layout(rpc_cli, rpc_host, layout).await?;
|
|
||||||
|
|
||||||
println!("Role removal is staged but not yet committed.");
|
|
||||||
println!("Use `garage layout show` to view staged role changes,");
|
|
||||||
println!("and `garage layout apply` to enact staged changes.");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn cmd_show_layout(
|
pub async fn cmd_show_layout(
|
||||||
rpc_cli: &Endpoint<SystemRpc, ()>,
|
rpc_cli: &Endpoint<SystemRpc, ()>,
|
||||||
rpc_host: NodeID,
|
rpc_host: NodeID,
|
||||||
|
@ -85,47 +57,6 @@ pub async fn cmd_show_layout(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cmd_apply_layout(
|
|
||||||
rpc_cli: &Endpoint<SystemRpc, ()>,
|
|
||||||
rpc_host: NodeID,
|
|
||||||
apply_opt: ApplyLayoutOpt,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let layout = fetch_layout(rpc_cli, rpc_host).await?;
|
|
||||||
|
|
||||||
let (layout, msg) = layout.apply_staged_changes(apply_opt.version)?;
|
|
||||||
for line in msg.iter() {
|
|
||||||
println!("{}", line);
|
|
||||||
}
|
|
||||||
|
|
||||||
send_layout(rpc_cli, rpc_host, layout).await?;
|
|
||||||
|
|
||||||
println!("New cluster layout with updated role assignment has been applied in cluster.");
|
|
||||||
println!("Data will now be moved around between nodes accordingly.");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn cmd_revert_layout(
|
|
||||||
rpc_cli: &Endpoint<SystemRpc, ()>,
|
|
||||||
rpc_host: NodeID,
|
|
||||||
revert_opt: RevertLayoutOpt,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if !revert_opt.yes {
|
|
||||||
return Err(Error::Message(
|
|
||||||
"Please add the --yes flag to run the layout revert operation".into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let layout = fetch_layout(rpc_cli, rpc_host).await?;
|
|
||||||
|
|
||||||
let layout = layout.revert_staged_changes()?;
|
|
||||||
|
|
||||||
send_layout(rpc_cli, rpc_host, layout).await?;
|
|
||||||
|
|
||||||
println!("All proposed role changes in cluster layout have been canceled.");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn cmd_config_layout(
|
pub async fn cmd_config_layout(
|
||||||
rpc_cli: &Endpoint<SystemRpc, ()>,
|
rpc_cli: &Endpoint<SystemRpc, ()>,
|
||||||
rpc_host: NodeID,
|
rpc_host: NodeID,
|
||||||
|
|
|
@ -233,27 +233,6 @@ pub fn print_bucket_info(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_matching_node(
|
|
||||||
cand: impl std::iter::Iterator<Item = Uuid>,
|
|
||||||
pattern: &str,
|
|
||||||
) -> Result<Uuid, Error> {
|
|
||||||
let mut candidates = vec![];
|
|
||||||
for c in cand {
|
|
||||||
if hex::encode(c).starts_with(pattern) && !candidates.contains(&c) {
|
|
||||||
candidates.push(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if candidates.len() != 1 {
|
|
||||||
Err(Error::Message(format!(
|
|
||||||
"{} nodes match '{}'",
|
|
||||||
candidates.len(),
|
|
||||||
pattern,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Ok(candidates[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_worker_list(wi: HashMap<usize, WorkerInfo>, wlo: WorkerListOpt) {
|
pub fn print_worker_list(wi: HashMap<usize, WorkerInfo>, wlo: WorkerListOpt) {
|
||||||
let mut wi = wi.into_iter().collect::<Vec<_>>();
|
let mut wi = wi.into_iter().collect::<Vec<_>>();
|
||||||
wi.sort_by_key(|(tid, info)| {
|
wi.sort_by_key(|(tid, info)| {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use bytesize::ByteSize;
|
//use bytesize::ByteSize;
|
||||||
use format_table::format_table;
|
//use format_table::format_table;
|
||||||
|
|
||||||
use garage_util::error::*;
|
use garage_util::error::*;
|
||||||
|
|
||||||
|
@ -14,21 +14,14 @@ impl Cli {
|
||||||
pub async fn layout_command_dispatch(&self, cmd: LayoutOperation) -> Result<(), Error> {
|
pub async fn layout_command_dispatch(&self, cmd: LayoutOperation) -> Result<(), Error> {
|
||||||
match cmd {
|
match cmd {
|
||||||
LayoutOperation::Assign(assign_opt) => self.cmd_assign_role(assign_opt).await,
|
LayoutOperation::Assign(assign_opt) => self.cmd_assign_role(assign_opt).await,
|
||||||
|
LayoutOperation::Remove(remove_opt) => self.cmd_remove_role(remove_opt).await,
|
||||||
|
LayoutOperation::Apply(apply_opt) => self.cmd_apply_layout(apply_opt).await,
|
||||||
|
LayoutOperation::Revert(revert_opt) => self.cmd_revert_layout(revert_opt).await,
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
LayoutOperation::Remove(remove_opt) => {
|
|
||||||
cli_v1::cmd_remove_role(&self.system_rpc_endpoint, self.rpc_host, remove_opt).await
|
|
||||||
}
|
|
||||||
LayoutOperation::Show => {
|
LayoutOperation::Show => {
|
||||||
cli_v1::cmd_show_layout(&self.system_rpc_endpoint, self.rpc_host).await
|
cli_v1::cmd_show_layout(&self.system_rpc_endpoint, self.rpc_host).await
|
||||||
}
|
}
|
||||||
LayoutOperation::Apply(apply_opt) => {
|
|
||||||
cli_v1::cmd_apply_layout(&self.system_rpc_endpoint, self.rpc_host, apply_opt).await
|
|
||||||
}
|
|
||||||
LayoutOperation::Revert(revert_opt) => {
|
|
||||||
cli_v1::cmd_revert_layout(&self.system_rpc_endpoint, self.rpc_host, revert_opt)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
LayoutOperation::Config(config_opt) => {
|
LayoutOperation::Config(config_opt) => {
|
||||||
cli_v1::cmd_config_layout(&self.system_rpc_endpoint, self.rpc_host, config_opt)
|
cli_v1::cmd_config_layout(&self.system_rpc_endpoint, self.rpc_host, config_opt)
|
||||||
.await
|
.await
|
||||||
|
@ -116,4 +109,64 @@ impl Cli {
|
||||||
println!("and `garage layout apply` to enact staged changes.");
|
println!("and `garage layout apply` to enact staged changes.");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn cmd_remove_role(&self, opt: RemoveRoleOpt) -> Result<(), Error> {
|
||||||
|
let status = self.api_request(GetClusterStatusRequest).await?;
|
||||||
|
let layout = self.api_request(GetClusterLayoutRequest).await?;
|
||||||
|
|
||||||
|
let all_node_ids_iter = status
|
||||||
|
.nodes
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.id.as_str())
|
||||||
|
.chain(layout.roles.iter().map(|x| x.id.as_str()));
|
||||||
|
|
||||||
|
let id = find_matching_node(all_node_ids_iter.clone(), &opt.node_id)?;
|
||||||
|
|
||||||
|
let actions = vec![NodeRoleChange {
|
||||||
|
id,
|
||||||
|
action: NodeRoleChangeEnum::Remove { remove: true },
|
||||||
|
}];
|
||||||
|
|
||||||
|
self.api_request(UpdateClusterLayoutRequest(actions))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
println!("Role removal is staged but not yet committed.");
|
||||||
|
println!("Use `garage layout show` to view staged role changes,");
|
||||||
|
println!("and `garage layout apply` to enact staged changes.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cmd_apply_layout(&self, apply_opt: ApplyLayoutOpt) -> Result<(), Error> {
|
||||||
|
let missing_version_error = r#"
|
||||||
|
Please pass the new layout version number to ensure that you are writing the correct version of the cluster layout.
|
||||||
|
To know the correct value of the new layout version, invoke `garage layout show` and review the proposed changes.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let req = ApplyClusterLayoutRequest {
|
||||||
|
version: apply_opt.version.ok_or_message(missing_version_error)?,
|
||||||
|
};
|
||||||
|
let res = self.api_request(req).await?;
|
||||||
|
|
||||||
|
for line in res.message.iter() {
|
||||||
|
println!("{}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("New cluster layout with updated role assignment has been applied in cluster.");
|
||||||
|
println!("Data will now be moved around between nodes accordingly.");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cmd_revert_layout(&self, revert_opt: RevertLayoutOpt) -> Result<(), Error> {
|
||||||
|
if !revert_opt.yes {
|
||||||
|
return Err(Error::Message(
|
||||||
|
"Please add the --yes flag to run the layout revert operation".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.api_request(RevertClusterLayoutRequest).await?;
|
||||||
|
|
||||||
|
println!("All proposed role changes in cluster layout have been canceled.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue