예제 #1
0
def unset_flavor(flavor,
                 properties=None,
                 project=None,
                 project_domain=None,
                 check_first=True,
                 fail_ok=False,
                 auth_info=Tenant.get('admin'),
                 con_ssh=None):
    """
    Unset specific extra spec(s) from given flavor.

    Args:
        flavor (str): id of the flavor
        properties (str|list|tuple): extra spec(s) to be removed. At least one should be provided.
        project_domain
        project
        check_first (bool): Whether to check if extra spec exists in flavor before attempt to unset
                con_ssh (SSHClient):
        auth_info (dict):
        fail_ok (bool):
        con_ssh

    Returns (tuple): (rtn_code (int), message (str))
        (-1, 'Extra spec(s) <specs> not exist in flavor. Do nothing.')
        (0, 'Flavor extra specs unset successfully.'): required extra spec(s) removed successfully
        (1, <stderr>): unset extra spec cli rejected
        (2, '<spec_name> is still in the extra specs list'): post action check failed

    """
    if isinstance(properties, str):
        properties = [properties]

    if properties and check_first:
        existing_specs = get_flavor_values(flavor,
                                           fields='properties',
                                           con_ssh=con_ssh,
                                           auth_info=auth_info)[0]
        properties = list(set(properties) & set(existing_specs.keys()))

    args_dict = {
        '--property': properties,
        '--project': project,
        '--project_domain': project_domain,
    }
    args = common.parse_args(args_dict, repeat_arg=True)
    if not args:
        msg = "Nothing to unset for flavor {}. Do nothing.".format(flavor)
        LOG.info(msg)
        return -1, msg

    LOG.info("Unsetting flavor {} with args: {}".format(flavor, args))
    exit_code, output = cli.openstack('flavor unset',
                                      args,
                                      ssh_client=con_ssh,
                                      fail_ok=fail_ok,
                                      auth_info=auth_info)
    if exit_code > 0:
        return 1, output

    success_msg = "Flavor {} unset successfully".format(flavor)
    LOG.info(success_msg)
    return 0, success_msg
예제 #2
0
def test_modify_timezone_log_timestamps():
    """
    Test correct log timestamps after timezone change

    Prerequisites
        - N/A
    Test Setups
        - Get a random timezone for testing
        - Get system time (epoch) before timezone change
    Test Steps
        - Modify timezone
        - While to modification is pending get the last timestamp (epoch) from each log
        - Wait for out_of_date alarms to clear
        - Get system time (epoch) after timezone change
        - Ensure the timezone change effected the date by comparing system time before and after timezone change
        - For 3 minutes check each log for a new entry
        - Ensure that the new entry in each log is in line with the timezone change
    Test Teardown
        - N/A
    """
    logs = ('auth.log', 'daemon.log', 'fm-event.log', 'fsmond.log', 'kern.log', 'openstack.log',
            'pmond.log', 'user.log')
    #  'sm-scheduler.log' fails (CGTS-10475)

    LOG.tc_step("Collect timezone, system time, and log timestamps before modify timezone")

    LOG.info("Get timezones for testing")
    prev_timezone = system_helper.get_timezone()
    post_timezone = __select_diff_timezone(current_zone=prev_timezone)

    con_ssh = ControllerClient.get_active_controller()
    # Saving the last entry from the logs; If it is the same later, there is no new entry in the log.
    LOG.tc_step("Get last entry from log files and compare with system time")
    prev_timestamps = {}
    time.sleep(5)
    for log in logs:
        last_line = con_ssh.exec_cmd('tail -n 1 /var/log/{}'.format(log))[1]
        log_epoch = parse_log_time(last_line)
        prev_timestamps[log] = log_epoch

    prev_system_epoch = get_epoch_date(con_ssh=con_ssh)
    prev_check_fail = []
    for log, timestamp in prev_timestamps.items():
        if timestamp > prev_system_epoch:
            prev_check_fail.append(log)

    assert not prev_check_fail, "{} timestamp does not match system time".format(prev_check_fail)

    start_time = time.time()
    LOG.tc_step("Modify timezone from {} to {}".format(prev_timezone, post_timezone))
    system_helper.modify_timezone(timezone=post_timezone)
    end_time = time.time()
    mod_diff = end_time - start_time

    LOG.tc_step("Verify system time is updated")
    time.sleep(10)
    post_system_epoch = get_epoch_date(con_ssh=con_ssh)
    time_diff = abs(prev_system_epoch - post_system_epoch)
    assert time_diff > 3600, "Timezone change did not affect the date"
    LOG.info("system time is updated after timezone modify")

    LOG.tc_step("Wait for new logs to generate and verify timestamps for new log entries are updated")
    logs_to_test = {}
    timeout = time.time() + 300
    while time.time() < timeout:
        for log_name, value in prev_timestamps.items():
            last_line = con_ssh.exec_cmd('tail -n 1 /var/log/{}'.format(log_name))[1]
            # If last line does not exist in last_log_entries; New line is in the log; Add log to logs_to_test
            new_log_epoch = parse_log_time(last_line)
            prev_log_epoch = prev_timestamps[log_name]
            epoch_diff_prev_log_to_sys = prev_system_epoch - prev_log_epoch
            epoch_diff_prev_log = new_log_epoch - prev_log_epoch

            LOG.info('timezone modify time used: {}; pre-modify sys time - last log time: {}'.
                     format(mod_diff, epoch_diff_prev_log_to_sys))
            if abs(epoch_diff_prev_log) > max(mod_diff, 180) + epoch_diff_prev_log_to_sys:
                LOG.info("{} has new log entry. Adding to logs_to_test.".format(log_name))
                logs_to_test[log_name] = new_log_epoch
                del prev_timestamps[log_name]
                break

        if not prev_timestamps:
            break

        time.sleep(10)

    # Get latest log entries, convert to epoch
    failed_logs = {}
    for log_name, value in logs_to_test.items():
        time_diff = abs(value - post_system_epoch)
        LOG.info("log: {} time diff: {}".format(log_name, time_diff))
        if time_diff > 330:
            failed_logs[log_name] = "time_diff: {}".format(time_diff)
    assert not failed_logs, "Timestamp for following new logs are different than system time: {}".format(failed_logs)
def test_set_hosts_storage_backing_equal(instance_backing, number_of_hosts):
    """
    Modify hosts storage backing if needed so that system has exact number of hosts in given instance backing

    Args:
        instance_backing:
        number_of_hosts:

    Test Steps:
        - Calculate the hosts to be configured based on test params
        - Configure hosts to meet given criteria
        - Check number of hosts in given instance backing is as specified

    """
    host_num_mapping = {'zero': 0, 'one': 1, 'two': 2}
    number_of_hosts = host_num_mapping[number_of_hosts]
    LOG.tc_step("Calculate the hosts to be configured based on test params")
    candidate_hosts = get_candidate_hosts(number_of_hosts=number_of_hosts)

    hosts_with_backing = host_helper.get_hosts_in_storage_backing(
        instance_backing)
    if len(hosts_with_backing) == number_of_hosts:
        LOG.info("Already have {} hosts in {} backing. Do nothing".format(
            number_of_hosts, instance_backing))
        return

    elif len(hosts_with_backing) < number_of_hosts:
        backing_to_config = instance_backing
        number_to_config = number_of_hosts - len(hosts_with_backing)
        hosts_pool = list(set(candidate_hosts) - set(hosts_with_backing))
    else:
        backing_to_config = 'remote' if 'image' in instance_backing else 'local_image'
        number_to_config = len(hosts_with_backing) - number_of_hosts
        hosts_pool = hosts_with_backing

    LOG.tc_step(
        "Delete vms if any to prepare for system configuration change with best effort"
    )
    vm_helper.delete_vms(fail_ok=True)

    hosts_to_config = hosts_pool[0:number_to_config]
    LOG.tc_step("Configure following hosts to {} backing: {}".format(
        hosts_to_config, backing_to_config))

    for host in hosts_to_config:
        host_helper.set_host_storage_backing(host=host,
                                             inst_backing=backing_to_config,
                                             unlock=False,
                                             wait_for_configured=False)
        HostsToRecover.add(host)

    host_helper.unlock_hosts(hosts_to_config,
                             check_hypervisor_up=True,
                             fail_ok=False)

    LOG.tc_step("Waiting for hosts in {} aggregate".format(backing_to_config))
    for host in hosts_to_config:
        host_helper.wait_for_host_in_instance_backing(
            host, storage_backing=backing_to_config)

    LOG.tc_step("Check number of {} hosts is {}".format(
        instance_backing, number_of_hosts))
    assert number_of_hosts == len(host_helper.get_hosts_in_storage_backing(instance_backing)), \
        "Number of {} hosts is not {} after configuration".format(instance_backing, number_of_hosts)
예제 #4
0
def delete_strategy(orchestration,
                    check_first=True,
                    fail_ok=False,
                    conn_ssh=None):
    """
    Deletes an orchestration strategy
    Args:
        orchestration (str): indicates the orchestration strategy type. Choices are  patch or upgrade
        conn_ssh:
        check_first (bool): Check if strategy exits, if so, check if strategy is still in-progress, if so, abort it
        fail_ok:

    Returns (tuple):
        (-1, "No strategy available. Do nothing.")
        (0, "<orch_type> orchestration strategy deleted successfully.")
        (1, <std_err>)  # CLI command rejected

    """
    if orchestration is None:
        raise ValueError(
            "The orchestration type (choices are 'patch' or 'upgrade') must be specified"
        )
    cmd = ''
    if orchestration is "patch":
        cmd += "patch-strategy "
    elif orchestration is "upgrade":
        cmd += "upgrade-strategy "

    strategy_info = get_current_strategy_info(orchestration, conn_ssh=conn_ssh)
    if check_first:
        if not strategy_info:
            msg = "No strategy available. Do nothing."
            LOG.info(msg)
            return -1, msg

        if strategy_info.get(OrchStrategyKey.INPROGRESS, None) == 'true':
            LOG.info("Strategy in progress. Abort.")
            strategy_state = strategy_info[OrchStrategyKey.STATE]
            if strategy_state in (OrchStrategyState.APPLYING,
                                  OrchStrategyState.BUILDING,
                                  OrchStrategyState.INITIAL):
                cli.sw_manager(cmd,
                               'abort',
                               ssh_client=conn_ssh,
                               fail_ok=False)
                wait_strategy_phase_completion(orchestration,
                                               OrchestStrategyPhase.ABORT)
            elif strategy_state == OrchStrategyState.ABORTING:
                wait_strategy_phase_completion(orchestration,
                                               OrchestStrategyPhase.ABORT)

    rc, output = cli.sw_manager(cmd,
                                'delete',
                                ssh_client=conn_ssh,
                                fail_ok=fail_ok)

    if rc != 0:
        return 1, output

    post_strategy_info = get_current_strategy_info(orchestration,
                                                   conn_ssh=conn_ssh)
    if post_strategy_info:
        raise exceptions.OrchestrationError(
            "{} strategy still exists after deletion: {}".format(
                orchestration, post_strategy_info))

    msg = "{} orchestration strategy deleted successfully.".format(
        orchestration)
    LOG.info(msg)
    return 0, msg
