1#!/usr/bin/env python3 -u 2 3r""" 4Generic utility functions. 5""" 6import imp 7import random 8import string 9import subprocess 10 11from robot.libraries.BuiltIn import BuiltIn 12from robot.utils import DotDict 13 14 15def random_mac(): 16 r""" 17 Return random mac address in the following format. 18 Example: 00:01:6C:80:02:78 19 """ 20 return ":".join( 21 map( 22 lambda x: "%02x" % x, 23 (random.randint(0x00, 0xFF) for _ in range(6)), 24 ) 25 ) 26 27 28def random_ip(): 29 r""" 30 Return random ip address in the following format. 31 Example: 9.3.128.100 32 """ 33 return ".".join(map(str, (random.randint(0, 255) for _ in range(4)))) 34 35 36def get_sensor(module_name, value): 37 r""" 38 Return sensor matched ID name. 39 """ 40 m = imp.load_source("module.name", module_name) 41 42 for i in m.ID_LOOKUP["SENSOR"]: 43 if m.ID_LOOKUP["SENSOR"][i] == value: 44 return i 45 46 return 0xFF 47 48 49def get_inventory_sensor(module_name, value): 50 r""" 51 Return sensor matched ID name from inventory. 52 """ 53 m = imp.load_source("module.name", module_name) 54 55 value = string.replace(value, m.INVENTORY_ROOT, "<inventory_root>") 56 57 for i in m.ID_LOOKUP["SENSOR"]: 58 if m.ID_LOOKUP["SENSOR"][i] == value: 59 return i 60 61 return 0xFF 62 63 64################################################################ 65# This will return the URI's of the FRU type 66# 67# i.e. get_inventory_list('../data/Palmetto.py') 68# 69# [/org/openbmc/inventory/system/chassis/motherboard/cpu0/core0, 70# /org/openbmc/inventory/system/chassis/motherboard/dimm0] 71################################################################ 72def get_inventory_list(module_name): 73 r""" 74 Return all FRU URI(s) list available from inventory. 75 """ 76 77 inventory_list = [] 78 m = imp.load_source("module.name", module_name) 79 80 for i in m.ID_LOOKUP["FRU"]: 81 s = m.ID_LOOKUP["FRU"][i] 82 s = s.replace("<inventory_root>", m.INVENTORY_ROOT) 83 inventory_list.append(s) 84 85 return inventory_list 86 87 88################################################################ 89# This will return the URI's of the FRU type 90# 91# i.e. get_inventory_fru_type_list('../data/Witherspoon.py', 'CPU') 92# 93# [/org/openbmc/inventory/system/chassis/motherboard/cpu0, 94# /org/openbmc/inventory/system/chassis/motherboard/cpu1] 95################################################################ 96def get_inventory_fru_type_list(module_name, fru): 97 r""" 98 Return FRU URI(s) list of a given type from inventory. 99 """ 100 inventory_list = [] 101 m = imp.load_source("module.name", module_name) 102 103 for i in m.FRU_INSTANCES.keys(): 104 if m.FRU_INSTANCES[i]["fru_type"] == fru: 105 s = i.replace("<inventory_root>", m.INVENTORY_ROOT) 106 inventory_list.append(s) 107 108 return inventory_list 109 110 111################################################################ 112# This will return the URI's of the FRU type that contain VPD 113# 114# i.e. get_vpd_inventory_list('../data/Palmetto.py', 'DIMM') 115# 116# [/org/openbmc/inventory/system/chassis/motherboard/dimm0, 117# /org/openbmc/inventory/system/chassis/motherboard/dimm1] 118################################################################ 119def get_vpd_inventory_list(module_name, fru): 120 r""" 121 Return VPD URI(s) list of a FRU type from inventory. 122 """ 123 inventory_list = [] 124 m = imp.load_source("module.name", module_name) 125 126 for i in m.ID_LOOKUP["FRU_STR"]: 127 x = m.ID_LOOKUP["FRU_STR"][i] 128 129 if m.FRU_INSTANCES[x]["fru_type"] == fru: 130 s = x.replace("<inventory_root>", m.INVENTORY_ROOT) 131 inventory_list.append(s) 132 133 return inventory_list 134 135 136def call_keyword(keyword): 137 r""" 138 Return result of the execute robot keyword. 139 """ 140 return BuiltIn().run_keyword(keyword) 141 142 143def main(): 144 r""" 145 Python main func call. 146 """ 147 print(get_vpd_inventory_list("../data/Palmetto.py", "DIMM")) 148 149 150if __name__ == "__main__": 151 main() 152 153 154def get_mtr_report(host=""): 155 r""" 156 Get an mtr report and return it as a dictionary of dictionaries. 157 158 The key for the top level dictionary will be the host DNS name. The key 159 for the next level dictionary will be the field of a given row of the 160 report. 161 162 Example result: 163 164 report: 165 report[host_dummy-dnsname.com]: 166 report[host_dummy-dnsname.com][row_num]: 1 167 report[host_dummy-dnsname.com][host]: host_dummy-dnsname.com 168 report[host_dummy-dnsname.com][loss]: 0.0 169 report[host_dummy-dnsname.com][snt]: 10 170 report[host_dummy-dnsname.com][last]: 0.2 171 report[host_dummy-dnsname.com][avg]: 3.5 172 report[host_dummy-dnsname.com][best]: 0.2 173 report[host_dummy-dnsname.com][wrst]: 32.5 174 report[host_dummy-dnsname.com][stdev]: 10.2 175 report[bmc-dummy-dnsname.com]: 176 report[bmc-dummy-dnsname.com][row_num]: 2 177 report[bmc-dummy-dnsname.com][host]: bmc-dummy-dnsname.com 178 report[bmc-dummy-dnsname.com][loss]: 0.0 179 report[bmc-dummy-dnsname.com][snt]: 10 180 report[bmc-dummy-dnsname.com][last]: 0.5 181 report[bmc-dummy-dnsname.com][avg]: 0.5 182 report[bmc-dummy-dnsname.com][best]: 0.5 183 report[bmc-dummy-dnsname.com][wrst]: 0.5 184 report[bmc-dummy-dnsname.com][stdev]: 0.0 185 186 Description of arguments: 187 host The DNS name or IP address to be passed to the mtr command. 188 """ 189 190 # Run the mtr command. Exclude the header line. Trim leading space from 191 # each line. Change all multiple spaces delims to single space delims. 192 cmd_buf = ( 193 "mtr --report " 194 + host 195 + " | tail -n +2 | sed -r -e 's/^[ ]+//g' -e 's/[ ]+/ /g'" 196 ) 197 sub_proc = subprocess.Popen( 198 cmd_buf, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT 199 ) 200 out_buf, err_buf = sub_proc.communicate() 201 shell_rc = sub_proc.returncode 202 out_buf = out_buf.decode("utf-8") 203 204 # Split the output by line. 205 rows = out_buf.rstrip("\n").split("\n") 206 207 # Initialize report dictionary. 208 report = DotDict() 209 for row in rows: 210 # Process each row of mtr output. 211 # Create a list of fields by splitting on space delimiter. 212 row_list = row.split(" ") 213 # Create dictionary for the row. 214 row = DotDict() 215 row["row_num"] = row_list[0].rstrip(".") 216 row["host"] = row_list[1] 217 row["loss"] = row_list[2].rstrip("%") 218 row["snt"] = row_list[3] 219 row["last"] = row_list[4] 220 row["avg"] = row_list[5] 221 row["best"] = row_list[6] 222 row["wrst"] = row_list[7] 223 row["stdev"] = row_list[8] 224 report[row["host"]] = row 225 226 # Return the full report as dictionary of dictionaries. 227 return report 228 229 230def get_mtr_row(host=""): 231 r""" 232 Run an mtr report and get a specified row and return it as a dictionary. 233 234 Example result: 235 236 row: 237 row[row_num]: 2 238 row[host]: bmc-dummy-dnsname.com 239 row[loss]: 0.0 240 row[snt]: 10 241 row[last]: 0.5 242 row[avg]: 0.5 243 row[best]: 0.4 244 row[wrst]: 0.7 245 row[stdev]: 0.1 246 247 Description of arguments: 248 host The DNS name or IP address to be passed to the mtr command as 249 well as the indicating which row of the report to return. 250 """ 251 252 report = get_mtr_report(host) 253 254 # The max length of host in output is 28 chars. 255 row = [value for key, value in report.items() if host[0:28] in key][0] 256 257 return row 258 259 260def list_to_set(fru_list=""): 261 r""" 262 Pack the list into a set tuple and return. 263 264 It may seem that this function is rather trivial. However, it simplifies 265 the code and improves robot program readability and achieve the result 266 required. 267 268 Example result: 269 270 set(['Version', 'PartNumber', 'SerialNumber', 'FieldReplaceable', 271 'BuildDate', 'Present', 'Manufacturer', 'PrettyName', 'Cached', 'Model']) 272 273 # Description of arguments. 274 fru_list List of FRU's elements. 275 """ 276 return set(fru_list) 277 278 279def min_list_value(value_list): 280 r""" 281 Returns the element from the list with minimum value. 282 """ 283 return min(value_list) 284 285 286def convert_lsb_to_msb(string): 287 r""" 288 Reverse given string (From LSB first to MSB first) and converts to HEX. 289 290 Input string 0a 00 291 Return string 0a 292 """ 293 datalist = string.split(" ") 294 new_list = datalist[::-1] 295 new_string = "".join([str(element) for element in new_list]) 296 return int(new_string, 16) 297 298 299def add_prefix_to_string(string, prefix): 300 r""" 301 Add given prefix to the string and return string. 302 303 Input string 0a 01 304 Return string 0x0a 0x01 305 """ 306 prefix_string = "" 307 data_list = string.strip().split(" ") 308 for item in data_list: 309 prefix_string += prefix + item + " " 310 return prefix_string.strip() 311 312 313def get_value_from_nested_dict(key, nested_dict): 314 r""" 315 Returns the key value from the nested dictionary. 316 317 key Key value of the dictionary to look up. 318 nested_dict Dictionary data. 319 """ 320 result = [] 321 for k, v in nested_dict.items(): 322 if k == key: 323 result.append(v) 324 elif isinstance(v, dict) and k != key: 325 result += get_value_from_nested_dict(key, v) 326 327 return result 328