Skip to content

Commit 16756cd

Browse files
Added load_canister_snapshot to the Root canister. This commit is analogous to the changes in PR 8159.
1 parent 9970e03 commit 16756cd

File tree

5 files changed

+117
-7
lines changed

5 files changed

+117
-7
lines changed

rs/nns/handlers/root/impl/canister/canister.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use ic_nns_handler_root::{
3030
};
3131
use ic_nns_handler_root_interface::{
3232
ChangeCanisterControllersRequest, ChangeCanisterControllersResponse,
33-
TakeCanisterSnapshotRequest, TakeCanisterSnapshotResponse, UpdateCanisterSettingsRequest,
34-
UpdateCanisterSettingsResponse,
33+
LoadCanisterSnapshotRequest, LoadCanisterSnapshotResponse, TakeCanisterSnapshotRequest,
34+
TakeCanisterSnapshotResponse, UpdateCanisterSettingsRequest, UpdateCanisterSettingsResponse,
3535
};
3636
use std::cell::RefCell;
3737

@@ -242,6 +242,20 @@ async fn take_canister_snapshot(
242242
.await
243243
}
244244

245+
/// Loads a snapshot of a canister controlled by NNS Root. Only callable by NNS
246+
/// Governance.
247+
#[update]
248+
async fn load_canister_snapshot(
249+
load_canister_snapshot_request: LoadCanisterSnapshotRequest,
250+
) -> LoadCanisterSnapshotResponse {
251+
check_caller_is_governance();
252+
canister_management::load_canister_snapshot(
253+
load_canister_snapshot_request,
254+
&mut new_management_canister_client(),
255+
)
256+
.await
257+
}
258+
245259
/// Resources to serve for a given http_request
246260
/// Serve an HttpRequest made to this canister
247261
#[query(

rs/nns/handlers/root/impl/canister/root.did

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,26 @@ type TakeCanisterSnapshotError = record {
172172
description : text;
173173
};
174174