예제 #5
0
def test_ldap_create_user(user_name, sudoer, secondary_group, expiry_days,
                          expiry_warn_days):
    """
    Create a LDAP User with the specified name

    User Stories:   US70961

    Steps:
        1   create a LDAP User with the specified name
        2   verify the LDAP User is successfully created and get its details

    """
    sudoer = True if sudoer == 'sudoer' else False
    secondary_group = True if secondary_group == 'secondary_group' else False

    LOG.tc_step(
        'Check if any LDAP User with name:{} existing'.format(user_name))
    existing, user_info = theLdapUserManager.find_ldap_user(user_name)
    if existing:
        LOG.warn(
            'LDAP User:{} already existing! Delete it for testing user-creation'
            .format(user_name))
        code, output = theLdapUserManager.rm_ldap_user(user_name)
        if 0 != code:
            skip('LDAP User:{} already existing and failed to delete!')
        else:
            LOG.warn('Existing LDAP User:{} is successfully deleted'.format(
                user_name))
    else:
        LOG.warn(
            'OK, LDAP User:{} is not existing, continue to create one'.format(
                user_name))

    LOG.tc_step('Creating LDAP User:{}'.format(user_name))

    code, user_settings = theLdapUserManager.create_ldap_user(
        user_name,
        sudoer=sudoer,
        secondary_group=secondary_group,
        password_expiry_days=expiry_days,
        password_expiry_warn_days=expiry_warn_days,
        check_if_existing=True,
        delete_if_existing=True)

    if 0 == code:
        LOG.info('OK, created LDAP for User:{}, user-details:\n{}'.format(
            user_name, user_settings))
    else:
        if 1 == code:
            msg = 'Already exists the LDAP User:{}.'.format(user_name)
        elif 2 == code:
            msg = 'Failed to find the created LDAP User:{} although creating succeeded.'.format(
                user_name)
        elif 3 == code:
            msg = 'Failed to create the LDAP User:{}.'.format(user_name)
        else:
            msg = 'Failed to create the LDAP User:{} for unknown reason.'.format(
                user_name)

        LOG.error(msg)
        assert False, msg

    LOG.info('OK, successfully created the LDAP User {}'.format(user_name))
예제 #6
0
def change_linux_user_password(password, new_password, user=None, host=None):
    if not user:
        user = HostLinuxUser.get_user()

    LOG.info(
        'Attempt to change password, from password:{}, to new-password:{}, '
        'on host:{}'.format(password, new_password, host))

    input_outputs = (
        (
            'passwd',
            (r'\(current\) UNIX password: '******'New password: '******': Authentication token manipulation error',
                EOF,
            ),
        ),
        (
            new_password,
            ('Retype new password:'******'BAD PASSWORD: The password is too similar to the old one',
                'BAD PASSWORD: No password supplied',
                'passwd: Have exhausted maximum number of retries for service',
                EOF,
            ),
        ),
        (
            new_password,
            (
                ': all authentication tokens updated successfully.',
                Prompt.CONTROLLER_PROMPT,
            ),
            (),
        ),
    )
    conn_to_ac = ControllerClient.get_active_controller()
    initial_prompt = r'.*{}\:~\$ '.format(host)
    LOG.info('Will login as user:"******", password:"******", to host:"{}"'.format(
        user, password, host))

    conn = SSHFromSSH(conn_to_ac,
                      host,
                      user,
                      password,
                      force_password=True,
                      initial_prompt=initial_prompt)
    passed = True
    try:
        conn.connect(retry=False, use_password=True)
        for cmd, expected, errors in input_outputs:
            # conn.flush()
            LOG.info("Send '{}'\n".format(cmd))
            conn.send(cmd)
            blob_list = list(expected) + list(errors)
            LOG.info("Expect: {}\n".format(blob_list))
            index = conn.expect(blob_list=blob_list)
            LOG.info('returned index:{}\n'.format(index))
            if len(expected) <= index:
                passed = False
                break

    except Exception as e:
        LOG.warn('Caught exception when connecting to host:{} as user:{} with '
                 'pasword:{}\n{}\n'.format(host, user, password, e))

        raise

    finally:
        if user != HostLinuxUser.get_user():
            conn.close()

    # flush the output to the cli so the next cli is correctly registered
    conn.flush()
    LOG.info('Successfully changed password from:\n{}\nto:{} for user:{} on '
             'host:{}'.format(password, new_password, user, host))

    return passed, new_password
예제 #7
0
def apply_strategy(orchestration,
                   timeout=OrchestrationPhaseTimeout.APPLY,
                   conn_ssh=None,
                   fail_ok=False):
    """
    applies an orchestration strategy
    Args:
        orchestration (str): indicates the orchestration strategy type. Choices are  patch or upgrade
        timeout (int):

        conn_ssh:
        fail_ok:

    Returns (tuple):
        (0, <actual_states>(dict)) - success  strategy applied successfully
        (1, <std_err>) - CLI command rejected
        (2, <actual_states>(dict)) - Strategy apply failed

    """
    if orchestration not in ('patch', 'upgrade'):
        raise ValueError(
            "The orchestration type (choices are 'patch' or 'upgrade') must be specified"
        )

    # strategy_values = get_current_strategy_values(orchestration)
    if orchestration is "patch":
        cmd = "patch-strategy apply"
    else:
        cmd = "upgrade-strategy apply"

    rc, output = cli.sw_manager(cmd, ssh_client=conn_ssh, fail_ok=fail_ok)

    if rc != 0:
        return 1, output

    res, results = wait_strategy_phase_completion(orchestration,
                                                  OrchestStrategyPhase.APPLY,
                                                  timeout=timeout,
                                                  conn_ssh=conn_ssh,
                                                  fail_ok=True)
    if not res:
        c_phase = results[OrchStrategyKey.CURRENT_PHASE]
        c_compl = results['current-phase-completion']

        if c_phase == OrchestStrategyPhase.APPLY and int(
                c_compl.strip()[:-1]) > 50:
            LOG.warning(
                'current-phase-completion > 50%, extend wait time for {} strategy to apply'
                .format(orchestration))
            res, results = wait_strategy_phase_completion(
                orchestration,
                OrchestStrategyPhase.APPLY,
                timeout=timeout,
                conn_ssh=conn_ssh,
                fail_ok=True)
    if not res:
        msg = "{} strategy failed to apply. Current state: {}".format(
            orchestration, results[OrchStrategyKey.STATE])
        LOG.warn(msg)
        if fail_ok:
            return 2, results
        else:
            raise exceptions.OrchestrationError(msg)

    if results[OrchStrategyKey.STATE] != OrchStrategyState.APPLIED or \
            results[OrchStrategyKey.APPLY_RESULT] != 'success':
        raise exceptions.OrchestrationError(
            '{} strategy not in applied state after completion'.format(
                orchestration))

    LOG.info("apply {} strategy completed successfully: {}".format(
        orchestration, results))
    return 0, results
예제 #8
0
def test_ima_no_event(operation, file_path):
    """
    This test validates following scenarios will not generate IMA event:
        - create symlink of a monitored file
        - copy a root file with the proper IMA signature, the nexcute it
        - make file attribute changes, include: chgrp, chown, chmod
        - create and execute a files as sysadmin

    Test Steps:
        - Perform specified operation on given file
        - Confirm IMA violation event is not triggered

    Teardown:
        - Delete created test file

    Maps to TC_17684/TC_17644/TC_17640/TC_17902 from US105523
    This test also covers TC_17665/T_16397 from US105523 (FM Event Log Updates)

    """

    global files_to_delete
    start_time = common.get_date_in_format()
    source_file = file_path
    con_ssh = ControllerClient.get_active_controller()

    LOG.tc_step("{} for {}".format(operation, source_file))
    if operation == 'create_symlink':
        dest_file = "my_symlink"
        create_symlink(source_file, dest_file)
        files_to_delete.append(dest_file)

        checksum_match = checksum_compare(source_file, dest_file)
        assert checksum_match, "SHA256 checksum should match source file and " \
                               "the symlink but didn't"

    elif operation == 'copy_and_execute':
        dest_file = "/usr/sbin/TEMP"
        copy_file(source_file, dest_file)
        files_to_delete.append(dest_file)

        LOG.info("Execute the copied file")
        con_ssh.exec_sudo_cmd("{} -p".format(dest_file))

    elif operation == 'change_file_attributes':
        if HostLinuxUser.get_home() != 'sysadmin':
            skip('sysadmin user is required to run this test')
        dest_file = "/usr/sbin/TEMP"
        copy_file(source_file, dest_file)
        files_to_delete.append(dest_file)

        LOG.info("Change permission of copy")
        chmod_file(dest_file, "777")
        LOG.info("Changing group ownership of file")
        chgrp_file(dest_file, "sys_protected")
        LOG.info("Changing file ownership")
        chown_file(dest_file, "sysadmin:sys_protected")

    elif operation == 'create_and_execute':
        dest_file = "{}/TEMP".format(HostLinuxUser.get_home())
        create_and_execute(file_path=dest_file, sudo=False)

    LOG.tc_step("Ensure no IMA events are raised")
    events_found = system_helper.wait_for_events(start=start_time,
                                                 timeout=60,
                                                 num=10,
                                                 event_log_id=EventLogID.IMA,
                                                 fail_ok=True,
                                                 strict=False)

    assert not events_found, "Unexpected IMA events found"
예제 #9
0
def test_ima_event_generation(operation, file_path):
    """
    Following IMA violation scenarios are covered:
        - append/edit data to/of a monitored file, result in changing of the
            hash
        - dynamic library changes
        - create and execute a files as sysadmin

    Test Steps:
    - Perform specified file operations
    - Check IMA violation event is logged

    """
    global files_to_delete

    con_ssh = ControllerClient.get_active_controller()
    start_time = common.get_date_in_format()

    source_file = file_path
    backup_file = None

    if operation in ('edit_and_execute', 'append_and_execute'):
        dest_file = "/usr/sbin/TEMP"
        copy_file(source_file, dest_file, cleanup='dest')

        if operation == 'edit_and_execute':
            LOG.tc_step("Open copy of monitored file and save")
            cmd = "vim {} '+:wq!'".format(dest_file)
            con_ssh.exec_sudo_cmd(cmd, fail_ok=False)
            execute_cmd = "{} -p".format(dest_file)
        else:
            LOG.tc_step("Append to copy of monitored file")
            cmd = 'echo "output" | sudo -S tee -a /usr/sbin/TEMP'.format(
                HostLinuxUser.get_password())
            con_ssh.exec_cmd(cmd, fail_ok=False)
            LOG.tc_step("Execute modified file")
            con_ssh.exec_sudo_cmd(dest_file)
            execute_cmd = "{}".format(dest_file)

        LOG.tc_step("Execute modified file")
        con_ssh.exec_sudo_cmd(execute_cmd)

    elif operation == 'replace_library':
        backup_file = "/root/{}".format(source_file.split('/')[-1])
        dest_file_nocsum = "/root/TEMP"

        LOG.info("Backup source file {} to {}".format(source_file,
                                                      backup_file))
        copy_file(source_file, backup_file)
        LOG.info("Copy the library without the checksum")
        copy_file(source_file, dest_file_nocsum, preserve=False)
        LOG.info("Replace the library with the unsigned one")
        move_file(dest_file_nocsum, source_file)

    elif operation == 'create_and_execute':
        dest_file = "{}/TEMP".format(HostLinuxUser.get_home())
        create_and_execute(file_path=dest_file, sudo=True)

    LOG.tc_step("Check for IMA event")
    ima_events = system_helper.wait_for_events(start=start_time,
                                               timeout=60,
                                               num=10,
                                               event_log_id=EventLogID.IMA,
                                               state='log',
                                               severity='major',
                                               fail_ok=True,
                                               strict=False)

    if backup_file:
        LOG.info("Restore backup file {} to {}".format(backup_file,
                                                       source_file))
        move_file(backup_file, source_file)

    assert ima_events, "IMA event is not generated after {} on " \
                       "{}".format(operation, file_path)
