diff --git a/src/api/admin/api_server.rs b/src/api/admin/api_server.rs index 57842548..dfaac015 100644 --- a/src/api/admin/api_server.rs +++ b/src/api/admin/api_server.rs @@ -3,7 +3,9 @@ use std::sync::Arc; use async_trait::async_trait; use futures::future::Future; -use http::header::{CONTENT_TYPE, ALLOW, ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN}; +use http::header::{ + ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN, ALLOW, CONTENT_TYPE, +}; use hyper::{Body, Request, Response}; use opentelemetry::trace::{SpanRef, Tracer}; @@ -16,8 +18,8 @@ use garage_util::error::Error as GarageError; use crate::error::*; use crate::generic_server::*; -use crate::admin::router::{Authorization, Endpoint}; use crate::admin::cluster::*; +use crate::admin::router::{Authorization, Endpoint}; pub struct AdminApiServer { garage: Arc, @@ -123,6 +125,7 @@ impl ApiHandler for AdminApiServer { Endpoint::Options => self.handle_options(&req), Endpoint::Metrics => self.handle_metrics(), Endpoint::GetClusterStatus => handle_get_cluster_status(&self.garage).await, + Endpoint::GetClusterLayout => handle_get_cluster_layout(&self.garage).await, _ => Err(Error::NotImplemented(format!( "Admin endpoint {} not implemented yet", endpoint.name() diff --git a/src/api/admin/cluster.rs b/src/api/admin/cluster.rs index 9ed41944..f4835648 100644 --- a/src/api/admin/cluster.rs +++ b/src/api/admin/cluster.rs @@ -1,47 +1,37 @@ -use std::sync::Arc; use std::collections::HashMap; -use std::net::{IpAddr, SocketAddr}; +use std::net::SocketAddr; +use std::sync::Arc; -use serde::{Serialize}; +use serde::Serialize; -use hyper::{Body, Request, Response, StatusCode}; +use hyper::{Body, Response, StatusCode}; -use garage_util::data::*; -use garage_util::error::Error as GarageError; use garage_rpc::layout::*; -use garage_rpc::system::*; +use garage_util::error::Error as GarageError; use garage_model::garage::Garage; - use crate::error::*; - -pub async fn handle_get_cluster_status( - garage: &Arc, -) -> Result, Error> { - let layout = garage.system.get_cluster_layout(); - +pub async fn handle_get_cluster_status(garage: &Arc) -> Result, Error> { let res = GetClusterStatusResponse { - known_nodes: garage.system.get_known_nodes() + 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())) + .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(), + layout: get_cluster_layout(garage), }; let resp_json = serde_json::to_string_pretty(&res).map_err(GarageError::from)?; @@ -50,11 +40,44 @@ pub async fn handle_get_cluster_status( .body(Body::from(resp_json))?) } +pub async fn handle_get_cluster_layout(garage: &Arc) -> Result, Error> { + let res = get_cluster_layout(garage); + let resp_json = serde_json::to_string_pretty(&res).map_err(GarageError::from)?; + Ok(Response::builder() + .status(StatusCode::OK) + .body(Body::from(resp_json))?) +} + +fn get_cluster_layout(garage: &Arc) -> GetClusterLayoutResponse { + let layout = garage.system.get_cluster_layout(); + + GetClusterLayoutResponse { + 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(), + } +} #[derive(Serialize)] struct GetClusterStatusResponse { #[serde(rename = "knownNodes")] known_nodes: HashMap, + layout: GetClusterLayoutResponse, +} + +#[derive(Serialize)] +struct GetClusterLayoutResponse { roles: HashMap>, #[serde(rename = "stagedRoleChanges")] staged_role_changes: HashMap>, diff --git a/src/rpc/system.rs b/src/rpc/system.rs index a5b8d4f4..73c7b898 100644 --- a/src/rpc/system.rs +++ b/src/rpc/system.rs @@ -462,7 +462,6 @@ impl System { SystemRpc::ReturnKnownNodes(known_nodes) } - async fn handle_advertise_status( self: &Arc, from: Uuid,