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.txt
6Resource        ../lib/connection_client.robot
7Resource        ../lib/utils.robot
8Resource        ../lib/state_manager.robot
9
10Library         String
11
12*** Variables ***
13${dbusHostIpmicmd1}=   dbus-send --system  ${OPENBMC_BASE_URI}HostIpmi/1
14${dbusHostIpmiCmdReceivedMsg}=   ${OPENBMC_BASE_DBUS}.HostIpmi.ReceivedMessage
15${netfnByte}=          ${EMPTY}
16${cmdByte}=            ${EMPTY}
17${arrayByte}=          array:byte:
18${IPMI_EXT_CMD}=       ipmitool -I lanplus -C ${IPMI_CIPHER_LEVEL}
19${IPMI_USER_OPTIONS}   ${EMPTY}
20${IPMI_INBAND_CMD}=    ipmitool -C ${IPMI_CIPHER_LEVEL}
21${HOST}=               -H
22${RAW}=                raw
23
24*** Keywords ***
25
26Run IPMI Command
27    [Arguments]  ${args}
28    ${resp}=  Run Keyword If  '${IPMI_COMMAND}' == 'External'
29    ...  Run External IPMI RAW Command  ${args}
30    ...  ELSE IF  '${IPMI_COMMAND}' == 'Inband'
31    ...  Run Inband IPMI RAW Command  ${args}
32    ...  ELSE IF  '${IPMI_COMMAND}' == 'Dbus'
33    ...  Run Dbus IPMI RAW Command  ${args}
34    ...  ELSE  Fail  msg=Invalid IPMI Command type provided : ${IPMI_COMMAND}
35    [Return]  ${resp}
36
37Run IPMI Standard Command
38    [Arguments]  ${args}
39    ${resp}=  Run Keyword If  '${IPMI_COMMAND}' == 'External'
40    ...  Run External IPMI Standard Command  ${args}
41    ...  ELSE IF  '${IPMI_COMMAND}' == 'Inband'
42    ...  Run Inband IPMI Standard Command  ${args}
43    ...  ELSE IF  '${IPMI_COMMAND}' == 'Dbus'
44    ...  Run Dbus IPMI Standard Command  ${args}
45    ...  ELSE  Fail  msg=Invalid IPMI Command type provided : ${IPMI_COMMAND}
46
47    [Return]  ${resp}
48
49Run Dbus IPMI RAW Command
50    [Arguments]    ${args}
51    ${valueinBytes}=   Byte Conversion  ${args}
52    ${cmd}=   Catenate   ${dbushostipmicmd1} ${dbusHostIpmiCmdReceivedMsg}
53    ${cmd}=   Catenate   ${cmd} ${valueinBytes}
54    ${output}   ${stderr}=  Execute Command  ${cmd}  return_stderr=True
55    Should Be Empty      ${stderr}
56    set test variable    ${OUTPUT}     "${output}"
57
58Run Dbus IPMI Standard Command
59    [Arguments]    ${args}
60    Copy ipmitool
61    ${stdout}    ${stderr}    ${output}=  Execute Command
62    ...    /tmp/ipmitool -I dbus ${args}    return_stdout=True
63    ...    return_stderr= True    return_rc=True
64    Should Be Equal    ${output}    ${0}    msg=${stderr}
65    [Return]    ${stdout}
66
67Run Inband IPMI Raw Command
68    [Documentation]  Run Inband IPMI raw command.
69    [Arguments]  ${args}  ${os_host}=${OS_HOST}  ${os_username}=${OS_USERNAME}
70    ...          ${os_password}=${OS_PASSWORD}
71
72    # Description of arguments:
73    # ${args}  parameters to IPMI command.
74    # ${os_host} IP address of the OS Host.
75    # ${os_username}  OS Host Login user name.
76    # ${os_password}  OS Host Login passwrd.
77
78    Login To OS Host  ${os_host}  ${os_username}  ${os_password}
79    Check If IPMI Tool Exist
80
81    ${inband_raw_cmd}=  Catenate  ${IPMI_INBAND_CMD}  ${RAW}  ${args}
82    ${stdout}  ${stderr}=  Execute Command  ${inband_raw_cmd}  return_stderr=True
83    Should Be Empty  ${stderr}  msg=${stdout}
84    [Return]  ${stdout}
85
86Run Inband IPMI Standard Command
87    [Documentation]  Run Inband IPMI standard command.
88    [Arguments]  ${args}  ${os_host}=${OS_HOST}  ${os_username}=${OS_USERNAME}
89    ...          ${os_password}=${OS_PASSWORD}
90
91    # Description of arguments:
92    # ${args}  parameters to IPMI command.
93    # ${os_host} IP address of the OS Host.
94    # ${os_username}  OS Host Login user name.
95    # ${os_password}  OS Host Login passwrd.
96
97    Login To OS Host  ${os_host}  ${os_username}  ${os_password}
98    Check If IPMI Tool Exist
99
100    ${inband_std_cmd}=  Catenate  ${IPMI_INBAND_CMD}  ${args}
101    ${stdout}  ${stderr}=  Execute Command  ${inband_std_cmd}  return_stderr=True
102    Should Be Empty  ${stderr}  msg=${stdout}
103    [Return]  ${stdout}
104
105Run External IPMI RAW Command
106    [Arguments]    ${args}
107    ${ipmi_raw_cmd}=   Catenate  SEPARATOR=
108    ...    ${IPMI_EXT_CMD} -P${SPACE}${IPMI_PASSWORD}${SPACE}
109    ...    ${HOST}${SPACE}${OPENBMC_HOST}${SPACE}${RAW}${SPACE}${args}
110    ${rc}    ${output}=    Run and Return RC and Output    ${ipmi_raw_cmd}
111    Should Be Equal    ${rc}    ${0}    msg=${output}
112    [Return]    ${output}
113
114Run External IPMI Standard Command
115    [Arguments]  ${args}  ${fail_on_err}=${1}
116
117    # Description of argument(s):
118    # args         IPMI command to be executed.
119    # fail_on_err  Fail if keyword the IPMI command fails
120
121    ${ipmi_cmd}=  Catenate  SEPARATOR=
122    ...  ${IPMI_EXT_CMD} ${IPMI_USER_OPTIONS} -P${SPACE}${IPMI_PASSWORD}
123    ...  ${SPACE}${HOST}${SPACE}${OPENBMC_HOST}${SPACE}${args}
124    ${rc}  ${output}=  Run And Return RC and Output  ${ipmi_cmd}
125    Return From Keyword If  ${fail_on_err} == ${0}  ${output}
126    Should Be Equal  ${rc}  ${0}  msg=${output}
127    [Return]  ${output}
128
129Check If IPMI Tool Exist
130    [Documentation]  Check if IPMI Tool installed or not.
131    ${output}=  Execute Command  which ipmitool
132    Should Not Be Empty  ${output}  msg=ipmitool not installed.
133
134
135Activate SOL Via IPMI
136    [Documentation]  Start SOL using IPMI and route output to a file.
137    [Arguments]  ${file_path}=/tmp/sol_${OPENBMC_HOST}
138    # Description of argument(s):
139    # file_path  The file path on the local machine (vs OBMC) to collect SOL
140    #            output. By default SOL output is collected at
141    #            /tmp/sol_<BMC_IP> else user input location.
142
143    ${ipmi_cmd}=  Catenate  SEPARATOR=
144    ...  ${IPMI_EXT_CMD} -P${SPACE}${IPMI_PASSWORD}${SPACE}${HOST}
145    ...  ${SPACE}${OPENBMC_HOST}${SPACE}sol activate usesolkeepalive
146
147    Start Process  ${ipmi_cmd}  shell=True  stdout=${file_path}
148    ...  alias=sol_proc
149
150
151Deactivate SOL Via IPMI
152    [Documentation]  Stop SOL using IPMI and return SOL output.
153    [Arguments]  ${file_path}=/tmp/sol_${OPENBMC_HOST}
154    # Description of argument(s):
155    # file_path  The file path on the local machine to copy SOL output
156    #            collected by above "Activate SOL Via IPMI" keyword.
157    #            By default it copies log from /tmp/sol_<BMC_IP>.
158
159    ${ipmi_cmd}=  Catenate  SEPARATOR=
160    ...  ${IPMI_EXT_CMD} -P${SPACE}${IPMI_PASSWORD}${SPACE}
161    ...  ${HOST}${SPACE}${OPENBMC_HOST}${SPACE}sol deactivate
162
163    ${rc}  ${output}=  Run and Return RC and Output  ${ipmi_cmd}
164    Run Keyword If  ${rc} > 0  Run Keywords
165    ...  Run Keyword And Ignore Error  Terminate Process  sol_proc
166    ...  AND  Return From Keyword  ${output}
167
168    ${rc}  ${output}=  Run and Return RC and Output  cat ${file_path}
169    Should Be Equal  ${rc}  ${0}  msg=${output}
170
171    # Logging SOL output for debug purpose.
172    Log  ${output}
173
174    [Return]  ${output}
175
176
177Byte Conversion
178    [Documentation]   Byte Conversion method receives IPMI RAW commands as
179    ...               argument in string format.
180    ...               Sample argument is as follows
181    ...               "0x04 0x30 9 0x01 0x00 0x35 0x00 0x00 0x00 0x00 0x00
182    ...               0x00"
183    ...               IPMI RAW command format is as follows
184    ...               <netfn Byte> <cmd Byte> <Data Bytes..>
185    ...               This method converts IPMI command format into
186    ...               dbus command format  as follows
187    ...               <byte:seq-id> <byte:netfn> <byte:lun> <byte:cmd>
188    ...               <array:byte:data>
189    ...               Sample dbus  Host IPMI Received Message argument
190    ...               byte:0x00 byte:0x04 byte:0x00 byte:0x30
191    ...               array:byte:9,0x01,0x00,0x35,0x00,0x00,0x00,0x00,0x00,0x00
192    [Arguments]     ${args}
193    ${argLength}=   Get Length  ${args}
194    Set Global Variable  ${arrayByte}   array:byte:
195    @{listargs}=   Split String  ${args}
196    ${index}=   Set Variable   ${0}
197    :FOR   ${word}   in   @{listargs}
198    \    Run Keyword if   ${index} == 0   Set NetFn Byte  ${word}
199    \    Run Keyword if   ${index} == 1   Set Cmd Byte    ${word}
200    \    Run Keyword if   ${index} > 1    Set Array Byte  ${word}
201    \    ${index}=    Set Variable    ${index + 1}
202    ${length}=   Get Length  ${arrayByte}
203    ${length}=   Evaluate  ${length} - 1
204    ${arrayByteLocal}=  Get Substring  ${arrayByte}  0   ${length}
205    Set Global Variable  ${arrayByte}   ${arrayByteLocal}
206    ${valueinBytesWithArray}=   Catenate  byte:0x00   ${netfnByte}  byte:0x00
207    ${valueinBytesWithArray}=   Catenate  ${valueinBytesWithArray}  ${cmdByte}
208    ${valueinBytesWithArray}=   Catenate  ${valueinBytesWithArray} ${arrayByte}
209    ${valueinBytesWithoutArray}=   Catenate  byte:0x00 ${netfnByte}  byte:0x00
210    ${valueinBytesWithoutArray}=   Catenate  ${valueinBytesWithoutArray} ${cmdByte}
211#   To Check scenario for smaller IPMI raw commands with only 2 arguments
212#   instead of usual 12 arguments.
213#   Sample small IPMI raw command: Run IPMI command 0x06 0x36
214#   If IPMI raw argument length is only 9 then return value in bytes without
215#   array population.
216#   Equivalent dbus-send argument for smaller IPMI raw command:
217#   byte:0x00 byte:0x06 byte:0x00 byte:0x36
218    Run Keyword if   ${argLength} == 9     Return from Keyword    ${valueinBytesWithoutArray}
219    [Return]    ${valueinBytesWithArray}
220
221
222Set NetFn Byte
223   [Arguments]    ${word}
224   ${netfnByteLocal}=  Catenate   byte:${word}
225   Set Global Variable  ${netfnByte}  ${netfnByteLocal}
226
227Set Cmd Byte
228   [Arguments]    ${word}
229   ${cmdByteLocal}=  Catenate   byte:${word}
230   Set Global Variable  ${cmdByte}  ${cmdByteLocal}
231
232Set Array Byte
233   [Arguments]    ${word}
234   ${arrayByteLocal}=   Catenate   SEPARATOR=  ${arrayByte}  ${word}
235   ${arrayByteLocal}=   Catenate   SEPARATOR=  ${arrayByteLocal}   ,
236   Set Global Variable  ${arrayByte}   ${arrayByteLocal}
237
238Copy ipmitool
239    OperatingSystem.File Should Exist   tools/ipmitool      msg=The ipmitool program could not be found in the tools directory. It is not part of the automation code by default. You must manually copy or link the correct openbmc version of the tool in to the tools directory in order to run this test suite.
240
241    Import Library      SCPLibrary      WITH NAME       scp
242    scp.Open connection     ${OPENBMC_HOST}     username=${OPENBMC_USERNAME}      password=${OPENBMC_PASSWORD}
243    scp.Put File    tools/ipmitool   /tmp
244    SSHLibrary.Open Connection     ${OPENBMC_HOST}
245    Login   ${OPENBMC_USERNAME}    ${OPENBMC_PASSWORD}
246    Execute Command     chmod +x /tmp/ipmitool
247
248Initiate Host Boot Via External IPMI
249    [Documentation]  Initiate host power on using external IPMI.
250    [Arguments]  ${wait}=${1}
251    # Description of argument(s):
252    # wait  Indicates that this keyword should wait for host running state.
253
254    ${output}=  Run External IPMI Standard Command  chassis power on
255    Should Not Contain  ${output}  Error
256
257    Run Keyword If  '${wait}' == '${0}'  Return From Keyword
258    Wait Until Keyword Succeeds  10 min  10 sec  Is Host Running
259
260Initiate Host PowerOff Via External IPMI
261    [Documentation]  Initiate host power off using external IPMI.
262    [Arguments]  ${wait}=${1}
263    # Description of argument(s):
264    # wait  Indicates that this keyword should wait for host off state.
265
266    ${output}=  Run External IPMI Standard Command  chassis power off
267    Should Not Contain  ${output}  Error
268
269    Run Keyword If  '${wait}' == '${0}'  Return From Keyword
270    Wait Until Keyword Succeeds  3 min  10 sec  Is Host Off
271
272Get Host State Via External IPMI
273    [Documentation]  Returns host state using external IPMI.
274
275    ${output}=  Run External IPMI Standard Command  chassis power status
276    Should Not Contain  ${output}  Error
277    ${output}=  Fetch From Right  ${output}  ${SPACE}
278
279    [Return]  ${output}
280