Source code for testcases.testRestAPI

#!/usr/bin/env python3
# OpenPOWER Automated Test Project
#
# Contributors Listed Below - COPYRIGHT 2017
# [+] International Business Machines Corp.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.
#

'''
Test OpenBMC REST API
---------------------

Tests a bunch of functionality only available through OpenBMC REST API

Generally takes about 10 minutes to run rest-api suite

.. note::

   The OpenBMC REST API is not a long term nor stable API.
   It's just as likely that OpenBMC changes their API as anything.
'''

import os

import unittest

import OpTestConfiguration
from common.OpTestSystem import OpSystemState
from common.Exceptions import HTTPCheck

import logging
import OpTestLogger
log = OpTestLogger.optest_logger_glob.get_logger(__name__)


[docs]class RestAPI(unittest.TestCase): ''' RestAPI Class - Execution order independent --run-suite rest-api --run testcases.testRestAPI.Runtime --run testcases.testRestAPI.HostOff or run the individual tests '''
[docs] @classmethod def setUpClass(cls): cls.conf = OpTestConfiguration.conf if "OpenBMC" not in cls.conf.args.bmc_type: raise unittest.SkipTest("OpenBMC specific Rest API Tests") cls.cv_SYSTEM = cls.conf.system() cls.cv_BMC = cls.conf.bmc() cls.rest = cls.conf.system().rest try: if cls.desired == OpSystemState.OFF: cls.cv_SYSTEM.goto_state(OpSystemState.OFF) else: cls.cv_SYSTEM.goto_state(OpSystemState.OS) except Exception as e: log.debug("Unable to find cls.desired, probably a test code problem") cls.cv_SYSTEM.goto_state(OpSystemState.OS)
[docs]class Runtime(RestAPI, unittest.TestCase): ''' Runtime Class performs tests with Host On HostOff Class will turn the Host Off --run testcases.testRestAPI.Runtime --run testcases.testRestAPI.HostOff '''
[docs] @classmethod def setUpClass(cls): cls.desired = OpSystemState.OS super(Runtime, cls).setUpClass()
[docs] def test_tpm_policy_setting(self): ''' REST TPM Policy Settings --run testcases.testRestAPI.Runtime.test_tpm_policy_setting --run testcases.testRestAPI.HostOff.test_tpm_policy_setting ''' status = self.rest.is_tpm_enabled() log.debug("TPM Enabled Starts={}".format(status)) self.rest.enable_tpm() self.assertTrue(self.rest.is_tpm_enabled(), "OpenBMC failed to enable TPM policy") self.rest.disable_tpm() self.assertFalse(self.rest.is_tpm_enabled(), "OpenBMC failed to disable TPM policy")
[docs] def test_system_power_cap(self): ''' REST System Power Cap --run testcases.testRestAPI.Runtime.test_system_power_cap --run testcases.testRestAPI.HostOff.test_system_power_cap ''' # System power cap enable/disable tests self.rest.power_cap_enable() PowerCapEnable, PowerCap = self.rest.get_power_cap_settings() log.debug("SHOULD BE ENABLED PowerCapEnable={} PowerCap={}".format( PowerCapEnable, PowerCap)) self.assertEqual(int(PowerCapEnable), 1, "System Power Cap Enable Failed") self.rest.power_cap_disable() PowerCapEnable, PowerCap = self.rest.get_power_cap_settings() log.debug("SHOULD BE DISABLED PowerCapEnable={} PowerCap={}".format( PowerCapEnable, PowerCap)) self.assertEqual(int(PowerCapEnable), 0, "System Power Cap Disable Failed")
[docs] def test_occ_active(self): ''' REST OCC Active --run testcases.testRestAPI.Runtime.test_occ_active --run testcases.testRestAPI.HostOff.test_occ_active ''' # OCC Active state tests using RestAPI ids = self.rest.get_occ_ids() log.debug("OCC IDs: {}".format(ids)) for id in ids: log.debug("OpSystemState={}".format(self.cv_SYSTEM.get_state())) # If system is in runtime OCC should be Active if self.cv_SYSTEM.get_state() in [OpSystemState.PETITBOOT, OpSystemState.PETITBOOT_SHELL, OpSystemState.BOOTING, OpSystemState.OS]: self.assertTrue(self.rest.is_occ_active( id), "OCC%s is not in active state" % id) # if system is in standby state OCC should be inactive elif self.cv_SYSTEM.get_state() == OpSystemState.OFF: self.assertFalse(self.rest.is_occ_active( id), "OCC%s is still in active state" % id)
[docs] def test_software_enumerate(self): ''' REST Software Enumerate --run testcases.testRestAPI.Runtime.test_software_enumerate --run testcases.testRestAPI.HostOff.test_software_enumerate ''' self.rest.software_enumerate() ids = self.rest.get_list_of_image_ids() log.debug("Software Enumerate IDs: {}".format(ids)) for id in ids: log.debug("Looking at Image Data Info ID={}".format(id)) start_priority = self.rest.get_image_priority(id) log.debug("Image ID={} Starting Priority={}".format( id, start_priority)) self.rest.set_image_priority(id, start_priority) updated_priority = self.rest.get_image_priority(id) log.debug("Image ID={} Updated Priority={}".format( id, updated_priority)) self.assertEqual(start_priority, updated_priority, "Image Priority Change did not happen as expected")
[docs] def test_image_lists(self): ''' REST Image Interfaces --run testcases.testRestAPI.Runtime.test_image_lists --run testcases.testRestAPI.HostOff.test_image_lists ''' ids = self.rest.get_list_of_image_ids() log.debug("Image IDs: {}".format(ids)) for id in ids: status = self.rest.is_image_already_active(id) log.debug("Image ID={} Active={}".format(id, status)) host_images = self.rest.host_image_ids() log.debug("Host Images: {}".format(host_images)) bmc_images = self.rest.bmc_image_ids() for id in bmc_images: status = self.rest.validate_functional_bootside(id) log.debug( "Image ID={} Functional Boot Side Validation: {}".format(id, status)) if status: try: activation_status = self.rest.image_ready_for_activation( id, timeout=1) log.debug("Activation Status: {}".format( activation_status)) except HTTPCheck as e: # expected since the image is active, we just testing API # xyz.openbmc_project.Software.Activation.Activations.Active log.debug( "HTTPCheck Exception={} e.message={}".format(e, e.message)) log.debug("BMC Images: {}".format(bmc_images))
[docs] def test_field_mode_enable_disable(self): ''' REST Field Mode Enable and Disable --run testcases.testRestAPI.Runtime.test_field_mode_enable_disable --run testcases.testRestAPI.HostOff.test_field_mode_enable_disable ''' # Field mode tests self.rest.has_field_mode_set() self.rest.set_field_mode("1") self.assertTrue(self.rest.has_field_mode_set(), "Field Mode Enable Failed") self.rest.set_field_mode("0") # clear_field_mode will reboot the BMC self.cv_BMC.clear_field_mode() self.assertFalse(self.rest.has_field_mode_set(), "Field Mode Disable Failed")
[docs] def test_upload_image(self): ''' REST Upload Image --run testcases.testRestAPI.Runtime.test_upload_image --run testcases.testRestAPI.HostOff.test_upload_image ''' # Upload image try: self.rest.upload_image(os.path.basename("README.md"), minutes=None) except Exception as e: # upload_image only works for verified images # so this is expected to fail, but we test the API log.debug("Upload Image Exception={} Message={}".format(e, e.message)) check_list = ["Version already exists", "failed to be extracted", "we timed out trying"] matching = [xs for xs in check_list if xs in e.message] if not len(matching): self.assertTrue(False, "Unexpected failure on upload_image")
[docs] def test_inventory(self): ''' REST Get Inventory --run testcases.testRestAPI.Runtime.test_inventory --run testcases.testRestAPI.HostOff.test_inventory ''' # FRU Inventory r = self.rest.get_inventory() log.debug("Inventory: {}".format(r))
# r = dictionary of dictionaries
[docs] def test_sensors(self): ''' REST Sensors --run testcases.testRestAPI.Runtime.test_sensors --run testcases.testRestAPI.HostOff.test_sensors ''' # Sensors r = self.rest.sensors() log.debug("Sensors: {}".format(r))
# r = dictionary of dictionaries
[docs] def test_obmc_states(self): ''' REST OBMC States --run testcases.testRestAPI.Runtime.test_obmc_states --run testcases.testRestAPI.HostOff.test_obmc_states ''' # get BMC State r = self.rest.get_bmc_state() # r=xyz.openbmc_project.State.BMC.BMCState.Ready # Get Chassis Power State r = self.rest.get_power_state() # r=xyz.openbmc_project.State.Host.HostState.Running # Get Host State r = self.rest.get_host_state()
# r=xyz.openbmc_project.State.Host.HostState.Running
[docs] def test_list_sel(self): ''' REST List SELs --run testcases.testRestAPI.Runtime.test_list_sel --run testcases.testRestAPI.HostOff.test_list_sel ''' # List SEL records json_data = self.rest.list_sel() log.debug("List SEL: {}".format(json_data)) # get list of SEL event ID's if any exist id_list, dict_list = self.rest.get_sel_ids() log.debug("SEL ID List: {} SEL DICT List: {}".format(id_list, dict_list))
[docs] def test_dump_sels(self): ''' REST Dump SELs --run testcases.testRestAPI.Runtime.test_dump_sels --run testcases.testRestAPI.HostOff.test_dump_sels ''' # Dump SEL records # Dump list of SEL event ID's if any exist id_list, dict_list = self.rest.get_sel_ids(dump=True) log.debug("SEL ID List: {} SEL DICT List: {}".format(id_list, dict_list))
[docs] def test_clear_sel(self): ''' REST Clear SELs --run testcases.testRestAPI.Runtime.test_clear_sel --run testcases.testRestAPI.HostOff.test_clear_sel ''' # Clear SEL entry by ID self.rest.clear_sel_by_id() id_list, dict_list = self.rest.get_sel_ids() log.debug("SEL ID List: {}\nSEL DICT List: {}\n".format( id_list, dict_list)) # Clear Complete SEL Repository self.rest.clear_sel() # Check if SEL has really zero entries or not self.assertTrue(self.rest.verify_clear_sel(), "openBMC failed to clear SEL repository")
[docs] def test_obmc_delete_dumps(self): ''' REST OBMC Delete ALL Dumps --run testcases.testRestAPI.Runtime.test_obmc_delete_dumps --run testcases.testRestAPI.HostOff.test_obmc_delete_dumps ''' # Delete all the dumps r = self.rest.delete_all_dumps() log.debug("Deleted all dumps")
[docs] def test_obmc_create_dump(self): ''' REST OBMC Create Dump --run testcases.testRestAPI.Runtime.test_obmc_create_dump --run testcases.testRestAPI.HostOff.test_obmc_create_dump ''' # Create a dump dump_id = self.rest.create_new_dump() log.debug("Created new dump ID={}".format(dump_id))
[docs] def test_obmc_download_dumps(self): ''' REST OBMC Download ALL Dumps --run testcases.testRestAPI.Runtime.test_obmc_download_dumps --run testcases.testRestAPI.HostOff.test_obmc_download_dumps ''' # List available dumps dump_ids = self.rest.get_dump_ids() log.debug("Available Dumps to Download: {}".format(dump_ids)) for id in dump_ids: dump_id = id log.debug("Downloading Dump ID: {}".format(dump_id)) self.rest.download_dump(id) if not len(dump_ids): log.debug("No Available dumps to download")
[docs] def test_obmc_dump(self): ''' REST OBMC List, Create and Download a Dump --run testcases.testRestAPI.Runtime.test_obmc_dump --run testcases.testRestAPI.HostOff.test_obmc_dump ''' # List available dumps r = self.rest.list_available_dumps() log.debug("Available Dumps: {}".format(r.json().get('data'))) # OpenBMC Dump capture procedure # Initiate a dump nd get the dump id id = self.rest.create_new_dump() # Wait for the dump to finish which can be downloaded self.assertTrue(self.rest.wait_for_dump_finish( id, counter=30), "OpenBMC Dump capture timeout") # Download the dump which is ready to offload self.rest.download_dump(id)
[docs] def test_set_bootdevs(self): ''' REST Set Boot Device to Setup then Regular, this leaves the boot device as we found it --run testcases.testRestAPI.Runtime.test_set_bootdevs --run testcases.testRestAPI.HostOff.test_set_bootdevs ''' # Check current bootdev start_bootdev = self.rest.get_current_bootdev() log.debug("Boot Device Starts={}".format(start_bootdev)) # Set bootdev to setup self.rest.set_bootdev_to_setup() # Get current bootdev bootdev = self.rest.get_current_bootdev() self.assertEqual(bootdev, "Setup", "Failed to set Setup boot device") # Set bootdev to Default self.rest.set_bootdev_to_none() # Get current bootdev bootdev = self.rest.get_current_bootdev() self.assertEqual(bootdev, "Regular", "Failed to set Regular boot device") # Put the bootdev back how we found it if bootdev != start_bootdev: if start_bootdev == "Setup": self.rest.set_bootdev_to_setup() else: self.rest.set_bootdev_to_none() # Check bootdev bootdev = self.rest.get_current_bootdev() log.debug("Boot Device Ends={}".format(bootdev))
[docs] def test_get_boot_progress(self): ''' REST Get Boot Progress --run testcases.testRestAPI.Runtime.test_get_boot_progress --run testcases.testRestAPI.HostOff.test_get_boot_progress ''' # Get boot progress info r = self.rest.get_boot_progress() log.debug("Boot Progress={}".format(r))
[docs] def test_clear_gard_record(self): ''' REST Clear ALL Gard Records --run testcases.testRestAPI.Runtime.test_clear_gard_record --run testcases.testRestAPI.HostOff.test_clear_gard_record ''' self.rest.clear_gard_records()
[docs] def test_factory_reset_software(self): ''' REST Factory Reset Software USE AT YOUR OWN RISK --run testcases.testRestAPI.Runtime.test_factory_reset_software --run testcases.testRestAPI.HostOff.test_factory_reset_software ''' # self.rest.factory_reset_software() # Not sure what the effect is, enable with caution pass
[docs] def test_factory_reset_network(self): ''' REST Factory Reset Network USE AT YOUR OWN RISK --run testcases.testRestAPI.Runtime.test_factory_reset_network --run testcases.testRestAPI.HostOff.test_factory_reset_network ''' # self.rest.factory_reset_network() # It may clear static N/W, enable with caution pass
[docs] def test_update_root_password(self): ''' REST Update Root Password Caution if OpTestConfiguration bmc_password is modified util_bmc_server does automatic login with stored credentials --run testcases.testRestAPI.Runtime.test_update_root_password --run testcases.testRestAPI.HostOff.test_update_root_password ''' self.rest.update_root_password(str(self.conf.args.bmc_password))
[docs]class HostOff(Runtime): ''' Runtime Class performs tests with Host On HostOff Class will turn the Host Off --run testcases.testRestAPI.Runtime --run testcases.testRestAPI.HostOff '''
[docs] @classmethod def setUpClass(cls): cls.desired = OpSystemState.OFF super(Runtime, cls).setUpClass()
[docs]class HostBounces(RestAPI, unittest.TestCase): ''' Performs Reboots and Power On/Off variety Purpose is to exercise the REST API's --run testcases.testRestAPI.HostBounces '''
[docs] @classmethod def setUpClass(cls): cls.desired = OpSystemState.OFF super(HostBounces, cls).setUpClass()
[docs] def test_power_on(self): ''' REST Power On --run testcases.testRestAPI.HostBounces.test_power_on ''' self.rest.power_on() self.rest.wait_for_runtime()
[docs] def test_soft_reboot(self): ''' REST Soft Reboot --run testcases.testRestAPI.HostBounces.test_soft_reboot ''' self.rest.power_on() self.rest.wait_for_runtime() self.rest.soft_reboot() self.rest.wait_for_standby() self.rest.wait_for_runtime()
[docs] def test_hard_reboot(self): ''' REST Hard Reboot --run testcases.testRestAPI.HostBounces.test_hard_reboot ''' self.rest.power_on() self.rest.wait_for_runtime() self.rest.hard_reboot() self.rest.wait_for_standby() self.rest.wait_for_runtime()
[docs] def test_power_soft(self): ''' REST Power Soft Off --run testcases.testRestAPI.HostBounces.test_power_soft ''' self.rest.power_on() self.rest.wait_for_runtime() self.rest.power_soft() self.rest.wait_for_standby()
[docs] def test_power_off(self): ''' REST Power Off --run testcases.testRestAPI.HostBounces.test_power_off ''' self.rest.power_on() self.rest.wait_for_runtime() self.rest.power_off() self.rest.wait_for_standby()
def host_off_suite(): # run with Host powered OFF s = unittest.TestSuite() s.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(HostOff)) return s def runtime_suite(): # run with Host powered ON s = unittest.TestSuite() s.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(Runtime)) return s