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