def get_hw_compatible_hosts(hosts): """ Given a list of hosts return a dict of hardware compatible ones, if any. Arguments: - Hosts (list) Returns: - Dict mapping hash to hosts """ hardware = {} hardware_hash = {} for host in hosts: rc, out = cli.system("host-disk-list {} --nowrap".format(host)) table_ = table_parser.table(out) device_nodes = table_parser.get_column(table_, "device_node") device_type = table_parser.get_column(table_, "device_type") size_gib = table_parser.get_column(table_, "size_gib") hardware[host] = list(zip(device_nodes, device_type, size_gib)) LOG.info("Hardware present on host {}: {}".format( host, hardware[host])) hardware_hash[host] = hash(str(hardware[host])) LOG.info("Host {} has hash {}".format(host, hardware_hash[host])) # Create reverse lookup of hash to hosts hash_to_hosts = {} for key, value in hardware_hash.items(): hash_to_hosts.setdefault(value, []).append(key) LOG.info( "These are the hardware compatible hosts: {}".format(hash_to_hosts)) return hash_to_hosts
def check_device_list_against_pci_list(lspci_list_info, sysinv_device_list_tab): """ Checks the host pci info against the output of cli system host-device-list Args: lspci_list_info: host's pci co-processor list from lspci command sysinv_device_list_tab: pci list from cli system host-device-list Returns: """ LOG.info("Checking all devices are included in the list") sysinv_device_list_tab = table_parser.filter_table(sysinv_device_list_tab, **{'class id': DevClassID.QAT_VF}) assert len(lspci_list_info) == len(sysinv_device_list_tab['values']), \ "host devices list:{} and pci list:{} mismatch".format(sysinv_device_list_tab['values'], lspci_list_info) # check if pci attribute values are the identical for pci in lspci_list_info: sysinv_tab = table_parser.filter_table(sysinv_device_list_tab, **{'name': pci['pci_name']}) assert pci['vendor_name'] == table_parser.get_column(sysinv_tab, 'vendor name')[0] assert pci['vendor_id'] == table_parser.get_column(sysinv_tab, 'vendor id')[0] assert pci['device_id'] == table_parser.get_column(sysinv_tab, 'device id')[0] assert pci['class_id'] == table_parser.get_column(sysinv_tab, 'class id')[0] assert pci['pci_address'] == table_parser.get_column(sysinv_tab, 'address')[0] LOG.info("All host devices are listed")
def test_lldp_neighbor_remote_port(): """ Tests if LLDP Neighbor remote_port exists on all hosts Test Steps: - Checks LLDP Neighbor remote_port to ensure it exists """ remote_port_missing = False LOG.tc_step("Parsing host-list for hostnames") hosts_tab = table_parser.table(cli.system('host-list')[1]) all_hosts = table_parser.get_column(hosts_tab, 'hostname') for host_name in all_hosts: LOG.tc_step( "Parsing host-lldp-neighbor-list for remote_ports on the " + host_name + " host") host = table_parser.table( cli.system('host-lldp-neighbor-list', '--nowrap {}'.format(host_name))[1]) host_remote_ports = table_parser.get_column(host, 'remote_port') for remote_port in host_remote_ports: LOG.tc_step("Checking LLDP remote_port to ensure it exists") if remote_port.lower() == 'none' or remote_port == '': LOG.tc_step("Port missing") remote_port_missing = True assert remote_port_missing is False, "Some remote ports are missing from 'system host-lldp-neighbor-list'"
def check_timestamps_order(table_): timestamps = table_parser.get_column(table_, 'Time Stamp') for i in range(len(timestamps) - 1): current_stamp = timestamps[i] prev_stamp = timestamps[i + 1] assert current_stamp >= prev_stamp, "Time Stamp {} is smaller than previous stamp in table: \n{}".\ format(current_stamp, table_)
def test_system_ntp_modify(): """ Test that ntp servers were initially configured and can be reconfigured Test Steps: - Execute system ntp-show - Verify that ntpservers field contains a list of 3 ntp servers - Update ntp with new ntp servers - Lock/unlock controllers to get rid of config out of date alarm - After lock and unlock verify that alarms cleared """ LOG.tc_step("Check 'system ntp-show' contains expected fields") table_ = table_parser.table(cli.system('ntp-show')[1]) expt_sub_fields = ['uuid', 'ntpservers', 'isystem_uuid', 'created_at', 'updated_at'] actual_fields = table_parser.get_column(table_, 'Property') LOG.tc_step("Actual ntp fields Names are {}".format(actual_fields)) assert set(expt_sub_fields) <= set(actual_fields), "Some expected fields are not included in system show table." LOG.tc_step("Modify 'system ntp-modify' and verify that it contains expected fields") ntp_pool = NtpPool.NTP_POOL_1 if sorted(system_helper.get_ntp_values(fields='ntpservers')[0].split(',')) == sorted(ntp_pool.split(',')): ntp_pool = NtpPool.NTP_POOL_2 system_helper.modify_ntp(ntp_servers=ntp_pool)
def _test_modify_non_existing_cpu_negative(lock_): """ TC1940 cpu data can't be modified for a non existing cpu Test Steps: - Choose a host to lock and find how many phys cores it has - Attempt to change the cpu settings for a phys core that doesn't exist - Verify that the cli is rejected """ host = lock_ table_ = host_helper.get_host_cpu_list_table(host) cores = set(table_parser.get_column(table_, 'phy_core')) fake_proc_num = 2 while fake_proc_num in cores: fake_proc_num += 1 fake_proc = 'p{}'.format(fake_proc_num) map_ = {fake_proc: 1} LOG.tc_step("Attempt to modify fake processor {}'s function to vSwitch".format(fake_proc)) code, out = host_helper.modify_host_cpu(host, 'vSwitch', fail_ok=True, **map_) assert 0 != code, "FAIL: Modifying a non existing processor was not rejected" hosts = system_helper.get_hosts() name = hosts[len(hosts) - 1] + "a" while True: if name not in hosts: break name += "a" LOG.tc_step("Attempt to modify fake host {}'s processor p0 function to vSwitch".format(name)) code, out = host_helper.modify_host_cpu(name, 'vSwitch', p0=1, fail_ok=True) LOG.tc_step("Verifying that the cli was rejected") assert 1 == code, "FAIL: Modifying a cpu on a non-existant host was not rejected"
def get_alarms(header='alarm_id', name=None, strict=False, auth_info=Tenant.get('admin'), con_ssh=None): """ Args: header name: strict: auth_info: con_ssh: Returns: """ table_ = table_parser.table(cli.openstack('alarm list', ssh_client=con_ssh, auth_info=auth_info)[1], combine_multiline_entry=True) if name is None: return table_parser.get_column(table_, header) return table_parser.get_values(table_, header, Name=name, strict=strict)
def teardown(): LOG.fixture_step("Unsuppress all events") system_helper.unsuppress_all_events(fail_ok=True) LOG.fixture_step("Delete 300.005 alarm(s)") active_alarm_tab = system_helper.get_alarms_table( query_key='alarm_id', query_value='300.005') alarm_uuids = table_parser.get_column(active_alarm_tab, 'UUID') system_helper.delete_alarms(alarm_uuids)
def pre_check_upgrade(): # con_ssh = ControllerClient.get_active_controller() ProjVar.set_var(SOURCE_OPENRC=True) is_simplex = system_helper.is_aio_simplex() # check if all nodes are unlocked admin_states = system_helper.get_hosts(field='administrative') assert set(admin_states) == {'unlocked'} # check no active alarms in system table_ = table_parser.table(cli.system('alarm-list')[1]) alarm_severity_list = table_parser.get_column(table_, "Severity") LOG.info("Alarm Severity List: {}".format(alarm_severity_list)) assert "major" or "critical" not in alarm_severity_list, \ "Active alarms in system. Clear alarms before beginning upgrade" # check if system is patch current assert patching_helper.is_patch_current( con_ssh), "System is not patch current" # check if Controller-0 is the active active_controller = system_helper.get_active_controller_name( con_ssh=con_ssh) assert active_controller == "controller-0", "The active controller is " \ "not controller-0. Make controller-0 " \ "active before starting upgrade. Current " \ "active controller is {}".format(active_controller) # check if upgrade version is supported current_version = system_helper.get_sw_version() upgrade_version = UpgradeVars.get_upgrade_var('upgrade_version') backup_dest_path = BackupVars.get_backup_var('BACKUP_DEST_PATH') if upgrade_version is None: upgrade_version = [ u[1] for u in SUPPORTED_UPGRADES if u[0] == current_version ][0] UpgradeVars.set_upgrade_var(upgrade_version=upgrade_version) UpgradeVars.set_upgrade_var(tis_build_dir=BuildServerPath. LATEST_HOST_BUILD_PATHS[upgrade_version]) UpgradeVars.set_upgrade_var( patch_dir=BuildServerPath.PATCH_DIR_PATHS[upgrade_version]) LOG.info("Current version = {}; Upgrade version = {}".format( current_version, upgrade_version)) if upgrade_version == "16.10": UpgradeVars.set_upgrade_var(orchestration_after=None) assert [current_version, upgrade_version ] in SUPPORTED_UPGRADES, "Upgrade from {} to {} is not supported" if is_simplex: assert backup_dest_path is not None, "Simplex Upgrade need backup destianation path please add " \ "--backup_path=< >"
def get_upgrade_state(con_ssh=None): output = cli.system('upgrade-show', ssh_client=con_ssh)[1] if ("+" and "-" and "|") in output: table_ = table_parser.table(output) table_ = table_parser.filter_table(table_, Property="state") return table_parser.get_column(table_, "Value") else: return output
def _wait_for_upgrade_data_migration_complete(timeout=1800, check_interval=60, auth_info=Tenant.get('admin_platform'), fail_ok=False, con_ssh=None): """ Waits until upgrade data migration is complete or fail Args: timeout (int): MAX seconds to wait for data migration to complete fail_ok (bool): if true return error code con_ssh (SSHClient): auth_info (str): Returns (tuple): (0, "Upgrade data migration complete.") (1, "Upgrade dat migration failed. Applicable only if ail_ok") (2, "Upgrade data migration timeout out before complete. Applicable only if fail_ok") (3, "Timeout waiting the Host upgrade data migration to complete. Applicable if fail_ok ") """ endtime = time.time() + timeout while time.time() < endtime: upgrade_progress_tab = table_parser.table( cli.system('upgrade-show', ssh_client=con_ssh, auth_info=auth_info)[1]) upgrade_progress_tab = table_parser.filter_table(upgrade_progress_tab, Property="state") if "data-migration-complete" in table_parser.get_column(upgrade_progress_tab, 'Value'): LOG.info("Upgrade data migration is complete") return 0, "Upgrade data migration is complete" elif "data-migration-failed" in table_parser.get_column(upgrade_progress_tab, 'Value'): err_msg = "Host Upgrade data migration failed." LOG.warning(err_msg) if fail_ok: return 1, err_msg else: raise exceptions.HostError(err_msg) time.sleep(check_interval) err_msg = "Timed out waiting for upgrade data migration to complete state" if fail_ok: LOG.warning(err_msg) return 3, err_msg else: raise exceptions.HostError(err_msg)
def get_sensor_names(host, sensor_group=False): """ Args: host: Host to query sensor_group Returns: the sensor name """ sensor_table = get_sensors_table(host, sensor_group) names = table_parser.get_column(sensor_table, 'name') return names
def get_hosts_upgrade_running_release(hostnames, con_ssh=None): """ Gets the running_release of host(s) Args: hostnames (str/list): specifies the host or list of hosts con_ssh: Returns: list of running release ids. """ if isinstance(hostnames, str): hostnames = [hostnames] table_ = table_parser.table(cli.system('host-upgrade-list', ssh_client=con_ssh)[1]) table_ = table_parser.filter_table(hostname=hostnames, table_=table_) return table_parser.get_column(table_, "running_release")
def get_hosts_upgrade_target_release(hostnames, con_ssh=None): """ Gets the target release of a upgrade hosts Args: hostnames(str/list): specifies the host or list of hosts con_ssh: Returns: list of target releases. """ if isinstance(hostnames, str): hostnames = [hostnames] table_ = table_parser.table(cli.system('host-upgrade-list', ssh_client=con_ssh)[1]) table_ = table_parser.filter_table(table_, hostname=hostnames) return table_parser.get_column(table_, "target_release")
def traffic_with_preset_configs(ixncfg, ixia_session=None): with ExitStack() as stack: if ixia_session is None: LOG.info("ixia_session not supplied, creating") from keywords import ixia_helper ixia_session = ixia_helper.IxiaSession() ixia_session.connect() stack.callback(ixia_session.disconnect) ixia_session.load_config(ixncfg) subnet_table = table_parser.table( cli.openstack('subnet list', auth_info=Tenant.get('admin'))[1]) cidrs = list( map(ipaddress.ip_network, table_parser.get_column(subnet_table, 'Subnet'))) for vport in ixia_session.getList(ixia_session.getRoot(), 'vport'): for interface in ixia_session.getList(vport, 'interface'): if ixia_session.testAttributes(interface, enabled='true'): ipv4_interface = ixia_session.getList(interface, 'ipv4')[0] gw = ipaddress.ip_address( ixia_session.getAttribute(ipv4_interface, 'gateway')) vlan_interface = ixia_session.getList(interface, 'vlan')[0] for cidr in cidrs: if gw in cidr: net_id = table_parser.get_values(subnet_table, 'Network', cidr=cidr)[0] table = table_parser.table( cli.openstack( 'network show', net_id, auth_info=Tenant.get('admin'))[1]) seg_id = table_parser.get_value_two_col_table( table, "provider:segmentation_id") ixia_session.configure(vlan_interface, vlanEnable=True, vlanId=str(seg_id)) LOG.info( "vport {} interface {} gw {} vlan updated to {}" .format(vport, interface, gw, seg_id))
def wait_for_delete_imported_load(load_id, timeout=120, check_interval=5, fail_ok=False, con_ssh=None, auth_info=Tenant.get('admin_platform')): LOG.info("Waiting for imported load {} to be deleted from the load-list ".format(load_id)) end_time = time.time() + timeout while time.time() < end_time: table_ = table_parser.table(cli.system('load-list', ssh_client=con_ssh, auth_info=auth_info)[1]) table_ = table_parser.filter_table(table_, **{'id': load_id}) if len(table_parser.get_values(table_, 'id')) == 0: return True else: if 'deleting' in table_parser.get_column(table_, 'state'): cli.system('load-delete', load_id, ssh_client=con_ssh, fail_ok=True) time.sleep(check_interval) else: err_msg = "Timed out waiting for load {} to get deleted".format(load_id) if fail_ok: LOG.warning(err_msg) return False else: raise exceptions.TimeoutException(err_msg)
def get_system_health_query_upgrade(con_ssh=None): """ Queries the upgrade health of a system in use. Args: con_ssh: Returns: tuple (0, None) - success (1, dict(error msg) ) - health query reported 1 or more failures other than missing manifest and alarm (2, dict(error msg) ) - health query reported missing manifest and atleast one alarm (3, dict(error msg) ) - health query reported only minor alarm (4, dict(error msg) ) - health query reported only missing manifest """ output = (cli.system('health-query-upgrade', ssh_client=con_ssh)[1]).splitlines() failed = {} ok = {} for line in output: if ":" in line: k, v = line.split(":") if "[OK]" in v.strip(): ok[k.strip()] = v.strip() elif "[Fail]" in v.strip(): failed[k.strip()] = v.strip() elif "Missing manifests" in line: failed[line] = line if len(failed) == 0: LOG.info("system health is OK to start upgrade......") return 0, None alarms = any("No alarms" in h for h in failed.keys()) manifest = any("Missing manifests" in h for h in failed.keys()) cinder_config = any("Cinder configuration" in h for h in failed.keys()) err_msg = "System health query upgrade failed: {}".format(failed) if len(failed) > 3: # more than three health check failures LOG.error(err_msg) return 1, failed if len(failed) == 3: # check if the two failures are alarms and manifest, otherwise return error. if not alarms or not manifest or not cinder_config: LOG.error(err_msg) return 1, failed else: # Only one health check failure. Return error if not alarm or manifest if not alarms and not manifest and not cinder_config: LOG.error(err_msg) return 1, failed if alarms: # Check if it alarm table_ = table_parser.table(cli.fm('alarm-list')[1]) alarm_severity_list = table_parser.get_column(table_, "Severity") if len(alarm_severity_list) > 0 and \ ("major" not in alarm_severity_list and "critical" not in alarm_severity_list): # minor alarm present LOG.warn("System health query upgrade found minor alarms: {}".format(alarm_severity_list)) else: # major/critical alarm present LOG.error("System health query upgrade found major or critical alarms: {}".format(alarm_severity_list)) return 1, failed if manifest and alarms: return 2, failed elif alarms: # only minor alarm return 3, failed else: # only missing manifests return 4, failed
def test_system_alarms_and_events_on_lock_unlock_compute(no_simplex): """ Verify fm alarm-show command Test Steps: - Delete active alarms - Lock a host - Check active alarm generated for host lock - Check relative values are the same in fm alarm-list and fm alarm-show <uuid> - Check host lock 'set' event logged via fm event-list - Unlock host - Check active alarms cleared via fm alarm-list - Check host lock 'clear' event logged via fm event-list """ # Remove following step because it's unnecessary and fails the test when # alarm is re-generated # # Clear the alarms currently present # LOG.tc_step("Clear the alarms table") # system_helper.delete_alarms() # Raise a new alarm by locking a compute node # Get the compute compute_host = host_helper.get_up_hypervisors()[0] if compute_host == system_helper.get_active_controller_name(): compute_host = system_helper.get_standby_controller_name() if not compute_host: skip('Standby controller unavailable') LOG.tc_step("Lock a nova hypervisor host {}".format(compute_host)) pre_lock_time = common.get_date_in_format() HostsToRecover.add(compute_host) host_helper.lock_host(compute_host) LOG.tc_step("Check host lock alarm is generated") post_lock_alarms = \ system_helper.wait_for_alarm(field='UUID', entity_id=compute_host, reason=compute_host, alarm_id=EventLogID.HOST_LOCK, strict=False, fail_ok=False)[1] LOG.tc_step( "Check related fields in fm alarm-list and fm alarm-show are of the " "same values") post_lock_alarms_tab = system_helper.get_alarms_table(uuid=True) alarms_l = ['Alarm ID', 'Entity ID', 'Severity', 'Reason Text'] alarms_s = ['alarm_id', 'entity_instance_id', 'severity', 'reason_text'] # Only 1 alarm since we are now checking the specific alarm ID for post_alarm in post_lock_alarms: LOG.tc_step( "Verify {} for alarm {} in alarm-list are in sync with " "alarm-show".format( alarms_l, post_alarm)) alarm_show_tab = table_parser.table(cli.fm('alarm-show', post_alarm)[1]) alarm_list_tab = table_parser.filter_table(post_lock_alarms_tab, UUID=post_alarm) for i in range(len(alarms_l)): alarm_l_val = table_parser.get_column(alarm_list_tab, alarms_l[i])[0] alarm_s_val = table_parser.get_value_two_col_table(alarm_show_tab, alarms_s[i]) assert alarm_l_val == alarm_s_val, \ "{} value in alarm-list: {} is different than alarm-show: " \ "{}".format(alarms_l[i], alarm_l_val, alarm_s_val) LOG.tc_step("Check host lock is logged via fm event-list") system_helper.wait_for_events(entity_instance_id=compute_host, start=pre_lock_time, timeout=60, event_log_id=EventLogID.HOST_LOCK, fail_ok=False, **{'state': 'set'}) pre_unlock_time = common.get_date_in_format() LOG.tc_step("Unlock {}".format(compute_host)) host_helper.unlock_host(compute_host) LOG.tc_step("Check host lock active alarm cleared") alarm_sets = [(EventLogID.HOST_LOCK, compute_host)] system_helper.wait_for_alarms_gone(alarm_sets, fail_ok=False) LOG.tc_step("Check host lock clear event logged") system_helper.wait_for_events(event_log_id=EventLogID.HOST_LOCK, start=pre_unlock_time, entity_instance_id=compute_host, fail_ok=False, **{'state': 'clear'})
def test_vm_numa_node_settings(vcpus, numa_nodes, numa_node0, numa_node1, no_simplex, check_numa_num): """ Test NUMA nodes settings in flavor extra specs are successfully applied to a vm Args: vcpus (int): Number of vcpus to set when creating flavor numa_nodes (int): Number of NUMA nodes to set in flavor extra specs numa_node0 (int): node.0 value in flavor extra specs numa_node1 (int): node.1 value in flavor extra specs Test Steps: - Create a flavor with given number of vcpus specified - Add numa_nodes related extra specs - Boot a vm with flavor - Run vm-topology - Verify vcpus, numa nodes, cpulist for specific vm reflects the settings in flavor - Ensure that all virtual NICs are associated with guest virtual numa node 0 (tests TC5069) Teardown: - Delete created vm, volume, and flavor """ if check_numa_num < numa_nodes: skip("Number of processors - {} is less than required numa nodes - {}". format(check_numa_num, numa_nodes)) LOG.tc_step("Create flavor with {} vcpus".format(vcpus)) flavor = nova_helper.create_flavor('numa_vm', vcpus=vcpus)[1] ResourceCleanup.add('flavor', flavor, scope='function') extra_specs = { FlavorSpec.CPU_POLICY: 'dedicated', FlavorSpec.NUMA_NODES: numa_nodes, FlavorSpec.NUMA_0: numa_node0 } if numa_node1 is not None: extra_specs[FlavorSpec.NUMA_1] = numa_node1 LOG.tc_step("Set following extra specs for flavor {}: {}.".format( extra_specs, flavor)) nova_helper.set_flavor(flavor, **extra_specs) LOG.tc_step("Boot vm with flavor {}.".format(flavor)) vm_id = vm_helper.boot_vm(flavor=flavor, cleanup='function')[1] LOG.tc_step("Verify cpu info for vm {} via vm-topology.".format(vm_id)) nova_tab, libvirt_tab = system_helper.get_vm_topology_tables( 'servers', 'libvirt') # Filter out the line for vm under test nova_tab = table_parser.filter_table(nova_tab, ID=vm_id) libvirt_tab = table_parser.filter_table(libvirt_tab, uuid=vm_id) instance_topology = table_parser.get_column(nova_tab, 'instance_topology')[0] cpulist = table_parser.get_column(libvirt_tab, 'cpulist')[0] if '-' in cpulist: cpulist = cpulist.split(sep='-') cpulist_len = int(cpulist[1]) - int(cpulist[0]) + 1 else: cpulist_len = len(cpulist.split(sep=',')) vcpus_libvirt = int(table_parser.get_column(libvirt_tab, 'vcpus')[0]) nodelist = table_parser.get_column(libvirt_tab, 'nodelist')[0] if isinstance(instance_topology, str): instance_topology = [instance_topology] # Each numa node will have an entry for given instance, thus number of entries should be the same as number of # numa nodes for the vm assert numa_nodes == len(instance_topology), \ "Number of numa node entries for vm {} is different than number of NUMA nodes set in flavor".format(vm_id) expected_node_vals = [ int(val) for val in [numa_node0, numa_node1] if val is not None ] actual_node_vals = [] for actual_node_info in instance_topology: actual_node_val = int( re.findall(InstanceTopology.NODE, actual_node_info)[0]) actual_node_vals.append(actual_node_val) assert expected_node_vals == actual_node_vals, \ "Individual NUMA node value(s) for vm {} is different than numa_node setting in flavor".format(vm_id) assert vcpus == vcpus_libvirt, \ "Number of vcpus for vm {} in libvirt view is different than what's set in flavor.".format(vm_id) assert vcpus == cpulist_len, \ "Number of entries in cpulist for vm {} in libvirt view is different than number of vcpus set in flavor".format( vm_id) if '-' in nodelist: nodelist = nodelist.split(sep='-') nodelist_len = int(nodelist[1]) - int(nodelist[0]) + 1 else: nodelist_len = 1 if nodelist else 0 assert numa_nodes == nodelist_len, \ "nodelist for vm {} in libvirt view does not match number of numa nodes set in flavor".format(vm_id) if system_helper.is_avs(): # TC5069 LOG.tc_step( "Check via vshell that all vNICs are associated with the host NUMA node that guest numa0 maps to" ) host = vm_helper.get_vm_host(vm_id) actual_ports = network_helper.get_ports(vm_id) with host_helper.ssh_to_host(host) as compute_ssh: for port_id in actual_ports: ports_tab = table_parser.table( compute_ssh.exec_cmd("vshell port-show {}".format(port_id), fail_ok=False)[1]) socket_id = int( table_parser.get_value_two_col_table(ports_tab, field='socket-id')) assert socket_id == numa_node0, "NIC is not associated with numa-node0"
def create_flavor(name=None, flavor_id=None, vcpus=1, ram=1024, root_disk=None, ephemeral=None, swap=None, is_public=None, rxtx_factor=None, project=None, project_domain=None, description=None, guest_os=None, fail_ok=False, auth_info=Tenant.get('admin'), con_ssh=None, storage_backing=None, rtn_id=True, cleanup=None, add_default_specs=True, properties=None): """ Create a flavor with given criteria. Args: name (str): substring of flavor name. Whole name will be <name>-<auto_count>. e,g., 'myflavor-1'. If None, name will be set to 'flavor'. flavor_id (str): auto generated by default unless specified. vcpus (int): ram (int): root_disk (int): ephemeral (int): swap (int|None): is_public (bool): rxtx_factor (str): project project_domain description guest_os (str|None): guest name such as 'tis-centos-guest' or None - default tis guest assumed fail_ok (bool): whether it's okay to fail to create a flavor. Default to False. auth_info (dict): This is set to Admin by default. Can be set to other tenant for negative test. con_ssh (SSHClient): storage_backing (str): storage backing in extra flavor. Auto set storage backing based on system config if None. Valid values: 'local_image', 'remote' rtn_id (bool): return id or name cleanup (str|None): cleanup scope. function, class, module, or session add_default_specs (False): Whether to automatically add extra specs that are needed to launch vm properties (str|list|dict) Returns (tuple): (rtn_code (int), flavor_id/err_msg (str)) (0, <flavor_id/name>): flavor created successfully (1, <stderr>): create flavor cli rejected """ table_ = table_parser.table( cli.openstack('flavor list', ssh_client=con_ssh, auth_info=auth_info)[1]) existing_names = table_parser.get_column(table_, 'Name') if name is None: name = 'flavor' flavor_name = common.get_unique_name(name_str=name, existing_names=existing_names, resource_type='flavor') if root_disk is None: if not guest_os: guest_os = GuestImages.DEFAULT['guest'] root_disk = GuestImages.IMAGE_FILES[guest_os][1] args_dict = { '--ephemeral': ephemeral, '--swap': swap, '--rxtx-factor': rxtx_factor, '--disk': root_disk, '--ram': ram, '--vcpus': vcpus, '--id': flavor_id, '--project': project, '--project-domain': project_domain, '--description': description, '--public': True if is_public else None, '--private': True if is_public is False else None, '--property': properties, } args = '{} {}'.format(common.parse_args(args_dict, repeat_arg=True), flavor_name) LOG.info("Creating flavor {}...".format(flavor_name)) LOG.info("openstack flavor create option: {}".format(args)) exit_code, output = cli.openstack('flavor create', args, ssh_client=con_ssh, fail_ok=fail_ok, auth_info=auth_info) if exit_code > 1: return 1, output table_ = table_parser.table(output) flavor_id = table_parser.get_value_two_col_table(table_, 'id') LOG.info("Flavor {} created successfully.".format(flavor_name)) if cleanup: ResourceCleanup.add('flavor', flavor_id, scope=cleanup) if add_default_specs: extra_specs = {FlavorSpec.MEM_PAGE_SIZE: 'large'} # extra_specs = {FlavorSpec.MEM_PAGE_SIZE: 'small'} default_flavor_backing = ProjVar.get_var('DEFAULT_INSTANCE_BACKING') sys_inst_backing = ProjVar.get_var('INSTANCE_BACKING') if not default_flavor_backing: from keywords import host_helper sys_inst_backing = host_helper.get_hosts_per_storage_backing( auth_info=auth_info, con_ssh=con_ssh, refresh=True) configured_backings = [ backing for backing in sys_inst_backing if sys_inst_backing.get(backing) ] LOG.debug( "configured backing:{} sys inst backing: {}, required storage backing: {}" .format(configured_backings, sys_inst_backing, storage_backing)) if storage_backing and storage_backing not in configured_backings: raise ValueError( 'Required local_storage {} is not configured on any nova hypervisor' .format(storage_backing)) if len(configured_backings) > 1: extra_specs[FlavorSpec.STORAGE_BACKING] = storage_backing if storage_backing else \ ProjVar.get_var('DEFAULT_INSTANCE_BACKING') if extra_specs: LOG.info("Setting flavor specs: {}".format(extra_specs)) set_flavor(flavor_id, con_ssh=con_ssh, auth_info=auth_info, **extra_specs) flavor = flavor_id if rtn_id else flavor_name return 0, flavor, storage_backing
def get_upgraded_host_names(upgrade_release, con_ssh=None): table_ = table_parser.table(cli.system('host-upgrade-list', ssh_client=con_ssh)[1]) table_ = table_parser.filter_table(table_, target_release=upgrade_release) return table_parser.get_column(table_, "hostname")
def vm_tenant2_image_unavailable(): table_ = table_parser.table( cli.openstack('server list', ssh_client=None) [1]) # auth_info unspecified, so it will run cli with primary tenant return 'tenant2-image' not in table_parser.get_column(table_, 'Name')
def get_system_health_query_upgrade_2(con_ssh=None): """ Queries the upgrade health of a system in use. Args: con_ssh: Returns: tuple (0, None) - success (1, dict(error msg) ) - health query reported 1 or more failures other than missing manifest and alarm (2, dict(error msg) ) - health query reported missing manifest and atleast one alarm (3, dict(error msg) ) - health query reported only minor alarm (4, dict(error msg) ) - health query reported only missing manifest """ output = (cli.system('health-query-upgrade', ssh_client=con_ssh)[1]).splitlines() failed = {} ok = {} for line in output: if ":" in line: k, v = line.split(":") if "[OK]" in v.strip(): ok[k.strip()] = v.strip() elif "[Fail]" in v.strip(): failed[k.strip()] = v.strip() elif "Hosts missing placement configuration" in k: failed[k.strip()] = v.strip() elif "Incomplete configuration" in k: failed[k.strip()] = v.strip() elif "Locked or disabled hosts" in k: failed[k.strip()] = v.strip() elif "Missing manifests" in line: failed[line] = line elif "alarms found" in line: if len(line.split(',')) > 1: failed["managment affecting"] = int(line.split(',')[1].strip()[1]) if len(failed) == 0: LOG.info("system health is OK to start upgrade......") return 0, None, None actions = {"lock_unlock": [[], ""], "force_upgrade": [False, ''], "swact": [False, ''], } for k, v in failed.items(): if "No alarms" in k: table_ = table_parser.table(cli.fm('alarm-list --uuid')[1]) alarm_severity_list = table_parser.get_column(table_, "Severity") if len(alarm_severity_list) > 0 \ and "major" not in alarm_severity_list \ and "critical" not in alarm_severity_list: # minor alarm present LOG.warn("System health query upgrade found minor alarms: {}".format(alarm_severity_list)) actions["force_upgrade"] = [True, "Minor alarms present"] elif "managment affecting" in k: if v == 0: # non management affecting alarm present use foce upgrade LOG.warn("System health query upgrade found non managment affecting alarms: {}" .format(k)) actions["force_upgrade"] = [True, "Non managment affecting alarms present"] else: # major/critical alarm present, management affecting LOG.error("System health query upgrade found major or critical alarms.") return 1, failed, None elif "Missing manifests" in k: # manifest = True if "controller-1" in k: if "controller-1" not in actions["lock_unlock"][0]: actions["lock_unlock"][0].append("controller-1") if "controller-0" in k: if "controller-0" not in actions["lock_unlock"][0]: actions["lock_unlock"][0].append("controller-0") actions["lock_unlock"][1] += "Missing manifests;" elif any(s in k for s in ("Cinder configuration", "Incomplete configuration")): # cinder_config = True actions["swact"] = [True, actions["swact"][1] + "Invalid Cinder configuration;"] elif "Placement Services Enabled" in k or "Hosts missing placement configuration" in k: # placement_services = True if "controller-1" in v: if "controller-1" not in actions["lock_unlock"][0]: actions["lock_unlock"][0].append("controller-1") if "controller-0" in v: if "controller-0" not in actions["lock_unlock"][0]: actions["lock_unlock"][0].append("controller-0") actions["lock_unlock"][1] += "Missing placement configuration;" else: err_msg = "System health query upgrade failed: {}".format(failed) LOG.error(err_msg) return 1, failed, None return 2, failed, actions