Add bios testing to plugin

Create functional tests for the BIOS cleanup steps

Change-Id: I7d40c0ce64d4d3c8c5212ffe6bbdfc8717682204
diff --git a/ironic_tempest_plugin/config.py b/ironic_tempest_plugin/config.py
index 8d10b00..3594b5b 100644
--- a/ironic_tempest_plugin/config.py
+++ b/ironic_tempest_plugin/config.py
@@ -120,6 +120,9 @@
     cfg.ListOpt('enabled_hardware_types',
                 default=['ipmi'],
                 help="List of Ironic enabled hardware types."),
+    cfg.ListOpt('enabled_bios_interfaces',
+                default=['fake'],
+                help="List of Ironic enabled bios interfaces."),
     cfg.ListOpt('enabled_deploy_interfaces',
                 default=['iscsi', 'direct'],
                 help="List of Ironic enabled deploy interfaces."),
diff --git a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
index 11fdebf..25420bc 100644
--- a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
+++ b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
@@ -89,6 +89,11 @@
         return self._list_request('/nodes/%s/states' % uuid)
 
     @base.handle_errors
+    def list_node_bios_settings(self, uuid):
+        """List node bios settings."""
+        return self._list_request('/nodes/%s/bios' % uuid)
+
+    @base.handle_errors
     def list_ports_detail(self, **kwargs):
         """Details list all existing ports."""
         return self._list_request('/ports/detail', **kwargs)
@@ -410,6 +415,7 @@
                            'properties/local_gb',
                            'properties/memory_mb',
                            'driver',
+                           'bios_interface',
                            'deploy_interface',
                            'rescue_interface',
                            'instance_uuid',
diff --git a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
index 74367f9..c7d6b50 100644
--- a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
+++ b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
@@ -359,6 +359,38 @@
         # was actually removing the metadata, because there was not a good
         # way to achieve that check for vms and baremetal
 
+    def check_bios_apply_and_reset_configuration(self, node, settings):
+        clean_steps = [
+            {
+                "interface": "bios",
+                "step": "apply_configuration",
+                "args": {"settings": settings}
+            }
+        ]
+        self.manual_cleaning(node, clean_steps=clean_steps)
+
+        # query the api to check node bios settings
+        _, bios_settings = self.baremetal_client.list_node_bios_settings(
+            node['uuid'])
+
+        for setting in settings:
+            self.assertIn(setting['name'],
+                          [i['name'] for i in bios_settings['bios']])
+            self.assertIn(setting['value'],
+                          [i['value'] for i in bios_settings['bios']])
+
+        # reset bios and ensure that the settings are not there
+        clean_steps = [
+            {
+                "interface": "bios",
+                "step": "factory_reset"
+            }
+        ]
+        self.manual_cleaning(node, clean_steps=clean_steps)
+        _, bios_settings = self.baremetal_client.list_node_bios_settings(
+            node['uuid'])
+        self.assertEqual([], bios_settings['bios'])
+
 
 class BaremetalStandaloneScenarioTest(BaremetalStandaloneManager):
 
@@ -368,6 +400,12 @@
     # The node driver to use in the test
     driver = None
 
+    # The bios interface to use by the HW type. The bios interface of the
+    # node used in the test will be set to this value. If set to None, the
+    # node will retain its existing bios_interface value (which may have been
+    # set via a different test).
+    bios_interface = None
+
     # The deploy interface to use by the HW type. The deploy interface of
     # the node used in the test will be set to this value. If set to None,
     # the node will retain its existing deploy_interface value (which may have
@@ -404,6 +442,13 @@
                     'driver': cls.driver,
                     'enabled_drivers': CONF.baremetal.enabled_drivers,
                     'enabled_hw_types': CONF.baremetal.enabled_hardware_types})
+        if (cls.bios_interface and cls.bios_interface not in
+                CONF.baremetal.enabled_bios_interfaces):
+            raise cls.skipException(
+                "Bios interface %(iface)s required by the test is not in the "
+                "list of enabled bios interfaces %(enabled)s" % {
+                    'iface': cls.bios_interface,
+                    'enabled': CONF.baremetal.enabled_bios_interfaces})
         if (cls.deploy_interface and cls.deploy_interface not in
                 CONF.baremetal.enabled_deploy_interfaces):
             raise cls.skipException(
@@ -446,6 +491,8 @@
         if not uuidutils.is_uuid_like(cls.image_ref):
             image_checksum = cls.image_checksum
         boot_kwargs = {'image_checksum': image_checksum}
+        if cls.bios_interface:
+            boot_kwargs['bios_interface'] = cls.bios_interface
         if cls.deploy_interface:
             boot_kwargs['deploy_interface'] = cls.deploy_interface
         if cls.rescue_interface:
diff --git a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_bios.py b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_bios.py
new file mode 100644
index 0000000..be92c16
--- /dev/null
+++ b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_bios.py
@@ -0,0 +1,51 @@
+#
+# Copyright 2018 Red Hat Inc.
+#
+# 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.
+
+from oslo_log import log as logging
+from tempest import config
+from tempest.lib import decorators
+
+from ironic_tempest_plugin.tests.scenario import \
+    baremetal_standalone_manager as bsm
+
+LOG = logging.getLogger(__name__)
+CONF = config.CONF
+
+
+class BaremetalFakeBios(
+        bsm.BaremetalStandaloneScenarioTest):
+
+    driver = 'fake-hardware'
+    bios_interface = 'fake'
+    deploy_interface = 'iscsi'
+    image_ref = CONF.baremetal.whole_disk_image_ref
+    wholedisk_image = True
+    delete_node = False
+    api_microversion = '1.40'
+
+    @decorators.idempotent_id('ef55c44a-cc10-4cf6-8fda-85f0c0793150')
+    def test_bios_apply_and_reset_configuration(self):
+        settings = [
+            {
+                "name": "setting1_name",
+                "value": "setting1_value"
+            },
+            {
+                "name": "setting2_name",
+                "value": "setting2_value"
+            }
+        ]
+
+        self.check_bios_apply_and_reset_configuration(self.node, settings)