Exemplo n.º 1
0
def create_snapshot(bin_cloner_path):
    """Create a snapshot of a microVM."""
    vm_builder = MicrovmBuilder(bin_cloner_path)
    vm_instance = vm_builder.build_vm_nano()
    basevm = vm_instance.vm
    root_disk = vm_instance.disks[0]
    ssh_key = vm_instance.ssh_key

    # Add a memory balloon.
    response = basevm.balloon.put(amount_mib=0,
                                  deflate_on_oom=True,
                                  stats_polling_interval_s=0)
    assert basevm.api_session.is_status_no_content(response.status_code)

    basevm.start()
    ssh_connection = net_tools.SSHConnection(basevm.ssh_config)

    # Verify if guest can run commands.
    exit_code, _, _ = ssh_connection.execute_command("sync")
    assert exit_code == 0

    # Create a snapshot builder from a microvm.
    snapshot_builder = SnapshotBuilder(basevm)

    # Create base snapshot.
    snapshot = snapshot_builder.create([root_disk.local_path()], ssh_key)

    basevm.kill()

    return snapshot
def test_restore_from_past_versions(bin_cloner_path):
    """Test scenario: restore all previous version snapshots."""
    logger = logging.getLogger("snapshot_version")

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Fetch all firecracker binaries.
    # With each binary create a snapshot and try to restore in current
    # version.
    firecracker_artifacts = artifacts.firecrackers()
    for firecracker in firecracker_artifacts:
        firecracker.download()
        jailer = firecracker.jailer()
        jailer.download()

        logger.info("Source Firecracker: %s", firecracker.local_path())
        logger.info("Source Jailer: %s", jailer.local_path())
        # Create a fresh snapshot using the binary artifacts.
        builder = MicrovmBuilder(bin_cloner_path, firecracker.local_path(),
                                 jailer.local_path())
        snapshot = create_512mb_full_snapshot(bin_cloner_path, None,
                                              firecracker.local_path(),
                                              jailer.local_path())
        microvm, _ = builder.build_from_snapshot(snapshot, True, False)
        ssh_connection = net_tools.SSHConnection(microvm.ssh_config)
        exit_code, _, _ = ssh_connection.execute_command("sleep 1 && sync")

        assert exit_code == 0
def test_restore_in_past_versions(bin_cloner_path):
    """Test scenario: create a snapshot and restore in previous versions."""
    logger = logging.getLogger("snapshot_version")

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Fetch all snapshots artifacts.
    # "fc_release" is the key that should be used for per release snapshot
    # artifacts. Such snapshots are created at release time and target the
    # current version. We are going to restore all these snapshots with current
    # testing build.
    firecracker_artifacts = artifacts.firecrackers()
    for firecracker in firecracker_artifacts:
        firecracker.download()
        jailer = firecracker.jailer()
        jailer.download()
        # The target version is in the name of the firecracker binary from S3.
        # We also strip the "v" as fc expects X.Y.Z version string.
        target_version = firecracker.base_name()[1:]
        logger.info("Creating snapshot for version: %s", target_version)

        # Create a fresh snapshot targeted at the binary artifact version.
        snapshot = create_512mb_full_snapshot(bin_cloner_path, target_version)

        builder = MicrovmBuilder(bin_cloner_path, firecracker.local_path(),
                                 jailer.local_path())
        microvm, _ = builder.build_from_snapshot(snapshot, True, False)

        logger.info("Using Firecracker: %s", firecracker.local_path())
        logger.info("Using Jailer: %s", jailer.local_path())

        # Attempt to connect to resumed microvm.
        ssh_connection = net_tools.SSHConnection(microvm.ssh_config)

        exit_code, _, _ = ssh_connection.execute_command("sleep 1 && sync")
        assert exit_code == 0
Exemplo n.º 4
0
def test_api_vsock(bin_cloner_path):
    """
    Test vsock related API commands.

    @type: functional
    """
    builder = MicrovmBuilder(bin_cloner_path)
    artifacts = ArtifactCollection(_test_images_s3_bucket())

    # Test with the current build.
    vm_instance = builder.build_vm_nano()
    _test_vsock(vm_instance.vm)

    # Fetch 1.0.0 and older firecracker binaries.
    # Create a vsock device with each FC binary
    # artifact.
    firecracker_artifacts = artifacts.firecrackers(
        # v1.0.0 deprecated `vsock_id`.
        min_version="1.0.0")

    for firecracker in firecracker_artifacts:
        firecracker.download()
        jailer = firecracker.jailer()
        jailer.download()

        vm_instance = builder.build_vm_nano(fc_binary=firecracker.local_path(),
                                            jailer_binary=jailer.local_path())

        _test_vsock(vm_instance.vm)
