1*** Settings ***
2Documentation   BMC and PNOR update utilities keywords.
3
4Library         code_update_utils.py
5Library         OperatingSystem
6Library         String
7Library         utilities.py
8Library         gen_robot_valid.py
9Variables       ../data/variables.py
10Resource        boot_utils.robot
11Resource        rest_client.robot
12Resource        openbmc_ffdc.robot
13
14*** Variables ***
15${ignore_err}    ${0}
16
17*** Keywords ***
18
19Get Software Objects
20    [Documentation]  Get the host software objects and return as a list.
21    [Arguments]  ${version_type}=${VERSION_PURPOSE_HOST}
22
23    # Description of argument(s):
24    # version_type  Either BMC or host version purpose.
25    #               By default host version purpose string.
26    #  (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
27    #        "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
28
29    # Example:
30    # "data": [
31    #      "/xyz/openbmc_project/software/f3b29aa8",
32    #      "/xyz/openbmc_project/software/e49bc78e",
33    # ],
34    # Iterate the list and return the host object name path list.
35
36    ${host_list}=  Create List
37    ${sw_list}=  Read Properties  ${SOFTWARE_VERSION_URI}
38
39    FOR  ${index}  IN  @{sw_list}
40      ${attr_purpose}=  Read Software Attribute  ${index}  Purpose
41      Continue For Loop If  '${attr_purpose}' != '${version_type}'
42      Append To List  ${host_list}  ${index}
43    END
44
45    [Return]  ${host_list}
46
47
48Read Software Attribute
49    [Documentation]  Return software attribute data.
50    [Arguments]  ${software_object}  ${attribute_name}
51
52    # Description of argument(s):
53    # software_object   Software object path.
54    #                   (e.g. "/xyz/openbmc_project/software/f3b29aa8").
55    # attribute_name    Software object attribute name.
56
57    ${resp}=  OpenBMC Get Request  ${software_object}/attr/${attribute_name}
58    ...  quiet=${1}
59    Return From Keyword If  ${resp.status_code} != ${HTTP_OK}
60    ${content}=  To JSON  ${resp.content}
61    [Return]  ${content["data"]}
62
63
64Get Software Objects Id
65    [Documentation]  Get the software objects id and return as a list.
66    [Arguments]  ${version_type}=${VERSION_PURPOSE_HOST}
67
68    # Description of argument(s):
69    # version_type  Either BMC or host version purpose.
70    #               By default host version purpose string.
71    #              (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
72    #               "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
73
74    ${sw_id_list}=  Create List
75    ${sw_list}=  Get Software Objects  ${version_type}
76
77    :FOR  ${index}  IN  @{sw_list}
78    \  Append To List  ${sw_id_list}  ${index.rsplit('/', 1)[1]}
79
80    [Return]  ${sw_id_list}
81
82
83Get Host Software Property
84    [Documentation]  Return a dictionary of host software properties.
85    [Arguments]  ${host_object}
86
87    # Description of argument(s):
88    # host_object  Host software object path.
89    #             (e.g. "/xyz/openbmc_project/software/f3b29aa8").
90
91    ${sw_attributes}=  Read Properties  ${host_object}
92    [return]  ${sw_attributes}
93
94Get Host Software Objects Details
95    [Documentation]  Return software object details as a list of dictionaries.
96    [Arguments]  ${quiet}=${QUIET}
97
98    ${software}=  Create List
99
100    ${pnor_details}=  Get Software Objects  ${VERSION_PURPOSE_HOST}
101    :FOR  ${pnor}  IN  @{pnor_details}
102    \  ${resp}=  OpenBMC Get Request  ${pnor}  quiet=${1}
103    \  ${json}=  To JSON  ${resp.content}
104    \  Append To List  ${software}  ${json["data"]}
105
106    [Return]  ${software}
107
108Set Host Software Property
109    [Documentation]  Set the host software properties of a given object.
110    [Arguments]  ${host_object}  ${sw_attribute}  ${data}
111
112    # Description of argument(s):
113    # host_object   Host software object name.
114    # sw_attribute  Host software attribute name.
115    #               (e.g. "Activation", "Priority", "RequestedActivation" etc).
116    # data          Value to be written.
117
118    ${args}=  Create Dictionary  data=${data}
119    Write Attribute  ${host_object}  ${sw_attribute}  data=${args}
120    # Sync time for software updater manager to update.
121    # TODO: openbmc/openbmc#2857
122    Sleep  10s
123
124
125Set Property To Invalid Value And Verify No Change
126    [Documentation]  Attempt to set a property and check that the value didn't
127    ...              change.
128    [Arguments]  ${property}  ${version_type}
129
130    # Description of argument(s):
131    # property      The property to attempt to set.
132    # version_type  Either BMC or host version purpose.
133    #               By default host version purpose string.
134    #  (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
135    #        "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
136
137    ${software_objects}=  Get Software Objects  version_type=${version_type}
138    ${prev_properties}=  Get Host Software Property  @{software_objects}[0]
139    Run Keyword And Expect Error  500 != 200
140    ...  Set Host Software Property  @{software_objects}[0]  ${property}  foo
141    ${cur_properties}=  Get Host Software Property  @{software_objects}[0]
142    Should Be Equal As Strings  &{prev_properties}[${property}]
143    ...  &{cur_properties}[${property}]
144
145
146Set Priority To Invalid Value And Expect Error
147    [Documentation]  Set the priority of an image to an invalid value and
148    ...              check that an error was returned.
149    [Arguments]  ${version_type}  ${priority}
150
151    # Description of argument(s):
152    # version_type  Either BMC or host version purpose.
153    #               (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
154    #                     "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
155    # priority      The priority value to set. Should be an integer outside of
156    #               the range of 0 through 255.
157
158    ${images}=  Get Software Objects  version_type=${version_type}
159    ${num_images}=  Get Length  ${images}
160    Should Be True  0 < ${num_images}
161
162    Run Keyword And Expect Error  403 != 200
163    ...  Set Host Software Property  @{images}[0]  Priority  ${priority}
164
165
166Redfish Upload Image
167    [Documentation]  Upload an image to the BMC via redfish.
168    [Arguments]  ${uri}  ${image_file_path}
169
170    # Description of argument(s):
171    # uri                 URI for uploading image via redfish.
172    # image_file_path     The path to the image tarball.
173
174    ${image_data}=  OperatingSystem.Get Binary File  ${image_file_path}
175
176    Wait Until Keyword Succeeds  2 times  120 sec
177    ...  Upload Image To BMC  ${uri}  timeout=${90}  data=${image_data}
178
179
180Redfish Verify BMC Version
181    [Documentation]  Verify that the version on the BMC is the same as the
182    ...              version in the given image via Redfish.
183    [Arguments]      ${image_file_path}
184
185    # Description of argument(s):
186    # image_file_path   Path to the image tarball.
187
188    # Extract the version from the image tarball on our local system.
189    ${tar_version}=  Get Version Tar  ${image_file_path}
190    ${bmc_version}=  Redfish Get BMC Version
191
192    Valid Value  bmc_version  valid_values=['${tar_version}']
193
194
195Redfish Verify Host Version
196    [Documentation]  Verify that the version of the PNOR image that is on the
197    ...              BMC is the same as the one in the given image via Redfish.
198    [Arguments]      ${image_file_path}
199
200    # Description of argument(s):
201    # image_file_path   Path to the image tarball.
202
203    # Extract the version from the image tarball on our local system.
204    ${tar_version}=  Get Version Tar  ${image_file_path}
205    ${host_version}=  Redfish Get Host Version
206
207    Valid Value  host_version  valid_values=['${tar_version}']
208
209
210Upload And Activate Image
211    [Documentation]  Upload an image to the BMC and activate it with REST.
212    [Arguments]  ${image_file_path}  ${wait}=${1}  ${skip_if_active}=false
213
214    # Description of argument(s):
215    # image_file_path     The path to the image tarball to upload and activate.
216    # wait                Indicates that this keyword should wait for host or
217    #                     BMC activation is completed.
218    # skip_if_active      If set to true, will skip the code update if this
219    #                     image is already on the BMC.
220
221    OperatingSystem.File Should Exist  ${image_file_path}
222    ${image_version}=  Get Version Tar  ${image_file_path}
223
224    ${image_data}=  OperatingSystem.Get Binary File  ${image_file_path}
225
226    Wait Until Keyword Succeeds  3 times  120 sec
227    ...   Upload Image To BMC  /upload/image  timeout=${90}  data=${image_data}
228    ${ret}  ${version_id}=  Verify Image Upload  ${image_version}
229    Should Be True  ${ret}
230
231    # Verify the image is 'READY' to be activated or if it's already active,
232    # set priority to 0 and reboot the BMC.
233    ${software_state}=  Read Properties  ${SOFTWARE_VERSION_URI}${version_id}
234    ${activation}=  Set Variable  &{software_state}[Activation]
235
236    Run Keyword If
237    ...  '${skip_if_active}' == 'true' and '${activation}' == '${ACTIVE}'
238    ...  Run Keywords
239    ...      Set Host Software Property  ${SOFTWARE_VERSION_URI}${version_id}
240    ...      Priority  ${0}
241    ...    AND
242    ...      Return From Keyword
243
244    Should Be Equal As Strings  ${software_state}[Activation]  ${READY}
245
246    # Request the image to be activated.
247    ${args}=  Create Dictionary  data=${REQUESTED_ACTIVE}
248    Write Attribute  ${SOFTWARE_VERSION_URI}${version_id}
249    ...  RequestedActivation  data=${args}
250    ${software_state}=  Read Properties  ${SOFTWARE_VERSION_URI}${version_id}
251    Should Be Equal As Strings  ${software_state}[RequestedActivation]
252    ...  ${REQUESTED_ACTIVE}
253
254    # Does caller want to wait for activation to complete?
255    Return From Keyword If  '${wait}' == '${0}'  ${version_id}
256
257    # Verify code update was successful and Activation state is Active.
258    Wait For Activation State Change  ${version_id}  ${ACTIVATING}
259    ${software_state}=  Read Properties  ${SOFTWARE_VERSION_URI}${version_id}
260    Should Be Equal As Strings  ${software_state}[Activation]  ${ACTIVE}
261
262    # Uploaded and activated image should have priority set to 0. Due to timing
263    # contention, it may take up to 10 seconds to complete updating priority.
264    Wait Until Keyword Succeeds  10 sec  5 sec
265    ...  Check Software Object Attribute  ${version_id}  Priority  ${0}
266
267    [Return]  ${version_id}
268
269
270Attempt To Reboot BMC During Image Activation
271    [Documentation]  Attempt to reboot the BMC while an image is activating and
272    ...              check that the BMC ignores the reboot command and finishes
273    ...              activation.
274    [Arguments]  ${image_file_path}
275
276    # Description of argument(s):
277    # image_file_path  Path to the image to update to.
278
279    # Attempt to reboot during activation.
280    ${version_id}=  Upload And Activate Image  ${image_file_path}
281    ...  wait=${0}
282    ${resp}=  OpenBMC Get Request  ${SOFTWARE_VERSION_URI}${version_id}
283    Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK}
284
285    OBMC Reboot (off)
286
287    ${resp}=  OpenBMC Get Request  ${SOFTWARE_VERSION_URI}${version_id}
288    Should Be Equal As Strings  ${resp.status_code}  ${HTTP_NOT_FOUND}
289
290
291Activate Image And Verify No Duplicate Priorities
292    [Documentation]  Upload an image, and then check that no images have the
293    ...              same priority.
294    [Arguments]  ${image_file_path}  ${image_purpose}
295
296    # Description of argument(s):
297    # image_file_path  The path to the image to upload.
298    # image_purpose    The purpose in the image's MANIFEST file.
299
300    Upload And Activate Image  ${image_file_path}  skip_if_active=true
301    Verify No Duplicate Image Priorities  ${image_purpose}
302
303
304Set Same Priority For Multiple Images
305    [Documentation]  Find two images, set the priorities to be the same, and
306    ...              verify that the priorities are not the same.
307    [Arguments]  ${version_purpose}
308
309    # Description of argument(s):
310    # version_purpose  Either BMC or host version purpose.
311    #                  (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
312    #                        "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
313
314    # Make sure we have more than two images.
315    ${software_objects}=  Get Software Objects  version_type=${version_purpose}
316    ${num_images}=  Get Length  ${software_objects}
317    Should Be True  1 < ${num_images}
318    ...  msg=Only found one image on the BMC with purpose ${version_purpose}.
319
320    # Set the priority of the second image to the priority of the first.
321    ${properties}=  Get Host Software Property  @{software_objects}[0]
322    Set Host Software Property  @{software_objects}[1]  Priority
323    ...  &{properties}[Priority]
324    Verify No Duplicate Image Priorities  ${version_purpose}
325
326    # Set the priority of the first image back to what it was before
327    Set Host Software Property  @{software_objects}[0]  Priority
328    ...  &{properties}[Priority]
329
330
331Delete Software Object
332    [Documentation]  Deletes an image from the BMC.
333    [Arguments]  ${software_object}
334
335    # Description of argument(s):
336    # software_object  The URI to the software image to delete.
337
338    ${arglist}=  Create List
339    ${args}=  Create Dictionary  data=${arglist}
340    ${resp}=  OpenBMC Post Request  ${software_object}/action/Delete
341    ...  data=${args}
342    Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK}
343
344
345Delete Image And Verify
346    [Documentation]  Delete an image from the BMC and verify that it was
347    ...              removed from software and the /tmp/images directory.
348    [Arguments]  ${software_object}  ${version_type}
349
350    # Description of argument(s):
351    # software_object        The URI of the software object to delete.
352    # version_type  The type of the software object, e.g.
353    #               xyz.openbmc_project.Software.Version.VersionPurpose.Host
354    #               or xyz.openbmc_project.Software.Version.VersionPurpose.BMC.
355
356    Log To Console  Deleting ${software_object}
357
358    # Delete the image.
359    Delete Software Object  ${software_object}
360
361    # Verify that it's gone from software.
362    ${software_objects}=  Get Software Objects  version_type=${version_type}
363    Should Not Contain  ${software_objects}  ${software_object}
364
365    # Check that there is no file in the /tmp/images directory.
366    ${image_id}=  Fetch From Right  ${software_object}  /
367    BMC Execute Command
368    ...  [ ! -d "/tmp/images/${image_id}" ]
369
370
371Delete All Non Running BMC Images
372    [Documentation]  Delete all BMC images that are not running on the BMC.
373
374    @{datalist}=  Create List
375    ${data}=  Create Dictionary  data=@{datalist}
376    Call Method  ${SOFTWARE_VERSION_URI}  DeleteAll  data=${data}
377
378
379Check Error And Collect FFDC
380    [Documentation]  Collect FFDC if error log exists.
381
382    ${status}=  Run Keyword And Return Status  Error Logs Should Not Exist
383    Run Keyword If  '${status}' == 'False'  FFDC
384    Delete Error Logs
385
386
387Verify Running BMC Image
388    [Documentation]  Verify that the version on the BMC is the same as the
389    ...              version in the given image.
390    [Arguments]  ${image_file_path}
391
392    # Description of argument(s):
393    # image_file_path   Path to the BMC image tarball.
394
395    ${tar_version}=  Get Version Tar  ${image_file_path}
396    ${bmc_version}=  Get BMC Version
397    ${bmc_version}=  Remove String  ${bmc_version}  "
398    Should Be Equal  ${tar_version}  ${bmc_version}
399
400
401Verify Running Host Image
402    [Documentation]  Verify that the version of the PNOR image that is on the
403    ...              BMC is the same as the one in the given image.
404    [Arguments]  ${image_file_path}
405
406    # Description of argument(s):
407    # image_file_path   Path to the PNOR image tarball.
408
409    ${tar_version}=  Get Version Tar  ${image_file_path}
410    ${pnor_version}=  Get PNOR Version
411    Should Be Equal  ${tar_version}  ${pnor_version}
412
413
414Get Least Value Priority Image
415    [Documentation]  Find the least value in "Priority" attribute and return.
416    [Arguments]  ${version_type}
417
418    # Description of argument(s):
419    # version_type  Either BMC or host version purpose.
420
421    ${priority_value_list}=  Create List
422    ${sw_list}=  Get Software Objects  version_type=${version_type}
423
424    :FOR  ${index}  IN  @{sw_list}
425    \  ${priority_value}=
426    ...  Read Software Attribute  ${index}  Priority
427    \  Append To List  ${priority_value_list}  ${priority_value}
428
429    ${min_value}=  Min List Value  ${priority_value_list}
430
431    [Return]  ${min_value}
432
433
434Enable Field Mode And Verify Unmount
435    [Documentation]  Enable field mode and check that /usr/local is unmounted.
436
437    # After running, /xyz/openbmc_project/software should look like this:
438    # /xyz/openbmc_project/software
439    # {
440    #     "FieldModeEnabled": 1,
441    #     "associations": [
442    #         [
443    #             "active",
444    #             "software_version",
445    #             "/xyz/openbmc_project/software/fcf8e182"
446    #         ],
447    #         [
448    #             "functional",
449    #             "functional",
450    #             "/xyz/openbmc_project/software/fcf8e182"
451    #         ]
452    #     ]
453    # }
454
455    ${args}=  Create Dictionary  data=${1}
456    Write Attribute  ${SOFTWARE_VERSION_URI}  FieldModeEnabled  data=${args}
457    Sleep  5s
458    BMC Execute Command  [ ! -d "/usr/local/share" ]
459
460
461Disable Field Mode And Verify Unmount
462    [Documentation]  Disable field mode, unmask usr local mount and reboot.
463
464    BMC Execute Command  /sbin/fw_setenv fieldmode
465    BMC Execute Command  /bin/systemctl unmask usr-local.mount
466    OBMC Reboot (off)  stack_mode=normal
467    BMC Execute Command  [ -d "/usr/local/share" ]
468
469
470Field Mode Should Be Enabled
471    [Documentation]  Check that field mode is enabled.
472
473    ${value}=  Read Attribute  ${SOFTWARE_VERSION_URI}  FieldModeEnabled
474    Should Be True  ${value}  ${1}
475
476List Installed Images
477    [Documentation]  List all the installed images.
478    [Arguments]  ${image_type}
479
480    # Description of argument(s):
481    # image_type  Either "BMC" or "PNOR".
482
483    # List the installed images.
484    ${installed_images}=  Get Software Objects
485    ...  ${SOFTWARE_PURPOSE}.${image_type}
486
487    Run Keyword If  ${installed_images} != []
488    ...  Get List of Images  ${installed_images}
489    ...  ELSE  Log  No ${image_type} images are present.
490
491Get List of Images
492    [Documentation]  Get List of Images
493    [Arguments]  ${installed_images}
494
495    FOR  ${uri}  IN  @{installed_images}
496      ${resp}=  OpenBMC Get Request  ${uri}
497      ${json}=  To JSON  ${resp.content}
498      Log  ${json["data"]}
499    END
500
501
502Check Software Object Attribute
503    [Documentation]  Get the software property of a given object and verify.
504    [Arguments]  ${image_object}  ${sw_attribute}  ${value}
505
506    # Description of argument(s):
507    # image_object  Image software object name.
508    # sw_attribute  Software attribute name.
509    #               (e.g. "Activation", "Priority", "RequestedActivation" etc).
510    # value         Software attribute value to compare.
511
512    ${data}=  Read Attribute
513    ...  ${SOFTWARE_VERSION_URI}${image_object}  ${sw_attribute}
514
515    Should Be True  ${data} == ${value}
516    ...  msg=Given attribute value ${data} mismatch ${value}.
517
518
519Image Should Be Signed
520    [Documentation]  Fail if the image is not signed.
521
522    Directory Should Exist  ${ACTIVATION_DIR_PATH}
523    ...  msg=${ACTIVATION_DIR_PATH} does not exist. Therefore, the image is not signed.
524
525
526Get Latest Image ID
527    [Documentation]  Return the ID of the most recently extracted image.
528    # Note: This keyword will fail if there is no such file.
529
530    # Example: # ls /tmp/images/
531    #            1b714fb7
532    ${image_id}=  Get Latest File  /tmp/images/
533    Valid Value  image_id
534
535    # Though an image sub-directory was found, it really isn't valid unless
536    # the MANIFEST file is present.
537    BMC Execute Command  ls -l /tmp/images/${image_id}/MANIFEST
538
539    [Return]  ${image_id}
540
541
542Check Image Update Progress State
543    [Documentation]  Check that the image update progress state matches the specified state.
544    [Arguments]  ${match_state}  ${image_id}
545
546    # Description of argument(s):
547    # match_state    The expected state. This may be one or more comma-separated values
548    #                (e.g. "Disabled", "Disabled, Updating"). If the actual state matches
549    #                any of the states named in this argument, this keyword passes.
550    # image_id       The image ID (e.g. "1b714fb7").
551
552    ${state}=  Get Image Update Progress State  image_id=${image_id}
553    Valid Value  state  valid_values=[${match_state}]
554
555
556Get Image Update Progress State
557    [Documentation]  Return the current state of the image update.
558    [Arguments]  ${image_id}
559
560    # Description of argument(s):
561    # image_id         The image ID (e.g. "1b714fb7").
562
563    # In this example, this keyword would return the value "Enabled".
564    #  "Status": {
565    #              "Health": "OK",
566    #              "HealthRollup": "OK",
567    #              "State": "Enabled"
568    #            },
569    ${status}=  Redfish.Get Attribute  /redfish/v1/UpdateService/FirmwareInventory/${image_id}  Status
570    Rprint Vars  status
571
572    [Return]  ${status["State"]}
573
574
575Get Firmware Image Version
576    [Documentation]  Get the version of the currently installed firmware and return it.
577    [Arguments]  ${image_id}
578
579    # Description of argument(s):
580    # image_id      The image ID (e.g. "1b714fb7").
581
582    # Example of a version returned by this keyword:
583    # 2.8.0-dev-19-g6d5764b33
584    ${version}=  Redfish.Get Attribute  /redfish/v1/UpdateService/FirmwareInventory/${image_id}  Version
585    Rprint Vars  version
586
587    [Return]  ${version}
588
589
590Get ApplyTime
591    [Documentation]  Get the firmware "ApplyTime" policy.
592    [Arguments]  ${policy}
593
594    # Description of argument(s):
595    # policy     ApplyTime allowed values (e.g. "OnReset", "Immediate").
596
597    ${system_applytime}=  Redfish.Get Attribute  ${REDFISH_BASE_URI}UpdateService  HttpPushUriOptions
598    [Return]  ${system_applytime["HttpPushUriApplyTime"]["ApplyTime"]}
599
600
601Verify Get ApplyTime
602    [Documentation]  Get and verify the firmware "ApplyTime" policy.
603    [Arguments]  ${policy}
604
605    # Description of argument(s):
606    # policy     ApplyTime allowed values (e.g. "OnReset", "Immediate").
607
608    ${system_applytime}=  Get ApplyTime  ${policy}
609    Valid Value  system_applytime  ['${policy}']
610
611
612Set ApplyTime
613    [Documentation]  Set and verify the firmware "ApplyTime" policy.
614    [Arguments]  ${policy}
615
616    # Description of argument(s):
617    # policy     ApplyTime allowed values (e.g. "OnReset", "Immediate").
618
619    Redfish.Patch  ${REDFISH_BASE_URI}UpdateService
620    ...  body={'HttpPushUriOptions' : {'HttpPushUriApplyTime' : {'ApplyTime' : '${policy}'}}}
621    Verify Get ApplyTime  ${policy}
622    Rprint Vars  apply_time
623
624
625Get Image Version From TFTP Server
626    [Documentation]  Get and return the image version
627    ...  from the TFTP server.
628    [Arguments]  ${server_host}  ${image_file_name}
629
630    # Description of argument(s):
631    # server_host   The host name or IP address of the TFTP server.
632    # image_file_name  The file name of the image.
633
634    Shell Cmd
635    ...  curl -s tftp://${server_host}/${image_file_name} > tftp_image.tar
636    ${version}=  Get Version Tar  tftp_image.tar
637    OperatingSystem.Remove File  tftp_image.tar
638
639    [Return]  ${version}
640
641