| George Keishing | e7e9171 | 2021-09-03 11:28:44 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
| Michael Walsh | ed5b46e | 2017-05-24 11:49:14 -0500 | [diff] [blame] | 2 |  | 
 | 3 | r""" | 
 | 4 | Provide useful ipmi functions. | 
 | 5 | """ | 
 | 6 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 7 | import json | 
| Michael Walsh | f4098fb | 2018-02-28 10:54:46 -0600 | [diff] [blame] | 8 | import re | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 9 | import tempfile | 
 | 10 |  | 
 | 11 | import bmc_ssh_utils as bsu | 
| George Keishing | e635ddc | 2022-12-08 07:38:02 -0600 | [diff] [blame] | 12 | import gen_cmd as gc | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 13 | import gen_misc as gm | 
 | 14 | import gen_print as gp | 
| Michael Walsh | ed5b46e | 2017-05-24 11:49:14 -0500 | [diff] [blame] | 15 | import gen_robot_keyword as grk | 
 | 16 | import gen_robot_utils as gru | 
| George Keishing | e635ddc | 2022-12-08 07:38:02 -0600 | [diff] [blame] | 17 | import ipmi_client as ic | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 18 | import var_funcs as vf | 
 | 19 | from robot.libraries.BuiltIn import BuiltIn | 
 | 20 |  | 
| George Keishing | 0967989 | 2022-12-08 08:21:52 -0600 | [diff] [blame] | 21 | gru.my_import_resource("ipmi_client.robot") | 
| Michael Walsh | ed5b46e | 2017-05-24 11:49:14 -0500 | [diff] [blame] | 22 |  | 
 | 23 |  | 
| Michael Walsh | ed5b46e | 2017-05-24 11:49:14 -0500 | [diff] [blame] | 24 | def get_sol_info(): | 
| Michael Walsh | ed5b46e | 2017-05-24 11:49:14 -0500 | [diff] [blame] | 25 |     r""" | 
 | 26 |     Get all SOL info and return it as a dictionary. | 
 | 27 |  | 
 | 28 |     Example use: | 
 | 29 |  | 
 | 30 |     Robot code: | 
 | 31 |     ${sol_info}=  get_sol_info | 
 | 32 |     Rpvars  sol_info | 
 | 33 |  | 
 | 34 |     Output: | 
 | 35 |     sol_info: | 
| Joy Onyerikwu | 004ad3c | 2018-06-11 16:29:56 -0500 | [diff] [blame] | 36 |       sol_info[Info]:                                SOL parameter 'Payload Channel (7)' | 
 | 37 |                                                      not supported - defaulting to 0x0e | 
| Michael Walsh | ed5b46e | 2017-05-24 11:49:14 -0500 | [diff] [blame] | 38 |       sol_info[Character Send Threshold]:            1 | 
 | 39 |       sol_info[Force Authentication]:                true | 
 | 40 |       sol_info[Privilege Level]:                     USER | 
 | 41 |       sol_info[Set in progress]:                     set-complete | 
 | 42 |       sol_info[Retry Interval (ms)]:                 100 | 
 | 43 |       sol_info[Non-Volatile Bit Rate (kbps)]:        IPMI-Over-Serial-Setting | 
 | 44 |       sol_info[Character Accumulate Level (ms)]:     100 | 
 | 45 |       sol_info[Enabled]:                             true | 
 | 46 |       sol_info[Volatile Bit Rate (kbps)]:            IPMI-Over-Serial-Setting | 
 | 47 |       sol_info[Payload Channel]:                     14 (0x0e) | 
 | 48 |       sol_info[Payload Port]:                        623 | 
 | 49 |       sol_info[Force Encryption]:                    true | 
 | 50 |       sol_info[Retry Count]:                         7 | 
 | 51 |     """ | 
 | 52 |  | 
| ishwaryamathim | 372cd86 | 2023-11-14 18:12:23 +0000 | [diff] [blame] | 53 |     status, ret_values = grk.run_key_u( | 
 | 54 |         "Run External IPMI Standard Command  sol info" | 
 | 55 |     ) | 
| Michael Walsh | ed5b46e | 2017-05-24 11:49:14 -0500 | [diff] [blame] | 56 |  | 
 | 57 |     # Create temp file path. | 
 | 58 |     temp = tempfile.NamedTemporaryFile() | 
 | 59 |     temp_file_path = temp.name | 
 | 60 |  | 
 | 61 |     # Write sol info to temp file path. | 
 | 62 |     text_file = open(temp_file_path, "w") | 
 | 63 |     text_file.write(ret_values) | 
 | 64 |     text_file.close() | 
 | 65 |  | 
 | 66 |     # Use my_parm_file to interpret data. | 
 | 67 |     sol_info = gm.my_parm_file(temp_file_path) | 
 | 68 |  | 
 | 69 |     return sol_info | 
 | 70 |  | 
| Rahul Maheshwari | d629b5c | 2017-05-23 08:06:28 -0500 | [diff] [blame] | 71 |  | 
| Rahul Maheshwari | d629b5c | 2017-05-23 08:06:28 -0500 | [diff] [blame] | 72 | def set_sol_setting(setting_name, setting_value): | 
| Rahul Maheshwari | d629b5c | 2017-05-23 08:06:28 -0500 | [diff] [blame] | 73 |     r""" | 
 | 74 |     Set SOL setting with given value. | 
 | 75 |  | 
 | 76 |     # Description of argument(s): | 
| Joy Onyerikwu | 004ad3c | 2018-06-11 16:29:56 -0500 | [diff] [blame] | 77 |     # setting_name                  SOL setting which needs to be set (e.g. | 
 | 78 |     #                               "retry-count"). | 
 | 79 |     # setting_value                 Value which needs to be set (e.g. "7"). | 
| Rahul Maheshwari | d629b5c | 2017-05-23 08:06:28 -0500 | [diff] [blame] | 80 |     """ | 
 | 81 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 82 |     status, ret_values = grk.run_key_u( | 
| ishwaryamathim | 372cd86 | 2023-11-14 18:12:23 +0000 | [diff] [blame] | 83 |         "Run External IPMI Standard Command  sol set " | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 84 |         + setting_name | 
 | 85 |         + " " | 
 | 86 |         + setting_value | 
 | 87 |     ) | 
| Rahul Maheshwari | d629b5c | 2017-05-23 08:06:28 -0500 | [diff] [blame] | 88 |  | 
 | 89 |     return status | 
 | 90 |  | 
| Rahul Maheshwari | d629b5c | 2017-05-23 08:06:28 -0500 | [diff] [blame] | 91 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 92 | def execute_ipmi_cmd( | 
 | 93 |     cmd_string, ipmi_cmd_type="inband", print_output=1, ignore_err=0, **options | 
 | 94 | ): | 