예제 #10
0
    def _prepare_test(vm1, vm2, get_hosts, with_router):
        """
        VMs:
            VM1: under test (primary tenant)
            VM2: traffic observer
        """

        vm1_host = vm_helper.get_vm_host(vm1)
        vm2_host = vm_helper.get_vm_host(vm2)
        vm1_router = network_helper.get_tenant_router(
            auth_info=Tenant.get_primary())
        vm2_router = network_helper.get_tenant_router(
            auth_info=Tenant.get_secondary())
        vm1_router_host = network_helper.get_router_host(router=vm1_router)
        vm2_router_host = network_helper.get_router_host(router=vm2_router)
        targets = list(get_hosts)

        if vm1_router_host == vm2_router_host:
            end_time = time.time() + 360
            while time.time() < end_time:
                vm1_router_host = network_helper.get_router_host(
                    router=vm1_router)
                vm2_router_host = network_helper.get_router_host(
                    router=vm2_router)
                if vm1_router_host != vm2_router_host:
                    break
            else:
                assert vm1_router_host != vm2_router_host, "two routers are located on the same compute host"

        if not with_router:
            """
            Setup:
                VM1 on COMPUTE-A
                VM2 not on COMPUTE-A
                ROUTER1 on COMPUTE-B
                ROUTER2 on COMPUTE-C
            """
            if len(get_hosts) < 3:
                skip(
                    "Lab not suitable for without_router, requires at least three hypervisors"
                )

            LOG.tc_step(
                "Ensure VM2, ROUTER2 not on COMPUTE-A, for simplicity, ensure they are on the same compute"
            )
            if vm2_host != vm2_router_host:
                vm_helper.live_migrate_vm(vm_id=vm2,
                                          destination_host=vm2_router_host)
                vm2_host = vm_helper.get_vm_host(vm2)
                assert vm2_host == vm2_router_host, "live-migration failed"
            host_observer = vm2_host

            LOG.tc_step(
                "Ensure VM1 and (ROUTER1, VM2, ROUTER2) are on different hosts"
            )
            if vm1_router_host in targets:
                # ensure vm1_router_host is not selected for vm1
                # vm1_router_host can be backed by any type of storage
                targets.remove(vm1_router_host)
            if vm2_host in targets:
                targets.remove(vm2_host)

            if vm1_host in targets:
                host_src_evacuation = vm1_host
            else:
                assert targets, "no suitable compute for vm1, after excluding ROUTER1, VM2, ROUTER2 's hosts"
                host_src_evacuation = targets[0]
                vm_helper.live_migrate_vm(vm_id=vm1,
                                          destination_host=host_src_evacuation)
                vm1_host = vm_helper.get_vm_host(vm1)
                assert vm1_host == host_src_evacuation, "live-migration failed"

            # verify setup
            vm1_host = vm_helper.get_vm_host(vm1)
            vm2_host = vm_helper.get_vm_host(vm2)
            vm1_router_host = network_helper.get_router_host(router=vm1_router)
            vm2_router_host = network_helper.get_router_host(router=vm2_router)
            assert vm1_router_host != vm1_host and vm2_host != vm1_host and vm2_router_host != vm1_host, \
                "setup is incorrect"
        else:
            """
            Setup:
                VM1, ROUTER1 on COMPUTE-A
                VM2 not on COMPUTE-A
                ROUTER2 on COMPUTE-B 
            """
            LOG.tc_step("Ensure VM1, ROUTER1 on COMPUTE-A")

            # VM1 must be sitting on ROUTER1's host, thus vm1_router_host must be backed by local_image
            assert vm1_router_host in targets, "vm1_router_host is not backed by local_image"

            if vm1_host != vm1_router_host:
                vm_helper.live_migrate_vm(vm_id=vm1,
                                          destination_host=vm1_router_host)
                vm1_host = vm_helper.get_vm_host(vm1)
                assert vm1_host == vm1_router_host, "live-migration failed"
            host_src_evacuation = vm1_host

            LOG.tc_step(
                "Ensure VM2, ROUTER2 not on COMPUTE-A, for simplicity, ensure they are on the same compute"
            )
            targets.remove(host_src_evacuation)
            if vm2_host in targets:
                host_observer = vm2_host
            else:
                assert targets, "no suitable compute for vm2, after excluding COMPUTE-A"
                host_observer = targets[0]
                vm_helper.live_migrate_vm(vm_id=vm2,
                                          destination_host=host_observer)
                vm2_host = vm_helper.get_vm_host(vm2)
                assert vm2_host == host_observer, "live-migration failed"

            # verify setup
            vm1_host = vm_helper.get_vm_host(vm1)
            vm2_host = vm_helper.get_vm_host(vm2)
            vm1_router_host = network_helper.get_router_host(router=vm1_router)
            vm2_router_host = network_helper.get_router_host(router=vm2_router)
            assert vm1_host == vm1_router_host and vm2_host != vm1_host and vm2_router_host != vm1_host, \
                "setup is incorrect"

        assert vm1_host == host_src_evacuation and vm2_host == host_observer, "setup is incorrect"
        LOG.info("Evacuate: VM {} on {}, ROUTER on {}".format(
            vm1, vm1_host, vm1_router_host))
        LOG.info("Observer: VM {} on {}, ROUTER on {}".format(
            vm2, vm2_host, vm2_router_host))

        return host_src_evacuation, host_observer
예제 #11
0
def test_ipv6_subnet(vif_model, check_avs_pattern):
    """
    Ipv6 Subnet feature test cases

    Test Steps:
        - Create networks
        - Create Ipv6 enabled subnet
        - Boot the first vm with the ipv6 subnet
        - Boot the second vm with ipv6 subnet
        - Configure interfaces to get ipv6 addr
        - Verify connectivity ipv6 interfaces
        - Ping default router

    Test Teardown:
        - Delete vms, subnets, and networks created

    """
    network_names = ['network11']
    net_ids = []
    sub_nets = ["fd00:0:0:21::/64"]
    gateway_ipv6 = "fd00:0:0:21::1"
    subnet_ids = []

    dns_server = "2001:4860:4860::8888"

    LOG.tc_step("Create Networks to setup IPV6 subnet")
    for net in network_names:
        net_ids.append(
            network_helper.create_network(name=net, cleanup='function')[1])

    LOG.tc_step("Create IPV6 Subnet on the Network Created")
    for sub, network in zip(sub_nets, net_ids):
        subnet_ids.append(
            network_helper.create_subnet(network=network,
                                         ip_version=6,
                                         dns_servers=dns_server,
                                         subnet_range=sub,
                                         gateway='none',
                                         cleanup='function')[1])

    LOG.tc_step("Boot a VM with mgmt net and Network with IPV6 subnet")
    mgmt_net_id = network_helper.get_mgmt_net_id()
    nics = [{
        'net-id': mgmt_net_id
    }, {
        'net-id': net_ids[0],
        'vif-model': vif_model
    }]

    image = None
    if vif_model == 'e1000':
        image = glance_helper.create_image(name=vif_model,
                                           hw_vif_model=vif_model,
                                           cleanup='function')[1]

    LOG.tc_step("Boot a vm with created nets")
    vm_id = vm_helper.boot_vm(name='vm-with-ipv6-nic',
                              nics=nics,
                              image_id=image,
                              cleanup='function')[1]
    LOG.tc_step("Setup interface script inside guest and restart network")
    _bring_up_interface(vm_id)

    LOG.tc_step("Boot a second vm with created nets")
    vm_id2 = vm_helper.boot_vm(name='vm2-with-ipv6-nic',
                               nics=nics,
                               cleanup='function')[1]
    LOG.tc_step("Setup interface script inside guest and restart network")
    _bring_up_interface(vm_id2)

    with vm_helper.ssh_to_vm_from_natbox(vm_id) as vm_ssh:
        ip_addr = _get_ipv6_for_eth(eth_name='eth1', ssh_client=vm_ssh)

        if ip_addr is '':
            LOG.info('Ip addr is not assigned')
            assert ip_addr != '', "Failed to assign ip"
        else:
            LOG.info("Got Ipv6 address:{}".format(ip_addr))

    with vm_helper.ssh_to_vm_from_natbox(vm_id2) as vm_ssh:
        LOG.tc_step("ping b/w vms on the ipv6 net")
        ping = _ping6_vms(ssh_client=vm_ssh, ipv6_addr=ip_addr)
        assert ping == 0, "Ping between VMs failed"
        LOG.tc_step("ping Default Gateway from vms on the ipv6 net")
        ping = _ping6_vms(ssh_client=vm_ssh, ipv6_addr=gateway_ipv6)
        assert ping == 0, "Ping to default router failed"
예제 #12
0
def test_horizon_storage_overview_display(storage_overview_pg):
    """
    Tests the storage overview display:

    Setups:
        - Login as Admin
        - Go to Admin > Platform > Storage Overview

    Teardown:
        - Logout

    Test Steps:
        - Test Storage cluster UUID, Health Status and Details display
        - Test host and rank table display
        - Test osd.# table and status display
    """
    con_ssh = ControllerClient.get_active_controller()
    standby = system_helper.get_standby_controller_name(con_ssh=con_ssh)
    if standby == 'controller-1':
        LOG.info('Workaround for CGTS-16739')
        host_helper.swact_host(con_ssh=con_ssh)

    LOG.tc_step('Check storage cluster UUID, ceph health and storage usage display')
    cli_storage_service_info = []

    uuid = system_helper.get_clusters(field='cluster_uuid')[0]
    cli_storage_service_info.append(uuid)

