Esempio n. 1
0
def check_vm_cpu_model(vm_id, vcpu_model, expt_arch=None):
    if vcpu_model == 'Passthrough':
        pattern_ps = 'host'
        pattern_virsh = 'host-passthrough'
        virsh_tag = 'cpu'
        type_ = 'dict'
    elif vcpu_model:
        virsh_tag = 'cpu/model'
        type_ = 'text'
        if vcpu_model == 'Haswell':
            pattern_ps = pattern_virsh = r'(haswell|haswell\-notsx)'
        else:
            pattern_ps = pattern_virsh = vcpu_model.lower()
    else:
        # vcpu model is not set
        pattern_ps = None
        pattern_virsh = None
        virsh_tag = 'cpu'
        type_ = 'dict'

    LOG.info(
        "Check vcpu model successfully applied to vm via ps aux and virsh dumpxml on vm host"
    )
    host = vm_helper.get_vm_host(vm_id)
    inst_name = vm_helper.get_vm_instance_name(vm_id)
    with host_helper.ssh_to_host(host) as host_ssh:
        output_ps = host_ssh.exec_cmd(
            "ps aux | grep --color='never' -i {}".format(vm_id),
            fail_ok=False)[1]
        output_virsh = host_helper.get_values_virsh_xmldump(
            inst_name, host_ssh, tag_paths=virsh_tag, target_type=type_)
        output_virsh = output_virsh[0]

    if vcpu_model:
        assert re.search(r'\s-cpu\s{}(\s|,)'.format(pattern_ps), output_ps.lower()), \
            'cpu_model {} not found for vm {}'.format(pattern_ps, vm_id)
    else:
        assert '-cpu' not in output_ps, "cpu model is specified in ps aux"

    if vcpu_model == 'Passthrough':
        assert output_virsh['mode'] == 'host-passthrough', \
            'cpu mode is not passthrough in virsh for vm {}'.format(vm_id)

        LOG.info("Check cpu passthrough model from within the vm")
        vm_vcpu_model = vm_helper.get_vcpu_model(vm_id)
        host_cpu_model = host_helper.get_host_cpu_model(host=host)
        assert host_cpu_model == vm_vcpu_model, "VM cpu model is different than host cpu model with cpu passthrough"

        if expt_arch:
            assert expt_arch == vm_vcpu_model, "VM cpu model changed. Original: {}. Current: {}".\
                format(expt_arch, vcpu_model)
    elif vcpu_model:
        assert re.search(pattern_virsh, output_virsh.lower()), \
            'cpu model {} is not found in virsh for vm {}'.format(pattern_virsh, vm_id)

    else:
        assert output_virsh == {}, "Virsh cpu output: {}".format(output_virsh)
        vm_vcpu_model = vm_helper.get_vcpu_model(vm_id)
        assert 'QEMU Virtual CPU' in vm_vcpu_model, "vCPU model is not QEMU Virtual CPU when unspecified"
Esempio n. 2
0
def test_vcpu_model_resize(source_model, dest_model):
    """

    Args:
        source_model:
        dest_model:

    Test Steps:
        - Create a source flavor with 4G root disk and vcpu model extra spec as specified in source_model
        - Create a dest flavor with 5G root disk and vcpu model extra spec as specified in dest_model
        - Launch a vm from image with source flavor
        - Check vcpu_model is successfully applied
        - Resize the vm with dest flavor
        - Check new vcpu_model is successfully applied

    Teardown:
        - Delete created vm, image, flavors

    """
    LOG.tc_step(
        "Create a source flavor with 4G root disk and vcpu model extra spec: {}"
        .format(source_model))
    source_flv = _create_flavor_vcpu_model(vcpu_model=source_model,
                                           root_disk_size=4)

    LOG.tc_step(
        "Create a destination flavor with 5G root disk and vcpu model extra spec: {}"
        .format(source_model))
    dest_flv = _create_flavor_vcpu_model(vcpu_model=dest_model,
                                         root_disk_size=5)

    LOG.tc_step(
        "Launch a vm from image with source flavor {}".format(source_flv))
    vm_id = vm_helper.boot_vm(flavor=source_flv,
                              source='image',
                              cleanup='function')[1]
    vm_helper.wait_for_vm_pingable_from_natbox(vm_id)
    check_vm_cpu_model(vm_id=vm_id, vcpu_model=source_model)

    expt_arch = None
    if source_model == dest_model == 'Passthrough':
        # Ensure vm resize to host with exact same cpu model when vcpu_model is passthrough
        host = vm_helper.get_vm_host(vm_id)
        expt_arch = host_helper.get_host_cpu_model(host)

    LOG.tc_step("Resize vm to destination flavor {}".format(dest_flv))
    vm_helper.resize_vm(vm_id, flavor_id=dest_flv)
    vm_helper.wait_for_vm_pingable_from_natbox(vm_id)
    check_vm_cpu_model(vm_id, vcpu_model=dest_model, expt_arch=expt_arch)