| Michael Walsh | 94811f6 | 2018-09-05 14:55:12 -0500 | [diff] [blame] | 95 |     r""" | 
 | 96 |     Run the given command string as an IPMI command and return the stdout, | 
 | 97 |     stderr and the return code. | 
 | 98 |  | 
 | 99 |     Description of argument(s): | 
 | 100 |     cmd_string                      The command string to be run as an IPMI | 
 | 101 |                                     command. | 
 | 102 |     ipmi_cmd_type                   'inband' or 'external'. | 
 | 103 |     print_output                    If this is set, this function will print | 
 | 104 |                                     the stdout/stderr generated by | 
 | 105 |                                     the IPMI command. | 
 | 106 |     ignore_err                      Ignore error means that a failure | 
 | 107 |                                     encountered by running the command | 
 | 108 |                                     string will not be raised as a python | 
 | 109 |                                     exception. | 
| Michael Walsh | 19e70c8 | 2019-01-23 11:07:15 -0600 | [diff] [blame] | 110 |     options                         These are passed directly to the | 
 | 111 |                                     create_ipmi_ext_command_string function. | 
 | 112 |                                     See that function's prolog for details. | 
| Michael Walsh | 94811f6 | 2018-09-05 14:55:12 -0500 | [diff] [blame] | 113 |     """ | 
 | 114 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 115 |     if ipmi_cmd_type == "inband": | 
| Michael Walsh | 94811f6 | 2018-09-05 14:55:12 -0500 | [diff] [blame] | 116 |         IPMI_INBAND_CMD = BuiltIn().get_variable_value("${IPMI_INBAND_CMD}") | 
 | 117 |         cmd_buf = IPMI_INBAND_CMD + " " + cmd_string | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 118 |         return bsu.os_execute_command( | 
 | 119 |             cmd_buf, print_out=print_output, ignore_err=ignore_err | 
 | 120 |         ) | 
| Michael Walsh | 94811f6 | 2018-09-05 14:55:12 -0500 | [diff] [blame] | 121 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 122 |     if ipmi_cmd_type == "external": | 
| Michael Walsh | 19e70c8 | 2019-01-23 11:07:15 -0600 | [diff] [blame] | 123 |         cmd_buf = ic.create_ipmi_ext_command_string(cmd_string, **options) | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 124 |         rc, stdout, stderr = gc.shell_cmd( | 
 | 125 |             cmd_buf, | 
 | 126 |             print_output=print_output, | 
 | 127 |             ignore_err=ignore_err, | 
 | 128 |             return_stderr=1, | 
 | 129 |         ) | 
| Michael Walsh | 94811f6 | 2018-09-05 14:55:12 -0500 | [diff] [blame] | 130 |         return stdout, stderr, rc | 
 | 131 |  | 
 | 132 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 133 | def get_lan_print_dict(channel_number="", ipmi_cmd_type="external"): | 
| Michael Walsh | 4481b93 | 2018-02-08 11:45:15 -0600 | [diff] [blame] | 134 |     r""" | 
 | 135 |     Get IPMI 'lan print' output and return it as a dictionary. | 
 | 136 |  | 
 | 137 |     Here is an example of the IPMI lan print output: | 
 | 138 |  | 
 | 139 |     Set in Progress         : Set Complete | 
 | 140 |     Auth Type Support       : MD5 | 
 | 141 |     Auth Type Enable        : Callback : MD5 | 
 | 142 |                             : User     : MD5 | 
 | 143 |                             : Operator : MD5 | 
 | 144 |                             : Admin    : MD5 | 
 | 145 |                             : OEM      : MD5 | 
 | 146 |     IP Address Source       : Static Address | 
 | 147 |     IP Address              : x.x.x.x | 
 | 148 |     Subnet Mask             : x.x.x.x | 
 | 149 |     MAC Address             : xx:xx:xx:xx:xx:xx | 
 | 150 |     Default Gateway IP      : x.x.x.x | 
 | 151 |     802.1q VLAN ID          : Disabled | 
 | 152 |     Cipher Suite Priv Max   : Not Available | 
 | 153 |     Bad Password Threshold  : Not Available | 
 | 154 |  | 
 | 155 |     Given that data, this function will return the following dictionary. | 
 | 156 |  | 
 | 157 |     lan_print_dict: | 
 | 158 |       [Set in Progress]:                              Set Complete | 
 | 159 |       [Auth Type Support]:                            MD5 | 
 | 160 |       [Auth Type Enable]: | 
 | 161 |         [Callback]:                                   MD5 | 
 | 162 |         [User]:                                       MD5 | 
 | 163 |         [Operator]:                                   MD5 | 
 | 164 |         [Admin]:                                      MD5 | 
 | 165 |         [OEM]:                                        MD5 | 
 | 166 |       [IP Address Source]:                            Static Address | 
 | 167 |       [IP Address]:                                   x.x.x.x | 
 | 168 |       [Subnet Mask]:                                  x.x.x.x | 
 | 169 |       [MAC Address]:                                  xx:xx:xx:xx:xx:xx | 
 | 170 |       [Default Gateway IP]:                           x.x.x.x | 
 | 171 |       [802.1q VLAN ID]:                               Disabled | 
 | 172 |       [Cipher Suite Priv Max]:                        Not Available | 
 | 173 |       [Bad Password Threshold]:                       Not Available | 
 | 174 |  | 
| Michael Walsh | 94811f6 | 2018-09-05 14:55:12 -0500 | [diff] [blame] | 175 |     Description of argument(s): | 
 | 176 |     ipmi_cmd_type                   The type of ipmi command to use (e.g. | 
 | 177 |                                     'inband', 'external'). | 
| Michael Walsh | 4481b93 | 2018-02-08 11:45:15 -0600 | [diff] [blame] | 178 |     """ | 
 | 179 |  | 
| Tony Lee | ea74130 | 2019-11-08 11:01:58 +0800 | [diff] [blame] | 180 |     channel_number = str(channel_number) | 
| Michael Walsh | 4481b93 | 2018-02-08 11:45:15 -0600 | [diff] [blame] | 181 |     # Notice in the example of data above that 'Auth Type Enable' needs some | 
 | 182 |     # special processing.  We essentially want to isolate its data and remove | 
 | 183 |     # the 'Auth Type Enable' string so that key_value_outbuf_to_dict can | 
 | 184 |     # process it as a sub-dictionary. | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 185 |     cmd_buf = ( | 
 | 186 |         "lan print " | 
 | 187 |         + channel_number | 
 | 188 |         + " | grep -E '^(Auth Type Enable)" | 
 | 189 |         + "?[ ]+: ' | sed -re 's/^(Auth Type Enable)?[ ]+: //g'" | 
 | 190 |     ) | 
 | 191 |     stdout1, stderr, rc = execute_ipmi_cmd( | 
 | 192 |         cmd_buf, ipmi_cmd_type, print_output=0 | 
 | 193 |     ) | 
| Michael Walsh | 4481b93 | 2018-02-08 11:45:15 -0600 | [diff] [blame] | 194 |  | 
 | 195 |     # Now get the remainder of the data and exclude the lines with no field | 
 | 196 |     # names (i.e. the 'Auth Type Enable' sub-fields). | 
