blob: 8e6ddc53cf94632da15a22a18bee1bdc1bbe41de [file] [log] [blame]
George Keishinge7e91712021-09-03 11:28:44 -05001#!/usr/bin/env python3 -u
George Keishingd9b3e162022-08-18 23:28:35 -05002
3r"""
4Generic utility functions.
5"""
Brian Ma139f1da2024-10-18 13:34:14 +08006import importlib.util
George Keishinge635ddc2022-12-08 07:38:02 -06007import random
Patrick Williams20f38712022-12-08 06:18:26 -06008import string
Michael Walsh8b270ec2017-01-31 12:07:08 -06009import subprocess
Patrick Williams20f38712022-12-08 06:18:26 -060010
George Keishingd9b3e162022-08-18 23:28:35 -050011from robot.libraries.BuiltIn import BuiltIn
Michael Walsh8b270ec2017-01-31 12:07:08 -060012from robot.utils import DotDict
13
Chris Austenb29d2e82016-06-07 12:25:35 -050014
Brian Ma139f1da2024-10-18 13:34:14 +080015def load_source(name, module_path):
16 r"""
17 import util to replace deprecated imp.load_source
18 """
19 spec = importlib.util.spec_from_file_location(name, module_path)
20 module = importlib.util.module_from_spec(spec)
21 spec.loader.exec_module(module)
22 return module
23
24
Rahul Maheshwari757d80c2016-10-17 01:09:55 -050025def random_mac():
26 r"""
27 Return random mac address in the following format.
28 Example: 00:01:6C:80:02:78
29 """
Patrick Williams20f38712022-12-08 06:18:26 -060030 return ":".join(
31 map(
32 lambda x: "%02x" % x,
33 (random.randint(0x00, 0xFF) for _ in range(6)),
34 )
35 )
Gunnar Mills096cd562018-03-26 10:19:12 -050036
Rahul Maheshwari757d80c2016-10-17 01:09:55 -050037
38def random_ip():
39 r"""
40 Return random ip address in the following format.
41 Example: 9.3.128.100
42 """
Patrick Williams20f38712022-12-08 06:18:26 -060043 return ".".join(map(str, (random.randint(0, 255) for _ in range(4))))
Gunnar Mills096cd562018-03-26 10:19:12 -050044
Chris Austenb29d2e82016-06-07 12:25:35 -050045
46def get_sensor(module_name, value):
George Keishingd9b3e162022-08-18 23:28:35 -050047 r"""
48 Return sensor matched ID name.
49 """
Brian Ma139f1da2024-10-18 13:34:14 +080050 m = load_source("module.name", module_name)
Chris Austenb29d2e82016-06-07 12:25:35 -050051
Patrick Williams20f38712022-12-08 06:18:26 -060052 for i in m.ID_LOOKUP["SENSOR"]:
53 if m.ID_LOOKUP["SENSOR"][i] == value:
Gunnar Millsbb398ac2016-11-14 11:50:22 -060054 return i
Chris Austenb29d2e82016-06-07 12:25:35 -050055
Gunnar Millsbb398ac2016-11-14 11:50:22 -060056 return 0xFF
57
Chris Austenb29d2e82016-06-07 12:25:35 -050058
Gunnar Mills096cd562018-03-26 10:19:12 -050059def get_inventory_sensor(module_name, value):
George Keishingd9b3e162022-08-18 23:28:35 -050060 r"""
61 Return sensor matched ID name from inventory.
62 """
Brian Ma139f1da2024-10-18 13:34:14 +080063 m = load_source("module.name", module_name)
Chris Austenb29d2e82016-06-07 12:25:35 -050064
Patrick Williams20f38712022-12-08 06:18:26 -060065 value = string.replace(value, m.INVENTORY_ROOT, "<inventory_root>")
Chris Austenb29d2e82016-06-07 12:25:35 -050066
Patrick Williams20f38712022-12-08 06:18:26 -060067 for i in m.ID_LOOKUP["SENSOR"]:
68 if m.ID_LOOKUP["SENSOR"][i] == value:
Gunnar Millsbb398ac2016-11-14 11:50:22 -060069 return i
Chris Austenb29d2e82016-06-07 12:25:35 -050070
Gunnar Millsbb398ac2016-11-14 11:50:22 -060071 return 0xFF
Chris Austenb29d2e82016-06-07 12:25:35 -050072
73
74################################################################
Gunnar Millsbb398ac2016-11-14 11:50:22 -060075# This will return the URI's of the FRU type
Chris Austenb29d2e82016-06-07 12:25:35 -050076#
77# i.e. get_inventory_list('../data/Palmetto.py')
78#
George Keishingd9b3e162022-08-18 23:28:35 -050079# [/org/openbmc/inventory/system/chassis/motherboard/cpu0/core0,
Chris Austenb29d2e82016-06-07 12:25:35 -050080# /org/openbmc/inventory/system/chassis/motherboard/dimm0]
81################################################################
82def get_inventory_list(module_name):
George Keishingd9b3e162022-08-18 23:28:35 -050083 r"""
84 Return all FRU URI(s) list available from inventory.
85 """
Chris Austenb29d2e82016-06-07 12:25:35 -050086
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -050087 inventory_list = []
Brian Ma139f1da2024-10-18 13:34:14 +080088 m = load_source("module.name", module_name)
Chris Austenb29d2e82016-06-07 12:25:35 -050089
Patrick Williams20f38712022-12-08 06:18:26 -060090 for i in m.ID_LOOKUP["FRU"]:
91 s = m.ID_LOOKUP["FRU"][i]
92 s = s.replace("<inventory_root>", m.INVENTORY_ROOT)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -050093 inventory_list.append(s)
Gunnar Millsbb398ac2016-11-14 11:50:22 -060094
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -050095 return inventory_list
Chris Austenb29d2e82016-06-07 12:25:35 -050096
97
98################################################################
Gunnar Millsbb398ac2016-11-14 11:50:22 -060099# This will return the URI's of the FRU type
Chris Austenb29d2e82016-06-07 12:25:35 -0500100#
George Keishingbe3cdfd2018-08-28 00:00:06 -0500101# i.e. get_inventory_fru_type_list('../data/Witherspoon.py', 'CPU')
Chris Austenb29d2e82016-06-07 12:25:35 -0500102#
George Keishingd9b3e162022-08-18 23:28:35 -0500103# [/org/openbmc/inventory/system/chassis/motherboard/cpu0,
104# /org/openbmc/inventory/system/chassis/motherboard/cpu1]
Chris Austenb29d2e82016-06-07 12:25:35 -0500105################################################################
Gunnar Mills096cd562018-03-26 10:19:12 -0500106def get_inventory_fru_type_list(module_name, fru):
George Keishingd9b3e162022-08-18 23:28:35 -0500107 r"""
108 Return FRU URI(s) list of a given type from inventory.
109 """
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500110 inventory_list = []
Brian Ma139f1da2024-10-18 13:34:14 +0800111 m = load_source("module.name", module_name)
Chris Austenb29d2e82016-06-07 12:25:35 -0500112
Gunnar Millsbb398ac2016-11-14 11:50:22 -0600113 for i in m.FRU_INSTANCES.keys():
Patrick Williams20f38712022-12-08 06:18:26 -0600114 if m.FRU_INSTANCES[i]["fru_type"] == fru:
115 s = i.replace("<inventory_root>", m.INVENTORY_ROOT)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500116 inventory_list.append(s)
Gunnar Millsbb398ac2016-11-14 11:50:22 -0600117
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500118 return inventory_list
Chris Austenb29d2e82016-06-07 12:25:35 -0500119
120
121################################################################
122# This will return the URI's of the FRU type that contain VPD
123#
124# i.e. get_vpd_inventory_list('../data/Palmetto.py', 'DIMM')
125#
126# [/org/openbmc/inventory/system/chassis/motherboard/dimm0,
127# /org/openbmc/inventory/system/chassis/motherboard/dimm1]
128################################################################
Gunnar Mills096cd562018-03-26 10:19:12 -0500129def get_vpd_inventory_list(module_name, fru):
George Keishingd9b3e162022-08-18 23:28:35 -0500130 r"""
131 Return VPD URI(s) list of a FRU type from inventory.
132 """
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500133 inventory_list = []
Brian Ma139f1da2024-10-18 13:34:14 +0800134 m = load_source("module.name", module_name)
Chris Austenb29d2e82016-06-07 12:25:35 -0500135
Patrick Williams20f38712022-12-08 06:18:26 -0600136 for i in m.ID_LOOKUP["FRU_STR"]:
137 x = m.ID_LOOKUP["FRU_STR"][i]
Chris Austenb29d2e82016-06-07 12:25:35 -0500138
Patrick Williams20f38712022-12-08 06:18:26 -0600139 if m.FRU_INSTANCES[x]["fru_type"] == fru:
140 s = x.replace("<inventory_root>", m.INVENTORY_ROOT)
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500141 inventory_list.append(s)
Gunnar Millsbb398ac2016-11-14 11:50:22 -0600142
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500143 return inventory_list
Chris Austenb29d2e82016-06-07 12:25:35 -0500144
145
146def call_keyword(keyword):
George Keishingd9b3e162022-08-18 23:28:35 -0500147 r"""
148 Return result of the execute robot keyword.
149 """
Chris Austenb29d2e82016-06-07 12:25:35 -0500150 return BuiltIn().run_keyword(keyword)
151
152
153def main():
George Keishingd9b3e162022-08-18 23:28:35 -0500154 r"""
155 Python main func call.
156 """
Patrick Williams20f38712022-12-08 06:18:26 -0600157 print(get_vpd_inventory_list("../data/Palmetto.py", "DIMM"))
Chris Austenb29d2e82016-06-07 12:25:35 -0500158
159
160if __name__ == "__main__":
Gunnar Mills096cd562018-03-26 10:19:12 -0500161 main()
Michael Walsh8b270ec2017-01-31 12:07:08 -0600162
163
Michael Walsh8b270ec2017-01-31 12:07:08 -0600164def get_mtr_report(host=""):
Michael Walsh8b270ec2017-01-31 12:07:08 -0600165 r"""
166 Get an mtr report and return it as a dictionary of dictionaries.
167
168 The key for the top level dictionary will be the host DNS name. The key
169 for the next level dictionary will be the field of a given row of the
170 report.
171
172 Example result:
173
174 report:
George Keishingfb4b1252017-06-15 00:05:45 -0500175 report[host_dummy-dnsname.com]:
176 report[host_dummy-dnsname.com][row_num]: 1
177 report[host_dummy-dnsname.com][host]: host_dummy-dnsname.com
178 report[host_dummy-dnsname.com][loss]: 0.0
179 report[host_dummy-dnsname.com][snt]: 10
180 report[host_dummy-dnsname.com][last]: 0.2
181 report[host_dummy-dnsname.com][avg]: 3.5
182 report[host_dummy-dnsname.com][best]: 0.2
183 report[host_dummy-dnsname.com][wrst]: 32.5
184 report[host_dummy-dnsname.com][stdev]: 10.2
185 report[bmc-dummy-dnsname.com]:
186 report[bmc-dummy-dnsname.com][row_num]: 2
187 report[bmc-dummy-dnsname.com][host]: bmc-dummy-dnsname.com
188 report[bmc-dummy-dnsname.com][loss]: 0.0
189 report[bmc-dummy-dnsname.com][snt]: 10
190 report[bmc-dummy-dnsname.com][last]: 0.5
191 report[bmc-dummy-dnsname.com][avg]: 0.5
192 report[bmc-dummy-dnsname.com][best]: 0.5
193 report[bmc-dummy-dnsname.com][wrst]: 0.5
194 report[bmc-dummy-dnsname.com][stdev]: 0.0
Michael Walsh8b270ec2017-01-31 12:07:08 -0600195
196 Description of arguments:
197 host The DNS name or IP address to be passed to the mtr command.
198 """
199
Gunnar Millsacc7c562019-08-20 13:12:46 -0500200 # Run the mtr command. Exclude the header line. Trim leading space from
Michael Walsh8b270ec2017-01-31 12:07:08 -0600201 # each line. Change all multiple spaces delims to single space delims.
Patrick Williams20f38712022-12-08 06:18:26 -0600202 cmd_buf = (
203 "mtr --report "
204 + host
205 + " | tail -n +2 | sed -r -e 's/^[ ]+//g' -e 's/[ ]+/ /g'"
206 )
207 sub_proc = subprocess.Popen(
208 cmd_buf, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
209 )
Michael Walsh8b270ec2017-01-31 12:07:08 -0600210 out_buf, err_buf = sub_proc.communicate()
211 shell_rc = sub_proc.returncode
manimozhik6abea652023-11-09 07:05:16 +0000212 out_buf = out_buf.decode("utf-8")
Michael Walsh8b270ec2017-01-31 12:07:08 -0600213
214 # Split the output by line.
Patrick Williams20f38712022-12-08 06:18:26 -0600215 rows = out_buf.rstrip("\n").split("\n")
Michael Walsh8b270ec2017-01-31 12:07:08 -0600216
217 # Initialize report dictionary.
218 report = DotDict()
219 for row in rows:
220 # Process each row of mtr output.
221 # Create a list of fields by splitting on space delimiter.
222 row_list = row.split(" ")
223 # Create dictionary for the row.
224 row = DotDict()
Patrick Williams20f38712022-12-08 06:18:26 -0600225 row["row_num"] = row_list[0].rstrip(".")
226 row["host"] = row_list[1]
227 row["loss"] = row_list[2].rstrip("%")
228 row["snt"] = row_list[3]
229 row["last"] = row_list[4]
230 row["avg"] = row_list[5]
231 row["best"] = row_list[6]
232 row["wrst"] = row_list[7]
233 row["stdev"] = row_list[8]
234 report[row["host"]] = row
Michael Walsh8b270ec2017-01-31 12:07:08 -0600235
236 # Return the full report as dictionary of dictionaries.
237 return report
238
Michael Walsh8b270ec2017-01-31 12:07:08 -0600239
Michael Walsh8b270ec2017-01-31 12:07:08 -0600240def get_mtr_row(host=""):
Michael Walsh8b270ec2017-01-31 12:07:08 -0600241 r"""
242 Run an mtr report and get a specified row and return it as a dictionary.
243
244 Example result:
245
246 row:
247 row[row_num]: 2
George Keishingfb4b1252017-06-15 00:05:45 -0500248 row[host]: bmc-dummy-dnsname.com
Michael Walsh8b270ec2017-01-31 12:07:08 -0600249 row[loss]: 0.0
250 row[snt]: 10
251 row[last]: 0.5
252 row[avg]: 0.5
253 row[best]: 0.4
254 row[wrst]: 0.7
255 row[stdev]: 0.1
256
257 Description of arguments:
258 host The DNS name or IP address to be passed to the mtr command as
259 well as the indicating which row of the report to return.
260 """
261
262 report = get_mtr_report(host)
263
264 # The max length of host in output is 28 chars.
Igor Kanyuka20fe49d2025-11-24 11:14:53 +0000265 host_part = host[:28]
266
267 row = [
268 value
269 for key, value in report.items()
270 if key in host or host_part in key
271 ][0]
Michael Walsh8b270ec2017-01-31 12:07:08 -0600272
273 return row
274
George Keishingefa97352017-03-13 07:13:03 -0500275
George Keishingefa97352017-03-13 07:13:03 -0500276def list_to_set(fru_list=""):
277 r"""
278 Pack the list into a set tuple and return.
279
280 It may seem that this function is rather trivial. However, it simplifies
281 the code and improves robot program readability and achieve the result
282 required.
283
284 Example result:
285
286 set(['Version', 'PartNumber', 'SerialNumber', 'FieldReplaceable',
287 'BuildDate', 'Present', 'Manufacturer', 'PrettyName', 'Cached', 'Model'])
288
289 # Description of arguments.
290 fru_list List of FRU's elements.
291 """
292 return set(fru_list)
293
George Keishing81ae45b2017-09-28 14:05:04 -0500294
295def min_list_value(value_list):
296 r"""
297 Returns the element from the list with minimum value.
298 """
299 return min(value_list)
nagarjunb2287138e62022-04-19 16:49:16 +0530300
301
302def convert_lsb_to_msb(string):
303 r"""
304 Reverse given string (From LSB first to MSB first) and converts to HEX.
305
George Keishing86d85f42022-08-18 23:02:22 -0500306 Input string 0a 00
nagarjunb2287138e62022-04-19 16:49:16 +0530307 Return string 0a
308 """
309 datalist = string.split(" ")
310 new_list = datalist[::-1]
311 new_string = "".join([str(element) for element in new_list])
312 return int(new_string, 16)
313
314
315def add_prefix_to_string(string, prefix):
316 r"""
317 Add given prefix to the string and return string.
318
319 Input string 0a 01
320 Return string 0x0a 0x01
321 """
Patrick Williams20f38712022-12-08 06:18:26 -0600322 prefix_string = ""
nagarjunb2287138e62022-04-19 16:49:16 +0530323 data_list = string.strip().split(" ")
324 for item in data_list:
Patrick Williams20f38712022-12-08 06:18:26 -0600325 prefix_string += prefix + item + " "
nagarjunb2287138e62022-04-19 16:49:16 +0530326 return prefix_string.strip()
George Keishing8ef9e722023-01-18 10:21:31 +0530327
328
329def get_value_from_nested_dict(key, nested_dict):
330 r"""
331 Returns the key value from the nested dictionary.
332
333 key Key value of the dictionary to look up.
334 nested_dict Dictionary data.
335 """
336 result = []
337 for k, v in nested_dict.items():
338 if k == key:
339 result.append(v)
340 elif isinstance(v, dict) and k != key:
341 result += get_value_from_nested_dict(key, v)
342
343 return result