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( 54 "Run External IPMI Standard Command sol info" 55 ) 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 71 72def set_sol_setting(setting_name, setting_value): 73 r""" 74 Set SOL setting with given value. 75 76 # Description of argument(s): 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"). 80 """ 81 82 status, ret_values = grk.run_key_u( 83 "Run External IPMI Standard Command sol set " 84 + setting_name 85 + " " 86 + setting_value 87 ) 88 89 return status 90 91 92def execute_ipmi_cmd( 93 cmd_string, ipmi_cmd_type="inband", print_output=1, ignore_err=0, **options 94): 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. 110 options These are passed directly to the 111 create_ipmi_ext_command_string function. 112 See that function's prolog for details. 113 """ 114 115 if ipmi_cmd_type == "inband": 116 IPMI_INBAND_CMD = BuiltIn().get_variable_value("${IPMI_INBAND_CMD}") 117 cmd_buf = IPMI_INBAND_CMD + " " + cmd_string 118 return bsu.os_execute_command( 119 cmd_buf, print_out=print_output, ignore_err=ignore_err 120 ) 121 122 if ipmi_cmd_type == "external": 123 cmd_buf = ic.create_ipmi_ext_command_string(cmd_string, **options) 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 ) 130 return stdout, stderr, rc 131 132 133def get_lan_print_dict(channel_number="", ipmi_cmd_type="external"): 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 175 Description of argument(s): 176 ipmi_cmd_type The type of ipmi command to use (e.g. 177 'inband', 'external'). 178 """ 179 180 channel_number = str(channel_number) 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. 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 ) 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). 197 cmd_buf = "lan print " + channel_number + " | grep -E -v '^[ ]+: '" 198 stdout2, stderr, rc = execute_ipmi_cmd( 199 cmd_buf, ipmi_cmd_type, print_output=0 200 ) 201 202 # Make auth_type_enable_dict sub-dictionary... 203 auth_type_enable_dict = vf.key_value_outbuf_to_dict( 204 stdout1, to_lower=0, underscores=0 205 ) 206 207 # Create the lan_print_dict... 208 lan_print_dict = vf.key_value_outbuf_to_dict( 209 stdout2, to_lower=0, underscores=0 210 ) 211 # Re-assign 'Auth Type Enable' to contain the auth_type_enable_dict. 212 lan_print_dict["Auth Type Enable"] = auth_type_enable_dict 213 214 return lan_print_dict 215 216 217def get_ipmi_power_reading(strip_watts=1): 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 242 243 Description of argument(s): 244 strip_watts Strip all dictionary values of the 245 trailing " Watts" substring. 246 """ 247 248 status, ret_values = grk.run_key_u( 249 "Run IPMI Standard Command dcmi power reading" 250 ) 251 result = vf.key_value_outbuf_to_dict(ret_values) 252 253 if strip_watts: 254 result.update((k, re.sub(" Watts$", "", v)) for k, v in result.items()) 255 256 return result 257 258 259def get_mc_info(): 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 311 status, ret_values = grk.run_key_u("Run IPMI Standard Command mc info") 312 result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1) 313 314 return result 315 316 317def get_sdr_info(): 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 352 status, ret_values = grk.run_key_u("Run IPMI Standard Command sdr info") 353 result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1) 354 355 return result 356 357 358def fetch_oem_sdr_count(sdr_data): 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 384def get_aux_version(version_id): 385 r""" 386 Get IPMI Aux version info data and return it. 387 388 Description of argument(s): 389 version_id The data is obtained by from BMC 390 /etc/os-release 391 (e.g. "xxx-v2.1-438-g0030304-r3-gfea8585"). 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. 400 count = re.findall("-(\\d{1,4})-", version_id) 401 402 # Release version. 403 release = re.findall("-r(\\d{1,4})", version_id) 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 410 411 412def 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 424 Board Mfg : <Manufacturer Name> 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 431 Board Mfg : <Manufacturer Name> 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 446 [board_mfg]: <Manufacturer Name> 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 453 [board_mfg]: <Manufacturer Name> 454 [board_product]: PROCESSOR MODULE 455 [board_serial]: YA1934315965 456 [board_part_number]: 02CY209 457 """ 458 459 status, ret_values = grk.run_key_u( 460 "Run IPMI Standard Command fru print -N 50" 461 ) 462 463 # Manipulate the "Device not present" line to create a "state" key. 464 ret_values = re.sub( 465 "Device not present", "state : Device not present", ret_values 466 ) 467 468 return [ 469 vf.key_value_outbuf_to_dict(x) for x in re.split("\n\n", ret_values) 470 ] 471 472 473def get_component_fru_info(component="cpu", fru_objs=None): 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): 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. 490 """ 491 492 if fru_objs is None: 493 fru_objs = get_fru_info() 494 return [ 495 x 496 for x in fru_objs 497 if re.match(component + "([0-9]+)? ", x["fru_device_description"]) 498 ] 499 500 501def 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 509 Note: If userid is blank, this function will return a list of dictionaries. Each list entry represents 510 one userid record. 511 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 539 """ 540 541 status, ret_values = grk.run_key_u( 542 "Run IPMI Standard Command channel getaccess " 543 + str(channel_number) 544 + " " 545 + str(userid) 546 ) 547 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) 552 553 554def channel_getciphers_ipmi(): 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) 581 582 583def 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 """ 601 stdout, stderr, rc = bsu.bmc_execute_command( 602 "cat /usr/share/ipmi-providers/dev_id.json" 603 ) 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 614 result["device_revision"] = result["revision"] & 0x0F 615 616 return result 617 618 619def 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 670 status, ret_values = grk.run_key_u( 671 "Run External IPMI Standard Command chassis status" 672 ) 673 result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1) 674 675 return result 676 677 678def 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 690 [volatile(active)_settings]: 691 [alerting]: enabled 692 [per-message_auth]: enabled 693 [user_level_auth]: enabled 694 [access_mode]: always available 695 [non-volatile_settings]: 696 [alerting]: enabled 697 [per-message_auth]: enabled 698 [user_level_auth]: enabled 699 [access_mode]: always available 700 """ 701 702 status, ret_values = grk.run_key_u( 703 "Run IPMI Standard Command channel info " + str(channel_number) 704 ) 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. 708 key_var_list[6] = "Volatile(active) Settings:" 709 key_var_list[11] = "Non-Volatile Settings:" 710 result = vf.key_value_list_to_dict(key_var_list, process_indent=1) 711 return result 712 713 714def get_user_access_ipmi(channel_number=1): 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) 743 744 745def get_channel_auth_capabilities(channel_number=1, privilege_level=4): 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 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 ) 770 result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1) 771 772 return result 773 774 775def 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 786def 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 800def 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 817 818 819def modify_and_fetch_threshold(old_threshold, threshold_list): 820 r""" 821 Description of argument(s): 822 823 old_threshold List of threshold values of sensor, 824 threshold_list List of higher and lower of critical and non-critical values. 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 829 830 For example : 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']. 833 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 837 """ 838 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. 842 n = 100 843 newthreshold_list = [] 844 for th in old_threshold: 845 th = th.strip() 846 if th == "na": 847 newthreshold_list.append("na") 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 854