1*** Settings ***
2Documentation  BMC and PNOR update utilities keywords.
3
4Library     code_update_utils.py
5Library     OperatingSystem
6Library     String
7Library     utilities.py
8Variables   ../data/variables.py
9Resource    boot_utils.robot
10Resource    rest_client.robot
11Resource    openbmc_ffdc.robot
12
13*** Keywords ***
14
15Get Software Objects
16    [Documentation]  Get the host software objects and return as a list.
17    [Arguments]  ${version_type}=${VERSION_PURPOSE_HOST}
18
19    # Description of argument(s):
20    # version_type  Either BMC or host version purpose.
21    #               By default host version purpose string.
22    #  (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
23    #        "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
24
25    # Example:
26    # "data": [
27    #      "/xyz/openbmc_project/software/f3b29aa8",
28    #      "/xyz/openbmc_project/software/e49bc78e",
29    # ],
30    # Iterate the list and return the host object name path list.
31
32    ${host_list}=  Create List
33    ${sw_list}=  Read Properties  ${SOFTWARE_VERSION_URI}
34
35    :FOR  ${index}  IN  @{sw_list}
36    \  ${attr_purpose}=  Read Software Attribute  ${index}  Purpose
37    \  Continue For Loop If  '${attr_purpose}' != '${version_type}'
38    \  Append To List  ${host_list}  ${index}
39
40    [Return]  ${host_list}
41
42
43Read Software Attribute
44    [Documentation]  Return software attribute data.
45    [Arguments]  ${software_object}  ${attribute_name}
46
47    # Description of argument(s):
48    # software_object   Software object path.
49    #                   (e.g. "/xyz/openbmc_project/software/f3b29aa8").
50    # attribute_name    Software object attribute name.
51
52    ${resp}=  OpenBMC Get Request  ${software_object}/attr/${attribute_name}
53    ...  quiet=${1}
54    Return From Keyword If  ${resp.status_code} != ${HTTP_OK}
55    ${content}=  To JSON  ${resp.content}
56    [Return]  ${content["data"]}
57
58
59Get Software Objects Id
60    [Documentation]  Get the software objects id and return as a list.
61    [Arguments]  ${version_type}=${VERSION_PURPOSE_HOST}
62
63    # Description of argument(s):
64    # version_type  Either BMC or host version purpose.
65    #               By default host version purpose string.
66    #              (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
67    #               "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
68
69    ${sw_id_list}=  Create List
70    ${sw_list}=  Get Software Objects  ${version_type}
71
72    :FOR  ${index}  IN  @{sw_list}
73    \  Append To List  ${sw_id_list}  ${index.rsplit('/', 1)[1]}
74
75    [Return]  ${sw_id_list}
76
77
78Get Host Software Property
79    [Documentation]  Return a dictionary of host software properties.
80    [Arguments]  ${host_object}
81
82    # Description of argument(s):
83    # host_object  Host software object path.
84    #             (e.g. "/xyz/openbmc_project/software/f3b29aa8").
85
86    ${sw_attributes}=  Read Properties  ${host_object}
87    [return]  ${sw_attributes}
88
89Get Host Software Objects Details
90    [Documentation]  Return software object details as a list of dictionaries.
91    [Arguments]  ${quiet}=${QUIET}
92
93    ${software}=  Create List
94
95    ${pnor_details}=  Get Software Objects  ${VERSION_PURPOSE_HOST}
96    :FOR  ${pnor}  IN  @{pnor_details}
97    \  ${resp}=  OpenBMC Get Request  ${pnor}  quiet=${1}
98    \  ${json}=  To JSON  ${resp.content}
99    \  Append To List  ${software}  ${json["data"]}
100
101    [Return]  ${software}
102
103Set Host Software Property
104    [Documentation]  Set the host software properties of a given object.
105    [Arguments]  ${host_object}  ${sw_attribute}  ${data}
106
107    # Description of argument(s):
108    # host_object   Host software object name.
109    # sw_attribute  Host software attribute name.
110    #               (e.g. "Activation", "Priority", "RequestedActivation" etc).
111    # data          Value to be written.
112
113    ${args}=  Create Dictionary  data=${data}
114    Write Attribute  ${host_object}  ${sw_attribute}  data=${args}
115
116
117Set Property To Invalid Value And Verify No Change
118    [Documentation]  Attempt to set a property and check that the value didn't
119    ...              change.
120    [Arguments]  ${property}  ${version_type}
121
122    # Description of argument(s):
123    # property      The property to attempt to set.
124    # version_type  Either BMC or host version purpose.
125    #               By default host version purpose string.
126    #  (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
127    #        "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
128
129    ${software_objects}=  Get Software Objects  version_type=${version_type}
130    ${prev_properties}=  Get Host Software Property  @{software_objects}[0]
131    Run Keyword And Expect Error  500 != 200
132    ...  Set Host Software Property  @{software_objects}[0]  ${property}  foo
133    ${cur_properties}=  Get Host Software Property  @{software_objects}[0]
134    Should Be Equal As Strings  &{prev_properties}[${property}]
135    ...  &{cur_properties}[${property}]
136
137
138Set Priority To Invalid Value And Expect Error
139    [Documentation]  Set the priority of an image to an invalid value and
140    ...              check that an error was returned.
141    [Arguments]  ${version_type}  ${priority}
142
143    # Description of argument(s):
144    # version_type  Either BMC or host version purpose.
145    #               (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
146    #                     "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
147    # priority      The priority value to set. Should be an integer outside of
148    #               the range of 0 through 255.
149
150    ${images}=  Get Software Objects  version_type=${version_type}
151    ${num_images}=  Get Length  ${images}
152    Should Be True  0 < ${num_images}
153
154    Run Keyword And Expect Error  403 != 200
155    ...  Set Host Software Property  @{images}[0]  Priority  ${priority}
156
157
158Upload And Activate Image
159    [Documentation]  Upload an image to the BMC and activate it with REST.
160    [Arguments]  ${image_file_path}  ${wait}=${1}  ${skip_if_active}=false
161
162    # Description of argument(s):
163    # image_file_path     The path to the image tarball to upload and activate.
164    # wait                Indicates that this keyword should wait for host or
165    #                     BMC activation is completed.
166    # skip_if_active      If set to true, will skip the code update if this
167    #                     image is already on the BMC.
168
169    OperatingSystem.File Should Exist  ${image_file_path}
170    ${image_version}=  Get Version Tar  ${image_file_path}
171
172    ${image_data}=  OperatingSystem.Get Binary File  ${image_file_path}
173    Upload Image To BMC  /upload/image  data=${image_data}
174    ${ret}  ${version_id}=  Verify Image Upload  ${image_version}
175    Should Be True  ${ret}
176
177    # Verify the image is 'READY' to be activated or if it's already active,
178    # set priority to 0 and reboot the BMC.
179    ${software_state}=  Read Properties  ${SOFTWARE_VERSION_URI}${version_id}
180    ${activation}=  Set Variable  &{software_state}[Activation]
181    Run Keyword If
182    ...  '${skip_if_active}' == 'true' and '${activation}' == '${ACTIVE}'
183    ...  Switch To Active Image And Pass  ${SOFTWARE_VERSION_URI}${version_id}
184    Should Be Equal As Strings  &{software_state}[Activation]  ${READY}
185
186    # Request the image to be activated.
187    ${args}=  Create Dictionary  data=${REQUESTED_ACTIVE}
188    Write Attribute  ${SOFTWARE_VERSION_URI}${version_id}
189    ...  RequestedActivation  data=${args}
190    ${software_state}=  Read Properties  ${SOFTWARE_VERSION_URI}${version_id}
191    Should Be Equal As Strings  &{software_state}[RequestedActivation]
192    ...  ${REQUESTED_ACTIVE}
193
194    # Does caller want to wait for activation to complete?
195    Return From Keyword If  '${wait}' == '${0}'  ${version_id}
196
197    # Verify code update was successful and Activation state is Active.
198    Wait For Activation State Change  ${version_id}  ${ACTIVATING}
199    ${software_state}=  Read Properties  ${SOFTWARE_VERSION_URI}${version_id}
200    Should Be Equal As Strings  &{software_state}[Activation]  ${ACTIVE}
201
202    [Return]  ${version_id}
203
204
205Attempt To Reboot BMC During Image Activation
206    [Documentation]  Attempt to reboot the BMC while an image is activating and
207    ...              check that the BMC ignores the reboot command and finishes
208    ...              activation.
209    [Arguments]  ${image_file_path}
210
211    # Description of argument(s):
212    # image_file_path  Path to the image to update to.
213
214    # Attempt to reboot during activation.
215    ${version_id}=  Upload And Activate Image  ${image_file_path}
216    ...  wait=${0}
217    ${resp}=  OpenBMC Get Request  ${SOFTWARE_VERSION_URI}${version_id}
218    Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK}
219
220    OBMC Reboot (off)
221
222    ${resp}=  OpenBMC Get Request  ${SOFTWARE_VERSION_URI}${version_id}
223    Should Be Equal As Strings  ${resp.status_code}  ${HTTP_NOT_FOUND}
224
225
226Switch To Active Image And Pass
227    [Documentation]  Make the given active image the image running on the BMC
228    ...              and pass the test.
229    [Arguments]  ${software_object}
230
231    # Description of argument(s):
232    # software_object  Software object path.
233    #                  (e.g. "/xyz/openbmc_project/software/f3b29aa8").
234
235    Set Host Software Property  ${software_object}  Priority  ${0}
236    OBMC Reboot (off)
237    Pass Execution  ${software_object} was already on the BMC.
238
239
240Activate Image And Verify No Duplicate Priorities
241    [Documentation]  Upload an image, and then check that no images have the
242    ...              same priority.
243    [Arguments]  ${image_file_path}  ${image_purpose}
244
245    # Description of argument(s):
246    # image_file_path  The path to the image to upload.
247    # image_purpose    The purpose in the image's MANIFEST file.
248
249    Upload And Activate Image  ${image_file_path}  skip_if_active=true
250    Verify No Duplicate Image Priorities  ${image_purpose}
251
252
253Set Same Priority For Multiple Images
254    [Documentation]  Find two images, set the priorities to be the same, and
255    ...              verify that the priorities are not the same.
256    [Arguments]  ${version_purpose}
257
258    # Description of argument(s):
259    # version_purpose  Either BMC or host version purpose.
260    #                  (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
261    #                        "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
262
263    # Make sure we have more than two images.
264    ${software_objects}=  Get Software Objects  version_type=${version_purpose}
265    ${num_images}=  Get Length  ${software_objects}
266    Should Be True  1 < ${num_images}
267    ...  msg=Only found one image on the BMC with purpose ${version_purpose}.
268
269    # Set the priority of the second image to the priority of the first.
270    ${properties}=  Get Host Software Property  @{software_objects}[0]
271    Set Host Software Property  @{software_objects}[1]  Priority
272    ...  &{properties}[Priority]
273    Verify No Duplicate Image Priorities  ${version_purpose}
274
275    # Set the priority of the first image back to what it was before
276    Set Host Software Property  @{software_objects}[0]  Priority
277    ...  &{properties}[Priority]
278
279
280Delete Software Object
281    [Documentation]  Deletes an image from the BMC.
282    [Arguments]  ${software_object}
283
284    # Description of argument(s):
285    # software_object  The URI to the software image to delete.
286
287    ${arglist}=  Create List
288    ${args}=  Create Dictionary  data=${arglist}
289    ${resp}=  OpenBMC Post Request  ${software_object}/action/delete
290    ...  data=${args}
291    Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK}
292
293
294Delete Image And Verify
295    [Documentation]  Delete an image from the BMC and verify that it was
296    ...              removed from software and the /tmp/images directory.
297    [Arguments]  ${software_object}  ${version_type}
298
299    # Description of argument(s):
300    # software_object        The URI of the software object to delete.
301    # version_type  The type of the software object, e.g.
302    #               xyz.openbmc_project.Software.Version.VersionPurpose.Host
303    #               or xyz.openbmc_project.Software.Version.VersionPurpose.BMC.
304
305    Log To Console  Deleteing ${software_object}
306
307    # Delete the image.
308    Delete Software Object  ${software_object}
309    # TODO: If/when we don't have to delete twice anymore, take this out
310    Run Keyword And Ignore Error  Delete Software Object  ${software_object}
311
312    # Verify that it's gone from software.
313    ${software_objects}=  Get Software Objects  version_type=${version_type}
314    Should Not Contain  ${software_objects}  ${software_object}
315
316    # Check that there is no file in the /tmp/images directory.
317    ${image_id}=  Fetch From Right  ${software_object}  /
318    BMC Execute Command
319    ...  [ ! -d "/tmp/images/${image_id}" ]
320
321
322Delete All Non Running BMC Images
323    [Documentation]  Delete all BMC images that are not running on the BMC.
324
325    @{datalist}=  Create List
326    ${data}=  Create Dictionary  data=@{datalist}
327    Call Method  ${SOFTWARE_VERSION_URI}  DeleteAll  data=${data}
328
329
330Check Error And Collect FFDC
331    [Documentation]  Collect FFDC if error log exists.
332
333    ${status}=  Run Keyword And Return Status  Error Logs Should Not Exist
334    Run Keyword If  '${status}' == 'False'  FFDC
335    Delete Error Logs
336
337
338Verify Running BMC Image
339    [Documentation]  Verify that the version on the BMC is the same as the
340    ...              version in the given image.
341    [Arguments]  ${image_file_path}
342
343    # Description of argument(s):
344    # image_file_path   Path to the BMC image tarball.
345
346    ${tar_version}=  Get Version Tar  ${image_file_path}
347    ${bmc_version}=  Get BMC Version
348    ${bmc_version}=  Remove String  ${bmc_version}  "
349    Should Be Equal  ${tar_version}  ${bmc_version}
350
351
352Verify Running Host Image
353    [Documentation]  Verify that the version of the PNOR image that is on the
354    ...              BMC is the same as the one in the given image.
355    [Arguments]  ${image_file_path}
356
357    # Description of argument(s):
358    # image_file_path   Path to the PNOR image tarball.
359
360    ${tar_version}=  Get Version Tar  ${image_file_path}
361    ${pnor_version}=  Get PNOR Version
362    Should Be Equal  ${tar_version}  ${pnor_version}
363
364
365Get Least Value Priority Image
366    [Documentation]  Find the least value in "Priority" attribute and return.
367    [Arguments]  ${version_type}
368
369    # Description of argument(s):
370    # version_type  Either BMC or host version purpose.
371
372    ${priority_value_list}=  Create List
373    ${sw_list}=  Get Software Objects  version_type=${version_type}
374
375    :FOR  ${index}  IN  @{sw_list}
376    \  ${priority_value}=
377    ...  Read Software Attribute  ${index}  Priority
378    \  Append To List  ${priority_value_list}  ${priority_value}
379
380    ${min_value}=  Min List Value  ${priority_value_list}
381
382    [Return]  ${min_value}
383
384
385Enable Field Mode And Verify Unmount
386    [Documentation]  Enable field mode and check that /usr/local is unmounted.
387
388    # After running, /xyz/openbmc_project/software should look like this:
389    # /xyz/openbmc_project/software
390    # {
391    #     "FieldModeEnabled": 1,
392    #     "associations": [
393    #         [
394    #             "active",
395    #             "software_version",
396    #             "/xyz/openbmc_project/software/fcf8e182"
397    #         ],
398    #         [
399    #             "functional",
400    #             "software_version",
401    #             "/xyz/openbmc_project/software/fcf8e182"
402    #         ]
403    #     ]
404    # }
405
406    ${args}=  Create Dictionary  data=${1}
407    Write Attribute  ${SOFTWARE_VERSION_URI}  FieldModeEnabled  data=${args}
408    Sleep  5s
409    BMC Execute Command  [ ! -d "/usr/local/share" ]
410
411
412Disable Field Mode And Verify Unmount
413    [Documentation]  Disable field mode, unmask usr local mount and reboot.
414
415    BMC Execute Command  /sbin/fw_setenv fieldmode
416    BMC Execute Command  /bin/systemctl unmask usr-local.mount
417    OBMC Reboot (off)  quiet=${1}
418    BMC Execute Command  [ -d "/usr/local/share" ]
419
420
421Field Mode Should Be Enabled
422    [Documentation]  Check that field mode is enabled.
423
424    ${value}=  Read Attribute  ${SOFTWARE_VERSION_URI}  FieldModeEnabled
425    Should Be True  ${value}  ${1}
426