Esempio n. 3
0
def test_vmx_setting():
    """
    Test that vmx feature can be set in guest VM.

    Test Steps:
       - Create a flavor with extra specs hw:wrs:nested_vmx=True and hw:cpu_model=<a cpu model supported by the host>
       - Instantiate a VM with the flavor and check that vm has correct vcpu model
       - ssh into the VM and execute "grep vmx /proc/cpuinfo" and verify that vmx feature is set
    """

    # Create a flavor with specs: hw:wrs:nested_vmx=True and extraspec hw:cpu_model=<compute host cpu model>

    host_cpu_model = 'Passthrough'
    LOG.tc_step("Create flavor for vcpu model {}".format(host_cpu_model))
    flavor_id = nova_helper.create_flavor(fail_ok=False)[1]
    ResourceCleanup.add('flavor', flavor_id)

    LOG.tc_step(
        "Set extra specs for flavor of vcpu model {}".format(host_cpu_model))
    extra_specs = {
        FlavorSpec.NESTED_VMX: True,
        FlavorSpec.VCPU_MODEL: host_cpu_model
    }
    nova_helper.set_flavor(flavor=flavor_id, **extra_specs)

    LOG.tc_step("Create VM for vcpu model {}".format(host_cpu_model))
    code, vm, msg = vm_helper.boot_vm(flavor=flavor_id,
                                      cleanup='function',
                                      fail_ok=False)
    ResourceCleanup.add('vm', vm)
    LOG.tc_step("Check vcpu model is correct")
    host = vm_helper.get_vm_host(vm)
    expt_arch = host_helper.get_host_cpu_model(host)
    check_vm_cpu_model(vm_id=vm, vcpu_model='Passthrough', expt_arch=expt_arch)

    LOG.tc_step("Checking to see if 'vmx' is in /proc/cpuinfo")
    with vm_helper.ssh_to_vm_from_natbox(vm) as vm_ssh:
        vm_ssh.exec_cmd("grep vmx /proc/cpuinfo", fail_ok=False)
Esempio n. 4
0
def test_vcpu_model_evacuation(add_admin_role_func, cpu_models_supported):
    """
    Launch a set of vms with different cpu models and evacuate.

    Skip if:
        - Less than two hypervisors available for evacuation

    Setups:
        - Add admin role to tenant under test (in order to launch vm onto specific host)

    Test Steps:
        - Boot 4 vms from image or volume onto the same host with different cpu models set in flavor or image metadata
            - 3 of them will have the 3 latest supported vcpu models
            - 1 of them with Passthrough model
        - Reboot -f the vms host all to trigger an evacuation
        - Ensure evacuation for all vms is successful (vm host changed, active state, pingable from NatBox)
        - Check VMs retained their correct cpu models

    Teardown:
            - Delete created vms
            - Remove admin role from primary tenant (module)
    """

    cpu_models_multi_host, all_cpu_models_supported = cpu_models_supported
    if not cpu_models_multi_host:
        skip("Less than two hypervisors available for evacuation")

    vm_dict = {}

    LOG.info("Create 3 vms with top 3 vcpu models from: {}".format(
        cpu_models_multi_host))
    target_host = None
    boot_source = 'image'
    flv_model = None
    for i in range(3):
        for vcpu_model in cpu_models_multi_host:
            if flv_model:
                img_model = vcpu_model
                flv_model = None
            else:
                img_model = None
                flv_model = vcpu_model
            code, vm, msg = _boot_vm_vcpu_model(flv_model=flv_model,
                                                img_model=img_model,
                                                boot_source=boot_source,
                                                avail_zone='nova',
                                                vm_host=target_host)
            assert 0 == code, "Failed to launch vm with {} cpu model. Details: {}".format(
                vcpu_model, msg)

            vm_helper.wait_for_vm_pingable_from_natbox(vm)
            check_vm_cpu_model(vm_id=vm, vcpu_model=vcpu_model)
            vm_dict[vm] = vcpu_model

            boot_source = 'image' if boot_source == 'volume' else 'volume'
            if len(vm_dict) == 3:
                break
            if not target_host:
                target_host = vm_helper.get_vm_host(vm_id=vm)

        if len(vm_dict) == 3:
            break

    # Create a Passthrough VM
    code, vm, msg = _boot_vm_vcpu_model('Passthrough',
                                        None,
                                        boot_source,
                                        avail_zone='nova',
                                        vm_host=target_host)
    vm_helper.wait_for_vm_pingable_from_natbox(vm)
    expt_arch = host_helper.get_host_cpu_model(target_host)
    check_vm_cpu_model(vm_id=vm, vcpu_model='Passthrough', expt_arch=expt_arch)
    vm_dict[vm] = 'Passthrough'

    LOG.tc_step(
        "Reboot target host {} to start evacuation".format(target_host))
    vm_helper.evacuate_vms(target_host, list(vm_dict.keys()), ping_vms=True)

    LOG.tc_step("Check vcpu models unchanged after evacuation")
    for vm_, cpu_ in vm_dict.items():
        post_evac_expt_arch = None
        LOG.info("Check vm {} has cpu model {} after evac".format(vm_, cpu_))

        if cpu_ == 'Passthrough':
            post_evac_expt_arch = expt_arch
        check_vm_cpu_model(vm_id=vm_,
                           vcpu_model=cpu_,
                           expt_arch=post_evac_expt_arch)