def test_negative_snapshot_create(bin_cloner_path):
    """
    Test create snapshot before pause.

    @type: negative
    """
    vm_builder = MicrovmBuilder(bin_cloner_path)
    vm_instance = vm_builder.build_vm_nano()
    vm = vm_instance.vm

    vm.start()

    response = vm.snapshot.create(mem_file_path="memfile",
                                  snapshot_path="statefile",
                                  diff=False)

    assert vm.api_session.is_status_bad_request(response.status_code)
    assert "save/restore unavailable while running" in response.text

    response = vm.vm.patch(state="Paused")
    assert vm.api_session.is_status_no_content(response.status_code)

    # Try diff with dirty pages tracking disabled.
    response = vm.snapshot.create(mem_file_path="memfile",
                                  snapshot_path="statefile",
                                  diff=True)
    msg = "Diff snapshots are not allowed on uVMs with dirty page" " tracking disabled"
    assert msg in response.text
    assert not os.path.exists("statefile")
    assert not os.path.exists("memfile")

    vm.kill()
Exemplo n.º 6
0
def test_restore_no_tsc(bin_cloner_path):
    """Test scenario: restore a snapshot without TSC in current version."""
    logger = logging.getLogger("no_tsc_snapshot")
    builder = MicrovmBuilder(bin_cloner_path)

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Fetch the v0.24.0 firecracker binary as that one does not have
    # the TSC frequency in the snapshot file.
    firecracker_artifacts = artifacts.firecrackers(keyword="v0.24.0")
    firecracker = firecracker_artifacts[0]
    firecracker.download()
    jailer = firecracker.jailer()
    jailer.download()
    diff_snapshots = True

    # Create a snapshot.
    snapshot = create_snapshot_helper(builder,
                                      logger,
                                      drives=scratch_drives,
                                      ifaces=net_ifaces,
                                      fc_binary=firecracker.local_path(),
                                      jailer_binary=jailer.local_path(),
                                      diff_snapshots=diff_snapshots,
                                      balloon=True)

    # Resume microvm using current build of FC/Jailer.
    # The resume should be successful because the CPU model
    # in the snapshot state is the same as this host's.
    microvm, _ = builder.build_from_snapshot(snapshot,
                                             resume=True,
                                             diff_snapshots=False)
    validate_all_devices(logger, microvm, net_ifaces, scratch_drives,
                         diff_snapshots)
    logger.debug("========== Firecracker restore snapshot log ==========")
    logger.debug(microvm.log_data)
Exemplo n.º 7
0
def test_create_invalid_version(bin_cloner_path):
    """Test scenario: create snapshot targeting invalid version."""
    # Use a predefined vm instance.
    builder = MicrovmBuilder(bin_cloner_path)
    test_microvm = builder.build_vm_nano().vm
    test_microvm.start()

    try:
        # Target an invalid Firecracker version string.
        test_microvm.pause_to_snapshot(mem_file_path="/vm.mem",
                                       snapshot_path="/vm.vmstate",
                                       diff=False,
                                       version="invalid")
    except AssertionError as error:
        # Check if proper error is returned.
        assert "Invalid microVM version format" in \
            str(error)
    else:
        assert False, "Negative test failed"

    try:
        # Target a valid version string but with no snapshot support.
        test_microvm.pause_to_snapshot(mem_file_path="/vm.mem",
                                       snapshot_path="/vm.vmstate",
                                       diff=False,
                                       version="0.22.0")
    except AssertionError as error:
        # Check if proper error is returned.
        assert "Cannot translate microVM version to snapshot data version" in \
            str(error)
    else:
        assert False, "Negative test failed"
