Add Ironic standalone tests

This patch adds the following standalone tests:

  * agent_ipmitool + wholedisk image + bios
  * agent_ipmitool + partitioned image + bios
  * pxe_ipmitool + wholedisk image + bios
  * pxe_ipmitool + partitioned image + bios

Partial-Bug: #1660606

Change-Id: Ic04b0f134e20d9937a610a14d7c4128f45738eeb
diff --git a/ironic_tempest_plugin/services/baremetal/base.py b/ironic_tempest_plugin/services/baremetal/base.py
index ec572b2..bb9ba9e 100644
--- a/ironic_tempest_plugin/services/baremetal/base.py
+++ b/ironic_tempest_plugin/services/baremetal/base.py
@@ -18,9 +18,21 @@
 from tempest.lib.common import api_version_utils
 from tempest.lib.common import rest_client
 
+# NOTE(vsaienko): concurrent tests work because they are launched in
+# separate processes so global variables are not shared among them.
 BAREMETAL_MICROVERSION = None
 
 
+def set_baremetal_api_microversion(baremetal_microversion):
+    global BAREMETAL_MICROVERSION
+    BAREMETAL_MICROVERSION = baremetal_microversion
+
+
+def reset_baremetal_api_microversion():
+    global BAREMETAL_MICROVERSION
+    BAREMETAL_MICROVERSION = None
+
+
 def handle_errors(f):
     """A decorator that allows to ignore certain types of errors."""
 
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 dc4cdc1..559e21d 100644
--- a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
+++ b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
@@ -215,10 +215,14 @@
         return self._delete_request('ports', uuid)
 
     @base.handle_errors
-    def update_node(self, uuid, **kwargs):
+    def update_node(self, uuid, patch=None, **kwargs):
         """Update the specified node.
 
         :param uuid: The unique identifier of the node.
+        :param patch: A JSON path that sets values of the specified attributes
+                      to the new ones.
+        :param **kwargs: Attributes and new values for them, used only when
+                         patch param is not set.
         :return: A tuple with the server response and the updated node.
 
         """
@@ -228,8 +232,8 @@
                            'properties/memory_mb',
                            'driver',
                            'instance_uuid')
-
-        patch = self._make_patch(node_attributes, **kwargs)
+        if not patch:
+            patch = self._make_patch(node_attributes, **kwargs)
 
         return self._patch_request('nodes', uuid, patch)
 
@@ -271,7 +275,8 @@
                                  target)
 
     @base.handle_errors
-    def set_node_provision_state(self, node_uuid, state, configdrive=None):
+    def set_node_provision_state(self, node_uuid, state, configdrive=None,
+                                 clean_steps=None):
         """Set provision state of the specified node.
 
         :param node_uuid: The unique identifier of the node.
@@ -279,8 +284,15 @@
                 (active/rebuild/deleted/inspect/manage/provide).
         :param configdrive: A gzipped, base64-encoded
             configuration drive string.
+        :param clean_steps: A list with clean steps to execute.
         """
-        data = {'target': state, 'configdrive': configdrive}
+        data = {'target': state}
+        # NOTE (vsaienk0): Add both here if specified, do not check anything.
+        # API will return an error in case of invalid parameters.
+        if configdrive is not None:
+            data['configdrive'] = configdrive
+        if clean_steps is not None:
+            data['clean_steps'] = clean_steps
         return self._put_request('nodes/%s/states/provision' % node_uuid,
                                  data)