Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dre): Include more info in the registry dump #410

Merged
merged 1 commit into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Cargo.Bazel.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"checksum": "b0c1429a1d74326f983596231a5f060a6870760dedec91dc54e2a44ca49c6975",
"checksum": "3be9f0f64dc894dc197dfa66905c30cbcddf085666768a4cbbe06451358145e1",
"crates": {
"actix-codec 0.5.2": {
"name": "actix-codec",
Expand Down Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rs/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
138 changes: 129 additions & 9 deletions rs/cli/src/registry_dump.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
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};
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;
Expand All @@ -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<PathBuf>, network: &Network, version: &i64) -> Result<(), Error> {
pub async fn dump_registry(path: &Option<PathBuf>, 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 = {
Expand All @@ -38,12 +39,21 @@ pub async fn dump_registry(path: &Option<PathBuf>, 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);
Expand All @@ -52,8 +62,11 @@ pub async fn dump_registry(path: &Option<PathBuf>, network: &Network, version: &

#[derive(Serialize)]
struct RegistryDump {
elected_guest_os_versions: Vec<ReplicaVersionRecord>,
elected_host_os_versions: Vec<HostosVersionRecord>,
nodes: Vec<NodeDetails>,
subnets: Vec<SubnetRecord>,
unassigned_nodes_config: Option<UnassignedNodesConfigRecord>,
dcs: Vec<DataCenterRecord>,
node_operators: Vec<NodeOperator>,
node_rewards_table: NodeRewardsTableFlattened,
Expand All @@ -62,8 +75,11 @@ pub async fn dump_registry(path: &Option<PathBuf>, 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,
Expand All @@ -74,12 +90,38 @@ pub async fn dump_registry(path: &Option<PathBuf>, network: &Network, version: &
Ok(())
}

fn get_elected_guest_os_versions(
local_registry: &LocalRegistry,
version: RegistryVersion,
) -> Result<Vec<ReplicaVersionRecord>, RegistryDumpError> {
let elected_versions = local_registry
.get_family_entries_of_version::<ReplicaVersionRecord>(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<Vec<HostosVersionRecord>, RegistryDumpError> {
let elected_versions = local_registry
.get_family_entries_of_version::<HostosVersionRecord>(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<PrincipalId, NodeOperator>,
subnets: &[SubnetRecord],
) -> Result<Vec<NodeDetails>, Error> {
) -> Result<Vec<NodeDetails>, RegistryDumpError> {
let nodes = local_registry
.get_family_entries_of_version::<NodeRecord>(version)
.map_err(|e| anyhow::anyhow!("Couldn't get nodes: {:?}", e))?
Expand Down Expand Up @@ -114,7 +156,10 @@ fn get_nodes(
Ok(nodes)
}

fn get_subnets(local_registry: &LocalRegistry, version: RegistryVersion) -> Result<Vec<SubnetRecord>, Error> {
fn get_subnets(
local_registry: &LocalRegistry,
version: RegistryVersion,
) -> Result<Vec<SubnetRecord>, RegistryDumpError> {
Ok(local_registry
.get_family_entries_of_version::<SubnetRecordProto>(version)
.map_err(|e| anyhow::anyhow!("Couldn't get subnets: {:?}", e))?
Expand Down Expand Up @@ -153,7 +198,24 @@ fn get_subnets(local_registry: &LocalRegistry, version: RegistryVersion) -> Resu
.collect::<Vec<_>>())
}

fn get_data_centers(local_registry: &LocalRegistry, version: RegistryVersion) -> Result<Vec<DataCenterRecord>, Error> {
fn get_unassigned_nodes(
local_registry: &LocalRegistry,
version: RegistryVersion,
) -> Result<UnassignedNodesConfigRecord, RegistryDumpError> {
let unassigned_nodes_config = local_registry
.get_family_entries_of_version::<UnassignedNodesConfigRecord>(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<Vec<DataCenterRecord>, RegistryDumpError> {
Ok(local_registry
.get_family_entries_of_version::<DataCenterRecord>(version)
.map_err(|e| anyhow::anyhow!("Couldn't get data centers: {:?}", e))?
Expand All @@ -165,7 +227,7 @@ fn get_data_centers(local_registry: &LocalRegistry, version: RegistryVersion) ->
fn get_node_operators(
local_registry: &LocalRegistry,
version: RegistryVersion,
) -> Result<BTreeMap<PrincipalId, NodeOperator>, Error> {
) -> Result<BTreeMap<PrincipalId, NodeOperator>, RegistryDumpError> {
let node_operators = local_registry
.get_family_entries_of_version::<NodeOperatorRecord>(version)
.map_err(|e| anyhow::anyhow!("Couldn't get node operators: {:?}", e))?
Expand Down Expand Up @@ -224,7 +286,7 @@ fn get_node_rewards_table(
fn get_api_boundary_nodes(
local_registry: &LocalRegistry,
version: RegistryVersion,
) -> Result<Vec<ApiBoundaryNodeDetails>, Error> {
) -> Result<Vec<ApiBoundaryNodeDetails>, RegistryDumpError> {
let api_bns = local_registry
.get_family_entries_of_version::<ApiBoundaryNodeRecord>(version)
.map_err(|e| anyhow::anyhow!("Couldn't get api boundary nodes: {:?}", e))?
Expand Down Expand Up @@ -326,3 +388,61 @@ pub struct NodeRewardsTableFlattened {
#[serde(flatten)]
pub table: BTreeMap<String, NodeRewardRatesFlattened>,
}

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<ic_types::registry::RegistryClientError> for RegistryDumpError {
fn from(e: ic_types::registry::RegistryClientError) -> Self {
RegistryDumpError::RegistryClientError(e)
}
}

impl From<ic_registry_local_registry::LocalRegistryError> for RegistryDumpError {
fn from(e: ic_registry_local_registry::LocalRegistryError) -> Self {
RegistryDumpError::LocalRegistryError(e)
}
}

impl From<std::io::Error> for RegistryDumpError {
fn from(e: std::io::Error) -> Self {
RegistryDumpError::IoError(e)
}
}

impl From<serde_json::Error> for RegistryDumpError {
fn from(e: serde_json::Error) -> Self {
RegistryDumpError::SerdeError(e)
}
}

impl From<String> for RegistryDumpError {
fn from(e: String) -> Self {
RegistryDumpError::GenericError(e)
}
}

impl From<anyhow::Error> for RegistryDumpError {
fn from(e: anyhow::Error) -> Self {
RegistryDumpError::GenericError(e.to_string())
}
}

impl From<RegistryDumpError> 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"),
}
}
}
16 changes: 14 additions & 2 deletions rs/ic-management-backend/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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};
Expand Down Expand Up @@ -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;
}
Expand Down
Loading