def test_patch_drive_snapshot(bin_cloner_path):
    """
    Test that a patched drive is correctly used by guests loaded from snapshot.

    @type: functional
    """
    logger = logging.getLogger("snapshot_sequence")

    vm_builder = MicrovmBuilder(bin_cloner_path)
    snapshot_type = SnapshotType.FULL
    diff_snapshots = False

    # Use a predefined vm instance.
    vm_instance = vm_builder.build_vm_nano()
    basevm = vm_instance.vm
    root_disk = vm_instance.disks[0]
    ssh_key = vm_instance.ssh_key

    # Add a scratch 128MB RW non-root block device.
    scratchdisk1 = drive_tools.FilesystemFile(tempfile.mktemp(), size=128)
    basevm.add_drive("scratch", scratchdisk1.path)

    basevm.start()
    ssh_connection = net_tools.SSHConnection(basevm.ssh_config)

    # Verify if guest can run commands.
    exit_code, _, _ = ssh_connection.execute_command("sync")
    assert exit_code == 0

    # Update drive to have another backing file, double in size.
    new_file_size_mb = 2 * int(scratchdisk1.size() / (1024 * 1024))
    logger.info("Patch drive, new file: size %sMB.", new_file_size_mb)
    scratchdisk1 = drive_tools.FilesystemFile(tempfile.mktemp(),
                                              new_file_size_mb)
    basevm.patch_drive("scratch", scratchdisk1)

    logger.info("Create %s #0.", snapshot_type)
    # Create a snapshot builder from a microvm.
    snapshot_builder = SnapshotBuilder(basevm)

    disks = [root_disk.local_path(), scratchdisk1.path]
    # Create base snapshot.
    snapshot = snapshot_builder.create(disks, ssh_key, snapshot_type)

    basevm.kill()

    # Load snapshot in a new Firecracker microVM.
    logger.info("Load snapshot, mem %s", snapshot.mem)
    microvm, _ = vm_builder.build_from_snapshot(snapshot,
                                                resume=True,
                                                diff_snapshots=diff_snapshots)
    # Attempt to connect to resumed microvm.
    ssh_connection = net_tools.SSHConnection(microvm.ssh_config)

    # Verify the new microVM has the right scratch drive.
    guest_drive_size = _get_guest_drive_size(ssh_connection)
    assert guest_drive_size == str(scratchdisk1.size())

    microvm.kill()
Exemplo n.º 9
0
def test_mmds_older_snapshot(bin_cloner_path):
    """
    Test MMDS behavior restoring older snapshots in the current version.

    Ensures that the MMDS version is persisted or initialised with the default
    if the FC version does not support this feature.

    @type: functional
    """
    vm_builder = MicrovmBuilder(bin_cloner_path)

    # Validate restoring a past snapshot in the current version.
    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Fetch all firecracker binaries.
    firecracker_artifacts = artifacts.firecrackers(
        max_version=get_firecracker_version_from_toml())
    for firecracker in firecracker_artifacts:
        firecracker.download()
        jailer = firecracker.jailer()
        jailer.download()

        net_iface = NetIfaceConfig()
        vm_instance = vm_builder.build_vm_nano(
            net_ifaces=[net_iface],
            fc_binary=firecracker.local_path(),
            jailer_binary=jailer.local_path()
        )

        fc_version = firecracker.base_name()[1:]
        # If the version is smaller or equal to 1.0.0, we expect that
        # MMDS will be initialised with V1 by default.
        # Otherwise, we may configure V2.
        if compare_versions(fc_version, "1.0.0") <= 0:
            mmds_version = "V1"
        else:
            mmds_version = "V2"

        # Check if we need to configure MMDS the old way, by
        # setting `allow_mmds_requests`.
        # If we do (for v0.25), reissue the network PUT api call.
        if compare_versions(fc_version, "1.0.0") < 0:
            basevm = vm_instance.vm
            guest_mac = net_tools.mac_from_ip(net_iface.guest_ip)
            response = basevm.network.put(
                iface_id=net_iface.dev_name,
                host_dev_name=net_iface.tap_name,
                guest_mac=guest_mac,
                allow_mmds_requests=True
            )
            assert basevm.api_session.is_status_no_content(
                response.status_code)

        _validate_mmds_snapshot(
            vm_instance,
            vm_builder,
            mmds_version,
            target_fc_version=fc_version
        )
def test_restore_old_version(bin_cloner_path):
    """
    Restore current snapshot with previous versions of Firecracker.

    @type: functional
    """
    # Microvm: 2vCPU 256MB RAM, balloon, 4 disks and 4 net devices.
    logger = logging.getLogger("old_snapshot_version_many_devices")
    builder = MicrovmBuilder(bin_cloner_path)

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Fetch all firecracker binaries.
    # Create a snapshot with current build and restore with each FC binary
    # artifact.
    firecracker_artifacts = artifacts.firecrackers(
        # current snapshot (i.e a machine snapshotted with current build)
        # is incompatible with any past release due to notification suppression.
        min_version="1.2.0",
        max_version=get_firecracker_version_from_toml(),
    )
    for firecracker in firecracker_artifacts:
        firecracker.download()
        jailer = firecracker.jailer()
        jailer.download()

        logger.info("Creating snapshot with local build")

        # Old version from artifact.
        target_version = firecracker.base_name()[1:]

        # Create a snapshot with current FC version targeting the old version.
        snapshot = create_snapshot_helper(
            builder,
            logger,
            target_version=target_version,
            drives=scratch_drives,
            ifaces=net_ifaces,
            balloon=True,
            diff_snapshots=True,
        )

        logger.info("Restoring snapshot with Firecracker: %s",
                    firecracker.local_path())
        logger.info("Using Jailer: %s", jailer.local_path())

        # Resume microvm using FC/Jailer binary artifacts.
        vm, _ = builder.build_from_snapshot(
            snapshot,
            resume=True,
            diff_snapshots=False,
            fc_binary=firecracker.local_path(),
            jailer_binary=jailer.local_path(),
        )
        validate_all_devices(logger, vm, net_ifaces, scratch_drives, True)
        logger.debug("========== Firecracker restore snapshot log ==========")
        logger.debug(vm.log_data)
