| #!/usr/bin/env python3 | 
 |  | 
 | r""" | 
 | PLDM functions. | 
 | """ | 
 |  | 
 | import json | 
 | import random | 
 | import re | 
 | import string | 
 |  | 
 | import bmc_ssh_utils as bsu | 
 | import func_args as fa | 
 | import var_funcs as vf | 
 | from robot.api import logger | 
 |  | 
 |  | 
 | 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" | 
 |       } | 
 |  | 
 |     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, ignore_err=1 | 
 |     ) | 
 |     if stderr: | 
 |         return stderr | 
 |     try: | 
 |         return json.loads(stdout) | 
 |     except ValueError: | 
 |         return stdout | 
 |  | 
 |  | 
 | def GetBIOSEnumAttributeOptionalValues(attr_val_table_data): | 
 |     """ | 
 |     From pldmtool GetBIOSTable of type AttributeValueTable get the dict of | 
 |     attribute handle and its optional values for BIOS Enumeration type. | 
 |  | 
 |     Description of argument(s): | 
 |     attr_val_table_data     pldmtool output from GetBIOSTable table type AttributeValueTable | 
 |                             e.g. | 
 |                             [{ | 
 |                                   "AttributeHandle": 20, | 
 |                                   "AttributeNameHandle": "23(pvm-pcie-error-inject)", | 
 |                                   "AttributeType": "BIOSEnumeration", | 
 |                                   "NumberOfPossibleValues": 2, | 
 |                                   "PossibleValueStringHandle[0]": "3(Disabled)", | 
 |                                   "PossibleValueStringHandle[1]": "4(Enabled)", | 
 |                                   "NumberOfDefaultValues": 1, | 
 |                                   "DefaultValueStringHandleIndex[0]": 1, | 
 |                                   "StringHandle": "4(Enabled)" | 
 |                              }] | 
 |     @return                  Dictionary of BIOS attribute and its value. | 
 |                              e.g. {'pvm_pcie_error_inject': ['Disabled', 'Enabled']} | 
 |     """ | 
 |  | 
 |     attr_val_data_dict = {} | 
 |     for item in attr_val_table_data: | 
 |         for attr in item: | 
 |             if attr == "NumberOfPossibleValues": | 
 |                 value_list = [] | 
 |                 for i in range(0, int(item[attr])): | 
 |                     attr_values = item[ | 
 |                         "PossibleValueStringHandle[" + str(i) + "]" | 
 |                     ] | 
 |                     value = re.search(r"\((.*?)\)", attr_values).group(1) | 
 |                     if value: | 
 |                         value_list.append(value) | 
 |                     else: | 
 |                         value_list.append("") | 
 |  | 
 |                 attr_handle = re.findall( | 
 |                     r"\(.*?\)", item["AttributeNameHandle"] | 
 |                 ) | 
 |                 attr_val_data_dict[attr_handle[0][1:-1]] = value_list | 
 |     return attr_val_data_dict | 
 |  | 
 |  | 
 | def GetBIOSStrAndIntAttributeHandles(attr_type, attr_val_table_data): | 
 |     """ | 
 |     From pldmtool GetBIOSTable of type AttributeValueTable get the dict of | 
 |     attribute handle and its values based on the attribute type. | 
 |  | 
 |     Description of argument(s): | 
 |     attr_type               "BIOSInteger" or "BIOSString". | 
 |     attr_val_table_data     pldmtool output from GetBIOSTable table type AttributeValueTable. | 
 |  | 
 |     @return                 Dict of BIOS attribute and its value based on attribute type. | 
 |  | 
 |     """ | 
 |     attr_val_int_dict = {} | 
 |     attr_val_str_dict = {} | 
 |     for item in attr_val_table_data: | 
 |         value_dict = {} | 
 |         attr_handle = re.findall(r"\(.*?\)", item["AttributeNameHandle"]) | 
 |         # Example: | 
 |         # {'vmi_if0_ipv4_prefix_length': {'UpperBound': 32, 'LowerBound': 0} | 
 |         if item["AttributeType"] == "BIOSInteger": | 
 |             value_dict["LowerBound"] = item["LowerBound"] | 
 |             value_dict["UpperBound"] = item["UpperBound"] | 
 |             attr_val_int_dict[attr_handle[0][1:-1]] = value_dict | 
 |         # Example: | 
 |         # {'vmi_if1_ipv4_ipaddr': {'MaximumStringLength': 15, 'MinimumStringLength': 7}} | 
 |         elif item["AttributeType"] == "BIOSString": | 
 |             value_dict["MinimumStringLength"] = item["MinimumStringLength"] | 
 |             value_dict["MaximumStringLength"] = item["MaximumStringLength"] | 
 |             attr_val_str_dict[attr_handle[0][1:-1]] = value_dict | 
 |  | 
 |     if attr_type == "BIOSInteger": | 
 |         return attr_val_int_dict | 
 |     if attr_type == "BIOSString": | 
 |         return attr_val_str_dict | 
 |  | 
 |     return None | 
 |  | 
 |  | 
 | def GetRandomBIOSIntAndStrValues(attr_name, count): | 
 |     """ | 
 |     Get random integer or string values for BIOS attribute values based on the count. | 
 |  | 
 |     Description of argument(s): | 
 |     attr_name               Attribute name of BIOS attribute type Integer or string. | 
 |     count                   Max length for BIOS attribute type Integer or string. | 
 |  | 
 |     @return                 Random attribute value based on BIOS attribute type Integer | 
 |                             or string. | 
 |  | 
 |     """ | 
 |     attr_random_value = "" | 
 |  | 
 |     # Example | 
 |     # 12.13.14.15 | 
 |     if "gateway" in attr_name: | 
 |         attr_random_value = ".".join( | 
 |             map(str, (random.randint(0, 255) for _ in range(4))) | 
 |         ) | 
 |     # Example | 
 |     # 11.11.11.11 | 
 |     elif "ipaddr" in attr_name: | 
 |         attr_random_value = ".".join( | 
 |             map(str, (random.randint(0, 255) for _ in range(4))) | 
 |         ) | 
 |     # Example | 
 |     # E5YWEDWJJ | 
 |     elif "name" in attr_name: | 
 |         data = string.ascii_uppercase + string.digits | 
 |         attr_random_value = "".join( | 
 |             random.choice(data) for _ in range(int(count)) | 
 |         ) | 
 |  | 
 |     elif "mfg_flags" in attr_name: | 
 |         data = string.ascii_uppercase + string.digits | 
 |         attr_random_value = "".join( | 
 |             random.choice(data) for _ in range(int(count)) | 
 |         ) | 
 |  | 
 |     elif "hb_lid_ids" in attr_name: | 
 |         attr_random_value = str(random.randint(0, int(count))) | 
 |  | 
 |     else: | 
 |         attr_random_value = random.randint(0, int(count)) | 
 |     return attr_random_value | 
 |  | 
 |  | 
 | def GetBIOSAttrOriginalValues(attr_val_table_data): | 
 |     """ | 
 |     From pldmtool GetBIOSTable of type AttributeValueTable get the dict of | 
 |     attribute handle and its values. | 
 |  | 
 |     Description of argument(s): | 
 |     attr_val_table_data     pldmtool output from GetBIOSTable table type AttributeValueTable. | 
 |  | 
 |     @return                 Dict of BIOS attribute and its value. | 
 |  | 
 |     """ | 
 |     attr_val_data_dict = {} | 
 |     for item in attr_val_table_data: | 
 |         attr_handle = re.findall(r"\(.*?\)", item["AttributeNameHandle"]) | 
 |         attr_name = attr_handle[0][1:-1] | 
 |  | 
 |         # Exclude BIOS attribute which are ReadOnly. | 
 |         if "ReadOnly" not in item["AttributeType"]: | 
 |             command = ( | 
 |                 "bios GetBIOSAttributeCurrentValueByHandle -a " + attr_name | 
 |             ) | 
 |             value = pldmtool(command) | 
 |             if "error" in value: | 
 |                 print("Ignore BIOS attribute which throws error...") | 
 |                 pass | 
 |             elif not value["CurrentValue"]: | 
 |                 if "name" in attr_name: | 
 |                     attr_val_data_dict[attr_name] = '""' | 
 |                 elif "hb_lid_ids" in attr_name: | 
 |                     attr_val_data_dict[attr_name] = '""' | 
 |             else: | 
 |                 attr_val_data_dict[attr_name] = value["CurrentValue"] | 
 |  | 
 |     return attr_val_data_dict | 
 |  | 
 |  | 
 | def GetBIOSAttrDefaultValues(attr_val_table_data): | 
 |     """ | 
 |     From pldmtool GetBIOSTable of type AttributeValueTable get the dict of | 
 |     attribute handle and its default attribute values. | 
 |  | 
 |     Description of argument(s): | 
 |     attr_val_table_data     pldmtool output from GetBIOSTable table type AttributeValueTable. | 
 |  | 
 |     @return                 Dict of BIOS attribute and its default attribute value. | 
 |  | 
 |     """ | 
 |     attr_val_data_dict = {} | 
 |     for item in attr_val_table_data: | 
 |         attr_handle = re.findall(r"\(.*?\)", item["AttributeNameHandle"]) | 
 |         attr_name = attr_handle[0][1:-1] | 
 |  | 
 |         if "DefaultString" in item: | 
 |             attr_val_data_dict[attr_name] = item["DefaultString"] | 
 |             if not item["DefaultString"]: | 
 |                 if "name" in attr_name: | 
 |                     attr_val_data_dict[attr_name] = '""' | 
 |                 elif "hb_lid_ids" in attr_name: | 
 |                     attr_val_data_dict[attr_name] = '""' | 
 |         elif "DefaultValue" in item: | 
 |             attr_val_data_dict[attr_name] = item["DefaultValue"] | 
 |         elif "StringHandle" in item: | 
 |             attr_default_value = re.findall(r"\(.*?\)", item["StringHandle"]) | 
 |             attr_val_data_dict[attr_name] = attr_default_value[0][1:-1] | 
 |  | 
 |     return attr_val_data_dict | 
 |  | 
 |  | 
 | def GetNewValuesForAllBIOSAttrs(attr_table_data): | 
 |     """ | 
 |     Get a new set of values for all attributes in Attribute Table. | 
 |  | 
 |     Description of argument(s): | 
 |     attr_table_data         pldmtool output from GetBIOSTable table type AttributeValueTable. | 
 |  | 
 |     @return                 Dict of BIOS attribute and new attribute value. | 
 |  | 
 |     """ | 
 |     existing_data = GetBIOSAttrOriginalValues(attr_table_data) | 
 |     logger.info(existing_data) | 
 |     string_attr_data = GetBIOSStrAndIntAttributeHandles( | 
 |         "BIOSString", attr_table_data | 
 |     ) | 
 |     logger.info(string_attr_data) | 
 |     int_attr_data = GetBIOSStrAndIntAttributeHandles( | 
 |         "BIOSInteger", attr_table_data | 
 |     ) | 
 |     logger.info(int_attr_data) | 
 |     enum_attr_data = GetBIOSEnumAttributeOptionalValues(attr_table_data) | 
 |     logger.info(enum_attr_data) | 
 |  | 
 |     attr_random_data = {} | 
 |     temp_list = enum_attr_data.copy() | 
 |     for attr in enum_attr_data: | 
 |         try: | 
 |             temp_list[attr].remove(existing_data[attr]) | 
 |         except ValueError: | 
 |             try: | 
 |                 # The data values have a double quote in them. | 
 |                 data = '"' + str(existing_data[attr]) + '"' | 
 |                 temp_list[attr].remove(data) | 
 |             except ValueError: | 
 |                 logger.info( | 
 |                     "Unable to remove the existing value " | 
 |                     + str(data) | 
 |                     + " from list " | 
 |                     + str(temp_list[attr]) | 
 |                 ) | 
 |         valid_values = temp_list[attr][:] | 
 |         value = random.choice(valid_values) | 
 |         attr_random_data[attr] = value.strip('"') | 
 |     logger.info("Values generated for enumeration type attributes") | 
 |  | 
 |     for attr in string_attr_data: | 
 |         # Iterating to make sure we have a different value | 
 |         # other than the existing value. | 
 |         for iter in range(5): | 
 |             random_val = GetRandomBIOSIntAndStrValues( | 
 |                 attr, string_attr_data[attr]["MaximumStringLength"] | 
 |             ) | 
 |             if random_val != existing_data[attr]: | 
 |                 break | 
 |         if isinstance(random_val, str): | 
 |             attr_random_data[attr] = random_val.strip('"') | 
 |     logger.info("Values generated for string type attributes") | 
 |  | 
 |     for attr in int_attr_data: | 
 |         for iter in range(5): | 
 |             random_val = GetRandomBIOSIntAndStrValues( | 
 |                 attr, int_attr_data[attr]["UpperBound"] | 
 |             ) | 
 |             if random_val != existing_data[attr]: | 
 |                 break | 
 |         attr_random_data[attr] = random_val | 
 |     logger.info("Values generated for integer type attributes") | 
 |  | 
 |     return attr_random_data |