Merge "refactor save_state code"
diff --git a/requirements.txt b/requirements.txt
index ebb23c3..b877312 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,16 +12,16 @@
 python-ceilometerclient>=1.0.6
 python-glanceclient>=0.15.0
 python-keystoneclient>=1.1.0
-python-novaclient>=2.18.0
-python-neutronclient>=2.3.6,<3
+python-novaclient>=2.18.0,!=2.21.0
+python-neutronclient>=2.3.11,<3
 python-cinderclient>=1.1.0
-python-heatclient>=0.2.9
+python-heatclient>=0.3.0
 python-ironicclient>=0.2.1
 python-saharaclient>=0.7.6
 python-swiftclient>=2.2.0
 testrepository>=0.0.18
 oslo.config>=1.6.0  # Apache-2.0
-six>=1.7.0
+six>=1.9.0
 iso8601>=0.1.9
 fixtures>=0.3.14
 testscenarios>=0.4
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 48201ec..e73ad1d 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -119,13 +119,10 @@
                        summary=False):
         self.assertIsNotNone(trust['id'])
         self.assertEqual(impersonate, trust['impersonation'])
-        # FIXME(shardy): ref bug #1246383 we can't check the
-        # microsecond component of the expiry time, because mysql
-        # <5.6.4 doesn't support microseconds.
-        # expected format 2013-12-20T16:08:36.036987Z
         if expires is not None:
-            expires_nousec = re.sub(r'\.([0-9]){6}Z', '', expires)
-            self.assertTrue(trust['expires_at'].startswith(expires_nousec))
+            # Omit microseconds of the expiry time
+            trust_expires_at = re.sub(r'\.([0-9]){6}', '', trust['expires_at'])
+            self.assertEqual(expires, trust_expires_at)
         else:
             self.assertIsNone(trust['expires_at'])
         self.assertEqual(self.trustor_user_id, trust['trustor_user_id'])
@@ -219,7 +216,13 @@
         # Test case to check we can create, get and delete a trust
         # with an expiry specified
         expires_at = timeutils.utcnow() + datetime.timedelta(hours=1)
-        expires_str = timeutils.isotime(at=expires_at, subsecond=True)
+        # NOTE(ylobankov) In some cases the expiry time may be rounded up
+        # because of microseconds. For example, we have the following expiry
+        # time for a trust: 2015-02-17T17:34:01.907051Z. However, if we make
+        # a GET request on the trust, the response may contain the time
+        # rounded up to 2015-02-17T17:34:02.000000Z. That is why we should
+        # omit microseconds when creating a trust.
+        expires_str = timeutils.isotime(at=expires_at)
 
         trust = self.create_trust(expires=expires_str)
         self.validate_trust(trust, expires=expires_str)
diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py
index c8dc5e0..eae0707 100644
--- a/tempest/api/messaging/base.py
+++ b/tempest/api/messaging/base.py
@@ -58,114 +58,114 @@
     @classmethod
     def create_queue(cls, queue_name):
         """Wrapper utility that returns a test queue."""
-        body = cls.client.create_queue(queue_name)
-        return body
+        resp, body = cls.client.create_queue(queue_name)
+        return resp, body
 
     @classmethod
     def delete_queue(cls, queue_name):
         """Wrapper utility that deletes a test queue."""
-        body = cls.client.delete_queue(queue_name)
-        return body
+        resp, body = cls.client.delete_queue(queue_name)
+        return resp, body
 
     @classmethod
     def check_queue_exists(cls, queue_name):
         """Wrapper utility that checks the existence of a test queue."""
-        body = cls.client.get_queue(queue_name)
-        return body
+        resp, body = cls.client.get_queue(queue_name)
+        return resp, body
 
     @classmethod
     def check_queue_exists_head(cls, queue_name):
         """Wrapper utility checks the head of a queue via http HEAD."""
-        body = cls.client.head_queue(queue_name)
-        return body
+        resp, body = cls.client.head_queue(queue_name)
+        return resp, body
 
     @classmethod
     def list_queues(cls):
         """Wrapper utility that lists queues."""