def test_restore_old_snapshot(bin_cloner_path):
    """
    Restore from snapshots obtained with previous versions of Firecracker.

    @type: functional
    """
    # Microvm: 2vCPU 256MB RAM, balloon, 4 disks and 4 net devices.
    logger = logging.getLogger("old_snapshot_many_devices")
    builder = MicrovmBuilder(bin_cloner_path)

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Fetch all firecracker binaries.
    # With each binary create a snapshot and try to restore in current
    # version.
    firecracker_artifacts = artifacts.firecrackers(
        max_version=get_firecracker_version_from_toml())

    for firecracker in firecracker_artifacts:
        firecracker.download()
        jailer = firecracker.jailer()
        jailer.download()

        logger.info("Creating snapshot with Firecracker: %s",
                    firecracker.local_path())
        logger.info("Using Jailer: %s", jailer.local_path())

        target_version = firecracker.base_name()[1:]

        # v0.23 does not support creating diff snapshots.
        # v0.23 does not support balloon.
        diff_snapshots = "0.23" not in target_version

        # Create a snapshot.
        snapshot = create_snapshot_helper(
            builder,
            logger,
            drives=scratch_drives,
            ifaces=net_ifaces,
            fc_binary=firecracker.local_path(),
            jailer_binary=jailer.local_path(),
            diff_snapshots=diff_snapshots,
            balloon=diff_snapshots,
        )

        # Resume microvm using current build of FC/Jailer.
        microvm, _ = builder.build_from_snapshot(snapshot,
                                                 resume=True,
                                                 diff_snapshots=False)
        validate_all_devices(logger, microvm, net_ifaces, scratch_drives,
                             diff_snapshots)
        logger.debug("========== Firecracker restore snapshot log ==========")
        logger.debug(microvm.log_data)
Exemplo n.º 12
0
def test_create_with_newer_virtio_features(bin_cloner_path):
    """
    Attempt to create a snapshot with newer virtio features.

    @type: functional
    """
    builder = MicrovmBuilder(bin_cloner_path)
    test_microvm = builder.build_vm_nano().vm
    test_microvm.start()

    # Init a ssh connection in order to wait for the VM to boot. This way
    # we can be sure that the block device was activated.
    iface = NetIfaceConfig()
    test_microvm.ssh_config['hostname'] = iface.guest_ip
    _ssh_connection = net_tools.SSHConnection(test_microvm.ssh_config)

    # Create directory and files for saving snapshot state and memory.
    snapshot_builder = SnapshotBuilder(test_microvm)
    _snapshot_dir = snapshot_builder.create_snapshot_dir()

    # Pause microVM for snapshot.
    response = test_microvm.vm.patch(state='Paused')
    assert test_microvm.api_session.is_status_no_content(response.status_code)

    # We try to create a snapshot to a target version < 0.26.0.
    # This should fail because Fc versions < 0.26.0 don't support
    # virtio notification suppression.
    target_fc_versions = ["0.24.0", "0.25.0"]
    if platform.machine() == "x86_64":
        target_fc_versions.insert(0, "0.23.0")
    for target_fc_version in target_fc_versions:
        response = test_microvm.snapshot.create(
            mem_file_path="/snapshot/vm.mem",
            snapshot_path="/snapshot/vm.vmstate",
            version=target_fc_version
        )
        assert test_microvm.api_session.is_status_bad_request(
            response.status_code
        )
        assert "The virtio devices use a features that is incompatible " \
               "with older versions of Firecracker: notification suppression" \
               in response.text

        # It should work when we target a version >= 0.26.0
        response = test_microvm.snapshot.create(
            mem_file_path="/snapshot/vm.mem",
            snapshot_path="/snapshot/vm.vmstate",
            version="0.26.0"
        )
        assert test_microvm.api_session.is_status_no_content(
            response.status_code
        )
