1*** Settings ***
2
3Documentation    Module to test out of band IPMI watchdog functionality.
4Resource         ../lib/ipmi_client.robot
5Resource         ../lib/openbmc_ffdc.robot
6Resource         ../lib/boot_utils.robot
7Library          ../lib/ipmi_utils.py
8Library          String
9Library          Collections
10Variables        ../data/ipmi_raw_cmd_table.py
11
12*** Variables ***
13
14${TIMER_DELAY}          3
15${POWER_STATE_CHANGE}   3
16
17*** Test Cases ***
18
19Test IPMI Watchdog Timer Does Not Log Bit
20    [Documentation]  Execute out of band set/get do not log bit for watchdog timer.
21    [Tags]  Test_IPMI_Watchdog_Timer_Does_Not_Log_Bit
22    [Template]  Execute IPMI Raw Command And Verify Response Data
23
24    # set_raw_cmd  get_raw_cmd  resp_expect
25    ${IPMI_RAW_CMD['Watchdog']['Set'][0]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
26    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][1]}
27    ${IPMI_RAW_CMD['Watchdog']['Set'][3]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
28    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][3]}
29
30Test IPMI Watchdog Timer Stop Bit
31    [Documentation]  Execute out of band set/get stop/resume timer stop bit for watchdog timer.
32    [Tags]  Test_IPMI_Watchdog_Timer_Stop_Bit
33    [Template]  Execute IPMI Raw Command And Verify Response Data After Watchdog Expires
34
35    # set_raw_cmd  get_raw_cmd  resp_expect
36    ${IPMI_RAW_CMD['Watchdog']['Set'][6]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
37    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][5]}
38    ${IPMI_RAW_CMD['Watchdog']['Set'][9]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
39    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][7]}
40
41Test IPMI Watchdog Timer Use Bits
42    [Documentation]  Execute out of band set/get timer use bits for watchdog timer.
43    [Tags]  Test_IPMI_Watchdog_Timer_Use_Bits
44    [Template]  Execute IPMI Raw Command And Verify Response Data
45
46    # set_raw_cmd  get_raw_cmd  resp_expect
47    ${IPMI_RAW_CMD['Watchdog']['Set'][12]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
48    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][9]}
49    ${IPMI_RAW_CMD['Watchdog']['Set'][15]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
50    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][11]}
51    ${IPMI_RAW_CMD['Watchdog']['Set'][18]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
52    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][13]}
53    ${IPMI_RAW_CMD['Watchdog']['Set'][21]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
54    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][15]}
55    ${IPMI_RAW_CMD['Watchdog']['Set'][24]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
56    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][17]}
57
58Test IPMI Watchdog Timer Pre-Timeout Interrupt Bits
59    [Documentation]  Execute out of band set/get pre-timeout interrupt bits for watchdog timer.
60    [Tags]  Test_IPMI_Watchdog_Timer_Pre-Timeout_Interrupt_Bits
61    [Template]  Execute IPMI Raw Command And Verify Response Data
62
63    # set_raw_cmd  get_raw_cmd  resp_expect
64    ${IPMI_RAW_CMD['Watchdog']['Set'][27]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
65    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][19]}
66    ${IPMI_RAW_CMD['Watchdog']['Set'][30]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
67    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][21]}
68
69Test IPMI Watchdog Timer Timeout Action Bits
70    [Documentation]  Execute out of band set/get timer timeout bits for watchdog timer.
71    [Tags]  Test_IPMI_Watchdog_Timer_Timeout_Action_Bits
72    [Template]  Execute IPMI Raw Command And Verify Response Data
73
74    # set_raw_cmd  get_raw_cmd  resp_expect
75    ${IPMI_RAW_CMD['Watchdog']['Set'][33]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
76    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][23]}
77    ${IPMI_RAW_CMD['Watchdog']['Set'][36]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
78    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][25]}
79    ${IPMI_RAW_CMD['Watchdog']['Set'][39]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
80    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][27]}
81    ${IPMI_RAW_CMD['Watchdog']['Set'][42]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
82    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][29]}
83
84Test IPMI Watchdog Timer Timeout Flag Bits
85    [Documentation]  Execute out of band set/get timer timeout flag bits for watchdog timer.
86    [Tags]  Test_IPMI_Watchdog_Timer_Timeout_Flag_Bits
87    [Template]  Execute IPMI Raw Command And Verify Timer Expiration Data
88
89    # set_raw_cmd  get_raw_cmd  resp_expect
90    ${IPMI_RAW_CMD['Watchdog']['Set'][45]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
91    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][31]}
92    ${IPMI_RAW_CMD['Watchdog']['Set'][48]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
93    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][33]}
94    ${IPMI_RAW_CMD['Watchdog']['Set'][51]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
95    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][35]}
96    ${IPMI_RAW_CMD['Watchdog']['Set'][54]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
97    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][37]}
98    ${IPMI_RAW_CMD['Watchdog']['Set'][57]}  ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
99    ...  ${IPMI_RAW_CMD['Watchdog']['Get'][39]}
100
101
102Verify Timer Action For State Change
103    [Documentation]  Set Watchdog via IPMI raw command and verify timer actions.
104    [Tags]  Verify_Timer_Action_For_State_Change
105    [Template]  Validate Watchdog Timer Actions And SEL Events
106
107    # set action command                  power state  SEL event
108    ${IPMI_RAW_CMD['Watchdog']['Set'][60]}  ['off']   Power down
109    ${IPMI_RAW_CMD['Watchdog']['Set'][63]}  ['on']    Hard reset
110    ${IPMI_RAW_CMD['Watchdog']['Set'][66]}  ['on']    Power cycle
111    ${IPMI_RAW_CMD['Watchdog']['Set'][69]}  ['on']    Timer expired
112
113
114Verify Reset Timer
115    [Documentation]  Set Watchdog via IPMI raw command and verify Reset Timer functions as expected.
116    [Tags]  Verify_Reset_Timer
117
118    # Check the chassis status.
119    Power On Host And Verify
120
121    # Set Watchdog Timer initCount(0x3530).
122    Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Set'][72]}
123
124    # Get Watchdog Timer.
125    ${resp}=  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
126    Should Contain  ${resp}  ${IPMI_RAW_CMD['Watchdog']['Get'][41]}
127
128    @{start_timer_value}=  Split String  ${resp}
129
130    # Convert start value to integer.
131    # Example: Get watchdog response is 0x06 0x24 0x05 0x00 0x64 0x00 0x64 0x00.
132    # Start_timer_value is bits 6 - 7; set to 0x64 0x00 (100 ms decimal).
133    # Reverse bits 6 - 7 due to BMC being little endian; new value is 0x00 0x64.
134    # Convert hex value 0x00 0x64 to integer; start_timer_integer = 100.
135    ${value}=   Get Slice From List  ${start_timer_value}   6
136    Reverse List   ${value}
137    ${start_timer_string}=  Evaluate   "".join(${value})
138    ${start_timer_integer} =  Convert To Integer 	${start_timer_string}  16
139
140    # Delay.
141    Sleep   ${TIMER_DELAY}
142
143    # Get Watchdog Timer before reset watchdog timer.
144    ${resp}=  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
145    Should Contain  ${resp}  ${IPMI_RAW_CMD['Watchdog']['Get'][41]}
146
147    FOR    ${1}    IN    ${3}
148
149        # Reset Watchdog Timer.
150        Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Reset'][0]}
151        # Delay.
152        Sleep  ${TIMER_DELAY}
153        Get Watchdog Timer And Compare To Start Value  ${start_timer_integer}
154
155    END
156
157
158Verify Pre-timeout Values
159    [Documentation]  Set Watchdog Pre-timeout via IPMI raw command and verify via Get Watchdog Timer.
160    [Tags]  Verify_Pre-timeout_Values
161    [Template]  Validate Watchdog Pre-timeout
162
163    # command                               response
164    ${IPMI_RAW_CMD['Watchdog']['Set'][75]}  ${EMPTY}
165    ${IPMI_RAW_CMD['Watchdog']['Set'][81]}  ${EMPTY}
166    ${IPMI_RAW_CMD['Watchdog']['Get'][0]}   ${IPMI_RAW_CMD['Watchdog']['Get'][43]}
167
168Verify Failure For Pre-Timeout Interval Greater Than Initial Count
169    [Documentation]  Set Watchdog Pre-timeout via IPMI raw command and verify via Get Watchdog Timer.
170    [Tags]  Verify_Failure_For_Pre-Timeout_Interval_Greater_Than_Initial_Count
171
172    # Expected to fail: pre-timeout interval (4000) > initial count (1000).
173    Run Keyword and Expect Error  *Invalid data field*
174    ...  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Set'][78]}
175
176Verify Invalid Request Data Length
177    [Documentation]  Set Watchdog via IPMI raw command and verify via Get Watchdog Timer.
178    [Tags]  Verify_Invalid_Request_Data_Length
179    [Template]  Watchdog Invalid Request Data Length
180
181    # command
182    ${IPMI_RAW_CMD['Watchdog']['Set'][84]}
183    ${IPMI_RAW_CMD['Watchdog']['Set'][87]}
184    ${IPMI_RAW_CMD['Watchdog']['Get'][45]}
185
186Verify Invalid Reset Timer Request Data
187    [Documentation]  Set Watchdog via IPMI raw command and verify via Get Watchdog Timer.
188    [Tags]  Verify_Invalid_Reset_Timer_Request_Data
189
190    # Reset Watchdog Timer with one extra byte.
191    Run Keyword and Expect Error  *Request data length*
192    ...  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Reset'][3]}
193
194    # Reset BMC.
195    Run External IPMI Standard Command  mc reset cold -N 10 -R 1
196    Wait Until Keyword Succeeds  ${OPENBMC_REBOOT_TIMEOUT} min  10 sec
197    ...  Is BMC Operational
198
199    # Reset Watchdog Timer without initialized watchdog.
200    Run Keyword and Expect Error  *Unknown*
201    ...  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Reset'][6]}
202
203*** Keywords ***
204
205Execute IPMI Raw Command And Verify Response Data After Watchdog Expires
206    [Documentation]  Execute out of band IPMI raw command and verify response data after watchdog expires.
207    [Arguments]  ${set_raw_cmd}  ${get_raw_cmd}  ${resp_expect}
208    # Description of argument(s):
209    # set_raw_cmd     The request bytes for the command.
210    # get_raw_cmd     The response bytes for the command.
211    # resp_expect     The expected response bytes for the command.
212
213    Run IPMI Standard Command  raw ${set_raw_cmd}
214    Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Reset'][0]}
215    Run IPMI Standard Command  raw ${set_raw_cmd}
216    ${resp}=  Run IPMI Standard Command  raw ${get_raw_cmd}
217    Should Contain  ${resp}  ${resp_expect}  msg=Expecting ${resp_expect} but got ${resp}.
218
219Execute IPMI Raw Command And Verify Response Data
220    [Documentation]  Execute out of band IPMI raw command and verify response data.
221    [Arguments]  ${set_raw_cmd}  ${get_raw_cmd}  ${resp_expect}
222
223    # Description of argument(s):
224    # set_raw_cmd     The request bytes for the command.
225    # get_raw_cmd     The response bytes for the command.
226    # resp_expect     The expected response bytes for the command.
227
228    Run IPMI Standard Command  raw ${set_raw_cmd}
229    ${resp}=  Run IPMI Standard Command  raw ${get_raw_cmd}
230    Should Contain  ${resp}  ${resp_expect}  msg=Expecting ${resp_expect} but got ${resp}.
231
232Execute IPMI Raw Command And Verify Timer Expiration Data
233    [Documentation]  Execute out of band IPMI raw command and verify timer expiration response data.
234    [Arguments]  ${set_raw_cmd}  ${get_raw_cmd}  ${resp_expect}
235
236    # Description of argument(s):
237    # set_raw_cmd        The request bytes for the command.
238    # get_raw_cmd        The response bytes for the command.
239    # resp_expect        The expected response bytes for the command.
240
241    Run IPMI Standard Command  raw ${set_raw_cmd}
242    Run IPMI Standard Command  raw ${get_raw_cmd}
243    Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Reset'][0]}
244    ${resp}=  Run IPMI Standard Command  raw ${get_raw_cmd}
245    Should Contain  ${resp}  ${resp_expect}  msg=Expecting ${resp_expect} but got ${resp}.
246
247Validate Watchdog Timer Actions And SEL Events
248    [Documentation]  Verify the watchdog timer actions and the associated SEL events.
249    [Arguments]  ${set_raw_cmd}  ${power_state}  ${sel_event}
250
251    # Description of argument(s):
252    # set_raw_cmd     The set timeout action request bytes for the command.
253    # power_state     The expected power state of the host.
254    # sel_event     The response bytes for the command.
255
256    # Check the chassis status.
257    Power On Host And Verify
258
259    # Clear SEL.
260    Run IPMI Standard Command  sel clear
261
262    # Set watchdog timer action to perform action.
263    Run IPMI Standard Command  raw ${set_raw_cmd}
264
265    # Reset Watchdog Timer.
266    Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Reset'][0]}
267
268    # Delay for power state.
269    Sleep  ${POWER_STATE_CHANGE}
270
271    IF  '${sel_event}' == 'Hard reset' or '${sel_event}' == 'Power cycle'
272        # If timer expire action is 'Hard Reset' then the host/chassis immediately powering on after
273        # timer expires. So, verify host is rebooting by expecting that host is unpingable.
274        Run Keyword If  '${sel_event}' == 'Power cycle'
275        ...  Wait Until Keyword Succeeds  1 min  10 sec  Verify Host Power State  ['off']
276        ...  ELSE
277        ...  Wait Until Keyword Succeeds  20 sec  5 sec  Is Host Unpingable  ${OS_HOST}
278        Wait Until Keyword Succeeds  5 min  30 sec  Verify Host Power State  ['on']
279        Wait Until Keyword Succeeds  7 min  30 sec  OS Execute Command  uptime
280    ELSE
281        Wait Until Keyword Succeeds  1 min  20 sec  Verify Host Power State  ${power_state}
282    END
283
284    Verify Watchdog Timer Action SEL Event  ${sel_event}
285
286
287Verify Host Power State
288    [Documentation]   Get host power state using external IPMI command and verify.
289    [Arguments]  ${power_state}
290
291    # Description of argument(s):
292    # power_state     Value of Host power state: "on" or "off".
293
294    ${ipmi_state}=  Get Host State Via External IPMI
295    Valid Value  ipmi_state  ${power_state}
296
297Verify Watchdog Timer Action SEL Event
298    [Documentation]   Verify_Watchdog_Timer_Action_SEL_Event.
299    [Arguments]  ${sel_event}
300
301    # Description of argument(s):
302    # sel_event   Text of SEL event after timer action.
303
304    ${resp}=  Run IPMI Standard Command  sel elist
305    ${power_status}=  Get Lines Containing String  ${resp}  Watchdog
306    Should Contain  ${power_status}  ${sel_event}
307
308Power On Host And Verify
309    [Documentation]   Power the host on and verify.
310
311    IPMI Power On  stack_mode=skip  quiet=1
312    ${ipmi_state}=  Get Host State Via External IPMI
313    Valid Value  ipmi_state  ['on']
314
315Watchdog Invalid Request Data Length
316    [Documentation]   Verify invalid request bytes for set watchdog returns correct error.
317    [Arguments]  ${watchdog_command}
318
319    # Description of argument(s):
320    # watchdog_command     The raw watchdog IPMI command request bytes.
321
322    Run Keyword and Expect Error  *Request data length*
323    ...  Run IPMI Standard Command  raw ${watchdog_command}
324
325Validate Watchdog Pre-timeout
326    [Documentation]   Verify watchdog pre-timeout valid request bytes.
327    [Arguments]  ${watchdog_command}  ${response}
328
329    # Description of argument(s):
330    # watchdog_command     The raw watchdog IPMI command request bytes.
331    # response             The expected response bytes.
332
333    ${resp}=  Run IPMI Standard Command  raw ${watchdog_command}
334    Should Contain  ${resp}  ${response}
335
336Get Watchdog Timer And Compare To Start Value
337    [Documentation]   Get watchdog value, convert to integer, and compare to original start value.
338    [Arguments]  ${start_timer_integer}
339
340    # Description of argument(s):
341    # start_timer_integer     The initial value for the watchdog timer.
342
343    # Get Watchdog Timer.
344    ${resp}=  Run IPMI Standard Command  raw ${IPMI_RAW_CMD['Watchdog']['Get'][0]}
345    @{timer_value}=  Split String  ${resp}
346
347    # Convert to integer and compare with start value.
348    # Example: Get watchdog response is 0x06 0x24 0x05 0x00 0x64 0x00 0x64 0x00.
349    # Start_timer_value is bits 6 - 7; set to 0x64 0x00 (100 ms decimal).
350    # Reverse bits 6 - 7 due to BMC being little endian; new value is 0x00 0x64.
351    # Convert hex value 0x00 0x64 to integer; start_timer_integer = 100.
352    ${value}=   Get Slice From List  ${timer_value}   6
353    Reverse List   ${value}
354    ${timer_string}=   Evaluate   "".join(${value})
355    ${current_timer_integer}=  Convert To Integer  ${timer_string}  16
356    Should Be True   ${current_timer_integer} < ${start_timer_integer}
357