1e7e9171eSGeorge Keishing#!/usr/bin/env python3 -u
2d9b3e163SGeorge Keishing
3d9b3e163SGeorge Keishingr"""
4d9b3e163SGeorge KeishingGeneric utility functions.
5d9b3e163SGeorge Keishing"""
6b29d2e84SChris Austenimport imp
7e635ddc0SGeorge Keishingimport random
820f38712SPatrick Williamsimport string
98b270ecfSMichael Walshimport subprocess
1020f38712SPatrick Williams
11d9b3e163SGeorge Keishingfrom robot.libraries.BuiltIn import BuiltIn
128b270ecfSMichael Walshfrom robot.utils import DotDict
138b270ecfSMichael Walsh
14b29d2e84SChris Austen
15757d80c1SRahul Maheshwaridef random_mac():
16757d80c1SRahul Maheshwari    r"""
17757d80c1SRahul Maheshwari    Return random mac address in the following format.
18757d80c1SRahul Maheshwari    Example: 00:01:6C:80:02:78
19757d80c1SRahul Maheshwari    """
2020f38712SPatrick Williams    return ":".join(
2120f38712SPatrick Williams        map(
2220f38712SPatrick Williams            lambda x: "%02x" % x,
2320f38712SPatrick Williams            (random.randint(0x00, 0xFF) for _ in range(6)),
2420f38712SPatrick Williams        )
2520f38712SPatrick Williams    )
26757d80c1SRahul Maheshwari
27096cd565SGunnar Mills
28757d80c1SRahul Maheshwaridef random_ip():
29757d80c1SRahul Maheshwari    r"""
30757d80c1SRahul Maheshwari    Return random ip address in the following format.
31757d80c1SRahul Maheshwari    Example: 9.3.128.100
32757d80c1SRahul Maheshwari    """
3320f38712SPatrick Williams    return ".".join(map(str, (random.randint(0, 255) for _ in range(4))))
34b29d2e84SChris Austen
35096cd565SGunnar Mills
36b29d2e84SChris Austendef get_sensor(module_name, value):
37d9b3e163SGeorge Keishing    r"""
38d9b3e163SGeorge Keishing    Return sensor matched ID name.
39d9b3e163SGeorge Keishing    """
4020f38712SPatrick Williams    m = imp.load_source("module.name", module_name)
41b29d2e84SChris Austen
4220f38712SPatrick Williams    for i in m.ID_LOOKUP["SENSOR"]:
4320f38712SPatrick Williams        if m.ID_LOOKUP["SENSOR"][i] == value:
44b29d2e84SChris Austen            return i
45b29d2e84SChris Austen
46b29d2e84SChris Austen    return 0xFF
47b29d2e84SChris Austen
48b29d2e84SChris Austen
49b29d2e84SChris Austendef get_inventory_sensor(module_name, value):
50d9b3e163SGeorge Keishing    r"""
51d9b3e163SGeorge Keishing    Return sensor matched ID name from inventory.
52d9b3e163SGeorge Keishing    """
5320f38712SPatrick Williams    m = imp.load_source("module.name", module_name)
54b29d2e84SChris Austen
5520f38712SPatrick Williams    value = string.replace(value, m.INVENTORY_ROOT, "<inventory_root>")
56b29d2e84SChris Austen
5720f38712SPatrick Williams    for i in m.ID_LOOKUP["SENSOR"]:
5820f38712SPatrick Williams        if m.ID_LOOKUP["SENSOR"][i] == value:
59b29d2e84SChris Austen            return i
60b29d2e84SChris Austen
61b29d2e84SChris Austen    return 0xFF
62b29d2e84SChris Austen
63b29d2e84SChris Austen
64b29d2e84SChris Austen################################################################
65b29d2e84SChris Austen#  This will return the URI's of the FRU type
66b29d2e84SChris Austen#
67b29d2e84SChris Austen#  i.e.  get_inventory_list('../data/Palmetto.py')
68b29d2e84SChris Austen#
69d9b3e163SGeorge Keishing#  [/org/openbmc/inventory/system/chassis/motherboard/cpu0/core0,
70b29d2e84SChris Austen#   /org/openbmc/inventory/system/chassis/motherboard/dimm0]
71b29d2e84SChris Austen################################################################
72b29d2e84SChris Austendef get_inventory_list(module_name):
73d9b3e163SGeorge Keishing    r"""
74d9b3e163SGeorge Keishing    Return all FRU URI(s) list available from inventory.
75d9b3e163SGeorge Keishing    """
76b29d2e84SChris Austen
77004ad3c9SJoy Onyerikwu    inventory_list = []
7820f38712SPatrick Williams    m = imp.load_source("module.name", module_name)
79b29d2e84SChris Austen
8020f38712SPatrick Williams    for i in m.ID_LOOKUP["FRU"]:
8120f38712SPatrick Williams        s = m.ID_LOOKUP["FRU"][i]
8220f38712SPatrick Williams        s = s.replace("<inventory_root>", m.INVENTORY_ROOT)
83004ad3c9SJoy Onyerikwu        inventory_list.append(s)
84b29d2e84SChris Austen
85004ad3c9SJoy Onyerikwu    return inventory_list
86b29d2e84SChris Austen
87b29d2e84SChris Austen
88b29d2e84SChris Austen################################################################
89b29d2e84SChris Austen#  This will return the URI's of the FRU type
90b29d2e84SChris Austen#
91be3cdfd0SGeorge Keishing#  i.e.  get_inventory_fru_type_list('../data/Witherspoon.py', 'CPU')
92b29d2e84SChris Austen#
93d9b3e163SGeorge Keishing#  [/org/openbmc/inventory/system/chassis/motherboard/cpu0,
94d9b3e163SGeorge Keishing#   /org/openbmc/inventory/system/chassis/motherboard/cpu1]
95b29d2e84SChris Austen################################################################
96b29d2e84SChris Austendef get_inventory_fru_type_list(module_name, fru):
97d9b3e163SGeorge Keishing    r"""
98d9b3e163SGeorge Keishing    Return FRU URI(s) list of a given type from inventory.
99d9b3e163SGeorge Keishing    """
100004ad3c9SJoy Onyerikwu    inventory_list = []
10120f38712SPatrick Williams    m = imp.load_source("module.name", module_name)
102b29d2e84SChris Austen
103b29d2e84SChris Austen    for i in m.FRU_INSTANCES.keys():
10420f38712SPatrick Williams        if m.FRU_INSTANCES[i]["fru_type"] == fru:
10520f38712SPatrick Williams            s = i.replace("<inventory_root>", m.INVENTORY_ROOT)
106004ad3c9SJoy Onyerikwu            inventory_list.append(s)
107b29d2e84SChris Austen
108004ad3c9SJoy Onyerikwu    return inventory_list
109b29d2e84SChris Austen
110b29d2e84SChris Austen
111b29d2e84SChris Austen################################################################
112b29d2e84SChris Austen#  This will return the URI's of the FRU type that contain VPD
113b29d2e84SChris Austen#
114b29d2e84SChris Austen#  i.e.  get_vpd_inventory_list('../data/Palmetto.py', 'DIMM')
115b29d2e84SChris Austen#
116b29d2e84SChris Austen#  [/org/openbmc/inventory/system/chassis/motherboard/dimm0,
117b29d2e84SChris Austen#   /org/openbmc/inventory/system/chassis/motherboard/dimm1]
118b29d2e84SChris Austen################################################################
119b29d2e84SChris Austendef get_vpd_inventory_list(module_name, fru):
120d9b3e163SGeorge Keishing    r"""
121d9b3e163SGeorge Keishing    Return VPD URI(s) list of a FRU type from inventory.
122d9b3e163SGeorge Keishing    """
123004ad3c9SJoy Onyerikwu    inventory_list = []
12420f38712SPatrick Williams    m = imp.load_source("module.name", module_name)
125b29d2e84SChris Austen
12620f38712SPatrick Williams    for i in m.ID_LOOKUP["FRU_STR"]:
12720f38712SPatrick Williams        x = m.ID_LOOKUP["FRU_STR"][i]
128b29d2e84SChris Austen
12920f38712SPatrick Williams        if m.FRU_INSTANCES[x]["fru_type"] == fru:
13020f38712SPatrick Williams            s = x.replace("<inventory_root>", m.INVENTORY_ROOT)
131004ad3c9SJoy Onyerikwu            inventory_list.append(s)
132b29d2e84SChris Austen
133004ad3c9SJoy Onyerikwu    return inventory_list
134b29d2e84SChris Austen
135b29d2e84SChris Austen
136b29d2e84SChris Austendef call_keyword(keyword):
137d9b3e163SGeorge Keishing    r"""
138d9b3e163SGeorge Keishing    Return result of the execute robot keyword.
139d9b3e163SGeorge Keishing    """
140b29d2e84SChris Austen    return BuiltIn().run_keyword(keyword)
141b29d2e84SChris Austen
142b29d2e84SChris Austen
143b29d2e84SChris Austendef main():
144d9b3e163SGeorge Keishing    r"""
145d9b3e163SGeorge Keishing    Python main func call.
146d9b3e163SGeorge Keishing    """
14720f38712SPatrick Williams    print(get_vpd_inventory_list("../data/Palmetto.py", "DIMM"))
148b29d2e84SChris Austen
149b29d2e84SChris Austen
150b29d2e84SChris Austenif __name__ == "__main__":
151b29d2e84SChris Austen    main()
1528b270ecfSMichael Walsh
1538b270ecfSMichael Walsh
1548b270ecfSMichael Walshdef get_mtr_report(host=""):
1558b270ecfSMichael Walsh    r"""
1568b270ecfSMichael Walsh    Get an mtr report and return it as a dictionary of dictionaries.
1578b270ecfSMichael Walsh
1588b270ecfSMichael Walsh    The key for the top level dictionary will be the host DNS name.  The key
1598b270ecfSMichael Walsh    for the next level dictionary will be the field of a given row of the
1608b270ecfSMichael Walsh    report.
1618b270ecfSMichael Walsh
1628b270ecfSMichael Walsh    Example result:
1638b270ecfSMichael Walsh
1648b270ecfSMichael Walsh    report:
165fb4b1256SGeorge Keishing      report[host_dummy-dnsname.com]:
166fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][row_num]:  1
167fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][host]:     host_dummy-dnsname.com
168fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][loss]:     0.0
169fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][snt]:      10
170fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][last]:     0.2
171fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][avg]:      3.5
172fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][best]:     0.2
173fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][wrst]:     32.5
174fb4b1256SGeorge Keishing        report[host_dummy-dnsname.com][stdev]:    10.2
175fb4b1256SGeorge Keishing      report[bmc-dummy-dnsname.com]:
176fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][row_num]:     2
177fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][host]:        bmc-dummy-dnsname.com
178fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][loss]:        0.0
179fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][snt]:         10
180fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][last]:        0.5
181fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][avg]:         0.5
182fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][best]:        0.5
183fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][wrst]:        0.5
184fb4b1256SGeorge Keishing        report[bmc-dummy-dnsname.com][stdev]:       0.0
1858b270ecfSMichael Walsh
1868b270ecfSMichael Walsh    Description of arguments:
1878b270ecfSMichael Walsh    host   The DNS name or IP address to be passed to the mtr command.
1888b270ecfSMichael Walsh    """
1898b270ecfSMichael Walsh
190acc7c56eSGunnar Mills    # Run the mtr command.  Exclude the header line.  Trim leading space from
1918b270ecfSMichael Walsh    # each line.  Change all multiple spaces delims to single space delims.
19220f38712SPatrick Williams    cmd_buf = (
19320f38712SPatrick Williams        "mtr --report "
19420f38712SPatrick Williams        + host
19520f38712SPatrick Williams        + " | tail -n +2 | sed -r -e 's/^[ ]+//g' -e 's/[ ]+/ /g'"
19620f38712SPatrick Williams    )
19720f38712SPatrick Williams    sub_proc = subprocess.Popen(
19820f38712SPatrick Williams        cmd_buf, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
19920f38712SPatrick Williams    )
2008b270ecfSMichael Walsh    out_buf, err_buf = sub_proc.communicate()
2018b270ecfSMichael Walsh    shell_rc = sub_proc.returncode
202*6abea65cSmanimozhik    out_buf = out_buf.decode("utf-8")
2038b270ecfSMichael Walsh
2048b270ecfSMichael Walsh    # Split the output by line.
20520f38712SPatrick Williams    rows = out_buf.rstrip("\n").split("\n")
2068b270ecfSMichael Walsh
2078b270ecfSMichael Walsh    # Initialize report dictionary.
2088b270ecfSMichael Walsh    report = DotDict()
2098b270ecfSMichael Walsh    for row in rows:
2108b270ecfSMichael Walsh        # Process each row of mtr output.
2118b270ecfSMichael Walsh        # Create a list of fields by splitting on space delimiter.
2128b270ecfSMichael Walsh        row_list = row.split(" ")
2138b270ecfSMichael Walsh        # Create dictionary for the row.
2148b270ecfSMichael Walsh        row = DotDict()
21520f38712SPatrick Williams        row["row_num"] = row_list[0].rstrip(".")
21620f38712SPatrick Williams        row["host"] = row_list[1]
21720f38712SPatrick Williams        row["loss"] = row_list[2].rstrip("%")
21820f38712SPatrick Williams        row["snt"] = row_list[3]
21920f38712SPatrick Williams        row["last"] = row_list[4]
22020f38712SPatrick Williams        row["avg"] = row_list[5]
22120f38712SPatrick Williams        row["best"] = row_list[6]
22220f38712SPatrick Williams        row["wrst"] = row_list[7]
22320f38712SPatrick Williams        row["stdev"] = row_list[8]
22420f38712SPatrick Williams        report[row["host"]] = row
2258b270ecfSMichael Walsh
2268b270ecfSMichael Walsh    # Return the full report as dictionary of dictionaries.
2278b270ecfSMichael Walsh    return report
2288b270ecfSMichael Walsh
2298b270ecfSMichael Walsh
2308b270ecfSMichael Walshdef get_mtr_row(host=""):
2318b270ecfSMichael Walsh    r"""
2328b270ecfSMichael Walsh    Run an mtr report and get a specified row and return it as a dictionary.
2338b270ecfSMichael Walsh
2348b270ecfSMichael Walsh    Example result:
2358b270ecfSMichael Walsh
2368b270ecfSMichael Walsh    row:
2378b270ecfSMichael Walsh      row[row_num]:              2
238fb4b1256SGeorge Keishing      row[host]:                 bmc-dummy-dnsname.com
2398b270ecfSMichael Walsh      row[loss]:                 0.0
2408b270ecfSMichael Walsh      row[snt]:                  10
2418b270ecfSMichael Walsh      row[last]:                 0.5
2428b270ecfSMichael Walsh      row[avg]:                  0.5
2438b270ecfSMichael Walsh      row[best]:                 0.4
2448b270ecfSMichael Walsh      row[wrst]:                 0.7
2458b270ecfSMichael Walsh      row[stdev]:                0.1
2468b270ecfSMichael Walsh
2478b270ecfSMichael Walsh    Description of arguments:
2488b270ecfSMichael Walsh    host   The DNS name or IP address to be passed to the mtr command as
2498b270ecfSMichael Walsh           well as the indicating which row of the report to return.
2508b270ecfSMichael Walsh    """
2518b270ecfSMichael Walsh
2528b270ecfSMichael Walsh    report = get_mtr_report(host)
2538b270ecfSMichael Walsh
2548b270ecfSMichael Walsh    # The max length of host in output is 28 chars.
2558b270ecfSMichael Walsh    row = [value for key, value in report.items() if host[0:28] in key][0]
2568b270ecfSMichael Walsh
2578b270ecfSMichael Walsh    return row
2588b270ecfSMichael Walsh
259efa97357SGeorge Keishing
260efa97357SGeorge Keishingdef list_to_set(fru_list=""):
261efa97357SGeorge Keishing    r"""
262efa97357SGeorge Keishing    Pack the list into a set tuple and return.
263efa97357SGeorge Keishing
264efa97357SGeorge Keishing    It may seem that this function is rather trivial. However, it simplifies
265efa97357SGeorge Keishing    the code and improves robot program readability and achieve the result
266efa97357SGeorge Keishing    required.
267efa97357SGeorge Keishing
268efa97357SGeorge Keishing    Example result:
269efa97357SGeorge Keishing
270efa97357SGeorge Keishing    set(['Version', 'PartNumber', 'SerialNumber', 'FieldReplaceable',
271efa97357SGeorge Keishing    'BuildDate', 'Present', 'Manufacturer', 'PrettyName', 'Cached', 'Model'])
272efa97357SGeorge Keishing
273efa97357SGeorge Keishing    # Description of arguments.
274efa97357SGeorge Keishing    fru_list   List of FRU's elements.
275efa97357SGeorge Keishing    """
276efa97357SGeorge Keishing    return set(fru_list)
277efa97357SGeorge Keishing
27881ae45b6SGeorge Keishing
27981ae45b6SGeorge Keishingdef min_list_value(value_list):
28081ae45b6SGeorge Keishing    r"""
28181ae45b6SGeorge Keishing    Returns the element from the list with minimum value.
28281ae45b6SGeorge Keishing    """
28381ae45b6SGeorge Keishing    return min(value_list)
28487138e6fSnagarjunb22
28587138e6fSnagarjunb22
28687138e6fSnagarjunb22def convert_lsb_to_msb(string):
28787138e6fSnagarjunb22    r"""
28887138e6fSnagarjunb22    Reverse given string (From LSB first to MSB first) and converts to HEX.
28987138e6fSnagarjunb22
29086d85f4cSGeorge Keishing    Input string     0a 00
29187138e6fSnagarjunb22    Return string    0a
29287138e6fSnagarjunb22    """
29387138e6fSnagarjunb22    datalist = string.split(" ")
29487138e6fSnagarjunb22    new_list = datalist[::-1]
29587138e6fSnagarjunb22    new_string = "".join([str(element) for element in new_list])
29687138e6fSnagarjunb22    return int(new_string, 16)
29787138e6fSnagarjunb22
29887138e6fSnagarjunb22
29987138e6fSnagarjunb22def add_prefix_to_string(string, prefix):
30087138e6fSnagarjunb22    r"""
30187138e6fSnagarjunb22    Add given prefix to the string and return string.
30287138e6fSnagarjunb22
30387138e6fSnagarjunb22    Input string      0a 01
30487138e6fSnagarjunb22    Return string     0x0a 0x01
30587138e6fSnagarjunb22    """
30620f38712SPatrick Williams    prefix_string = ""
30787138e6fSnagarjunb22    data_list = string.strip().split(" ")
30887138e6fSnagarjunb22    for item in data_list:
30920f38712SPatrick Williams        prefix_string += prefix + item + " "
31087138e6fSnagarjunb22    return prefix_string.strip()
3118ef9e72bSGeorge Keishing
3128ef9e72bSGeorge Keishing
3138ef9e72bSGeorge Keishingdef get_value_from_nested_dict(key, nested_dict):
3148ef9e72bSGeorge Keishing    r"""
3158ef9e72bSGeorge Keishing    Returns the key value from the nested dictionary.
3168ef9e72bSGeorge Keishing
3178ef9e72bSGeorge Keishing    key               Key value of the dictionary to look up.
3188ef9e72bSGeorge Keishing    nested_dict       Dictionary data.
3198ef9e72bSGeorge Keishing    """
3208ef9e72bSGeorge Keishing    result = []
3218ef9e72bSGeorge Keishing    for k, v in nested_dict.items():
3228ef9e72bSGeorge Keishing        if k == key:
3238ef9e72bSGeorge Keishing            result.append(v)
3248ef9e72bSGeorge Keishing        elif isinstance(v, dict) and k != key:
3258ef9e72bSGeorge Keishing            result += get_value_from_nested_dict(key, v)
3268ef9e72bSGeorge Keishing
3278ef9e72bSGeorge Keishing    return result
328