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 203 # Split the output by line. 204 rows = out_buf.rstrip("\n").split("\n") 205 206 # Initialize report dictionary. 207 report = DotDict() 208 for row in rows: 209 # Process each row of mtr output. 210 # Create a list of fields by splitting on space delimiter. 211 row_list = row.split(" ") 212 # Create dictionary for the row. 213 row = DotDict() 214 row["row_num"] = row_list[0].rstrip(".") 215 row["host"] = row_list[1] 216 row["loss"] = row_list[2].rstrip("%") 217 row["snt"] = row_list[3] 218 row["last"] = row_list[4] 219 row["avg"] = row_list[5] 220 row["best"] = row_list[6] 221 row["wrst"] = row_list[7] 222 row["stdev"] = row_list[8] 223 report[row["host"]] = row 224 225 # Return the full report as dictionary of dictionaries. 226 return report 227 228 229def get_mtr_row(host=""): 230 r""" 231 Run an mtr report and get a specified row and return it as a dictionary. 232 233 Example result: 234 235 row: 236 row[row_num]: 2 237 row[host]: bmc-dummy-dnsname.com 238 row[loss]: 0.0 239 row[snt]: 10 240 row[last]: 0.5 241 row[avg]: 0.5 242 row[best]: 0.4 243 row[wrst]: 0.7 244 row[stdev]: 0.1 245 246 Description of arguments: 247 host The DNS name or IP address to be passed to the mtr command as 248 well as the indicating which row of the report to return. 249 """ 250 251 report = get_mtr_report(host) 252 253 # The max length of host in output is 28 chars. 254 row = [value for key, value in report.items() if host[0:28] in key][0] 255 256 return row 257 258 259def list_to_set(fru_list=""): 260 r""" 261 Pack the list into a set tuple and return. 262 263 It may seem that this function is rather trivial. However, it simplifies 264 the code and improves robot program readability and achieve the result 265 required. 266 267 Example result: 268 269 set(['Version', 'PartNumber', 'SerialNumber', 'FieldReplaceable', 270 'BuildDate', 'Present', 'Manufacturer', 'PrettyName', 'Cached', 'Model']) 271 272 # Description of arguments. 273 fru_list List of FRU's elements. 274 """ 275 return set(fru_list) 276 277 278def min_list_value(value_list): 279 r""" 280 Returns the element from the list with minimum value. 281 """ 282 return min(value_list) 283 284 285def convert_lsb_to_msb(string): 286 r""" 287 Reverse given string (From LSB first to MSB first) and converts to HEX. 288 289 Input string 0a 00 290 Return string 0a 291 """ 292 datalist = string.split(" ") 293 new_list = datalist[::-1] 294 new_string = "".join([str(element) for element in new_list]) 295 return int(new_string, 16) 296 297 298def add_prefix_to_string(string, prefix): 299 r""" 300 Add given prefix to the string and return string. 301 302 Input string 0a 01 303 Return string 0x0a 0x01 304 """ 305 prefix_string = "" 306 data_list = string.strip().split(" ") 307 for item in data_list: 308 prefix_string += prefix + item + " " 309 return prefix_string.strip() 310 311 312def get_value_from_nested_dict(key, nested_dict): 313 r""" 314 Returns the key value from the nested dictionary. 315 316 key Key value of the dictionary to look up. 317 nested_dict Dictionary data. 318 """ 319 result = [] 320 for k, v in nested_dict.items(): 321 if k == key: 322 result.append(v) 323 elif isinstance(v, dict) and k != key: 324 result += get_value_from_nested_dict(key, v) 325 326 return result 327