def verify_image_not_in_bmc_uploads_dir(image_version, timeout=3): r""" Check that an image with the given version is not unpacked inside of the BMCs image uploads directory. If no image is found, retry every 30 seconds until the given timeout is hit, in case the BMC takes time unpacking the image. Description of argument(s): image_version The version of the image to look for on the BMC. timeout How long, in minutes, to try to find an image on the BMC. Default is 3 minutes. """ for i in range(timeout * 2): stdout, stderr, rc = \ bsu.bmc_execute_command('ls ' + var.IMAGE_UPLOAD_DIR_PATH + '*/MANIFEST 2>/dev/null ' + '| xargs grep -rl "version=' + image_version + '"') image_dir = os.path.dirname(stdout.split('\n')[0]) if '' != image_dir: bsu.bmc_execute_command('rm -rf ' + image_dir) BuiltIn().fail('Found invalid BMC Image: ' + image_dir) time.sleep(30)
def get_bmc_df(df_parm_string=""): r""" Get df report from BMC and return as a report "object". A df report object is a list where each entry is a dictionary whose keys are the field names from the first entry in report_list. Example df report object: df_report: df_report[0]: [filesystem]: dev [1k-blocks]: 247120 [used]: 0 [available]: 247120 [use%]: 0% [mounted]: /dev df_report[1]: [filesystem]: dev [1k-blocks]: 247120 [used]: 0 [available]: 247120 [use%]: 0% [mounted]: /dev . Description of argument(s): df_parm_string A string containing valid df command parms (e.g. "-h /var"). """ out_buf, stderr, rc = bsu.bmc_execute_command("df " + df_parm_string) return vf.outbuf_to_report(out_buf)
def get_device_id_config(): r""" Get the device id config data and return as a dictionary. Example: dev_id_config = get_device_id_config() print_vars(dev_id_config) dev_id_config: [manuf_id]: 7244 [addn_dev_support]: 141 [prod_id]: 16976 [aux]: 0 [id]: 32 [revision]: 129 [device_revision]: 1 """ stdout, stderr, rc = bsu.bmc_execute_command("cat /usr/share/ipmi-providers/dev_id.json") result = json.loads(stdout) # Create device revision field for the user. # Reference IPMI specification v2.0 "Get Device ID Command" # [7] 1 = device provides Device SDRs # 0 = device does not provide Device SDRs # [6:4] reserved. Return as 0. # [3:0] Device Revision, binary encoded. result['device_revision'] = result['revision'] & 0x0F return result
def pldmtool(option_string, **bsu_options): r""" Run pldmtool on the BMC with the caller's option string and return the result. Example: ${pldm_results}= Pldmtool base GetPLDMTypes Rprint Vars pldm_results pldm_results: pldmtool base GetPLDMVersion -t 0 { "Response": "1.0.0" } pldmtool base GetTID { "Response": 1 } Description of argument(s): option_string A string of options which are to be processed by the pldmtool command. parse_results Parse the pldmtool results and return a dictionary rather than the raw pldmtool output. bsu_options Options to be passed directly to bmc_execute_command. See its prolog for details. """ # This allows callers to specify arguments in python style (e.g. print_out=1 vs. print_out=${1}). bsu_options = fa.args_to_objects(bsu_options) stdout, stderr, rc = bsu.bmc_execute_command('pldmtool ' + option_string, **bsu_options) return json.loads(stdout)
def peltool(option_string, **bsu_options): r""" Run peltool on the BMC with the caller's option string and return the result. Example: ${pel_results}= Peltool -l Rprint Vars pel_results pel_results: [0x50000031]: [CompID]: 0x1000 [PLID]: 0x50000031 [Subsystem]: BMC Firmware [Message]: An application had an internal failure [SRC]: BD8D1002 [Commit Time]: 02/25/2020 04:51:31 [Sev]: Unrecoverable Error [CreatorID]: BMC Description of argument(s): option_string A string of options which are to be processed by the peltool command. bsu_options Options to be passed directly to bmc_execute_command. See its prolog for details. """ bsu_options = fa.args_to_objects(bsu_options) out_buf, stderr, rc = bsu.bmc_execute_command('peltool ' + option_string, **bsu_options) out_buf = json.loads(out_buf) return out_buf
def get_channel_access_config(file_name): r""" Get the channel access config data and return as a dictionary. Description of argument: file_name File name for channel access settings (e.g. '/run/ipmi/channel_access_volatile.json', '/var/lib/ipmi/channel_access_nv.json'.). Example: channel_access_config = get_channel_access_config() print_vars(channel_access_config) channel_access_config: [1]: [priv_limit]: priv-admin [per_msg_auth_disabled]: False [access_mode]: always_available [alerting_disabled]: False [user_auth_disabled]: False [2]: [priv_limit]: priv-admin [per_msg_auth_disabled]: False [access_mode]: always_available [alerting_disabled]: False [user_auth_disabled]: False """ stdout, stderr, rc = bsu.bmc_execute_command("cat " + file_name) return json.loads(stdout)
def get_dump_dict(quiet=None): r""" Get dump information and return as an ordered dictionary where the keys are the dump IDs and the values are the full path names of the dumps. Example robot program call: ${dump_dict}= Get Dump Dict Rpvars 1 dump_dict Example output: dump_dict: [1]: /var/lib/phosphor-debug-collector/dumps/1/obmcdump_1_1508255216.tar.xz [2]: /var/lib/phosphor-debug-collector/dumps/2/obmcdump_2_1508255245.tar.xz [3]: /var/lib/phosphor-debug-collector/dumps/3/obmcdump_3_1508255267.tar.xz [4]: /var/lib/phosphor-debug-collector/dumps/4/obmcdump_4_1508255283.tar.xz Description of argument(s): quiet If quiet is set to 1, this function will NOT write status messages to stdout. """ quiet = int(gp.get_var_value(quiet, 1)) cmd_buf = "dump_dir_path=" + var.DUMP_DIR_PATH + " ; " \ + "for dump_id in $(ls ${dump_dir_path} | sort -n) ; " \ + "do echo -n $dump_id: ; ls ${dump_dir_path}${dump_id}/* ; done" output, stderr, rc = bsu.bmc_execute_command(cmd_buf, quiet=quiet) return vf.key_value_outbuf_to_dict(output)
def get_dump_dict(quiet=None): r""" Get dump information and return as an ordered dictionary where the keys are the dump IDs and the values are the full path names of the dumps. Example robot program call: ${dump_dict}= Get Dump Dict Rprint Vars dump_dict Example output: dump_dict: [1]: /var/lib/phosphor-debug-collector/dumps/1/obmcdump_1_1508255216.tar.xz [2]: /var/lib/phosphor-debug-collector/dumps/2/obmcdump_2_1508255245.tar.xz [3]: /var/lib/phosphor-debug-collector/dumps/3/obmcdump_3_1508255267.tar.xz [4]: /var/lib/phosphor-debug-collector/dumps/4/obmcdump_4_1508255283.tar.xz Description of argument(s): quiet If quiet is set to 1, this function will NOT write status messages to stdout. """ quiet = int(gp.get_var_value(quiet, 1)) cmd_buf = "dump_dir_path=" + var.DUMP_DIR_PATH + " ; " \ + "for dump_id in $(ls ${dump_dir_path} | sort -n) ; do " \ + "file_path=$(ls ${dump_dir_path}${dump_id}/* 2>/dev/null)" \ + " || continue ; echo ${dump_id}:${file_path} ; done" output, stderr, rc = bsu.bmc_execute_command(cmd_buf, quiet=quiet) return vf.key_value_outbuf_to_dict(output)
def get_sbe(): r""" Return CFAM value which contains such things as SBE side bit. """ cmd_buf = "pdbg -d p9w -p0 getcfam 0x2808 | sed -re 's/.* = //g'" out_buf, stderr, rc = bsu.bmc_execute_command(cmd_buf) return int(out_buf, 16)
def get_image_version(file_path): r""" Read the file for a version object. Description of argument(s): file_path The path to a file that holds the image version. """ stdout, stderr, rc = \ bsu.bmc_execute_command("cat " + file_path + " | grep \"version=\"", ignore_err=1) return (stdout.split("\n")[0]).split("=")[-1]
def get_image_purpose(file_path): r""" Read the file for a purpose object. Description of argument(s): file_path The path to a file that holds the image purpose. """ stdout, stderr, rc = \ bsu.bmc_execute_command("cat " + file_path + " | grep \"purpose=\"", ignore_err=1) return stdout.split("=")[-1]
def get_latest_file(dir_path): r""" Get the path to the latest uploaded file. Description of argument(s): dir_path Path to the dir from which the name of the last updated file or folder will be returned to the calling function. """ stdout, stderr, rc = \ bsu.bmc_execute_command("cd " + dir_path + "; stat -c '%Y %n' * |" + " sort -k1,1nr | head -n 1") return stdout.split(" ")[-1]
def get_bmc_date_time(): r""" Get date/time info from BMC and return as a dictionary. Example of dictionary data returned by this keyword. time_dict: [local_time]: Fri 2017-11-03 152756 UTC [local_time_seconds]: 1509740876 [universal_time]: Fri 2017-11-03 152756 UTC [universal_time_seconds]: 1509740876 [rtc_time]: Fri 2016-05-20 163403 [rtc_time_seconds]: 1463780043 [time_zone]: n/a (UTC, +0000) [network_time_on]: yes [ntp_synchronized]: no [rtc_in_local_tz]: no """ out_buf, stderr, rc = bsu.bmc_execute_command('timedatectl') # Example of output returned by call to timedatectl: # Local time: Fri 2017-11-03 15:27:56 UTC # Universal time: Fri 2017-11-03 15:27:56 UTC # RTC time: Fri 2016-05-20 16:34:03 # Time zone: n/a (UTC, +0000) # Network time on: yes # NTP synchronized: no # RTC in local TZ: no # Convert the out_buf to a dictionary. initial_time_dict = vf.key_value_outbuf_to_dict(out_buf) # For each "_time" entry in the dictionary, we will create a corresponding # "_time_seconds" entry. We create a new dictionary so that the entries # are kept in a nice order for printing. try: result_time_dict = collections.OrderedDict() except AttributeError: result_time_dict = DotDict() for key, value in initial_time_dict.items(): result_time_dict[key] = value if not key.endswith("_time"): continue result_time_dict[key + '_seconds'] = \ int(DateTime.convert_date(value, result_format='epoch')) return result_time_dict
def pdbg(option_string, **bsu_options): r""" Run pdbg on the BMC with the caller's option string and return the output. Description of argument(s): option_string A string of options which are to be processed by the pdbg command. bsu_options Options to be passed directly to bmc_execute_command. See its prolog for details. """ # Default print_out to 1. if 'print_out' not in bsu_options: bsu_options['print_out'] = 1 stdout, stderr, rc = bsu.bmc_execute_command('pdbg ' + option_string, **bsu_options) return stdout
def ecmd(option_string, **bsu_options): r""" Run ecmd command on the BMC with the caller's option string and return the output. Description of argument(s): option_string A string of options which are to be executed on BMC. (e.g. getscom pu 20010a40 -all, putscom pu 20010a40 4000000000000000 -p0). bsu_options Options to be passed directly to bmc_execute_command. See its prolog for details. """ # Default print_out to 1. if 'print_out' not in bsu_options: bsu_options['print_out'] = 1 stdout, stderr, rc = bsu.bmc_execute_command(option_string, **bsu_options) return stdout
def vpdtool(option_string, **bsu_options): r""" Run vpdtool on the BMC with the caller's option string and return the result. Example: ${vpd_results}= vpd-tool -i Rprint Vars vpd_results vpd_results: [/system/chassis/motherboard]: [PN]: PN12345 [SN]: YL2E2D010000 [LocationCode]: U78DA.ND1. -P0 [CC]: 2E2D [DR]: SYSTEM BACKPLANE [FN]: F191014 [type]: xyz.openbmc_project.Inventory.Item.Board.Motherboard [/system/chassis/motherboard/ebmc_card_bmc]: [PN]: PN12345 [SN]: YL6B58010000 [LocationCode]: U78DA.ND1. -P0-C5 [CC]: 6B58 [DR]: EBMC [FN]: F191014 [type]: xyz.openbmc_project.Inventory.Item.Bmc Description of argument(s): option_string A string of options which are to be processed by the vpd-tool command. bsu_options Options to be passed directly to bmc_execute_command. See its prolog for details. """ bsu_options = fa.args_to_objects(bsu_options) out_buf, stderr, rc = bsu.bmc_execute_command('vpd-tool ' + option_string, **bsu_options) # Only return output if its not a VPD write command. if '-w' not in option_string: out_buf = json.loads(out_buf) if '-r' in option_string: return out_buf else: return out_buf[0]
def get_channel_config(): r""" Get the channel config data and return as a dictionary. Example: channel_config = get_channel_config() print_vars(channel_config) channel_config: [0]: [name]: IPMB [is_valid]: True [active_sessions]: 0 [channel_info]: [medium_type]: ipmb [protocol_type]: ipmb-1.0 [session_supported]: session-less [is_ipmi]: True [1]: [name]: eth0 [is_valid]: True [active_sessions]: 0 [channel_info]: [medium_type]: other-lan [protocol_type]: ipmb-1.0 [session_supported]: multi-session [is_ipmi]: True [2]: [name]: eth1 [is_valid]: True [active_sessions]: 0 [channel_info]: [medium_type]: lan-802.3 [protocol_type]: ipmb-1.0 [session_supported]: multi-session [is_ipmi]: True (etc.) """ stdout, stderr, rc = bsu.bmc_execute_command( "cat /usr/share/ipmi-providers/channel_config.json") return json.loads(stdout)
def get_secure_boot_info(self, quiet=None): r""" Get secure-boot information and return it as a tuple consisting of num_procs, secure_boot, jumper. num_procs is the number of processors containing the information. secure_boot will be set to True if each and every register value in question has its secureboot bit set (Bit 4). jumper will be set to True if each and every register value in question has its jumper bit set (Bit 5). Description of argument(s): quiet See shell_cmd for details. """ cmd_buf = "pdbg -d p9w -a getcfam 0x2801" out_buf, stderr, rc = bsu.bmc_execute_command(cmd_buf, quiet=quiet) # Convert result to a dictionary with one key for each processor: # result: # [p0:0x2801]: 0x80c00002 # [p1:0x2801]: 0x90c00002 result = vf.key_value_outbuf_to_dict(out_buf, delim="=") num_procs = len(result) # Initialize values to True. secure_boot = True jumper = True for key, value in result.items(): # Convert hex string to int. reg_value = int(value, 16) if not reg_value & secure_boot_mask(): secure_boot = False if not reg_value & jumper_mask(): jumper = False return num_procs, secure_boot, jumper
def get_bmc_release_info(): r""" Get release info from the BMC and return as a dictionary. Example: ${release_info}= Get BMC Release Info Rprint Vars release_info Output: release_info: [id]: openbmc-phosphor [name]: Phosphor OpenBMC (Phosphor OpenBMC Project Reference... [version]: 2.8.0-dev [version_id]: 2.8.0-dev-1083-g8954c3505 [pretty_name]: Phosphor OpenBMC (Phosphor OpenBMC Project Reference... [build_id]: 2.8.0-dev [openbmc_target_machine]: witherspoon """ out_buf, stderr, rc = bsu.bmc_execute_command('cat /etc/os-release') return vf.key_value_outbuf_to_dict(out_buf, delim="=", strip='"')
def get_image_path(image_version): r""" Query the upload image dir for the presence of image matching the version that was read from the MANIFEST before uploading the image. Based on the purpose verify the activation object exists and is either READY or INVALID. Description of argument(s): image_version The version of the image that should match one of the images in the upload dir. """ stdout, stderr, rc = \ bsu.bmc_execute_command("ls -d " + var.IMAGE_UPLOAD_DIR_PATH + "*/") image_list = stdout.split("\n") retry = 0 while (retry < 10): for i in range(0, len(image_list)): version = get_image_version(image_list[i] + "MANIFEST") if (version == image_version): return image_list[i] time.sleep(10) retry += 1
def pldmtool(option_string, parse_results=1, **bsu_options): r""" Run pldmtool on the BMC with the caller's option string and return the result. Example: ${pldm_results}= Pldmtool base GetPLDMTypes Rprint Vars pldm_results pldm_results: [request_message]: 08 01 80 00 04 [success_in_creating_the_socket]: RC = 3 [success_in_connecting_to_socket]: RC = 0 [success_in_sending_message_type_as_pldm_to_mctp]:RC = 0 [write_to_socket_successful]: RC = 5 [total_length]: 14 [loopback_response_message]: 08 01 80 00 04 [on_first_recv(),response_==_request]: RC = 0 [shutdown_socket_successful]: RC = 0 [response_message]: 08 01 00 00 04 00 0d 00 00 00 00 00 00 00 [supported_types]: [raw]: [0]: 0 [1]: 2 [2]: 3 [text]: [0]: base [1]: platform [2]: bios Description of argument(s): option_string A string of options which are to be processed by the pldmtool command. parse_results Parse the pldmtool results and return a dictionary rather than the raw pldmtool output. bsu_options Options to be passed directly to bmc_execute_command. See its prolog for details. """ # This allows callers to specify arguments in python style (e.g. print_out=1 vs. print_out=${1}). bsu_options = fa.args_to_objects(bsu_options) stdout, stderr, rc = bsu.bmc_execute_command('pldmtool ' + option_string, **bsu_options) if parse_results: # Remove linefeeds following colons. stdout = re.sub(":\n", ":", stdout) # Remove first line (e.g. "Encode request successfully"). stdout = re.sub("^.*\\n", "", stdout) result = vf.key_value_outbuf_to_dict(stdout) if 'supported_types' in result: # 'supported types' begins like this: # 0(base) 2(platform) 3(bios) # Parsing it to look like it does in the example above. supported_types = {'raw': [], 'text': []} for entry in result['supported_types'].split(" "): record = entry.split("(") supported_types['raw'].append(record[0]) supported_types['text'].append(record[1].rstrip(")")) result['supported_types'] = supported_types if 'date_&_time' in result: return result['yyyy-mm-dd_hh'].split(' - ')[1] return result return stdout
def pldmtool(option_string, parse_results=1, **bsu_options): r""" Run pldmtool on the BMC with the caller's option string and return the result. Example: ${pldm_results}= Pldmtool base GetPLDMTypes Rprint Vars pldm_results pldm_results: [supported_types]: [raw]: [0]: 0 [1]: 2 [2]: 3 [text]: [0]: base [1]: platform [2]: bios Description of argument(s): option_string A string of options which are to be processed by the pldmtool command. parse_results Parse the pldmtool results and return a dictionary rather than the raw pldmtool output. bsu_options Options to be passed directly to bmc_execute_command. See its prolog for details. """ # This allows callers to specify arguments in python style (e.g. print_out=1 vs. print_out=${1}). bsu_options = fa.args_to_objects(bsu_options) stdout, stderr, rc = bsu.bmc_execute_command('pldmtool ' + option_string, **bsu_options) if parse_results: result = vf.key_value_outbuf_to_dict(stdout) if 'supported_types' in result: # 'supported types' begins like this: # 0(base) 2(platform) 3(bios) # Parsing it to look like it does in the example above. supported_types = {'raw': [], 'text': []} for entry in result['supported_types'].split(" "): record = entry.split("(") supported_types['raw'].append(record[0]) supported_types['text'].append(record[1].rstrip(")")) result['supported_types'] = supported_types elif 'supported_commands' in result: commands = result['supported_commands'].split(":")[0].split(" ") return commands elif 'yyyy-mm-dd_hh' in result: # Date & Time : # YYYY-MM-DD HH:MM:SS - 2020-02-24 06:44:16 return result['yyyy-mm-dd_hh'].split(' - ')[1] # Simplfying dict output for GetPDR with type PDREntityAssociation. # Example : # pldmtool platform GetPDR -d 10 # Entity Association # nextRecordHandle: 0 # responseCount: 56 # recordHandle: 10 # PDRHeaderVersion: 1 # PDRType: 15 # recordChangeNumber: 0 # dataLength: 46 # containerID: 1 # associationType: Physical # containerEntityType: System Board # containerEntityInstanceNumber: 1 # containerEntityContainerID: 0 # containedEntityCount: 6 # containedEntityType[1]: Chassis front panel board (control panel) # containedEntityInstanceNumber[1]: 1 # containedEntityContainerID[1]: 1 # containedEntityType[2]: Chassis front panel board (control panel) # containedEntityInstanceNumber[2]: 2 # containedEntityContainerID[2]: 1 elif 'containerentitycontainerid' in result: dict_data1, dict_data2 = vf.split_dict_on_key( 'containerentitycontainerid', result) return dict_data1 elif 'entitytype' in result: # Example : # entityType: 24576(OEM) # Note: OEM type number is dynamic if 'OEM' in result['entitytype']: result['entitytype'] = 'OEM' # Collect bios strings from bios string table in to list. # Example output for pldmtool GetBIOSTable --type stringTable # PLDM StringTable: # BIOSStringHandle : BIOSString # 0 : Allowed # 1 : Disabled # 2 : Enabled elif 'pldm_stringtable' in result: result.pop('pldm_stringtable') result.pop('biosstringhandle') bios_string_list = [] for data in result: bios_string_list.append(result[data]) # Example for bios_string_list: # bios_string_list = ['Allowed', 'Disabled', 'Enabled'] return bios_string_list # Check if parameter pldm_attributetable/pldm_attributevaluetable present for # pldmtool GetBIOSTable --type AttributeTable/AttributeValueTable. # Note: Output for AttributeTable/AttributeValueTable is huge and verification of # table content is not available. elif 'pldm_attributetable' in result: result['pldm_attributetable'] = True return result elif 'pldm_attributevaluetable' in result: result['pldm_attributevaluetable'] = True return result return result return stdout