| Tony Lee | ea74130 | 2019-11-08 11:01:58 +0800 | [diff] [blame] | 197 |     cmd_buf = "lan print " + channel_number + " | grep -E -v '^[ ]+: '" | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 198 |     stdout2, stderr, rc = execute_ipmi_cmd( | 
 | 199 |         cmd_buf, ipmi_cmd_type, print_output=0 | 
 | 200 |     ) | 
| Michael Walsh | 4481b93 | 2018-02-08 11:45:15 -0600 | [diff] [blame] | 201 |  | 
 | 202 |     # Make auth_type_enable_dict sub-dictionary... | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 203 |     auth_type_enable_dict = vf.key_value_outbuf_to_dict( | 
 | 204 |         stdout1, to_lower=0, underscores=0 | 
 | 205 |     ) | 
| Michael Walsh | 4481b93 | 2018-02-08 11:45:15 -0600 | [diff] [blame] | 206 |  | 
 | 207 |     # Create the lan_print_dict... | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 208 |     lan_print_dict = vf.key_value_outbuf_to_dict( | 
 | 209 |         stdout2, to_lower=0, underscores=0 | 
 | 210 |     ) | 
| Michael Walsh | 4481b93 | 2018-02-08 11:45:15 -0600 | [diff] [blame] | 211 |     # Re-assign 'Auth Type Enable' to contain the auth_type_enable_dict. | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 212 |     lan_print_dict["Auth Type Enable"] = auth_type_enable_dict | 
| Michael Walsh | 4481b93 | 2018-02-08 11:45:15 -0600 | [diff] [blame] | 213 |  | 
 | 214 |     return lan_print_dict | 
| Michael Walsh | d59ed7c | 2018-02-15 10:19:38 -0600 | [diff] [blame] | 215 |  | 
 | 216 |  | 
| Michael Walsh | f4098fb | 2018-02-28 10:54:46 -0600 | [diff] [blame] | 217 | def get_ipmi_power_reading(strip_watts=1): | 
| Michael Walsh | d59ed7c | 2018-02-15 10:19:38 -0600 | [diff] [blame] | 218 |     r""" | 
 | 219 |     Get IPMI power reading data and return it as a dictionary. | 
 | 220 |  | 
 | 221 |     The data is obtained by issuing the IPMI "power reading" command.  An | 
 | 222 |     example is shown below: | 
 | 223 |  | 
 | 224 |     Instantaneous power reading:                   234 Watts | 
 | 225 |     Minimum during sampling period:                234 Watts | 
 | 226 |     Maximum during sampling period:                234 Watts | 
 | 227 |     Average power reading over sample period:      234 Watts | 
 | 228 |     IPMI timestamp:                           Thu Jan  1 00:00:00 1970 | 
 | 229 |     Sampling period:                          00000000 Seconds. | 
 | 230 |     Power reading state is:                   deactivated | 
 | 231 |  | 
 | 232 |     For the data shown above, the following dictionary will be returned. | 
 | 233 |  | 
 | 234 |     result: | 
 | 235 |       [instantaneous_power_reading]:              238 Watts | 
 | 236 |       [minimum_during_sampling_period]:           238 Watts | 
 | 237 |       [maximum_during_sampling_period]:           238 Watts | 
 | 238 |       [average_power_reading_over_sample_period]: 238 Watts | 
 | 239 |       [ipmi_timestamp]:                           Thu Jan  1 00:00:00 1970 | 
 | 240 |       [sampling_period]:                          00000000 Seconds. | 
 | 241 |       [power_reading_state_is]:                   deactivated | 
| Michael Walsh | f4098fb | 2018-02-28 10:54:46 -0600 | [diff] [blame] | 242 |  | 
 | 243 |     Description of argument(s): | 
| Joy Onyerikwu | 004ad3c | 2018-06-11 16:29:56 -0500 | [diff] [blame] | 244 |     strip_watts                     Strip all dictionary values of the | 
 | 245 |                                     trailing " Watts" substring. | 
| Michael Walsh | d59ed7c | 2018-02-15 10:19:38 -0600 | [diff] [blame] | 246 |     """ | 
 | 247 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 248 |     status, ret_values = grk.run_key_u( | 
 | 249 |         "Run IPMI Standard Command  dcmi power reading" | 
 | 250 |     ) | 
| Michael Walsh | d59ed7c | 2018-02-15 10:19:38 -0600 | [diff] [blame] | 251 |     result = vf.key_value_outbuf_to_dict(ret_values) | 
 | 252 |  | 
| Michael Walsh | f4098fb | 2018-02-28 10:54:46 -0600 | [diff] [blame] | 253 |     if strip_watts: | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 254 |         result.update((k, re.sub(" Watts$", "", v)) for k, v in result.items()) | 
| Michael Walsh | f4098fb | 2018-02-28 10:54:46 -0600 | [diff] [blame] | 255 |  | 
| Michael Walsh | d59ed7c | 2018-02-15 10:19:38 -0600 | [diff] [blame] | 256 |     return result | 
| Michael Walsh | af5607e | 2018-02-19 17:37:20 -0600 | [diff] [blame] | 257 |  | 
 | 258 |  | 
 | 259 | def get_mc_info(): | 
| Michael Walsh | af5607e | 2018-02-19 17:37:20 -0600 | [diff] [blame] | 260 |     r""" | 
 | 261 |     Get IPMI mc info data and return it as a dictionary. | 
 | 262 |  | 
 | 263 |     The data is obtained by issuing the IPMI "mc info" command.  An | 
 | 264 |     example is shown below: | 
 | 265 |  | 
 | 266 |     Device ID                 : 0 | 
 | 267 |     Device Revision           : 0 | 
 | 268 |     Firmware Revision         : 2.01 | 
 | 269 |     IPMI Version              : 2.0 | 
 | 270 |     Manufacturer ID           : 42817 | 
 | 271 |     Manufacturer Name         : Unknown (0xA741) | 
 | 272 |     Product ID                : 16975 (0x424f) | 
 | 273 |     Product Name              : Unknown (0x424F) | 
 | 274 |     Device Available          : yes | 
 | 275 |     Provides Device SDRs      : yes | 
 | 276 |     Additional Device Support : | 
 | 277 |         Sensor Device | 
 | 278 |         SEL Device | 
 | 279 |         FRU Inventory Device | 
 | 280 |         Chassis Device | 
 | 281 |     Aux Firmware Rev Info     : | 
 | 282 |         0x00 | 
 | 283 |         0x00 | 
 | 284 |         0x00 | 
 | 285 |         0x00 | 
 | 286 |  | 
 | 287 |     For the data shown above, the following dictionary will be returned. | 
 | 288 |     mc_info: | 
 | 289 |       [device_id]:                       0 | 
 | 290 |       [device_revision]:                 0 | 
 | 291 |       [firmware_revision]:               2.01 | 
 | 292 |       [ipmi_version]:                    2.0 | 
 | 293 |       [manufacturer_id]:                 42817 | 
 | 294 |       [manufacturer_name]:               Unknown (0xA741) | 
 | 295 |       [product_id]:                      16975 (0x424f) | 
 | 296 |       [product_name]:                    Unknown (0x424F) | 
 | 297 |       [device_available]:                yes | 
 | 298 |       [provides_device_sdrs]:            yes | 
 | 299 |       [additional_device_support]: | 
 | 300 |         [additional_device_support][0]:  Sensor Device | 
 | 301 |         [additional_device_support][1]:  SEL Device | 
 | 302 |         [additional_device_support][2]:  FRU Inventory Device | 
 | 303 |         [additional_device_support][3]:  Chassis Device | 
 | 304 |       [aux_firmware_rev_info]: | 
 | 305 |         [aux_firmware_rev_info][0]:      0x00 | 
 | 306 |         [aux_firmware_rev_info][1]:      0x00 | 
 | 307 |         [aux_firmware_rev_info][2]:      0x00 | 
 | 308 |         [aux_firmware_rev_info][3]:      0x00 | 
 | 309 |     """ | 
 | 310 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 311 |     status, ret_values = grk.run_key_u("Run IPMI Standard Command  mc info") | 
