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 (e.g. "0penBmc", "0penBmc1", etc.).
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    [Return]  ${resp}
506
507
508Fetch One Threshold Sensor From Sensor List
509    [Documentation]  Fetch one threshold sensor randomly from Sensor list.
510
511    @{sensor_name_list}=  Create List
512
513    ${resp}=  Run IPMI Standard Command  sensor
514    @{sensor_list}=  Split To Lines  ${resp}
515
516    # Omit the discrete sensor and create an threshold sensor name list
517    FOR  ${sensor}  IN  @{sensor_list}
518      ${discrete_sensor_status}=  Run Keyword And Return Status  Should Contain  ${sensor}  discrete
519      Continue For Loop If  '${discrete_sensor_status}' == 'True'
520      ${sensor_details}=  Split String  ${sensor}  |
521      ${get_sensor_name}=  Get From List  ${sensor_details}  0
522      ${sensor_name}=  Set Variable  ${get_sensor_name.strip()}
523      Append To List  ${sensor_name_list}  ${sensor_name}
524    END
525
526    ${random_sensor_name}=  Evaluate  random.choice(${sensor_name_list})  random
527
528    [Return]  ${random_sensor_name}
529
530Fetch Sensor Details From SDR
531    [Documentation]  Identify the sensors from sdr get and fetch sensor details required.
532    [Arguments]  ${sensor_name}  ${setting}
533
534    # Description of argument(s):
535    #    ${sensor_number}        Sensor number of the sensor in hexadecimal.
536    #                            obtained sensor name from - 'ipmitool sensor' command.
537    #                            Example: a | 02/14/2020 | 01:16:58 | Sensor_type #0x17 |  | Asserted
538    #                            here, a is the sensor name.
539
540    #    ${setting}              Field to fetch data. Example : Sensor ID, Sensor Type (Threshold), etc,.
541
542    ${resp}=  Run IPMI Standard Command  sdr get "${sensor_name}"
543
544    ${setting_line}=  Get Lines Containing String  ${resp}  ${setting}
545    ...  case-insensitive
546    ${setting_status}=  Fetch From Right  ${setting_line}  :${SPACE}
547
548    [Return]  ${setting_status}
549
550
551Get Bytes From SDR Sensor
552    [Documentation]  Fetch the Field Data and hexadecimal values from given details.
553    [Arguments]  ${sensor_detail}
554
555    # Description of argument(s):
556    #    ${sensor_detail}      Requested field and the value from the sdr get ipmi command.
557    #                          Example : if Sensor ID is the requesting setting, then,
558    #                          ${sensor_detail} will be "Sensor ID : SENSOR_1 (0xHH)"
559
560    ${sensor_detail}=  Split String  ${sensor_detail}  (0x
561    ${sensor_hex}=  Replace String  ${sensor_detail[1]}  )  ${EMPTY}
562    ${sensor_hex}=  Zfill Data  ${sensor_hex}  2
563
564    [Return]  ${sensor_hex}
565
566
567Get Current Date from BMC
568    [Documentation]  Runs the date command from BMC and returns current date and time
569
570    # Get Current Date from BMC
571    ${date}  ${stderr}  ${rc}=  BMC Execute Command   date
572
573    # 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
574    ${date}=  Split String  ${date}
575    Remove From List  ${date}  0
576    Remove From List  ${date}  -2
577    ${date}=  Evaluate  " ".join(${date})
578
579    # Convert the date format to %m/%d/%Y %H:%M:%S
580    ${date}=  Convert Date  ${date}  date_format=%b %d %H:%M:%S %Y  result_format=%m/%d/%Y %H:%M:%S  exclude_millis=True
581
582    [Return]   ${date}
583
584
585Get SEL Info Via IPMI
586    [Documentation]  Get the SEL Info via IPMI raw command
587
588    # Get SEL Info response consist of 14 bytes of hexadecimal data.
589
590    # Byte 1 - SEL Version,
591    # Byte 2 & 3 - Entry bytes - LSB MSB,
592    # Byte 4 & 5 - Free Space in bytes, LS Byte first.
593    # Byte 6 - 9 - Most recent addition timestamp,
594    # Byte 10-13 - Most recent erase timestamp,
595    # Byte 14 - Operation Support
596
597    # Example: ${resp} will be "51 XX XX XX XX ff ff ff ff ff ff ff ff XX"
598
599    ${resp}=  Run IPMI Standard Command
600    ...  raw ${IPMI_RAW_CMD['SEL_entry']['SEL_info'][0]}
601    ${resp}=  Split String  ${resp}
602
603    [Return]  ${resp}
604
605
606Verify Invalid IPMI Command
607    [Documentation]  Execute invalid IPMI command and verify with given response code.
608    [Arguments]  ${ipmi_cmd}  ${error_code}=0xc9
609
610    #  Description Of Arguments.
611    #  ${ipmi_cmd}   - IPMI raw cmd with invalid data length.
612    #  ${error_code} - Expected error code e.g 0xc7, 0xcc.
613
614    ${resp}=  Run External IPMI Raw Command  ${ipmi_cmd}  fail_on_err=0
615
616    Should Contain  ${resp}  rsp=${error_code}
617
618
619Identify Request Data
620    [Documentation]  Convert text from variable declared to request data.
621    [Arguments]  ${string}
622
623    # Convert string to hexadecimal data for each character.
624    # Return the hex data with prefix of 0x as string and list of hex data.
625    # Description of argument(s):
626    #    string             Any string to be converted to hex.
627
628    # Given a string, convert to hexadecimal and prefix with 0x
629    ${hex1}=  Create List
630    ${hex2}=  Create List
631    ${resp_data}=  Split String With Index  ${string}  1
632    FOR  ${data}  IN  @{resp_data}
633        # prefixes 0x by default
634        ${hex_value}=  Evaluate  hex(ord("${data}"))
635        # prefixes string with bytes prefixed 0x by default
636        Append To List  ${hex1}  ${hex_value}
637        # provides only hexadecimal bytes
638        ${hex}=  Evaluate  hex(ord("${data}"))[2:]
639        # provides string with only hexadecimal bytes
640        Append To List  ${hex2}  ${hex}
641    END
642    ${hex1}=  Evaluate  " ".join(${hex1})
643
644    # ${hex1} will contains the data to write for fru in list.
645    # ${hex2} will contains the data to verify fru after write operation completed.
646
647    [Return]  ${hex1}  ${hex2}
648