From ada0c8ab70b36a7dfa0f173b1117aeeb36748352 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 1 May 2026 16:57:27 +0000 Subject: [PATCH] admin api: add fields to GetNodeInfo result (fix #1429) (#1434) Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/1434 --- src/api/admin/api.rs | 23 +++++++++++++++++++++++ src/api/admin/node.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/api/admin/api.rs b/src/api/admin/api.rs index ed145ea7..bcfc3634 100644 --- a/src/api/admin/api.rs +++ b/src/api/admin/api.rs @@ -1165,6 +1165,29 @@ pub struct LocalGetNodeInfoResponse { pub rust_version: String, /// database engine used for metadata pub db_engine: String, + // FIXME for v3: remove Option<> and serde(default) for field below + // FIXME for v3: merge LocalGetNodeInfoResponse and NodeResp + /// Socket address used by other nodes to connect to this node for RPC + #[serde(default, skip_serializing_if = "Option::is_none")] + #[schema(value_type = Option)] + pub addr: Option, + /// Whether this node is connected in the cluster + #[serde(default, skip_serializing_if = "Option::is_none")] + pub is_up: Option, + /// Role assigned to this node in the current cluster layout + #[serde(default, skip_serializing_if = "Option::is_none")] + pub role: Option, + /// Whether this node is part of an older layout version and is draining data. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub draining: Option, + /// Total and available space on the disk partition(s) containing the data + /// directory(ies) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub data_partition: Option, + /// Total and available space on the disk partition containing the + /// metadata directory + #[serde(default, skip_serializing_if = "Option::is_none")] + pub metadata_partition: Option, } // ---- GetNodeStatistics ---- diff --git a/src/api/admin/node.rs b/src/api/admin/node.rs index 12163f18..8701a6a7 100644 --- a/src/api/admin/node.rs +++ b/src/api/admin/node.rs @@ -25,6 +25,9 @@ impl RequestHandler for LocalGetNodeInfoRequest { let sys_status = garage.system.local_status(); let hostname = sys_status.hostname.unwrap_or_default().to_string(); + let layout = garage.system.cluster_layout(); + let current_layout = layout.inner().current(); + Ok(LocalGetNodeInfoResponse { node_id: hex::encode(garage.system.id), hostname: Some(hostname), @@ -33,6 +36,41 @@ impl RequestHandler for LocalGetNodeInfoRequest { .map(|features| features.iter().map(ToString::to_string).collect()), rust_version: garage_util::version::rust_version().to_string(), db_engine: garage.db.engine(), + is_up: Some(true), + addr: garage + .system + .get_known_nodes() + .iter() + .find(|x| x.id == garage.system.id) + .and_then(|x| x.addr), + draining: Some( + current_layout.node_role(&garage.system.id).is_none() + && layout + .inner() + .versions + .iter() + .filter(|x| x.version != current_layout.version) + .any(|x| x.node_role(&garage.system.id).is_some()), + ), + role: current_layout + .node_role(&garage.system.id) + .map(|v| NodeAssignedRole { + zone: v.zone.clone(), + capacity: v.capacity, + tags: v.tags.clone(), + }), + data_partition: sys_status + .data_disk_avail + .map(|(avail, total)| FreeSpaceResp { + available: avail, + total, + }), + metadata_partition: sys_status + .meta_disk_avail + .map(|(avail, total)| FreeSpaceResp { + available: avail, + total, + }), }) } }