| Michael Walsh | af5607e | 2018-02-19 17:37:20 -0600 | [diff] [blame] | 312 |     result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1) | 
 | 313 |  | 
 | 314 |     return result | 
| Rahul Maheshwari | dc6a32c | 2018-03-15 05:21:55 -0500 | [diff] [blame] | 315 |  | 
 | 316 |  | 
 | 317 | def get_sdr_info(): | 
| Rahul Maheshwari | dc6a32c | 2018-03-15 05:21:55 -0500 | [diff] [blame] | 318 |     r""" | 
 | 319 |     Get IPMI sdr info data and return it as a dictionary. | 
 | 320 |  | 
 | 321 |     The data is obtained by issuing the IPMI "sdr info" command.  An | 
 | 322 |     example is shown below: | 
 | 323 |  | 
 | 324 |     SDR Version                         : 0x51 | 
 | 325 |     Record Count                        : 216 | 
 | 326 |     Free Space                          : unspecified | 
 | 327 |     Most recent Addition                : | 
 | 328 |     Most recent Erase                   : | 
 | 329 |     SDR overflow                        : no | 
 | 330 |     SDR Repository Update Support       : unspecified | 
 | 331 |     Delete SDR supported                : no | 
 | 332 |     Partial Add SDR supported           : no | 
 | 333 |     Reserve SDR repository supported    : no | 
 | 334 |     SDR Repository Alloc info supported : no | 
 | 335 |  | 
 | 336 |     For the data shown above, the following dictionary will be returned. | 
 | 337 |     mc_info: | 
 | 338 |  | 
 | 339 |       [sdr_version]:                         0x51 | 
 | 340 |       [record_Count]:                        216 | 
 | 341 |       [free_space]:                          unspecified | 
 | 342 |       [most_recent_addition]: | 
 | 343 |       [most_recent_erase]: | 
 | 344 |       [sdr_overflow]:                        no | 
 | 345 |       [sdr_repository_update_support]:       unspecified | 
 | 346 |       [delete_sdr_supported]:                no | 
 | 347 |       [partial_add_sdr_supported]:           no | 
 | 348 |       [reserve_sdr_repository_supported]:    no | 
 | 349 |       [sdr_repository_alloc_info_supported]: no | 
 | 350 |     """ | 
 | 351 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 352 |     status, ret_values = grk.run_key_u("Run IPMI Standard Command  sdr info") | 
| Rahul Maheshwari | dc6a32c | 2018-03-15 05:21:55 -0500 | [diff] [blame] | 353 |     result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1) | 
 | 354 |  | 
 | 355 |     return result | 
| George Keishing | 3511a3f | 2018-04-19 10:38:30 -0500 | [diff] [blame] | 356 |  | 
 | 357 |  | 
| KManimozhi123 | f320b4e | 2024-03-13 10:22:41 +0000 | [diff] [blame] | 358 | def fetch_oem_sdr_count(sdr_data): | 
| manimozhik | dd32165 | 2023-11-08 10:22:06 +0000 | [diff] [blame] | 359 |     r""" | 
 | 360 |     Get IPMI SDR list and return the SDR OEM count. | 
 | 361 |  | 
 | 362 |     The data is obtained by issuing the IPMI "sdr elist -vvv" command.  An | 
 | 363 |     example is shown below: | 
 | 364 |  | 
 | 365 |     SDR record ID   : 0x00cb | 
 | 366 |     SDR record ID   : 0x00cc | 
 | 367 |     SDR record type : 0xc0 | 
 | 368 |     SDR record next : 0xffff | 
 | 369 |     SDR record bytes: 11 | 
 | 370 |     Getting 11 bytes from SDR at offset 5 | 
 | 371 |  | 
 | 372 |     For the data shown above, the SDR record type with 0xc0 count will be returned. | 
 | 373 |     """ | 
 | 374 |  | 
 | 375 |     data = sdr_data.split("\n") | 
 | 376 |     sdr_list = [] | 
 | 377 |     for i, j in enumerate(data): | 
 | 378 |         a = j.split(":") | 
 | 379 |         if a[0].strip() == "SDR record type": | 
 | 380 |             sdr_list.append(a[1].strip()) | 
 | 381 |     return sdr_list.count("0xc0") | 
 | 382 |  | 
 | 383 |  | 
| George Keishing | 3511a3f | 2018-04-19 10:38:30 -0500 | [diff] [blame] | 384 | def get_aux_version(version_id): | 
 | 385 |     r""" | 
 | 386 |     Get IPMI Aux version info data and return it. | 
 | 387 |  | 
 | 388 |     Description of argument(s): | 
| Joy Onyerikwu | 004ad3c | 2018-06-11 16:29:56 -0500 | [diff] [blame] | 389 |     version_id                      The data is obtained by from BMC | 
 | 390 |                                     /etc/os-release | 
 | 391 |                                     (e.g. "xxx-v2.1-438-g0030304-r3-gfea8585"). | 
| George Keishing | 3511a3f | 2018-04-19 10:38:30 -0500 | [diff] [blame] | 392 |  | 
 | 393 |     In the prior example, the 3rd field is "438" is the commit version and | 
 | 394 |     the 5th field is "r3" and value "3" is the release version. | 
 | 395 |  | 
 | 396 |     Aux version return from this function 4380003. | 
 | 397 |     """ | 
 | 398 |  | 
 | 399 |     # Commit version. | 
| Joy Onyerikwu | 004ad3c | 2018-06-11 16:29:56 -0500 | [diff] [blame] | 400 |     count = re.findall("-(\\d{1,4})-", version_id) | 
| George Keishing | 3511a3f | 2018-04-19 10:38:30 -0500 | [diff] [blame] | 401 |  | 
 | 402 |     # Release version. | 
| Joy Onyerikwu | 004ad3c | 2018-06-11 16:29:56 -0500 | [diff] [blame] | 403 |     release = re.findall("-r(\\d{1,4})", version_id) | 
| George Keishing | 3511a3f | 2018-04-19 10:38:30 -0500 | [diff] [blame] | 404 |     if release: | 
 | 405 |         aux_version = count[0] + "{0:0>4}".format(release[0]) | 
 | 406 |     else: | 
 | 407 |         aux_version = count[0] + "0000" | 
 | 408 |  | 
 | 409 |     return aux_version | 
