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