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