diff --git a/rs/registry/admin/bin/main.rs b/rs/registry/admin/bin/main.rs index 5faa84564000..bf3a84af84f9 100644 --- a/rs/registry/admin/bin/main.rs +++ b/rs/registry/admin/bin/main.rs @@ -419,6 +419,9 @@ enum SubCommand { /// Submits a proposal to bless an alternative GuestOS version for disaster recovery. ProposeToBlessAlternativeGuestOsVersion(ProposeToBlessAlternativeGuestOsVersionCmd), + /// Submits a proposal to change what replica version(s) are run by Cloud Engines. + ProposeToUpdateStandardEngineReplicaVersion(ProposeToUpdateStandardEngineReplicaVersionCmd), + /// Submits a proposal to change an existing canister on NNS. ProposeToChangeNnsCanister(ProposeToChangeNnsCanisterCmd), @@ -2183,6 +2186,60 @@ impl ProposalAction for ProposeToBlessAlternativeGuestOsVersionCmd { } } +/// Sub-command to submit a proposal to change what replica version(s) are run +/// by Cloud Engines. +#[derive_common_proposal_fields] +#[derive(Clone, Parser, ProposalMetadata)] +struct ProposeToUpdateStandardEngineReplicaVersionCmd { + /// The replica version that Cloud Engines should eventually upgrade to. + #[clap(long, required = true)] + new_replica_version_id: String, + + /// The replica version that Cloud Engines should upgrade from. + #[clap(long, required = true)] + old_replica_version_id: String, + + /// The (approximate) fraction of Cloud Engines that should be on new + /// replica version (the rest stay on the old one). Must be in the closed + /// interval [0.0, 1.0]. + #[clap(long, required = true)] + deployment_progress: f64, +} + +impl ProposalTitle for ProposeToUpdateStandardEngineReplicaVersionCmd { + fn title(&self) -> String { + if let Some(title) = &self.proposal_title { + return title.clone(); + } + + format!( + "Update {:.1}% of Cloud Engines to {}", + self.deployment_progress * 100.0, + shortened_hash_string(&self.new_replica_version_id), + ) + } +} + +#[async_trait] +impl ProposalAction for ProposeToUpdateStandardEngineReplicaVersionCmd { + async fn action(&self, _: &Agent) -> ProposalActionRequest { + let Self { + new_replica_version_id, + old_replica_version_id, + deployment_progress, + .. + } = self.clone(); + + ProposalActionRequest::UpdateStandardEngineReplicaVersion( + ic_nns_governance_api::UpdateStandardEngineReplicaVersion { + new_replica_version_id: Some(new_replica_version_id), + old_replica_version_id: Some(old_replica_version_id), + deployment_progress: Some(deployment_progress), + }, + ) + } +} + /// Sub-command to submit a proposal to add a new NNS canister. #[derive_common_proposal_fields] #[derive(Parser, ProposalMetadata)] @@ -4649,6 +4706,7 @@ async fn main() { SubCommand::ProposeToUpdateSnsDeployWhitelist(_) => (), SubCommand::ProposeToUpdateSnsSubnetIdsInSnsWasm(_) => (), SubCommand::ProposeToUpdateSshReadonlyAccessForAllUnassignedNodes(_) => (), + SubCommand::ProposeToUpdateStandardEngineReplicaVersion(_) => (), SubCommand::ProposeToUpdateSubnet(_) => (), SubCommand::ProposeToUpdateSubnetType(_) => (), SubCommand::ProposeToUpdateXdrIcpConversionRate(_) => (), @@ -6037,6 +6095,16 @@ async fn main() { ); propose_action_from_command(cmd, canister_client, proposer).await; } + SubCommand::ProposeToUpdateStandardEngineReplicaVersion(cmd) => { + let (proposer, sender) = cmd.proposer_and_sender(sender); + let canister_client = make_canister_client( + reachable_nns_urls, + opts.verify_nns_responses, + opts.nns_public_key_pem_file, + sender, + ); + propose_action_from_command(cmd, canister_client, proposer).await; + } } }