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    BMC Execute Command  /sbin/reboot
218
219    # Wait for activation to finish.
220    Wait For Activation State Change  ${version_id}  ${ACTIVATING}
221    ${software_state}=  Read Properties  ${SOFTWARE_VERSION_URI}${version_id}
222    Should Be Equal As Strings  &{software_state}[Activation]  ${ACTIVE}
223
224    # Verify the image priority is 0.
225    ${priority}=  Read Software Attribute  ${SOFTWARE_VERSION_URI}${version_id}
226    ...  Priority
227    Should Be Equal  ${priority}  ${0}
228
229
230Switch To Active Image And Pass
231    [Documentation]  Make the given active image the image running on the BMC
232    ...              and pass the test.
233    [Arguments]  ${software_object}
234
235    # Description of argument(s):
236    # software_object  Software object path.
237    #                  (e.g. "/xyz/openbmc_project/software/f3b29aa8").
238
239    Set Host Software Property  ${software_object}  Priority  ${0}
240    OBMC Reboot (off)
241    Pass Execution  ${software_object} was already on the BMC.
242
243
244Activate Image And Verify No Duplicate Priorities
245    [Documentation]  Upload an image, and then check that no images have the
246    ...              same priority.
247    [Arguments]  ${image_file_path}  ${image_purpose}
248
249    # Description of argument(s):
250    # image_file_path  The path to the image to upload.
251    # image_purpose    The purpose in the image's MANIFEST file.
252
253    Upload And Activate Image  ${image_file_path}
254    Verify No Duplicate Image Priorities  ${image_purpose}
255
256
257Set Same Priority For Multiple Images
258    [Documentation]  Find two images, set the priorities to be the same, and
259    ...              verify that the priorities are not the same.
260    [Arguments]  ${version_purpose}
261
262    # Description of argument(s):
263    # version_purpose  Either BMC or host version purpose.
264    #                  (e.g. "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"
265    #                        "xyz.openbmc_project.Software.Version.VersionPurpose.Host").
266
267    # Make sure we have more than two images.
268    ${software_objects}=  Get Software Objects  version_type=${version_purpose}
269    ${num_images}=  Get Length  ${software_objects}
270    Should Be True  1 < ${num_images}
271    ...  msg=Only found one image on the BMC with purpose ${version_purpose}.
272
273    # Set the priority of the second image to the priority of the first.
274    ${properties}=  Get Host Software Property  @{software_objects}[0]
275    Set Host Software Property  @{software_objects}[1]  Priority
276    ...  &{properties}[Priority]
277    Verify No Duplicate Image Priorities  ${version_purpose}
278
279    # Set the priority of the first image back to what it was before
280    Set Host Software Property  @{software_objects}[0]  Priority
281    ...  &{properties}[Priority]
282
283
284Delete Software Object
285    [Documentation]  Deletes an image from the BMC.
286    [Arguments]  ${software_object}
287
288    # Description of argument(s):
289    # software_object  The URI to the software image to delete.
290
291    ${arglist}=  Create List
292    ${args}=  Create Dictionary  data=${arglist}
293    ${resp}=  OpenBMC Post Request  ${software_object}/action/delete
294    ...  data=${args}
295    Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK}
296
297
298Delete Image And Verify
299    [Documentation]  Delete an image from the BMC and verify that it was
300    ...              removed from software and the /tmp/images directory.
301    [Arguments]  ${software_object}  ${version_type}
302
303    # Description of argument(s):
304    # software_object        The URI of the software object to delete.
305    # version_type  The type of the software object, e.g.
306    #               xyz.openbmc_project.Software.Version.VersionPurpose.Host
307    #               or xyz.openbmc_project.Software.Version.VersionPurpose.BMC.
308
309    Log To Console  Deleteing ${software_object}
310
311    # Delete the image.
312    Delete Software Object  ${software_object}
313    # TODO: If/when we don't have to delete twice anymore, take this out
314    Run Keyword And Ignore Error  Delete Software Object  ${software_object}
315
316    # Verify that it's gone from software.
317    ${software_objects}=  Get Software Objects  version_type=${version_type}
318    Should Not Contain  ${software_objects}  ${software_object}
319
320    # Check that there is no file in the /tmp/images directory.
321    ${image_id}=  Fetch From Right  ${software_object}  /
322    BMC Execute Command
323    ...  [ ! -d "/tmp/images/${image_id}" ]
324
325
326Delete All Non Running BMC Images
327    [Documentation]  Delete all BMC images that are not running on the BMC.
328
329    @{datalist}=  Create List
330    ${data}=  Create Dictionary  data=@{datalist}
331    Call Method  ${SOFTWARE_VERSION_URI}  DeleteAll  data=${data}
332
333
334Check Error And Collect FFDC
335    [Documentation]  Collect FFDC if error log exists.
336
337    ${status}=  Run Keyword And Return Status  Error Logs Should Not Exist
338    Run Keyword If  '${status}' == 'False'  FFDC
339    Delete Error Logs
340
341
342Verify Running BMC Image
343    [Documentation]  Verify that the version on the BMC is the same as the
344    ...              version in the given image.
345    [Arguments]  ${image_file_path}
346
347    # Description of argument(s):
348    # image_file_path   Path to the BMC image tarball.
349
350    ${tar_version}=  Get Version Tar  ${image_file_path}
351    ${bmc_version}=  Get BMC Version
352    ${bmc_version}=  Remove String  ${bmc_version}  "
353    Should Be Equal  ${tar_version}  ${bmc_version}
354
355
356Verify Running Host Image
357    [Documentation]  Verify that the version of the PNOR image that is on the
358    ...              BMC is the same as the one in the given image.
359    [Arguments]  ${image_file_path}
360
361    # Description of argument(s):
362    # image_file_path   Path to the PNOR image tarball.
363
364    ${tar_version}=  Get Version Tar  ${image_file_path}
365    ${pnor_version}=  Get PNOR Version
366    Should Be Equal  ${tar_version}  ${pnor_version}
367
368
369Get Least Value Priority Image
370    [Documentation]  Find the least value in "Priority" attribute and return.
371    [Arguments]  ${version_type}
372
373    # Description of argument(s):
374    # version_type  Either BMC or host version purpose.
375
376    ${priority_value_list}=  Create List
377    ${sw_list}=  Get Software Objects  version_type=${version_type}
378
379    :FOR  ${index}  IN  @{sw_list}
380    \  ${priority_value}=
381    ...  Read Software Attribute  ${index}  Priority
382    \  Append To List  ${priority_value_list}  ${priority_value}
383
384    ${min_value}=  Min List Value  ${priority_value_list}
385
386    [Return]  ${min_value}
387
388
389Enable Field Mode And Verify Unmount
390    [Documentation]  Enable field mode and check that /usr/local is unmounted.
391
392    # After running, /xyz/openbmc_project/software should look like this:
393    # /xyz/openbmc_project/software
394    # {
395    #     "FieldModeEnabled": 1,
396    #     "associations": [
397    #         [
398    #             "active",
399    #             "software_version",
400    #             "/xyz/openbmc_project/software/fcf8e182"
401    #         ],
402    #         [
403    #             "functional",
404    #             "software_version",
405    #             "/xyz/openbmc_project/software/fcf8e182"
406    #         ]
407    #     ]
408    # }
409
410    ${args}=  Create Dictionary  data=${1}
411    Write Attribute  ${SOFTWARE_VERSION_URI}  FieldModeEnabled  data=${args}
412    Sleep  5s
413    BMC Execute Command  [ ! -d "/usr/local/share" ]
414
415