Merge "Change tempest BadRequest exc to tempest-lib exc"
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index e88fecb..909f0a5 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -31,14 +31,11 @@
     @test.attr(type='gate')
     def test_get_availability_zone_list(self):
         # List of availability zone
-        resp, availability_zone = self.client.get_availability_zone_list()
-        self.assertEqual(200, resp.status)
+        availability_zone = self.client.get_availability_zone_list()
         self.assertTrue(len(availability_zone) > 0)
 
     @test.attr(type='gate')
     def test_get_availability_zone_list_detail(self):
         # List of availability zones and available services
-        resp, availability_zone = \
-            self.client.get_availability_zone_list_detail()
-        self.assertEqual(200, resp.status)
+        availability_zone = self.client.get_availability_zone_list_detail()
         self.assertTrue(len(availability_zone) > 0)
diff --git a/tempest/api/compute/admin/test_baremetal_nodes.py b/tempest/api/compute/admin/test_baremetal_nodes.py
new file mode 100644
index 0000000..d894de6
--- /dev/null
+++ b/tempest/api/compute/admin/test_baremetal_nodes.py
@@ -0,0 +1,43 @@
+# Copyright 2015 NEC Corporation.  All rights reserved.
+#
+#    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 tempest.api.compute import base
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class BaremetalNodesAdminTestJSON(base.BaseV2ComputeAdminTest):
+    """
+    Tests Baremetal API
+    """
+
+    @classmethod
+    def resource_setup(cls):
+        super(BaremetalNodesAdminTestJSON, cls).resource_setup()
+        if not CONF.service_available.ironic:
+            skip_msg = ('%s skipped as Ironic is not available' % cls.__name__)
+            raise cls.skipException(skip_msg)
+        cls.client = cls.os_adm.baremetal_nodes_client
+
+    @test.attr(type='smoke')
+    def test_list_baremetal_nodes(self):
+        # List all baremetal nodes.
+        baremetal_nodes = self.client.list_baremetal_nodes()
+        self.assertNotEmpty(baremetal_nodes, "No baremetal nodes found.")
+
+        for node in baremetal_nodes:
+            baremetal_node = self.client.get_baremetal_node(node['id'])
+            self.assertEqual(node['id'], baremetal_node['id'])
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py
index f7b5e43..16ce93c 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py
@@ -30,8 +30,7 @@
     @test.attr(type='gate')
     def test_list_instance_usage_audit_logs(self):
         # list instance usage audit logs