#   'ceph health' cmd output sample:
#   HEALTH_ERR 1728 pgs are stuck inactive for more than 300 seconds; 1728 pgs stuck inactive; 1728 pgs stuck unclean;\
#   1 mons down, quorum 0,1 controller-0,controller-1
    health_details = con_ssh.exec_cmd('ceph health')[1]
    health_status = health_details.split(' ')[0]
    cli_storage_service_info.append(health_status)

    if health_status == 'HEALTH_ERR':
        health_details = health_details.split('HEALTH_ERR ')[1]
    elif health_status == 'HEALTH_WARN':
        health_details = health_details.split('HEALTH_WARN ')[1]
    cli_storage_service_info.append(health_details)

    horizon_ceph_info = storage_overview_pg.storage_service_info.get_content()
    for info in cli_storage_service_info:
        assert info in horizon_ceph_info.values(), 'Horizon storage cluster info does not match to cli info'
    LOG.tc_step('Storage service details display correct')

    LOG.info('Test host and rank table display')
    ceph_mon_status = eval(con_ssh.exec_cmd('ceph mon_status')[1])
    mon_map = ceph_mon_status.get('monmap')
    cli_ceph_monitor = {}
    # mon_map.get('mons') returns a dict list
    for mon_info_dict in mon_map.get('mons'):
        host_name = mon_info_dict.get('name')
        host_rank = mon_info_dict.get('rank')
        cli_ceph_monitor[host_name] = str(host_rank)

    for host_name in cli_ceph_monitor.keys():
        cli_rank_val = cli_ceph_monitor[host_name]
        horizon_rank_val = storage_overview_pg.get_storage_overview_monitor_info(host_name, 'Rank')
        assert horizon_rank_val == cli_rank_val, '{} rank display incorrectly'.format(host_name)

    LOG.info('Host and rank table display correct')

    LOG.tc_step('Test osd table and status display')
    osd_list = storage_helper.get_osds()
    for osd_id in osd_list:
        if osd_id is not None:
            expt_horizon = {}
            for header in storage_overview_pg.osds_table.column_names:
                host_name = storage_helper.get_osd_host(osd_id)
                osd_name = 'osd.{}'.format(osd_id)
                expt_horizon['Host'] = host_name
                expt_horizon['Name'] = osd_name
                expt_horizon['Status'] = 'up'
                if not storage_helper.is_osd_up(osd_id, con_ssh):
                    expt_horizon['Status'] = 'down'
                horizon_val = storage_overview_pg.get_storage_overview_osd_info(osd_name, header)
                assert expt_horizon[header] == horizon_val, '{}{} display incorrect'.format(osd_name, header)
    LOG.info('Osd table display correct')
    horizon.test_result = True
예제 #13
0
def create_aggregate(field='name',
                     name=None,
                     avail_zone=None,
                     properties=None,
                     check_first=True,
                     fail_ok=False,
                     con_ssh=None,
                     auth_info=Tenant.get('admin')):
    """
    Add a aggregate with given name and availability zone.

    Args:
        field (str): name or id
        name (str): name for aggregate to create
        avail_zone (str|None):
        properties (dict|None)
        check_first (bool)
        fail_ok (bool):
        con_ssh (SSHClient):
        auth_info (dict):

    Returns (tuple):
        (0, <rtn_val>)          -- aggregate successfully created
        (1, <stderr>)           -- cli rejected
        (2, "Created aggregate is not as specified")    -- name and/or availability zone mismatch

    """
    if not name:
        existing_names = get_aggregates(field='name')
        name = common.get_unique_name(name_str='cgcsauto',
                                      existing_names=existing_names)

    args_dict = {
        '--zone': avail_zone,
        '--property': properties,
    }
    args = '{} {}'.format(common.parse_args(args_dict, repeat_arg=True), name)

    if check_first:
        aggregates_ = get_aggregates(field=field,
                                     name=name,
                                     avail_zone=avail_zone)
        if aggregates_:
            LOG.warning(
                "Aggregate {} already exists. Do nothing.".format(name))
            return -1, aggregates_[0]

    LOG.info("Adding aggregate {}".format(name))
    res, out = cli.openstack('aggregate create',
                             args,
                             ssh_client=con_ssh,
                             fail_ok=fail_ok,
                             auth_info=auth_info)
    if res == 1:
        return res, out

    out_tab = table_parser.table(out)

    succ_msg = "Aggregate {} is successfully created".format(name)
    LOG.info(succ_msg)
    return 0, table_parser.get_value_two_col_table(out_tab, field)
예제 #14
0
def delete_server_groups(srv_grp_ids=None,
                         check_first=True,
                         fail_ok=False,
                         auth_info=Tenant.get('admin'),
                         con_ssh=None):
    """
    Delete server group(s)

    Args:
        srv_grp_ids (list|str): id(s) for server group(s) to delete.
        check_first (bool): whether to check existence of given server groups before attempt to
            delete. Default: True.
        fail_ok (bool):
        auth_info (dict|None):
        con_ssh (SSHClient):

    Returns (tuple): (rtn_code(int), msg(str))  # rtn_code 1,2 only returns when fail_ok=True
        (-1, 'No server group(s) to delete.')
        (-1, 'None of the given server group(s) exists on system.')
        (0, "Server group(s) deleted successfully.")
        (1, <stderr>)   # Deletion rejected for all of the server groups. Return CLI stderr.
        (2, "Some deleted server group(s) still exist on system:: <srv_grp_ids>")
    """
    existing_sgs = None
    if not srv_grp_ids:
        existing_sgs = srv_grp_ids = get_server_groups(con_ssh=con_ssh,
                                                       auth_info=auth_info)
    elif isinstance(srv_grp_ids, str):
        srv_grp_ids = [srv_grp_ids]

    srv_grp_ids = [sg for sg in srv_grp_ids if sg]
    if not srv_grp_ids:
        LOG.info("No server group(s) to delete. Do Nothing")
        return -1, 'No server group(s) to delete.'

    if check_first:
        if existing_sgs is None:
            existing_sgs = get_server_groups(con_ssh=con_ssh,
                                             auth_info=auth_info)

        srv_grp_ids = list(set(srv_grp_ids) & set(existing_sgs))
        if not srv_grp_ids:
            msg = "None of the given server group(s) exists on system. Do nothing"
            LOG.info(msg)
            return -1, msg

    LOG.info("Deleting server group(s): {}".format(srv_grp_ids))
    code, output = cli.openstack('server group delete',
                                 ' '.join(srv_grp_ids),
                                 ssh_client=con_ssh,
                                 fail_ok=True,
                                 auth_info=auth_info,
                                 timeout=60)
    if code == 1:
        return 1, output

    existing_sgs = get_server_groups(con_ssh=con_ssh, auth_info=auth_info)
    grps_undeleted = list(set(srv_grp_ids) & set(existing_sgs))
    if grps_undeleted:
        msg = "Some server group(s) still exist on system after deletion: {}".format(
            grps_undeleted)
        LOG.warning(msg)
        if fail_ok:
            return 2, msg
        raise exceptions.NovaError(msg)

    msg = "Server group(s) deleted successfully."
    LOG.info(msg)
    return 0, "Server group(s) deleted successfully."
예제 #15
0
def test_multi_node_failure_avoidance(reserve_unreserve_all_hosts_module,
                                      mnfa_timeout, mnfa_threshold):
    """
    Test multi node failure avoidance
    Args:
        mnfa_timeout
        mnfa_threshold
        reserve_unreserve_all_hosts_module: test fixture to reserve unreserve all vlm nodes for lab under test

    Setups:
        - Reserve all nodes in vlm

    Test Steps:

        - Power off compute/storage nodes in vlm using multi-processing to simulate a power outage on computes
        - Power on all nodes compute nodes
        - Wait for nodes to become degraded state during the mnfa mode
        - Wait for nodes to become active state
        - Check new event is are created for multi node failure
        - Verify the time differences between multi node failure enter and exit in the event log equal to configured
          mnfa thereshold value.

    """

    hosts_to_check = system_helper.get_hosts(
        availability=(HostAvailState.AVAILABLE, HostAvailState.ONLINE))
    hosts_to_test = [
        host for host in hosts_to_check if 'controller' not in host
    ]

    if len(hosts_to_test) < mnfa_threshold:
        skip(
            "Compute and storage host count smaller than mnfa threshhold value"
        )
    elif len(hosts_to_test) > mnfa_threshold + 1:
        hosts_to_test = hosts_to_test[:mnfa_threshold + 1]

    LOG.info("Online or Available hosts before power-off: {}".format(
        hosts_to_check))
    start_time = common.get_date_in_format(date_format='%Y-%m-%d %T')

    LOG.tc_step('Modify mnfa_timeout parameter to {}'.format(mnfa_timeout))
    system_helper.modify_service_parameter(service='platform',
                                           section='maintenance',
                                           name='mnfa_timeout',
                                           apply=True,
                                           value=str(mnfa_timeout))
    system_helper.modify_service_parameter(service='platform',
                                           section='maintenance',
                                           name='mnfa_threshold',
                                           apply=True,
                                           value=str(mnfa_threshold))

    try:
        LOG.tc_step("Power off hosts and check for degraded state: {}".format(
            hosts_to_test))
        vlm_helper.power_off_hosts_simultaneously(hosts=hosts_to_test)
        time.sleep(20)
        degraded_hosts = system_helper.get_hosts(
            availability=HostAvailState.DEGRADED, hostname=hosts_to_check)
    finally:
        LOG.tc_step("Power on hosts and ensure they are recovered: {}".format(
            hosts_to_test))
        vlm_helper.power_on_hosts(hosts=hosts_to_test,
                                  reserve=False,
                                  hosts_to_check=hosts_to_check,
                                  check_interval=20)

    assert sorted(degraded_hosts) == sorted(
        hosts_to_test), 'Degraded hosts mismatch with powered-off hosts'

    LOG.tc_step(
        "Check MNFA duration is the same as MNFA timeout value via system event log"
    )
    active_con = system_helper.get_active_controller_name()
    entity_instance_id = 'host={}.event=mnfa_enter'.format(active_con)
    first_event = system_helper.wait_for_events(
        num=1,
        timeout=70,
        start=start_time,
        fail_ok=True,
        strict=False,
        event_log_id=EventLogID.MNFA_MODE,
        field='Time Stamp',
        entity_instance_id=entity_instance_id)
    entity_instance_id = 'host={}.event=mnfa_exit'.format(active_con)
    second_event = system_helper.wait_for_events(
        num=1,
        timeout=70,
        start=start_time,
        fail_ok=False,
        strict=False,
        event_log_id=EventLogID.MNFA_MODE,
        field='Time Stamp',
        entity_instance_id=entity_instance_id)
    pattern = '%Y-%m-%dT%H:%M:%S'
    event_duration = datetime.strptime(second_event[0][:-7],
                                       pattern) - datetime.strptime(
                                           first_event[0][:-7], pattern)
    event_duration = event_duration.total_seconds()
    assert abs(event_duration - mnfa_timeout) <= 1, 'MNFA event duration {} is different than MNFA timeout value {}'.\
        format(event_duration, mnfa_timeout)