| Michael Walsh | 27b14a6 | 2018-05-24 11:05:07 -0500 | [diff] [blame] | 410 |  | 
 | 411 |  | 
 | 412 | def get_fru_info(): | 
 | 413 |     r""" | 
 | 414 |     Get fru info and return it as a list of dictionaries. | 
 | 415 |  | 
 | 416 |     The data is obtained by issuing the IPMI "fru print -N 50" command.  An | 
 | 417 |     example is shown below: | 
 | 418 |  | 
 | 419 |     FRU Device Description : Builtin FRU Device (ID 0) | 
 | 420 |      Device not present (Unspecified error) | 
 | 421 |  | 
 | 422 |     FRU Device Description : cpu0 (ID 1) | 
 | 423 |      Board Mfg Date        : Sun Dec 31 18:00:00 1995 | 
| George Keishing | e0a8128 | 2018-06-08 10:02:30 -0500 | [diff] [blame] | 424 |      Board Mfg             : <Manufacturer Name> | 
| Michael Walsh | 27b14a6 | 2018-05-24 11:05:07 -0500 | [diff] [blame] | 425 |      Board Product         : PROCESSOR MODULE | 
 | 426 |      Board Serial          : YA1934315964 | 
 | 427 |      Board Part Number     : 02CY209 | 
 | 428 |  | 
 | 429 |     FRU Device Description : cpu1 (ID 2) | 
 | 430 |      Board Mfg Date        : Sun Dec 31 18:00:00 1995 | 
| George Keishing | e0a8128 | 2018-06-08 10:02:30 -0500 | [diff] [blame] | 431 |      Board Mfg             : <Manufacturer Name> | 
| Michael Walsh | 27b14a6 | 2018-05-24 11:05:07 -0500 | [diff] [blame] | 432 |      Board Product         : PROCESSOR MODULE | 
 | 433 |      Board Serial          : YA1934315965 | 
 | 434 |      Board Part Number     : 02CY209 | 
 | 435 |  | 
 | 436 |     For the data shown above, the following list of dictionaries will be | 
 | 437 |     returned. | 
 | 438 |  | 
 | 439 |     fru_obj: | 
 | 440 |       fru_obj[0]: | 
 | 441 |         [fru_device_description]:  Builtin FRU Device (ID 0) | 
 | 442 |         [state]:                   Device not present (Unspecified error) | 
 | 443 |       fru_obj[1]: | 
 | 444 |         [fru_device_description]:  cpu0 (ID 1) | 
 | 445 |         [board_mfg_date]:          Sun Dec 31 18:00:00 1995 | 
| George Keishing | e0a8128 | 2018-06-08 10:02:30 -0500 | [diff] [blame] | 446 |         [board_mfg]:               <Manufacturer Name> | 
| Michael Walsh | 27b14a6 | 2018-05-24 11:05:07 -0500 | [diff] [blame] | 447 |         [board_product]:           PROCESSOR MODULE | 
 | 448 |         [board_serial]:            YA1934315964 | 
 | 449 |         [board_part_number]:       02CY209 | 
 | 450 |       fru_obj[2]: | 
 | 451 |         [fru_device_description]:  cpu1 (ID 2) | 
 | 452 |         [board_mfg_date]:          Sun Dec 31 18:00:00 1995 | 
| George Keishing | e0a8128 | 2018-06-08 10:02:30 -0500 | [diff] [blame] | 453 |         [board_mfg]:               <Manufacturer Name> | 
| Michael Walsh | 27b14a6 | 2018-05-24 11:05:07 -0500 | [diff] [blame] | 454 |         [board_product]:           PROCESSOR MODULE | 
 | 455 |         [board_serial]:            YA1934315965 | 
 | 456 |         [board_part_number]:       02CY209 | 
 | 457 |     """ | 
 | 458 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 459 |     status, ret_values = grk.run_key_u( | 
 | 460 |         "Run IPMI Standard Command  fru print -N 50" | 
 | 461 |     ) | 
| Michael Walsh | 27b14a6 | 2018-05-24 11:05:07 -0500 | [diff] [blame] | 462 |  | 
 | 463 |     # Manipulate the "Device not present" line to create a "state" key. | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 464 |     ret_values = re.sub( | 
 | 465 |         "Device not present", "state : Device not present", ret_values | 
 | 466 |     ) | 
| Michael Walsh | 27b14a6 | 2018-05-24 11:05:07 -0500 | [diff] [blame] | 467 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 468 |     return [ | 
 | 469 |         vf.key_value_outbuf_to_dict(x) for x in re.split("\n\n", ret_values) | 
 | 470 |     ] | 
| Michael Walsh | 61224e6 | 2018-05-30 17:58:42 -0500 | [diff] [blame] | 471 |  | 
 | 472 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 473 | def get_component_fru_info(component="cpu", fru_objs=None): | 
| Michael Walsh | 61224e6 | 2018-05-30 17:58:42 -0500 | [diff] [blame] | 474 |     r""" | 
 | 475 |     Get fru info for the given component and return it as a list of | 
 | 476 |     dictionaries. | 
 | 477 |  | 
 | 478 |     This function calls upon get_fru_info and then filters out the unwanted | 
 | 479 |     entries.  See get_fru_info's prolog for a layout of the data. | 
 | 480 |  | 
 | 481 |     Description of argument(s): | 
| Joy Onyerikwu | 004ad3c | 2018-06-11 16:29:56 -0500 | [diff] [blame] | 482 |     component                       The component (e.g. "cpu", "dimm", etc.). | 
 | 483 |     fru_objs                        A fru_objs list such as the one returned | 
 | 484 |                                     by get_fru_info.  If this is None, then | 
 | 485 |                                     this function will call get_fru_info to | 
 | 486 |                                     obtain such a list. | 
 | 487 |                                     Supplying this argument may improve | 
 | 488 |                                     performance if this function is to be | 
 | 489 |                                     called multiple times. | 
| Michael Walsh | 61224e6 | 2018-05-30 17:58:42 -0500 | [diff] [blame] | 490 |     """ | 
 | 491 |  | 
| Michael Walsh | a95e4ef | 2018-06-06 17:53:04 -0500 | [diff] [blame] | 492 |     if fru_objs is None: | 
 | 493 |         fru_objs = get_fru_info() | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 494 |     return [ | 
 | 495 |         x | 
 | 496 |         for x in fru_objs | 
 | 497 |         if re.match(component + "([0-9]+)? ", x["fru_device_description"]) | 
 | 498 |     ] | 
