aboutsummaryrefslogtreecommitdiff
path: root/src/garage
diff options
context:
space:
mode:
Diffstat (limited to 'src/garage')
-rw-r--r--src/garage/admin/mod.rs39
-rw-r--r--src/garage/cli/cmd.rs3
-rw-r--r--src/garage/cli/structs.rs15
-rw-r--r--src/garage/server.rs2
-rw-r--r--src/garage/tests/common/garage.rs6
5 files changed, 63 insertions, 2 deletions
diff --git a/src/garage/admin/mod.rs b/src/garage/admin/mod.rs
index 300e1211..e2468143 100644
--- a/src/garage/admin/mod.rs
+++ b/src/garage/admin/mod.rs
@@ -44,6 +44,7 @@ pub enum AdminRpc {
Stats(StatsOpt),
Worker(WorkerOperation),
BlockOperation(BlockOperation),
+ MetaOperation(MetaOperation),
// Replies
Ok(String),
@@ -465,6 +466,43 @@ impl AdminRpcHandler {
)]))
}
}
+
+ // ================ META DB COMMANDS ====================
+
+ async fn handle_meta_cmd(self: &Arc<Self>, mo: &MetaOperation) -> Result<AdminRpc, Error> {
+ match mo {
+ MetaOperation::Snapshot { all: true } => {
+ let to = self.garage.system.cluster_layout().all_nodes().to_vec();
+
+ let resps = futures::future::join_all(to.iter().map(|to| async move {
+ let to = (*to).into();
+ self.endpoint
+ .call(
+ &to,
+ AdminRpc::MetaOperation(MetaOperation::Snapshot { all: false }),
+ PRIO_NORMAL,
+ )
+ .await
+ }))
+ .await;
+
+ let mut ret = vec![];
+ for (to, resp) in to.iter().zip(resps.iter()) {
+ let res_str = match resp {
+ Ok(_) => "ok".to_string(),
+ Err(e) => format!("error: {}", e),
+ };
+ ret.push(format!("{:?}\t{}", to, res_str));
+ }
+
+ Ok(AdminRpc::Ok(format_table_to_string(ret)))
+ }
+ MetaOperation::Snapshot { all: false } => {
+ garage_model::snapshot::async_snapshot_metadata(&self.garage).await?;
+ Ok(AdminRpc::Ok("Snapshot has been saved.".into()))
+ }
+ }
+ }
}
#[async_trait]
@@ -481,6 +519,7 @@ impl EndpointHandler<AdminRpc> for AdminRpcHandler {
AdminRpc::Stats(opt) => self.handle_stats(opt.clone()).await,
AdminRpc::Worker(wo) => self.handle_worker_cmd(wo).await,
AdminRpc::BlockOperation(bo) => self.handle_block_cmd(bo).await,
+ AdminRpc::MetaOperation(mo) => self.handle_meta_cmd(mo).await,
m => Err(GarageError::unexpected_rpc_message(m).into()),
}
}
diff --git a/src/garage/cli/cmd.rs b/src/garage/cli/cmd.rs
index 7440457f..a84061a7 100644
--- a/src/garage/cli/cmd.rs
+++ b/src/garage/cli/cmd.rs
@@ -41,6 +41,9 @@ pub async fn cli_command_dispatch(
Command::Block(bo) => {
cmd_admin(admin_rpc_endpoint, rpc_host, AdminRpc::BlockOperation(bo)).await
}
+ Command::Meta(mo) => {
+ cmd_admin(admin_rpc_endpoint, rpc_host, AdminRpc::MetaOperation(mo)).await
+ }
_ => unreachable!(),
}
}
diff --git a/src/garage/cli/structs.rs b/src/garage/cli/structs.rs
index a5e2e6e8..1f572a9a 100644
--- a/src/garage/cli/structs.rs
+++ b/src/garage/cli/structs.rs
@@ -52,6 +52,10 @@ pub enum Command {
#[structopt(name = "block", version = garage_version())]
Block(BlockOperation),
+ /// Operations on the metadata db
+ #[structopt(name = "meta", version = garage_version())]
+ Meta(MetaOperation),
+
/// Convert metadata db between database engine formats
#[structopt(name = "convert-db", version = garage_version())]
ConvertDb(convert_db::ConvertDbOpt),
@@ -611,3 +615,14 @@ pub enum BlockOperation {
blocks: Vec<String>,
},
}
+
+#[derive(Serialize, Deserialize, StructOpt, Debug, Eq, PartialEq, Clone, Copy)]
+pub enum MetaOperation {
+ /// Save a snapshot of the metadata db file
+ #[structopt(name = "snapshot", version = garage_version())]
+ Snapshot {
+ /// Run on all nodes instead of only local node
+ #[structopt(long = "all")]
+ all: bool,
+ },
+}
diff --git a/src/garage/server.rs b/src/garage/server.rs
index 6323f957..65bf34db 100644
--- a/src/garage/server.rs
+++ b/src/garage/server.rs
@@ -51,7 +51,7 @@ pub async fn run_server(config_file: PathBuf, secrets: Secrets) -> Result<(), Er
let (background, await_background_done) = BackgroundRunner::new(watch_cancel.clone());
info!("Spawning Garage workers...");
- garage.spawn_workers(&background);
+ garage.spawn_workers(&background)?;
if config.admin.trace_sink.is_some() {
info!("Initialize tracing...");
diff --git a/src/garage/tests/common/garage.rs b/src/garage/tests/common/garage.rs
index f1c1efc8..db23d316 100644
--- a/src/garage/tests/common/garage.rs
+++ b/src/garage/tests/common/garage.rs
@@ -42,6 +42,10 @@ impl Instance {
.ok()
.unwrap_or_else(|| env::temp_dir().join(format!("garage-integ-test-{}", port)));
+ let db_engine = env::var("GARAGE_TEST_INTEGRATION_DB_ENGINE")
+ .ok()
+ .unwrap_or_else(|| "lmdb".into());
+
// Clean test runtime directory
if path.exists() {
fs::remove_dir_all(&path).expect("Could not clean test runtime directory");
@@ -52,7 +56,7 @@ impl Instance {
r#"
metadata_dir = "{path}/meta"
data_dir = "{path}/data"
-db_engine = "lmdb"
+db_engine = "{db_engine}"
replication_factor = 1