Admin API refactoring: convert existing commands to API requests (step 3) #945
9 changed files with 94 additions and 68 deletions
|
@ -77,6 +77,9 @@ admin_endpoints![
|
||||||
AddBucketAlias,
|
AddBucketAlias,
|
||||||
RemoveBucketAlias,
|
RemoveBucketAlias,
|
||||||
|
|
||||||
|
// Node operations
|
||||||
|
CreateMetadataSnapshot,
|
||||||
|
|
||||||
// Worker operations
|
// Worker operations
|
||||||
ListWorkers,
|
ListWorkers,
|
||||||
GetWorkerInfo,
|
GetWorkerInfo,
|
||||||
|
@ -91,6 +94,8 @@ admin_endpoints![
|
||||||
];
|
];
|
||||||
|
|
||||||
local_admin_endpoints![
|
local_admin_endpoints![
|
||||||
|
// Node operations
|
||||||
|
CreateMetadataSnapshot,
|
||||||
// Background workers
|
// Background workers
|
||||||
ListWorkers,
|
ListWorkers,
|
||||||
GetWorkerInfo,
|
GetWorkerInfo,
|
||||||
|
@ -623,6 +628,18 @@ pub struct RemoveBucketAliasRequest {
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse);
|
pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse);
|
||||||
|
|
||||||
|
// **********************************************
|
||||||
|
// Node operations
|
||||||
|
// **********************************************
|
||||||
|
|
||||||
|
// ---- CreateMetadataSnapshot ----
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct LocalCreateMetadataSnapshotRequest;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct LocalCreateMetadataSnapshotResponse;
|
||||||
|
|
||||||
// **********************************************
|
// **********************************************
|
||||||
// Worker operations
|
// Worker operations
|
||||||
// **********************************************
|
// **********************************************
|
||||||
|
|
|
@ -16,6 +16,7 @@ mod key;
|
||||||
mod special;
|
mod special;
|
||||||
|
|
||||||
mod block;
|
mod block;
|
||||||
|
mod node;
|
||||||
mod worker;
|
mod worker;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
23
src/api/admin/node.rs
Normal file
23
src/api/admin/node.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use garage_model::garage::Garage;
|
||||||
|
|
||||||
|
use crate::api::*;
|
||||||
|
use crate::error::Error;
|
||||||
|
use crate::{Admin, RequestHandler};
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl RequestHandler for LocalCreateMetadataSnapshotRequest {
|
||||||
|
type Response = LocalCreateMetadataSnapshotResponse;
|
||||||
|
|
||||||
|
async fn handle(
|
||||||
|
self,
|
||||||
|
garage: &Arc<Garage>,
|
||||||
|
_admin: &Admin,
|
||||||
|
) -> Result<LocalCreateMetadataSnapshotResponse, Error> {
|
||||||
|
garage_model::snapshot::async_snapshot_metadata(garage).await?;
|
||||||
|
Ok(LocalCreateMetadataSnapshotResponse)
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,8 @@ impl AdminApiRequest {
|
||||||
// Bucket aliases
|
// Bucket aliases
|
||||||
POST AddBucketAlias (body),
|
POST AddBucketAlias (body),
|
||||||
POST RemoveBucketAlias (body),
|
POST RemoveBucketAlias (body),
|
||||||
|
// Node APIs
|
||||||
|
POST CreateMetadataSnapshot (default::body, query::node),
|
||||||
// Worker APIs
|
// Worker APIs
|
||||||
POST ListWorkers (body_field, query::node),
|
POST ListWorkers (body_field, query::node),
|
||||||
POST GetWorkerInfo (body_field, query::node),
|
POST GetWorkerInfo (body_field, query::node),
|
||||||
|
|
|
@ -20,10 +20,6 @@ use garage_rpc::*;
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_model::helper::error::Error;
|
use garage_model::helper::error::Error;
|
||||||
|
|
||||||
use garage_api_admin::api::{AdminApiRequest, TaggedAdminApiResponse};
|
|
||||||
use garage_api_admin::RequestHandler as AdminApiEndpoint;
|
|
||||||
use garage_api_common::generic_server::ApiError;
|
|
||||||
|
|
||||||
use crate::cli::*;
|
use crate::cli::*;
|
||||||
use crate::repair::online::launch_online_repair;
|
use crate::repair::online::launch_online_repair;
|
||||||
|
|
||||||
|
@ -34,7 +30,6 @@ pub const ADMIN_RPC_PATH: &str = "garage/admin_rpc.rs/Rpc";
|
||||||
pub enum AdminRpc {
|
pub enum AdminRpc {
|
||||||
LaunchRepair(RepairOpt),
|
LaunchRepair(RepairOpt),
|
||||||
Stats(StatsOpt),
|
Stats(StatsOpt),
|
||||||
MetaOperation(MetaOperation),
|
|
||||||
|
|
||||||
// Replies
|
// Replies
|
||||||
Ok(String),
|
Ok(String),
|
||||||
|
@ -319,43 +314,6 @@ impl AdminRpcHandler {
|
||||||
t.data.gc_todo_len()?
|
t.data.gc_todo_len()?
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================ 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]
|
#[async_trait]
|
||||||
|
@ -368,7 +326,6 @@ impl EndpointHandler<AdminRpc> for AdminRpcHandler {
|
||||||
match message {
|
match message {
|
||||||
AdminRpc::LaunchRepair(opt) => self.handle_launch_repair(opt.clone()).await,
|
AdminRpc::LaunchRepair(opt) => self.handle_launch_repair(opt.clone()).await,
|
||||||
AdminRpc::Stats(opt) => self.handle_stats(opt.clone()).await,
|
AdminRpc::Stats(opt) => self.handle_stats(opt.clone()).await,
|
||||||
AdminRpc::MetaOperation(mo) => self.handle_meta_cmd(mo).await,
|
|
||||||
m => Err(GarageError::unexpected_rpc_message(m).into()),
|
m => Err(GarageError::unexpected_rpc_message(m).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
use garage_util::error::*;
|
|
||||||
|
|
||||||
use garage_rpc::system::*;
|
|
||||||
use garage_rpc::*;
|
use garage_rpc::*;
|
||||||
|
|
||||||
use garage_model::helper::error::Error as HelperError;
|
use garage_model::helper::error::Error as HelperError;
|
||||||
|
@ -22,18 +19,3 @@ pub async fn cmd_admin(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- utility ----
|
|
||||||
|
|
||||||
pub async fn fetch_status(
|
|
||||||
rpc_cli: &Endpoint<SystemRpc, ()>,
|
|
||||||
rpc_host: NodeID,
|
|
||||||
) -> Result<Vec<KnownNodeInfo>, Error> {
|
|
||||||
match rpc_cli
|
|
||||||
.call(&rpc_host, SystemRpc::GetKnownNodes, PRIO_NORMAL)
|
|
||||||
.await??
|
|
||||||
{
|
|
||||||
SystemRpc::ReturnKnownNodes(nodes) => Ok(nodes),
|
|
||||||
resp => Err(Error::unexpected_rpc_message(resp)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -260,6 +260,19 @@ pub async fn cmd_layout_skip_dead_nodes(
|
||||||
|
|
||||||
// --- utility ---
|
// --- utility ---
|
||||||
|
|
||||||
|
pub async fn fetch_status(
|
||||||
|
rpc_cli: &Endpoint<SystemRpc, ()>,
|
||||||
|
rpc_host: NodeID,
|
||||||
|
) -> Result<Vec<KnownNodeInfo>, Error> {
|
||||||
|
match rpc_cli
|
||||||
|
.call(&rpc_host, SystemRpc::GetKnownNodes, PRIO_NORMAL)
|
||||||
|
.await??
|
||||||
|
{
|
||||||
|
SystemRpc::ReturnKnownNodes(nodes) => Ok(nodes),
|
||||||
|
resp => Err(Error::unexpected_rpc_message(resp)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn fetch_layout(
|
pub async fn fetch_layout(
|
||||||
rpc_cli: &Endpoint<SystemRpc, ()>,
|
rpc_cli: &Endpoint<SystemRpc, ()>,
|
||||||
rpc_host: NodeID,
|
rpc_host: NodeID,
|
||||||
|
|
|
@ -4,6 +4,7 @@ pub mod key;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
|
|
||||||
pub mod block;
|
pub mod block;
|
||||||
|
pub mod node;
|
||||||
pub mod worker;
|
pub mod worker;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -43,6 +44,7 @@ impl Cli {
|
||||||
Command::Key(ko) => self.cmd_key(ko).await,
|
Command::Key(ko) => self.cmd_key(ko).await,
|
||||||
Command::Worker(wo) => self.cmd_worker(wo).await,
|
Command::Worker(wo) => self.cmd_worker(wo).await,
|
||||||
Command::Block(bo) => self.cmd_block(bo).await,
|
Command::Block(bo) => self.cmd_block(bo).await,
|
||||||
|
Command::Meta(mo) => self.cmd_meta(mo).await,
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
Command::Repair(ro) => cli_v1::cmd_admin(
|
Command::Repair(ro) => cli_v1::cmd_admin(
|
||||||
|
@ -57,13 +59,6 @@ impl Cli {
|
||||||
.await
|
.await
|
||||||
.ok_or_message("cli_v1")
|
.ok_or_message("cli_v1")
|
||||||
}
|
}
|
||||||
Command::Meta(mo) => cli_v1::cmd_admin(
|
|
||||||
&self.admin_rpc_endpoint,
|
|
||||||
self.rpc_host,
|
|
||||||
AdminRpc::MetaOperation(mo),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.ok_or_message("cli_v1"),
|
|
||||||
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
36
src/garage/cli_v2/node.rs
Normal file
36
src/garage/cli_v2/node.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
use format_table::format_table;
|
||||||
|
|
||||||
|
use garage_util::error::*;
|
||||||
|
|
||||||
|
use garage_api_admin::api::*;
|
||||||
|
|
||||||
|
use crate::cli::structs::*;
|
||||||
|
use crate::cli_v2::*;
|
||||||
|
|
||||||
|
impl Cli {
|
||||||
|
pub async fn cmd_meta(&self, cmd: MetaOperation) -> Result<(), Error> {
|
||||||
|
let MetaOperation::Snapshot { all } = cmd;
|
||||||
|
|
||||||
|
let res = self
|
||||||
|
.api_request(CreateMetadataSnapshotRequest {
|
||||||
|
node: if all {
|
||||||
|
"*".to_string()
|
||||||
|
} else {
|
||||||
|
hex::encode(self.rpc_host)
|
||||||
|
},
|
||||||
|
body: LocalCreateMetadataSnapshotRequest,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut table = vec![];
|
||||||
|
for (node, err) in res.error.iter() {
|
||||||
|
table.push(format!("{:.16}\tError: {}", node, err));
|
||||||
|
}
|
||||||
|
for (node, _) in res.success.iter() {
|
||||||
|
table.push(format!("{:.16}\tOk", node));
|
||||||
|
}
|
||||||
|
format_table(table);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue