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