| Rahul Maheshwari | 24e0e79 | 2019-02-12 22:40:23 -0600 | [diff] [blame] | 499 |  | 
 | 500 |  | 
 | 501 | def get_user_info(userid, channel_number=1): | 
 | 502 |     r""" | 
 | 503 |     Get user info using channel command and return it as a dictionary. | 
 | 504 |  | 
 | 505 |     Description of argument(s): | 
 | 506 |     userid          The userid (e.g. "1", "2", etc.). | 
 | 507 |     channel_number  The user's channel number (e.g. "1"). | 
 | 508 |  | 
| Michael Walsh | e733b26 | 2019-12-09 11:45:24 -0600 | [diff] [blame] | 509 |     Note: If userid is blank, this function will return a list of dictionaries.  Each list entry represents | 
 | 510 |     one userid record. | 
 | 511 |  | 
| Rahul Maheshwari | 24e0e79 | 2019-02-12 22:40:23 -0600 | [diff] [blame] | 512 |     The data is obtained by issuing the IPMI "channel getaccess" command.  An | 
 | 513 |     example is shown below for user id 1 and channel number 1. | 
 | 514 |  | 
 | 515 |     Maximum User IDs     : 15 | 
 | 516 |     Enabled User IDs     : 1 | 
 | 517 |     User ID              : 1 | 
 | 518 |     User Name            : root | 
 | 519 |     Fixed Name           : No | 
 | 520 |     Access Available     : callback | 
 | 521 |     Link Authentication  : enabled | 
 | 522 |     IPMI Messaging       : enabled | 
 | 523 |     Privilege Level      : ADMINISTRATOR | 
 | 524 |     Enable Status        : enabled | 
 | 525 |  | 
 | 526 |     For the data shown above, the following dictionary will be returned. | 
 | 527 |  | 
 | 528 |     user_info: | 
 | 529 |       [maximum_userids]:     15 | 
 | 530 |       [enabled_userids:      1 | 
 | 531 |       [userid]               1 | 
 | 532 |       [user_name]            root | 
 | 533 |       [fixed_name]           No | 
 | 534 |       [access_available]     callback | 
 | 535 |       [link_authentication]  enabled | 
 | 536 |       [ipmi_messaging]       enabled | 
 | 537 |       [privilege_level]      ADMINISTRATOR | 
 | 538 |       [enable_status]        enabled | 
| Rahul Maheshwari | 24e0e79 | 2019-02-12 22:40:23 -0600 | [diff] [blame] | 539 |     """ | 
 | 540 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 541 |     status, ret_values = grk.run_key_u( | 
 | 542 |         "Run IPMI Standard Command  channel getaccess " | 
 | 543 |         + str(channel_number) | 
 | 544 |         + " " | 
 | 545 |         + str(userid) | 
 | 546 |     ) | 
| Rahul Maheshwari | 24e0e79 | 2019-02-12 22:40:23 -0600 | [diff] [blame] | 547 |  | 
| Michael Walsh | e733b26 | 2019-12-09 11:45:24 -0600 | [diff] [blame] | 548 |     if userid == "": | 
 | 549 |         return vf.key_value_outbuf_to_dicts(ret_values, process_indent=1) | 
 | 550 |     else: | 
 | 551 |         return vf.key_value_outbuf_to_dict(ret_values, process_indent=1) | 
| George Keishing | 45511e8 | 2019-10-15 01:26:55 -0500 | [diff] [blame] | 552 |  | 
 | 553 |  | 
 | 554 | def channel_getciphers_ipmi(): | 
| George Keishing | 45511e8 | 2019-10-15 01:26:55 -0500 | [diff] [blame] | 555 |     r""" | 
 | 556 |     Run 'channel getciphers ipmi' command and return the result as a list of dictionaries. | 
 | 557 |  | 
 | 558 |     Example robot code: | 
 | 559 |     ${ipmi_channel_ciphers}=  Channel Getciphers IPMI | 
 | 560 |     Rprint Vars  ipmi_channel_ciphers | 
 | 561 |  | 
 | 562 |     Example output: | 
 | 563 |     ipmi_channel_ciphers: | 
 | 564 |       [0]: | 
 | 565 |         [id]:                                         3 | 
 | 566 |         [iana]:                                       N/A | 
 | 567 |         [auth_alg]:                                   hmac_sha1 | 
 | 568 |         [integrity_alg]:                              hmac_sha1_96 | 
 | 569 |         [confidentiality_alg]:                        aes_cbc_128 | 
 | 570 |       [1]: | 
 | 571 |         [id]:                                         17 | 
 | 572 |         [iana]:                                       N/A | 
 | 573 |         [auth_alg]:                                   hmac_sha256 | 
 | 574 |         [integrity_alg]:                              sha256_128 | 
 | 575 |         [confidentiality_alg]:                        aes_cbc_128 | 
 | 576 |     """ | 
 | 577 |  | 
 | 578 |     cmd_buf = "channel getciphers ipmi | sed -re 's/ Alg/_Alg/g'" | 
 | 579 |     stdout, stderr, rc = execute_ipmi_cmd(cmd_buf, "external", print_output=0) | 
 | 580 |     return vf.outbuf_to_report(stdout) | 
| Tony Lee | 9bca44b | 2019-12-13 09:34:26 +0800 | [diff] [blame] | 581 |  | 
 | 582 |  | 
 | 583 | def get_device_id_config(): | 
 | 584 |     r""" | 
 | 585 |     Get the device id config data and return as a dictionary. | 
 | 586 |  | 
 | 587 |     Example: | 
 | 588 |  | 
 | 589 |     dev_id_config =  get_device_id_config() | 
 | 590 |     print_vars(dev_id_config) | 
 | 591 |  | 
 | 592 |     dev_id_config: | 
 | 593 |         [manuf_id]:            7244 | 
 | 594 |         [addn_dev_support]:     141 | 
 | 595 |         [prod_id]:            16976 | 
 | 596 |         [aux]:                    0 | 
 | 597 |         [id]:                    32 | 
 | 598 |         [revision]:             129 | 
 | 599 |         [device_revision]:        1 | 
 | 600 |     """ | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 601 |     stdout, stderr, rc = bsu.bmc_execute_command( | 
 | 602 |         "cat /usr/share/ipmi-providers/dev_id.json" | 
 | 603 |     ) | 
| Tony Lee | 9bca44b | 2019-12-13 09:34:26 +0800 | [diff] [blame] | 604 |  | 
 | 605 |     result = json.loads(stdout) | 
 | 606 |  | 
 | 607 |     # Create device revision field for the user. | 
 | 608 |     # Reference IPMI specification v2.0 "Get Device ID Command" | 
 | 609 |     # [7]   1 = device provides Device SDRs | 
 | 610 |     #       0 = device does not provide Device SDRs | 
 | 611 |     # [6:4] reserved. Return as 0. | 
 | 612 |     # [3:0] Device Revision, binary encoded. | 
 | 613 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 614 |     result["device_revision"] = result["revision"] & 0x0F | 
| Tony Lee | 9bca44b | 2019-12-13 09:34:26 +0800 | [diff] [blame] | 615 |  | 
 | 616 |     return result | 
