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