Skip to content

Commit d420de5

Browse files
committed
ci: move create_snapshot_artifact to a test
It's more hassle to keep this as a separate tool than including it in the tests, and we avoid having to treat it specially. Also this way we can run it in parallel easily. Signed-off-by: Pablo Barbáchano <[email protected]>
1 parent 5ec49b9 commit d420de5

File tree

6 files changed

+126
-179
lines changed

6 files changed

+126
-179
lines changed

.buildkite/pipeline_cross.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,9 @@
2121
instances_x86_64 = ["c5n.metal", "m5n.metal", "m6i.metal", "m6a.metal"]
2222
instances_aarch64 = ["m7g.metal"]
2323
commands = [
24-
# we run 0 tests for the side effect of downloading the artifacts. We
25-
# should convert create_snapshot_artifact to a proper test/
26-
"./tools/devtool test -- integration_tests/performance/test_benchmarks.py",
27-
"./tools/devtool -y sh ./tools/create_snapshot_artifact/main.py",
24+
"./tools/devtool -y test --no-build -- -m nonci -n4 integration_tests/functional/test_snapshot_phase1.py",
2825
"mkdir -pv snapshots/{instance}_{kv}",
29-
"sudo chown -Rc $USER: snapshot_artifacts",
30-
"mv -v snapshot_artifacts/* snapshots/{instance}_{kv}",
26+
"mv -v test_results/test_snapshot_phase1/* snapshots/{instance}_{kv}",
3127
]
3228
pipeline.build_group(
3329
"📸 create snapshots",
@@ -86,7 +82,7 @@
8682
f"buildkite-agent artifact download snapshots/{src_instance}_{src_kv}/* .",
8783
f"mv -v snapshots/{src_instance}_{src_kv} snapshot_artifacts",
8884
*pipeline.devtool_test(
89-
pytest_opts=f"-m nonci {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py",
85+
pytest_opts=f"-m nonci -n4 {k_val} integration_tests/functional/test_snapshot_restore_cross_kernel.py",
9086
),
9187
],
9288
"label": f"🎬 {src_instance} {src_kv} ➡️ {dst_instance} {dst_kv}",

docs/snapshotting/snapshot-support.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,8 @@ booting, to avoid this issue.
642642

643643
We have a mechanism in place to experiment with snapshot compatibility across
644644
supported host kernel versions by generating snapshot artifacts through
645-
[this tool](../../tools/create_snapshot_artifact) and checking devices'
646-
functionality using
645+
[this test](../../tests/integration_tests/functional/test_snapshot_phase1.py)
646+
and checking devices' functionality using
647647
[this test](../../tests/integration_tests/functional/test_snapshot_restore_cross_kernel.py).
648648
The test restores the snapshot and ensures that all the devices set-up (network
649649
devices, disk, vsock, balloon and MMDS) are operational post-load.

tests/conftest.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -307,14 +307,20 @@ def custom_cpu_template(request, record_property):
307307

308308

309309
@pytest.fixture(
310-
params=list(static_cpu_templates_params()) + list(custom_cpu_templates_params())
310+
params=[
311+
pytest.param(None, id="NO_CPU_TMPL"),
312+
*static_cpu_templates_params(),
313+
*custom_cpu_templates_params(),
314+
],
311315
)
312316
def cpu_template_any(request, record_property):
313-
"""This fixture combines static and custom CPU templates"""
314-
if "name" in request.param:
315-
record_property("custom_cpu_template", request.param["name"])
316-
else:
317-
record_property("static_cpu_template", request.param)
317+
"""This fixture combines no template, static and custom CPU templates"""
318+
cpu_template_name = request.param
319+
if request.param is None:
320+
cpu_template_name = "None"
321+
elif "name" in request.param:
322+
cpu_template_name = request.param["name"]
323+
record_property("cpu_template", cpu_template_name)
318324
return request.param
319325

