mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-12 07:16:52 +00:00
Implement ring comparison algorithm
This commit is contained in:
+70
-1
@@ -61,6 +61,10 @@ pub enum Command {
|
||||
/// Configure Garage node
|
||||
#[structopt(name = "configure")]
|
||||
Configure(ConfigureOpt),
|
||||
|
||||
/// Remove Garage node from cluster
|
||||
#[structopt(name = "remove")]
|
||||
Remove(RemoveOpt),
|
||||
}
|
||||
|
||||
#[derive(StructOpt, Debug)]
|
||||
@@ -82,6 +86,16 @@ pub struct ConfigureOpt {
|
||||
n_tokens: u32,
|
||||
}
|
||||
|
||||
#[derive(StructOpt, Debug)]
|
||||
pub struct RemoveOpt {
|
||||
/// Node to configure (prefix of hexadecimal node id)
|
||||
node_id: String,
|
||||
|
||||
/// If this flag is not given, the node won't be removed
|
||||
#[structopt(long = "yes")]
|
||||
yes: bool,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let opt = Opt::from_args();
|
||||
@@ -102,11 +116,20 @@ async fn main() {
|
||||
let rpc_cli = RpcClient::new(&tls_config).expect("Could not create RPC client");
|
||||
|
||||
let resp = match opt.cmd {
|
||||
Command::Server(server_opt) => server::run_server(server_opt.config_file).await,
|
||||
Command::Server(server_opt) => {
|
||||
// Abort on panic (same behavior as in Go)
|
||||
std::panic::set_hook(Box::new(|panic_info| {
|
||||
eprintln!("{}", panic_info.to_string());
|
||||
std::process::abort();
|
||||
}));
|
||||
|
||||
server::run_server(server_opt.config_file).await
|
||||
}
|
||||
Command::Status => cmd_status(rpc_cli, opt.rpc_host).await,
|
||||
Command::Configure(configure_opt) => {
|
||||
cmd_configure(rpc_cli, opt.rpc_host, configure_opt).await
|
||||
}
|
||||
Command::Remove(remove_opt) => cmd_remove(rpc_cli, opt.rpc_host, remove_opt).await,
|
||||
};
|
||||
|
||||
if let Err(e) = resp {
|
||||
@@ -224,3 +247,49 @@ async fn cmd_configure(
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn cmd_remove(
|
||||
rpc_cli: RpcClient,
|
||||
rpc_host: SocketAddr,
|
||||
args: RemoveOpt,
|
||||
) -> Result<(), Error> {
|
||||
let mut config = match rpc_cli
|
||||
.call(&rpc_host, &Message::PullConfig, DEFAULT_TIMEOUT)
|
||||
.await?
|
||||
{
|
||||
Message::AdvertiseConfig(cfg) => cfg,
|
||||
resp => return Err(Error::Message(format!("Invalid RPC response: {:?}", resp))),
|
||||
};
|
||||
|
||||
let mut candidates = vec![];
|
||||
for (key, _) in config.members.iter() {
|
||||
if hex::encode(key).starts_with(&args.node_id) {
|
||||
candidates.push(key.clone());
|
||||
}
|
||||
}
|
||||
if candidates.len() != 1 {
|
||||
return Err(Error::Message(format!(
|
||||
"{} matching nodes",
|
||||
candidates.len()
|
||||
)));
|
||||
}
|
||||
|
||||
if !args.yes {
|
||||
return Err(Error::Message(format!(
|
||||
"Add the flag --yes to really remove {:?} from the cluster",
|
||||
candidates[0]
|
||||
)));
|
||||
}
|
||||
|
||||
config.members.remove(&candidates[0]);
|
||||
config.version += 1;
|
||||
|
||||
rpc_cli
|
||||
.call(
|
||||
&rpc_host,
|
||||
&Message::AdvertiseConfig(config),
|
||||
DEFAULT_TIMEOUT,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user