Exemplo n.º 13
0
def test_negative_postload_api(bin_cloner_path):
    """Test APIs fail after loading from snapshot."""
    logger = logging.getLogger("snapshot_api_fail")

    vm_builder = MicrovmBuilder(bin_cloner_path)
    vm_instance = VMNano.spawn(bin_cloner_path, diff_snapshots=True)
    basevm = vm_instance.vm
    root_disk = vm_instance.disks[0]
    ssh_key = vm_instance.ssh_key

    basevm.start()
    ssh_connection = net_tools.SSHConnection(basevm.ssh_config)

    # Verify if guest can run commands.
    exit_code, _, _ = ssh_connection.execute_command("sync")
    assert exit_code == 0

    logger.info("Create snapshot")
    # Create a snapshot builder from a microvm.
    snapshot_builder = SnapshotBuilder(basevm)

    # Create base snapshot.
    snapshot = snapshot_builder.create([root_disk.local_path()],
                                       ssh_key,
                                       SnapshotType.DIFF)

    basevm.kill()

    logger.info("Load snapshot, mem %s", snapshot.mem)
    # Do not resume, just load, so we can still call APIs that work.
    microvm, _ = vm_builder.build_from_snapshot(snapshot,
                                                False,
                                                True)
    fail_msg = "The requested operation is not supported after starting " \
        "the microVM"

    try:
        microvm.start()
    except AssertionError as error:
        assert fail_msg in str(error)
    else:
        assert False, "Negative test failed"

    try:
        microvm.basic_config()
    except AssertionError as error:
        assert fail_msg in str(error)
    else:
        assert False, "Negative test failed"

    microvm.kill()
Exemplo n.º 14
0
def test_mmds_snapshot(bin_cloner_path,  version):
    """
    Test MMDS behavior by restoring a snapshot on current and past FC versions.

    Ensures that the version is persisted or initialised with the default if
    the firecracker version does not support it.

    @type: functional
    """
    vm_builder = MicrovmBuilder(bin_cloner_path)
    vm_instance = vm_builder.build_vm_nano(
        net_ifaces=[NetIfaceConfig()]
    )

    # Validate current version.
    _validate_mmds_snapshot(
        vm_instance, vm_builder, version)

    # Validate restoring in past versions.
    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Fetch all firecracker binaries.
    # Create a snapshot with current build and restore with each FC binary
    # artifact.
    firecracker_artifacts = artifacts.firecrackers(
        # v1.1.0 breaks snapshot compatibility with older versions.
        min_version="1.1.0",
        max_version=get_firecracker_version_from_toml())
    for firecracker in firecracker_artifacts:
        vm_instance = vm_builder.build_vm_nano(
            net_ifaces=[NetIfaceConfig()]
        )
        firecracker.download()
        jailer = firecracker.jailer()
        jailer.download()

        target_version = firecracker.base_name()[1:]
        # If the version is smaller or equal to 1.0.0, we expect that
        # MMDS will be initialised with V1 by default.
        if compare_versions(target_version, "1.0.0") <= 0:
            mmds_version = "V1"
        else:
            mmds_version = version

        _validate_mmds_snapshot(
            vm_instance,
            vm_builder,
            mmds_version,
            target_fc_version=target_version,
            fc_path=firecracker.local_path(),
            jailer_path=jailer.local_path()
        )
Exemplo n.º 15
0
def test_serial_after_snapshot(bin_cloner_path):
    """
    Serial I/O after restoring from a snapshot.

    @type: functional
    """
    vm_builder = MicrovmBuilder(bin_cloner_path)
    vm_instance = vm_builder.build_vm_nano(
        diff_snapshots=False,
        daemonize=False,
    )
    microvm = vm_instance.vm
    root_disk = vm_instance.disks[0]
    ssh_key = vm_instance.ssh_key

    microvm.start()
    serial = Serial(microvm)
    serial.open()

    # Image used for tests on aarch64 has autologon
    if platform.machine() == "x86_64":
        serial.rx(token="login: "******"root")
        serial.rx("Password: "******"root")
    # Make sure that at the time we snapshot the vm, the user is logged in.
    serial.rx("#")

    snapshot_builder = SnapshotBuilder(microvm)
    disks = [root_disk.local_path()]
    # Create diff snapshot.
    snapshot = snapshot_builder.create(disks, ssh_key, SnapshotType.FULL)
    # Kill base microVM.
    microvm.kill()

    # Load microVM clone from snapshot.
    test_microvm, _ = vm_builder.build_from_snapshot(snapshot,
                                                     resume=True,
                                                     diff_snapshots=False,
                                                     daemonize=False)
    serial = Serial(test_microvm)
    serial.open()
    # We need to send a newline to signal the serial to flush
    # the login content.
    serial.tx("")
    serial.rx("#")
    serial.tx("pwd")
    res = serial.rx("#")
    assert "/root" in res
