PNOR Code Update test implementation
Resolves openbmc/openbmc-test-automation#572
Change-Id: Idc1f31bdc6435e5d36f93b79de5e50a32a524bb3
Signed-off-by: Saqib Khan <khansa@us.ibm.com>
diff --git a/data/variables.py b/data/variables.py
index feed8bc..972a69f 100644
--- a/data/variables.py
+++ b/data/variables.py
@@ -42,8 +42,23 @@
BMC_LOGGING_ENTRY = BMC_LOGGING_URI + 'entry/'
# Software manager version
-SOFTWARE_VERSION_URI = '/xyz/openbmc_project/software/'
+SOFTWARE_VERSION = '/xyz/openbmc_project/software/'
ACTIVE = 'xyz.openbmc_project.Software.Activation.Activations.Active'
+READY = 'xyz.openbmc_project.Software.Activation.Activations.Ready'
+INVALID = 'xyz.openbmc_project.Software.Activation.Activations.Invalid'
+ACTIVATING = 'xyz.openbmc_project.Software.Activation.Activations.Activating'
+NOTREADY = 'xyz.openbmc_project.Software.Activation.Activations.NotReady'
+FAILED = 'xyz.openbmc_project.Software.Activation.Activations.Failed'
+
+SOFTWARE_ACTIVATION = 'xyz.openbmc_project.Software.Activation'
+REQUESTED_ACTIVATION = SOFTWARE_ACTIVATION + '.RequestedActivations'
+REQUESTED_ACTIVE = REQUESTED_ACTIVATION + '.Active'
+REQUESTED_NONE = REQUESTED_ACTIVATION + '.None'
+
+SOFTWARE_PURPOSE = 'xyz.openbmc_project.Software.Version.VersionPurpose'
+VERSION_PURPOSE_HOST = SOFTWARE_PURPOSE + '.Host'
+VERSION_PURPOSE_BMC = SOFTWARE_PURPOSE + '.BMC'
+VERSION_PURPOSE_SYSTEM = SOFTWARE_PURPOSE + '.System'
# Inventory URI
HOST_INVENTORY_URI = '/xyz/openbmc_project/inventory/'
diff --git a/extended/code_update/code_update.py b/extended/code_update/code_update.py
new file mode 100644
index 0000000..5f29936
--- /dev/null
+++ b/extended/code_update/code_update.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+
+r"""
+This module is the python counterpart to code_update.robot.
+"""
+
+import os
+import sys
+import re
+import string
+import tarfile
+import time
+
+robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
+repo_lib_path = re.sub('/extended/code_update/', '/lib', robot_pgm_dir_path)
+repo_data_path = re.sub('/extended/code_update/', '/data', robot_pgm_dir_path)
+sys.path.append(repo_lib_path)
+sys.path.append(repo_data_path)
+
+import gen_robot_keyword as keyword
+import gen_print as gp
+import gen_valid as gv
+import variables as var
+from robot.libraries.BuiltIn import BuiltIn
+
+
+###############################################################################
+def wait_for_activation_state_change(version_id, initial_state):
+
+ r"""
+ Wait for the current activation state of ${version_id} to
+ change from the state provided by the calling function.
+
+ Description of argument(s):
+ version_id The version ID whose state change we are waiting for.
+ initial_state The activation state we want to wait for.
+ """
+
+ keyword.run_key_u("Open Connection And Log In")
+ retry = 0
+ while (retry < 20):
+ status, software_state = keyword.run_key("Read Properties " +
+ var.SOFTWARE_VERSION + str(version_id))
+ current_state = (software_state)["Activation"]
+ if (initial_state == current_state):
+ time.sleep(60)
+ retry += 1
+ else:
+ return
+ return
+
+###############################################################################
diff --git a/extended/code_update/code_update.robot b/extended/code_update/code_update.robot
new file mode 100644
index 0000000..1c9e4f4
--- /dev/null
+++ b/extended/code_update/code_update.robot
@@ -0,0 +1,90 @@
+*** Settings ***
+Documentation Code update to a target BMC.
+... Execution Method:
+... python -m robot -v OPENBMC_HOST:<hostname>
+... -v IMAGE_FILE_PATH:<path/*.tar> code_update.robot
+...
+... Code update method BMC
+... Update work flow sequence:
+... - Upload image via REST
+... - Verify that the file exists on the BMC
+... - Check software "Activation" status to be "Ready"
+... - Set "Requested Activation" to "Active"
+... - Wait for code update to complete
+... - Verify the new version
+
+#TODO: Move test_uploadimage.py to lib/
+Library ../test_uploadimage.py
+Library code_update.py
+Library OperatingSystem
+Variables ../../data/variables.py
+Resource code_update_utils.robot
+Resource ../lib/rest_client.robot
+Resource ../lib/openbmc_ffdc.robot
+
+Test Teardown Code Update Teardown
+
+*** Variables ***
+
+${QUIET} ${1}
+${version_id} ${EMPTY}
+${upload_dir_path} /tmp/images/
+${image_version} ${EMPTY}
+${image_purpose} ${EMPTY}
+${activation_state} ${EMPTY}
+${requested_state} ${EMPTY}
+${IMAGE_FILE_PATH} ${EMPTY}
+
+*** Test Cases ***
+
+REST PNOR Code Update
+ [Documentation] Do a PNOR code update by uploading image on BMC via REST.
+ [Tags] REST_PNOR_Code_Update
+
+ OperatingSystem.File Should Exist ${IMAGE_FILE_PATH}
+ ${IMAGE_VERSION}= Get Version Tar ${IMAGE_FILE_PATH}
+
+ ${image_data}= OperatingSystem.Get Binary File ${IMAGE_FILE_PATH}
+ Upload Image To BMC /upload/image data=${image_data}
+ ${ret}= Verify Image Upload
+ Should Be True ${ret}
+
+ # Verify the image is 'READY' to be activated.
+ ${software_state}= Read Properties ${SOFTWARE_VERSION}${version_id}
+ Should Be Equal As Strings &{software_state}[Activation] ${READY}
+
+ # Request the image to be activated.
+ ${args}= Create Dictionary data=${REQUESTED_ACTIVE}
+ Write Attribute ${SOFTWARE_VERSION}${version_id}
+ ... RequestedActivation data=${args}
+ ${software_state}= Read Properties ${SOFTWARE_VERSION}${version_id}
+ Should Be Equal As Strings &{software_state}[RequestedActivation]
+ ... ${REQUESTED_ACTIVE}
+
+ # Verify code update was successful and Activation state is Active.
+ Wait For Activation State Change ${version_id} ${ACTIVATING}
+ ${software_state}= Read Properties ${SOFTWARE_VERSION}${version_id}
+ Should Be Equal As Strings &{software_state}[Activation] ${ACTIVE}
+
+*** Keywords ***
+
+Code Update Teardown
+ [Documentation] Do code update test case teardown.
+
+ #TODO: Use the Delete interface instead once delivered
+ Open Connection And Log In
+ Execute Command On BMC rm -rf /tmp/images/*
+
+ Close All Connections
+ FFDC On Test Case Fail
+
+Get PNOR Extended Version
+ [Documentation] Return the PNOR extended version.
+ ... Description of arguments:
+ ... path Path of the MANIFEST file
+ [Arguments] ${path}
+
+ Open Connection And Log In
+ ${version}= Execute Command On BMC
+ ... "grep \"extended_version=\" " + ${path}
+ [return] ${version.split(",")}
diff --git a/extended/test_uploadimage.py b/extended/test_uploadimage.py
index e4ac71b..024c4f0 100644
--- a/extended/test_uploadimage.py
+++ b/extended/test_uploadimage.py
@@ -83,8 +83,8 @@
grk.run_key_u("Open Connection And Log In")
status, ret_values =\
grk.run_key("Execute Command On BMC cat "
- + file_path + " | grep \"version=\"")
- return ret_values.split("=")[-1]
+ + file_path + " | grep \"version=\"", ignore=1)
+ return (ret_values.split("\n")[0]).split("=")[-1]
###############################################################################
@@ -102,7 +102,7 @@
grk.run_key_u("Open Connection And Log In")
status, ret_values =\
grk.run_key("Execute Command On BMC cat "
- + file_path + " | grep \"purpose=\"")
+ + file_path + " | grep \"purpose=\"", ignore=1)
return ret_values.split("=")[-1]
###############################################################################
@@ -122,7 +122,7 @@
of the images in the upload dir.
"""
- upload_dir = BuiltIn().get_variable_value("${UPLOAD_DIR_PATH}")
+ upload_dir = BuiltIn().get_variable_value("${upload_dir_path}")
grk.run_key_u("Open Connection And Log In")
status, image_list =\
grk.run_key("Execute Command On BMC ls -d " + upload_dir
@@ -149,14 +149,16 @@
a valid d-bus object
"""
- image_version = BuiltIn().get_variable_value("${IMAGE_VERSION}")
+ image_version = BuiltIn().get_variable_value("${image_version}")
image_path = get_image_path(image_version)
image_version_id = image_path.split("/")[-2]
+ BuiltIn().set_global_variable("${version_id}", image_version_id)
grk.run_key_u("Open Connection And Log In")
image_purpose = get_image_purpose(image_path + "MANIFEST")
- if (image_purpose == "bmc" or image_purpose == "host"):
- uri = var.SOFTWARE_VERSION_URI + "/" + image_version_id
+ if (image_purpose == var.VERSION_PURPOSE_BMC or
+ image_purpose == var.VERSION_PURPOSE_HOST):
+ uri = var.SOFTWARE_VERSION + image_version_id
status, ret_values =\
grk.run_key("Read Attribute " + uri + " Activation")
@@ -167,7 +169,7 @@
gp.print_var(ret_values)
return False
else:
- gp.print_var(versionPurpose)
+ gp.print_var(image_purpose)
return False
###############################################################################
diff --git a/extended/test_uploadimage.robot b/extended/test_uploadimage.robot
index 008596c..3b50c46 100644
--- a/extended/test_uploadimage.robot
+++ b/extended/test_uploadimage.robot
@@ -24,9 +24,9 @@
*** Variables ***
${timeout} 10
-${UPLOAD_DIR_PATH} /tmp/images/
+${upload_dir_path} /tmp/images/
${QUIET} ${1}
-${IMAGE_VERSION} ${EMPTY}
+${image_version} ${EMPTY}
*** Test Cases ***
@@ -37,7 +37,7 @@
OperatingSystem.File Should Exist ${IMAGE_FILE_PATH}
${IMAGE_VERSION}= Get Version Tar ${IMAGE_FILE_PATH}
${image_data}= OperatingSystem.Get Binary File ${IMAGE_FILE_PATH}
- Upload Post Request /upload/image data=${image_data}
+ Upload Image To BMC /upload/image data=${image_data}
${ret}= Verify Image Upload
Should Be True True == ${ret}
@@ -48,12 +48,12 @@
@{image}= Create List ${TFTP_FILE_NAME} ${TFTP_SERVER}
${data}= Create Dictionary data=@{image}
${resp}= OpenBMC Post Request
- ... ${SOFTWARE_VERSION_URI}/action/DownloadViaTFTP data=${data}
+ ... ${SOFTWARE_VERSION}/action/DownloadViaTFTP data=${data}
Should Be Equal As Strings ${resp.status_code} ${HTTP_OK}
Sleep 1 minute
- ${upload_file}= Get Latest File ${UPLOAD_DIR_PATH}
- ${IMAGE_VERSION}= Get Image Version
- ... ${UPLOAD_DIR_PATH}${upload_file}/MANIFEST
+ ${upload_file}= Get Latest File ${upload_dir_path}
+ ${image_version}= Get Image Version
+ ... ${upload_dir_path}${upload_file}/MANIFEST
${ret}= Verify Image Upload
Should Be True True == ${ret}
@@ -116,12 +116,15 @@
*** Keywords ***
Upload Image Teardown
- [Documentation] Log FFDC if test suite fails and collect SOL log for
- ... debugging purposes.
+ [Documentation] Log FFDC if test fails for debugging purposes.
+
+ Open Connection And Log In
+ Execute Command On BMC rm -rf /tmp/images/*
Close All Connections
FFDC On Test Case Fail
+
Upload Post Request
[Arguments] ${uri} ${timeout}=10 ${quiet}=${QUIET} &{kwargs}
@@ -159,4 +162,3 @@
${version}= Get Version Tar bad_image.tar
OperatingSystem.Remove File bad_image.tar
[Return] ${version}
-
diff --git a/lib/rest_client.robot b/lib/rest_client.robot
index ff3142a..b3c0056 100644
--- a/lib/rest_client.robot
+++ b/lib/rest_client.robot
@@ -196,3 +196,25 @@
${resp}= OpenBmc Post Request ${base_uri}/action/${method}
... timeout=${timeout} quiet=${quiet} &{kwargs}
[Return] ${resp}
+
+Upload Image To BMC
+ [Arguments] ${uri} ${timeout}=10 ${quiet}=${QUIET} &{kwargs}
+
+ # Description of argument(s):
+ # uri URI for uploading image via REST e.g. "/upload/image".
+ # timeout Time allocated for the REST command to return status
+ # (specified in Robot Framework Time Format e.g. "3 mins").
+ # quiet If enabled turns off logging to console.
+ # kwargs A dictionary keys/values to be passed directly to
+ # Post Request.
+
+ Initialize OpenBMC ${timeout} quiet=${quiet}
+ ${base_uri}= Catenate SEPARATOR= ${DBUS_PREFIX} ${uri}
+ ${headers}= Create Dictionary Content-Type=application/octet-stream
+ ... Accept=application/octet-stream
+ Set To Dictionary ${kwargs} headers ${headers}
+ Run Keyword If '${quiet}' == '${0}' Log Request method=Post
+ ... base_uri=${base_uri} args=&{kwargs}
+ ${ret}= Post Request openbmc ${base_uri} &{kwargs} timeout=${timeout}
+ Run Keyword If '${quiet}' == '${0}' Log Response ${ret}
+ Should Be Equal As Strings ${ret.status_code} ${HTTP_OK}