| #!/usr/bin/env python3 -u | 
 |  | 
 | r""" | 
 | Generic utility functions. | 
 | """ | 
 | import importlib.util | 
 | import random | 
 | import string | 
 | import subprocess | 
 |  | 
 | from robot.libraries.BuiltIn import BuiltIn | 
 | from robot.utils import DotDict | 
 |  | 
 |  | 
 | def load_source(name, module_path): | 
 |     r""" | 
 |     import util to replace deprecated imp.load_source | 
 |     """ | 
 |     spec = importlib.util.spec_from_file_location(name, module_path) | 
 |     module = importlib.util.module_from_spec(spec) | 
 |     spec.loader.exec_module(module) | 
 |     return module | 
 |  | 
 |  | 
 | def random_mac(): | 
 |     r""" | 
 |     Return random mac address in the following format. | 
 |     Example: 00:01:6C:80:02:78 | 
 |     """ | 
 |     return ":".join( | 
 |         map( | 
 |             lambda x: "%02x" % x, | 
 |             (random.randint(0x00, 0xFF) for _ in range(6)), | 
 |         ) | 
 |     ) | 
 |  | 
 |  | 
 | def random_ip(): | 
 |     r""" | 
 |     Return random ip address in the following format. | 
 |     Example: 9.3.128.100 | 
 |     """ | 
 |     return ".".join(map(str, (random.randint(0, 255) for _ in range(4)))) | 
 |  | 
 |  | 
 | def get_sensor(module_name, value): | 
 |     r""" | 
 |     Return sensor matched ID name. | 
 |     """ | 
 |     m = load_source("module.name", module_name) | 
 |  | 
 |     for i in m.ID_LOOKUP["SENSOR"]: | 
 |         if m.ID_LOOKUP["SENSOR"][i] == value: | 
 |             return i | 
 |  | 
 |     return 0xFF | 
 |  | 
 |  | 
 | def get_inventory_sensor(module_name, value): | 
 |     r""" | 
 |     Return sensor matched ID name from inventory. | 
 |     """ | 
 |     m = load_source("module.name", module_name) | 
 |  | 
 |     value = string.replace(value, m.INVENTORY_ROOT, "<inventory_root>") | 
 |  | 
 |     for i in m.ID_LOOKUP["SENSOR"]: | 
 |         if m.ID_LOOKUP["SENSOR"][i] == value: | 
 |             return i | 
 |  | 
 |     return 0xFF | 
 |  | 
 |  | 
 | ################################################################ | 
 | #  This will return the URI's of the FRU type | 
 | # | 
 | #  i.e.  get_inventory_list('../data/Palmetto.py') | 
 | # | 
 | #  [/org/openbmc/inventory/system/chassis/motherboard/cpu0/core0, | 
 | #   /org/openbmc/inventory/system/chassis/motherboard/dimm0] | 
 | ################################################################ | 
 | def get_inventory_list(module_name): | 
 |     r""" | 
 |     Return all FRU URI(s) list available from inventory. | 
 |     """ | 
 |  | 
 |     inventory_list = [] | 
 |     m = load_source("module.name", module_name) | 
 |  | 
 |     for i in m.ID_LOOKUP["FRU"]: | 
 |         s = m.ID_LOOKUP["FRU"][i] | 
 |         s = s.replace("<inventory_root>", m.INVENTORY_ROOT) | 
 |         inventory_list.append(s) | 
 |  | 
 |     return inventory_list | 
 |  | 
 |  | 
 | ################################################################ | 
 | #  This will return the URI's of the FRU type | 
 | # | 
 | #  i.e.  get_inventory_fru_type_list('../data/Witherspoon.py', 'CPU') | 
 | # | 
 | #  [/org/openbmc/inventory/system/chassis/motherboard/cpu0, | 
 | #   /org/openbmc/inventory/system/chassis/motherboard/cpu1] | 
 | ################################################################ | 
 | def get_inventory_fru_type_list(module_name, fru): | 
 |     r""" | 
 |     Return FRU URI(s) list of a given type from inventory. | 
 |     """ | 
 |     inventory_list = [] | 
 |     m = load_source("module.name", module_name) | 
 |  | 
 |     for i in m.FRU_INSTANCES.keys(): | 
 |         if m.FRU_INSTANCES[i]["fru_type"] == fru: | 
 |             s = i.replace("<inventory_root>", m.INVENTORY_ROOT) | 
 |             inventory_list.append(s) | 
 |  | 
 |     return inventory_list | 
 |  | 
 |  | 
 | ################################################################ | 
 | #  This will return the URI's of the FRU type that contain VPD | 
 | # | 
 | #  i.e.  get_vpd_inventory_list('../data/Palmetto.py', 'DIMM') | 
 | # | 
 | #  [/org/openbmc/inventory/system/chassis/motherboard/dimm0, | 
 | #   /org/openbmc/inventory/system/chassis/motherboard/dimm1] | 
 | ################################################################ | 
 | def get_vpd_inventory_list(module_name, fru): | 
 |     r""" | 
 |     Return VPD URI(s) list of a FRU type from inventory. | 
 |     """ | 
 |     inventory_list = [] | 
 |     m = load_source("module.name", module_name) | 
 |  | 
 |     for i in m.ID_LOOKUP["FRU_STR"]: | 
 |         x = m.ID_LOOKUP["FRU_STR"][i] | 
 |  | 
 |         if m.FRU_INSTANCES[x]["fru_type"] == fru: | 
 |             s = x.replace("<inventory_root>", m.INVENTORY_ROOT) | 
 |             inventory_list.append(s) | 
 |  | 
 |     return inventory_list | 
 |  | 
 |  | 
 | def call_keyword(keyword): | 
 |     r""" | 
 |     Return result of the execute robot keyword. | 
 |     """ | 
 |     return BuiltIn().run_keyword(keyword) | 
 |  | 
 |  | 
 | def main(): | 
 |     r""" | 
 |     Python main func call. | 
 |     """ | 
 |     print(get_vpd_inventory_list("../data/Palmetto.py", "DIMM")) | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |     main() | 
 |  | 
 |  | 
 | def get_mtr_report(host=""): | 
 |     r""" | 
 |     Get an mtr report and return it as a dictionary of dictionaries. | 
 |  | 
 |     The key for the top level dictionary will be the host DNS name.  The key | 
 |     for the next level dictionary will be the field of a given row of the | 
 |     report. | 
 |  | 
 |     Example result: | 
 |  | 
 |     report: | 
 |       report[host_dummy-dnsname.com]: | 
 |         report[host_dummy-dnsname.com][row_num]:  1 | 
 |         report[host_dummy-dnsname.com][host]:     host_dummy-dnsname.com | 
 |         report[host_dummy-dnsname.com][loss]:     0.0 | 
 |         report[host_dummy-dnsname.com][snt]:      10 | 
 |         report[host_dummy-dnsname.com][last]:     0.2 | 
 |         report[host_dummy-dnsname.com][avg]:      3.5 | 
 |         report[host_dummy-dnsname.com][best]:     0.2 | 
 |         report[host_dummy-dnsname.com][wrst]:     32.5 | 
 |         report[host_dummy-dnsname.com][stdev]:    10.2 | 
 |       report[bmc-dummy-dnsname.com]: | 
 |         report[bmc-dummy-dnsname.com][row_num]:     2 | 
 |         report[bmc-dummy-dnsname.com][host]:        bmc-dummy-dnsname.com | 
 |         report[bmc-dummy-dnsname.com][loss]:        0.0 | 
 |         report[bmc-dummy-dnsname.com][snt]:         10 | 
 |         report[bmc-dummy-dnsname.com][last]:        0.5 | 
 |         report[bmc-dummy-dnsname.com][avg]:         0.5 | 
 |         report[bmc-dummy-dnsname.com][best]:        0.5 | 
 |         report[bmc-dummy-dnsname.com][wrst]:        0.5 | 
 |         report[bmc-dummy-dnsname.com][stdev]:       0.0 | 
 |  | 
 |     Description of arguments: | 
 |     host   The DNS name or IP address to be passed to the mtr command. | 
 |     """ | 
 |  | 
 |     # Run the mtr command.  Exclude the header line.  Trim leading space from | 
 |     # each line.  Change all multiple spaces delims to single space delims. | 
 |     cmd_buf = ( | 
 |         "mtr --report " | 
 |         + host | 
 |         + " | tail -n +2 | sed -r -e 's/^[ ]+//g' -e 's/[ ]+/ /g'" | 
 |     ) | 
 |     sub_proc = subprocess.Popen( | 
 |         cmd_buf, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT | 
 |     ) | 
 |     out_buf, err_buf = sub_proc.communicate() | 
 |     shell_rc = sub_proc.returncode | 
 |     out_buf = out_buf.decode("utf-8") | 
 |  | 
 |     # Split the output by line. | 
 |     rows = out_buf.rstrip("\n").split("\n") | 
 |  | 
 |     # Initialize report dictionary. | 
 |     report = DotDict() | 
 |     for row in rows: | 
 |         # Process each row of mtr output. | 
 |         # Create a list of fields by splitting on space delimiter. | 
 |         row_list = row.split(" ") | 
 |         # Create dictionary for the row. | 
 |         row = DotDict() | 
 |         row["row_num"] = row_list[0].rstrip(".") | 
 |         row["host"] = row_list[1] | 
 |         row["loss"] = row_list[2].rstrip("%") | 
 |         row["snt"] = row_list[3] | 
 |         row["last"] = row_list[4] | 
 |         row["avg"] = row_list[5] | 
 |         row["best"] = row_list[6] | 
 |         row["wrst"] = row_list[7] | 
 |         row["stdev"] = row_list[8] | 
 |         report[row["host"]] = row | 
 |  | 
 |     # Return the full report as dictionary of dictionaries. | 
 |     return report | 
 |  | 
 |  | 
 | def get_mtr_row(host=""): | 
 |     r""" | 
 |     Run an mtr report and get a specified row and return it as a dictionary. | 
 |  | 
 |     Example result: | 
 |  | 
 |     row: | 
 |       row[row_num]:              2 | 
 |       row[host]:                 bmc-dummy-dnsname.com | 
 |       row[loss]:                 0.0 | 
 |       row[snt]:                  10 | 
 |       row[last]:                 0.5 | 
 |       row[avg]:                  0.5 | 
 |       row[best]:                 0.4 | 
 |       row[wrst]:                 0.7 | 
 |       row[stdev]:                0.1 | 
 |  | 
 |     Description of arguments: | 
 |     host   The DNS name or IP address to be passed to the mtr command as | 
 |            well as the indicating which row of the report to return. | 
 |     """ | 
 |  | 
 |     report = get_mtr_report(host) | 
 |  | 
 |     # The max length of host in output is 28 chars. | 
 |     row = [value for key, value in report.items() if host[0:28] in key][0] | 
 |  | 
 |     return row | 
 |  | 
 |  | 
 | def list_to_set(fru_list=""): | 
 |     r""" | 
 |     Pack the list into a set tuple and return. | 
 |  | 
 |     It may seem that this function is rather trivial. However, it simplifies | 
 |     the code and improves robot program readability and achieve the result | 
 |     required. | 
 |  | 
 |     Example result: | 
 |  | 
 |     set(['Version', 'PartNumber', 'SerialNumber', 'FieldReplaceable', | 
 |     'BuildDate', 'Present', 'Manufacturer', 'PrettyName', 'Cached', 'Model']) | 
 |  | 
 |     # Description of arguments. | 
 |     fru_list   List of FRU's elements. | 
 |     """ | 
 |     return set(fru_list) | 
 |  | 
 |  | 
 | def min_list_value(value_list): | 
 |     r""" | 
 |     Returns the element from the list with minimum value. | 
 |     """ | 
 |     return min(value_list) | 
 |  | 
 |  | 
 | def convert_lsb_to_msb(string): | 
 |     r""" | 
 |     Reverse given string (From LSB first to MSB first) and converts to HEX. | 
 |  | 
 |     Input string     0a 00 | 
 |     Return string    0a | 
 |     """ | 
 |     datalist = string.split(" ") | 
 |     new_list = datalist[::-1] | 
 |     new_string = "".join([str(element) for element in new_list]) | 
 |     return int(new_string, 16) | 
 |  | 
 |  | 
 | def add_prefix_to_string(string, prefix): | 
 |     r""" | 
 |     Add given prefix to the string and return string. | 
 |  | 
 |     Input string      0a 01 | 
 |     Return string     0x0a 0x01 | 
 |     """ | 
 |     prefix_string = "" | 
 |     data_list = string.strip().split(" ") | 
 |     for item in data_list: | 
 |         prefix_string += prefix + item + " " | 
 |     return prefix_string.strip() | 
 |  | 
 |  | 
 | def get_value_from_nested_dict(key, nested_dict): | 
 |     r""" | 
 |     Returns the key value from the nested dictionary. | 
 |  | 
 |     key               Key value of the dictionary to look up. | 
 |     nested_dict       Dictionary data. | 
 |     """ | 
 |     result = [] | 
 |     for k, v in nested_dict.items(): | 
 |         if k == key: | 
 |             result.append(v) | 
 |         elif isinstance(v, dict) and k != key: | 
 |             result += get_value_from_nested_dict(key, v) | 
 |  | 
 |     return result |