Exemplo n.º 16
0
def test_negative_api_lifecycle(bin_cloner_path):
    """Test some vm lifecycle error scenarios."""
    builder = MicrovmBuilder(bin_cloner_path)
    vm_instance = builder.build_vm_nano()
    basevm = vm_instance.vm

    # Try to pause microvm when not running, it must fail.
    response = basevm.vm.patch(state='Paused')
    assert "not supported before starting the microVM" \
        in response.text

    # Try to resume microvm when not running, it must fail.
    response = basevm.vm.patch(state='Resumed')
    assert "not supported before starting the microVM" \
        in response.text
Exemplo n.º 17
0
    def from_artifacts(cls,
                       bin_cloner_path,
                       config,
                       kernel,
                       disks,
                       cpu_template,
                       start=False,
                       fc_binary=None,
                       jailer_binary=None,
                       net_ifaces=None,
                       enable_diff_snapshots=False):
        """Spawns a new Firecracker and applies specified config."""
        artifacts = ArtifactCollection(_test_images_s3_bucket())
        # Pick the first artifact in the set.
        config = artifacts.microvms(keyword=config)[0]
        kernel = artifacts.kernels(keyword=kernel)[0]
        disks = artifacts.disks(keyword=disks)
        config.download()
        kernel.download()
        attached_disks = []
        for disk in disks:
            disk.download()
            attached_disks.append(disk.copy())

        vm_builder = MicrovmBuilder(bin_cloner_path, fc_binary, jailer_binary)

        # SSH key is attached to root disk artifact.
        # Builder will download ssh key in the VM root.
        ssh_key = disks[0].ssh_key()

        # Create a fresh microvm from aftifacts.
        basevm = vm_builder.build(kernel=kernel,
                                  disks=attached_disks,
                                  ssh_key=ssh_key,
                                  config=config,
                                  cpu_template=cpu_template,
                                  net_ifaces=net_ifaces,
                                  enable_diff_snapshots=enable_diff_snapshots)

        if start:
            basevm.start()
            ssh_connection = net_tools.SSHConnection(basevm.ssh_config)

            # Verify if we can run commands in guest via ssh.
            exit_code, _, _ = ssh_connection.execute_command("sync")
            assert exit_code == 0

        return VmInstance(config, kernel, attached_disks, ssh_key, basevm)
Exemplo n.º 18
0
def test_5_inc_snapshots(network_config, bin_cloner_path):
    """Test scenario: 5 incremental snapshots with disk intensive workload."""
    logger = logging.getLogger("snapshot_sequence")

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Testing matrix:
    # - Guest kernel: Linux 4.9/4.14
    # - Rootfs: Ubuntu 18.04
    # - Microvm: 2vCPU with 512 MB RAM
    # TODO: Multiple microvm sizes must be tested in the async pipeline.
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_4096mb"))
    kernel_artifacts = ArtifactSet(artifacts.kernels(keyword="vmlinux-4.14"))
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'network_config': network_config,
        'logger': logger,
        'snapshot_type': SnapshotType.DIFF,
        'seq_len': 5
    }

    # Create the test matrix.
    test_matrix = TestMatrix(
        context=test_context,
        artifact_sets=[microvm_artifacts, kernel_artifacts, disk_artifacts])

    test_matrix.run_test(_test_seq_snapshots)
def test_network_tcp_throughput(bin_cloner_path, results_file_dumper):
    """Test network throughput driver for multiple artifacts."""
    logger = logging.getLogger("network_tcp_throughput")
    artifacts = ArtifactCollection(_test_images_s3_bucket())
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_1024mb"))
    microvm_artifacts.insert(artifacts.microvms(keyword="1vcpu_1024mb"))
    kernel_artifacts = ArtifactSet(artifacts.kernels())
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'logger': logger,
        'name': 'network_tcp_throughput',
        'results_file_dumper': results_file_dumper
    }

    test_matrix = TestMatrix(context=test_context,
                             artifact_sets=[
                                 microvm_artifacts,
                                 kernel_artifacts,
                                 disk_artifacts
                             ])
    test_matrix.run_test(iperf_workload)
Exemplo n.º 20
0
def test_snapshot_resume_latency(network_config, bin_cloner_path):
    """Test scenario: Snapshot load performance measurement."""
    logger = logging.getLogger("snapshot_load")

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Testing matrix:
    # - Guest kernel: Linux 4.14
    # - Rootfs: Ubuntu 18.04
    # - Microvm: 2vCPU with 256/512 MB RAM
    # TODO: Multiple microvm sizes must be tested in the async pipeline.
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_512mb"))
    microvm_artifacts.insert(artifacts.microvms(keyword="2vcpu_256mb"))

    kernel_artifacts = ArtifactSet(artifacts.kernels(keyword="4.14"))
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'network_config': network_config,
        'logger': logger,
        'snapshot_type': SnapshotType.FULL,
    }

    # Create the test matrix.
    test_matrix = TestMatrix(
        context=test_context,
        artifact_sets=[microvm_artifacts, kernel_artifacts, disk_artifacts])

    test_matrix.run_test(_test_snapshot_resume_latency)