예제 #16
0
def test_ima_keyring_protection():
    """
    This test validates that the IMA keyring is safe from user space attacks.

    Test Steps:
    - Attempt to add new keys to the keyring
    - Extract key ID and save
    - Attempt to change the key timeout
    - Attempt to change the group and ownership of the key
    - Attempt to delete the key

    This test maps to TC_17667/T_16387 from US105523 (IMA keyring is safe from
    user space attacks)

    """

    con_ssh = ControllerClient.get_active_controller()

    LOG.info("Extract ima key ID")
    exitcode, msg = con_ssh.exec_sudo_cmd("cat /proc/keys | grep _ima")
    raw_key_id = msg.split(" ", maxsplit=1)[0]
    key_id = "0x{}".format(raw_key_id)
    LOG.info("Extracted key is: {}".format(key_id))

    LOG.info("Attempting to add new keys to keyring")
    exitcode, msg = con_ssh.exec_sudo_cmd("keyctl add keyring TEST stuff "
                                          "{}".format(key_id))
    assert exitcode != 0, \
        "Key addition should have failed but instead succeeded"

    LOG.info("Attempt to change the timeout on a key")
    exitcode, msg = con_ssh.exec_sudo_cmd("keyctl timeout {} "
                                          "3600".format(key_id))
    assert exitcode != 0, \
        "Key timeout modification should be rejected but instead succeeded"

    LOG.info("Attempt to change the group of a key")
    exitcode, msg = con_ssh.exec_sudo_cmd("keyctl chgrp {} 0".format(key_id))
    assert exitcode != 0, \
        "Key group modification should be rejected but instead succeeded"

    LOG.info("Attempt to change the ownership of a key")
    exitcode, msg = con_ssh.exec_sudo_cmd(
        "keyctl chown {} 1875".format(key_id))
    assert exitcode != 0, \
        "Key ownership modification should be rejected but instead succeeded"

    LOG.info("Attempt to delete a key")
    exitcode, msg = con_ssh.exec_sudo_cmd("keyctl clear {}".format(key_id))
    assert exitcode != 0, \
        "Key ownership deletion should be rejected but instead succeeded"