320326

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""
5+
Creates snapshots for other tests like test_snapshot_restore_cross_kernel.py
6+
"""
7+
8+
import json
9+
import platform
10+
import re
11+
12+
import pytest
13+
14+
from framework.utils import (
15+
configure_mmds,
16+
generate_mmds_get_request,
17+
generate_mmds_session_token,
18+
)
19+
20+
if platform.machine() != "x86_64":
21+
pytestmark = pytest.mark.skip("only x86_64 architecture supported")
22+
23+
# Default IPv4 address to route MMDS requests.
24+
IPV4_ADDRESS = "169.254.169.254"
25+
NET_IFACE_FOR_MMDS = "eth3"
26+
27+
28+
@pytest.mark.nonci
29+
def test_snapshot_phase1(
30+
microvm_factory, guest_kernel, rootfs_ubuntu_24, cpu_template_any, results_dir
31+
):
32+
"""Create a snapshot and save it to disk"""
33+
34+
vm = microvm_factory.build(guest_kernel, rootfs_ubuntu_24, monitor_memory=False)
35+
vm.spawn(log_level="Info")
36+
vm.add_net_iface()
37+
38+
static_cpu_template = None
39+
cpu_template_name = "None"
40+
if isinstance(cpu_template_any, str):
41+
static_cpu_template = cpu_template_any
42+
cpu_template_name = f"static_{cpu_template_any}"
43+
elif isinstance(cpu_template_any, dict):
44+
vm.api.cpu_config.put(**cpu_template_any["template"])
45+
cpu_template_name = f"custom_{cpu_template_any['name']}"
46+
vm.basic_config(
47+
vcpu_count=2,
48+
mem_size_mib=1024,
49+
cpu_template=static_cpu_template,
50+
)
51+
52+
guest_kernel_version = re.search("vmlinux-(.*)", vm.kernel_file.name)
53+
snapshot_artifacts_dir = (
54+
results_dir
55+
/ f"{guest_kernel_version.group(1)}_{cpu_template_name}_guest_snapshot"
56+
)
57+
58+
# Add 4 network devices
59+
for i in range(4):
60+
vm.add_net_iface()
61+
# Add a vsock device
62+
vm.api.vsock.put(vsock_id="vsock0", guest_cid=3, uds_path="/v.sock")
63+
# Add MMDS
64+
configure_mmds(vm, ["eth3"], version="V2")
65+
# Add a memory balloon.
66+
vm.api.balloon.put(amount_mib=0, deflate_on_oom=True, stats_polling_interval_s=1)
67+
68+
vm.start()
69+
70+
# Populate MMDS.
71+
data_store = {
72+
"latest": {
73+
"meta-data": {
74+
"ami-id": "ami-12345678",
75+
"reservation-id": "r-fea54097",
76+
"local-hostname": "ip-10-251-50-12.ec2.internal",
77+
"public-hostname": "ec2-203-0-113-25.compute-1.amazonaws.com",
78+
}
79+
}
80+
}
81+
82+
# MMDS should be empty.
83+
assert vm.api.mmds.get().json() == {}
84+
# Populate MMDS with data.
85+
vm.api.mmds.put(**data_store)
86+
# Ensure data is persistent inside the data store.
87+
assert vm.api.mmds.get().json() == data_store
88+
89+
# Iterate and validate connectivity on all ifaces after boot.
90+
for i in range(4):
91+
exit_code, _, _ = vm.ssh_iface(i).run("sync")
92+
assert exit_code == 0
93+
94+
# Validate MMDS.
95+
# Configure interface to route MMDS requests
96+
vm.ssh.check_output(f"ip route add {IPV4_ADDRESS} dev {NET_IFACE_FOR_MMDS}")
97+
98+
# Fetch metadata to ensure MMDS is accessible.
99+
token = generate_mmds_session_token(vm.ssh, IPV4_ADDRESS, token_ttl=60)
100+
cmd = generate_mmds_get_request(IPV4_ADDRESS, token=token)
101+
_, stdout, _ = vm.ssh.run(cmd)
102+
assert json.loads(stdout) == data_store
103+
104+
# Copy snapshot files to be published to S3 for the 2nd part of the test
105+
# Create snapshot artifacts directory specific for the kernel version used.
106+
snapshot = vm.snapshot_full()
107+
snapshot_artifacts_dir.mkdir(parents=True)
108+
snapshot.save_to(snapshot_artifacts_dir)

tests/integration_tests/security/test_nv.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def uvm_with_cpu_template(
3030
if isinstance(cpu_template_any, str):
3131
cpu_template = cpu_template_any
3232
vm.basic_config(cpu_template=cpu_template)
33-
if cpu_template is None:
33+
if isinstance(cpu_template_any, dict):
3434
vm.api.cpu_config.put(**cpu_template_any["template"])
3535
vm.add_net_iface()
3636
vm.start()

tools/create_snapshot_artifact/main.py

-163
This file was deleted.

0 commit comments

Comments
 (0)