Skip to content

Commit 527ef55

Browse files
andrewlabchalios
authored andcommitted
Tests for snapshot network renames
Test that we can correctly parse configuration and API calls in a backwards compatible way. Signed-off-by: Andrew Laucius <[email protected]> Signed-off-by: Babis Chalios <[email protected]>
1 parent 3388595 commit 527ef55

File tree

4 files changed

+88
-1
lines changed

4 files changed

+88
-1
lines changed

src/firecracker/src/api_server/request/snapshot.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ fn parse_put_snapshot_load(body: &Body) -> Result<ParsedRequest, RequestError> {
121121

122122
#[cfg(test)]
123123
mod tests {
124-
use vmm::vmm_config::snapshot::{MemBackendConfig, MemBackendType};
124+
use vmm::vmm_config::snapshot::{MemBackendConfig, MemBackendType, NetworkOverride};
125125

126126
use super::*;
127127
use crate::api_server::parsed_request::tests::{depr_action_from_req, vmm_action_from_request};
@@ -256,6 +256,45 @@ mod tests {
256256
VmmAction::LoadSnapshot(expected_config)
257257
);
258258

259+
let body = r#"{
260+
"snapshot_path": "foo",
261+
"mem_backend": {
262+
"backend_path": "bar",
263+
"backend_type": "Uffd"
264+
},
265+
"resume_vm": true,
266+
"network_overrides": [
267+
{
268+
"iface_id": "eth0",
269+
"host_dev_name": "vmtap2"
270+
}
271+
]
272+
}"#;
273+
let expected_config = LoadSnapshotParams {
274+
snapshot_path: PathBuf::from("foo"),
275+
mem_backend: MemBackendConfig {
276+
backend_path: PathBuf::from("bar"),
277+
backend_type: MemBackendType::Uffd,
278+
},
279+
enable_diff_snapshots: false,
280+
resume_vm: true,
281+
network_overrides: vec![NetworkOverride {
282+
iface_id: String::from("eth0"),
283+
host_dev_name: String::from("vmtap2"),
284+
}],
285+
};
286+
let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap();
287+
assert!(
288+
parsed_request
289+
.parsing_info()
290+
.take_deprecation_message()
291+
.is_none()
292+
);
293+
assert_eq!(
294+
vmm_action_from_request(parsed_request),
295+
VmmAction::LoadSnapshot(expected_config)
296+
);
297+
259298
let body = r#"{
260299
"snapshot_path": "foo",
261300
"mem_file_path": "bar",

src/vmm/tests/integration_tests.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ fn verify_load_snapshot(snapshot_file: TempFile, memory_file: TempFile) {
261261
},
262262
enable_diff_snapshots: false,
263263
resume_vm: true,
264+
network_overrides: vec![],
264265
}))
265266
.unwrap();
266267

@@ -344,6 +345,7 @@ fn verify_load_snap_disallowed_after_boot_resources(res: VmmAction, res_name: &s
344345
},
345346
enable_diff_snapshots: false,
346347
resume_vm: false,
348+
network_overrides: vec![],
347349
});
348350
let err = preboot_api_controller.handle_preboot_request(req);
349351
assert!(

tests/framework/microvm.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,7 @@ def restore_from_snapshot(
974974
snapshot: Snapshot,
975975
resume: bool = False,
976976
uffd_path: Path = None,
977+
rename_interfaces: dict = None,
977978
):
978979
"""Restore a snapshot"""
979980
jailed_snapshot = snapshot.copy_to_chroot(Path(self.chroot()))
@@ -1001,11 +1002,27 @@ def restore_from_snapshot(
10011002
# Adjust things just in case
10021003
self.kernel_file = Path(self.kernel_file)
10031004

1005+
iface_overrides = []
1006+
if rename_interfaces is not None:
1007+
iface_overrides = [
1008+
{"iface_id": k, "host_dev_name": v}
1009+
for k, v in rename_interfaces.items()
1010+
]
1011+
1012+
optional_kwargs = {}
1013+
if iface_overrides:
1014+
# For backwards compatibility ab testing we want to avoid adding
1015+
# new parameters until we have a release baseline with the new
1016+
# parameter. Once the release baseline has moved, this assignment
1017+
# can be inline in the snapshot_load command below
1018+
optional_kwargs["network_overrides"] = iface_overrides
1019+
10041020
self.api.snapshot_load.put(
10051021
mem_backend=mem_backend,
10061022
snapshot_path=str(jailed_vmstate),
10071023
enable_diff_snapshots=snapshot.is_diff,
10081024
resume_vm=resume,
1025+
**optional_kwargs,
10091026
)
10101027
# This is not a "wait for boot", but rather a "VM still works after restoration"
10111028
if snapshot.net_ifaces and resume:

tests/integration_tests/functional/test_snapshot_basic.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@
22
# SPDX-License-Identifier: Apache-2.0
33
"""Basic tests scenarios for snapshot save/restore."""
44

5+
import dataclasses
56
import filecmp
67
import logging
78
import os
89
import platform
910
import re
1011
import shutil
1112
import time
13+
import uuid
1214
from pathlib import Path
1315

1416
import pytest
1517

1618
import host_tools.cargo_build as host
1719
import host_tools.drive as drive_tools
20+
import host_tools.network as net_tools
1821
from framework import utils
1922
from framework.microvm import SnapshotType
2023
from framework.properties import global_props
@@ -570,3 +573,29 @@ def test_physical_counter_reset_aarch64(uvm_nano):
570573
break
571574
else:
572575
raise RuntimeError("Did not find CNTPCT_EL0 register in snapshot")
576+
577+
578+
def test_snapshot_rename_interface(uvm_nano, microvm_factory):
579+
"""
580+
Test that we can restore a snapshot and point its interface to a
581+
different host interface.
582+
"""
583+
vm = uvm_nano
584+
base_iface = vm.add_net_iface()
585+
vm.start()
586+
snapshot = vm.snapshot_full()
587+
588+
# We don't reuse the network namespace as it may conflict with
589+
# previous/future devices
590+
restored_vm = microvm_factory.build(netns=net_tools.NetNs(str(uuid.uuid4())))
591+
# Override the tap name, but keep the same IP configuration
592+
iface_override = dataclasses.replace(base_iface, tap_name="tap_override")
593+
594+
restored_vm.spawn()
595+
snapshot.net_ifaces.clear()
596+
snapshot.net_ifaces.append(iface_override)
597+
restored_vm.restore_from_snapshot(
598+
snapshot,
599+
rename_interfaces={iface_override.dev_name: iface_override.tap_name},
600+
resume=True,
601+
)

0 commit comments

Comments
 (0)