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