diff options
author | Alex Auvolat <alex@adnab.me> | 2022-05-05 13:40:31 +0200 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2022-05-10 13:25:10 +0200 |
commit | 7a19daafbd08b1372aa3c41eab9b3871c26bca80 (patch) | |
tree | 76d49a330c703658055373482660935019631922 /src/api/admin/cluster.rs | |
parent | 99fcfa3844a346463e5739fec19ac2a6b560adfc (diff) | |
download | garage-7a19daafbd08b1372aa3c41eab9b3871c26bca80.tar.gz garage-7a19daafbd08b1372aa3c41eab9b3871c26bca80.zip |
Implement /status Admin endpoint
Diffstat (limited to 'src/api/admin/cluster.rs')
-rw-r--r-- | src/api/admin/cluster.rs | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/api/admin/cluster.rs b/src/api/admin/cluster.rs new file mode 100644 index 00000000..9ed41944 --- /dev/null +++ b/src/api/admin/cluster.rs @@ -0,0 +1,69 @@ +use std::sync::Arc; +use std::collections::HashMap; +use std::net::{IpAddr, SocketAddr}; + +use serde::{Serialize}; + +use hyper::{Body, Request, Response, StatusCode}; + +use garage_util::data::*; +use garage_util::error::Error as GarageError; +use garage_rpc::layout::*; +use garage_rpc::system::*; + +use garage_model::garage::Garage; + + +use crate::error::*; + + +pub async fn handle_get_cluster_status( + garage: &Arc<Garage>, +) -> Result<Response<Body>, Error> { + let layout = garage.system.get_cluster_layout(); + + let res = GetClusterStatusResponse { + known_nodes: garage.system.get_known_nodes() + .into_iter() + .map(|i| (hex::encode(i.id), KnownNodeResp { + addr: i.addr, + is_up: i.is_up, + last_seen_secs_ago: i.last_seen_secs_ago, + hostname: i.status.hostname, + })) + .collect(), + roles: layout.roles.items() + .iter() + .filter(|(_, _, v)| v.0.is_some()) + .map(|(k, _, v)| (hex::encode(k), v.0.clone())) + .collect(), + staged_role_changes: layout.staging.items() + .iter() + .filter(|(k, _, v)| layout.roles.get(k) != Some(v)) + .map(|(k, _, v)| (hex::encode(k), v.0.clone())) + .collect(), + }; + + let resp_json = serde_json::to_string_pretty(&res).map_err(GarageError::from)?; + Ok(Response::builder() + .status(StatusCode::OK) + .body(Body::from(resp_json))?) +} + + +#[derive(Serialize)] +struct GetClusterStatusResponse { + #[serde(rename = "knownNodes")] + known_nodes: HashMap<String, KnownNodeResp>, + roles: HashMap<String, Option<NodeRole>>, + #[serde(rename = "stagedRoleChanges")] + staged_role_changes: HashMap<String, Option<NodeRole>>, +} + +#[derive(Serialize)] +struct KnownNodeResp { + addr: SocketAddr, + is_up: bool, + last_seen_secs_ago: Option<u64>, + hostname: String, +} |