Add support for API microversions in Tempest tests

This adds support for testing Ironic API microversions, specified
as an additional 'X-OpenStack-Ironic-API-Version' header. This change
also adds tests for Ironic API /v1/nodes/(node_ident)/states/*
endpoint for microversions that were changing state machine.

Co-Authored-By: Vladyslav Drok <vdrok@mirantis.com>
Change-Id: Ibf0c73aa6795aaa52e945fd6baa821de20a599e7
diff --git a/ironic_tempest_plugin/services/baremetal/base.py b/ironic_tempest_plugin/services/baremetal/base.py
index edb9ecb..b7a9c32 100644
--- a/ironic_tempest_plugin/services/baremetal/base.py
+++ b/ironic_tempest_plugin/services/baremetal/base.py
@@ -15,8 +15,11 @@
 from oslo_serialization import jsonutils as json
 import six
 from six.moves.urllib import parse as urllib
+from tempest.lib.common import api_version_utils
 from tempest.lib.common import rest_client
 
+BAREMETAL_MICROVERSION = None
+
 
 def handle_errors(f):
     """A decorator that allows to ignore certain types of errors."""
@@ -41,8 +44,27 @@
 class BaremetalClient(rest_client.RestClient):
     """Base Tempest REST client for Ironic API."""
 
+    api_microversion_header_name = 'X-OpenStack-Ironic-API-Version'
     uri_prefix = ''
 
+    def get_headers(self):
+        headers = super(BaremetalClient, self).get_headers()
+        if BAREMETAL_MICROVERSION:
+            headers[self.api_microversion_header_name] = BAREMETAL_MICROVERSION
+        return headers
+
+    def request(self, method, url, extra_headers=False, headers=None,
+                body=None):
+        resp, resp_body = super(BaremetalClient, self).request(
+            method, url, extra_headers, headers, body)
+        if (BAREMETAL_MICROVERSION and
+            BAREMETAL_MICROVERSION != api_version_utils.LATEST_MICROVERSION):
+            api_version_utils.assert_version_header_matches_request(
+                self.api_microversion_header_name,
+                BAREMETAL_MICROVERSION,
+                resp)
+        return resp, resp_body
+
     def serialize(self, object_dict):
         """Serialize an Ironic object."""