-        body = cls.client.list_queues()
-        return body
+        resp, body = cls.client.list_queues()
+        return resp, body
 
     @classmethod
     def get_queue_stats(cls, queue_name):
         """Wrapper utility that returns the queue stats."""
-        body = cls.client.get_queue_stats(queue_name)
-        return body
+        resp, body = cls.client.get_queue_stats(queue_name)
+        return resp, body
 
     @classmethod
     def get_queue_metadata(cls, queue_name):
         """Wrapper utility that gets a queue metadata."""
-        body = cls.client.get_queue_metadata(queue_name)
-        return body
+        resp, body = cls.client.get_queue_metadata(queue_name)
+        return resp, body
 
     @classmethod
     def set_queue_metadata(cls, queue_name, rbody):
         """Wrapper utility that sets the metadata of a queue."""
-        body = cls.client.set_queue_metadata(queue_name, rbody)
-        return body
+        resp, body = cls.client.set_queue_metadata(queue_name, rbody)
+        return resp, body
 
     @classmethod
     def post_messages(cls, queue_name, rbody):
         """Wrapper utility that posts messages to a queue."""
-        body = cls.client.post_messages(queue_name, rbody)
+        resp, body = cls.client.post_messages(queue_name, rbody)
 
-        return body
+        return resp, body
 
     @classmethod
     def list_messages(cls, queue_name):
         """Wrapper utility that lists the messages in a queue."""
-        body = cls.client.list_messages(queue_name)
+        resp, body = cls.client.list_messages(queue_name)
 
-        return body
+        return resp, body
 
     @classmethod
     def get_single_message(cls, message_uri):
         """Wrapper utility that gets a single message."""
-        body = cls.client.get_single_message(message_uri)
+        resp, body = cls.client.get_single_message(message_uri)
 
-        return body
+        return resp, body
 
     @classmethod
     def get_multiple_messages(cls, message_uri):
         """Wrapper utility that gets multiple messages."""
-        body = cls.client.get_multiple_messages(message_uri)
+        resp, body = cls.client.get_multiple_messages(message_uri)
 
-        return body
+        return resp, body
 
     @classmethod
     def delete_messages(cls, message_uri):
         """Wrapper utility that deletes messages."""
-        body = cls.client.delete_messages(message_uri)
+        resp, body = cls.client.delete_messages(message_uri)
 
-        return body
+        return resp, body
 
     @classmethod
     def post_claims(cls, queue_name, rbody, url_params=False):
         """Wrapper utility that claims messages."""
-        body = cls.client.post_claims(
+        resp, body = cls.client.post_claims(
             queue_name, rbody, url_params=False)
 
-        return body
+        return resp, body
 
     @classmethod
     def query_claim(cls, claim_uri):
         """Wrapper utility that gets a claim."""
-        body = cls.client.query_claim(claim_uri)
+        resp, body = cls.client.query_claim(claim_uri)
 
-        return body
+        return resp, body
 
     @classmethod
     def update_claim(cls, claim_uri, rbody):
         """Wrapper utility that updates a claim."""
-        body = cls.client.update_claim(claim_uri, rbody)
+        resp, body = cls.client.update_claim(claim_uri, rbody)
 
-        return body
+        return resp, body
 
     @classmethod
     def release_claim(cls, claim_uri):
         """Wrapper utility that deletes a claim."""
-        body = cls.client.release_claim(claim_uri)
+        resp, body = cls.client.release_claim(claim_uri)
 
-        return body
+        return resp, body
 
     @classmethod
     def generate_message_body(cls, repeat=1):
diff --git a/tempest/api/messaging/test_claims.py b/tempest/api/messaging/test_claims.py
index ef5e4f7..c9064b0 100644
--- a/tempest/api/messaging/test_claims.py
+++ b/tempest/api/messaging/test_claims.py
@@ -49,14 +49,14 @@
         claim_grace = data_utils.\
             rand_int_id(start=60, end=CONF.messaging.max_claim_grace)
         claim_body = {"ttl": claim_ttl, "grace": claim_grace}
-        body = self.client.post_claims(queue_name=self.queue_name,
-                                       rbody=claim_body)
+        resp, body = self.client.post_claims(queue_name=self.queue_name,
+                                             rbody=claim_body)
 
-        return body
+        return resp, body
 
     @test.attr(type='smoke')
     def test_post_claim(self):
-        body = self._post_and_claim_messages(queue_name=self.queue_name)
+        _, body = self._post_and_claim_messages(queue_name=self.queue_name)
         claimed_message_uri = body[0]['href']
 
         # Skipping this step till bug-1331517  is fixed
@@ -70,10 +70,10 @@
     @test.attr(type='smoke')
     def test_query_claim(self):
         # Post a Claim
-        body = self._post_and_claim_messages(queue_name=self.queue_name)
+        resp, body = self._post_and_claim_messages(queue_name=self.queue_name)
 
         # Query Claim
-        claim_uri = body.response['location']
+        claim_uri = resp['location']
         self.client.query_claim(claim_uri)
 
         # Delete Claimed message
@@ -84,9 +84,9 @@
     @test.attr(type='smoke')
     def test_update_claim(self):
         # Post a Claim
-        body = self._post_and_claim_messages(queue_name=self.queue_name)
+        resp, body = self._post_and_claim_messages(queue_name=self.queue_name)
 
-        claim_uri = body.response['location']
+        claim_uri = resp['location']
         claimed_message_uri = body[0]['href']
 
         # Update Claim
@@ -97,7 +97,7 @@
         self.client.update_claim(claim_uri, rbody=update_rbody)
 
         # Verify claim ttl >= updated ttl value
-        body = self.client.query_claim(claim_uri)
+        _, body = self.client.query_claim(claim_uri)
         updated_claim_ttl = body["ttl"]
         self.assertTrue(updated_claim_ttl >= claim_ttl)
 
@@ -107,8 +107,8 @@
     @test.attr(type='smoke')
     def test_release_claim(self):
         # Post a Claim
-        body = self._post_and_claim_messages(queue_name=self.queue_name)
-        claim_uri = body.response['location']
+        resp, body = self._post_and_claim_messages(queue_name=self.queue_name)
+        claim_uri = resp['location']
 
         # Release Claim
         self.client.release_claim(claim_uri)
diff --git a/tempest/api/messaging/test_messages.py b/tempest/api/messaging/test_messages.py
index 2345e9e..dca95fc 100644
--- a/tempest/api/messaging/test_messages.py
+++ b/tempest/api/messaging/test_messages.py
@@ -36,18 +36,18 @@
 
     def _post_messages(self, repeat=CONF.messaging.max_messages_per_page):
         message_body = self.generate_message_body(repeat=repeat)
-        body = self.post_messages(queue_name=self.queue_name,
-                                  rbody=message_body)
-        return body
+        resp, body = self.post_messages(queue_name=self.queue_name,
+                                        rbody=message_body)
+        return resp, body
 
     @test.attr(type='smoke')
     def test_post_messages(self):
         # Post Messages
-        resp = self._post_messages().response
+        resp, _ = self._post_messages()
 
         # Get on the posted messages
         message_uri = resp['location']
-        resp = self.client.get_multiple_messages(message_uri).response
+        resp, _ = self.client.get_multiple_messages(message_uri)
         # The test has an assertion here, because the response cannot be 204
         # in this case (the client allows 200 or 204 for this API call).
         self.assertEqual('200', resp['status'])
@@ -58,7 +58,7 @@
         self._post_messages()
 
         # List Messages
-        resp = self.list_messages(queue_name=self.queue_name).response
+        resp, _ = self.list_messages(queue_name=self.queue_name)
         # The test has an assertion here, because the response cannot be 204
         # in this case (the client allows 200 or 204 for this API call).
         self.assertEqual('200', resp['status'])
@@ -66,11 +66,11 @@
     @test.attr(type='smoke')
     def test_get_message(self):
         # Post Messages
-        body = self._post_messages()
+        _, body = self._post_messages()
         message_uri = body['resources'][0]
 
         # Get posted message
-        resp = self.client.get_single_message(message_uri).response
+        resp, _ = self.client.get_single_message(message_uri)
         # The test has an assertion here, because the response cannot be 204
         # in this case (the client allows 200 or 204 for this API call).
         self.assertEqual('200', resp['status'])
@@ -78,11 +78,11 @@
     @test.attr(type='smoke')
     def test_get_multiple_messages(self):
         # Post Messages
-        resp = self._post_messages().response
+        resp, _ = self._post_messages()
         message_uri = resp['location']
 
         # Get posted messages
-        resp = self.client.get_multiple_messages(message_uri).response
+        resp, _ = self.client.get_multiple_messages(message_uri)
         # The test has an assertion here, because the response cannot be 204
         # in this case (the client allows 200 or 204 for this API call).
         self.assertEqual('200', resp['status'])
@@ -90,14 +90,14 @@
     @test.attr(type='smoke')
     def test_delete_single_message(self):
         # Post Messages
-        body = self._post_messages()
+        _, body = self._post_messages()
         message_uri = body['resources'][0]
 
         # Delete posted message & verify the delete operration
         self.client.delete_messages(message_uri)
 
         message_uri = message_uri.replace('/messages/', '/messages?ids=')
-        resp = self.client.get_multiple_messages(message_uri).response
+        resp, _ = self.client.get_multiple_messages(message_uri)
         # The test has an assertion here, because the response has to be 204
         # in this case (the client allows 200 or 204 for this API call).
         self.assertEqual('204', resp['status'])
@@ -105,12 +105,12 @@
     @test.attr(type='smoke')
     def test_delete_multiple_messages(self):
         # Post Messages
-        resp = self._post_messages().response
+        resp, _ = self._post_messages()
         message_uri = resp['location']
 
         # Delete multiple messages
         self.client.delete_messages(message_uri)
-        resp = self.client.get_multiple_messages(message_uri).response
+        resp, _ = self.client.get_multiple_messages(message_uri)
         # The test has an assertion here, because the response has to be 204
         # in this case (the client allows 200 or 204 for this API call).
         self.assertEqual('204', resp['status'])
diff --git a/tempest/api/messaging/test_queues.py b/tempest/api/messaging/test_queues.py
index a8860f0..24656bf 100644
--- a/tempest/api/messaging/test_queues.py
+++ b/tempest/api/messaging/test_queues.py
@@ -33,7 +33,7 @@
     def test_create_delete_queue(self):
         # Create & Delete Queue
         queue_name = data_utils.rand_name('test-')
-        body = self.create_queue(queue_name)
+        _, body = self.create_queue(queue_name)
 
         self.addCleanup(self.client.delete_queue, queue_name)
         # NOTE(gmann): create_queue returns response status code as 201
@@ -74,7 +74,7 @@
     @test.attr(type='smoke')
     def test_list_queues(self):
         # Listing queues
-        body = self.list_queues()
+        _, body = self.list_queues()
         self.assertEqual(len(body['queues']), len(self.queues))
         for item in body['queues']:
             self.assertIn(item['name'], self.queues)
@@ -85,7 +85,7 @@
         queue_name = self.queues[data_utils.rand_int_id(0,
                                                         len(self.queues) - 1)]
         # Get Queue Stats for a newly created Queue
-        body = self.get_queue_stats(queue_name)
+        _, body = self.get_queue_stats(queue_name)
         msgs = body['messages']
         for element in ('free', 'claimed', 'total'):
             self.assertEqual(0, msgs[element])
@@ -98,7 +98,7 @@
         queue_name = self.queues[data_utils.rand_int_id(0,
                                                         len(self.queues) - 1)]
         # Check the Queue has no metadata
-        body = self.get_queue_metadata(queue_name)
+        _, body = self.get_queue_metadata(queue_name)
         self.assertThat(body, matchers.HasLength(0))
         # Create metadata
         key3 = [0, 1, 2, 3, 4]
@@ -112,7 +112,7 @@
         self.set_queue_metadata(queue_name, req_body)
 
         # Get Queue Metadata
-        body = self.get_queue_metadata(queue_name)
+        _, body = self.get_queue_metadata(queue_name)
         self.assertThat(body, matchers.Equals(req_body))
 
     @classmethod
diff --git a/tempest/api/network/admin/test_floating_ips_admin_actions.py b/tempest/api/network/admin/test_floating_ips_admin_actions.py
index ee3b0bb..e7d4c06 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -15,6 +15,7 @@
 
 from tempest.api.network import base
 from tempest import clients
+from tempest.common.utils import data_utils
 from tempest import config
 from tempest import test
 
@@ -32,6 +33,12 @@
         cls.floating_ip = cls.create_floatingip(cls.ext_net_id)
         cls.alt_manager = clients.Manager(cls.isolated_creds.get_alt_creds())
         cls.alt_client = cls.alt_manager.network_client
+        cls.network = cls.create_network()
+        cls.subnet = cls.create_subnet(cls.network)
+        cls.router = cls.create_router(data_utils.rand_name('router-'),
+                                       external_network_id=cls.ext_net_id)
+        cls.create_router_interface(cls.router['id'], cls.subnet['id'])
+        cls.port = cls.create_port(cls.network)
 
     @test.attr(type='smoke')
     def test_list_floating_ips_from_admin_and_nonadmin(self):
@@ -63,3 +70,39 @@
         self.assertNotIn(floating_ip_admin['floatingip']['id'],
                          floating_ip_ids)
         self.assertNotIn(floating_ip_alt['id'], floating_ip_ids)
+
+    @test.attr(type='smoke')
+    def test_create_list_show_floating_ip_with_tenant_id_by_admin(self):
+        # Creates a floating IP
+        body = self.admin_client.create_floatingip(
+            floating_network_id=self.ext_net_id,
+            tenant_id=self.network['tenant_id'],
+            port_id=self.port['id'])
+        created_floating_ip = body['floatingip']
+        self.addCleanup(self.client.delete_floatingip,
+                        created_floating_ip['id'])
+        self.assertIsNotNone(created_floating_ip['id'])
+        self.assertIsNotNone(created_floating_ip['tenant_id'])
+        self.assertIsNotNone(created_floating_ip['floating_ip_address'])
+        self.assertEqual(created_floating_ip['port_id'], self.port['id'])
+        self.assertEqual(created_floating_ip['floating_network_id'],
+                         self.ext_net_id)
+        port = self.port['fixed_ips']
+        self.assertEqual(created_floating_ip['fixed_ip_address'],
+                         port[0]['ip_address'])
+        # Verifies the details of a floating_ip
+        floating_ip = self.admin_client.show_floatingip(
+            created_floating_ip['id'])
+        shown_floating_ip = floating_ip['floatingip']
+        self.assertEqual(shown_floating_ip['id'], created_floating_ip['id'])
+        self.assertEqual(shown_floating_ip['floating_network_id'],
+                         self.ext_net_id)
+        self.assertEqual(shown_floating_ip['tenant_id'],
+                         self.network['tenant_id'])
+        self.assertEqual(shown_floating_ip['floating_ip_address'],
+                         created_floating_ip['floating_ip_address'])
+        self.assertEqual(shown_floating_ip['port_id'], self.port['id'])
+        # Verify the floating ip exists in the list of all floating_ips
+        floating_ips = self.admin_client.list_floatingips()
+        floatingip_id_list = [f['id'] for f in floating_ips['floatingips']]
+        self.assertIn(created_floating_ip['id'], floatingip_id_list)
diff --git a/tempest/api_schema/response/compute/baremetal_nodes.py b/tempest/api_schema/response/compute/baremetal_nodes.py
index 2f67d37..e82792c 100644
--- a/tempest/api_schema/response/compute/baremetal_nodes.py
+++ b/tempest/api_schema/response/compute/baremetal_nodes.py
@@ -19,9 +19,9 @@
         'interfaces': {'type': 'array'},
         'host': {'type': 'string'},
         'task_state': {'type': ['string', 'null']},
-        'cpus': {'type': 'integer'},
-        'memory_mb': {'type': 'integer'},
-        'disk_gb': {'type': 'integer'},
+        'cpus': {'type': ['integer', 'string']},
+        'memory_mb': {'type': ['integer', 'string']},
+        'disk_gb': {'type': ['integer', 'string']},
     },
     'required': ['id', 'interfaces', 'host', 'task_state', 'cpus', 'memory_mb',
                  'disk_gb']
diff --git a/tempest/api_schema/response/compute/hypervisors.py b/tempest/api_schema/response/compute/hypervisors.py
index e9e1bc9..273b579 100644
--- a/tempest/api_schema/response/compute/hypervisors.py
+++ b/tempest/api_schema/response/compute/hypervisors.py
@@ -160,9 +160,14 @@
                 'items': {
                     'type': 'object',
                     'properties': {
+                        'status': {'type': 'string'},
+                        'state': {'type': 'string'},
                         'id': {'type': ['integer', 'string']},
                         'hypervisor_hostname': {'type': 'string'}
                     },
+                    # NOTE: When loading os-hypervisor-status extension,
+                    # a response contains status and state. So these params
+                    # should not be required.
                     'required': ['id', 'hypervisor_hostname']
                 }
             }
diff --git a/tempest/api_schema/response/compute/quotas.py b/tempest/api_schema/response/compute/quotas.py
index f49771e..863104c 100644
--- a/tempest/api_schema/response/compute/quotas.py
+++ b/tempest/api_schema/response/compute/quotas.py
@@ -28,8 +28,13 @@
                     'metadata_items': {'type': 'integer'},
                     'key_pairs': {'type': 'integer'},
                     'security_groups': {'type': 'integer'},
-                    'security_group_rules': {'type': 'integer'}
+                    'security_group_rules': {'type': 'integer'},
+                    'server_group_members': {'type': 'integer'},
+                    'server_groups': {'type': 'integer'},
                 },
+                # NOTE: server_group_members and server_groups are represented
+                # when enabling quota_server_group extension. So they should
+                # not be required.
                 'required': ['instances', 'cores', 'ram',
                              'floating_ips', 'fixed_ips',
                              'metadata_items', 'key_pairs',
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index dd8d498..9ecf596 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -100,7 +100,7 @@
         hash_path = os.path.join(self.accounts_dir, hash_string)
         if not os.path.isfile(hash_path):
             LOG.warning('Expected an account lock file %s to remove, but '
-                        'one did not exist')
+                        'one did not exist' % hash_path)
         else:
             os.remove(hash_path)
             if not os.listdir(self.accounts_dir):
diff --git a/tempest/common/service_client.py b/tempest/common/service_client.py
index 8949609..fde05af 100644
--- a/tempest/common/service_client.py
+++ b/tempest/common/service_client.py
@@ -79,7 +79,7 @@
         self.response = response
 
     def __str__(self):
-        body = super.__str__(self)
+        body = super(ResponseBody, self).__str__()
         return "response: %s\nBody: %s" % (self.response, body)
 
 
@@ -108,5 +108,5 @@
         self.response = response
 
     def __str__(self):
-        body = super.__str__(self)
+        body = super(ResponseBodyList, self).__str__()
         return "response: %s\nBody: %s" % (self.response, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 2af96c7..968c8ca 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -909,6 +909,11 @@
             dict(
                 # ping
                 protocol='icmp',
+            ),
+            dict(
+                # ipv6-icmp for ping6
+                protocol='icmp',
+                ethertype='IPv6',
             )
         ]
         for ruleset in rulesets:
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 7f01182..132afda 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -17,7 +17,6 @@
 import re
 
 import testtools
-from testtools.tests import matchers
 
 from tempest.common.utils import data_utils
 from tempest import config
@@ -432,16 +431,6 @@
             should_connect=True, msg="after updating "
             "admin_state_up of router to True")
 
-    def _check_dns_server(self, ssh_client, dns_servers):
-        servers = ssh_client.get_dns_servers()
-        self.assertEqual(set(dns_servers), set(servers),
-                         'Looking for servers: {trgt_serv}. '
-                         'Retrieved DNS nameservers: {act_serv} '
-                         'From host: {host}.'
-                         .format(host=ssh_client.ssh_client.host,
-                                 act_serv=servers,
-                                 trgt_serv=dns_servers))
-
     @testtools.skipUnless(CONF.scenario.dhcp_client,
                           "DHCP client is not available.")
     @test.attr(type='smoke')
@@ -486,7 +475,15 @@
         private_key = self._get_server_key(server)
         ssh_client = self._ssh_to_server(ip_address, private_key)
 
-        self._check_dns_server(ssh_client, [initial_dns_server])
+        dns_servers = [initial_dns_server]
+        servers = ssh_client.get_dns_servers()
+        self.assertEqual(set(dns_servers), set(servers),
+                         'Looking for servers: {trgt_serv}. '
+                         'Retrieved DNS nameservers: {act_serv} '
+                         'From host: {host}.'
+                         .format(host=ssh_client.ssh_client.host,
+                                 act_serv=servers,
+                                 trgt_serv=dns_servers))
 
         self.subnet.update(dns_nameservers=[alt_dns_server])
         # asserts that Neutron DB has updated the nameservers
