1*** Settings ***
2Documentation     Validate IPMI sensor IDs using Redfish.
3
4Resource          ../lib/ipmi_client.robot
5Resource          ../lib/openbmc_ffdc.robot
6Resource          ../lib/boot_utils.robot
7Library           ../lib/ipmi_utils.py
8Variables         ../data/ipmi_raw_cmd_table.py
9
10Test Setup        Redfish.Login
11Test Teardown     Run Keywords  FFDC On Test Case Fail  AND
12...  Redfish.Logout
13
14Force Tags        IPMI_Sensor
15
16*** Variables ***
17
18${allowed_temp_diff}    ${2}
19${allowed_power_diff}   ${10}
20
21
22*** Test Cases ***
23
24Verify IPMI Temperature Readings using Redfish
25    [Documentation]  Verify temperatures from IPMI sensor reading command using Redfish.
26    [Tags]  Verify_IPMI_Temperature_Readings_using_Redfish
27    [Template]  Get Temperature Reading And Verify In Redfish
28
29    # command_type  sensor_id  member_id
30    IPMI            PCIE       PCIE
31    IPMI            Ambient    Ambient
32
33
34Verify DCMI Temperature Readings using Redfish
35    [Documentation]  Verify temperatures from DCMI sensor reading command using Redfish.
36    [Tags]  Verify_DCMI_Temperature_Readings_using_Redfish
37    [Template]  Get Temperature Reading And Verify In Redfish
38
39    # command_type  sensor_id  member_id
40    DCMI            PCIE       PCIE
41    DCMI            Ambient    Ambient
42
43
44Test Ambient Temperature Via IPMI
45    [Documentation]  Test ambient temperature via IPMI and verify using Redfish.
46    [Tags]  Test_Ambient_Temperature_Via_IPMI
47
48    # Example of IPMI dcmi get_temp_reading output:
49    #        Entity ID                       Entity Instance    Temp. Readings
50    # Inlet air temperature(40h)                      1               +22 C
51    # Inlet air temperature(40h)                      2               +23 C
52    # Inlet air temperature(40h)                      3               +22 C
53    # CPU temperature sensors(41h)                    0               +0 C
54    # Baseboard temperature sensors(42h)              1               +26 C
55    # Baseboard temperature sensors(42h)              2               +27 C
56
57    ${temp_reading}=  Run IPMI Standard Command  dcmi get_temp_reading -N 10
58    Should Contain  ${temp_reading}  Inlet air temperature
59    ...  msg="Unable to get inlet temperature via DCMI".
60
61    ${ambient_temp_line}=
62    ...  Get Lines Containing String  ${temp_reading}
63    ...  Inlet air temperature  case-insensitive
64
65    ${ambient_temp_line}=  Split To Lines  ${ambient_temp_line}
66    ${ipmi_temp_list}=  Create List
67    FOR  ${line}  IN  @{ambient_temp_line}
68        ${ambient_temp_ipmi}=  Set Variable  ${line.split('+')[1].strip(' C')}
69        Append To List  ${ipmi_temp_list}  ${ambient_temp_ipmi}
70    END
71    ${list_length}=  Get Length  ${ipmi_temp_list}
72
73    # Getting temperature readings from Redfish.
74    ${ambient_temp_redfish}=  Get Temperature Reading From Redfish  Ambient
75    ${ambient_temp_redfish}=  Get Dictionary Values  ${ambient_temp_redfish}  sort_keys=True
76    FOR  ${index}  IN RANGE  ${list_length}
77        ${ipmi_redfish_temp_diff}=
78        ...  Evaluate  abs(${ambient_temp_redfish[${index}]} - ${ipmi_temp_list[${index}]})
79
80        Should Be True  ${ipmi_redfish_temp_diff} <= ${allowed_temp_diff}
81        ...  msg=Ambient temperature above allowed threshold ${allowed_temp_diff}.
82    END
83
84
85Test Power Reading Via IPMI With Host Off
86    [Documentation]  Verify power reading via IPMI with host in off state
87    [Tags]  Test_Power_Reading_Via_IPMI_With_Host_Off
88
89    Redfish Power Off  stack_mode=skip
90
91    ${ipmi_reading}=  Get IPMI Power Reading
92
93    Should Be Equal  ${ipmi_reading['instantaneous_power_reading']}  0
94    ...  msg=Power reading not zero when power is off.
95
96
97Test Power Reading Via IPMI With Host Booted
98    [Documentation]  Test power reading via IPMI with host in booted state and
99    ...  verify using Redfish.
100    [Tags]  Test_Power_Reading_Via_IPMI_With_Host_Booted
101
102    IPMI Power On  stack_mode=skip
103
104    Wait Until Keyword Succeeds  2 min  30 sec  Verify Power Reading Using IPMI And Redfish
105
106
107Test Baseboard Temperature Via IPMI
108    [Documentation]  Test baseboard temperature via IPMI and verify using Redfish.
109    [Tags]  Test_Baseboard_Temperature_Via_IPMI
110
111    # Example of IPMI dcmi get_temp_reading output:
112    #        Entity ID                       Entity Instance    Temp. Readings
113    # Inlet air temperature(40h)                      1               +22 C
114    # Inlet air temperature(40h)                      2               +23 C
115    # Inlet air temperature(40h)                      3               +22 C
116    # CPU temperature sensors(41h)                    0               +0 C
117    # Baseboard temperature sensors(42h)              1               +26 C
118    # Baseboard temperature sensors(42h)              2               +27 C
119
120    ${temp_reading}=  Run IPMI Standard Command  dcmi get_temp_reading -N 10
121    Should Contain  ${temp_reading}  Baseboard temperature sensors
122    ...  msg="Unable to get baseboard temperature via DCMI".
123    ${baseboard_temp_lines}=
124    ...  Get Lines Containing String  ${temp_reading}
125    ...  Baseboard temperature  case-insensitive=True
126    ${lines}=  Split To Lines  ${baseboard_temp_lines}
127
128    ${ipmi_temp_list}=  Create List
129    FOR  ${line}  IN  @{lines}
130        ${baseboard_temp_ipmi}=  Set Variable  ${line.split('+')[1].strip(' C')}
131        Append To List  ${ipmi_temp_list}  ${baseboard_temp_ipmi}
132    END
133    ${list_length}=  Get Length  ${ipmi_temp_list}
134
135    # Getting temperature readings from Redfish.
136    ${baseboard_temp_redfish}=  Get Temperature Reading From Redfish  PCIE
137    ${baseboard_temp_redfish}=  Get Dictionary Values  ${baseboard_temp_redfish}  sort_keys=True
138
139    FOR  ${index}  IN RANGE  ${list_length}
140        ${baseboard_temp_diff}=  Evaluate  abs(${baseboard_temp_redfish[${index}]} - ${ipmi_temp_list[${index}]})
141        Should Be True
142        ...  ${baseboard_temp_diff} <= ${allowed_temp_diff}
143        ...  msg=Baseboard temperature above allowed threshold ${allowed_temp_diff}.
144    END
145
146Test Power Reading Via IPMI Raw Command
147    [Documentation]  Test power reading via IPMI raw command and verify
148    ...  using Redfish.
149    [Tags]  Test_Power_Reading_Via_IPMI_Raw_Command
150
151    IPMI Power On  stack_mode=skip
152
153    Wait Until Keyword Succeeds  2 min  30 sec  Verify Power Reading Via Raw Command
154
155
156Verify CPU Present
157    [Documentation]  Verify the IPMI sensor for CPU present using Redfish.
158    [Tags]  Verify_CPU_Present
159    [Template]  Set Present Bit Via IPMI and Verify Using Redfish
160
161    # component  state
162    cpu          Enabled
163
164
165Verify CPU Not Present
166    [Documentation]  Verify the IPMI sensor for CPU not present using Redfish.
167    [Tags]  Verify_CPU_Not_Present
168    [Template]  Set Present Bit Via IPMI and Verify Using Redfish
169
170    # component  state
171    cpu          Absent
172
173
174Verify GPU Present
175    [Documentation]  Verify the IPMI sensor for GPU present using Redfish.
176    [Tags]  Verify_GPU_Present
177    [Template]  Set Present Bit Via IPMI and Verify Using Redfish
178
179    # sensor_id  component
180    0xC5         gv100card0
181
182
183Verify GPU Not Present
184    [Documentation]  Verify the IPMI sensor for GPU not present using Redfish.
185    [Tags]  Verify_GPU_Not_Present
186    [Template]  Set Present Bit Via IPMI and Verify Using Redfish
187
188    # sensor_id  component
189    0xC5         gv100card0
190
191
192Test Sensor Threshold Via IPMI
193    [Documentation]  Test sensor threshold via IPMI and verify using Redfish.
194    [Tags]  Test_Sensor_Threshold_Via_IPMI
195    [Template]  Verify Power Supply Sensor Threshold
196
197    # threshold_id             component
198    Upper Non-Critical         UpperThresholdNonCritical
199    Upper Critical             UpperThresholdCritical
200    Lower Non-Critical         LowerThresholdNonCritical
201    Lower Critical             LowerThresholdCritical
202
203
204*** Keywords ***
205
206Get Temperature Reading And Verify In Redfish
207    [Documentation]  Get IPMI or DCMI sensor reading and verify in Redfish.
208    [Arguments]  ${command_type}  ${sensor_id}  ${member_id}
209
210    # Description of argument(s):
211    # command_type  Type of command used to get sensor data (eg. IPMI, DCMI).
212    # sensor_id     Sensor id used to get reading in IPMI or DCMI.
213    # member_id     Member id of sensor data in Redfish.
214
215    ${ipmi_value}=  Run Keyword If  '${command_type}' == 'IPMI'  Get IPMI Sensor Reading  ${sensor_id}
216    ...  ELSE  Get DCMI Sensor Reading  ${sensor_id}
217
218    ${redfish_value}=  Get Temperature Reading From Redfish  ${member_id}
219
220    ${keys}=  Get Dictionary Keys  ${ipmi_value}
221    FOR  ${index}  IN  @{keys}
222        ${value_diff}=  Evaluate  abs(${redfish_value["${index}"]} - ${ipmi_value["${index}"]})
223        Should Be True  ${value_diff} <= ${allowed_temp_diff}
224    END
225
226
227
228Get IPMI Sensor Reading
229    [Documentation]  Get IPMI sensor readings as a dictionary.
230    [Arguments]  ${sensor_id}
231
232    # Description of argument(s):
233    # sensor_id     Sensor id used to get reading in IPMI.
234
235    ${sensor_list}=  Get Available Sensors  ${sensor_id}
236    ${sensor_value_dict}=  Create Dictionary
237
238    FOR  ${ids}  IN  @{sensor_list}
239        ${data}=  Run IPMI Standard Command  sensor reading ${ids}
240
241        # Example reading:
242        # PCIE_0_Temp      | 5Ch | ok  | 41.1 | 27 degrees C
243
244        ${sensor_key}=  Set Variable  ${data.split('| ')[0].strip()}
245        ${sensor_value}=  Set Variable  ${data.split('| ')[1].strip()}
246        Set To Dictionary  ${sensor_value_dict}  ${sensor_key}  ${sensor_value}
247    END
248
249    [Return]  ${sensor_value_dict}
250
251
252Get DCMI Sensor Reading
253    [Documentation]  Get DCMI sensor readings as a dictionary.
254    [Arguments]  ${sensor_id}
255
256    # Description of argument(s):
257    # sensor_id     Sensor id used to get reading in DCMI.
258
259    ${data}=  Run IPMI Standard Command  dcmi sensors
260    ${sensor_data}=  Get Lines Containing String  ${data}  ${sensor_id}  case_insensitive
261    ${sensor_lines}=  Split To Lines  ${sensor_data}
262
263    # Example reading:
264    # Record ID 0x005c: PCIE_0_Temp      | 27 degrees C      | ok
265
266    ${sensor_value_dict}=  Create Dictionary
267
268    FOR  ${line}  IN  @{sensor_lines}
269        ${sensor}=  Set Variable  ${line.split(' | ')}
270        ${sensor_key}=  Set Variable  ${sensor[0].split(':')[1].strip()}
271        ${sensor_value}=  Set Variable  ${sensor[1].split()[0].strip()}
272        ${contains}=  Evaluate  """disabled""" in "${sensor_value}"
273
274        Run Keyword IF  "${contains}" != """True"""
275        ...  Set To Dictionary  ${sensor_value_dict}  ${sensor_key}  ${sensor_value}
276    END
277
278    [Return]  ${sensor_value_dict}
279
280
281Get Temperature Reading From Redfish
282    [Documentation]  Get temperature reading from Redfish.
283    [Arguments]  ${member_id}
284
285    # Description of argument(s):
286    # member_id    Member id of temperature.
287
288    @{thermal_uri}=  redfish_utils.Get Member List  /redfish/v1/Chassis/
289    @{redfish_readings}=  redfish_utils.Get Attribute
290    ...  ${thermal_uri[0]}/${THERMAL_METRICS}  TemperatureReadingsCelsius
291
292    # Example of Baseboard temperature via Redfish
293
294    # "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/ThermalMetrics",
295    # "@odata.type": "#ThermalMetrics.v1_0_0.ThermalMetrics",
296    # "Id": "ThermalMetrics",
297    # "Name": "Chassis Thermal Metrics",
298    # "TemperatureReadingsCelsius": [
299    # {
300    # "@odata.id": "/redfish/v1/Chassis/chassis/Sensors/PCIE_0_Temp",
301    # "DataSourceUri": "/redfish/v1/Chassis/chassis/Sensors/PCIE_0_Temp",
302    # "DeviceName": "PCIE_0_Temp",
303    # "Reading": 23.75
304    # },
305
306    ${redfish_value_dict}=  Create Dictionary
307    FOR  ${data}  IN  @{redfish_readings}
308        ${contains}=  Evaluate  "${member_id}" in """${data}[DeviceName]"""
309        ${reading}=  Set Variable  ${data}[Reading]
310        Run Keyword IF  "${contains}" == "True"
311        ...  Set To Dictionary  ${redfish_value_dict}  ${data}[DeviceName]  ${reading}
312    END
313
314    [Return]  ${redfish_value_dict}
315
316
317Verify Power Reading Using IPMI And Redfish
318    [Documentation]  Verify power reading using IPMI and Redfish.
319
320    # Example of power reading command output via IPMI.
321    # Instantaneous power reading:                   235 Watts
322    # Minimum during sampling period:                235 Watts
323    # Maximum during sampling period:                235 Watts
324    # Average power reading over sample period:      235 Watts
325    # IPMI timestamp:                                Thu Jan  1 00:00:00 1970
326    # Sampling period:                               00000000 Seconds.
327    # Power reading state is:                        deactivated
328
329    ${ipmi_reading}=  Get IPMI Power Reading
330    ${redfish_power_reading}=  redfish_utils.Get Attribute
331    ...  /redfish/v1/Chassis/${CHASSIS_ID}/Sensors/power_total_power  Reading
332
333    ${ipmi_redfish_power_diff}=
334    ...  Evaluate  abs(${redfish_power_reading} - ${ipmi_reading['instantaneous_power_reading']})
335    Should Be True  ${ipmi_redfish_power_diff} <= ${allowed_power_diff}
336    ...  msg=Power reading above allowed threshold ${allowed_power_diff}.
337
338
339Verify Power Reading Via Raw Command
340    [Documentation]  Get dcmi power reading via IPMI raw command.
341
342    ${ipmi_raw_output}=  Run IPMI Standard Command
343    ...  raw ${IPMI_RAW_CMD['power_reading']['Get'][0]}
344
345    ${power_reading_ipmi}=  Set Variable  ${ipmi_raw_output.split()[1]}
346    ${power_reading_ipmi}=
347    ...  Convert To Integer  0x${power_reading_ipmi}
348
349    #  Example of power reading via Redfish
350    #  "@odata.id": "/redfish/v1/Chassis/chassis/Power#/PowerControl/0",
351    #  "@odata.type": "#Power.v1_0_0.PowerControl",
352    #  "MemberId": "0",
353    #  "Name": "Chassis Power Control",
354    #  "PowerConsumedWatts": 145.0,
355
356    ${power}=  Redfish.Get Properties  /redfish/v1/Chassis/${CHASSIS_ID}/Power
357    ${redfish_reading}=  Set Variable  ${power['PowerControl'][0]['PowerConsumedWatts']}
358
359    ${ipmi_redfish_power_diff}=
360    ...  Evaluate  abs(${redfish_reading} - ${power_reading_ipmi})
361
362    Should Be True  ${ipmi_redfish_power_diff} <= ${allowed_power_diff}
363    ...  msg=Power reading above allowed threshold ${allowed_power_diff}.
364
365
366Set Present Bit Via IPMI and Verify Using Redfish
367    [Documentation]  Set present bit of sensor via IPMI and verify using Redfish.
368    [Arguments]  ${component}  ${status}
369
370    # Description of argument(s):
371    # component    The Redfish component of IPMI sensor.
372    # status  Status of the bit to be set(e.g. Absent, Present).
373
374    ${sensor_list}=  Get Available Sensors  ${component}
375    ${sensor_name}=  Set Variable  ${sensor_list[0]}
376    ${sensor_id}=  Get Sensor Id For Sensor  ${sensor_name}
377
378     Run Keyword If  '${status}' == 'Absent'
379     ...  Run IPMI Command
380     ...  0x04 0x30 ${sensor_id} 0xa9 0x00 0x00 0x00 0x80 0x00 0x00 0x20 0x00
381     ...  ELSE IF  '${status}' == 'Enabled'
382     ...  Run IPMI Command
383     ...  0x04 0x30 ${sensor_id} 0xa9 0x00 0x80 0x00 0x00 0x00 0x00 0x20 0x00
384
385     # Redfish cpu components have "-" instead of "_" (e.g.: dcm0-cpu0).
386     ${cpu_name}=  Replace String  ${sensor_name}  _  -
387     ${sensor_properties}=  Redfish.Get Properties  /redfish/v1/Systems/system/Processors/${cpu_name}
388
389     #  Example of CPU state via Redfish
390
391     # "ProcessorType": "CPU",
392     # "SerialNumber": "YA1936422499",
393     # "Socket": "",
394     # "SparePartNumber": "F210110",
395     # "Status": {
396     # "Health": "OK",
397     # "State": "Absent"
398     # }
399
400     Should Be True  '${sensor_properties['Status']['State']}' == '${status}'
401
402
403Verify Power Supply Sensor Threshold
404    [Documentation]  Get power supply sensor threshold value via IPMI and verify using Redfish.
405    [Arguments]  ${ipmi_threshold_id}  ${redfish_threshold_id}
406
407    # Description of argument(s):
408    # ipmi_threshold_id       The sensor threshold component of IPMI sensor.
409    # redfish_threshold_id    The sensor threshold component of Redfish sensor.
410
411
412    #  Example of ipmi sensor output
413    # Locating sensor record...
414    # Sensor ID              : ps0_input_voltag (0xf7)
415    # Entity ID             : 10.19
416    # Sensor Type (Threshold)  : Voltage
417    # Sensor Reading        : 208 (+/- 0) Volts
418    # Status                : ok
419    # Lower Non-Recoverable : na
420    # Lower Critical        : 180.000
421    # Lower Non-Critical    : 200.000
422    # Upper Non-Critical    : 290.000
423    # Upper Critical        : 300.000
424    # Upper Non-Recoverable : na
425    # Positive Hysteresis   : Unspecified
426    # Negative Hysteresis   : Unspecified
427
428
429    ${ipmi_sensor_output}=  Run External IPMI Standard Command  sensor get ps0_input_voltag
430    ${ipmi_threshold_output}=  Get Lines Containing String  ${ipmi_sensor_output}  ${ipmi_threshold_id}
431    ${ipmi_threshold_reading}=  Fetch From Right  ${ipmi_threshold_output}  :${SPACE}
432
433    ${ipmi_threshold_reading}=  Set Variable If  '${ipmi_threshold_reading}' == 'na'
434    ...  ${0}  ${ipmi_threshold_reading}
435
436    #  Example of redfish sensor output
437    # "@odata.id": "/redfish/v1/Chassis/chassis/Power#/Voltages/0",
438    # "@odata.type": "#Power.v1_0_0.Voltage",
439    # "LowerThresholdCritical": 180.0,
440    # "LowerThresholdNonCritical": 200.0,
441    # "MaxReadingRange": 0.0,
442    # "MemberId": "ps0_input_voltage",
443    # "MinReadingRange": 0.0,
444    # "Name": "ps0 input voltage",
445    # "ReadingVolts": 209.5,
446    # "Status": {
447    # "Health": "OK",
448    # "State": "Enabled"
449    # },
450    # "UpperThresholdCritical": 300.0,
451    # "UpperThresholdNonCritical": 290.0
452
453    @{redfish_readings}=  Redfish.Get Attribute  /redfish/v1/Chassis/${CHASSIS_ID}/Power  Voltages
454    FOR  ${data}  IN  @{redfish_readings}
455        Run keyword if  '${data}[MemberId]' == 'ps0_input_voltage'
456        ...  Should Be Equal As Numbers  ${data['${redfish_threshold_id}']}  ${ipmi_threshold_reading}
457    END
458
459
460Get Available Sensors
461    [Documentation]  Get all the available sensors for the required component.
462    ...  Returns a list of available sensors.
463    [Arguments]  ${sensor_component}
464
465    # Description of argument(s):
466    # sensor_component     sensor component name.(e.g.:cpu)
467
468    ${resp}=  Run IPMI Standard Command  sdr elist
469    ${sensor_list}=  Create List
470    ${sensors}=  Get Lines Containing String  ${resp}  ${sensor_component}  case-insensitive
471    ${sensors}=  Split To Lines  ${sensors}
472
473    # Example of IPMI sdr elist command.
474
475    # dcm0_cpu0        | 41h | ok  |  3.1 | Presence detected
476    # dcm0_cpu1        | 42h | ok  |  3.2 | Presence detected, Disabled
477    # dcm1_cpu0        | 43h | ok  |  3.3 | Presence detected
478    # dcm1_cpu1        | 44h | ok  |  3.4 | Presence detected, Disabled
479    # dcm2_cpu0        | 45h | ns  |  3.5 | Disabled
480    # dcm2_cpu1        | 46h | ns  |  3.6 | Disabled
481    # dcm3_cpu0        | 47h | ns  |  3.7 | Disabled
482    # dcm3_cpu1        | 48h | ns  |  3.8 | Disabled
483
484    FOR  ${line}  IN  @{sensors}
485        ${sensor_name}=  Set Variable  ${line.split('|')[0].strip()}
486
487        # Adding sensors to the list whose presence is detected.
488        ${contains}=  Evaluate  "Presence detected" in "${line}" or "ok" in "${line}"
489        Run Keyword IF  "${contains}" == "True"
490        ...  Append To List  ${sensor_list}  ${sensor_name}
491    END
492
493    # Example of output for ${sensor_list}
494    # ['dcm0_cpu0', 'dcm0_cpu1', 'dcm1_cpu0', 'dcm1_cpu1']
495
496    [RETURN]  ${sensor_list}
497
498
499Get Sensor Id For Sensor
500    [Documentation]  Returns the sensor ID value for the given sensor.
501    [Arguments]  ${sensor_name}
502
503    # Description of argument(s):
504    # sensor_name     Name of sensor whose ID is required(e.g.: dcm0_cpu0, dcm0_cpu1 etc).
505
506    ${get_resp}=  Run IPMI Standard Command  sensor get ${sensor_name}
507
508    # Example of sensor get command.
509
510    # Locating sensor record...
511    # Sensor ID              : dcm0_cpu0 (0x41)
512    # Entity ID             : 3.1
513    # Sensor Type (Discrete): Processor
514    # States Asserted       : Processor
515    #                  [Presence detected]
516
517    ${line}=  Get Lines Containing String  ${get_resp}  Sensor ID
518    ${sensor_id}=  Set Variable  ${line[-5:-1]}
519
520    # Example of output for ${sensor_id} is 0x41.
521
522    [RETURN]  ${sensor_id}
523
524