-        resp, body = self.adm_client.list_instance_usage_audit_logs()
-        self.assertEqual(200, resp.status)
+        body = self.adm_client.list_instance_usage_audit_logs()
         expected_items = ['total_errors', 'total_instances', 'log',
                           'num_hosts_running', 'num_hosts_done',
                           'num_hosts', 'hosts_not_run', 'overall_status',
@@ -44,10 +43,9 @@
     def test_get_instance_usage_audit_log(self):
         # Get instance usage audit log before specified time
         now = datetime.datetime.now()
-        resp, body = self.adm_client.get_instance_usage_audit_log(
+        body = self.adm_client.get_instance_usage_audit_log(
             urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
 
-        self.assertEqual(200, resp.status)
         expected_items = ['total_errors', 'total_instances', 'log',
                           'num_hosts_running', 'num_hosts_done', 'num_hosts',
                           'hosts_not_run', 'overall_status', 'period_ending',
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 7e567d3..c51ad61 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -31,8 +31,7 @@
     @test.attr(type='gate')
     def test_list_migrations(self):
         # Admin can get the migrations list
-        resp, _ = self.client.list_migrations()
-        self.assertEqual(200, resp.status)
+        self.client.list_migrations()
 
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
@@ -48,8 +47,7 @@
         self.servers_client.confirm_resize(server_id)
         self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
 
-        resp, body = self.client.list_migrations()
-        self.assertEqual(200, resp.status)
+        body = self.client.list_migrations()
 
         instance_uuids = [x['instance_uuid'] for x in body]
         self.assertIn(server_id, instance_uuids)
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index 31566d6..6775d1f 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -48,8 +48,7 @@
         params = {'start': self.start,
                   'end': self.end,
                   'detailed': int(bool(True))}
-        resp, tenant_usage = self.adm_client.list_tenant_usages(params)
-        self.assertEqual(200, resp.status)
+        tenant_usage = self.adm_client.list_tenant_usages(params)
         self.assertEqual(len(tenant_usage), 8)
 
     @test.attr(type='gate')
@@ -57,10 +56,9 @@
         # Get usage for a specific tenant
         params = {'start': self.start,
                   'end': self.end}
-        resp, tenant_usage = self.adm_client.get_tenant_usage(
+        tenant_usage = self.adm_client.get_tenant_usage(
             self.tenant_id, params)
 
-        self.assertEqual(200, resp.status)
         self.assertEqual(len(tenant_usage), 8)
 
     @test.attr(type='gate')
@@ -68,8 +66,7 @@
         # Get usage for a specific tenant with non admin user
         params = {'start': self.start,
                   'end': self.end}
-        resp, tenant_usage = self.client.get_tenant_usage(
+        tenant_usage = self.client.get_tenant_usage(
             self.tenant_id, params)
 
-        self.assertEqual(200, resp.status)
         self.assertEqual(len(tenant_usage), 8)
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
index 15ccf53..321a0a1 100644
--- a/tempest/api/compute/certificates/test_certificates.py
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -24,14 +24,13 @@
     @test.attr(type='gate')
     def test_create_root_certificate(self):
         # create certificates
-        resp, body = self.certificates_client.create_certificate()
+        body = self.certificates_client.create_certificate()
         self.assertIn('data', body)
         self.assertIn('private_key', body)
 
     @test.attr(type='gate')
     def test_get_root_certificate(self):
         # get the root certificate
-        resp, body = self.certificates_client.get_certificate('root')
-        self.assertEqual(200, resp.status)
+        body = self.certificates_client.get_certificate('root')
         self.assertIn('data', body)
         self.assertIn('private_key', body)
diff --git a/tempest/api/compute/servers/test_availability_zone.py b/tempest/api/compute/servers/test_availability_zone.py
index 5ddf053..dfff014 100644
--- a/tempest/api/compute/servers/test_availability_zone.py
+++ b/tempest/api/compute/servers/test_availability_zone.py
@@ -31,6 +31,5 @@
     @test.attr(type='gate')
     def test_get_availability_zone_list_with_non_admin_user(self):
         # List of availability zone with non-administrator user
-        resp, availability_zone = self.client.get_availability_zone_list()
-        self.assertEqual(200, resp.status)
+        availability_zone = self.client.get_availability_zone_list()
         self.assertTrue(len(availability_zone) > 0)
diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py
index 46e7251..f40ae9f 100644
--- a/tempest/api/compute/test_extensions.py
+++ b/tempest/api/compute/test_extensions.py
@@ -32,8 +32,7 @@
         # List of all extensions
         if len(CONF.compute_feature_enabled.api_extensions) == 0:
             raise self.skipException('There are not any extensions configured')
-        resp, extensions = self.extensions_client.list_extensions()
-        self.assertEqual(200, resp.status)
+        extensions = self.extensions_client.list_extensions()
         ext = CONF.compute_feature_enabled.api_extensions[0]
         if ext == 'all':
             self.assertIn('Hosts', map(lambda x: x['name'], extensions))
@@ -49,6 +48,5 @@
     @test.attr(type='gate')
     def test_get_extension(self):
         # get the specified extensions
-        resp, extension = self.extensions_client.get_extension('os-consoles')
-        self.assertEqual(200, resp.status)
+        extension = self.extensions_client.get_extension('os-consoles')
         self.assertEqual('os-consoles', extension['alias'])
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index e307c5c..6b654ca 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -65,8 +65,8 @@
         self.assertEqual(1024, body.get('size'))
 
         # Now try get image file
-        _, body = self.client.get_image_file(image_id)
-        self.assertEqual(file_content, body)
+        body = self.client.get_image_file(image_id)
+        self.assertEqual(file_content, body.data)
 
     @test.attr(type='gate')
     def test_delete_image(self):
diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py
index 58511a9..eae0707 100644
--- a/tempest/api/messaging/base.py
+++ b/tempest/api/messaging/base.py
@@ -35,13 +35,25 @@
     """
 
     @classmethod
-    def resource_setup(cls):
-        super(BaseMessagingTest, cls).resource_setup()
+    def skip_checks(cls):
+        super(BaseMessagingTest, cls).skip_checks()
         if not CONF.service_available.zaqar:
             raise cls.skipException("Zaqar support is required")
-        os = cls.get_client_manager()
+
+    @classmethod
+    def setup_credentials(cls):
+        super(BaseMessagingTest, cls).setup_credentials()
+        cls.os = cls.get_client_manager()
+
+    @classmethod
+    def setup_clients(cls):
+        super(BaseMessagingTest, cls).setup_clients()
+        cls.client = cls.os.messaging_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(BaseMessagingTest, cls).resource_setup()
         cls.messaging_cfg = CONF.messaging
-        cls.client = os.messaging_client
 
     @classmethod
     def create_queue(cls, queue_name):
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 6873756..b8b0562 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -30,14 +30,19 @@
     """Base test case class for all Orchestration API tests."""
 
     @classmethod
-    def resource_setup(cls):
-        super(BaseOrchestrationTest, cls).resource_setup()
-        cls.os = clients.Manager()
+    def skip_checks(cls):
+        super(BaseOrchestrationTest, cls).skip_checks()
         if not CONF.service_available.heat:
             raise cls.skipException("Heat support is required")
-        cls.build_timeout = CONF.orchestration.build_timeout
-        cls.build_interval = CONF.orchestration.build_interval
 
+    @classmethod
+    def setup_credentials(cls):
+        super(BaseOrchestrationTest, cls).setup_credentials()
+        cls.os = clients.Manager()
+
+    @classmethod
+    def setup_clients(cls):
+        super(BaseOrchestrationTest, cls).setup_clients()
         cls.orchestration_client = cls.os.orchestration_client
         cls.client = cls.orchestration_client
         cls.servers_client = cls.os.servers_client
@@ -45,6 +50,12 @@
         cls.network_client = cls.os.network_client
         cls.volumes_client = cls.os.volumes_client
         cls.images_v2_client = cls.os.image_client_v2
+
+    @classmethod
+    def resource_setup(cls):
+        super(BaseOrchestrationTest, cls).resource_setup()
+        cls.build_timeout = CONF.orchestration.build_timeout
+        cls.build_interval = CONF.orchestration.build_interval
         cls.stacks = []
         cls.keypairs = []
         cls.images = []
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index deb6b1d..3987ee3 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -30,15 +30,27 @@
 class NeutronResourcesTestJSON(base.BaseOrchestrationTest):
 
     @classmethod
-    def resource_setup(cls):
-        super(NeutronResourcesTestJSON, cls).resource_setup()
+    def skip_checks(cls):
+        super(NeutronResourcesTestJSON, cls).skip_checks()
         if not CONF.orchestration.image_ref:
             raise cls.skipException("No image available to test")
-        os = clients.Manager()
         if not CONF.service_available.neutron:
             raise cls.skipException("Neutron support is required")
+
+    @classmethod
+    def setup_credentials(cls):
+        super(NeutronResourcesTestJSON, cls).setup_credentials()
+        cls.os = clients.Manager()
+
+    @classmethod
+    def setup_clients(cls):
+        super(NeutronResourcesTestJSON, cls).setup_clients()
+        cls.network_client = cls.os.network_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(NeutronResourcesTestJSON, cls).resource_setup()
         cls.neutron_basic_template = cls.load_template('neutron_basic')
-        cls.network_client = os.network_client
         cls.stack_name = data_utils.rand_name('heat')
         template = cls.read_template('neutron_basic')
         cls.keypair_name = (CONF.orchestration.keypair_name or
diff --git a/tempest/api/orchestration/stacks/test_swift_resources.py b/tempest/api/orchestration/stacks/test_swift_resources.py
index 0288fd4..83abc91 100644
--- a/tempest/api/orchestration/stacks/test_swift_resources.py
+++ b/tempest/api/orchestration/stacks/test_swift_resources.py
@@ -26,15 +26,27 @@
 
 class SwiftResourcesTestJSON(base.BaseOrchestrationTest):
     @classmethod
+    def skip_checks(cls):
+        super(SwiftResourcesTestJSON, cls).skip_checks()
+        if not CONF.service_available.swift:
+            raise cls.skipException("Swift support is required")
+
+    @classmethod
+    def setup_credentials(cls):
+        super(SwiftResourcesTestJSON, cls).setup_credentials()
+        cls.os = clients.Manager()
+
+    @classmethod
+    def setup_clients(cls):
+        super(SwiftResourcesTestJSON, cls).setup_clients()
+        cls.account_client = cls.os.account_client
+        cls.container_client = cls.os.container_client
+
+    @classmethod
     def resource_setup(cls):
         super(SwiftResourcesTestJSON, cls).resource_setup()
         cls.stack_name = data_utils.rand_name('heat')
         template = cls.read_template('swift_basic')
-        os = clients.Manager()
-        if not CONF.service_available.swift:
-            raise cls.skipException("Swift support is required")
-        cls.account_client = os.account_client
-        cls.container_client = os.container_client
         # create the stack
         cls.stack_identifier = cls.create_stack(
             cls.stack_name,
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index 322bdf1..8356497 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -27,8 +27,8 @@
 class CinderResourcesTest(base.BaseOrchestrationTest):
 
     @classmethod
-    def resource_setup(cls):
-        super(CinderResourcesTest, cls).resource_setup()
+    def skip_checks(cls):
+        super(CinderResourcesTest, cls).skip_checks()
         if not CONF.service_available.cinder:
             raise cls.skipException('Cinder support is required')
 
diff --git a/tempest/api/telemetry/test_telemetry_alarming_api.py b/tempest/api/telemetry/test_telemetry_alarming_api.py
index 05aed08..cb2d2bd 100644
--- a/tempest/api/telemetry/test_telemetry_alarming_api.py
+++ b/tempest/api/telemetry/test_telemetry_alarming_api.py
@@ -80,12 +80,12 @@
         # Set alarm state and verify
         new_state =\
             [elem for elem in alarm_states if elem != alarm['state']][0]
-        _, state = self.telemetry_client.alarm_set_state(alarm['alarm_id'],
-                                                         new_state)
-        self.assertEqual(new_state, state)
+        state = self.telemetry_client.alarm_set_state(alarm['alarm_id'],
+                                                      new_state)
+        self.assertEqual(new_state, state.data)
         # Get alarm state and verify
-        _, state = self.telemetry_client.alarm_get_state(alarm['alarm_id'])
-        self.assertEqual(new_state, state)
+        state = self.telemetry_client.alarm_get_state(alarm['alarm_id'])
+        self.assertEqual(new_state, state.data)
 
     @test.attr(type="gate")
     def test_create_delete_alarm_with_combination_rule(self):
diff --git a/tempest/api_schema/response/compute/baremetal_nodes.py b/tempest/api_schema/response/compute/baremetal_nodes.py
new file mode 100644
index 0000000..2f67d37
--- /dev/null
+++ b/tempest/api_schema/response/compute/baremetal_nodes.py
@@ -0,0 +1,53 @@
+# Copyright 2015 NEC Corporation.  All rights reserved.
+#
+#    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.
+
+node = {
+    'type': 'object',
+    'properties': {
+        'id': {'type': 'string'},
+        'interfaces': {'type': 'array'},
+        'host': {'type': 'string'},
+        'task_state': {'type': ['string', 'null']},
+        'cpus': {'type': 'integer'},
+        'memory_mb': {'type': 'integer'},
+        'disk_gb': {'type': 'integer'},
+    },
+    'required': ['id', 'interfaces', 'host', 'task_state', 'cpus', 'memory_mb',
+                 'disk_gb']
+}
+
+list_baremetal_nodes = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'nodes': {
+                'type': 'array',
+                'items': node
+            }
+        },
+        'required': ['nodes']
+    }
+}
+
+get_baremetal_node = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'node': node
+        },
+        'required': ['node']
+    }
+}
diff --git a/tempest/api_schema/response/compute/v2/images.py b/tempest/api_schema/response/compute/v2/images.py
index 923c744..2317e6b 100644
--- a/tempest/api_schema/response/compute/v2/images.py
+++ b/tempest/api_schema/response/compute/v2/images.py
@@ -12,15 +12,20 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import copy
+
 from tempest.api_schema.response.compute import parameter_types
 
+image_links = copy.deepcopy(parameter_types.links)
+image_links['items']['properties'].update({'type': {'type': 'string'}})
+
 common_image_schema = {
     'type': 'object',
     'properties': {
         'id': {'type': 'string'},
         'status': {'type': 'string'},
         'updated': {'type': 'string'},
-        'links': parameter_types.links,
+        'links': image_links,
         'name': {'type': 'string'},
         'created': {'type': 'string'},
         'minDisk': {'type': 'integer'},
@@ -67,7 +72,7 @@
                     'type': 'object',
                     'properties': {
                         'id': {'type': 'string'},
-                        'links': parameter_types.links,
+                        'links': image_links,
                         'name': {'type': 'string'}
                     },
                     'required': ['id', 'links', 'name']
diff --git a/tempest/auth.py b/tempest/auth.py
index 7e1928f..ffeae02 100644
--- a/tempest/auth.py
+++ b/tempest/auth.py
@@ -22,13 +22,11 @@
 
 import six
 
-from tempest import config
 from tempest.openstack.common import log as logging
 from tempest.services.identity.json import token_client as json_id
 from tempest.services.identity.v3.json import token_client as json_v3id
 
 
-CONF = config.CONF
 LOG = logging.getLogger(__name__)
 
 
@@ -564,16 +562,6 @@
                   'project_name', 'tenant_id', 'tenant_name', 'user_domain_id',
                   'user_domain_name', 'user_id']
 
-    def __init__(self, **kwargs):
-        """
-        If domain is not specified, load the one configured for the
-        identity manager.
-        """
-        domain_fields = set(x for x in self.ATTRIBUTES if 'domain' in x)
-        if not domain_fields.intersection(kwargs.keys()):
-            kwargs['user_domain_name'] = CONF.identity.admin_domain_name
-        super(KeystoneV3Credentials, self).__init__(**kwargs)
-
     def __setattr__(self, key, value):
         parent = super(KeystoneV3Credentials, self)
         # for tenant_* set both project and tenant
diff --git a/tempest/clients.py b/tempest/clients.py
index 786e05f..096470e 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -29,6 +29,8 @@
     AggregatesClientJSON
 from tempest.services.compute.json.availability_zone_client import \
     AvailabilityZoneClientJSON
+from tempest.services.compute.json.baremetal_nodes_client import \
+    BaremetalNodesClientJSON
 from tempest.services.compute.json.certificates_client import \
     CertificatesClientJSON
 from tempest.services.compute.json.extensions_client import \
@@ -269,6 +271,8 @@
             InstanceUsagesAuditLogClientJSON(self.auth_provider, **params)
         self.tenant_networks_client = \
             TenantNetworksClientJSON(self.auth_provider, **params)
+        self.baremetal_nodes_client = BaremetalNodesClientJSON(
+            self.auth_provider, **params)
 
         # NOTE: The following client needs special timeout values because
         # the API is a proxy for the other component.
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index d22858d..e9b6621 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -232,9 +232,6 @@
         LOG.error("%s not found in USERS: %s" % (name, USERS))
 
 
-def resp_ok(response):
-    return 200 >= int(response['status']) < 300
-
 ###################
 #
 # TENANTS
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 87f5ca6..697965f 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -154,7 +154,7 @@
 
 def verify_extensions(os, service, results):
     extensions_client = get_extension_client(os, service)
-    if service == 'neutron' or service == 'cinder':
+    if service != 'swift':
         resp = extensions_client.list_extensions()
     else:
         __, resp = extensions_client.list_extensions()
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index f40ed7a..d899303 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -70,6 +70,12 @@
 # is none is specified
 def get_credentials(fill_in=True, identity_version=None, **kwargs):
     identity_version = identity_version or CONF.identity.auth_version
+    # In case of "v3" add the domain from config if not specified
+    if identity_version == 'v3':
+        domain_fields = set(x for x in auth.KeystoneV3Credentials.ATTRIBUTES
+                            if 'domain' in x)
+        if not domain_fields.intersection(kwargs.keys()):
+            kwargs['user_domain_name'] = CONF.identity.admin_domain_name
     return auth.get_credentials(fill_in=fill_in,
                                 identity_version=identity_version,
                                 **kwargs)
diff --git a/tempest/services/compute/json/availability_zone_client.py b/tempest/services/compute/json/availability_zone_client.py
index e37c9d9..343c412 100644
--- a/tempest/services/compute/json/availability_zone_client.py
+++ b/tempest/services/compute/json/availability_zone_client.py
@@ -25,11 +25,13 @@
         resp, body = self.get('os-availability-zone')
         body = json.loads(body)
         self.validate_response(schema.get_availability_zone_list, resp, body)
-        return resp, body['availabilityZoneInfo']
+        return service_client.ResponseBodyList(resp,
+                                               body['availabilityZoneInfo'])
 
     def get_availability_zone_list_detail(self):
         resp, body = self.get('os-availability-zone/detail')
         body = json.loads(body)
         self.validate_response(schema.get_availability_zone_list_detail, resp,
                                body)
-        return resp, body['availabilityZoneInfo']
+        return service_client.ResponseBodyList(resp,
+                                               body['availabilityZoneInfo'])
diff --git a/tempest/services/compute/json/baremetal_nodes_client.py b/tempest/services/compute/json/baremetal_nodes_client.py
new file mode 100644
index 0000000..d8bbadd
--- /dev/null
+++ b/tempest/services/compute/json/baremetal_nodes_client.py
@@ -0,0 +1,43 @@
+# Copyright 2015 NEC Corporation.  All rights reserved.
+#
+#    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.
+
+import json
+import urllib
+
+from tempest.api_schema.response.compute import baremetal_nodes as schema
+from tempest.common import service_client
+
+
+class BaremetalNodesClientJSON(service_client.ServiceClient):
+    """
+    Tests Baremetal API
+    """
+
+    def list_baremetal_nodes(self, params=None):
+        """List all baremetal nodes."""
+        url = 'os-baremetal-nodes'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        body = json.loads(body)
+        self.validate_response(schema.list_baremetal_nodes, resp, body)
+        return service_client.ResponseBodyList(resp, body['nodes'])
+
+    def get_baremetal_node(self, baremetal_node_id):
+        """Returns the details of a single baremetal node."""
+        url = 'os-baremetal-nodes/%s' % baremetal_node_id
+        resp, body = self.get(url)
+        body = json.loads(body)
+        self.validate_response(schema.get_baremetal_node, resp, body)
+        return service_client.ResponseBody(resp, body['node'])
diff --git a/tempest/services/compute/json/certificates_client.py b/tempest/services/compute/json/certificates_client.py
index b705c37..4a30f1e 100644
--- a/tempest/services/compute/json/certificates_client.py
+++ b/tempest/services/compute/json/certificates_client.py
@@ -27,7 +27,7 @@
         resp, body = self.get(url)
         body = json.loads(body)
         self.validate_response(schema.get_certificate, resp, body)
-        return resp, body['certificate']
+        return service_client.ResponseBody(resp, body['certificate'])
 
     def create_certificate(self):
         """create certificates."""
@@ -35,4 +35,4 @@
         resp, body = self.post(url, None)
         body = json.loads(body)
         self.validate_response(v2schema.create_certificate, resp, body)
-        return resp, body['certificate']
+        return service_client.ResponseBody(resp, body['certificate'])
diff --git a/tempest/services/compute/json/extensions_client.py b/tempest/services/compute/json/extensions_client.py
index d3148b4..09561b3 100644
--- a/tempest/services/compute/json/extensions_client.py
+++ b/tempest/services/compute/json/extensions_client.py
@@ -26,14 +26,14 @@
         resp, body = self.get(url)
         body = json.loads(body)
         self.validate_response(schema.list_extensions, resp, body)
-        return resp, body['extensions']
+        return service_client.ResponseBodyList(resp, body['extensions'])
 
     def is_enabled(self, extension):
-        _, extensions = self.list_extensions()
+        extensions = self.list_extensions()
         exts = extensions['extensions']
         return any([e for e in exts if e['name'] == extension])
 
     def get_extension(self, extension_alias):
         resp, body = self.get('extensions/%s' % extension_alias)
         body = json.loads(body)
-        return resp, body['extension']
+        return service_client.ResponseBody(resp, body['extension'])
diff --git a/tempest/services/compute/json/instance_usage_audit_log_client.py b/tempest/services/compute/json/instance_usage_audit_log_client.py
index 80d7334..551d751 100644
--- a/tempest/services/compute/json/instance_usage_audit_log_client.py
+++ b/tempest/services/compute/json/instance_usage_audit_log_client.py
@@ -28,11 +28,13 @@
         body = json.loads(body)
         self.validate_response(schema.list_instance_usage_audit_log,
                                resp, body)
-        return resp, body["instance_usage_audit_logs"]
+        return service_client.ResponseBody(resp,
+                                           body["instance_usage_audit_logs"])
 
     def get_instance_usage_audit_log(self, time_before):
         url = 'os-instance_usage_audit_log/%s' % time_before
         resp, body = self.get(url)
         body = json.loads(body)
         self.validate_response(schema.get_instance_usage_audit_log, resp, body)
-        return resp, body["instance_usage_audit_log"]
+        return service_client.ResponseBody(resp,
+                                           body["instance_usage_audit_log"])
diff --git a/tempest/services/compute/json/migrations_client.py b/tempest/services/compute/json/migrations_client.py
index b41abc8..a65b655 100644
--- a/tempest/services/compute/json/migrations_client.py
+++ b/tempest/services/compute/json/migrations_client.py
@@ -31,4 +31,4 @@
         resp, body = self.get(url)
         body = json.loads(body)
         self.validate_response(schema.list_migrations, resp, body)
-        return resp, body['migrations']
+        return service_client.ResponseBodyList(resp, body['migrations'])
diff --git a/tempest/services/compute/json/tenant_usages_client.py b/tempest/services/compute/json/tenant_usages_client.py
index 5dc1d5d..bbc1051 100644
--- a/tempest/services/compute/json/tenant_usages_client.py
+++ b/tempest/services/compute/json/tenant_usages_client.py
@@ -30,7 +30,7 @@
         resp, body = self.get(url)
         body = json.loads(body)
         self.validate_response(schema.list_tenant, resp, body)
-        return resp, body['tenant_usages'][0]
+        return service_client.ResponseBodyList(resp, body['tenant_usages'][0])
 
     def get_tenant_usage(self, tenant_id, params=None):
         url = 'os-simple-tenant-usage/%s' % tenant_id
@@ -40,4 +40,4 @@
         resp, body = self.get(url)
         body = json.loads(body)
         self.validate_response(schema.get_tenant, resp, body)
-        return resp, body['tenant_usage']
+        return service_client.ResponseBodyList(resp, body['tenant_usage'])
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index 0c05118..4ea710f 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -239,8 +239,7 @@
         url = 'v1/images/%s' % image_id
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
-        # We can't return a ResponseBody because the body is a string
-        return resp, body
+        return service_client.ResponseBodyData(resp, body)
 
     def is_resource_deleted(self, id):
         try:
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index 4cddc59..50f273c 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -141,8 +141,7 @@
         url = 'v2/images/%s/file' % image_id
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
-        # We can't return a ResponseBody because the body is a string
-        return resp, body
+        return service_client.ResponseBodyData(resp, body)
 
     def add_image_tag(self, image_id, tag):
         url = 'v2/images/%s/tags/%s' % (image_id, tag)
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index dd899e4..a249625 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -127,7 +127,7 @@
         resp, body = self.get(uri)
         self.expected_success(200, resp.status)
         body = self.deserialize(body)
-        return resp, body
+        return service_client.ResponseBodyData(resp, body)
 
     def alarm_set_state(self, alarm_id, state):
         uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
@@ -135,4 +135,4 @@
         resp, body = self.put(uri, body)
         self.expected_success(200, resp.status)
         body = self.deserialize(body)
-        return resp, body
+        return service_client.ResponseBodyData(resp, body)
diff --git a/tempest/test.py b/tempest/test.py
index 0c9cbfd..d4123a4 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -394,7 +394,7 @@
         return admin_client
 
     @classmethod
-    def set_network_resources(self, network=False, router=False, subnet=False,
+    def set_network_resources(cls, network=False, router=False, subnet=False,
                               dhcp=False):
         """Specify which network resources should be created
 
@@ -407,8 +407,8 @@
         # in order to ensure that even if it's called multiple times in
         # a chain of overloaded methods, the attribute is set only
         # in the leaf class
-        if not self.network_resources:
-            self.network_resources = {
+        if not cls.network_resources:
+            cls.network_resources = {
                 'network': network,
                 'router': router,
                 'subnet': subnet,
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 1abe29a..17e2550 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -282,8 +282,8 @@
 
     def test_verify_extensions_nova(self):
         def fake_list_extensions():
-            return (None, [{'alias': 'fake1'}, {'alias': 'fake2'},
-                           {'alias': 'not_fake'}])
+            return ([{'alias': 'fake1'}, {'alias': 'fake2'},
+                     {'alias': 'not_fake'}])
         fake_os = mock.MagicMock()
         fake_os.extensions_client.list_extensions = fake_list_extensions
         self.useFixture(mockpatch.PatchObject(
@@ -303,9 +303,9 @@
 
     def test_verify_extensions_nova_all(self):
         def fake_list_extensions():
-            return (None, {'extensions': [{'alias': 'fake1'},
-                                          {'alias': 'fake2'},
-                                          {'alias': 'not_fake'}]})
+            return ({'extensions': [{'alias': 'fake1'},
+                                    {'alias': 'fake2'},
+                                    {'alias': 'not_fake'}]})
         fake_os = mock.MagicMock()
         fake_os.extensions_client.list_extensions = fake_list_extensions
         self.useFixture(mockpatch.PatchObject(