1*** Settings ***
2Documentation   This module is for IPMI client for copying ipmitool to
3...             openbmc box and execute ipmitool IPMI standard
4...             command. IPMI raw command will use dbus-send command
5Resource        ../lib/resource.robot
6Resource        ../lib/connection_client.robot
7Resource        ../lib/utils.robot
8Resource        ../lib/state_manager.robot
9
10Library         String
11Library         var_funcs.py
12Library         ipmi_client.py
13Library         ../lib/bmc_ssh_utils.py
14
15*** Variables ***
16${dbusHostIpmicmd1}=   dbus-send --system  ${OPENBMC_BASE_URI}HostIpmi/1
17${dbusHostIpmiCmdReceivedMsg}=   ${OPENBMC_BASE_DBUS}.HostIpmi.ReceivedMessage
18${netfnByte}=          ${EMPTY}
19${cmdByte}=            ${EMPTY}
20${arrayByte}=          array:byte:
21${IPMI_USER_OPTIONS}   ${EMPTY}
22${IPMI_INBAND_CMD}=    ipmitool -C ${IPMI_CIPHER_LEVEL} -N ${IPMI_TIMEOUT} -p ${IPMI_PORT}
23${HOST}=               -H
24${RAW}=                raw
25${IPMITOOL_PATH}  /tmp/ipmitool
26
27*** Keywords ***
28
29Run IPMI Command
30    [Documentation]  Run the raw IPMI command.
31    [Arguments]  ${command}  ${fail_on_err}=${1}  &{options}
32
33    # Description of argument(s):
34    # command                       The IPMI command string to be executed
35    #                               (e.g. "power status").
36    # fail_on_err                   Fail if the IPMI command execution fails.
37    # options                       Additional ipmitool command options (e.g.
38    #                               -C=3, -I=lanplus, etc.).  Currently, only
39    #                               used for external IPMI commands.
40
41    ${resp}=  Run Keyword If  '${IPMI_COMMAND}' == 'External'
42    ...    Run External IPMI Raw Command  ${command}  ${fail_on_err}  &{options}
43    ...  ELSE IF  '${IPMI_COMMAND}' == 'Inband'
44    ...    Run Inband IPMI Raw Command  ${command}
45    ...  ELSE IF  '${IPMI_COMMAND}' == 'Dbus'
46    ...    Run Dbus IPMI RAW Command  ${command}
47    ...  ELSE  Fail  msg=Invalid IPMI Command type provided: ${IPMI_COMMAND}
48    [Return]  ${resp}
49
50
51Run IPMI Standard Command
52    [Documentation]  Run the standard IPMI command.
53    [Arguments]  ${command}  ${fail_on_err}=${1}  ${expected_rc}=${0}  &{options}
54
55    # Description of argument(s):
56    # command                       The IPMI command string to be executed
57    #                               (e.g. "0x06 0x36").
58    # fail_on_err                   Fail if the IPMI command execution fails.
59    # expected_rc                   The expected return code from the ipmi
60    #                               command (e.g. ${0}, ${1}, etc.).
61    # options                       Additional ipmitool command options (e.g.
62    #                               -C=3, -I=lanplus, etc.).  Currently, only
63    #                               used for external IPMI commands.
64
65    ${resp}=  Run Keyword If  '${IPMI_COMMAND}' == 'External'
66    ...    Run External IPMI Standard Command  ${command}  ${fail_on_err}  ${expected_rc}  &{options}
67    ...  ELSE IF  '${IPMI_COMMAND}' == 'Inband'
68    ...    Run Inband IPMI Standard Command  ${command}  ${fail_on_err}
69    ...  ELSE IF  '${IPMI_COMMAND}' == 'Dbus'
70    ...    Run Dbus IPMI Standard Command  ${command}
71    ...  ELSE  Fail  msg=Invalid IPMI Command type provided : ${IPMI_COMMAND}
72    [Return]  ${resp}
73
74
75Run Dbus IPMI RAW Command
76    [Documentation]  Run the raw IPMI command through dbus.
77    [Arguments]    ${command}
78    ${valueinBytes}=   Byte Conversion  ${command}
79    ${cmd}=   Catenate   ${dbushostipmicmd1} ${dbusHostIpmiCmdReceivedMsg}
80    ${cmd}=   Catenate   ${cmd} ${valueinBytes}
81    ${output}   ${stderr}=  Execute Command  ${cmd}  return_stderr=True
82    Should Be Empty      ${stderr}
83    set test variable    ${OUTPUT}     "${output}"
84
85
86Run Dbus IPMI Standard Command
87    [Documentation]  Run the standard IPMI command through dbus.
88    [Arguments]    ${command}
89    Copy ipmitool
90    ${stdout}    ${stderr}    ${output}=  Execute Command
91    ...    ${IPMITOOL_PATH} -I dbus ${command}    return_stdout=True
92    ...    return_stderr= True    return_rc=True
93    Should Be Equal    ${output}    ${0}    msg=${stderr}
94    [Return]    ${stdout}
95
96
97Run Inband IPMI Raw Command
98    [Documentation]  Run the raw IPMI command in-band.
99    [Arguments]  ${command}  ${fail_on_err}=${1}  ${os_host}=${OS_HOST}  ${os_username}=${OS_USERNAME}
100    ...          ${os_password}=${OS_PASSWORD}
101
102    # Description of argument(s):
103    # command                       The IPMI command string to be executed
104    #                               (e.g. "0x06 0x36").
105    # os_host                       The host name or IP address of the OS Host.
106    # os_username                   The OS host user name.
107    # os_password                   The OS host passwrd.
108
109    Login To OS Host  ${os_host}  ${os_username}  ${os_password}
110    Check If IPMI Tool Exist
111
112    ${ipmi_cmd}=  Catenate  ${IPMI_INBAND_CMD}  ${RAW}  ${command}
113    Qprint Issuing  ${ipmi_cmd}
114    ${stdout}  ${stderr}=  Execute Command  ${ipmi_cmd}  return_stderr=True
115    Return From Keyword If  ${fail_on_err} == ${0}  ${stderr}
116    Should Be Empty  ${stderr}  msg=${stdout}
117    [Return]  ${stdout}
118
119
120Run Inband IPMI Standard Command
121    [Documentation]  Run the standard IPMI command in-band.
122    [Arguments]  ${command}  ${fail_on_err}=${1}  ${os_host}=${OS_HOST}
123    ...          ${os_username}=${OS_USERNAME}  ${os_password}=${OS_PASSWORD}
124    ...          ${login_host}=${1}
125
126    # Description of argument(s):
127    # command                       The IPMI command string to be executed
128    #                               (e.g. "power status").
129    # os_host                       The host name or IP address of the OS Host.
130    # os_username                   The OS host user name.
131    # os_password                   The OS host passwrd.
132    # login_host                    Indicates that this keyword should login to host OS.
133
134    Run Keyword If  ${login_host} == ${1}
135    ...  Login To OS Host  ${os_host}  ${os_username}  ${os_password}
136    Check If IPMI Tool Exist
137
138    ${ipmi_cmd}=  Catenate  ${IPMI_INBAND_CMD}  ${command}
139    Qprint Issuing  ${ipmi_cmd}
140    ${stdout}  ${stderr}=  Execute Command  ${ipmi_cmd}  return_stderr=True
141    Return From Keyword If  ${fail_on_err} == ${0}  ${stderr}
142    Should Be Empty  ${stderr}  msg=${stdout}
143    [Return]  ${stdout}
144
145
146Run External IPMI Standard Command
147    [Documentation]  Run the external IPMI standard command.
148    [Arguments]  ${command}  ${fail_on_err}=${1}  ${expected_rc}=${0}  &{options}
149
150    # Description of argument(s):
151    # command                       The IPMI command string to be executed
152    #                               (e.g. "power status").  Note that if
153    #                               ${IPMI_USER_OPTIONS} has a value (e.g.
154    #                               "-vvv"), it will be pre-pended to this
155    #                               command string.
156    # fail_on_err                   Fail if the IPMI command execution fails.
157    # expected_rc                   The expected return code from the ipmi
158    #                               command (e.g. ${0}, ${1}, etc.).
159    # options                       Additional ipmitool command options (e.g.
160    #                               -C=3, -I=lanplus, etc.).
161
162    ${command_string}=  Process IPMI User Options  ${command}
163    ${ipmi_cmd}=  Create IPMI Ext Command String  ${command_string}  &{options}
164    Qprint Issuing  ${ipmi_cmd}
165    ${rc}  ${output}=  Run And Return RC and Output  ${ipmi_cmd}
166    Return From Keyword If  ${fail_on_err} == ${0}  ${output}
167    Should Be Equal  ${rc}  ${expected_rc}  msg=${output}
168    [Return]  ${output}
169
170
171Run External IPMI Raw Command
172    [Documentation]  Run the external IPMI raw command.
173    [Arguments]  ${command}  ${fail_on_err}=${1}  &{options}
174
175    # This keyword is a wrapper for 'Run External IPMI Standard Command'. See
176    # that keyword's prolog for argument details.  This keyword will pre-pend
177    # the word "raw" plus a space to command prior to calling 'Run External
178    # IPMI Standard Command'.
179
180    ${output}=  Run External IPMI Standard Command
181    ...  raw ${command}  ${fail_on_err}  &{options}
182    [Return]  ${output}
183
184
185Check If IPMI Tool Exist
186    [Documentation]  Check if IPMI Tool installed or not.
187    ${output}=  Execute Command  which ipmitool
188    Should Not Be Empty  ${output}  msg=ipmitool not installed.
189
190
191Activate SOL Via IPMI
192    [Documentation]  Start SOL using IPMI and route output to a file.
193    [Arguments]  ${file_path}=${IPMI_SOL_LOG_FILE}
194
195    # Description of argument(s):
196    # file_path                     The file path on the local machine (vs.
197    #                               OBMC) to collect SOL output. By default
198    #                               SOL output is collected at
199    #                               logs/sol_<BMC_IP> else user input location.
200
201    ${ipmi_cmd}=  Create IPMI Ext Command String  sol activate usesolkeepalive
202    Qprint Issuing  ${ipmi_cmd}
203    Start Process  ${ipmi_cmd}  shell=True  stdout=${file_path}
204    ...  alias=sol_proc
205
206
207Deactivate SOL Via IPMI
208    [Documentation]  Stop SOL using IPMI and return SOL output.
209    [Arguments]  ${file_path}=${IPMI_SOL_LOG_FILE}
210
211    # Description of argument(s):
212    # file_path                     The file path on the local machine to copy
213    #                               SOL output collected by above "Activate
214    #                               SOL Via IPMI" keyword.  By default it
215    #                               copies log from logs/sol_<BMC_IP>.
216
217    ${ipmi_cmd}=  Create IPMI Ext Command String  sol deactivate
218    Qprint Issuing  ${ipmi_cmd}
219    ${rc}  ${output}=  Run and Return RC and Output  ${ipmi_cmd}
220    Run Keyword If  ${rc} > 0  Run Keywords
221    ...  Run Keyword And Ignore Error  Terminate Process  sol_proc
222    ...  AND  Return From Keyword  ${output}
223
224    ${output}=  OperatingSystem.Get File  ${file_path}  encoding_errors=ignore
225
226    # Logging SOL output for debug purpose.
227    Log  ${output}
228
229    [Return]  ${output}
230
231
232Byte Conversion
233    [Documentation]   Byte Conversion method receives IPMI RAW commands as
234    ...               argument in string format.
235    ...               Sample argument is as follows
236    ...               "0x04 0x30 9 0x01 0x00 0x35 0x00 0x00 0x00 0x00 0x00
237    ...               0x00"
238    ...               IPMI RAW command format is as follows
239    ...               <netfn Byte> <cmd Byte> <Data Bytes..>
240    ...               This method converts IPMI command format into
241    ...               dbus command format  as follows
242    ...               <byte:seq-id> <byte:netfn> <byte:lun> <byte:cmd>
243    ...               <array:byte:data>
244    ...               Sample dbus  Host IPMI Received Message argument
245    ...               byte:0x00 byte:0x04 byte:0x00 byte:0x30
246    ...               array:byte:9,0x01,0x00,0x35,0x00,0x00,0x00,0x00,0x00,0x00
247    [Arguments]     ${args}
248    ${argLength}=   Get Length  ${args}
249    Set Global Variable  ${arrayByte}   array:byte:
250    @{listargs}=   Split String  ${args}
251    ${index}=   Set Variable   ${0}
252    FOR  ${word}  IN  @{listargs}
253         Run Keyword if   ${index} == 0   Set NetFn Byte  ${word}
254         Run Keyword if   ${index} == 1   Set Cmd Byte    ${word}
255         Run Keyword if   ${index} > 1    Set Array Byte  ${word}
256         ${index}=    Set Variable    ${index + 1}
257    END
258    ${length}=   Get Length  ${arrayByte}
259    ${length}=   Evaluate  ${length} - 1
260    ${arrayByteLocal}=  Get Substring  ${arrayByte}  0   ${length}
261    Set Global Variable  ${arrayByte}   ${arrayByteLocal}
262    ${valueinBytesWithArray}=   Catenate  byte:0x00   ${netfnByte}  byte:0x00
263    ${valueinBytesWithArray}=   Catenate  ${valueinBytesWithArray}  ${cmdByte}
264    ${valueinBytesWithArray}=   Catenate  ${valueinBytesWithArray} ${arrayByte}
265    ${valueinBytesWithoutArray}=   Catenate  byte:0x00 ${netfnByte}  byte:0x00
266    ${valueinBytesWithoutArray}=   Catenate  ${valueinBytesWithoutArray} ${cmdByte}
267    #   To Check scenario for smaller IPMI raw commands with only 2 arguments
268    #   instead of usual 12 arguments.
269    #   Sample small IPMI raw command: Run IPMI command 0x06 0x36
270    #   If IPMI raw argument length is only 9 then return value in bytes without
271    #   array population.
272    #   Equivalent dbus-send argument for smaller IPMI raw command:
273    #   byte:0x00 byte:0x06 byte:0x00 byte:0x36
274    Run Keyword if   ${argLength} == 9     Return from Keyword    ${valueinBytesWithoutArray}
275    [Return]    ${valueinBytesWithArray}
276
277
278Set NetFn Byte
279    [Documentation]  Set the network function byte.
280    [Arguments]    ${word}
281    ${netfnByteLocal}=  Catenate   byte:${word}
282    Set Global Variable  ${netfnByte}  ${netfnByteLocal}
283
284
285Set Cmd Byte
286    [Documentation]  Set the command byte.
287    [Arguments]    ${word}
288    ${cmdByteLocal}=  Catenate   byte:${word}
289    Set Global Variable  ${cmdByte}  ${cmdByteLocal}
290
291
292Set Array Byte
293    [Documentation]  Set the array byte.
294    [Arguments]    ${word}
295    ${arrayByteLocal}=   Catenate   SEPARATOR=  ${arrayByte}  ${word}
296    ${arrayByteLocal}=   Catenate   SEPARATOR=  ${arrayByteLocal}   ,
297    Set Global Variable  ${arrayByte}   ${arrayByteLocal}
298
299
300Copy ipmitool
301    [Documentation]  Copy the ipmitool to the BMC.
302    ${ipmitool_error}=  Catenate  The ipmitool program could not be found in the tools directory.
303    ...  It is not part of the automation code by default. You must manually copy or link the correct openbmc
304    ...  version of the tool in to the tools directory in order to run this test suite.
305
306    ${response}  ${stderr}  ${rc}=  BMC Execute Command
307    ...  which ipmitool  ignore_err=${1}
308    ${installed}=  Get Regexp Matches  ${response}  ipmitool
309    Run Keyword If  ${installed} == ['ipmitool']
310    ...  Run Keywords  Set Suite Variable  ${IPMITOOL_PATH}  ${response}
311    ...  AND  SSHLibrary.Open Connection     ${OPENBMC_HOST}
312    ...  AND  SSHLibrary.Login   ${OPENBMC_USERNAME}    ${OPENBMC_PASSWORD}
313    ...  AND  Return From Keyword
314
315    OperatingSystem.File Should Exist  tools/ipmitool  msg=${ipmitool_error}
316    Import Library      SCPLibrary      WITH NAME       scp
317    scp.Open connection     ${OPENBMC_HOST}     username=${OPENBMC_USERNAME}      password=${OPENBMC_PASSWORD}
318    scp.Put File    tools/ipmitool   /tmp
319    SSHLibrary.Open Connection     ${OPENBMC_HOST}
320    SSHLibrary.Login   ${OPENBMC_USERNAME}    ${OPENBMC_PASSWORD}
321    Execute Command     chmod +x ${IPMITOOL_PATH}
322
323
324Initiate Host Boot Via External IPMI
325    [Documentation]  Initiate host power on using external IPMI.
326    [Arguments]  ${wait}=${1}
327
328    # Description of argument(s):
329    # wait                          Indicates that this keyword should wait
330    #                               for host running state.
331
332    ${output}=  Run External IPMI Standard Command  chassis power on
333    Should Not Contain  ${output}  Error
334
335    Run Keyword If  '${wait}' == '${0}'  Return From Keyword
336    Wait Until Keyword Succeeds  10 min  10 sec  Is Host Running
337
338
339Initiate Host PowerOff Via External IPMI
340    [Documentation]  Initiate host power off using external IPMI.
341    [Arguments]  ${wait}=${1}
342
343    # Description of argument(s):
344    # wait                          Indicates that this keyword should wait
345    #                               for host off state.
346
347    ${output}=  Run External IPMI Standard Command  chassis power off
348    Should Not Contain  ${output}  Error
349
350    Run Keyword If  '${wait}' == '${0}'  Return From Keyword
351    Wait Until Keyword Succeeds  3 min  10 sec  Is Host Off
352
353
354Is Host Off Via IPMI
355    [Documentation]  Verify if the Host is off using IPMI command.
356
357    ${status}=  Run External IPMI Standard Command  chassis power status
358    Should Contain  ${status}  off
359
360
361Get Host State Via External IPMI
362    [Documentation]  Returns host state using external IPMI.
363
364    ${output}=  Run External IPMI Standard Command  chassis power status
365    Should Not Contain  ${output}  Error
366    ${output}=  Fetch From Right  ${output}  ${SPACE}
367
368    [Return]  ${output}
369
370
371Set BMC Network From Host
372    [Documentation]  Set BMC network from host.
373    [Arguments]  ${nw_info}
374
375    # Description of argument(s):
376    # nw_info                       A dictionary containing the network
377    #                               information to apply.
378
379    Run Inband IPMI Standard Command
380    ...  lan set 1 ipaddr ${nw_info['IP Address']}
381
382    Run Inband IPMI Standard Command
383    ...  lan set 1 netmask ${nw_info['Subnet Mask']}
384
385    Run Inband IPMI Standard Command
386    ...  lan set 1 defgw ipaddr ${nw_info['Default Gateway IP']}
387
388
389Verify IPMI Username And Password
390    [Documentation]  Verify that user is able to run IPMI command
391    ...  with given username and password.
392    [Arguments]  ${username}  ${password}
393
394    # Description of argument(s):
395    # username    The user name (e.g. "root", "robert", etc.).
396    # password    The user password.
397
398    ${output}=  Wait Until Keyword Succeeds  15 sec  5 sec  Run External IPMI Standard Command
399    ...  sel info  U=${username}  P=${password}
400    Should Contain  ${output}  SEL Information  msg=SEL information not present
401
402
403IPMI Create User
404    [Documentation]  Create IPMI user with given userid and username.
405    [Arguments]  ${userid}  ${username}
406
407    # Description of argument(s):
408    # userid      The user ID (e.g. "1", "2", etc.).
409    # username    The user name (e.g. "root", "robert", etc.).
410
411    ${ipmi_cmd}=  Catenate  user set name ${userid} ${username}
412    ${resp}=  Run IPMI Standard Command  ${ipmi_cmd}
413    ${user_info}=  Get User Info  ${userid}  ${CHANNEL_NUMBER}
414    Should Be Equal  ${user_info['user_name']}  ${username}
415
416
417Enable IPMI User And Verify
418    [Documentation]  Enable the userid and verify that it has been enabled.
419    [Arguments]  ${userid}
420
421    # Description of argument(s):
422    # userid   A numeric userid (e.g. "4").
423
424    Run IPMI Standard Command  user enable ${userid}
425    ${user_info}=  Get User Info  ${userid}  ${CHANNEL_NUMBER}
426    Valid Value  user_info['enable_status']  ['enabled']
427
428
429Create Random IPMI User
430    [Documentation]  Create IPMI user with random username and userid and return those fields.
431
432    ${random_username}=  Generate Random String  8  [LETTERS]
433    ${random_userid}=  Evaluate  random.randint(2, 15)  modules=random
434    IPMI Create User  ${random_userid}  ${random_username}
435    [Return]  ${random_userid}  ${random_username}
436
437
438Delete Created User
439    [Documentation]  Delete created IPMI user.
440    [Arguments]  ${userid}
441    # Description of argument(s):
442    # userid  The user ID (e.g. "1", "2", etc.).
443
444    Run IPMI Standard Command  user set name ${userid} ""
445    Sleep  5s
446
447
448Set Channel Access
449    [Documentation]  Verify that user is able to run IPMI command
450    ...  with given username and password.
451    [Arguments]  ${userid}  ${options}  ${channel_number}=${CHANNEL_NUMBER}
452
453    # Description of argument(s):
454    # userid          The user ID (e.g. "1", "2", etc.).
455    # options         Set channel command options (e.g.
456    #                 "link=on", "ipmi=on", etc.).
457    # channel_number  The user's channel number (e.g. "1").
458
459    ${ipmi_cmd}=  Catenate  SEPARATOR=
460    ...  channel setaccess${SPACE}${channel_number}${SPACE}${userid}
461    ...  ${SPACE}${options}
462    Run IPMI Standard Command  ${ipmi_cmd}
463
464
465Delete All Non Root IPMI User
466    [Documentation]  Delete all non-root IPMI user.
467
468    # Get complete list of user info records.
469    ${user_info}=  Get User Info  ${EMPTY}  ${CHANNEL_NUMBER}
470    # Remove header record.
471    ${user_info}=  Filter Struct  ${user_info}  [('user_name', None)]  invert=1
472    ${non_empty_user_info}=  Filter Struct  ${user_info}  [('user_name', '')]  invert=1
473    ${non_root_user_info}=  Filter Struct  ${non_empty_user_info}  [('user_name', 'root')]  invert=1
474
475    FOR  ${user_record}  IN  @{non_root_user_info}
476        Run IPMI Standard Command   user set name ${user_record['user_id']} ""
477        Sleep  5s
478    END
479
480
481Create SEL
482    [Documentation]  Create a SEL.
483    [Arguments]  ${sensor_type}  ${sensor_number}
484
485    # Create a SEL.
486    # Example:
487    # a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 |  | Asserted
488    # Description of argument(s):
489    #    ${sensor_type}            Type of the sensor used in hexadecimal (can be fan, temp etc.,),
490    #                              obtained from Sensor Type field in - ipmitool sdr get "sensor_name".
491    #                              Example: Sensor Type (Threshold) : Fan (0x04), here 0xHH is sensor type.
492
493    #    ${sensor_number}          Sensor number of the sensor in hexadecimal.
494    #                              obtained from Sensor ID field in - ipmitool sdr get "sensor_name".
495    #                              Example: Sensor ID : SENSOR_1 (0xHH), here 0xHH is sensor number.
496
497    ${cmd}=  Catenate  ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][0]} 0x${GEN_ID_BYTE_1} 0x${GEN_ID_BYTE_2}
498    ...  ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][1]} 0x${sensor_type} 0x${sensor_number}
499    ...  ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][2]}
500
501    ${resp}=  Run IPMI Command  ${cmd}
502
503    Should Not Contain  ${resp}  00 00  msg=SEL not created.
504
505    Sleep  5s
506
507    [Return]  ${resp}
508
509
510Fetch One Threshold Sensor From Sensor List
511    [Documentation]  Fetch one threshold sensor randomly from Sensor list.
512
513    @{sensor_name_list}=  Create List
514
515    ${resp}=  Run IPMI Standard Command  sensor
516    @{sensor_list}=  Split To Lines  ${resp}
517
518    # Omit the discrete sensor and create an threshold sensor name list
519    FOR  ${sensor}  IN  @{sensor_list}
520      ${discrete_sensor_status}=  Run Keyword And Return Status  Should Contain  ${sensor}  discrete
521      Continue For Loop If  '${discrete_sensor_status}' == 'True'
522      ${sensor_details}=  Split String  ${sensor}  |
523      ${get_sensor_name}=  Get From List  ${sensor_details}  0
524      ${sensor_name}=  Set Variable  ${get_sensor_name.strip()}
525      Append To List  ${sensor_name_list}  ${sensor_name}
526    END
527
528    ${random_sensor_name}=  Evaluate  random.choice(${sensor_name_list})  random
529
530    [Return]  ${random_sensor_name}
531
532Fetch Sensor Details From SDR
533    [Documentation]  Identify the sensors from sdr get and fetch sensor details required.
534    [Arguments]  ${sensor_name}  ${setting}
535
536    # Description of argument(s):
537    #    ${sensor_number}        Sensor number of the sensor in hexadecimal.
538    #                            obtained sensor name from - 'ipmitool sensor' command.
539    #                            Example: a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 |  | Asserted
540    #                            here, a is the sensor name.
541
542    #    ${setting}              Field to fetch data. Example : Sensor ID, Sensor Type (Threshold), etc,.
543
544    ${resp}=  Run IPMI Standard Command  sdr get "${sensor_name}"
545
546    ${setting_line}=  Get Lines Containing String  ${resp}  ${setting}
547    ...  case-insensitive
548    ${setting_status}=  Fetch From Right  ${setting_line}  :${SPACE}
549
550    [Return]  ${setting_status}
551
552
553Get Bytes From SDR Sensor
554    [Documentation]  Fetch the Field Data and hexadecimal values from given details.
555    [Arguments]  ${sensor_detail}
556
557    # Description of argument(s):
558    #    ${sensor_detail}      Requested field and the value from the sdr get ipmi command.
559    #                          Example : if Sensor ID is the requesting setting, then,
560    #                          ${sensor_detail} will be "Sensor ID : SENSOR_1 (0xHH)"
561
562    ${sensor_detail}=  Split String  ${sensor_detail}  (0x
563    ${sensor_hex}=  Replace String  ${sensor_detail[1]}  )  ${EMPTY}
564    ${sensor_hex}=  Zfill Data  ${sensor_hex}  2
565
566    [Return]  ${sensor_hex}
567
568
569Get Current Date from BMC
570    [Documentation]  Runs the date command from BMC and returns current date and time
571    [Arguments]  ${date_format}=%m/%d/%Y %H:%M:%S
572
573    # Description of argument(s):
574    # date_format    Date format of the result. E.g. %Y-%m-%d %H:%M:%S etc.
575
576    # Get Current Date from BMC
577    ${date}  ${stderr}  ${rc}=  BMC Execute Command   date
578
579    # Split the string and remove first and 2nd last value from the list and join to form %d %b %H:%M:%S %Y date format
580    ${date}=  Split String  ${date}
581    Remove From List  ${date}  0
582    Remove From List  ${date}  -2
583    ${date}=  Evaluate  " ".join(${date})
584
585    # Convert the date to specified format, default:%m/%d/%Y %H:%M:%S
586    ${date}=  Convert Date  ${date}  date_format=%b %d %H:%M:%S %Y  result_format=${date_format}  exclude_millis=True
587
588    [Return]   ${date}
589
590
591Get SEL Info Via IPMI
592    [Documentation]  Get the SEL Info via IPMI raw command
593
594    # Get SEL Info response consist of 14 bytes of hexadecimal data.
595
596    # Byte 1 - SEL Version,
597    # Byte 2 & 3 - Entry bytes - LSB MSB,
598    # Byte 4 & 5 - Free Space in bytes, LS Byte first.
599    # Byte 6 - 9 - Most recent addition timestamp,
600    # Byte 10-13 - Most recent erase timestamp,
601    # Byte 14 - Operation Support
602
603    # Example: ${resp} will be "51 XX XX XX XX ff ff ff ff ff ff ff ff XX"
604
605    ${resp}=  Run IPMI Standard Command
606    ...  raw ${IPMI_RAW_CMD['SEL_entry']['SEL_info'][0]}
607    ${resp}=  Split String  ${resp}
608
609    [Return]  ${resp}
610
611
612Verify Invalid IPMI Command
613    [Documentation]  Execute invalid IPMI command and verify with given response code.
614    [Arguments]  ${ipmi_cmd}  ${error_code}=0xc9
615
616    #  Description Of Arguments.
617    #  ${ipmi_cmd}   - IPMI raw cmd with invalid data length.
618    #  ${error_code} - Expected error code e.g 0xc7, 0xcc.
619
620    ${resp}=  Run External IPMI Raw Command  ${ipmi_cmd}  fail_on_err=0
621
622    Should Contain  ${resp}  rsp=${error_code}
623
624
625Identify Request Data
626    [Documentation]  Convert text from variable declared to request data.
627    [Arguments]  ${string}
628
629    # Convert string to hexadecimal data for each character.
630    # Return the hex data with prefix of 0x as string and list of hex data.
631    # Description of argument(s):
632    #    string             Any string to be converted to hex.
633
634    # Given a string, convert to hexadecimal and prefix with 0x
635    ${hex1}=  Create List
636    ${hex2}=  Create List
637    ${resp_data}=  Split String With Index  ${string}  1
638    FOR  ${data}  IN  @{resp_data}
639        # prefixes 0x by default
640        ${hex_value}=  Evaluate  hex(ord("${data}"))
641        # prefixes string with bytes prefixed 0x by default
642        Append To List  ${hex1}  ${hex_value}
643        # provides only hexadecimal bytes
644        ${hex}=  Evaluate  hex(ord("${data}"))[2:]
645        # provides string with only hexadecimal bytes
646        Append To List  ${hex2}  ${hex}
647    END
648    ${hex1}=  Evaluate  " ".join(${hex1})
649
650    # ${hex1} will contains the data to write for fru in list.
651    # ${hex2} will contains the data to verify fru after write operation completed.
652
653    [Return]  ${hex1}  ${hex2}
654