| Rahul Maheshwari | 02ea62c | 2020-02-21 05:06:13 -0600 | [diff] [blame] | 617 |  | 
 | 618 |  | 
 | 619 | def get_chassis_status(): | 
 | 620 |     r""" | 
 | 621 |     Get IPMI chassis status data and return it as a dictionary. | 
 | 622 |  | 
 | 623 |     The data is obtained by issuing the IPMI "chassis status" command. An | 
 | 624 |     example is shown below: | 
 | 625 |  | 
 | 626 |     System Power              : off | 
 | 627 |     Power Overload            : false | 
 | 628 |     Power Interlock           : inactive | 
 | 629 |     Main Power Fault          : false | 
 | 630 |     Power Control Fault       : false | 
 | 631 |     Power Restore Policy      : previous | 
 | 632 |     Last Power Event          : | 
 | 633 |     Chassis Intrusion         : inactive | 
 | 634 |     Front-Panel Lockout       : inactive | 
 | 635 |     Drive Fault               : false | 
 | 636 |     Cooling/Fan Fault         : false | 
 | 637 |     Sleep Button Disable      : not allowed | 
 | 638 |     Diag Button Disable       : not allowed | 
 | 639 |     Reset Button Disable      : not allowed | 
 | 640 |     Power Button Disable      : allowed | 
 | 641 |     Sleep Button Disabled     : false | 
 | 642 |     Diag Button Disabled      : false | 
 | 643 |     Reset Button Disabled     : false | 
 | 644 |     Power Button Disabled     : false | 
 | 645 |  | 
 | 646 |     For the data shown above, the following dictionary will be returned. | 
 | 647 |  | 
 | 648 |     chassis_status: | 
 | 649 |       [system_power]:                        off | 
 | 650 |       [power_overload]:                      false | 
 | 651 |       [power_interlock]:                     inactive | 
 | 652 |       [main_power_fault]:                    false | 
 | 653 |       [power_control_fault]:                 false | 
 | 654 |       [power_restore_policy]:                previous | 
 | 655 |       [last_power_event]: | 
 | 656 |       [chassis_intrusion]:                   inactive | 
 | 657 |       [front-panel_lockout]:                 inactive | 
 | 658 |       [drive_fault]:                         false | 
 | 659 |       [cooling/fan_fault]:                   false | 
 | 660 |       [sleep_button_disable]:                not allowed | 
 | 661 |       [diag_button_disable]:                 not allowed | 
 | 662 |       [reset_button_disable]:                not allowed | 
 | 663 |       [power_button_disable]:                allowed | 
 | 664 |       [sleep_button_disabled]:               false | 
 | 665 |       [diag_button_disabled]:                false | 
 | 666 |       [reset_button_disabled]:               false | 
 | 667 |       [power_button_disabled]:               false | 
 | 668 |     """ | 
 | 669 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 670 |     status, ret_values = grk.run_key_u( | 
| ishwaryamathim | 372cd86 | 2023-11-14 18:12:23 +0000 | [diff] [blame] | 671 |         "Run External IPMI Standard Command  chassis status" | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 672 |     ) | 
| Rahul Maheshwari | 02ea62c | 2020-02-21 05:06:13 -0600 | [diff] [blame] | 673 |     result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1) | 
 | 674 |  | 
 | 675 |     return result | 
| Tony Lee | 18c6f9a | 2020-02-18 17:00:20 +0800 | [diff] [blame] | 676 |  | 
 | 677 |  | 
 | 678 | def get_channel_info(channel_number=1): | 
 | 679 |     r""" | 
 | 680 |     Get the channel info and return as a dictionary. | 
 | 681 |     Example: | 
 | 682 |  | 
 | 683 |     channel_info: | 
 | 684 |       [channel_0x2_info]: | 
 | 685 |         [channel_medium_type]:                        802.3 LAN | 
 | 686 |         [channel_protocol_type]:                      IPMB-1.0 | 
 | 687 |         [session_support]:                            multi-session | 
 | 688 |         [active_session_count]:                       0 | 
 | 689 |         [protocol_vendor_id]:                         7154 | 
| Tony Lee | 87c9cb9 | 2020-03-04 14:47:09 +0800 | [diff] [blame] | 690 |       [volatile(active)_settings]: | 
| Tony Lee | 18c6f9a | 2020-02-18 17:00:20 +0800 | [diff] [blame] | 691 |         [alerting]:                                   enabled | 
 | 692 |         [per-message_auth]:                           enabled | 
 | 693 |         [user_level_auth]:                            enabled | 
 | 694 |         [access_mode]:                                always available | 
| Tony Lee | 87c9cb9 | 2020-03-04 14:47:09 +0800 | [diff] [blame] | 695 |       [non-volatile_settings]: | 
| Tony Lee | 18c6f9a | 2020-02-18 17:00:20 +0800 | [diff] [blame] | 696 |         [alerting]:                                   enabled | 
 | 697 |         [per-message_auth]:                           enabled | 
 | 698 |         [user_level_auth]:                            enabled | 
 | 699 |         [access_mode]:                                always available | 
 | 700 |     """ | 
 | 701 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 702 |     status, ret_values = grk.run_key_u( | 
 | 703 |         "Run IPMI Standard Command  channel info " + str(channel_number) | 
 | 704 |     ) | 
| Tony Lee | 87c9cb9 | 2020-03-04 14:47:09 +0800 | [diff] [blame] | 705 |     key_var_list = list(filter(None, ret_values.split("\n"))) | 
 | 706 |     # To match the dict format, add a colon after 'Volatile(active) Settings' and 'Non-Volatile Settings' | 
 | 707 |     # respectively. | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 708 |     key_var_list[6] = "Volatile(active) Settings:" | 
 | 709 |     key_var_list[11] = "Non-Volatile Settings:" | 
| Tony Lee | 87c9cb9 | 2020-03-04 14:47:09 +0800 | [diff] [blame] | 710 |     result = vf.key_value_list_to_dict(key_var_list, process_indent=1) | 
| Tony Lee | 18c6f9a | 2020-02-18 17:00:20 +0800 | [diff] [blame] | 711 |     return result | 
| Tony Lee | 3d351ee | 2020-02-19 10:21:04 +0800 | [diff] [blame] | 712 |  | 
 | 713 |  | 
 | 714 | def get_user_access_ipmi(channel_number=1): | 
| Tony Lee | 3d351ee | 2020-02-19 10:21:04 +0800 | [diff] [blame] | 715 |     r""" | 
 | 716 |     Run 'user list [<channel number>]' command and return the result as a list of dictionaries. | 
 | 717 |  | 
 | 718 |     Example robot code: | 
 | 719 |     ${users_access}=  user list 1 | 
 | 720 |     Rprint Vars  users_access | 
 | 721 |  | 
 | 722 |     Example output: | 
 | 723 |     users: | 
 | 724 |       [0]: | 
 | 725 |         [id]:                                         1 | 
 | 726 |         [name]:                                       root | 
 | 727 |         [callin]:                                     false | 
 | 728 |         [link]:                                       true | 
 | 729 |         [auth]:                                       true | 
 | 730 |         [ipmi]:                                       ADMINISTRATOR | 
 | 731 |       [1]: | 
 | 732 |         [id]:                                         2 | 
 | 733 |         [name]:                                       axzIDwnz | 
 | 734 |         [callin]:                                     true | 
 | 735 |         [link]:                                       false | 
 | 736 |         [auth]:                                       true | 
 | 737 |         [ipmi]:                                       ADMINISTRATOR | 
 | 738 |     """ | 
 | 739 |  | 
 | 740 |     cmd_buf = "user list " + str(channel_number) | 
 | 741 |     stdout, stderr, rc = execute_ipmi_cmd(cmd_buf, "external", print_output=0) | 
 | 742 |     return vf.outbuf_to_report(stdout) | 