Exemplo n.º 21
0
def test_block_performance_sync(bin_cloner_path, results_file_dumper):
    """
    Test block performance for multiple vm configurations.

    @type: performance
    """
    logger = logging.getLogger(TEST_ID)

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    vm_artifacts = ArtifactSet(artifacts.microvms(keyword="1vcpu_1024mb"))
    vm_artifacts.insert(artifacts.microvms(keyword="2vcpu_1024mb"))

    kernel_artifacts = ArtifactSet(artifacts.kernels())
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    logger.info("Testing on processor %s", get_cpu_model_name())

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'logger': logger,
        'name': TEST_ID,
        'results_file_dumper': results_file_dumper,
        'io_engine': 'Sync'
    }

    test_matrix = TestMatrix(
        context=test_context,
        artifact_sets=[vm_artifacts, kernel_artifacts, disk_artifacts])
    test_matrix.run_test(fio_workload)
Exemplo n.º 22
0
def test_cmp_full_and_first_diff_mem(network_config, bin_cloner_path):
    """Test scenario: cmp memory of 2 consecutive full and diff snapshots."""
    logger = logging.getLogger("snapshot_sequence")

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Testing matrix:
    # - Guest kernel: Linux 4.9/4.14
    # - Rootfs: Ubuntu 18.04
    # - Microvm: 2vCPU with 512 MB RAM
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_512mb"))
    kernel_artifacts = ArtifactSet(artifacts.kernels(keyword="vmlinux-4.14"))
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'network_config': network_config,
        'logger': logger
    }

    # Create the test matrix.
    test_matrix = TestMatrix(
        context=test_context,
        artifact_sets=[microvm_artifacts, kernel_artifacts, disk_artifacts])

    test_matrix.run_test(_test_compare_mem_files)
Exemplo n.º 23
0
def test_network_latency(network_config, bin_cloner_path):
    """Test network latency driver for multiple artifacts."""
    logger = logging.getLogger("network_latency")
    microvm_artifacts = ArtifactSet(
        ARTIFACTS_COLLECTION.microvms(keyword="2vcpu_1024mb"))
    kernel_artifacts = ArtifactSet(ARTIFACTS_COLLECTION.kernels())
    disk_artifacts = ArtifactSet(ARTIFACTS_COLLECTION.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'network_config': network_config,
        'logger': logger,
        'requests': 10,
        'interval': 0.2,  # Seconds.
        'name': 'network_latency'
    }

    # Create the test matrix.
    test_matrix = TestMatrix(
        context=test_context,
        artifact_sets=[microvm_artifacts, kernel_artifacts, disk_artifacts])

    test_matrix.run_test(_g2h_send_ping)
Exemplo n.º 24
0
def test_vsock_throughput(bin_cloner_path):
    """Test vsock throughput driver for multiple artifacts."""
    logger = logging.getLogger("vsock_throughput")
    artifacts = ArtifactCollection(_test_images_s3_bucket())
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="1vcpu_1024mb"))
    microvm_artifacts.insert(artifacts.microvms(keyword="2vcpu_1024mb"))
    kernel_artifacts = ArtifactSet(
        artifacts.kernels(keyword="vmlinux-4.14.bin"))
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'logger': logger,
        'name': 'vsock_throughput'
    }

    print(get_cpu_model_name())

    test_matrix = TestMatrix(context=test_context,
                             artifact_sets=[
                                 microvm_artifacts,
                                 kernel_artifacts,
                                 disk_artifacts
                             ])
    test_matrix.run_test(iperf_workload)
def test_cmp_full_and_first_diff_mem(network_config, bin_cloner_path):
    """
    Compare memory of 2 consecutive full and diff snapshots.

    @type: functional
    """
    logger = logging.getLogger("snapshot_sequence")

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Testing matrix:
    # - Guest kernel: All supported ones
    # - Rootfs: Ubuntu 18.04
    # - Microvm: 2vCPU with 512 MB RAM
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_512mb"))
    kernel_artifacts = ArtifactSet(artifacts.kernels())
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        "builder": MicrovmBuilder(bin_cloner_path),
        "network_config": network_config,
        "logger": logger,
    }

    # Create the test matrix.
    test_matrix = TestMatrix(
        context=test_context,
        artifact_sets=[microvm_artifacts, kernel_artifacts, disk_artifacts],
    )

    test_matrix.run_test(_test_compare_mem_files)