@@ -501,9 +498,7 @@
             subnet-update API call returns.
             """
             ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
-            try:
-                self._check_dns_server(ssh_client, [alt_dns_server])
-            except matchers.MismatchError:
+            if ssh_client.get_dns_servers() != [alt_dns_server]:
                 LOG.debug("Failed to update DNS nameservers")
                 return False
             return True
diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_swift_telemetry_middleware.py
index dce6023..dd6d855 100644
--- a/tempest/scenario/test_swift_telemetry_middleware.py
+++ b/tempest/scenario/test_swift_telemetry_middleware.py
@@ -76,19 +76,22 @@
             LOG.debug('got samples %s', results)
 
             # Extract container info from samples.
-            containers = [sample['resource_metadata']['container']
-                          for sample in results
-                          if sample['resource_metadata']['container']
-                          != 'None']
-            # Extract object info from samples.
-            objects = [sample['resource_metadata']['object']
-                       for sample in results
-                       if sample['resource_metadata']['object'] != 'None']
+            containers, objects = [], []
+            for sample in results:
+                meta = sample['resource_metadata']
+                if meta.get('container') and meta['container'] != 'None':
+                    containers.append(meta['container'])
+                elif (meta.get('target') and
+                      meta['target']['metadata']['container'] != 'None'):
+                    containers.append(meta['target']['metadata']['container'])
 
-            return (containers
-                    and objects
-                    and container_name in containers
-                    and obj_name in objects)
+                if meta.get('object') and meta['object'] != 'None':
+                    objects.append(meta['object'])
+                elif (meta.get('target') and
+                      meta['target']['metadata']['object'] != 'None'):
+                    objects.append(meta['target']['metadata']['object'])
+
+            return (container_name in containers and obj_name in objects)
 
         self.assertTrue(test.call_until_true(_check_samples,
                                              NOTIFICATIONS_WAIT,
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index 50d0779..1cbdb0c 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -39,7 +39,7 @@
         # FIXME(andreaf) replace credentials and auth_url with auth_provider
 
         insecure_ssl = CONF.identity.disable_ssl_certificate_validation
-        ca_cert = CONF.identity.ca_certificates_file
+        self.ca_cert = CONF.identity.ca_certificates_file
 
         self.connection_timeout = str(CONF.boto.http_socket_timeout)
         self.num_retries = str(CONF.boto.num_retries)
@@ -49,7 +49,7 @@
                         "auth_url": auth_url,
                         "tenant_name": tenant_name,
                         "insecure": insecure_ssl,
-                        "cacert": ca_cert}
+                        "cacert": self.ca_cert}
 
     def _keystone_aws_get(self):
         # FIXME(andreaf) Move EC2 credentials to AuthProvider
@@ -77,6 +77,16 @@
         boto.config.set("Boto", "http_socket_timeout", timeout)
         boto.config.set("Boto", "num_retries", retries)
 
+    def _config_boto_ca_certificates_file(self, ca_cert):
+        if ca_cert is None:
+            return
+
+        try:
+            boto.config.add_section("Boto")
+        except ConfigParser.DuplicateSectionError:
+            pass
+        boto.config.set("Boto", "ca_certificates_file", ca_cert)
+
     def __getattr__(self, name):
         """Automatically creates methods for the allowed methods set."""
         if name in self.ALLOWED_METHODS:
@@ -94,6 +104,7 @@
 
     def get_connection(self):
         self._config_boto_timeout(self.connection_timeout, self.num_retries)
+        self._config_boto_ca_certificates_file(self.ca_cert)
         if not all((self.connection_data["aws_access_key_id"],
                    self.connection_data["aws_secret_access_key"])):
             if all([self.ks_cred.get('auth_url'),
diff --git a/tempest/services/messaging/json/messaging_client.py b/tempest/services/messaging/json/messaging_client.py
index 89aa87b..36444a9 100644
--- a/tempest/services/messaging/json/messaging_client.py
+++ b/tempest/services/messaging/json/messaging_client.py
@@ -50,51 +50,51 @@
         if resp['status'] != '204':
             body = json.loads(body)
             self.validate_response(queues_schema.list_queues, resp, body)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def create_queue(self, queue_name):
         uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
         resp, body = self.put(uri, body=None)
         self.expected_success(201, resp.status)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def get_queue(self, queue_name):
         uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
         resp, body = self.get(uri)
         self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def head_queue(self, queue_name):
         uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
         resp, body = self.head(uri)
         self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def delete_queue(self, queue_name):
         uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
         resp, body = self.delete(uri)
         self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def get_queue_stats(self, queue_name):
         uri = '{0}/queues/{1}/stats'.format(self.uri_prefix, queue_name)
         resp, body = self.get(uri)
         body = json.loads(body)
         self.validate_response(queues_schema.queue_stats, resp, body)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def get_queue_metadata(self, queue_name):
         uri = '{0}/queues/{1}/metadata'.format(self.uri_prefix, queue_name)
         resp, body = self.get(uri)
         self.expected_success(200, resp.status)
         body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def set_queue_metadata(self, queue_name, rbody):
         uri = '{0}/queues/{1}/metadata'.format(self.uri_prefix, queue_name)
         resp, body = self.put(uri, body=json.dumps(rbody))
         self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def post_messages(self, queue_name, rbody):
         uri = '{0}/queues/{1}/messages'.format(self.uri_prefix, queue_name)
@@ -104,7 +104,7 @@
 
         body = json.loads(body)
         self.validate_response(queues_schema.post_messages, resp, body)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def list_messages(self, queue_name):
         uri = '{0}/queues/{1}/messages?echo=True'.format(self.uri_prefix,
@@ -115,7 +115,7 @@
             body = json.loads(body)
             self.validate_response(queues_schema.list_messages, resp, body)
 
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def get_single_message(self, message_uri):
         resp, body = self.get(message_uri, extra_headers=True,
@@ -124,7 +124,7 @@
             body = json.loads(body)
             self.validate_response(queues_schema.get_single_message, resp,
                                    body)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def get_multiple_messages(self, message_uri):
         resp, body = self.get(message_uri, extra_headers=True,
@@ -136,12 +136,12 @@
                                    resp,
                                    body)
 
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def delete_messages(self, message_uri):
         resp, body = self.delete(message_uri)
         self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def post_claims(self, queue_name, rbody, url_params=False):
         uri = '{0}/queues/{1}/claims'.format(self.uri_prefix, queue_name)
@@ -154,7 +154,7 @@
 
         body = json.loads(body)
         self.validate_response(queues_schema.claim_messages, resp, body)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def query_claim(self, claim_uri):
         resp, body = self.get(claim_uri)
@@ -162,14 +162,14 @@
         if resp['status'] != '204':
             body = json.loads(body)
             self.validate_response(queues_schema.query_claim, resp, body)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def update_claim(self, claim_uri, rbody):
         resp, body = self.patch(claim_uri, body=json.dumps(rbody))
         self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
+        return resp, body
 
     def release_claim(self, claim_uri):
         resp, body = self.delete(claim_uri)
         self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
+        return resp, body