Esempio n. 5
0
def test_vm_vcpu_model(vcpu_model, vcpu_source, boot_source,
                       cpu_models_supported):
    """
    Test vcpu model specified in flavor will be applied to vm. In case host does not support specified vcpu model,
    proper error message should be displayed in nova show.

    Args:
        vcpu_model
        vcpu_source
        boot_source

    Test Steps:
        - Set flavor extra spec or image metadata with given vcpu model.
        - Boot a vm from volume/image
        - Stop and then start vm and ensure that it retains its cpu model
        - If vcpu model is supported by host,
            - Check vcpu model specified in flavor/image is used by vm via virsh, ps aux (and /proc/cpuinfo)
            - Live migrate vm and check vcpu model again
            - Cold migrate vm and check vcpu model again
        - If vcpu model is not supported by host, check proper error message is included if host does not
            support specified vcpu model.
    Teardown:
        - Delete created vm, volume, image, flavor

    """
    cpu_models_multi_host, all_cpu_models_supported = cpu_models_supported
    flv_model = vcpu_model if vcpu_source == 'flavor' else None
    img_model = vcpu_model if vcpu_source == 'image' else None
    code, vm, msg = _boot_vm_vcpu_model(flv_model=flv_model,
                                        img_model=img_model,
                                        boot_source=boot_source)

    is_supported = (not vcpu_model) or (vcpu_model == 'Passthrough') or (
        vcpu_model in all_cpu_models_supported)
    if not is_supported:
        LOG.tc_step(
            "Check vm in error state due to vcpu model unsupported by hosts.")
        assert 1 == code, "boot vm cli exit code is not 1. Actual fail reason: {}".format(
            msg)

        expt_fault = VCPUSchedulerErr.CPU_MODEL_UNAVAIL
        res_bool, vals = vm_helper.wait_for_vm_values(vm,
                                                      10,
                                                      regex=True,
                                                      strict=False,
                                                      status='ERROR')
        err = vm_helper.get_vm_fault_message(vm)

        assert res_bool, "VM did not reach expected error state. Actual: {}".format(
            vals)
        assert re.search(expt_fault, err), "Incorrect fault reported. Expected: {} Actual: {}" \
            .format(expt_fault, err)
        return

    # System supports specified vcpu, continue to verify
    expt_arch = None
    if vcpu_model == 'Passthrough':
        host = vm_helper.get_vm_host(vm)
        expt_arch = host_helper.get_host_cpu_model(host)

    LOG.tc_step("Check vm is launched with expected vcpu model")
    vm_helper.wait_for_vm_pingable_from_natbox(vm_id=vm)
    check_vm_cpu_model(vm_id=vm, vcpu_model=vcpu_model, expt_arch=expt_arch)

    multi_hosts_supported = (not vcpu_model) or (vcpu_model in cpu_models_multi_host) or \
                            (vcpu_model == 'Passthrough' and cpu_models_multi_host)
    # TC5141
    LOG.tc_step(
        "Stop and then restart vm and check if it retains its vcpu model")
    vm_helper.stop_vms(vm)
    vm_helper.start_vms(vm)
    vm_helper.wait_for_vm_pingable_from_natbox(vm_id=vm)
    check_vm_cpu_model(vm_id=vm, vcpu_model=vcpu_model, expt_arch=expt_arch)

    if not multi_hosts_supported:
        LOG.info(
            "Skip migration steps. Less than two hosts in same storage aggregate support {}"
            .format(vcpu_model))
        return

    LOG.tc_step(
        "Live (block) migrate vm and check {} vcpu model".format(vcpu_model))
    vm_helper.live_migrate_vm(vm_id=vm)
    vm_helper.wait_for_vm_pingable_from_natbox(vm_id=vm)
    check_vm_cpu_model(vm, vcpu_model, expt_arch=expt_arch)

    LOG.tc_step("Cold migrate vm and check {} vcpu model".format(vcpu_model))
    vm_helper.cold_migrate_vm(vm_id=vm)
    vm_helper.wait_for_vm_pingable_from_natbox(vm_id=vm)
    check_vm_cpu_model(vm, vcpu_model, expt_arch=expt_arch)