From 05c3f25b9a313c7926640a32a902cf1cf1fea772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1a=20Tomi=C4=87?= Date: Wed, 22 May 2024 19:04:27 +0200 Subject: [PATCH] feat(dre): Include more info in the registry dump - Version running on unassigned nodes - Elected GuestOS versions - Elected HostOS versions --- Cargo.Bazel.lock | 6 +- Cargo.lock | 1 + rs/cli/Cargo.toml | 1 + rs/cli/src/registry_dump.rs | 138 +++++++++++++++++++++-- rs/ic-management-backend/src/registry.rs | 16 ++- 5 files changed, 150 insertions(+), 12 deletions(-) diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock index 194566102..1ddaff30b 100644 --- a/Cargo.Bazel.lock +++ b/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "b0c1429a1d74326f983596231a5f060a6870760dedec91dc54e2a44ca49c6975", + "checksum": "3be9f0f64dc894dc197dfa66905c30cbcddf085666768a4cbbe06451358145e1", "crates": { "actix-codec 0.5.2": { "name": "actix-codec", @@ -11347,6 +11347,10 @@ "id": "ic-sys 0.9.0", "target": "ic_sys" }, + { + "id": "ic-types 0.9.0", + "target": "ic_types" + }, { "id": "itertools 0.12.1", "target": "itertools" diff --git a/Cargo.lock b/Cargo.lock index 833330344..e3efc2ba1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2251,6 +2251,7 @@ dependencies = [ "ic-registry-subnet-type", "ic-sns-wasm", "ic-sys", + "ic-types", "itertools 0.12.1", "keyring", "log", diff --git a/rs/cli/Cargo.toml b/rs/cli/Cargo.toml index 756989a84..38c43cf3c 100644 --- a/rs/cli/Cargo.toml +++ b/rs/cli/Cargo.toml @@ -46,6 +46,7 @@ ic-registry-local-registry = { workspace = true } ic-registry-subnet-type = { workspace = true } ic-sns-wasm = { workspace = true } ic-sys = { workspace = true } +ic-types = { workspace = true } itertools = { workspace = true } keyring = { workspace = true } log = { workspace = true } diff --git a/rs/cli/src/registry_dump.rs b/rs/cli/src/registry_dump.rs index df1c346f0..7d01e633a 100644 --- a/rs/cli/src/registry_dump.rs +++ b/rs/cli/src/registry_dump.rs @@ -1,6 +1,5 @@ use std::{collections::BTreeMap, path::PathBuf, str::FromStr, time::Duration}; -use anyhow::Error; use ic_base_types::{PrincipalId, RegistryVersion}; use ic_interfaces_registry::RegistryClient; use ic_management_backend::registry::{local_registry_path, sync_local_store, RegistryFamilyEntries}; @@ -8,9 +7,12 @@ use ic_management_types::Network; use ic_protobuf::registry::{ api_boundary_node::v1::ApiBoundaryNodeRecord, dc::v1::DataCenterRecord, + hostos_version::v1::HostosVersionRecord, node::v1::{ConnectionEndpoint, IPv4InterfaceConfig, NodeRecord}, node_operator::v1::NodeOperatorRecord, + replica_version::v1::ReplicaVersionRecord, subnet::v1::{EcdsaConfig, GossipConfig as GossipConfigProto, SubnetFeatures, SubnetRecord as SubnetRecordProto}, + unassigned_nodes_config::v1::UnassignedNodesConfigRecord, }; use ic_registry_keys::NODE_REWARDS_TABLE_KEY; use ic_registry_local_registry::LocalRegistry; @@ -20,14 +22,13 @@ use log::warn; use registry_canister::mutations::common::decode_registry_value; use serde::Serialize; -pub async fn dump_registry(path: &Option, network: &Network, version: &i64) -> Result<(), Error> { +pub async fn dump_registry(path: &Option, network: &Network, version: &i64) -> Result<(), anyhow::Error> { if let Some(path) = path { std::env::set_var("LOCAL_REGISTRY_PATH", path) } sync_local_store(network).await?; - let local_registry = LocalRegistry::new(local_registry_path(network), Duration::from_secs(10)) - .map_err(|e| anyhow::anyhow!("Couldn't create local registry client instance: {:?}", e))?; + let local_registry = LocalRegistry::new(local_registry_path(network), Duration::from_secs(10))?; // determine desired version let version = { @@ -38,12 +39,21 @@ pub async fn dump_registry(path: &Option, network: &Network, version: & } }; + let elected_guest_os_versions = get_elected_guest_os_versions(&local_registry, version)?; + let elected_host_os_versions = get_elected_host_os_versions(&local_registry, version)?; + let node_operators = get_node_operators(&local_registry, version)?; let dcs = get_data_centers(&local_registry, version)?; let subnets = get_subnets(&local_registry, version)?; + let unassigned_nodes_config = match get_unassigned_nodes(&local_registry, version) { + Ok(config) => Some(config), + Err(RegistryDumpError::RecordNotFound) => None, + Err(e) => return Err(e.into()), + }; + let nodes = get_nodes(&local_registry, version, &node_operators, &subnets)?; let node_rewards_table = get_node_rewards_table(&local_registry, version, network); @@ -52,8 +62,11 @@ pub async fn dump_registry(path: &Option, network: &Network, version: & #[derive(Serialize)] struct RegistryDump { + elected_guest_os_versions: Vec, + elected_host_os_versions: Vec, nodes: Vec, subnets: Vec, + unassigned_nodes_config: Option, dcs: Vec, node_operators: Vec, node_rewards_table: NodeRewardsTableFlattened, @@ -62,8 +75,11 @@ pub async fn dump_registry(path: &Option, network: &Network, version: & println!( "{}", serde_json::to_string(&RegistryDump { + elected_guest_os_versions, + elected_host_os_versions, nodes, subnets, + unassigned_nodes_config, dcs, node_operators: node_operators.values().cloned().collect_vec(), node_rewards_table, @@ -74,12 +90,38 @@ pub async fn dump_registry(path: &Option, network: &Network, version: & Ok(()) } +fn get_elected_guest_os_versions( + local_registry: &LocalRegistry, + version: RegistryVersion, +) -> Result, RegistryDumpError> { + let elected_versions = local_registry + .get_family_entries_of_version::(version) + .map_err(|e| anyhow::anyhow!("Couldn't get elected versions: {:?}", e))? + .into_iter() + .map(|(_, (_, record))| record) + .collect(); + Ok(elected_versions) +} + +fn get_elected_host_os_versions( + local_registry: &LocalRegistry, + version: RegistryVersion, +) -> Result, RegistryDumpError> { + let elected_versions = local_registry + .get_family_entries_of_version::(version) + .map_err(|e| anyhow::anyhow!("Couldn't get elected versions: {:?}", e))? + .into_iter() + .map(|(_, (_, record))| record) + .collect(); + Ok(elected_versions) +} + fn get_nodes( local_registry: &LocalRegistry, version: RegistryVersion, node_operators: &BTreeMap, subnets: &[SubnetRecord], -) -> Result, Error> { +) -> Result, RegistryDumpError> { let nodes = local_registry .get_family_entries_of_version::(version) .map_err(|e| anyhow::anyhow!("Couldn't get nodes: {:?}", e))? @@ -114,7 +156,10 @@ fn get_nodes( Ok(nodes) } -fn get_subnets(local_registry: &LocalRegistry, version: RegistryVersion) -> Result, Error> { +fn get_subnets( + local_registry: &LocalRegistry, + version: RegistryVersion, +) -> Result, RegistryDumpError> { Ok(local_registry .get_family_entries_of_version::(version) .map_err(|e| anyhow::anyhow!("Couldn't get subnets: {:?}", e))? @@ -153,7 +198,24 @@ fn get_subnets(local_registry: &LocalRegistry, version: RegistryVersion) -> Resu .collect::>()) } -fn get_data_centers(local_registry: &LocalRegistry, version: RegistryVersion) -> Result, Error> { +fn get_unassigned_nodes( + local_registry: &LocalRegistry, + version: RegistryVersion, +) -> Result { + let unassigned_nodes_config = local_registry + .get_family_entries_of_version::(version) + .map_err(|e| anyhow::anyhow!("Couldn't get unassigned nodes config: {:?}", e))? + .into_iter() + .map(|(_, (_, record))| record) + .next() + .ok_or(RegistryDumpError::RecordNotFound)?; + Ok(unassigned_nodes_config) +} + +fn get_data_centers( + local_registry: &LocalRegistry, + version: RegistryVersion, +) -> Result, RegistryDumpError> { Ok(local_registry .get_family_entries_of_version::(version) .map_err(|e| anyhow::anyhow!("Couldn't get data centers: {:?}", e))? @@ -165,7 +227,7 @@ fn get_data_centers(local_registry: &LocalRegistry, version: RegistryVersion) -> fn get_node_operators( local_registry: &LocalRegistry, version: RegistryVersion, -) -> Result, Error> { +) -> Result, RegistryDumpError> { let node_operators = local_registry .get_family_entries_of_version::(version) .map_err(|e| anyhow::anyhow!("Couldn't get node operators: {:?}", e))? @@ -224,7 +286,7 @@ fn get_node_rewards_table( fn get_api_boundary_nodes( local_registry: &LocalRegistry, version: RegistryVersion, -) -> Result, Error> { +) -> Result, RegistryDumpError> { let api_bns = local_registry .get_family_entries_of_version::(version) .map_err(|e| anyhow::anyhow!("Couldn't get api boundary nodes: {:?}", e))? @@ -326,3 +388,61 @@ pub struct NodeRewardsTableFlattened { #[serde(flatten)] pub table: BTreeMap, } + +enum RegistryDumpError { + RegistryClientError(ic_types::registry::RegistryClientError), + LocalRegistryError(ic_registry_local_registry::LocalRegistryError), + IoError(std::io::Error), + SerdeError(serde_json::Error), + GenericError(String), + RecordNotFound, +} + +impl From for RegistryDumpError { + fn from(e: ic_types::registry::RegistryClientError) -> Self { + RegistryDumpError::RegistryClientError(e) + } +} + +impl From for RegistryDumpError { + fn from(e: ic_registry_local_registry::LocalRegistryError) -> Self { + RegistryDumpError::LocalRegistryError(e) + } +} + +impl From for RegistryDumpError { + fn from(e: std::io::Error) -> Self { + RegistryDumpError::IoError(e) + } +} + +impl From for RegistryDumpError { + fn from(e: serde_json::Error) -> Self { + RegistryDumpError::SerdeError(e) + } +} + +impl From for RegistryDumpError { + fn from(e: String) -> Self { + RegistryDumpError::GenericError(e) + } +} + +impl From for RegistryDumpError { + fn from(e: anyhow::Error) -> Self { + RegistryDumpError::GenericError(e.to_string()) + } +} + +impl From for anyhow::Error { + fn from(e: RegistryDumpError) -> Self { + match e { + RegistryDumpError::RegistryClientError(e) => anyhow::anyhow!("Registry client error: {:?}", e), + RegistryDumpError::LocalRegistryError(e) => anyhow::anyhow!("Registry error: {:?}", e), + RegistryDumpError::IoError(e) => anyhow::anyhow!("IO error: {:?}", e), + RegistryDumpError::SerdeError(e) => anyhow::anyhow!("Serde error: {:?}", e), + RegistryDumpError::GenericError(e) => anyhow::anyhow!("Generic error: {:?}", e), + RegistryDumpError::RecordNotFound => anyhow::anyhow!("Record not found"), + } + } +} diff --git a/rs/ic-management-backend/src/registry.rs b/rs/ic-management-backend/src/registry.rs index 2ab947bb4..35bb98416 100644 --- a/rs/ic-management-backend/src/registry.rs +++ b/rs/ic-management-backend/src/registry.rs @@ -17,7 +17,7 @@ use ic_management_types::{ use ic_protobuf::registry::api_boundary_node::v1::ApiBoundaryNodeRecord; use ic_protobuf::registry::crypto::v1::PublicKey; use ic_protobuf::registry::hostos_version::v1::HostosVersionRecord; -use ic_protobuf::registry::replica_version::v1::BlessedReplicaVersions; +use ic_protobuf::registry::replica_version::v1::{BlessedReplicaVersions, ReplicaVersionRecord}; use ic_protobuf::registry::unassigned_nodes_config::v1::UnassignedNodesConfigRecord; use ic_protobuf::registry::{ dc::v1::DataCenterRecord, node::v1::NodeRecord, node_operator::v1::NodeOperatorRecord, subnet::v1::SubnetRecord, @@ -30,7 +30,7 @@ use ic_registry_common_proto::pb::local_store::v1::{ }; use ic_registry_keys::{ make_blessed_replica_versions_key, HOSTOS_VERSION_KEY_PREFIX, NODE_OPERATOR_RECORD_KEY_PREFIX, - NODE_RECORD_KEY_PREFIX, SUBNET_RECORD_KEY_PREFIX, + NODE_RECORD_KEY_PREFIX, REPLICA_VERSION_KEY_PREFIX, SUBNET_RECORD_KEY_PREFIX, }; use ic_registry_keys::{make_crypto_threshold_signing_pubkey_key, ROOT_SUBNET_ID_KEY}; use ic_registry_keys::{API_BOUNDARY_NODE_RECORD_KEY_PREFIX, DATA_CENTER_KEY_PREFIX}; @@ -102,6 +102,18 @@ impl RegistryEntry for SubnetRecord { const KEY_PREFIX: &'static str = SUBNET_RECORD_KEY_PREFIX; } +impl RegistryEntry for ReplicaVersionRecord { + const KEY_PREFIX: &'static str = REPLICA_VERSION_KEY_PREFIX; +} + +impl RegistryEntry for HostosVersionRecord { + const KEY_PREFIX: &'static str = HOSTOS_VERSION_KEY_PREFIX; +} + +impl RegistryEntry for UnassignedNodesConfigRecord { + const KEY_PREFIX: &'static str = "unassigned_nodes_config"; +} + impl RegistryEntry for ApiBoundaryNodeRecord { const KEY_PREFIX: &'static str = API_BOUNDARY_NODE_RECORD_KEY_PREFIX; }