175+
type LoadCanisterSnapshotRequest = record {
176+
canister_id : principal;
177+
snapshot_id : blob;
178+
};
179+
180+
type LoadCanisterSnapshotResponse = variant {
181+
Ok : LoadCanisterSnapshotOk;
182+
Err : LoadCanisterSnapshotError;
183+
};
184+
185+
type LoadCanisterSnapshotOk = record {
186+
// This intentionally left empty. It is nevertheless here for
187+
// a) consistency, and b) in case of future expansion.
188+
};
189+
190+
type LoadCanisterSnapshotError = record {
191+
code : opt int32;
192+
description : text;
193+
};
194+
175195
service : () -> {
176196
canister_status : (CanisterIdRecord) -> (CanisterStatusResult);
177197
get_build_metadata : () -> (text) query;
@@ -190,4 +210,7 @@ service : () -> {
190210
take_canister_snapshot : (TakeCanisterSnapshotArgs) -> (
191211
TakeCanisterSnapshotResponse,
192212
);
213+
load_canister_snapshot : (LoadCanisterSnapshotRequest) -> (
214+
LoadCanisterSnapshotResponse,
215+
);
193216
}

rs/nns/handlers/root/impl/src/canister_management.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use ic_cdk::{
77
};
88
use ic_management_canister_types_private::{
99
CanisterInstallMode::Install, CanisterSettingsArgsBuilder, CanisterSnapshotResponse,
10-
CreateCanisterArgs, InstallCodeArgs, TakeCanisterSnapshotArgs,
10+
CreateCanisterArgs, InstallCodeArgs, LoadCanisterSnapshotArgs, TakeCanisterSnapshotArgs,
1111
};
1212
use ic_nervous_system_clients::{
1313
canister_id_record::CanisterIdRecord,
@@ -24,9 +24,11 @@ use ic_nns_common::{
2424
types::CallCanisterRequest,
2525
};
2626
use ic_nns_handler_root_interface::{
27-
ChangeCanisterControllersRequest, ChangeCanisterControllersResponse, TakeCanisterSnapshotError,
28-
TakeCanisterSnapshotOk, TakeCanisterSnapshotRequest, TakeCanisterSnapshotResponse,
29-
UpdateCanisterSettingsError, UpdateCanisterSettingsRequest, UpdateCanisterSettingsResponse,
27+
ChangeCanisterControllersRequest, ChangeCanisterControllersResponse, LoadCanisterSnapshotError,
28+
LoadCanisterSnapshotOk, LoadCanisterSnapshotRequest, LoadCanisterSnapshotResponse,
29+
TakeCanisterSnapshotError, TakeCanisterSnapshotOk, TakeCanisterSnapshotRequest,
30+
TakeCanisterSnapshotResponse, UpdateCanisterSettingsError, UpdateCanisterSettingsRequest,
31+
UpdateCanisterSettingsResponse,
3032
};
3133
use ic_protobuf::{
3234
registry::nns::v1::{NnsCanisterRecord, NnsCanisterRecords},
@@ -321,3 +323,50 @@ fn convert_from_canister_snapshot_response_to_take_canister_snapshot_ok(
321323
total_size,
322324
}
323325
}
326+
327+
pub async fn load_canister_snapshot(
328+
load_canister_snapshot_request: LoadCanisterSnapshotRequest,
329+
management_canister_client: &mut impl ManagementCanisterClient,
330+
) -> LoadCanisterSnapshotResponse {
331+
let LoadCanisterSnapshotRequest {
332+
canister_id,
333+
snapshot_id,
334+
} = load_canister_snapshot_request;
335+
336+
let snapshot_id = match SnapshotId::try_from(snapshot_id) {
337+
Ok(ok) => ok,
338+
Err(err) => {
339+
return LoadCanisterSnapshotResponse::Err(LoadCanisterSnapshotError {
340+
code: None,
341+
description: format!("Invalid snapshot ID: {err}"),
342+
});
343+
}
344+
};
345+
346+
let canister_id = match CanisterId::try_from(canister_id) {
347+
Ok(ok) => ok,
348+
Err(err) => {
349+
return LoadCanisterSnapshotResponse::Err(LoadCanisterSnapshotError {
350+
code: None,
351+
description: format!("Invalid canister ID: {err}"),
352+
});
353+
}
354+
};
355+
356+
let load_canister_snapshot_args = LoadCanisterSnapshotArgs::new(
357+
canister_id,
358+
snapshot_id,
359+
management_canister_client.canister_version(),
360+
);
361+
362+
match management_canister_client
363+
.load_canister_snapshot(load_canister_snapshot_args)
364+
.await
365+
{
366+
Ok(()) => LoadCanisterSnapshotResponse::Ok(LoadCanisterSnapshotOk {}),
367+
Err((code, description)) => LoadCanisterSnapshotResponse::Err(LoadCanisterSnapshotError {
368+
code: Some(code),
369+
description,
370+
}),
371+
}
372+
}

rs/nns/handlers/root/interface/src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,24 @@ pub struct TakeCanisterSnapshotError {
107107
pub code: Option<i32>,
108108
pub description: String,
109109
}
110+
111+
#[derive(Clone, Eq, PartialEq, Hash, Debug, CandidType, Deserialize)]
112+
pub struct LoadCanisterSnapshotRequest {
113+
pub canister_id: PrincipalId,
114+
pub snapshot_id: Vec<u8>,
115+
}
116+
117+
#[derive(Clone, Eq, PartialEq, Hash, Debug, CandidType, Deserialize)]
118+
pub enum LoadCanisterSnapshotResponse {
119+
Ok(LoadCanisterSnapshotOk),
120+
Err(LoadCanisterSnapshotError),
121+
}
122+
123+
#[derive(Clone, Eq, PartialEq, Hash, Debug, CandidType, Deserialize)]
124+
pub struct LoadCanisterSnapshotOk {}
125+
126+
#[derive(Clone, Eq, PartialEq, Hash, Debug, CandidType, Deserialize)]
127+
pub struct LoadCanisterSnapshotError {
128+
pub code: Option<i32>,
129+
pub description: String,
130+
}

rs/nns/handlers/root/unreleased_changelog.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ on the process that this file is part of, see
99

1010
## Added
1111

12-
* Added `take_canister_snapshot` method. It is only callable by the Governance canister though.
12+
* Added `take_canister_snapshot`, and `load_canister_snapshot` methods. These
13+
are only callable by the Governance canister though. What these do is
14+
proxy/immediately forward to methods of the same name in the Management
15+
(pseudo-)canister.
1316

1417
## Changed
1518

0 commit comments

Comments
 (0)