예제 #17
0
    def login_as_ldap_user(self,
                           user_name,
                           password,
                           host=None,
                           pre_store=False,
                           disconnect_after=False):
        """
        Login as the specified user name and password onto the specified host

        Args:
            user_name (str):        user name
            password (str):         password
            host (str):             host to login to
            pre_store (bool):
                    True    -       pre-store keystone user credentials for
                    session
                    False   -       chose 'N' (by default) meaning do not
                    pre-store keystone user credentials
            disconnect_after (bool):
                    True    -       disconnect the logged in session
                    False   -       keep the logged in session

        Returns (tuple):
            logged_in (bool)    -   True if successfully logged into the
            specified host
                                    using the specified user/password
            password (str)      -   the password used to login
            ssh_con (object)    -   the ssh session logged in
        """
        if not host:
            host = 'controller-1'
            if system_helper.is_aio_simplex():
                host = 'controller-0'

        prompt_keystone_user_name = r'Enter Keystone username \[{}\]: '.format(
            user_name)
        cmd_expected = (
            (
                'ssh -l {} -o UserKnownHostsFile=/dev/null {}'.format(
                    user_name, host),
                (r'Are you sure you want to continue connecting \(yes/no\)\?',
                 ),
                ('ssh: Could not resolve hostname {}: Name or service not '
                 'known'.format(host), ),
            ),
            (
                'yes',
                (r'{}@{}\'s password: '******'{}'.format(password),
                (
                    prompt_keystone_user_name,
                    Prompt.CONTROLLER_PROMPT,
                ),
                (r'Permission denied, please try again\.', ),
            ),
        )

        logged_in = False
        self.ssh_con.flush()
        for i in range(len(cmd_expected)):
            cmd, expected, errors = cmd_expected[i]
            LOG.info('cmd={}\nexpected={}\nerrors={}\n'.format(
                cmd, expected, errors))
            self.ssh_con.send(cmd)

            index = self.ssh_con.expect(blob_list=list(expected + errors))
            if len(expected) <= index:
                break
            elif 3 == i:
                if expected[index] == prompt_keystone_user_name:
                    assert pre_store, \
                        'pre_store is False, while selecting "y" to ' \
                        '"Pre-store Keystone user credentials ' \
                        'for this session!"'
                else:
                    logged_in = True
                    break
        else:
            logged_in = True

        if logged_in:
            if disconnect_after:
                self.ssh_con.send('exit')

        return logged_in, password, self.ssh_con
예제 #18
0
def wait_for_apps_status(apps,
                         status,
                         timeout=360,
                         check_interval=5,
                         fail_ok=False,
                         con_ssh=None,
                         auth_info=Tenant.get('admin_platform')):
    """
    Wait for applications to reach expected status via system application-list
    Args:
        apps:
        status:
        timeout:
        check_interval:
        fail_ok:
        con_ssh:
        auth_info:

    Returns (tuple):

    """
    status = '' if not status else status
    if isinstance(apps, str):
        apps = [apps]
    apps_to_check = list(apps)
    check_failed = []
    end_time = time.time() + timeout

    LOG.info("Wait for {} application(s) to reach status: {}".format(
        apps, status))
    while time.time() < end_time:
        apps_status = get_apps(application=apps_to_check,
                               field=('application', 'status'),
                               con_ssh=con_ssh,
                               auth_info=auth_info)
        apps_status = {item[0]: item[1] for item in apps_status if item}

        checked = []
        for app in apps_to_check:
            current_app_status = apps_status.get(app, '')
            if current_app_status == status:
                checked.append(app)
            elif current_app_status.endswith('ed'):
                check_failed.append(app)
                checked.append(app)

        apps_to_check = list(set(apps_to_check) - set(checked))
        if not apps_to_check:
            if check_failed:
                msg = '{} failed to reach status - {}'.format(
                    check_failed, status)
                LOG.warning(msg)
                if fail_ok:
                    return False, check_failed
                else:
                    raise exceptions.ContainerError(msg)

            LOG.info("{} reached expected status {}".format(apps, status))
            return True, None

        time.sleep(check_interval)

    check_failed += apps_to_check
    msg = '{} did not reach status {} within {}s'.format(
        check_failed, status, timeout)
    LOG.warning(msg)
    if fail_ok:
        return False, check_failed
    raise exceptions.ContainerError(msg)
예제 #19
0
def modify_https(enable_https=True,
                 check_first=True,
                 con_ssh=None,
                 auth_info=Tenant.get('admin_platform'),
                 fail_ok=False):
    """
    Modify platform https via 'system modify https_enable=<bool>'

    Args:
        enable_https (bool): True/False to enable https or not
        check_first (bool): if user want to check if the lab is already in
        the state that user try to enable
        con_ssh (SSHClient):
        auth_info (dict):
        fail_ok (bool):

    Returns (tuple):
        (-1, msg)
        (0, msg)
        (1, <std_err>)

    """
    if check_first:
        is_https = keystone_helper.is_https_enabled(source_openrc=False,
                                                    auth_info=auth_info,
                                                    con_ssh=con_ssh)
        if (is_https and enable_https) or (not is_https and not enable_https):
            msg = "Https is already {}. Do nothing.".format(
                'enabled' if enable_https else 'disabled')
            LOG.info(msg)
            return -1, msg

    LOG.info("Modify system to {} https".format(
        'enable' if enable_https else 'disable'))
    res, output = system_helper.modify_system(fail_ok=fail_ok,
                                              con_ssh=con_ssh,
                                              auth_info=auth_info,
                                              https_enabled='{}'.format(
                                                  str(enable_https).lower()))
    if res == 1:
        return 1, output

    LOG.info("Wait up to 60s for config out-of-date alarm with best effort.")
    system_helper.wait_for_alarm(alarm_id=EventLogID.CONFIG_OUT_OF_DATE,
                                 entity_id='controller-',
                                 strict=False,
                                 con_ssh=con_ssh,
                                 timeout=60,
                                 fail_ok=True,
                                 auth_info=auth_info)

    LOG.info("Wait up to 600s for config out-of-date alarm to clear.")
    system_helper.wait_for_alarm_gone(EventLogID.CONFIG_OUT_OF_DATE,
                                      con_ssh=con_ssh,
                                      timeout=600,
                                      check_interval=20,
                                      fail_ok=False,
                                      auth_info=auth_info)

    LOG.info("Wait up to 300s for public endpoints to be updated")
    expt_status = 'enabled' if enable_https else 'disabled'
    end_time = time.time() + 300
    while time.time() < end_time:
        if keystone_helper.is_https_enabled(con_ssh=con_ssh,
                                            source_openrc=False,
                                            auth_info=auth_info) == \
                enable_https:
            break
        time.sleep(10)
    else:
        raise exceptions.KeystoneError(
            "Https is not {} in 'openstack endpoint list'".format(expt_status))

    msg = 'Https is {} successfully'.format(expt_status)
    LOG.info(msg)
    # TODO: install certificate for https. There will be a warning msg if
    #  self-signed certificate is used

    if not ProjVar.get_var('IS_DC') or \
            (auth_info and auth_info.get('region', None) in (
            'RegionOne', 'SystemController')):
        # If DC, use the central region https as system https, since that is
        # the one used for external access
        CliAuth.set_vars(HTTPS=enable_https)

    return 0, msg
예제 #20
0
def apply_app(app_name,
              check_first=False,
              fail_ok=False,
              applied_timeout=300,
              check_interval=10,
              wait_for_alarm_gone=True,
              con_ssh=None,
              auth_info=Tenant.get('admin_platform')):
    """
    Apply/Re-apply application via system application-apply. Check for status
    reaches 'applied'.
    Args:
        app_name (str):
        check_first:
        fail_ok:
        applied_timeout:
        check_interval:
        con_ssh:
        wait_for_alarm_gone (bool):
        auth_info:

    Returns (tuple):
        (-1, "<app_name> is already applied. Do nothing.")     # only returns
        if check_first=True.
        (0, "<app_name> (re)applied successfully")
        (1, <std_err>)  # cli rejected
        (2, "<app_name> failed to apply")   # did not reach applied status
        after apply.

    """
    if check_first:
        app_status = get_apps(application=app_name,
                              field='status',
                              con_ssh=con_ssh,
                              auth_info=auth_info)
        if app_status and app_status[0] == AppStatus.APPLIED:
            msg = '{} is already applied. Do nothing.'.format(app_name)
            LOG.info(msg)
            return -1, msg

    LOG.info("Apply application: {}".format(app_name))
    code, output = cli.system('application-apply',
                              app_name,
                              ssh_client=con_ssh,
                              fail_ok=fail_ok,
                              auth_info=auth_info)
    if code > 0:
        return 1, output

    res = wait_for_apps_status(apps=app_name,
                               status=AppStatus.APPLIED,
                               timeout=applied_timeout,
                               check_interval=check_interval,
                               con_ssh=con_ssh,
                               auth_info=auth_info,
                               fail_ok=fail_ok)[0]
    if not res:
        return 2, "{} failed to apply".format(app_name)

    if wait_for_alarm_gone:
        alarm_id = EventLogID.CONFIG_OUT_OF_DATE
        if system_helper.wait_for_alarm(alarm_id=alarm_id,
                                        entity_id='controller',
                                        timeout=15,
                                        fail_ok=True,
                                        auth_info=auth_info,
                                        con_ssh=con_ssh)[0]:
            system_helper.wait_for_alarm_gone(alarm_id=alarm_id,
                                              entity_id='controller',
                                              timeout=120,
                                              check_interval=10,
                                              con_ssh=con_ssh,
                                              auth_info=auth_info)

    msg = '{} (re)applied successfully'.format(app_name)
    LOG.info(msg)
    return 0, msg
예제 #21
0
def create_strategy(orchestration,
                    controller_apply_type=None,
                    storage_apply_type=None,
                    compute_apply_type=None,
                    max_parallel_computes=0,
                    instance_action=None,
                    alarm_restrictions=None,
                    wait_for_completion=True,
                    timeout=None,
                    conn_ssh=None,
                    fail_ok=False):
    """
    Creates a orchestration strategy
    Args:
        orchestration (str): indicates the orchestration strategy type. Choices are  patch or upgrade
        controller_apply_type (str): Valid only for patch orchestration. indicates how the strategy is applied on
            controllers: serial/parallel/ignore.  Default is serial
        storage_apply_type (str): indicates how the strategy is applied on storage hosts. Choices are: serial/parallel/
                                    ignore. Default is serial
        compute_apply_type (str): indicates how the strategy is applied on computes hosts. Choices are: serial/parallel/
                                    ignore.  'parallel' is valid only for patch orchestration. Default is serial.
        max_parallel_computes(int):  indicates the maximum compute hosts to apply strategy in parallel
        instance_action (str): valid only for patch orchestration. Indicates what action to perform on instances.
            Choices are migrate or stop-start. The default is to stop-start
        alarm_restrictions(str): indicates how to handle alarm restrictions based on the management affecting statuses.
            Choices are strict or relaxed. Default is strict.
        wait_for_completion:
        timeout:
        conn_ssh:
        fail_ok:

    Returns: tuple (rc, dict/msg)
        (0, dict) - success
        (1, output) - CLI reject
        (2, err_msg) - strategy build completion timeout
        (3, err_msg) - strategy build completed but with failed state

    """
    if orchestration is None:
        raise ValueError(
            "The orchestration type must be specified: choices are 'patch' or 'upgrade'"
        )

    args_dict = {
        '--storage-apply-type':
        storage_apply_type,
        '--compute-apply-type':
        compute_apply_type,
        '--max-parallel-compute-hosts':
        max_parallel_computes if max_parallel_computes >= 2 else None,
        '--alarm-restrictions':
        alarm_restrictions,
    }

    cmd = ''
    if orchestration is "patch":
        cmd += "patch-strategy create"
        args_dict['--controller-apply-type'] = controller_apply_type
        args_dict['--instance-action'] = instance_action
    elif orchestration is "upgrade":
        cmd += "upgrade-strategy create"
    else:
        raise exceptions.OrchestrationError(
            "Invalid orchestration type (choices are 'patch' or 'upgrade') specified"
        )

    args = ''
    for key, val in args_dict.items():
        if val is not None and val != '':
            args += ' {} {}'.format(key, val)

    LOG.info("Creating {} orchestration strategy with arguments: {} {}".format(
        orchestration, cmd, args))
    rc, output = cli.sw_manager(cmd,
                                args,
                                ssh_client=conn_ssh,
                                fail_ok=fail_ok)
    LOG.info("Verifying if the {} orchestration strategy is created".format(
        orchestration))
    if rc != 0:
        msg = "Create {} strategy failed: {}".format(orchestration, output)
        LOG.warn(msg)
        if fail_ok:
            return 1, msg
        else:
            raise exceptions.OrchestrationError(msg)

    if 'strategy-uuid' not in [tr.strip() for tr in output.split(':')]:
        msg = "The {} strategy not created: {}".format(orchestration, output)
        LOG.warn(msg)
        if fail_ok:
            return 1, msg
        else:
            raise exceptions.OrchestrationError(msg)

    if wait_for_completion:
        if timeout is None:
            timeout = OrchestrationPhaseTimeout.BUILD

        if not wait_strategy_phase_completion(orchestration,
                                              OrchestStrategyPhase.BUILD,
                                              timeout,
                                              conn_ssh=conn_ssh)[0]:
            msg = "The {} strategy created failed build: {}".format(
                orchestration, output)
            if fail_ok:
                LOG.warning(msg)
                return 2, msg
            else:
                raise exceptions.OrchestrationError(msg)

    # get values of the created strategy
    results = get_current_strategy_info(orchestration, conn_ssh=conn_ssh)

    if OrchestStrategyPhase.BUILD != results['current-phase']:

        msg = "Unexpected {} strategy phase= {} encountered. A 'build' phase was expected. "\
            .format(orchestration, results["current-phase"])
        if fail_ok:
            LOG.warning(msg)
            return 3, msg
        else:
            raise exceptions.OrchestrationError(msg)

    if "failed" in results["state"]:
        msg = "The {} strategy  'failed' in build phase; reason = {}".format(
            orchestration, results["build-reason"])
        if fail_ok:
            LOG.warning(msg)
            return 3, msg
        else:
            raise exceptions.OrchestrationError(msg)

    LOG.info("Create {} strategy completed successfully: {}".format(
        orchestration, results))
    return 0, results
예제 #22
0
def test_lock_unlock_host(host_type, collect_kpi):
    """
    Verify lock unlock host

    Test Steps:
        - Select a host per given type. If type is controller, select standby controller.
        - Lock selected host and ensure it is successfully locked
        - Unlock selected host and ensure it is successfully unlocked

    """
    init_time = None
    if collect_kpi:
        init_time = common.get_date_in_format(date_format=KPI_DATE_FORMAT)

    LOG.tc_step("Select a {} node from system if any".format(host_type))
    if host_type == 'controller':
        if system_helper.is_aio_simplex():
            host = 'controller-0'
        else:
            host = system_helper.get_standby_controller_name()
            assert host, "No standby controller available"

    else:
        if host_type == 'compute' and (system_helper.is_aio_duplex()
                                       or system_helper.is_aio_simplex()):
            skip("No compute host on AIO system")
        elif host_type == 'storage' and not system_helper.is_storage_system():
            skip("System does not have storage nodes")

        hosts = system_helper.get_hosts(personality=host_type,
                                        availability=HostAvailState.AVAILABLE,
                                        operational=HostOperState.ENABLED)

        assert hosts, "No good {} host on system".format(host_type)
        host = hosts[0]

    LOG.tc_step(
        "Lock {} host - {} and ensure it is successfully locked".format(
            host_type, host))
    HostsToRecover.add(host)
    host_helper.lock_host(host, swact=False)

    # wait for services to stabilize before unlocking
    time.sleep(20)

    # unlock standby controller node and verify controller node is successfully unlocked
    LOG.tc_step(
        "Unlock {} host - {} and ensure it is successfully unlocked".format(
            host_type, host))
    host_helper.unlock_host(host)

    LOG.tc_step("Check helm list after host unlocked")
    con_ssh = ControllerClient.get_active_controller()
    con_ssh.exec_cmd('helm list', fail_ok=False)

    if collect_kpi:
        lock_kpi_name = HostLock.NAME.format(host_type)
        unlock_kpi_name = HostUnlock.NAME.format(host_type)
        unlock_host_type = host_type
        if container_helper.is_stx_openstack_deployed():
            if system_helper.is_aio_system():
                unlock_host_type = 'compute'
        else:
            lock_kpi_name += '_platform'
            unlock_kpi_name += '_platform'
            if unlock_host_type == 'compute':
                unlock_host_type = 'compute_platform'

        LOG.info("Collect kpi for lock/unlock {}".format(host_type))
        code_lock, out_lock = kpi_log_parser.record_kpi(
            local_kpi_file=collect_kpi,
            kpi_name=lock_kpi_name,
            host=None,
            log_path=HostLock.LOG_PATH,
            end_pattern=HostLock.END.format(host),
            start_pattern=HostLock.START.format(host),
            start_path=HostLock.START_PATH,
            init_time=init_time)

        time.sleep(30)  # delay in sysinv log vs nova hypervisor list
        code_unlock, out_unlock = kpi_log_parser.record_kpi(
            local_kpi_file=collect_kpi,
            kpi_name=unlock_kpi_name,
            host=None,
            log_path=HostUnlock.LOG_PATH,
            end_pattern=HostUnlock.END[unlock_host_type].format(host),
            init_time=init_time,
            start_pattern=HostUnlock.START.format(host),
            start_path=HostUnlock.START_PATH)

        assert code_lock == 0, 'Failed to collect kpi for host-lock {}. ' \
                               'Error: \n'.format(host, out_lock)
        assert code_unlock == 0, 'Failed to collect kpi for host-unlock {}. ' \
                                 'Error: \n'.format(host, out_lock)
예제 #23
0
def wait_strategy_phase_completion(orchestration,
                                   current_phase,
                                   timeout=None,
                                   conn_ssh=None,
                                   fail_ok=False):
    """
    Waits until the orchestration strategy phase is completed
    Args:
        orchestration (str): - indicates the orchestration type. possible values: upgrade or patch
        current_phase (str): - indicates the current phase of the orchestration. Possible values: build, apply or abort
        timeout (int): - indicates the timeout value to wait for the current phase to complete
        conn_ssh:
        fail_ok:

    Returns (tuple):
        (True, <strategy info>(dict))
        (False, <strategy info>(dict))


    """

    if orchestration is None:
        raise ValueError(
            "The orchestration type (choices are 'patch' or 'upgrade') must be specified"
        )
    elif orchestration is not "patch" and orchestration is not "upgrade":
        raise ValueError(
            "Invalid orchestration type (choices are 'patch' or 'upgrade') specified"
        )

    if not validate_current_strategy_phase(orchestration, current_phase):
        raise exceptions.OrchestrationError(
            "Current {} strategy phase does not match the specified phase={}".
            format(orchestration, current_phase))
    check_interval = PHASE_COMPLETION_CHECK_INTERVAL
    if timeout is not None and timeout < PHASE_COMPLETION_CHECK_INTERVAL:
        timeout = PHASE_COMPLETION_CHECK_INTERVAL
    else:
        if timeout is None:
            if current_phase == OrchestStrategyPhase.BUILD:
                timeout = OrchestrationPhaseTimeout.BUILD
            elif current_phase == OrchestStrategyPhase.APPLY:
                timeout = OrchestrationPhaseTimeout.APPLY
                check_interval = 40
            else:
                timeout = OrchestrationPhaseTimeout.ABORT

    end_time = time.time() + timeout

    output = None
    prev_phase_completion = "0%"

    if conn_ssh is None:
        conn_ssh = ControllerClient.get_active_controller()

    while time.time() < end_time:
        if not conn_ssh.is_connected():
            # ssh connection is lost. Controllers may swact in path application.
            time.sleep(30)
            conn_ssh.connect(retry=True, retry_timeout=HostTimeout.SWACT - 30)
            time.sleep(60)
            end_time = end_time + HostTimeout.SWACT

        output = get_current_strategy_info(orchestration, conn_ssh=conn_ssh)
        if output:
            if current_phase == OrchestStrategyPhase.ABORT:
                if output[OrchStrategyKey.
                          STATE] == OrchStrategyState.ABORT_TIMEOUT:
                    msg = '{} strategy abort timed out. Stop waiting for completion.'.format(
                        orchestration)
                    if fail_ok:
                        LOG.warning(msg)
                        return False, output
                    else:
                        raise exceptions.OrchestrationError(msg)

            elif output[OrchStrategyKey.
                        CURRENT_PHASE] == OrchestStrategyPhase.ABORT:
                msg = "{} strategy {} phase is aborted. Stop waiting for completion."\
                    .format(orchestration, current_phase)
                if fail_ok:
                    LOG.warn(msg)
                    return False, output
                else:
                    raise exceptions.OrchestrationError(msg)

            phase_completion = output['current-phase-completion']
            if phase_completion != prev_phase_completion:
                LOG.info(
                    "Orchestration current phase completion is at {}".format(
                        phase_completion))
                prev_phase_completion = phase_completion

            if phase_completion == '100%':
                return True, output
            else:
                time.sleep(check_interval)
    else:
        msg = "{} strategy {} phase did not complete within automation timeout {}seconds. Current status: {}"\
            .format(orchestration, current_phase, timeout, output)
        if fail_ok:
            LOG.warn(msg)
            return False, output
        else:
            raise exceptions.OrchestrationError(msg)
예제 #24
0
    def test_sriov_robustness(self, sriov_prep, add_admin_role_func):
        """
        Exhaust all CPUs on one compute by spawning VMs with 2 SR-IOV interface

        Args:
            sriov_prep: test fixture to set up test environment and get proper pci nets/hosts

        Setups:
            - select two hosts configured with same pci-sriov providernet
            - add the two hosts to cgcsauto aggregate to limit the vms host to the selected hosts
            - Select one network under above providernet

        Test Steps:
            - Boot 2+ pci-sriov vms with pci-sriov vif over selected network onto same host
            - Verify resource usage for providernet is increased as expected
            - Lock vms host and ensure vms are all migrated to other host
            - Verify vms' pci-sriov interfaces reachable and resource usage for pnet unchanged
            - 'sudo reboot -f' new vms host, and ensure vms are evacuated to initial host
            - Verify vms' pci-sriov interfaces reachable and resource usage for pnet unchanged

        Teardown:
            - Delete vms, volumes, flavor created
            - Remove admin role to tenant
            - Recover hosts if applicable
            - Remove cgcsauto aggregate     - class

        """
        net_type, pci_net, pci_hosts, pnet_id, nics, initial_host, other_host, vfs_use_init, vm_num, vm_vcpus = \
            sriov_prep
        vif_model = 'pci-sriov'

        # proc0_vm, proc1_vm = host_helper.get_logcores_counts(initial_host, functions='VMs')
        # if system_helper.is_hyperthreading_enabled(initial_host):
        #     proc0_vm *= 2
        #     proc1_vm *= 2
        # vm_vcpus = int(min(proc1_vm, proc0_vm) / (vm_num/2))

        # Create flavor with calculated vcpu number
        LOG.tc_step(
            "Create a flavor with dedicated cpu policy and {} vcpus".format(
                vm_vcpus))
        flavor_id = nova_helper.create_flavor(
            name='dedicated_{}vcpu'.format(vm_vcpus), ram=1024,
            vcpus=vm_vcpus)[1]
        ResourceCleanup.add('flavor', flavor_id, scope='module')
        extra_specs = {
            FlavorSpec.CPU_POLICY: 'dedicated',
        }
        # FlavorSpec.PCI_NUMA_AFFINITY: 'preferred'}    # LP1854516
        nova_helper.set_flavor(flavor=flavor_id, **extra_specs)

        # Boot vms with 2 {} vifs each, and wait for pingable
        LOG.tc_step("Boot {} vms with 2 {} vifs each".format(
            vm_num, vif_model))
        vms = []
        for i in range(vm_num):
            sriov_nics = nics.copy()
            sriov_nic2 = sriov_nics[-1].copy()
            sriov_nic2['port-id'] = network_helper.create_port(
                net_id=sriov_nic2.pop('net-id'),
                vnic_type='direct',
                name='sriov_port')[1]
            sriov_nics.append(sriov_nic2)
            LOG.info("Booting vm{}...".format(i + 1))
            vm_id = vm_helper.boot_vm(flavor=flavor_id,
                                      nics=sriov_nics,
                                      cleanup='function',
                                      vm_host=initial_host,
                                      avail_zone='cgcsauto')[1]
            vms.append(vm_id)
            vm_helper.wait_for_vm_pingable_from_natbox(vm_id)

        check_vm_pci_interface(vms=vms, net_type=net_type)
        # TODO: feature unavailable atm. Update required
        # vfs_use_post_boot = nova_helper.get_provider_net_info(pnet_id, field='pci_vfs_used')
        # assert vfs_use_post_boot - vfs_use_init == vm_num * 2, "Number of PCI vfs used is not as expected"

        HostsToRecover.add(pci_hosts)

        LOG.tc_step("Lock host of {} vms: {}".format(vif_model, initial_host))
        host_helper.lock_host(host=initial_host, check_first=False, swact=True)

        LOG.tc_step(
            "Check vms are migrated to other host: {}".format(other_host))
        for vm in vms:
            vm_host = vm_helper.get_vm_host(vm_id=vm)
            assert other_host == vm_host, "VM did not move to {} after locking {}".format(
                other_host, initial_host)

        check_vm_pci_interface(vms,
                               net_type=net_type,
                               ping_timeout=VMTimeout.DHCP_RETRY)
        # TODO: feature unavailable atm. Update required
        # vfs_use_post_lock = nova_helper.get_provider_net_info(pnet_id, field='pci_vfs_used')
        # assert vfs_use_post_boot == vfs_use_post_lock, "Number of PCI vfs used after locking host is not as expected"

        LOG.tc_step("Unlock {}".format(initial_host))
        host_helper.unlock_host(initial_host)

        LOG.tc_step("Reboot {} and ensure vms are evacuated to {}".format(
            other_host, initial_host))
        vm_helper.evacuate_vms(other_host,
                               vms,
                               post_host=initial_host,
                               wait_for_host_up=True)
        check_vm_pci_interface(vms, net_type=net_type)
예제 #25
0
def delete_test_pod():
    LOG.info("Delete {} pod if exists".format(POD_NAME))
    kube_helper.delete_resources(resource_names=POD_NAME, fail_ok=True)
예제 #26
0
    def test_pcipt_robustness(self, pcipt_prep):
        """
        TC3_robustness: PCI-passthrough by locking and rebooting pci_vm host

        Args:
            pcipt_prep: test fixture to set up test environment and get proper pci nets/hosts/seg_id

        Setups:
            - select a providernet with pcipt interfaces configured
            - get pci hosts configured with same above providernet
            - get one network under above providernet (or two for CX4 nic)

        Test Steps:
            - Boot 2 pcipt vms with pci-passthrough vif over selected network
            - Verify resource usage for providernet is increased as expected
            - Lock pci_vm host and ensure vm migrated to other host (or fail to lock if no other pcipt host available)
            - (Delete above tested pcipt vm if only two pcipt hosts available)
            - Lock host for another pcipt vm, and lock is successful
            - Verify vms' pci-pt interfaces reachable and resource usage for pnet as expected
            - 'sudo reboot -f' pci_vm host, and ensure vm evacuated or up on same host if no other pcipt host available
            - Repeat above step for another pcipt vm
            - Verify vms' pci-pt interfaces reachable and resource usage for pnet unchanged

        Teardown:
            - Delete vms, volumes, flavor created
            - Recover hosts if applicable

        """
        net_type, pci_net_name, pci_hosts, pnet_id, nics, min_vcpu_host, seg_id, vm_num, vm_vcpus, pfs_use_init = \
            pcipt_prep
        vif_model = 'pci-passthrough'

        # Create flavor with calculated vcpu number
        LOG.fixture_step(
            "Create a flavor with dedicated cpu policy and {} vcpus".format(
                vm_vcpus))
        flavor_id = nova_helper.create_flavor(
            name='dedicated_{}vcpu'.format(vm_vcpus), ram=1024,
            vcpus=vm_vcpus)[1]
        ResourceCleanup.add('flavor', flavor_id, scope='module')
        extra_specs = {
            FlavorSpec.CPU_POLICY: 'dedicated',
        }
        # FlavorSpec.PCI_NUMA_AFFINITY: 'preferred'}    # LP1854516
        nova_helper.set_flavor(flavor=flavor_id, **extra_specs)

        # Boot vms with 2 {} vifs each, and wait for pingable
        LOG.tc_step("Boot {} vms with 2 {} vifs each".format(
            vm_num, vif_model))
        vms = []
        for i in range(vm_num):
            LOG.info("Booting pci-passthrough vm{}".format(i + 1))
            vm_id = vm_helper.boot_vm(flavor=flavor_id,
                                      nics=nics,
                                      cleanup='function')[1]
            vms.append(vm_id)
            vm_helper.wait_for_vm_pingable_from_natbox(vm_id)
            vm_helper.add_vlan_for_vm_pcipt_interfaces(vm_id,
                                                       seg_id,
                                                       init_conf=True)

        # TODO: feature unavailable atm. Update required
        # pfs_use_post_boot = nova_helper.get_provider_net_info(pnet_id, field='pci_pfs_used')
        # resource_change = 2 if isinstance(seg_id, dict) else 1
        # assert pfs_use_post_boot - pfs_use_init == vm_num * resource_change, "Number of PCI pfs used is not as expected"

        check_vm_pci_interface(vms=vms, net_type=net_type)
        HostsToRecover.add(pci_hosts)

        # pfs_use_pre_action = pfs_use_post_boot
        iter_count = 2 if len(pci_hosts) < 3 else 1
        for i in range(iter_count):
            if i == 1:
                LOG.tc_step(
                    "Delete a pcipt vm and test lock and reboot pcipt host again for success pass"
                )
                vm_helper.delete_vms(vms=vms[1])
                vms.pop()
                # TODO: feature unavailable atm. Update required
                # pfs_use_pre_action -= resource_change
                # common.wait_for_val_from_func(expt_val=pfs_use_pre_action, timeout=30, check_interval=3,
                #                               func=nova_helper.get_provider_net_info,
                #                               providernet_id=pnet_id, field='pci_pfs_used')

            LOG.tc_step("Test lock {} vms hosts started - iter{}".format(
                vif_model, i + 1))
            for vm in vms:
                pre_lock_host = vm_helper.get_vm_host(vm)
                assert pre_lock_host in pci_hosts, "VM is not booted on pci_host"

                LOG.tc_step("Lock host of {} vms: {}".format(
                    vif_model, pre_lock_host))
                code, output = host_helper.lock_host(host=pre_lock_host,
                                                     check_first=False,
                                                     swact=True,
                                                     fail_ok=True)
                post_lock_host = vm_helper.get_vm_host(vm)
                assert post_lock_host in pci_hosts, "VM is not on pci host after migrating"

                if len(pci_hosts) < 3 and i == 0:
                    assert 5 == code, "Expect host-lock fail due to migration of vm failure. Actual: {}".format(
                        output)
                    assert pre_lock_host == post_lock_host, "VM host should not change when no other host to migrate to"
                else:
                    assert 0 == code, "Expect host-lock successful. Actual: {}".format(
                        output)
                    assert pre_lock_host != post_lock_host, "VM host did not change"
                    LOG.tc_step("Unlock {}".format(pre_lock_host))

                check_vm_pci_interface(vms, net_type=net_type)
                host_helper.unlock_host(pre_lock_host, available_only=True)
            # TODO: feature unavailable atm. Update required
            # pfs_use_post_lock = nova_helper.get_provider_net_info(pnet_id, field='pci_pfs_used')
            # assert pfs_use_pre_action == pfs_use_post_lock, "Number of PCI pfs used after host-lock is not as expected"

            LOG.tc_step("Test evacuate {} vms started - iter{}".format(
                vif_model, i + 1))
            for vm in vms:
                pre_evac_host = vm_helper.get_vm_host(vm)

                LOG.tc_step(
                    "Reboot {} and ensure {} vm are evacuated when applicable".
                    format(pre_evac_host, vif_model))
                code, output = vm_helper.evacuate_vms(pre_evac_host,
                                                      vm,
                                                      fail_ok=True,
                                                      wait_for_host_up=True)

                if len(pci_hosts) < 3 and i == 0:
                    assert 1 == code, "Expect vm stay on same host due to migration fail. Actual:{}".format(
                        output)
                    vm_helper.wait_for_vm_status(vm_id=vm)
                else:
                    assert 0 == code, "Expect vm evacuated to other host. Actual: {}".format(
                        output)
                    post_evac_host = vm_helper.get_vm_host(vm)
                    assert post_evac_host in pci_hosts, "VM is not on pci host after evacuation"

                check_vm_pci_interface(vms, net_type=net_type)
예제 #27
0
def test_boot_vm(name, flavor, source, source_name):
    vm_id = vm_helper.boot_vm(name=name,
                              flavor=flavor,
                              source=source,
                              source_id=source_name)[1]
    LOG.info("VM ID: {}".format(vm_id))
def test_system_upgrade_simplex(upgrade_setup,
                                check_system_health_query_upgrade):
    """
     This script starts the upgrade with creating a backup file which is wipes the disk at the end of the execution .
      to complete the upgrade test_upgrade_simplex_restore.py need to be executed with the backup file path.
    Args:
        upgrade_setup:   This will check parameters ftp upload load and patches
        check_system_health_query_upgrade: Check the health of system for upgrade
    Example
        To Execute

         check_system_health_query_upgrade: Checks the upgrade health .
        steps:

         1. FTP load and patches and loads to system.
         2. Checks the health of the upgrade
         3. Start upgrade
         4. Checks the backup files.
         5. Backup the volume and images
         6. Execute host-upgrade
         7. Ftp backup files

    teardown:
         flush ssh.

    """
    lab = upgrade_setup['lab']

    current_version = upgrade_setup['current_version']
    upgrade_version = upgrade_setup['upgrade_version']

    if not system_helper.is_aio_simplex():
        assert False, "This lab is not simplex to start upgrade"
    force = False
    controller0 = lab['controller-0']

    backup_dest_path = BackupVars.get_backup_var('BACKUP_DEST_PATH')
    backup_dest_full_path = '{}/{}/'.format(backup_dest_path,
                                            lab['short_name'])
    date = time.strftime(BACKUP_FILE_DATE_STR)
    build_id = system_helper.get_build_info()['BUILD_ID']
    lab_system_name = lab['name']
    backup_file_name = "{}{}_{}_{}".format(PREFIX_BACKUP_FILE, date, build_id,
                                           lab_system_name)
    print('Backup_File_Name', backup_file_name)
    # ssh to test server
    test_server_attr = dict()
    test_server_attr['name'] = TestFileServer.get_hostname().split('.')[0]
    test_server_attr['server_ip'] = TestFileServer.get_server()
    test_server_attr['prompt'] = r'\[{}@{} {}\]\$ ' \
        .format(TestFileServer.get_user(), test_server_attr['name'], TestFileServer.get_user())

    test_server_conn = install_helper.establish_ssh_connection(
        test_server_attr['name'],
        user=TestFileServer.get_user(),
        password=TestFileServer.get_password(),
        initial_prompt=test_server_attr['prompt'])

    test_server_conn.set_prompt(test_server_attr['prompt'])
    test_server_conn.deploy_ssh_key(install_helper.get_ssh_public_key())
    test_server_attr['ssh_conn'] = test_server_conn
    test_server_obj = Server(**test_server_attr)
    dest_server = test_server_obj
    # test if backup path for the lab exist in Test server
    if test_server_conn.exec_cmd(
            "test -e {}".format(backup_dest_full_path))[0]:
        test_server_conn.exec_cmd("mkdir -p {}".format(backup_dest_full_path))
    LOG.tc_step("Checking system health for upgrade .....")
    if check_system_health_query_upgrade[0] == 0:
        LOG.info("System health OK for upgrade......")
    if check_system_health_query_upgrade[0] == 1:
        assert False, "System health query upgrade failed: {}".format(
            check_system_health_query_upgrade[1])

    if check_system_health_query_upgrade[
            0] == 3 or check_system_health_query_upgrade[0] == 2:
        LOG.info(
            "System health indicate minor alarms; using --force option to start upgrade......"
        )
        force = True

    vol_ids = cinder_helper.get_volumes(auth_info=Tenant.get('admin'))
    if len(vol_ids) > 0:
        LOG.info("Exporting cinder volumes: {}".format(vol_ids))
        exported = install_helper.export_cinder_volumes(
            backup_dest='local',
            backup_dest_path=backup_dest_full_path,
            dest_server=dest_server)

        assert len(exported) > 0, "Fail to export all volumes"
        assert len(exported) == len(
            vol_ids), "Some volumes failed export: {}".format(
                set(vol_ids) - set(exported))
    else:
        LOG.info(
            "No cinder volumes are avaialbe in the system; skipping cinder volume export..."
        )

    LOG.tc_step("Starting upgrade from release {} to target release {}".format(
        current_version, upgrade_version))
    upgrade_helper.system_upgrade_start(force=force)
    upgrade_helper.wait_for_upgrade_states('started',
                                           timeout=1360,
                                           check_interval=30,
                                           fail_ok=True)

    LOG.info("upgrade started successfully......")

    # scp backup files to test server
    LOG.tc_step("SCP system and image tgz file into test server {} ",
                backup_dest_full_path)

    source_file = '/opt/backups/upgrade_data_*system.tgz '
    backup_dest_full_path_image = backup_dest_full_path
    backup_dest_full_path = backup_dest_full_path + "/" + backup_file_name + "_system.tgz"
    common.scp_from_active_controller_to_test_server(source_file,
                                                     backup_dest_full_path,
                                                     is_dir=False)
    backup_dest_full_path_image = backup_dest_full_path_image + "/" + backup_file_name + "_images.tgz"
    source_file = '/opt/backups/upgrade_data_*images.tgz '
    common.scp_from_active_controller_to_test_server(
        source_file, backup_dest_full_path_image, is_dir=False)
    LOG.info("Starting {} upgrade.....".format(controller0.name))
    # Below line will wipe disk
    # upgrade_helper.upgrade_host(controller0.name, lock=True)

    LOG.tc_step(
        "Host Upgrade executed .This will wipe the disk reboot controller-0 .")
    time.sleep(3)
    # open vlm console for controller-0 for boot through mgmt interface
    LOG.info(
        "Upgrade simpelx backup is complete . Resotore script should be run on this backup to compelte  upgrade "
    )
예제 #29
0
def barr_func(func_num, rep, barrier):
    barrier.wait(10)
    for i in range(0, rep):
        LOG.info("function #{}".format(func_num))
        sleep(1)
예제 #30
0
def __remove_or_add_hosts_in_aggregate(aggregate,
                                       hosts=None,
                                       remove=False,
                                       check_first=True,
                                       fail_ok=False,
                                       con_ssh=None,
                                       auth_info=Tenant.get('admin')):
    """
    Remove/Add hosts from/to given aggregate

    Args:
        aggregate (str): name of the aggregate to add/remove hosts. cgcsauto aggregate can be added
            via add_cgcsauto_zone session fixture
        hosts (list|str):
        remove (bool): True if remove hosts from given aggregate, otherwise add hosts to aggregate
        check_first (bool):
        fail_ok (bool):
        con_ssh (SSHClient):
        auth_info (dict):

    Returns (tuple):
        (0, "Hosts successfully removed from aggregate")
        (1, <stderr>)       cli rejected on at least one host
        (2, "Host(s) still exist in aggregate <aggr> after aggregate-remove-host: <unremoved_hosts>)

    """
    hosts_in_aggregate = get_hosts_in_aggregate(aggregate, con_ssh=con_ssh)

    if hosts is None:
        if remove:
            hosts = hosts_in_aggregate
        else:
            from keywords import host_helper
            hosts = host_helper.get_hypervisors()

    if isinstance(hosts, str):
        hosts = [hosts]

    msg_str = 'Remov' if remove else 'Add'
    LOG.info("{}ing hosts {} in aggregate {}".format(msg_str, hosts,
                                                     aggregate))
    if check_first:
        if remove:
            hosts_to_rm_or_add = list(set(hosts) & set(hosts_in_aggregate))
        else:
            hosts_to_rm_or_add = list(set(hosts) - set(hosts_in_aggregate))
    else:
        hosts_to_rm_or_add = list(hosts)

    if not hosts_to_rm_or_add:
        warn_str = 'No' if remove else 'All'
        msg = "{} given host(s) in aggregate {}. Do nothing. Given hosts: {}; hosts in " \
              "aggregate: {}".format(warn_str, aggregate, hosts, hosts_in_aggregate)
        LOG.warning(msg)
        return -1, msg

    failed_res = {}
    cmd = 'aggregate remove host' if remove else 'aggregate add host'
    for host in hosts_to_rm_or_add:
        args = '{} {}'.format(aggregate, host)
        code, output = cli.openstack(cmd,
                                     args,
                                     ssh_client=con_ssh,
                                     fail_ok=True,
                                     auth_info=auth_info)
        if code > 0:
            failed_res[host] = output

    if failed_res:
        err_msg = "'{}' is rejected for following host(s) in aggregate {}: {}".format(
            cmd, aggregate, failed_res)
        if fail_ok:
            LOG.warning(err_msg)
            return 1, err_msg
        else:
            raise exceptions.NovaError(err_msg)

    post_hosts_in_aggregate = get_hosts_in_aggregate(aggregate,
                                                     con_ssh=con_ssh)
    if remove:
        failed_hosts = list(set(hosts) & set(post_hosts_in_aggregate))
    else:
        failed_hosts = list(set(hosts) - set(post_hosts_in_aggregate))

    if failed_hosts:
        err_msg = "{} accepted, but some host(s) are not {}ed in aggregate {}: {}".format(
            cmd, msg_str, aggregate, failed_hosts)
        if fail_ok:
            LOG.warning(err_msg)
            return 2, err_msg
        else:
            raise exceptions.NovaError(err_msg)

    succ_msg = "Hosts successfully {}ed in aggregate {}: {}".format(
        msg_str.lower(), aggregate, hosts)
    LOG.info(succ_msg)
    return 0, succ_msg