| Tony Lee | 0754c5f | 2020-03-13 19:38:24 +0800 | [diff] [blame] | 743 |  | 
 | 744 |  | 
| nagarjunb22 | 9845074 | 2022-04-19 12:00:02 +0530 | [diff] [blame] | 745 | def get_channel_auth_capabilities(channel_number=1, privilege_level=4): | 
| Tony Lee | 0754c5f | 2020-03-13 19:38:24 +0800 | [diff] [blame] | 746 |     r""" | 
 | 747 |     Get the channel authentication capabilities and return as a dictionary. | 
 | 748 |  | 
 | 749 |     Example: | 
 | 750 |  | 
 | 751 |     channel_auth_cap: | 
 | 752 |         [channel_number]:                               2 | 
 | 753 |         [ipmi_v1.5__auth_types]: | 
 | 754 |         [kg_status]:                                    default (all zeroes) | 
 | 755 |         [per_message_authentication]:                   enabled | 
 | 756 |         [user_level_authentication]:                    enabled | 
 | 757 |         [non-null_user_names_exist]:                    yes | 
 | 758 |         [null_user_names_exist]:                        no | 
 | 759 |         [anonymous_login_enabled]:                      no | 
 | 760 |         [channel_supports_ipmi_v1.5]:                   no | 
 | 761 |         [channel_supports_ipmi_v2.0]:                   yes | 
 | 762 |     """ | 
 | 763 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 764 |     status, ret_values = grk.run_key_u( | 
 | 765 |         "Run IPMI Standard Command  channel authcap " | 
 | 766 |         + str(channel_number) | 
 | 767 |         + " " | 
 | 768 |         + str(privilege_level) | 
 | 769 |     ) | 
| Tony Lee | 0754c5f | 2020-03-13 19:38:24 +0800 | [diff] [blame] | 770 |     result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1) | 
 | 771 |  | 
 | 772 |     return result | 
| chithrag | 0a8c878 | 2022-03-01 12:35:00 +0000 | [diff] [blame] | 773 |  | 
 | 774 |  | 
 | 775 | def fetch_date(date): | 
 | 776 |     r""" | 
 | 777 |     Removes prefix 0 in a date in given date | 
 | 778 |  | 
 | 779 |     Example : 08/12/2021 then returns 8/12/2021 | 
 | 780 |     """ | 
 | 781 |  | 
 | 782 |     date = date.lstrip("0") | 
 | 783 |     return date | 
 | 784 |  | 
 | 785 |  | 
 | 786 | def fetch_added_sel_date(entry): | 
 | 787 |     r""" | 
 | 788 |     Split sel entry string with with | and join only the date with space | 
 | 789 |  | 
 | 790 |     Example : If entry given is, "a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 |  | Asserted" | 
 | 791 |     Then the result will be "02/14/2020 01:16:58" | 
 | 792 |     """ | 
 | 793 |  | 
 | 794 |     temp = entry.split(" | ") | 
 | 795 |     date = temp[1] + " " + temp[2] | 
 | 796 |     print(date) | 
 | 797 |     return date | 
 | 798 |  | 
 | 799 |  | 
 | 800 | def prefix_bytes(listx): | 
 | 801 |     r""" | 
 | 802 |     prefixes byte strings in list | 
 | 803 |  | 
 | 804 |     Example: | 
 | 805 |     ${listx} = ['01', '02', '03'] | 
 | 806 |     ${listx}=  Prefix Bytes  ${listx} | 
 | 807 |     then, | 
 | 808 |     ${listx}= ['0x01', '0x02', '0x03'] | 
 | 809 |  | 
 | 810 |     """ | 
 | 811 |  | 
 | 812 |     listy = [] | 
 | 813 |     for item in listx: | 
 | 814 |         item = "0x" + item | 
 | 815 |         listy.append(item) | 
 | 816 |     return listy | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 817 |  | 
 | 818 |  | 
| chithrag | 6b279b3 | 2022-05-05 08:28:05 +0000 | [diff] [blame] | 819 | def modify_and_fetch_threshold(old_threshold, threshold_list): | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 820 |     r""" | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 821 |     Description of argument(s): | 
 | 822 |  | 
| chithrag | 6b279b3 | 2022-05-05 08:28:05 +0000 | [diff] [blame] | 823 |         old_threshold              List of threshold values of sensor, | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 824 |         threshold_list             List of higher and lower of critical and non-critical values. | 
| chithrag | 6b279b3 | 2022-05-05 08:28:05 +0000 | [diff] [blame] | 825 |                                    i,e [ "lcr", "lnc", "unc", "ucr" ] | 
 | 826 |  | 
 | 827 |     Gets old threshold values from sensor and threshold levels, | 
 | 828 |     then returns the list of new threshold and the dict of threshold levels | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 829 |  | 
 | 830 |     For example : | 
| chithrag | 6b279b3 | 2022-05-05 08:28:05 +0000 | [diff] [blame] | 831 |     1. If old_threshold list is [ 1, 2, 3, 4] then the newthreshold_list will be [ 101, 102, 103, 104 ]. | 
 | 832 |        If old_threshold has 'na' the same will be appended to new list, eg: [ 101, 102, 103, 104, 'na']. | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 833 |  | 
| chithrag | 6b279b3 | 2022-05-05 08:28:05 +0000 | [diff] [blame] | 834 |     2. The newthreshold_list will be zipped to dictionary with threshold_list levels, | 
 | 835 |        Example : threshold_dict = { 'lcr': 101, 'lnc': 102, 'unc': 103, 'ucr': 104 } | 
 | 836 |  | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 837 |     """ | 
 | 838 |  | 
| chithrag | 6b279b3 | 2022-05-05 08:28:05 +0000 | [diff] [blame] | 839 |     # Adding the difference of 100 as less than this value, | 
 | 840 |     # may not have greater impact as the sensor considered is a fan sensor. | 
 | 841 |     # The set threshold may round off for certain values below 100. | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 842 |     n = 100 | 
 | 843 |     newthreshold_list = [] | 
 | 844 |     for th in old_threshold: | 
 | 845 |         th = th.strip() | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 846 |         if th == "na": | 
 | 847 |             newthreshold_list.append("na") | 
| chithrag | ff43db9 | 2022-03-01 13:13:48 +0000 | [diff] [blame] | 848 |         else: | 
 | 849 |             x = int(float(th)) + n | 
 | 850 |             newthreshold_list.append(x) | 
 | 851 |             n = n + 100 | 
 | 852 |     threshold_dict = dict(zip(threshold_list, newthreshold_list)) | 
 | 853 |     return newthreshold_list, threshold_dict |