Validate scheduling fields in basic ops scenario

Currently there is no validation of node scheduling fields - resource
class and traits - in the scenario tests. This change adds validation of
these fields to the bare metal basic ops test.

We query the flavor used to boot the instance, and extract all requested
resources and traits from extra_specs. These are matched against the
resource class and traits set on the bare metal node that was scheduled.

Change-Id: I9ddc895ead61cf02c6967ead094d061cb7f558d8
Depends-On: https://review.openstack.org/545370
Related-Bug: #1722194
diff --git a/ironic_tempest_plugin/services/baremetal/base.py b/ironic_tempest_plugin/services/baremetal/base.py
index 494c780..c588a70 100644
--- a/ironic_tempest_plugin/services/baremetal/base.py
+++ b/ironic_tempest_plugin/services/baremetal/base.py
@@ -154,10 +154,14 @@
                       resource,
                       uuid=None,
                       permanent=False,
+                      headers=None,
+                      extra_headers=False,
                       **kwargs):
         """Gets a specific object of the specified type.
 
         :param uuid: Unique identifier of the object in UUID format.
+        :param headers: List of headers to use in request.
+        :param extra_headers: Specify whether to use headers.
         :returns: Serialized object as a dictionary.
 
         """
@@ -165,7 +169,8 @@
             uri = kwargs['uri']
         else:
             uri = self._get_uri(resource, uuid=uuid, permanent=permanent)
-        resp, body = self.get(uri)
+        resp, body = self.get(uri, headers=headers,
+                              extra_headers=extra_headers)
         self.expected_success(http_client.OK, resp.status)
 
         return resp, self.deserialize(body)
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 550128a..c9f52ae 100644
--- a/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
+++ b/ironic_tempest_plugin/services/baremetal/v1/json/baremetal_client.py
@@ -20,6 +20,24 @@
     version = '1'
     uri_prefix = 'v1'
 
+    @staticmethod
+    def _get_headers(api_version):
+        """Return headers for a request.
+
+        Currently supports a header specifying the API version to use.
+
+        :param api_version: Ironic API version to use.
+        :return: a 2-tuple of (extra_headers, headers), where 'extra_headers'
+            is whether to use headers, and 'headers' is a list of headers to
+            use in the request.
+        """
+        extra_headers = False
+        headers = None
+        if api_version is not None:
+            extra_headers = True
+            headers = {'x-openstack-ironic-api-version': api_version}
+        return extra_headers, headers
+
     @base.handle_errors
     def list_nodes(self, **kwargs):
         """List all existing nodes."""
@@ -81,28 +99,33 @@
         return self._list_request('drivers')
 
     @base.handle_errors
-    def show_node(self, uuid):
+    def show_node(self, uuid, api_version=None):
         """Gets a specific node.
 
         :param uuid: Unique identifier of the node in UUID format.
+        :param api_version: Ironic API version to use.
         :return: Serialized node as a dictionary.
 
         """
-        return self._show_request('nodes', uuid)
+        extra_headers, headers = self._get_headers(api_version)
+        return self._show_request('nodes', uuid, headers=headers,
+                                  extra_headers=extra_headers)
 
     @base.handle_errors
-    def show_node_by_instance_uuid(self, instance_uuid):
+    def show_node_by_instance_uuid(self, instance_uuid, api_version=None):
         """Gets a node associated with given instance uuid.
 
         :param instance_uuid: Unique identifier of the instance in UUID format.
+        :param api_version: Ironic API version to use.
         :return: Serialized node as a dictionary.
 
         """
         uri = '/nodes/detail?instance_uuid=%s' % instance_uuid
-
+        extra_headers, headers = self._get_headers(api_version)
         return self._show_request('nodes',
                                   uuid=None,
-                                  uri=uri)
+                                  uri=uri, headers=headers,
+                                  extra_headers=extra_headers)
 
     @base.handle_errors
     def show_chassis(self, uuid):