def test_snap_restore_performance(bin_cloner_path, results_file_dumper):
    """
    Test the performance of snapshot restore.

    @type: performance
    """
    logger = logging.getLogger(TEST_ID)
    artifacts = ArtifactCollection(_test_images_s3_bucket())
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_1024mb"))
    kernel_artifacts = ArtifactSet(artifacts.kernels())
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    logger.info("Testing on processor %s", get_cpu_model_name())

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'logger': logger,
        'name': TEST_ID,
        'results_file_dumper': results_file_dumper
    }

    test_matrix = TestMatrix(
        context=test_context,
        artifact_sets=[microvm_artifacts, kernel_artifacts, disk_artifacts])
    test_matrix.run_test(snapshot_workload)
Exemplo n.º 27
0
def test_pause_resume(network_config, bin_cloner_path):
    """Test scenario: boot/pause/resume for all available configurations."""
    logger = logging.getLogger("pause_resume")
    # Currently, artifacts share the bucket with all other resources.
    artifact_collection = ArtifactCollection(_test_images_s3_bucket())

    microvm_artifacts = ArtifactSet(artifact_collection.microvms())
    kernel_artifacts = ArtifactSet(artifact_collection.kernels())
    # Restrict root fs to ubuntu.
    disk_artifacts = ArtifactSet(artifact_collection.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'network_config': network_config,
        'logger': logger
    }

    # Create the test matrix.
    test_matrix = TestMatrix(
        context=test_context,
        artifact_sets=[microvm_artifacts, kernel_artifacts, disk_artifacts])

    test_matrix.run_test(_test_pause_resume)
Exemplo n.º 28
0
def test_older_snapshot_resume_latency(bin_cloner_path, results_file_dumper):
    """
    Test scenario: Older snapshot load performance measurement.

    @type: performance
    """
    logger = logging.getLogger("old_snapshot_load")

    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Fetch all firecracker binaries.
    # With each binary create a snapshot and try to restore in current
    # version.
    firecracker_artifacts = ArtifactSet(artifacts.firecrackers(
        max_version=get_firecracker_version_from_toml()))
    assert len(firecracker_artifacts) > 0

    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_512mb"))

    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'logger': logger,
        'snapshot_type': SnapshotType.FULL,
        'name': 'old_snapshot_resume_latency',
        'results_file_dumper': results_file_dumper
    }

    # Create the test matrix.
    test_matrix = TestMatrix(context=test_context,
                             artifact_sets=[
                                 firecracker_artifacts,
                                 microvm_artifacts,
                             ])

    test_matrix.run_test(_test_older_snapshot_resume_latency)
Exemplo n.º 29
0
def build_test_matrix(network_config, bin_cloner_path, logger):
    """Build a test matrix using the kernel with the balloon driver."""
    artifacts = ArtifactCollection(_test_images_s3_bucket())
    # Testing matrix:
    # - Guest kernel: Linux 4.14
    # - Rootfs: Ubuntu 18.04
    # - Microvm: 2vCPU with 256 MB RAM
    # TODO: Multiple microvm sizes must be tested in the async pipeline.
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_256mb"))
    kernel_artifacts = ArtifactSet(artifacts.kernels(keyword="vmlinux-4.14"))
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'network_config': network_config,
        'logger': logger,
        'snapshot_type': SnapshotType.FULL,
        'seq_len': 5
    }

    # Create the test matrix.
    return TestMatrix(
        context=test_context,
        artifact_sets=[microvm_artifacts, kernel_artifacts, disk_artifacts])
Exemplo n.º 30
0
def test_block_performance(bin_cloner_path):
    """Test network throughput driver for multiple artifacts."""
    logger = logging.getLogger(TEST_ID)
    artifacts = ArtifactCollection(_test_images_s3_bucket())
    microvm_artifacts = ArtifactSet(artifacts.microvms(keyword="2vcpu_1024mb"))
    microvm_artifacts.insert(artifacts.microvms(keyword="1vcpu_1024mb"))
    kernel_artifacts = ArtifactSet(artifacts.kernels())
    disk_artifacts = ArtifactSet(artifacts.disks(keyword="ubuntu"))

    # Create a test context and add builder, logger, network.
    test_context = TestContext()
    test_context.custom = {
        'builder': MicrovmBuilder(bin_cloner_path),
        'logger': logger,
        'name': TEST_ID
    }

    print(f"CPU model: {get_cpu_model_name()}.")

    test_matrix = TestMatrix(context=test_context,
                             artifact_sets=[
                                 microvm_artifacts,
                                 kernel_artifacts,
                                 disk_artifacts
                             ])
    test_matrix.run_test(fio_workload)