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