1#!/usr/bin/env python3 2 3r""" 4PLDM functions. 5""" 6 7import re 8import var_funcs as vf 9import func_args as fa 10import bmc_ssh_utils as bsu 11import json 12import random 13import string 14from robot.api import logger 15 16 17def pldmtool(option_string, **bsu_options): 18 19 r""" 20 Run pldmtool on the BMC with the caller's option string and return the result. 21 22 Example: 23 24 ${pldm_results}= Pldmtool base GetPLDMTypes 25 Rprint Vars pldm_results 26 27 pldm_results: 28 pldmtool base GetPLDMVersion -t 0 29 { 30 "Response": "1.0.0" 31 } 32 33 Description of argument(s): 34 option_string A string of options which are to be processed by the pldmtool command. 35 parse_results Parse the pldmtool results and return a dictionary rather than the raw 36 pldmtool output. 37 bsu_options Options to be passed directly to bmc_execute_command. See its prolog for 38 details. 39 """ 40 41 # This allows callers to specify arguments in python style (e.g. print_out=1 vs. print_out=${1}). 42 bsu_options = fa.args_to_objects(bsu_options) 43 44 stdout, stderr, rc = bsu.bmc_execute_command('pldmtool ' + option_string, **bsu_options) 45 if stderr: 46 return stderr 47 try: 48 return json.loads(stdout) 49 except ValueError: 50 return stdout 51 52 53def GetBIOSEnumAttributeOptionalValues(attr_val_table_data): 54 55 """ 56 From pldmtool GetBIOSTable of type AttributeValueTable get the dict of 57 attribute handle and its optional values for BIOS Enumeration type. 58 59 Description of argument(s): 60 attr_val_table_data pldmtool output from GetBIOSTable table type AttributeValueTable 61 e.g. 62 [{ 63 "AttributeHandle": 20, 64 "AttributeNameHandle": "23(pvm-pcie-error-inject)", 65 "AttributeType": "BIOSEnumeration", 66 "NumberOfPossibleValues": 2, 67 "PossibleValueStringHandle[0]": "3(Disabled)", 68 "PossibleValueStringHandle[1]": "4(Enabled)", 69 "NumberOfDefaultValues": 1, 70 "DefaultValueStringHandleIndex[0]": 1, 71 "StringHandle": "4(Enabled)" 72 }] 73 @return Dictionary of BIOS attribute and its value. 74 e.g. {'pvm_pcie_error_inject': ['Disabled', 'Enabled']} 75 """ 76 77 attr_val_data_dict = {} 78 for item in attr_val_table_data: 79 for attr in item: 80 if (attr == "NumberOfPossibleValues"): 81 value_list = [] 82 for i in range(0, int(item[attr])): 83 attr_values = item["PossibleValueStringHandle[" + str(i) + "]"] 84 value = re.search(r'\((.*?)\)', attr_values).group(1) 85 if value: 86 # Example: 87 # value = '"Power Off"' 88 if ' ' in value: 89 value = '"' + value + '"' 90 value_list.append(value) 91 else: 92 value_list.append('') 93 94 attr_handle = re.findall(r'\(.*?\)', item["AttributeNameHandle"]) 95 attr_val_data_dict[attr_handle[0][1:-1]] = value_list 96 return attr_val_data_dict 97 98 99def GetBIOSStrAndIntAttributeHandles(attr_type, attr_val_table_data): 100 101 """ 102 From pldmtool GetBIOSTable of type AttributeValueTable get the dict of 103 attribute handle and its values based on the attribute type. 104 105 Description of argument(s): 106 attr_type "BIOSInteger" or "BIOSString". 107 attr_val_table_data pldmtool output from GetBIOSTable table type AttributeValueTable. 108 109 @return Dict of BIOS attribute and its value based on attribute type. 110 111 """ 112 attr_val_int_dict = {} 113 attr_val_str_dict = {} 114 for item in attr_val_table_data: 115 value_dict = {} 116 attr_handle = re.findall(r'\(.*?\)', item["AttributeNameHandle"]) 117 # Example: 118 # {'vmi_if0_ipv4_prefix_length': {'UpperBound': 32, 'LowerBound': 0} 119 if (item["AttributeType"] == "BIOSInteger"): 120 value_dict["LowerBound"] = item["LowerBound"] 121 value_dict["UpperBound"] = item["UpperBound"] 122 attr_val_int_dict[attr_handle[0][1:-1]] = value_dict 123 # Example: 124 # {'vmi_if1_ipv4_ipaddr': {'MaximumStringLength': 15, 'MinimumStringLength': 7}} 125 elif (item["AttributeType"] == "BIOSString"): 126 value_dict["MinimumStringLength"] = item["MinimumStringLength"] 127 value_dict["MaximumStringLength"] = item["MaximumStringLength"] 128 attr_val_str_dict[attr_handle[0][1:-1]] = value_dict 129 130 if (attr_type == "BIOSInteger"): 131 return attr_val_int_dict 132 elif (attr_type == "BIOSString"): 133 return attr_val_str_dict 134 135 136def GetRandomBIOSIntAndStrValues(attr_name, count): 137 138 """ 139 Get random integer or string values for BIOS attribute values based on the count. 140 141 Description of argument(s): 142 attr_name Attribute name of BIOS attribute type Integer or string. 143 count Max length for BIOS attribute type Integer or string. 144 145 @return Random attribute value based on BIOS attribute type Integer 146 or string. 147 148 """ 149 attr_random_value = '' 150 151 # Example 152 # 12.13.14.15 153 if 'gateway' in attr_name: 154 attr_random_value = ".".join(map(str, (random.randint(0, 255) for _ in range(4)))) 155 # Example 156 # 11.11.11.11 157 elif 'ipaddr' in attr_name: 158 attr_random_value = ".".join(map(str, (random.randint(0, 255) for _ in range(4)))) 159 # Example 160 # E5YWEDWJJ 161 elif 'name' in attr_name: 162 data = string.ascii_uppercase + string.digits 163 attr_random_value = ''.join(random.choice(data) for _ in range(int(count))) 164 165 elif 'mfg_flags' in attr_name: 166 data = string.ascii_uppercase + string.digits 167 attr_random_value = ''.join(random.choice(data) for _ in range(int(count))) 168 169 elif 'hb_lid_ids' in attr_name: 170 attr_random_value = str(random.randint(0, int(count))) 171 172 else: 173 attr_random_value = random.randint(0, int(count)) 174 return attr_random_value 175 176 177def GetBIOSAttrOriginalValues(attr_val_table_data): 178 179 """ 180 From pldmtool GetBIOSTable of type AttributeValueTable get the dict of 181 attribute handle and its values. 182 183 Description of argument(s): 184 attr_val_table_data pldmtool output from GetBIOSTable table type AttributeValueTable. 185 186 @return Dict of BIOS attribute and its value. 187 188 """ 189 attr_val_data_dict = {} 190 for item in attr_val_table_data: 191 attr_handle = re.findall(r'\(.*?\)', item["AttributeNameHandle"]) 192 attr_name = attr_handle[0][1:-1] 193 194 command = "bios GetBIOSAttributeCurrentValueByHandle -a " + attr_name 195 value = pldmtool(command) 196 attr_val_data_dict[attr_name] = value["CurrentValue"] 197 if not value["CurrentValue"]: 198 if 'name' in attr_name: 199 attr_val_data_dict[attr_name] = '""' 200 elif 'hb_lid_ids' in attr_name: 201 attr_val_data_dict[attr_name] = '""' 202 203 return attr_val_data_dict 204 205 206def GetBIOSAttrDefaultValues(attr_val_table_data): 207 208 """ 209 From pldmtool GetBIOSTable of type AttributeValueTable get the dict of 210 attribute handle and its default attribute values. 211 212 Description of argument(s): 213 attr_val_table_data pldmtool output from GetBIOSTable table type AttributeValueTable. 214 215 @return Dict of BIOS attribute and its default attribute value. 216 217 """ 218 attr_val_data_dict = {} 219 for item in attr_val_table_data: 220 attr_handle = re.findall(r'\(.*?\)', item["AttributeNameHandle"]) 221 attr_name = attr_handle[0][1:-1] 222 223 if "DefaultString" in item: 224 attr_val_data_dict[attr_name] = item["DefaultString"] 225 if not item["DefaultString"]: 226 if 'name' in attr_name: 227 attr_val_data_dict[attr_name] = '""' 228 elif 'hb_lid_ids' in attr_name: 229 attr_val_data_dict[attr_name] = '""' 230 elif "DefaultValue" in item: 231 attr_val_data_dict[attr_name] = item["DefaultValue"] 232 elif "StringHandle" in item: 233 attr_default_value = re.findall(r'\(.*?\)', item["StringHandle"]) 234 attr_val_data_dict[attr_name] = attr_default_value[0][1:-1] 235 236 return attr_val_data_dict 237 238 239def GetNewValuesForAllBIOSAttrs(attr_table_data): 240 241 """ 242 Get a new set of values for all attributes in Attribute Table. 243 244 Description of argument(s): 245 attr_table_data pldmtool output from GetBIOSTable table type AttributeValueTable. 246 247 @return Dict of BIOS attribute and new attribute value. 248 249 """ 250 existing_data = GetBIOSAttrOriginalValues(attr_table_data) 251 logger.info(existing_data) 252 string_attr_data = GetBIOSStrAndIntAttributeHandles("BIOSString", attr_table_data) 253 logger.info(string_attr_data) 254 int_attr_data = GetBIOSStrAndIntAttributeHandles("BIOSInteger", attr_table_data) 255 logger.info(int_attr_data) 256 enum_attr_data = GetBIOSEnumAttributeOptionalValues(attr_table_data) 257 logger.info(enum_attr_data) 258 259 attr_random_data = {} 260 temp_list = enum_attr_data.copy() 261 for attr in enum_attr_data: 262 try: 263 temp_list[attr].remove(existing_data[attr]) 264 except ValueError: 265 try: 266 # The data values have a double quote in them. 267 # Eg: '"IBM I"' instead of just 'IBM I' 268 data = '"' + str(existing_data[attr]) + '"' 269 temp_list[attr].remove(data) 270 except ValueError: 271 logger.info("Unable to remove the existing value " 272 + str(data) + " from list " + str(temp_list[attr])) 273 valid_values = temp_list[attr][:] 274 value = random.choice(valid_values) 275 attr_random_data[attr] = value.strip('"') 276 logger.info("Values generated for enumeration type attributes") 277 278 for attr in string_attr_data: 279 # Iterating to make sure we have a different value 280 # other than the existing value. 281 for iter in range(5): 282 random_val = GetRandomBIOSIntAndStrValues(attr, string_attr_data[attr]["MaximumStringLength"]) 283 if random_val != existing_data[attr]: 284 break 285 attr_random_data[attr] = random_val.strip('"') 286 logger.info("Values generated for string type attributes") 287 288 for attr in int_attr_data: 289 for iter in range(5): 290 random_val = GetRandomBIOSIntAndStrValues(attr, int_attr_data[attr]["UpperBound"]) 291 if random_val != existing_data[attr]: 292 break 293 attr_random_data[attr] = random_val 294 logger.info("Values generated for integer type attributes") 295 296 return attr_random_data 297