Merge "Add README section about API stability"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 37d4d53..9051310 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -327,6 +327,11 @@
 # (integer value)
 #shelved_offload_time=0
 
+# Unallocated floating IP range, which will be used to test
+# the floating IP bulk feature for CRUD operation. (string
+# value)
+#floating_ip_range=10.0.0.0/29
+
 # Allows test cases to create/destroy tenants and users. This
 # option enables isolated test cases and better parallel
 # execution, but also requires that OpenStack Identity API
@@ -366,17 +371,19 @@
 #
 
 # If false, skip all nova v3 tests. (boolean value)
-#api_v3=true
+#api_v3=false
 
 # If false, skip disk config tests (boolean value)
 #disk_config=true
 
 # A list of enabled compute extensions with a special entry
-# all which indicates every extension is enabled (list value)
+# all which indicates every extension is enabled. Each
+# extension should be specified with alias name (list value)
 #api_extensions=all
 
 # A list of enabled v3 extensions with a special entry all
-# which indicates every extension is enabled (list value)
+# which indicates every extension is enabled. Each extension
+# should be specified with alias name (list value)
 #api_v3_extensions=all
 
 # Does the test environment support changing the admin
@@ -711,6 +718,10 @@
 # (integer value)
 #build_interval=1
 
+# List of dns servers whichs hould be used for subnet creation
+# (list value)
+#dns_servers=8.8.8.8,8.8.4.4
+
 
 [network-feature-enabled]
 
@@ -976,6 +987,10 @@
 # value)
 #endpoint_type=publicURL
 
+# This variable is used as flag to enable notification tests
+# (boolean value)
+#too_slow_to_test=true
+
 
 [volume]
 
diff --git a/openstack-common.conf b/openstack-common.conf
index 38d58ee..a9a6b0b 100644
--- a/openstack-common.conf
+++ b/openstack-common.conf
@@ -7,6 +7,7 @@
 module=log
 module=importlib
 module=fixture
+module=versionutils
 
 # The base module to hold the copy of openstack.common
 base=tempest
diff --git a/requirements.txt b/requirements.txt
index f907e7d..ab2903a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,7 +8,7 @@
 paramiko>=1.13.0
 netaddr>=0.7.6
 python-glanceclient>=0.9.0
-python-keystoneclient>=0.8.0
+python-keystoneclient>=0.9.0
 python-novaclient>=2.17.0
 python-neutronclient>=2.3.4,<3
 python-cinderclient>=1.0.6
@@ -18,8 +18,8 @@
 python-swiftclient>=2.0.2
 testresources>=0.2.4
 testrepository>=0.0.18
-oslo.config>=1.2.0
-six>=1.6.0
+oslo.config>=1.2.1
+six>=1.7.0
 iso8601>=0.1.9
 fixtures>=0.3.14
 testscenarios>=0.4
diff --git a/setup.cfg b/setup.cfg
index 339da12..5c62710 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -21,6 +21,7 @@
 console_scripts =
     verify-tempest-config = tempest.cmd.verify_tempest_config:main
     javelin2 = tempest.cmd.javelin:main
+    run-tempest-stress = tempest.cmd.run_stress:main
 
 [build_sphinx]
 all_files = 1
diff --git a/tempest/api/baremetal/base.py b/tempest/api/baremetal/base.py
index 021adaf..6f7e438 100644
--- a/tempest/api/baremetal/base.py
+++ b/tempest/api/baremetal/base.py
@@ -27,13 +27,12 @@
     def decorator(f):
         @functools.wraps(f)
         def wrapper(cls, *args, **kwargs):
-            result = f(cls, *args, **kwargs)
-            body = result[resource]
+            resp, body = f(cls, *args, **kwargs)
 
             if 'uuid' in body:
                 cls.created_objects[resource].add(body['uuid'])
 
-            return result
+            return resp, body
         return wrapper
     return decorator
 
@@ -51,7 +50,7 @@
 
         mgr = clients.AdminManager()
         cls.client = mgr.baremetal_client
-
+        cls.power_timeout = CONF.baremetal.power_timeout
         cls.created_objects = {'chassis': set(),
                                'port': set(),
                                'node': set()}
@@ -81,8 +80,7 @@
         """
         description = description or data_utils.rand_name('test-chassis-')
         resp, body = cls.client.create_chassis(description=description)
-
-        return {'chassis': body, 'response': resp}
+        return resp, body
 
     @classmethod
     @creates('node')
@@ -102,7 +100,7 @@
                                             cpu_num=cpu_num, storage=storage,
                                             memory=memory, driver=driver)
 
-        return {'node': body, 'response': resp}
+        return resp, body
 
     @classmethod
     @creates('port')
@@ -121,7 +119,7 @@
         resp, body = cls.client.create_port(address=address, node_id=node_id,
                                             extra=extra, uuid=uuid)
 
-        return {'port': body, 'response': resp}
+        return resp, body
 
     @classmethod
     def delete_chassis(cls, chassis_id):
diff --git a/tempest/api/baremetal/test_api_discovery.py b/tempest/api/baremetal/test_api_discovery.py
index e594b3e..bee10b9 100644
--- a/tempest/api/baremetal/test_api_discovery.py
+++ b/tempest/api/baremetal/test_api_discovery.py
@@ -20,6 +20,7 @@
     @test.attr(type='smoke')
     def test_api_versions(self):
         resp, descr = self.client.get_api_description()
+        self.assertEqual('200', resp['status'])
         expected_versions = ('v1',)
 
         versions = [version['id'] for version in descr['versions']]
@@ -30,6 +31,7 @@
     @test.attr(type='smoke')
     def test_default_version(self):
         resp, descr = self.client.get_api_description()
+        self.assertEqual('200', resp['status'])
         default_version = descr['default_version']
 
         self.assertEqual(default_version['id'], 'v1')
@@ -37,6 +39,7 @@
     @test.attr(type='smoke')
     def test_version_1_resources(self):
         resp, descr = self.client.get_version_description(version='v1')
+        self.assertEqual('200', resp['status'])
         expected_resources = ('nodes', 'chassis',
                               'ports', 'links', 'media_types')
 
diff --git a/tempest/api/baremetal/test_chassis.py b/tempest/api/baremetal/test_chassis.py
index 7af1336..4ab86c2 100644
--- a/tempest/api/baremetal/test_chassis.py
+++ b/tempest/api/baremetal/test_chassis.py
@@ -20,57 +20,64 @@
 class TestChassis(base.BaseBaremetalTest):
     """Tests for chassis."""
 
+    @classmethod
+    def setUpClass(cls):
+        super(TestChassis, cls).setUpClass()
+        _, cls.chassis = cls.create_chassis()
+
+    def _assertExpected(self, expected, actual):
+        # Check if not expected keys/values exists in actual response body
+        for key, value in expected.iteritems():
+            if key not in ('created_at', 'updated_at'):
+                self.assertIn(key, actual)
+                self.assertEqual(value, actual[key])
+
     @test.attr(type='smoke')
     def test_create_chassis(self):
         descr = data_utils.rand_name('test-chassis-')
-        ch = self.create_chassis(description=descr)['chassis']
-
-        self.assertEqual(ch['description'], descr)
+        resp, chassis = self.create_chassis(description=descr)
+        self.assertEqual('201', resp['status'])
+        self.assertEqual(chassis['description'], descr)
 
     @test.attr(type='smoke')
     def test_create_chassis_unicode_description(self):
         # Use a unicode string for testing:
         # 'We ♡ OpenStack in Ukraine'
         descr = u'В Україні ♡ OpenStack!'
-        ch = self.create_chassis(description=descr)['chassis']
-
-        self.assertEqual(ch['description'], descr)
+        resp, chassis = self.create_chassis(description=descr)
+        self.assertEqual('201', resp['status'])
+        self.assertEqual(chassis['description'], descr)
 
     @test.attr(type='smoke')
     def test_show_chassis(self):
-        descr = data_utils.rand_name('test-chassis-')
-        uuid = self.create_chassis(description=descr)['chassis']['uuid']
-
-        resp, chassis = self.client.show_chassis(uuid)
-
-        self.assertEqual(chassis['uuid'], uuid)
-        self.assertEqual(chassis['description'], descr)
+        resp, chassis = self.client.show_chassis(self.chassis['uuid'])
+        self.assertEqual('200', resp['status'])
+        self._assertExpected(self.chassis, chassis)
 
     @test.attr(type="smoke")
     def test_list_chassis(self):
-        created_ids = [self.create_chassis()['chassis']['uuid']
-                       for i in range(0, 5)]
-
         resp, body = self.client.list_chassis()
-        loaded_ids = [ch['uuid'] for ch in body['chassis']]
-
-        for i in created_ids:
-            self.assertIn(i, loaded_ids)
+        self.assertEqual('200', resp['status'])
+        self.assertIn(self.chassis['uuid'],
+                      [i['uuid'] for i in body['chassis']])
 
     @test.attr(type='smoke')
     def test_delete_chassis(self):
-        uuid = self.create_chassis()['chassis']['uuid']
+        resp, body = self.create_chassis()
+        uuid = body['uuid']
 
-        self.delete_chassis(uuid)
-
+        resp = self.delete_chassis(uuid)
+        self.assertEqual('204', resp['status'])
         self.assertRaises(exc.NotFound, self.client.show_chassis, uuid)
 
     @test.attr(type='smoke')
     def test_update_chassis(self):
-        chassis_id = self.create_chassis()['chassis']['uuid']
+        resp, body = self.create_chassis()
+        uuid = body['uuid']
 
         new_description = data_utils.rand_name('new-description-')
-        self.client.update_chassis(chassis_id, description=new_description)
-
-        resp, chassis = self.client.show_chassis(chassis_id)
+        resp, body = (self.client.update_chassis(uuid,
+                      description=new_description))
+        self.assertEqual('200', resp['status'])
+        resp, chassis = self.client.show_chassis(uuid)
         self.assertEqual(chassis['description'], new_description)
diff --git a/tempest/api/baremetal/test_nodes.py b/tempest/api/baremetal/test_nodes.py
index 0f585cb..b6432ad 100644
--- a/tempest/api/baremetal/test_nodes.py
+++ b/tempest/api/baremetal/test_nodes.py
@@ -23,7 +23,15 @@
     def setUp(self):
         super(TestNodes, self).setUp()
 
-        self.chassis = self.create_chassis()['chassis']
+        _, self.chassis = self.create_chassis()
+        _, self.node = self.create_node(self.chassis['uuid'])
+
+    def _assertExpected(self, expected, actual):
+        # Check if not expected keys/values exists in actual response body
+        for key, value in six.iteritems(expected):
+            if key not in ('created_at', 'updated_at'):
+                self.assertIn(key, actual)
+                self.assertEqual(value, actual[key])
 
     @test.attr(type='smoke')
     def test_create_node(self):
@@ -32,45 +40,32 @@
                   'storage': '10240',
                   'memory': '1024'}
 
-        node = self.create_node(self.chassis['uuid'], **params)['node']
-
-        for key in params:
-            self.assertEqual(node['properties'][key], params[key])
+        resp, body = self.create_node(self.chassis['uuid'], **params)
+        self.assertEqual('201', resp['status'])
+        self._assertExpected(params, body['properties'])
 
     @test.attr(type='smoke')
     def test_delete_node(self):
-        node = self.create_node(self.chassis['uuid'])['node']
-        node_id = node['uuid']
+        resp, node = self.create_node(self.chassis['uuid'])
+        self.assertEqual('201', resp['status'])
 
-        resp = self.delete_node(node_id)
+        resp = self.delete_node(node['uuid'])
 
         self.assertEqual(resp['status'], '204')
-        self.assertRaises(exc.NotFound, self.client.show_node, node_id)
+        self.assertRaises(exc.NotFound, self.client.show_node, node['uuid'])
 
     @test.attr(type='smoke')
     def test_show_node(self):
-        params = {'cpu_arch': 'x86_64',
-                  'cpu_num': '4',
-                  'storage': '100',
-                  'memory': '512'}
-
-        created_node = self.create_node(self.chassis['uuid'], **params)['node']
-        resp, loaded_node = self.client.show_node(created_node['uuid'])
-
-        for key, val in created_node.iteritems():
-            if key not in ('created_at', 'updated_at'):
-                self.assertEqual(loaded_node[key], val)
+        resp, loaded_node = self.client.show_node(self.node['uuid'])
+        self.assertEqual('200', resp['status'])
+        self._assertExpected(self.node, loaded_node)
 
     @test.attr(type='smoke')
     def test_list_nodes(self):
-        uuids = [self.create_node(self.chassis['uuid'])['node']['uuid']
-                 for i in range(0, 5)]
-
         resp, body = self.client.list_nodes()
-        loaded_uuids = [n['uuid'] for n in body['nodes']]
-
-        for u in uuids:
-            self.assertIn(u, loaded_uuids)
+        self.assertEqual('200', resp['status'])
+        self.assertIn(self.node['uuid'],
+                      [i['uuid'] for i in body['nodes']])
 
     @test.attr(type='smoke')
     def test_update_node(self):
@@ -79,17 +74,16 @@
                  'storage': '10',
                  'memory': '128'}
 
-        node = self.create_node(self.chassis['uuid'], **props)['node']
-        node_id = node['uuid']
+        resp, node = self.create_node(self.chassis['uuid'], **props)
+        self.assertEqual('201', resp['status'])
 
-        new_props = {'cpu_arch': 'x86',
-                     'cpu_num': '1',
-                     'storage': '10000',
-                     'memory': '12300'}
+        new_p = {'cpu_arch': 'x86',
+                 'cpu_num': '1',
+                 'storage': '10000',
+                 'memory': '12300'}
 
-        self.client.update_node(node_id, properties=new_props)
-        resp, node = self.client.show_node(node_id)
-
-        for name, value in six.iteritems(new_props):
-            if name not in ('created_at', 'updated_at'):
-                self.assertEqual(node['properties'][name], value)
+        resp, body = self.client.update_node(node['uuid'], properties=new_p)
+        self.assertEqual('200', resp['status'])
+        resp, node = self.client.show_node(node['uuid'])
+        self.assertEqual('200', resp['status'])
+        self._assertExpected(new_p, node['properties'])
diff --git a/tempest/api/baremetal/test_nodestates.py b/tempest/api/baremetal/test_nodestates.py
index c658d7f..3044bc6 100644
--- a/tempest/api/baremetal/test_nodestates.py
+++ b/tempest/api/baremetal/test_nodestates.py
@@ -13,6 +13,8 @@
 #    under the License.
 
 from tempest.api.baremetal import base
+from tempest import exceptions
+from tempest.openstack.common import timeutils
 from tempest import test
 
 
@@ -20,10 +22,25 @@
     """Tests for baremetal NodeStates."""
 
     @classmethod
-    def setUpClass(self):
-        super(TestNodeStates, self).setUpClass()
-        chassis = self.create_chassis()['chassis']
-        self.node = self.create_node(chassis['uuid'])['node']
+    def setUpClass(cls):
+        super(TestNodeStates, cls).setUpClass()
+        resp, cls.chassis = cls.create_chassis()
+        resp, cls.node = cls.create_node(cls.chassis['uuid'])
+
+    def _validate_power_state(self, node_uuid, power_state):
+        # Validate that power state is set within timeout
+        if power_state == 'rebooting':
+            power_state = 'power on'
+        start = timeutils.utcnow()
+        while timeutils.delta_seconds(
+                start, timeutils.utcnow()) < self.power_timeout:
+            resp, node = self.client.show_node(node_uuid)
+            self.assertEqual(200, resp.status)
+            if node['power_state'] == power_state:
+                return
+        message = ('Failed to set power state within '
+                   'the required time: %s sec.' % self.power_timeout)
+        raise exceptions.TimeoutException(message)
 
     @test.attr(type='smoke')
     def test_list_nodestates(self):
@@ -31,3 +48,16 @@
         self.assertEqual('200', resp['status'])
         for key in nodestates:
             self.assertEqual(nodestates[key], self.node[key])
+
+    @test.attr(type='smoke')
+    def test_set_node_power_state(self):
+        resp, node = self.create_node(self.chassis['uuid'])
+        self.assertEqual('201', resp['status'])
+        states = ["power on", "rebooting", "power off"]
+        for state in states:
+            # Set power state
+            resp, _ = self.client.set_node_power_state(node['uuid'],
+                                                       state)
+            self.assertEqual('202', resp['status'])
+            # Check power state after state is set
+            self._validate_power_state(node['uuid'], state)
diff --git a/tempest/api/baremetal/test_ports.py b/tempest/api/baremetal/test_ports.py
index 8b76811..c2af29a 100644
--- a/tempest/api/baremetal/test_ports.py
+++ b/tempest/api/baremetal/test_ports.py
@@ -22,25 +22,30 @@
     def setUp(self):
         super(TestPorts, self).setUp()
 
-        chassis = self.create_chassis()['chassis']
-        self.node = self.create_node(chassis['uuid'])['node']
+        _, self.chassis = self.create_chassis()
+        _, self.node = self.create_node(self.chassis['uuid'])
+        _, self.port = self.create_port(self.node['uuid'],
+                                        data_utils.rand_mac_address())
+
+    def _assertExpected(self, expected, actual):
+        # Check if not expected keys/values exists in actual response body
+        for key, value in expected.iteritems():
+            if key not in ('created_at', 'updated_at'):
+                self.assertIn(key, actual)
+                self.assertEqual(value, actual[key])
 
     @test.attr(type='smoke')
     def test_create_port(self):
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        result = self.create_port(node_id=node_id, address=address)
-
-        port = result['port']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual(201, resp.status)
 
         resp, body = self.client.show_port(port['uuid'])
 
         self.assertEqual(200, resp.status)
-        self.assertEqual(port['uuid'], body['uuid'])
-        self.assertEqual(address, body['address'])
-        self.assertEqual({}, body['extra'])
-        self.assertEqual(node_id, body['node_uuid'])
+        self._assertExpected(port, body)
 
     @test.attr(type='smoke')
     def test_create_port_specifying_uuid(self):
@@ -48,15 +53,13 @@
         address = data_utils.rand_mac_address()
         uuid = data_utils.rand_uuid()
 
-        self.create_port(node_id=node_id, address=address, uuid=uuid)
+        resp, port = self.create_port(node_id=node_id,
+                                      address=address, uuid=uuid)
+        self.assertEqual(201, resp.status)
 
         resp, body = self.client.show_port(uuid)
-
         self.assertEqual(200, resp.status)
-        self.assertEqual(uuid, body['uuid'])
-        self.assertEqual(address, body['address'])
-        self.assertEqual({}, body['extra'])
-        self.assertEqual(node_id, body['node_uuid'])
+        self._assertExpected(port, body)
 
     @test.attr(type='smoke')
     def test_create_port_with_extra(self):
@@ -64,76 +67,46 @@
         address = data_utils.rand_mac_address()
         extra = {'key': 'value'}
 
-        result = self.create_port(node_id=node_id, address=address,
-                                  extra=extra)
-        port = result['port']
+        resp, port = self.create_port(node_id=node_id, address=address,
+                                      extra=extra)
+        self.assertEqual(201, resp.status)
 
         resp, body = self.client.show_port(port['uuid'])
-
         self.assertEqual(200, resp.status)
-        self.assertEqual(port['uuid'], body['uuid'])
-        self.assertEqual(address, body['address'])
-        self.assertEqual(extra, body['extra'])
-        self.assertEqual(node_id, body['node_uuid'])
+        self._assertExpected(port, body)
 
     @test.attr(type='smoke')
     def test_delete_port(self):
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual(201, resp.status)
 
-        resp = self.delete_port(port_id)
+        resp = self.delete_port(port['uuid'])
 
         self.assertEqual(204, resp.status)
-        self.assertRaises(exc.NotFound, self.client.show_port, port_id)
+        self.assertRaises(exc.NotFound, self.client.show_port, port['uuid'])
 
     @test.attr(type='smoke')
     def test_show_port(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key': 'value'}
-
-        port_id = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)['port']['uuid']
-
-        resp, port = self.client.show_port(port_id)
-
+        resp, port = self.client.show_port(self.port['uuid'])
         self.assertEqual(200, resp.status)
-        self.assertEqual(port_id, port['uuid'])
-        self.assertEqual(address, port['address'])
-        self.assertEqual(extra, port['extra'])
+        self._assertExpected(self.port, port)
 
     @test.attr(type='smoke')
     def test_show_port_with_links(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
-
-        resp, body = self.client.show_port(port_id)
-
+        resp, port = self.client.show_port(self.port['uuid'])
         self.assertEqual(200, resp.status)
-        self.assertIn('links', body.keys())
-        self.assertEqual(2, len(body['links']))
-        self.assertIn(port_id, body['links'][0]['href'])
+        self.assertIn('links', port.keys())
+        self.assertEqual(2, len(port['links']))
+        self.assertIn(port['uuid'], port['links'][0]['href'])
 
     @test.attr(type='smoke')
     def test_list_ports(self):
-        node_id = self.node['uuid']
-
-        uuids = [self.create_port(node_id=node_id,
-                                  address=data_utils.rand_mac_address())
-                 ['port']['uuid'] for i in xrange(5)]
-
         resp, body = self.client.list_ports()
         self.assertEqual(200, resp.status)
-        loaded_uuids = [p['uuid'] for p in body['ports']]
-
-        for uuid in uuids:
-            self.assertIn(uuid, loaded_uuids)
-
+        self.assertIn(self.port['uuid'],
+                      [i['uuid'] for i in body['ports']])
         # Verify self links.
         for port in body['ports']:
             self.validate_self_link('ports', port['uuid'],
@@ -141,15 +114,8 @@
 
     @test.attr(type='smoke')
     def test_list_with_limit(self):
-        node_id = self.node['uuid']
-
-        for i in xrange(5):
-            self.create_port(node_id=node_id,
-                             address=data_utils.rand_mac_address())
-
         resp, body = self.client.list_ports(limit=3)
         self.assertEqual(200, resp.status)
-        self.assertEqual(3, len(body['ports']))
 
         next_marker = body['ports'][-1]['uuid']
         self.assertIn(next_marker, body['next'])
@@ -160,13 +126,13 @@
         uuids = [
             self.create_port(node_id=node_id,
                              address=data_utils.rand_mac_address())
-            ['port']['uuid'] for i in range(0, 5)]
+            [1]['uuid'] for i in range(0, 5)]
 
         resp, body = self.client.list_ports_detail()
         self.assertEqual(200, resp.status)
 
-        ports_dict = {port['uuid']: port for port in body['ports']
-                      if port['uuid'] in uuids}
+        ports_dict = dict((port['uuid'], port) for port in body['ports']
+                          if port['uuid'] in uuids)
 
         for uuid in uuids:
             self.assertIn(uuid, ports_dict)
@@ -185,8 +151,9 @@
         address = data_utils.rand_mac_address()
         extra = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
 
-        port_id = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address,
+                                      extra=extra)
+        self.assertEqual(201, resp.status)
 
         new_address = data_utils.rand_mac_address()
         new_extra = {'key1': 'new-value1', 'key2': 'new-value2',
@@ -205,9 +172,10 @@
                   'op': 'replace',
                   'value': new_extra['key3']}]
 
-        self.client.update_port(port_id, patch)
+        resp, _ = self.client.update_port(port['uuid'], patch)
+        self.assertEqual(200, resp.status)
 
-        resp, body = self.client.show_port(port_id)
+        resp, body = self.client.show_port(port['uuid'])
         self.assertEqual(200, resp.status)
         self.assertEqual(new_address, body['address'])
         self.assertEqual(new_extra, body['extra'])
@@ -218,23 +186,25 @@
         address = data_utils.rand_mac_address()
         extra = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
 
-        port_id = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address,
+                                      extra=extra)
+        self.assertEqual(201, resp.status)
 
         # Removing one item from the collection
-        resp, _ = self.client.update_port(port_id, [{'path': '/extra/key2',
-                                                     'op': 'remove'}])
+        resp, _ = self.client.update_port(port['uuid'],
+                                          [{'path': '/extra/key2',
+                                           'op': 'remove'}])
         self.assertEqual(200, resp.status)
         extra.pop('key2')
-        resp, body = self.client.show_port(port_id)
+        resp, body = self.client.show_port(port['uuid'])
         self.assertEqual(200, resp.status)
         self.assertEqual(extra, body['extra'])
 
         # Removing the collection
-        resp, _ = self.client.update_port(port_id, [{'path': '/extra',
-                                                     'op': 'remove'}])
+        resp, _ = self.client.update_port(port['uuid'], [{'path': '/extra',
+                                                         'op': 'remove'}])
         self.assertEqual(200, resp.status)
-        resp, body = self.client.show_port(port_id)
+        resp, body = self.client.show_port(port['uuid'])
         self.assertEqual(200, resp.status)
         self.assertEqual({}, body['extra'])
 
@@ -247,8 +217,8 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual(201, resp.status)
 
         extra = {'key1': 'value1', 'key2': 'value2'}
 
@@ -259,9 +229,10 @@
                   'op': 'add',
                   'value': extra['key2']}]
 
-        self.client.update_port(port_id, patch)
+        resp, _ = self.client.update_port(port['uuid'], patch)
+        self.assertEqual(200, resp.status)
 
-        resp, body = self.client.show_port(port_id)
+        resp, body = self.client.show_port(port['uuid'])
         self.assertEqual(200, resp.status)
         self.assertEqual(extra, body['extra'])
 
@@ -271,8 +242,9 @@
         address = data_utils.rand_mac_address()
         extra = {'key1': 'value1', 'key2': 'value2'}
 
-        port_id = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address,
+                                      extra=extra)
+        self.assertEqual(201, resp.status)
 
         new_address = data_utils.rand_mac_address()
         new_extra = {'key1': 'new-value1', 'key3': 'new-value3'}
@@ -289,9 +261,10 @@
                   'op': 'add',
                   'value': new_extra['key3']}]
 
-        self.client.update_port(port_id, patch)
+        resp, _ = self.client.update_port(port['uuid'], patch)
+        self.assertEqual(200, resp.status)
 
-        resp, body = self.client.show_port(port_id)
+        resp, body = self.client.show_port(port['uuid'])
         self.assertEqual(200, resp.status)
         self.assertEqual(new_address, body['address'])
         self.assertEqual(new_extra, body['extra'])
diff --git a/tempest/api/baremetal/test_ports_negative.py b/tempest/api/baremetal/test_ports_negative.py
index 4cbe00e..3e77a5f 100644
--- a/tempest/api/baremetal/test_ports_negative.py
+++ b/tempest/api/baremetal/test_ports_negative.py
@@ -22,8 +22,11 @@
     def setUp(self):
         super(TestPortsNegative, self).setUp()
 
-        chassis = self.create_chassis()['chassis']
-        self.node = self.create_node(chassis['uuid'])['node']
+        resp, self.chassis = self.create_chassis()
+        self.assertEqual('201', resp['status'])
+
+        resp, self.node = self.create_node(self.chassis['uuid'])
+        self.assertEqual('201', resp['status'])
 
     @test.attr(type=['negative', 'smoke'])
     def test_create_port_malformed_mac(self):
@@ -134,9 +137,13 @@
         address = data_utils.rand_mac_address()
         extra = {'key': 'value'}
 
-        port_id = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)['port']['uuid']
-        self.client.delete_port(port_id)
+        resp, port = self.create_port(node_id=node_id, address=address,
+                                      extra=extra)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
+
+        resp, body = self.client.delete_port(port_id)
+        self.assertEqual('204', resp['status'])
 
         patch = [{'path': '/extra/key',
                   'op': 'replace',
@@ -162,8 +169,9 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
 
         self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
                           [{'path': '/extra/key', ' op': 'add',
@@ -174,8 +182,9 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
 
         self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
                           [{'path': '/extra',
@@ -187,8 +196,10 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
+
         self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
                           [{'path': '/nonexistent', ' op': 'add',
                             'value': 'value'}])
@@ -198,8 +209,9 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id,
-                                   address=address)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
 
         patch = [{'path': '/node_uuid',
                   'op': 'replace',
@@ -213,9 +225,13 @@
         address1 = data_utils.rand_mac_address()
         address2 = data_utils.rand_mac_address()
 
-        self.create_port(node_id=node_id, address=address1)
-        port_id = self.create_port(node_id=node_id,
-                                   address=address2)['port']['uuid']
+        resp, port1 = self.create_port(node_id=node_id, address=address1)
+        self.assertEqual('201', resp['status'])
+
+        resp, port2 = self.create_port(node_id=node_id, address=address2)
+        self.assertEqual('201', resp['status'])
+        port_id = port2['uuid']
+
         patch = [{'path': '/address',
                   'op': 'replace',
                   'value': address1}]
@@ -227,8 +243,9 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id,
-                                   address=address)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
 
         patch = [{'path': '/node_uuid',
                   'op': 'replace',
@@ -241,8 +258,10 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id,
-                                   address=address)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
+
         patch = [{'path': '/address',
                   'op': 'replace',
                   'value': 'malformed:mac'}]
@@ -256,13 +275,14 @@
         address = data_utils.rand_mac_address()
         extra = {'key': 'value'}
 
-        port_id = self.create_port(node_id=node_id,
-                                   address=address,
-                                   extra=extra)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address,
+                                      extra=extra)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
+
         patch = [{'path': '/extra/key',
                   'op': 'replace',
                   'value': 0.123}]
-
         self.assertRaises(exc.BadRequest,
                           self.client.update_port, port_id, patch)
 
@@ -270,11 +290,11 @@
     def test_update_port_replace_whole_extra_with_malformed(self):
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
-        extra = {'key': 'value'}
 
-        port_id = self.create_port(node_id=node_id,
-                                   address=address,
-                                   extra=extra)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
+
         patch = [{'path': '/extra',
                   'op': 'replace',
                   'value': [1, 2, 3, 4, 'a']}]
@@ -287,8 +307,9 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id,
-                                   address=address)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
 
         patch = [{'path': '/nonexistent', ' op': 'replace', 'value': 'value'}]
 
@@ -300,8 +321,10 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
+
         self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
                           [{'path': '/address', 'op': 'remove'}])
 
@@ -310,8 +333,10 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
+
         self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
                           [{'path': '/uuid', 'op': 'remove'}])
 
@@ -320,8 +345,10 @@
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
 
-        port_id = self.create_port(node_id=node_id, address=address)['port'][
-            'uuid']
+        resp, port = self.create_port(node_id=node_id, address=address)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
+
         self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
                           [{'path': '/nonexistent', 'op': 'remove'}])
 
@@ -339,8 +366,10 @@
         address = data_utils.rand_mac_address()
         extra = {'key1': 'value1', 'key2': 'value2'}
 
-        port_id = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)['port']['uuid']
+        resp, port = self.create_port(node_id=node_id, address=address,
+                                      extra=extra)
+        self.assertEqual('201', resp['status'])
+        port_id = port['uuid']
 
         new_address = data_utils.rand_mac_address()
         new_extra = {'key1': 'new-value1', 'key3': 'new-value3'}
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 111ac9c..18866e5 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -30,8 +30,8 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsAdminTestJSON, cls).setUpClass()
-        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
-            msg = "FlavorExtraData extension not enabled."
+        if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+            msg = "OS-FLV-EXT-DATA extension not enabled."
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
@@ -231,7 +231,7 @@
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
-            # Create the flavor
+        # Create the flavor
         resp, flavor = self.client.create_flavor(flavor_name,
                                                  self.ram, self.vcpus,
                                                  self.disk,
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index 3ba7314..f2554ea 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -28,8 +28,8 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsAccessTestJSON, cls).setUpClass()
-        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
-            msg = "FlavorExtraData extension not enabled."
+        if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+            msg = "OS-FLV-EXT-DATA extension not enabled."
             raise cls.skipException(msg)
 
         # Compute admin flavor client
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 73834e9..b636ccd 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -31,8 +31,8 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsAccessNegativeTestJSON, cls).setUpClass()
-        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
-            msg = "FlavorExtraData extension not enabled."
+        if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+            msg = "OS-FLV-EXT-DATA extension not enabled."
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 91145ec..56daf96 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -29,8 +29,8 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsExtraSpecsTestJSON, cls).setUpClass()
-        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
-            msg = "FlavorExtraData extension not enabled."
+        if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+            msg = "OS-FLV-EXT-DATA extension not enabled."
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index a139c2f..1e5695f 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -30,8 +30,8 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsExtraSpecsNegativeTestJSON, cls).setUpClass()
-        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
-            msg = "FlavorExtraData extension not enabled."
+        if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+            msg = "OS-FLV-EXT-DATA extension not enabled."
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
diff --git a/tempest/api/compute/admin/test_flavors_negative.py b/tempest/api/compute/admin/test_flavors_negative.py
index b37d32c..9e4412f 100644
--- a/tempest/api/compute/admin/test_flavors_negative.py
+++ b/tempest/api/compute/admin/test_flavors_negative.py
@@ -32,8 +32,8 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsAdminNegativeTestJSON, cls).setUpClass()
-        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
-            msg = "FlavorExtraData extension not enabled."
+        if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
+            msg = "OS-FLV-EXT-DATA extension not enabled."
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
new file mode 100644
index 0000000..208b032
--- /dev/null
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -0,0 +1,82 @@
+# Copyright 2014 NEC Technologies India Ltd.
+# 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 netaddr
+
+from tempest.api.compute import base
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class FloatingIPsBulkAdminTestJSON(base.BaseV2ComputeAdminTest):
+    """
+    Tests Floating IPs Bulk APIs Create, List and  Delete that
+    require admin privileges.
+    API documentation - http://docs.openstack.org/api/openstack-compute/2/
+    content/ext-os-floating-ips-bulk.html
+    """
+
+    @classmethod
+    @test.safe_setup
+    def setUpClass(cls):
+        super(FloatingIPsBulkAdminTestJSON, cls).setUpClass()
+        cls.client = cls.os_adm.floating_ips_client
+        cls.ip_range = CONF.compute.floating_ip_range
+        cls.verify_unallocated_floating_ip_range(cls.ip_range)
+
+    @classmethod
+    def verify_unallocated_floating_ip_range(cls, ip_range):
+        # Verify whether configure floating IP range is not already allocated.
+        _, body = cls.client.list_floating_ips_bulk()
+        allocated_ips_list = map(lambda x: x['address'], body)
+        for ip_addr in netaddr.IPNetwork(ip_range).iter_hosts():
+            if str(ip_addr) in allocated_ips_list:
+                msg = ("Configured unallocated floating IP range is already "
+                       "allocated. Configure the correct unallocated range "
+                       "as 'floating_ip_range'")
+                raise cls.skipException(msg)
+        return
+
+    def _delete_floating_ips_bulk(self, ip_range):
+        try:
+            self.client.delete_floating_ips_bulk(ip_range)
+        except Exception:
+            pass
+
+    @test.attr(type='gate')
+    def test_create_list_delete_floating_ips_bulk(self):
+        # Create, List  and delete the Floating IPs Bulk
+        pool = 'test_pool'
+        # NOTE(GMann): Reserving the IP range but those are not attached
+        # anywhere. Using the below mentioned interface which is not ever
+        # expected to be used. Clean Up has been done for created IP range
+        interface = 'eth0'
+        resp, body = self.client.create_floating_ips_bulk(self.ip_range,
+                                                          pool,
+                                                          interface)
+
+        self.assertEqual(200, resp.status)
+        self.addCleanup(self._delete_floating_ips_bulk, self.ip_range)
+        self.assertEqual(self.ip_range, body['ip_range'])
+        resp, ips_list = self.client.list_floating_ips_bulk()
+        self.assertEqual(200, resp.status)
+        self.assertNotEqual(0, len(ips_list))
+        for ip in netaddr.IPNetwork(self.ip_range).iter_hosts():
+            self.assertIn(str(ip), map(lambda x: x['address'], ips_list))
+        resp, body = self.client.delete_floating_ips_bulk(self.ip_range)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(self.ip_range, body)
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index bfebb5e..0e6b9d6 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -67,8 +67,8 @@
     @test.attr(type='gate')
     def test_list_flavors_using_marker(self):
         # The list of flavors should start from the provided marker
-        resp, flavors = self.client.list_flavors()
-        flavor_id = flavors[0]['id']
+        resp, flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor_id = flavor['id']
 
         params = {'marker': flavor_id}
         resp, flavors = self.client.list_flavors(params)
@@ -78,8 +78,8 @@
     @test.attr(type='gate')
     def test_list_flavors_detailed_using_marker(self):
         # The list of flavors should start from the provided marker
-        resp, flavors = self.client.list_flavors_with_detail()
-        flavor_id = flavors[0]['id']
+        resp, flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor_id = flavor['id']
 
         params = {'marker': flavor_id}
         resp, flavors = self.client.list_flavors_with_detail(params)
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index ae00ae2..6163f4d 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -40,7 +40,7 @@
         # Delete server before trying to create server
         self.servers_client.delete_server(server['id'])
         self.servers_client.wait_for_server_termination(server['id'])
-       # Create a new image after server is deleted
+        # Create a new image after server is deleted
         name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
         self.assertRaises(exceptions.NotFound,
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index 768cc11..28d64fb 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import datetime
-
 from six import moves
 
 from tempest.api.compute import base
@@ -37,9 +35,8 @@
         # tearDownClass method of the super-class.
         cls.existing_fixtures = []
         cls.deleted_fixtures = []
-        cls.start_time = datetime.datetime.utcnow()
         for x in moves.xrange(2):
-            resp, srv = cls.create_test_server()
+            resp, srv = cls.create_test_server(wait_until='ACTIVE')
             cls.existing_fixtures.append(srv)
 
         resp, srv = cls.create_test_server()
@@ -127,19 +124,6 @@
         self.assertRaises(exceptions.BadRequest, self.client.list_servers,
                           {'limit': -1})
 
-    @test.attr(type='gate')
-    def test_list_servers_by_changes_since(self):
-        # Servers are listed by specifying changes-since date
-        changes_since = {'changes-since': self.start_time.isoformat()}
-        resp, body = self.client.list_servers(changes_since)
-        self.assertEqual('200', resp['status'])
-        # changes-since returns all instances, including deleted.
-        num_expected = (len(self.existing_fixtures) +
-                        len(self.deleted_fixtures))
-        self.assertEqual(num_expected, len(body['servers']),
-                         "Number of servers %d is wrong in %s" %
-                         (num_expected, body['servers']))
-
     @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_changes_since_invalid_date(self):
         # Return an error when invalid date format is passed
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 80e6008..d0fd876 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -193,26 +193,46 @@
             if current_flavor == self.flavor_ref else self.flavor_ref
         return current_flavor, new_flavor_ref
 
-    @testtools.skipUnless(CONF.compute_feature_enabled.resize,
-                          'Resize not available.')
-    @test.attr(type='smoke')
-    def test_resize_server_confirm(self):
+    def _test_resize_server_confirm(self, stop=False):
         # The server's RAM and disk space should be modified to that of
         # the provided flavor
 
         previous_flavor_ref, new_flavor_ref = \
             self._detect_server_image_flavor(self.server_id)
 
+        if stop:
+            resp = self.servers_client.stop(self.server_id)[0]
+            self.assertEqual(202, resp.status)
+            self.servers_client.wait_for_server_status(self.server_id,
+                                                       'SHUTOFF')
+
         resp, server = self.client.resize(self.server_id, new_flavor_ref)
         self.assertEqual(202, resp.status)
         self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
 
         self.client.confirm_resize(self.server_id)
-        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+        expected_status = 'SHUTOFF' if stop else 'ACTIVE'
+        self.client.wait_for_server_status(self.server_id, expected_status)
 
         resp, server = self.client.get_server(self.server_id)
         self.assertEqual(new_flavor_ref, server['flavor']['id'])
 
+        if stop:
+            # NOTE(mriedem): tearDown requires the server to be started.
+            self.client.start(self.server_id)
+
+    @testtools.skipUnless(CONF.compute_feature_enabled.resize,
+                          'Resize not available.')
+    @test.attr(type='smoke')
+    def test_resize_server_confirm(self):
+        self._test_resize_server_confirm(stop=False)
+
+    @testtools.skipUnless(CONF.compute_feature_enabled.resize,
+                          'Resize not available.')
+    @test.attr(type='smoke')
+    def test_resize_server_confirm_from_stopped(self):
+        self._test_resize_server_confirm(stop=True)
+
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     @test.attr(type='gate')
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 40b97d7..936b871 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -70,20 +70,34 @@
         resp, server = self.client.get_server(server['id'])
         self.assertEqual(key_name, server['key_name'])
 
+    def _update_server_name(self, server_id, status):
+        # The server name should be changed to the the provided value
+        new_name = data_utils.rand_name('server')
+        # Update the server with a new name
+        resp, server = self.client.update_server(server_id,
+                                                 name=new_name)
+        self.client.wait_for_server_status(server_id, status)
+
+        # Verify the name of the server has changed
+        resp, server = self.client.get_server(server_id)
+        self.assertEqual(new_name, server['name'])
+        return server
+
     @test.attr(type='gate')
     def test_update_server_name(self):
         # The server name should be changed to the the provided value
         resp, server = self.create_test_server(wait_until='ACTIVE')
 
-        # Update the server with a new name
-        resp, server = self.client.update_server(server['id'],
-                                                 name='newname')
-        self.assertEqual(200, resp.status)
-        self.client.wait_for_server_status(server['id'], 'ACTIVE')
+        self._update_server_name(server['id'], 'ACTIVE')
 
-        # Verify the name of the server has changed
-        resp, server = self.client.get_server(server['id'])
-        self.assertEqual('newname', server['name'])
+    @test.attr(type='gate')
+    def test_update_server_name_in_stop_state(self):
+        # The server name should be changed to the the provided value
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+        self.client.stop(server['id'])
+        self.client.wait_for_server_status(server['id'], 'SHUTOFF')
+        updated_server = self._update_server_name(server['id'], 'SHUTOFF')
+        self.assertNotIn('progress', updated_server)
 
     @test.attr(type='gate')
     def test_update_access_server_address(self):
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 5ac667e..6343ead 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -45,7 +45,10 @@
     def setUpClass(cls):
         super(ServersNegativeTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
-        cls.alt_os = clients.AltManager()
+        if CONF.compute.allow_tenant_isolation:
+            cls.alt_os = clients.Manager(cls.isolated_creds.get_alt_creds())
+        else:
+            cls.alt_os = clients.AltManager()
         cls.alt_client = cls.alt_os.servers_client
         resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
diff --git a/tempest/api/compute/v3/admin/test_flavors.py b/tempest/api/compute/v3/admin/test_flavors.py
index 2a4fc02..8a4e3cf 100644
--- a/tempest/api/compute/v3/admin/test_flavors.py
+++ b/tempest/api/compute/v3/admin/test_flavors.py
@@ -229,7 +229,7 @@
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
-            # Create the flavor
+        # Create the flavor
         resp, flavor = self.client.create_flavor(flavor_name,
                                                  self.ram, self.vcpus,
                                                  self.disk,
diff --git a/tempest/api/compute/v3/admin/test_servers_negative.py b/tempest/api/compute/v3/admin/test_servers_negative.py
index a971463..5eb6395 100644
--- a/tempest/api/compute/v3/admin/test_servers_negative.py
+++ b/tempest/api/compute/v3/admin/test_servers_negative.py
@@ -54,6 +54,7 @@
             flavor_id = data_utils.rand_int_id(start=1000)
         return flavor_id
 
+    @test.skip_because(bug="1298131")
     @test.attr(type=['negative', 'gate'])
     def test_resize_server_using_overlimit_ram(self):
         flavor_name = data_utils.rand_name("flavor-")
@@ -67,11 +68,12 @@
                                                              ram, vcpus, disk,
                                                              flavor_id)
         self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
-        self.assertRaises(exceptions.OverLimit,
+        self.assertRaises(exceptions.Unauthorized,
                           self.client.resize,
                           self.servers[0]['id'],
                           flavor_ref['id'])
 
+    @test.skip_because(bug="1298131")
     @test.attr(type=['negative', 'gate'])
     def test_resize_server_using_overlimit_vcpus(self):
         flavor_name = data_utils.rand_name("flavor-")
@@ -85,7 +87,7 @@
                                                              ram, vcpus, disk,
                                                              flavor_id)
         self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
-        self.assertRaises(exceptions.OverLimit,
+        self.assertRaises(exceptions.Unauthorized,
                           self.client.resize,
                           self.servers[0]['id'],
                           flavor_ref['id'])
diff --git a/tempest/api/compute/v3/servers/test_list_servers_negative.py b/tempest/api/compute/v3/servers/test_list_servers_negative.py
index 9cbc4e0..18e5c67 100644
--- a/tempest/api/compute/v3/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/v3/servers/test_list_servers_negative.py
@@ -39,7 +39,7 @@
         cls.deleted_fixtures = []
         cls.start_time = datetime.datetime.utcnow()
         for x in moves.xrange(2):
-            resp, srv = cls.create_test_server()
+            resp, srv = cls.create_test_server(wait_until='ACTIVE')
             cls.existing_fixtures.append(srv)
 
         resp, srv = cls.create_test_server()
diff --git a/tempest/api/compute/v3/servers/test_server_actions.py b/tempest/api/compute/v3/servers/test_server_actions.py
index 721fe42..e098311 100644
--- a/tempest/api/compute/v3/servers/test_server_actions.py
+++ b/tempest/api/compute/v3/servers/test_server_actions.py
@@ -186,26 +186,46 @@
             if current_flavor == self.flavor_ref else self.flavor_ref
         return current_flavor, new_flavor_ref
 
-    @testtools.skipUnless(CONF.compute_feature_enabled.resize,
-                          'Resize not available.')
-    @test.attr(type='smoke')
-    def test_resize_server_confirm(self):
+    def _test_resize_server_confirm(self, stop=False):
         # The server's RAM and disk space should be modified to that of
         # the provided flavor
 
         previous_flavor_ref, new_flavor_ref = \
             self._detect_server_image_flavor(self.server_id)
 
+        if stop:
+            resp = self.servers_client.stop(self.server_id)[0]
+            self.assertEqual(202, resp.status)
+            self.servers_client.wait_for_server_status(self.server_id,
+                                                       'SHUTOFF')
+
         resp, server = self.client.resize(self.server_id, new_flavor_ref)
         self.assertEqual(202, resp.status)
         self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
 
         self.client.confirm_resize(self.server_id)
-        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+        expected_status = 'SHUTOFF' if stop else 'ACTIVE'
+        self.client.wait_for_server_status(self.server_id, expected_status)
 
         resp, server = self.client.get_server(self.server_id)
         self.assertEqual(new_flavor_ref, server['flavor']['id'])
 
+        if stop:
+            # NOTE(mriedem): tearDown requires the server to be started.
+            self.client.start(self.server_id)
+
+    @testtools.skipUnless(CONF.compute_feature_enabled.resize,
+                          'Resize not available.')
+    @test.attr(type='smoke')
+    def test_resize_server_confirm(self):
+        self._test_resize_server_confirm(stop=False)
+
+    @testtools.skipUnless(CONF.compute_feature_enabled.resize,
+                          'Resize not available.')
+    @test.attr(type='smoke')
+    def test_resize_server_confirm_from_stopped(self):
+        self._test_resize_server_confirm(stop=True)
+
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     @test.attr(type='gate')
diff --git a/tempest/api/compute/v3/servers/test_servers_negative.py b/tempest/api/compute/v3/servers/test_servers_negative.py
index 827c4c4..90deaa9 100644
--- a/tempest/api/compute/v3/servers/test_servers_negative.py
+++ b/tempest/api/compute/v3/servers/test_servers_negative.py
@@ -45,7 +45,10 @@
     def setUpClass(cls):
         super(ServersNegativeV3Test, cls).setUpClass()
         cls.client = cls.servers_client
-        cls.alt_os = clients.AltManager()
+        if CONF.compute.allow_tenant_isolation:
+            cls.alt_os = clients.Manager(cls.isolated_creds.get_alt_creds())
+        else:
+            cls.alt_os = clients.AltManager()
         cls.alt_client = cls.alt_os.servers_v3_client
         resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 4585912..5a64544 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -53,28 +53,28 @@
     def _create_and_attach(self):
         # Start a server and wait for it to become ready
         admin_pass = self.image_ssh_password
-        resp, server = self.create_test_server(wait_until='ACTIVE',
-                                               adminPass=admin_pass)
-        self.server = server
+        _, self.server = self.create_test_server(wait_until='ACTIVE',
+                                                 adminPass=admin_pass)
 
         # Record addresses so that we can ssh later
-        resp, server['addresses'] = \
-            self.servers_client.list_addresses(server['id'])
+        _, self.server['addresses'] = \
+            self.servers_client.list_addresses(self.server['id'])
 
         # Create a volume and wait for it to become ready
-        resp, volume = self.volumes_client.create_volume(1,
-                                                         display_name='test')
-        self.volume = volume
+        _, self.volume = self.volumes_client.create_volume(
+            1, display_name='test')
         self.addCleanup(self._delete_volume)
-        self.volumes_client.wait_for_volume_status(volume['id'], 'available')
+        self.volumes_client.wait_for_volume_status(self.volume['id'],
+                                                   'available')
 
         # Attach the volume to the server
-        self.servers_client.attach_volume(server['id'], volume['id'],
+        self.servers_client.attach_volume(self.server['id'],
+                                          self.volume['id'],
                                           device='/dev/%s' % self.device)
-        self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
+        self.volumes_client.wait_for_volume_status(self.volume['id'], 'in-use')
 
         self.attached = True
-        self.addCleanup(self._detach, server['id'], volume['id'])
+        self.addCleanup(self._detach, self.server['id'], self.volume['id'])
 
     @testtools.skipUnless(CONF.compute.run_ssh, 'SSH required for this test')
     @test.attr(type='gate')
@@ -82,31 +82,33 @@
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
         self._create_and_attach()
-        server = self.server
-        volume = self.volume
 
-        self.servers_client.stop(server['id'])
-        self.servers_client.wait_for_server_status(server['id'], 'SHUTOFF')
+        self.servers_client.stop(self.server['id'])
+        self.servers_client.wait_for_server_status(self.server['id'],
+                                                   'SHUTOFF')
 
-        self.servers_client.start(server['id'])
-        self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
+        self.servers_client.start(self.server['id'])
+        self.servers_client.wait_for_server_status(self.server['id'], 'ACTIVE')
 
-        linux_client = remote_client.RemoteClient(server, self.image_ssh_user,
-                                                  server['adminPass'])
+        linux_client = remote_client.RemoteClient(self.server,
+                                                  self.image_ssh_user,
+                                                  self.server['adminPass'])
         partitions = linux_client.get_partitions()
         self.assertIn(self.device, partitions)
 
-        self._detach(server['id'], volume['id'])
+        self._detach(self.server['id'], self.volume['id'])
         self.attached = False
 
-        self.servers_client.stop(server['id'])
-        self.servers_client.wait_for_server_status(server['id'], 'SHUTOFF')
+        self.servers_client.stop(self.server['id'])
+        self.servers_client.wait_for_server_status(self.server['id'],
+                                                   'SHUTOFF')
 
-        self.servers_client.start(server['id'])
-        self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
+        self.servers_client.start(self.server['id'])
+        self.servers_client.wait_for_server_status(self.server['id'], 'ACTIVE')
 
-        linux_client = remote_client.RemoteClient(server, self.image_ssh_user,
-                                                  server['adminPass'])
+        linux_client = remote_client.RemoteClient(self.server,
+                                                  self.image_ssh_user,
+                                                  self.server['adminPass'])
         partitions = linux_client.get_partitions()
         self.assertNotIn(self.device, partitions)
 
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index cc76880..0d6773c 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -39,6 +39,7 @@
         cls._cluster_templates = []
         cls._data_sources = []
         cls._job_binary_internals = []
+        cls._job_binaries = []
 
     @classmethod
     def tearDownClass(cls):
@@ -50,6 +51,8 @@
                               cls.client.delete_data_source)
         cls.cleanup_resources(getattr(cls, '_job_binary_internals', []),
                               cls.client.delete_job_binary_internal)
+        cls.cleanup_resources(getattr(cls, '_job_binaries', []),
+                              cls.client.delete_job_binary)
         cls.clear_isolated_creds()
         super(BaseDataProcessingTest, cls).tearDownClass()
 
@@ -128,3 +131,16 @@
         cls._job_binary_internals.append(body['id'])
 
         return resp, body
+
+    def create_job_binary(cls, name, url, extra=None, **kwargs):
+        """Creates watched job binary with specified params.
+
+        It supports passing additional params using kwargs and returns created
+        object. All resources created in this method will be automatically
+        removed in tearDownClass method.
+        """
+        resp, body = cls.client.create_job_binary(name, url, extra, **kwargs)
+        # store id of created job binary
+        cls._job_binaries.append(body['id'])
+
+        return resp, body
diff --git a/tempest/api/data_processing/test_cluster_templates.py b/tempest/api/data_processing/test_cluster_templates.py
new file mode 100644
index 0000000..e5c6303
--- /dev/null
+++ b/tempest/api/data_processing/test_cluster_templates.py
@@ -0,0 +1,146 @@
+# Copyright (c) 2014 Mirantis Inc.
+#
+#    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.data_processing import base as dp_base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class ClusterTemplateTest(dp_base.BaseDataProcessingTest):
+    """Link to the API documentation is http://docs.openstack.org/developer/
+    sahara/restapi/rest_api_v1.0.html#cluster-templates
+    """
+    @classmethod
+    def setUpClass(cls):
+        super(ClusterTemplateTest, cls).setUpClass()
+        # create node group template
+        node_group_template = {
+            'name': data_utils.rand_name('sahara-ng-template'),
+            'description': 'Test node group template',
+            'plugin_name': 'vanilla',
+            'hadoop_version': '1.2.1',
+            'node_processes': ['datanode'],
+            'flavor_id': cls.flavor_ref,
+            'node_configs': {
+                'HDFS': {
+                    'Data Node Heap Size': 1024
+                }
+            }
+        }
+        resp_body = cls.create_node_group_template(**node_group_template)[1]
+
+        cls.full_cluster_template = {
+            'description': 'Test cluster template',
+            'plugin_name': 'vanilla',
+            'hadoop_version': '1.2.1',
+            'cluster_configs': {
+                'HDFS': {
+                    'dfs.replication': 2
+                },
+                'MapReduce': {
+                    'mapred.map.tasks.speculative.execution': False,
+                    'mapred.child.java.opts': '-Xmx500m'
+                },
+                'general': {
+                    'Enable Swift': False
+                }
+            },
+            'node_groups': [
+                {
+                    'name': 'master-node',
+                    'flavor_id': cls.flavor_ref,
+                    'node_processes': ['namenode'],
+                    'count': 1
+                },
+                {
+                    'name': 'worker-node',
+                    'node_group_template_id': resp_body['id'],
+                    'count': 3
+                }
+            ]
+        }
+        # create cls.cluster_template variable to use for comparison to cluster
+        # template response body. The 'node_groups' field in the response body
+        # has some extra info that post body does not have. The 'node_groups'
+        # field in the response body is something like this
+        #
+        #   'node_groups': [
+        #       {
+        #           'count': 3,
+        #           'name': 'worker-node',
+        #           'volume_mount_prefix': '/volumes/disk',
+        #           'created_at': '2014-05-21 14:31:37',
+        #           'updated_at': None,
+        #           'floating_ip_pool': None,
+        #           ...
+        #       },
+        #       ...
+        #   ]
+        cls.cluster_template = cls.full_cluster_template.copy()
+        del cls.cluster_template['node_groups']
+
+    def _create_cluster_template(self, template_name=None):
+        """Creates Cluster Template with optional name specified.
+
+        It creates template and ensures response status, template name and
+        response body. Returns id and name of created template.
+        """
+        if not template_name:
+            # generate random name if it's not specified
+            template_name = data_utils.rand_name('sahara-cluster-template')
+
+        # create cluster template
+        resp, body = self.create_cluster_template(template_name,
+                                                  **self.full_cluster_template)
+
+        # ensure that template created successfully
+        self.assertEqual(202, resp.status)
+        self.assertEqual(template_name, body['name'])
+        self.assertDictContainsSubset(self.cluster_template, body)
+
+        return body['id'], template_name
+
+    @test.attr(type='smoke')
+    def test_cluster_template_create(self):
+        self._create_cluster_template()
+
+    @test.attr(type='smoke')
+    def test_cluster_template_list(self):
+        template_info = self._create_cluster_template()
+
+        # check for cluster template in list
+        resp, templates = self.client.list_cluster_templates()
+        self.assertEqual(200, resp.status)
+        templates_info = [(template['id'], template['name'])
+                          for template in templates]
+        self.assertIn(template_info, templates_info)
+
+    @test.attr(type='smoke')
+    def test_cluster_template_get(self):
+        template_id, template_name = self._create_cluster_template()
+
+        # check cluster template fetch by id
+        resp, template = self.client.get_cluster_template(template_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(template_name, template['name'])
+        self.assertDictContainsSubset(self.cluster_template, template)
+
+    @test.attr(type='smoke')
+    def test_cluster_template_delete(self):
+        template_id = self._create_cluster_template()[0]
+
+        # delete the cluster template by id
+        resp = self.client.delete_cluster_template(template_id)[0]
+        self.assertEqual(204, resp.status)
+        # TODO(ylobankov): check that cluster template is really deleted
diff --git a/tempest/api/data_processing/test_job_binary_internals.py b/tempest/api/data_processing/test_job_binary_internals.py
new file mode 100644
index 0000000..6d59177
--- /dev/null
+++ b/tempest/api/data_processing/test_job_binary_internals.py
@@ -0,0 +1,88 @@
+# Copyright (c) 2014 Mirantis Inc.
+#
+#    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.data_processing import base as dp_base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class JobBinaryInternalTest(dp_base.BaseDataProcessingTest):
+    """Link to the API documentation is http://docs.openstack.org/developer/
+    sahara/restapi/rest_api_v1.1_EDP.html#job-binary-internals
+    """
+    @classmethod
+    def setUpClass(cls):
+        super(JobBinaryInternalTest, cls).setUpClass()
+        cls.job_binary_internal_data = 'Some script may be data'
+
+    def _create_job_binary_internal(self, binary_name=None):
+        """Creates Job Binary Internal with optional name specified.
+
+        It puts data into Sahara database and ensures response status and
+        job binary internal name. Returns id and name of created job binary
+        internal.
+        """
+        if not binary_name:
+            # generate random name if it's not specified
+            binary_name = data_utils.rand_name('sahara-job-binary-internal')
+
+        # create job binary internal
+        resp, body = self.create_job_binary_internal(
+            binary_name, self.job_binary_internal_data)
+
+        # ensure that job binary internal created successfully
+        self.assertEqual(202, resp.status)
+        self.assertEqual(binary_name, body['name'])
+
+        return body['id'], binary_name
+
+    @test.attr(type='smoke')
+    def test_job_binary_internal_create(self):
+        self._create_job_binary_internal()
+
+    @test.attr(type='smoke')
+    def test_job_binary_internal_list(self):
+        binary_info = self._create_job_binary_internal()
+
+        # check for job binary internal in list
+        resp, binaries = self.client.list_job_binary_internals()
+        self.assertEqual(200, resp.status)
+        binaries_info = [(binary['id'], binary['name']) for binary in binaries]
+        self.assertIn(binary_info, binaries_info)
+
+    @test.attr(type='smoke')
+    def test_job_binary_internal_get(self):
+        binary_id, binary_name = self._create_job_binary_internal()
+
+        # check job binary internal fetch by id
+        resp, binary = self.client.get_job_binary_internal(binary_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(binary_name, binary['name'])
+
+    @test.attr(type='smoke')
+    def test_job_binary_internal_delete(self):
+        binary_id = self._create_job_binary_internal()[0]
+
+        # delete the job binary internal by id
+        resp = self.client.delete_job_binary_internal(binary_id)[0]
+        self.assertEqual(204, resp.status)
+
+    @test.attr(type='smoke')
+    def test_job_binary_internal_get_data(self):
+        binary_id = self._create_job_binary_internal()[0]
+
+        # get data of job binary internal by id
+        resp, data = self.client.get_job_binary_internal_data(binary_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(data, self.job_binary_internal_data)
diff --git a/tempest/api/database/base.py b/tempest/api/database/base.py
index cf70d11..b68c84a 100644
--- a/tempest/api/database/base.py
+++ b/tempest/api/database/base.py
@@ -41,4 +41,5 @@
         os = cls.get_client_manager()
         cls.os = os
         cls.database_flavors_client = cls.os.database_flavors_client
+        cls.os_flavors_client = cls.os.flavors_client
         cls.database_versions_client = cls.os.database_versions_client
diff --git a/tempest/api/database/flavors/test_flavors.py b/tempest/api/database/flavors/test_flavors.py
index a591e8e..64d71b9 100644
--- a/tempest/api/database/flavors/test_flavors.py
+++ b/tempest/api/database/flavors/test_flavors.py
@@ -28,6 +28,7 @@
     def test_get_db_flavor(self):
         # The expected flavor details should be returned
         resp, flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
+        self.assertEqual(200, resp.status)
         self.assertEqual(self.db_flavor_ref, str(flavor['id']))
         self.assertIn('ram', flavor)
         self.assertIn('links', flavor)
@@ -36,6 +37,36 @@
     @test.attr(type='smoke')
     def test_list_db_flavors(self):
         resp, flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
+        self.assertEqual(200, resp.status)
         # List of all flavors should contain the expected flavor
         resp, flavors = self.client.list_db_flavors()
+        self.assertEqual(200, resp.status)
         self.assertIn(flavor, flavors)
+
+    def _check_values(self, names, db_flavor, os_flavor, in_db=True):
+        for name in names:
+            self.assertIn(name, os_flavor)
+            if in_db:
+                self.assertIn(name, db_flavor)
+                self.assertEqual(str(db_flavor[name]), str(os_flavor[name]),
+                                 "DB flavor differs from OS on '%s' value"
+                                 % name)
+            else:
+                self.assertNotIn(name, db_flavor)
+
+    @test.attr(type='smoke')
+    def test_compare_db_flavors_with_os(self):
+        resp, db_flavors = self.client.list_db_flavors()
+        self.assertEqual(200, resp.status)
+        resp, os_flavors = self.os_flavors_client.list_flavors_with_detail()
+        self.assertEqual(200, resp.status)
+        self.assertEqual(len(os_flavors), len(db_flavors),
+                         "OS flavors %s do not match DB flavors %s" %
+                         (os_flavors, db_flavors))
+        for os_flavor in os_flavors:
+            resp, db_flavor =\
+                self.client.get_db_flavor_details(os_flavor['id'])
+            self.assertEqual(200, resp.status)
+            self._check_values(['id', 'name', 'ram'], db_flavor, os_flavor)
+            self._check_values(['disk', 'vcpus', 'swap'], db_flavor, os_flavor,
+                               in_db=False)
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index 0472e07..5926488 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -101,7 +101,7 @@
         # List and Verify Services
         resp, body = self.client.list_services()
         self.assertEqual(200, resp.status)
-        found = [service for service in body if service['id'] in service_ids]
+        found = [serv for serv in body if serv['id'] in service_ids]
         self.assertEqual(len(found), len(services), 'Services not found')
 
 
diff --git a/tempest/api/identity/admin/test_tenants.py b/tempest/api/identity/admin/test_tenants.py
index b989664..93734d2 100644
--- a/tempest/api/identity/admin/test_tenants.py
+++ b/tempest/api/identity/admin/test_tenants.py
@@ -36,7 +36,7 @@
         tenant_ids = map(lambda x: x['id'], tenants)
         resp, body = self.client.list_tenants()
         self.assertEqual(200, resp.status)
-        found = [tenant for tenant in body if tenant['id'] in tenant_ids]
+        found = [t for t in body if t['id'] in tenant_ids]
         self.assertEqual(len(found), len(tenants), 'Tenants not created')
 
         for tenant in tenants:
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index 31a0ddd..79717b1 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -171,13 +171,13 @@
 
     @test.attr(type='gate')
     def test_associate_user_to_project(self):
-        #Associate a user to a project
-        #Create a Project
+        # Associate a user to a project
+        # Create a Project
         p_name = data_utils.rand_name('project-')
         resp, project = self.client.create_project(p_name)
         self.data.projects.append(project)
 
-        #Create a User
+        # Create a User
         u_name = data_utils.rand_name('user-')
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
@@ -191,7 +191,7 @@
 
         # Get User To validate the user details
         resp, new_user_get = self.client.get_user(user['id'])
-        #Assert response body of GET
+        # Assert response body of GET
         self.assertEqual(u_name, new_user_get['name'])
         self.assertEqual(u_desc, new_user_get['description'])
         self.assertEqual(project['id'],
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
new file mode 100644
index 0000000..03974e4
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_regions.py
@@ -0,0 +1,102 @@
+# Copyright 2014 OpenStack Foundation
+# 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.identity import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class RegionsTestJSON(base.BaseIdentityV3AdminTest):
+    _interface = 'json'
+
+    @classmethod
+    @test.safe_setup
+    def setUpClass(cls):
+        super(RegionsTestJSON, cls).setUpClass()
+        cls.setup_regions = list()
+        cls.client = cls.region_client
+        for i in range(2):
+            r_description = data_utils.rand_name('description-')
+            _, region = cls.client.create_region(r_description)
+            cls.setup_regions.append(region)
+
+    @classmethod
+    def tearDownClass(cls):
+        for r in cls.setup_regions:
+            cls.client.delete_region(r['id'])
+        super(RegionsTestJSON, cls).tearDownClass()
+
+    def _delete_region(self, region_id):
+        resp, _ = self.client.delete_region(region_id)
+        self.assertEqual(204, resp.status)
+        self.assertRaises(exceptions.NotFound,
+                          self.client.get_region, region_id)
+
+    @test.attr(type='gate')
+    def test_create_update_get_delete_region(self):
+        r_description = data_utils.rand_name('description-')
+        resp, region = self.client.create_region(
+            r_description, parent_region_id=self.setup_regions[0]['id'])
+        self.assertEqual(201, resp.status)
+        self.addCleanup(self._delete_region, region['id'])
+        self.assertEqual(r_description, region['description'])
+        self.assertEqual(self.setup_regions[0]['id'],
+                         region['parent_region_id'])
+        # Update region with new description and parent ID
+        r_alt_description = data_utils.rand_name('description-')
+        resp, region = self.client.update_region(
+            region['id'],
+            description=r_alt_description,
+            parent_region_id=self.setup_regions[1]['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(r_alt_description, region['description'])
+        self.assertEqual(self.setup_regions[1]['id'],
+                         region['parent_region_id'])
+        # Get the details of region
+        resp, region = self.client.get_region(region['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(r_alt_description, region['description'])
+        self.assertEqual(self.setup_regions[1]['id'],
+                         region['parent_region_id'])
+
+    @test.attr(type='smoke')
+    def test_create_region_with_specific_id(self):
+        # Create a region with a specific id
+        r_region_id = data_utils.rand_uuid()
+        r_description = data_utils.rand_name('description-')
+        resp, region = self.client.create_region(
+            r_description, unique_region_id=r_region_id)
+        self.addCleanup(self._delete_region, region['id'])
+        # Asserting Create Region with specific id response body
+        self.assertEqual(201, resp.status)
+        self.assertEqual(r_region_id, region['id'])
+        self.assertEqual(r_description, region['description'])
+
+    @test.attr(type='gate')
+    def test_list_regions(self):
+        # Get a list of regions
+        resp, fetched_regions = self.client.list_regions()
+        self.assertEqual(200, resp.status)
+        missing_regions =\
+            [e for e in self.setup_regions if e not in fetched_regions]
+        # Asserting List Regions response
+        self.assertEqual(0, len(missing_regions),
+                         "Failed to find region %s in fetched list" %
+                         ', '.join(str(e) for e in missing_regions))
+
+
+class RegionsTestXML(RegionsTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index e4e74c1..697057f 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -96,6 +96,7 @@
         cls.client = cls.os_adm.identity_v3_client
         cls.token = cls.os_adm.token_v3_client
         cls.endpoints_client = cls.os_adm.endpoints_client
+        cls.region_client = cls.os_adm.region_client
         cls.data = DataGenerator(cls.client)
         cls.non_admin_client = cls.os.identity_v3_client
         cls.service_client = cls.os_adm.service_client
diff --git a/tempest/api/identity/test_extension.py b/tempest/api/identity/test_extension.py
new file mode 100644
index 0000000..67f20f4
--- /dev/null
+++ b/tempest/api/identity/test_extension.py
@@ -0,0 +1,37 @@
+# Copyright 2014 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.identity import base
+from tempest import test
+
+
+class ExtensionTestJSON(base.BaseIdentityV2AdminTest):
+    _interface = 'json'
+
+    @test.attr(type='gate')
+    def test_list_extensions(self):
+        # List all the extensions
+        resp, body = self.non_admin_client.list_extensions()
+        self.assertEqual(200, resp.status)
+        self.assertNotEmpty(body)
+        keys = ['name', 'updated', 'alias', 'links',
+                'namespace', 'description']
+        for value in body:
+            for key in keys:
+                self.assertIn(key, value)
+
+
+class ExtensionTestXML(ExtensionTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index c8726a2..2cc2009 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -55,8 +55,7 @@
         resp, body = self.create_image(name='New Remote Image',
                                        container_format='bare',
                                        disk_format='raw', is_public=False,
-                                       location='http://example.com'
-                                                '/someimage.iso',
+                                       location=CONF.image.http_image,
                                        properties={'key1': 'value1',
                                                    'key2': 'value2'})
         self.assertIn('id', body)
@@ -143,7 +142,7 @@
         image
         """
         name = 'New Remote Image %s' % name
-        location = 'http://example.com/someimage_%s.iso' % name
+        location = CONF.image.http_image
         resp, image = cls.create_image(name=name,
                                        container_format=container_format,
                                        disk_format=disk_format,
@@ -247,11 +246,17 @@
     @classmethod
     @test.safe_setup
     def setUpClass(cls):
-        super(ListSnapshotImagesTest, cls).setUpClass()
+        # This test class only uses nova v3 api to create snapshot
+        # as the similar test which uses nova v2 api already exists
+        # in nova v2 compute images api tests.
+        # Since nova v3 doesn't have images api proxy, this test
+        # class was added in the image api tests.
         if not CONF.compute_feature_enabled.api_v3:
-            cls.servers_client = cls.os.servers_client
-        else:
-            cls.servers_client = cls.os.servers_v3_client
+            skip_msg = ("%s skipped as nova v3 api is not available" %
+                        cls.__name__)
+            raise cls.skipException(skip_msg)
+        super(ListSnapshotImagesTest, cls).setUpClass()
+        cls.servers_client = cls.os.servers_v3_client
         cls.servers = []
         # We add a few images here to test the listing functionality of
         # the images API
@@ -281,8 +286,7 @@
         cls.servers.append(server)
         cls.servers_client.wait_for_server_status(
             server['id'], 'ACTIVE')
-        resp, image = cls.servers_client.create_image(
-            server['id'], name)
+        resp, _ = cls.servers_client.create_image(server['id'], name)
         image_id = data_utils.parse_image_id(resp['location'])
         cls.created_images.append(image_id)
         cls.client.wait_for_image_status(image_id,
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index dcd9bff..cc768fd 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -81,9 +81,13 @@
         cls.metering_label_rules = []
         cls.fw_rules = []
         cls.fw_policies = []
+        cls.ipsecpolicies = []
 
     @classmethod
     def tearDownClass(cls):
+        # Clean up ipsec policies
+        for ipsecpolicy in cls.ipsecpolicies:
+            cls.client.delete_ipsecpolicy(ipsecpolicy['id'])
         # Clean up firewall policies
         for fw_policy in cls.fw_policies:
             cls.client.delete_firewall_policy(fw_policy['id'])
@@ -145,15 +149,16 @@
         return network
 
     @classmethod
-    def create_subnet(cls, network, gateway=None):
+    def create_subnet(cls, network, gateway=None, cidr=None, mask_bits=None):
         """Wrapper utility that returns a test subnet."""
         # The cidr and mask_bits depend on the ip version.
         if cls._ip_version == 4:
-            cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
-            mask_bits = CONF.network.tenant_network_mask_bits
+            cidr = cidr or netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+            mask_bits = mask_bits or CONF.network.tenant_network_mask_bits
         elif cls._ip_version == 6:
-            cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
-            mask_bits = CONF.network.tenant_network_v6_mask_bits
+            cidr = (
+                cidr or netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr))
+            mask_bits = mask_bits or CONF.network.tenant_network_v6_mask_bits
         # Find a cidr that is not in use yet and create a subnet with it
         for subnet_cidr in cidr.subnet(mask_bits):
             if not gateway:
@@ -342,6 +347,14 @@
                 router['id'], i['fixed_ips'][0]['subnet_id'])
         cls.client.delete_router(router['id'])
 
+    @classmethod
+    def create_ipsecpolicy(cls, name):
+        """Wrapper utility that returns a test ipsec policy."""
+        _, body = cls.client.create_ipsecpolicy(name=name)
+        ipsecpolicy = body['ipsecpolicy']
+        cls.ipsecpolicies.append(ipsecpolicy)
+        return ipsecpolicy
+
 
 class BaseAdminNetworkTest(BaseNetworkTest):
 
diff --git a/tempest/api/network/base_routers.py b/tempest/api/network/base_routers.py
index b278002..1303bcf 100644
--- a/tempest/api/network/base_routers.py
+++ b/tempest/api/network/base_routers.py
@@ -37,6 +37,15 @@
             routers_list.append(router['id'])
         self.assertNotIn(router_id, routers_list)
 
+    def _add_router_interface_with_subnet_id(self, router_id, subnet_id):
+        resp, interface = self.client.add_router_interface_with_subnet_id(
+            router_id, subnet_id)
+        self.assertEqual('200', resp['status'])
+        self.addCleanup(self._remove_router_interface_with_subnet_id,
+                        router_id, subnet_id)
+        self.assertEqual(subnet_id, interface['subnet_id'])
+        return interface
+
     def _remove_router_interface_with_subnet_id(self, router_id, subnet_id):
         resp, body = self.client.remove_router_interface_with_subnet_id(
             router_id, subnet_id)
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index 673fc47..db24e0d 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -259,7 +259,7 @@
         self.assertEqual('200', resp['status'])
         member = body['member']
         for key, value in member.iteritems():
-             # 'status' should not be confirmed in api tests
+            # 'status' should not be confirmed in api tests
             if key != 'status':
                 self.assertEqual(self.member[key], value)
 
@@ -340,7 +340,7 @@
         self.assertEqual('200', resp['status'])
         health_monitor = body['health_monitor']
         for key, value in health_monitor.iteritems():
-             # 'status' should not be confirmed in api tests
+            # 'status' should not be confirmed in api tests
             if key != 'status':
                 self.assertEqual(self.health_monitor[key], value)
 
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 7605b8a..d38633f 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -300,9 +300,13 @@
 
     @test.attr(type='smoke')
     def test_add_multiple_router_interfaces(self):
-        network = self.create_network()
-        subnet01 = self.create_subnet(network)
-        subnet02 = self.create_subnet(network)
+        network01 = self.create_network(
+            network_name=data_utils.rand_name('router-network01-'))
+        network02 = self.create_network(
+            network_name=data_utils.rand_name('router-network02-'))
+        subnet01 = self.create_subnet(network01)
+        sub02_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr).next()
+        subnet02 = self.create_subnet(network02, cidr=sub02_cidr)
         router = self._create_router(data_utils.rand_name('router-'))
         interface01 = self._add_router_interface_with_subnet_id(router['id'],
                                                                 subnet01['id'])
@@ -313,15 +317,6 @@
         self._verify_router_interface(router['id'], subnet02['id'],
                                       interface02['port_id'])
 
-    def _add_router_interface_with_subnet_id(self, router_id, subnet_id):
-        resp, interface = self.client.add_router_interface_with_subnet_id(
-            router_id, subnet_id)
-        self.assertEqual('200', resp['status'])
-        self.addCleanup(self._remove_router_interface_with_subnet_id,
-                        router_id, subnet_id)
-        self.assertEqual(subnet_id, interface['subnet_id'])
-        return interface
-
     def _verify_router_interface(self, router_id, subnet_id, port_id):
         resp, show_port_body = self.client.show_port(port_id)
         self.assertEqual('200', resp['status'])
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 91ab9d6..feee51b 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -13,11 +13,16 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import netaddr
+
 from tempest.api.network import base_routers as base
 from tempest.common.utils import data_utils
+from tempest import config
 from tempest import exceptions
 from tempest import test
 
+CONF = config.CONF
+
 
 class RoutersNegativeTest(base.BaseRouterTest):
     _interface = 'json'
@@ -43,12 +48,30 @@
 
     @test.attr(type=['negative', 'smoke'])
     def test_router_add_gateway_net_not_external_returns_400(self):
-        self.create_subnet(self.network)
+        alt_network = self.create_network(
+            network_name=data_utils.rand_name('router-negative-'))
+        sub_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr).next()
+        self.create_subnet(alt_network, cidr=sub_cidr)
         self.assertRaises(exceptions.BadRequest,
                           self.client.update_router,
                           self.router['id'],
                           external_gateway_info={
-                              'network_id': self.network['id']})
+                              'network_id': alt_network['id']})
+
+    @test.attr(type=['negative', 'smoke'])
+    def test_add_router_interfaces_on_overlapping_subnets_returns_400(self):
+        network01 = self.create_network(
+            network_name=data_utils.rand_name('router-network01-'))
+        network02 = self.create_network(
+            network_name=data_utils.rand_name('router-network02-'))
+        subnet01 = self.create_subnet(network01)
+        subnet02 = self.create_subnet(network02)
+        self._add_router_interface_with_subnet_id(self.router['id'],
+                                                  subnet01['id'])
+        self.assertRaises(exceptions.BadRequest,
+                          self._add_router_interface_with_subnet_id,
+                          self.router['id'],
+                          subnet02['id'])
 
     @test.attr(type=['negative', 'smoke'])
     def test_router_remove_interface_in_use_returns_409(self):
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index 0b86398..53c9d12 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -55,7 +55,7 @@
     def test_create_security_group_rule_with_bad_protocol(self):
         group_create_body, _ = self._create_security_group()
 
-        #Create rule with bad protocol name
+        # Create rule with bad protocol name
         pname = 'bad_protocol_name'
         self.assertRaises(
             exceptions.BadRequest, self.client.create_security_group_rule,
@@ -66,7 +66,7 @@
     def test_create_security_group_rule_with_invalid_ports(self):
         group_create_body, _ = self._create_security_group()
 
-        #Create rule with invalid ports
+        # Create rule with invalid ports
         states = [(-16, 80, 'Invalid value for port -16'),
                   (80, 79, 'port_range_min must be <= port_range_max'),
                   (80, 65536, 'Invalid value for port 65536'),
diff --git a/tempest/api/network/test_vpnaas_extensions.py b/tempest/api/network/test_vpnaas_extensions.py
index a49e944..d1fe15c 100644
--- a/tempest/api/network/test_vpnaas_extensions.py
+++ b/tempest/api/network/test_vpnaas_extensions.py
@@ -16,6 +16,7 @@
 from tempest.api.network import base
 from tempest.common.utils import data_utils
 from tempest import config
+from tempest import exceptions
 from tempest import test
 
 CONF = config.CONF
@@ -53,6 +54,8 @@
                                                cls.router['id'])
         cls.ikepolicy = cls.create_ikepolicy(
             data_utils.rand_name("ike-policy-"))
+        cls.ipsecpolicy = cls.create_ipsecpolicy(
+            data_utils.rand_name("ipsec-policy-"))
 
     def _delete_ike_policy(self, ike_policy_id):
         # Deletes a ike policy and verifies if it is deleted or not
@@ -70,6 +73,20 @@
                 ike_id_list.append(i['id'])
             self.assertNotIn(ike_policy_id, ike_id_list)
 
+    def _delete_ipsec_policy(self, ipsec_policy_id):
+        # Deletes an ike policy if it exists
+        try:
+            self.client.delete_ipsecpolicy(ipsec_policy_id)
+
+        except exceptions.NotFound:
+            pass
+
+    def _assertExpected(self, expected, actual):
+        # Check if not expected keys/values exists in actual response body
+        for key, value in expected.iteritems():
+            self.assertIn(key, actual)
+            self.assertEqual(value, actual[key])
+
     @test.attr(type='smoke')
     def test_list_vpn_services(self):
         # Verify the VPN service exists in the list of all VPN services
@@ -177,6 +194,51 @@
         self.assertEqual(self.ikepolicy['ike_version'],
                          ikepolicy['ike_version'])
 
+    @test.attr(type='smoke')
+    def test_list_ipsec_policies(self):
+        # Verify the ipsec policy exists in the list of all ipsec policies
+        resp, body = self.client.list_ipsecpolicies()
+        self.assertEqual('200', resp['status'])
+        ipsecpolicies = body['ipsecpolicies']
+        self.assertIn(self.ipsecpolicy['id'], [i['id'] for i in ipsecpolicies])
+
+    @test.attr(type='smoke')
+    def test_create_update_delete_ipsec_policy(self):
+        # Creates an ipsec policy
+        ipsec_policy_body = {'name': data_utils.rand_name('ipsec-policy'),
+                             'pfs': 'group5',
+                             'encryption_algorithm': "aes-128",
+                             'auth_algorithm': 'sha1'}
+        resp, resp_body = self.client.create_ipsecpolicy(**ipsec_policy_body)
+        self.assertEqual('201', resp['status'])
+        ipsecpolicy = resp_body['ipsecpolicy']
+        self.addCleanup(self._delete_ipsec_policy, ipsecpolicy['id'])
+        self._assertExpected(ipsec_policy_body, ipsecpolicy)
+        # Verification of ipsec policy update
+        new_ipsec = {'description': 'Updated ipsec policy',
+                     'pfs': 'group2',
+                     'name': data_utils.rand_name("New-IPSec"),
+                     'encryption_algorithm': "aes-256",
+                     'lifetime': {'units': "seconds", 'value': '2000'}}
+        resp, body = self.client.update_ipsecpolicy(ipsecpolicy['id'],
+                                                    **new_ipsec)
+        self.assertEqual('200', resp['status'])
+        updated_ipsec_policy = body['ipsecpolicy']
+        self._assertExpected(new_ipsec, updated_ipsec_policy)
+        # Verification of ipsec policy delete
+        resp, _ = self.client.delete_ipsecpolicy(ipsecpolicy['id'])
+        self.assertEqual('204', resp['status'])
+        self.assertRaises(exceptions.NotFound,
+                          self.client.delete_ipsecpolicy, ipsecpolicy['id'])
+
+    @test.attr(type='smoke')
+    def test_show_ipsec_policy(self):
+        # Verifies the details of an ipsec policy
+        resp, body = self.client.show_ipsecpolicy(self.ipsecpolicy['id'])
+        self.assertEqual('200', resp['status'])
+        ipsecpolicy = body['ipsecpolicy']
+        self._assertExpected(self.ipsecpolicy, ipsecpolicy)
+
 
 class VPNaaSTestXML(VPNaaSTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 6bda83b..5f46d01 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -67,6 +67,7 @@
         super(ContainerSyncTest, cls).tearDownClass()
 
     @test.attr(type='slow')
+    @test.skip_because(bug='1317133')
     def test_container_synchronization(self):
         # container to container synchronization
         # to allow/accept sync requests to/from other accounts
diff --git a/tempest/api/orchestration/stacks/templates/cinder_basic.yaml b/tempest/api/orchestration/stacks/templates/cinder_basic.yaml
index 3e03a30..ffff580 100644
--- a/tempest/api/orchestration/stacks/templates/cinder_basic.yaml
+++ b/tempest/api/orchestration/stacks/templates/cinder_basic.yaml
@@ -6,6 +6,7 @@
         properties:
             size: 1
             description: a descriptive description
+            name: volume_name
 
 outputs:
   status:
@@ -20,5 +21,8 @@
     description: display_description
     value: { get_attr: ['volume', 'display_description'] }
 
+  display_name:
+    value: { get_attr: ['volume', 'display_name'] }
+
   volume_id:
     value: { get_resource: volume }
diff --git a/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml b/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml
index 08e3da4..b660c19 100644
--- a/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml
+++ b/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml
@@ -7,6 +7,7 @@
         properties:
             size: 1
             description: a descriptive description
+            name: volume_name
 
 outputs:
   status:
@@ -21,5 +22,8 @@
     description: display_description
     value: { get_attr: ['volume', 'display_description'] }
 
+  display_name:
+    value: { get_attr: ['volume', 'display_name'] }
+
   volume_id:
     value: { get_resource: volume }
diff --git a/tempest/api/orchestration/stacks/templates/neutron_basic.yaml b/tempest/api/orchestration/stacks/templates/neutron_basic.yaml
index 63b03f4..878ff68 100644
--- a/tempest/api/orchestration/stacks/templates/neutron_basic.yaml
+++ b/tempest/api/orchestration/stacks/templates/neutron_basic.yaml
@@ -8,10 +8,12 @@
     type: string
   ImageId:
     type: string
-  ExternalRouterId:
+  SubNetCidr:
     type: string
   ExternalNetworkId:
     type: string
+  DNSServers:
+    type: comma_delimited_list
   timeout:
     type: number
 resources:
@@ -25,21 +27,19 @@
       network_id: {Ref: Network}
       name: NewSubnet
       ip_version: 4
-      cidr: 10.0.3.0/24
-      dns_nameservers: ["8.8.8.8"]
-      allocation_pools:
-      - {end: 10.0.3.150, start: 10.0.3.20}
+      cidr: { get_param: SubNetCidr }
+      dns_nameservers: { get_param: DNSServers }
   Router:
     type: OS::Neutron::Router
     properties:
       name: NewRouter
-      admin_state_up: false
+      admin_state_up: true
       external_gateway_info:
         network: {get_param: ExternalNetworkId}
   RouterInterface:
     type: OS::Neutron::RouterInterface
     properties:
-      router_id: {get_param: ExternalRouterId}
+      router_id: {get_resource: Router}
       subnet_id: {get_resource: Subnet}
   Server:
     type: OS::Nova::Server
@@ -56,8 +56,8 @@
           template: |
             #!/bin/bash -v
 
-            /opt/aws/bin/cfn-signal -e 0 -r "SmokeServerNeutron created" \
-            'wait_handle'
+            while ! /opt/aws/bin/cfn-signal -e 0 -r "SmokeServerNeutron created" \
+            'wait_handle' ; do sleep 3; done
           params:
             wait_handle: {get_resource: WaitHandleNeutron}
   WaitHandleNeutron:
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 3086d78..e92b945 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -12,6 +12,7 @@
 
 
 import logging
+import netaddr
 
 from tempest.api.orchestration import base
 from tempest import clients
@@ -41,9 +42,12 @@
         template = cls.load_template('neutron_basic')
         cls.keypair_name = (CONF.orchestration.keypair_name or
                             cls._create_keypair()['name'])
-        cls.external_router_id = cls._get_external_router_id()
         cls.external_network_id = CONF.network.public_network_id
 
+        tenant_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+        mask_bits = CONF.network.tenant_network_mask_bits
+        cls.subnet_cidr = tenant_cidr.subnet(mask_bits).next()
+
         # create the stack
         cls.stack_identifier = cls.create_stack(
             cls.stack_name,
@@ -52,9 +56,10 @@
                 'KeyName': cls.keypair_name,
                 'InstanceType': CONF.orchestration.instance_type,
                 'ImageId': CONF.orchestration.image_ref,
-                'ExternalRouterId': cls.external_router_id,
                 'ExternalNetworkId': cls.external_network_id,
-                'timeout': CONF.orchestration.build_timeout
+                'timeout': CONF.orchestration.build_timeout,
+                'DNSServers': CONF.network.dns_servers,
+                'SubNetCidr': str(cls.subnet_cidr)
             })
         cls.stack_id = cls.stack_identifier.split('/')[1]
         try:
@@ -77,14 +82,6 @@
         for resource in resources:
             cls.test_resources[resource['logical_resource_id']] = resource
 
-    @classmethod
-    def _get_external_router_id(cls):
-        resp, body = cls.network_client.list_ports()
-        ports = body['ports']
-        router_ports = filter(lambda port: port['device_owner'] ==
-                              'network:router_interface', ports)
-        return router_ports[0]['device_id']
-
     @test.attr(type='slow')
     def test_created_resources(self):
         """Verifies created neutron resources."""
@@ -121,11 +118,10 @@
         self.assertEqual(subnet_id, subnet['id'])
         self.assertEqual(network_id, subnet['network_id'])
         self.assertEqual('NewSubnet', subnet['name'])
-        self.assertEqual('8.8.8.8', subnet['dns_nameservers'][0])
-        self.assertEqual('10.0.3.20', subnet['allocation_pools'][0]['start'])
-        self.assertEqual('10.0.3.150', subnet['allocation_pools'][0]['end'])
+        self.assertEqual(sorted(CONF.network.dns_servers),
+                         sorted(subnet['dns_nameservers']))
         self.assertEqual(4, subnet['ip_version'])
-        self.assertEqual('10.0.3.0/24', subnet['cidr'])
+        self.assertEqual(str(self.subnet_cidr), subnet['cidr'])
 
     @test.attr(type='slow')
     def test_created_router(self):
@@ -137,18 +133,19 @@
         self.assertEqual('NewRouter', router['name'])
         self.assertEqual(self.external_network_id,
                          router['external_gateway_info']['network_id'])
-        self.assertEqual(False, router['admin_state_up'])
+        self.assertEqual(True, router['admin_state_up'])
 
     @test.attr(type='slow')
     def test_created_router_interface(self):
         """Verifies created router interface."""
+        router_id = self.test_resources.get('Router')['physical_resource_id']
         network_id = self.test_resources.get('Network')['physical_resource_id']
         subnet_id = self.test_resources.get('Subnet')['physical_resource_id']
         resp, body = self.network_client.list_ports()
         self.assertEqual('200', resp['status'])
         ports = body['ports']
         router_ports = filter(lambda port: port['device_id'] ==
-                              self.external_router_id, ports)
+                              router_id, ports)
         created_network_ports = filter(lambda port: port['network_id'] ==
                                        network_id, router_ports)
         self.assertEqual(1, len(created_network_ports))
@@ -158,7 +155,8 @@
                                   subnet_id, fixed_ips)
         self.assertEqual(1, len(subnet_fixed_ips))
         router_interface_ip = subnet_fixed_ips[0]['ip_address']
-        self.assertEqual('10.0.3.1', router_interface_ip)
+        self.assertEqual(str(self.subnet_cidr.iter_hosts().next()),
+                         router_interface_ip)
 
     @test.attr(type='slow')
     def test_created_server(self):
@@ -170,8 +168,4 @@
         self.assertEqual('ACTIVE', server['status'])
         network = server['addresses']['NewNetwork'][0]
         self.assertEqual(4, network['version'])
-        ip_addr_prefix = network['addr'][:7]
-        ip_addr_suffix = int(network['addr'].split('.')[3])
-        self.assertEqual('10.0.3.', ip_addr_prefix)
-        self.assertTrue(ip_addr_suffix >= 20)
-        self.assertTrue(ip_addr_suffix <= 150)
+        self.assertIn(netaddr.IPAddress(network['addr']), self.subnet_cidr)
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index cb70d07..a81a540 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -68,13 +68,13 @@
         output_map = {}
         for outputs in stack['outputs']:
             output_map[outputs['output_key']] = outputs['output_value']
-        #Test that first key generated public and private keys
+        # Test that first key generated public and private keys
         self.assertTrue('KeyPair_PublicKey' in output_map)
         self.assertTrue("Generated" in output_map['KeyPair_PublicKey'])
         self.assertTrue('KeyPair_PrivateKey' in output_map)
         self.assertTrue('-----BEGIN' in output_map['KeyPair_PrivateKey'])
-        #Test that second key generated public key, and private key is not
-        #in the output due to save_private_key = false
+        # Test that second key generated public key, and private key is not
+        # in the output due to save_private_key = false
         self.assertTrue('KeyPairDontSavePrivate_PublicKey' in output_map)
         self.assertTrue('Generated' in
                         output_map['KeyPairDontSavePrivate_PublicKey'])
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index 2544c41..5ac2a8d 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -39,6 +39,8 @@
         self.assertEqual(1, volume.get('size'))
         self.assertEqual('a descriptive description',
                          volume.get('display_description'))
+        self.assertEqual('volume_name',
+                         volume.get('display_name'))
 
     def _outputs_verify(self, stack_identifier):
         self.assertEqual('available',
@@ -48,6 +50,9 @@
         self.assertEqual('a descriptive description',
                          self.get_stack_output(stack_identifier,
                                                'display_description'))
+        self.assertEqual('volume_name',
+                         self.get_stack_output(stack_identifier,
+                                               'display_name'))
 
     @test.attr(type='gate')
     def test_cinder_volume_create_delete(self):
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index c4614c6..2b422fd 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -10,9 +10,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
+
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
+from tempest.openstack.common import timeutils
 import tempest.test
 
 CONF = config.CONF
@@ -29,6 +32,12 @@
         super(BaseTelemetryTest, cls).setUpClass()
         os = cls.get_client_manager()
         cls.telemetry_client = os.telemetry_client
+        cls.servers_client = os.servers_client
+        cls.flavors_client = os.flavors_client
+
+        cls.nova_notifications = ['memory', 'vcpus', 'disk.root.size',
+                                  'disk.ephemeral.size']
+        cls.server_ids = []
         cls.alarm_ids = []
 
     @classmethod
@@ -41,11 +50,46 @@
         return resp, body
 
     @classmethod
-    def tearDownClass(cls):
-        for alarm_id in cls.alarm_ids:
+    def create_server(cls):
+        resp, body = cls.servers_client.create_server(
+            data_utils.rand_name('ceilometer-instance'),
+            CONF.compute.image_ref, CONF.compute.flavor_ref,
+            wait_until='ACTIVE')
+        if resp['status'] == '202':
+            cls.server_ids.append(body['id'])
+        return resp, body
+
+    @staticmethod
+    def cleanup_resources(method, list_of_ids):
+        for resource_id in list_of_ids:
             try:
-                cls.telemetry_client.delete_alarm(alarm_id)
+                method(resource_id)
             except exceptions.NotFound:
                 pass
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.cleanup_resources(cls.telemetry_client.delete_alarm, cls.alarm_ids)
+        cls.cleanup_resources(cls.servers_client.delete_server, cls.server_ids)
         cls.clear_isolated_creds()
         super(BaseTelemetryTest, cls).tearDownClass()
+
+    def await_samples(self, metric, query):
+        """
+        This method is to wait for sample to add it to database.
+        There are long time delays when using Postgresql (or Mysql)
+        database as ceilometer backend
+        """
+        timeout = CONF.compute.build_timeout
+        start = timeutils.utcnow()
+        while timeutils.delta_seconds(start, timeutils.utcnow()) < timeout:
+            resp, body = self.telemetry_client.list_samples(metric, query)
+            self.assertEqual(resp.status, 200)
+            if body:
+                return resp, body
+            time.sleep(CONF.compute.build_interval)
+
+        raise exceptions.TimeoutException(
+            'Sample for metric:%s with query:%s has not been added to the '
+            'database within %d seconds' % (metric, query,
+                                            CONF.compute.build_timeout))
diff --git a/tempest/api/telemetry/test_telemetry_notification_api.py b/tempest/api/telemetry/test_telemetry_notification_api.py
new file mode 100644
index 0000000..148f5a3
--- /dev/null
+++ b/tempest/api/telemetry/test_telemetry_notification_api.py
@@ -0,0 +1,47 @@
+#    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 testtools
+
+from tempest.api.telemetry import base
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class TelemetryNotificationAPITestJSON(base.BaseTelemetryTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        if CONF.telemetry.too_slow_to_test:
+            raise cls.skipException("Ceilometer feature for fast work mysql "
+                                    "is disabled")
+        super(TelemetryNotificationAPITestJSON, cls).setUpClass()
+
+    @test.attr(type="gate")
+    @testtools.skipIf(not CONF.service_available.nova,
+                      "Nova is not available.")
+    def test_check_nova_notification(self):
+
+        resp, body = self.create_server()
+        self.assertEqual(resp.status, 202)
+
+        query = ('resource', 'eq', body['id'])
+
+        for metric in self.nova_notifications:
+            self.await_samples(metric, query)
+
+
+class TelemetryNotificationAPITestXML(TelemetryNotificationAPITestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index ee1d09a..3b8c214 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -118,14 +118,16 @@
                          'from the created Volume_type')
 
     @test.attr(type='smoke')
-    def test_volume_type_encryption_create_get(self):
-        # Create/get encryption type.
+    def test_volume_type_encryption_create_get_delete(self):
+        # Create/get/delete encryption type.
         provider = "LuksEncryptor"
         control_location = "front-end"
         name = data_utils.rand_name("volume-type-")
         resp, body = self.client.create_volume_type(name)
         self.assertEqual(200, resp.status)
         self.addCleanup(self._delete_volume_type, body['id'])
+
+        # Create encryption type
         resp, encryption_type = self.client.create_encryption_type(
             body['id'], provider=provider,
             control_location=control_location)
@@ -137,6 +139,8 @@
         self.assertEqual(control_location, encryption_type['control_location'],
                          "The created encryption_type control_location is not "
                          "equal to the requested control_location")
+
+        # Get encryption type
         resp, fetched_encryption_type = self.client.get_encryption_type(
             encryption_type['volume_type_id'])
         self.assertEqual(200, resp.status)
@@ -148,3 +152,15 @@
                          fetched_encryption_type['control_location'],
                          'The fetched encryption_type control_location is '
                          'different from the created encryption_type')
+
+        # Delete encryption type
+        resp, _ = self.client.delete_encryption_type(
+            encryption_type['volume_type_id'])
+        self.assertEqual(202, resp.status)
+        resource = {"id": encryption_type['volume_type_id'],
+                    "type": "encryption-type"}
+        self.client.wait_for_resource_deletion(resource)
+        resp, deleted_encryption_type = self.client.get_encryption_type(
+            encryption_type['volume_type_id'])
+        self.assertEqual(200, resp.status)
+        self.assertEmpty(deleted_encryption_type)
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index d3a052e..da421dc 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -29,9 +29,9 @@
         super(ExtraSpecsNegativeTest, cls).setUpClass()
         vol_type_name = data_utils.rand_name('Volume-type-')
         cls.extra_specs = {"spec1": "val1"}
-        resp, cls.volume_type = cls.client.create_volume_type(vol_type_name,
-                                                              extra_specs=
-                                                              cls.extra_specs)
+        resp, cls.volume_type = cls.client.create_volume_type(
+            vol_type_name,
+            extra_specs=cls.extra_specs)
 
     @classmethod
     def tearDownClass(cls):
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 67d0203..2a9b407 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -16,6 +16,7 @@
 from tempest import clients
 from tempest.common.utils import data_utils
 from tempest import config
+from tempest import exceptions
 from tempest.openstack.common import log as logging
 import tempest.test
 
@@ -25,9 +26,11 @@
 
 
 class BaseVolumeTest(tempest.test.BaseTestCase):
-
     """Base test case class for all Cinder API tests."""
 
+    _api_version = 2
+    _interface = 'json'
+
     @classmethod
     def setUpClass(cls):
         cls.set_network_resources()
@@ -47,6 +50,28 @@
         cls.snapshots = []
         cls.volumes = []
 
+        if cls._api_version == 1:
+            if not CONF.volume_feature_enabled.api_v1:
+                msg = "Volume API v1 is disabled"
+                raise cls.skipException(msg)
+            cls.snapshots_client = cls.os.snapshots_client
+            cls.volumes_client = cls.os.volumes_client
+            cls.backups_client = cls.os.backups_client
+            cls.volume_services_client = cls.os.volume_services_client
+            cls.volumes_extension_client = cls.os.volumes_extension_client
+            cls.availability_zone_client = (
+                cls.os.volume_availability_zone_client)
+
+        elif cls._api_version == 2:
+            if not CONF.volume_feature_enabled.api_v2:
+                msg = "Volume API v2 is disabled"
+                raise cls.skipException(msg)
+            cls.volumes_client = cls.os.volumes_v2_client
+
+        else:
+            msg = ("Invalid Cinder API version (%s)" % cls._api_version)
+            raise exceptions.InvalidConfiguration(message=msg)
+
     @classmethod
     def tearDownClass(cls):
         cls.clear_snapshots()
@@ -55,6 +80,22 @@
         super(BaseVolumeTest, cls).tearDownClass()
 
     @classmethod
+    def create_volume(cls, size=1, **kwargs):
+        """Wrapper utility that returns a test volume."""
+        vol_name = data_utils.rand_name('Volume')
+        if cls._api_version == 1:
+            resp, volume = cls.volumes_client.create_volume(
+                size, display_name=vol_name, **kwargs)
+            assert 200 == resp.status
+        elif cls._api_version == 2:
+            resp, volume = cls.volumes_client.create_volume(
+                size, name=vol_name, **kwargs)
+            assert 202 == resp.status
+        cls.volumes.append(volume)
+        cls.volumes_client.wait_for_volume_status(volume['id'], 'available')
+        return volume
+
+    @classmethod
     def create_snapshot(cls, volume_id=1, **kwargs):
         """Wrapper utility that returns a test snapshot."""
         resp, snapshot = cls.snapshots_client.create_snapshot(volume_id,
@@ -98,30 +139,11 @@
 
 
 class BaseVolumeV1Test(BaseVolumeTest):
-    @classmethod
-    def setUpClass(cls):
-        if not CONF.volume_feature_enabled.api_v1:
-            msg = "Volume API v1 not supported"
-            raise cls.skipException(msg)
-        super(BaseVolumeV1Test, cls).setUpClass()
-        cls.snapshots_client = cls.os.snapshots_client
-        cls.volumes_client = cls.os.volumes_client
-        cls.backups_client = cls.os.backups_client
-        cls.volume_services_client = cls.os.volume_services_client
-        cls.volumes_extension_client = cls.os.volumes_extension_client
-        cls.availability_zone_client = cls.os.volume_availability_zone_client
+    _api_version = 1
 
-    @classmethod
-    def create_volume(cls, size=1, **kwargs):
-        """Wrapper utility that returns a test volume."""
-        vol_name = data_utils.rand_name('Volume')
-        resp, volume = cls.volumes_client.create_volume(size,
-                                                        display_name=vol_name,
-                                                        **kwargs)
-        assert 200 == resp.status
-        cls.volumes.append(volume)
-        cls.volumes_client.wait_for_volume_status(volume['id'], 'available')
-        return volume
+
+class BaseVolumeV2Test(BaseVolumeTest):
+    _api_version = 2
 
 
 class BaseVolumeV1AdminTest(BaseVolumeV1Test):
@@ -144,25 +166,3 @@
         cls.client = cls.os_adm.volume_types_client
         cls.hosts_client = cls.os_adm.volume_hosts_client
         cls.quotas_client = cls.os_adm.volume_quotas_client
-
-
-class BaseVolumeV2Test(BaseVolumeTest):
-    @classmethod
-    def setUpClass(cls):
-        if not CONF.volume_feature_enabled.api_v2:
-            msg = "Volume API v2 not supported"
-            raise cls.skipException(msg)
-        super(BaseVolumeV2Test, cls).setUpClass()
-        cls.volumes_client = cls.os.volumes_v2_client
-
-    @classmethod
-    def create_volume(cls, size=1, **kwargs):
-        """Wrapper utility that returns a test volume."""
-        vol_name = data_utils.rand_name('Volume')
-        resp, volume = cls.volumes_client.create_volume(size,
-                                                        name=vol_name,
-                                                        **kwargs)
-        assert 202 == resp.status
-        cls.volumes.append(volume)
-        cls.volumes_client.wait_for_volume_status(volume['id'], 'available')
-        return volume
diff --git a/tempest/api/volume/test_availability_zone.py b/tempest/api/volume/test_availability_zone.py
index 1db7b7b..fe8f96e 100644
--- a/tempest/api/volume/test_availability_zone.py
+++ b/tempest/api/volume/test_availability_zone.py
@@ -22,6 +22,7 @@
     """
     Tests Availability Zone API List
     """
+    _interface = 'json'
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 58da440..2745b95 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -39,7 +39,7 @@
     def _is_true(self, val):
         # NOTE(jdg): Temporary conversion method to get cinder patch
         # merged.  Then we'll make this strict again and
-        #specifically check "true" or "false"
+        # specifically check "true" or "false"
         if val in ['true', 'True', True]:
             return True
         else:
@@ -121,19 +121,19 @@
         new_volume = {}
         new_v_desc = data_utils.rand_name('@#$%^* description')
         resp, new_volume = \
-            self.client.create_volume(size=1,
-                                      display_description=new_v_desc,
-                                      availability_zone=
-                                      volume['availability_zone'])
+            self.client.create_volume(
+                size=1,
+                display_description=new_v_desc,
+                availability_zone=volume['availability_zone'])
         self.assertEqual(200, resp.status)
         self.assertIn('id', new_volume)
         self.addCleanup(self._delete_volume, new_volume['id'])
         self.client.wait_for_volume_status(new_volume['id'], 'available')
         resp, update_volume = \
-            self.client.update_volume(new_volume['id'],
-                                      display_name=volume['display_name'],
-                                      display_description=
-                                      volume['display_description'])
+            self.client.update_volume(
+                new_volume['id'],
+                display_name=volume['display_name'],
+                display_description=volume['display_description'])
         self.assertEqual(200, resp.status)
 
         # NOTE(jdg): Revert back to strict true/false checking
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index a8b0a8d..bc5b1dc 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -154,6 +154,7 @@
         self.assertRaises(exceptions.NotFound, self.client.delete_volume, '')
 
     @test.attr(type=['negative', 'gate'])
+    @test.services('compute')
     def test_attach_volumes_with_nonexistent_volume_id(self):
         srv_name = data_utils.rand_name('Instance-')
         resp, server = self.servers_client.create_server(srv_name,
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 6294cd9..26316d2 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -63,6 +63,7 @@
                 self.assertEqual(params[key], snap[key], msg)
 
     @test.attr(type='gate')
+    @test.services('compute')
     def test_snapshot_create_with_volume_in_use(self):
         # Create a snapshot when volume status is in-use
         # Create a test instance
diff --git a/tempest/api_schema/compute/servers.py b/tempest/api_schema/compute/servers.py
index 2002927..14e9ce9 100644
--- a/tempest/api_schema/compute/servers.py
+++ b/tempest/api_schema/compute/servers.py
@@ -84,11 +84,16 @@
                     'links': parameter_types.links,
                     'addresses': parameter_types.addresses,
                 },
+                # NOTE(GMann): 'progress' attribute is present in the response
+                # only when server's status is one of the progress statuses
+                # ("ACTIVE","BUILD", "REBUILD", "RESIZE","VERIFY_RESIZE")
+                # So it is not defined as 'required'.
                 'required': ['id', 'name', 'status', 'image', 'flavor',
                              'user_id', 'tenant_id', 'created', 'updated',
-                             'progress', 'metadata', 'links', 'addresses']
+                             'metadata', 'links', 'addresses']
             }
-        }
+        },
+        'required': ['server']
     }
 }
 
@@ -114,6 +119,8 @@
 
 list_server_metadata = copy.deepcopy(set_server_metadata)
 
+update_server_metadata = copy.deepcopy(set_server_metadata)
+
 delete_server_metadata_item = {
     'status_code': [204]
 }
@@ -158,3 +165,17 @@
         'required': ['output']
     }
 }
+
+common_instance_actions = {
+    'type': 'object',
+    'properties': {
+        'action': {'type': 'string'},
+        'request_id': {'type': 'string'},
+        'user_id': {'type': 'string'},
+        'project_id': {'type': 'string'},
+        'start_time': {'type': 'string'},
+        'message': {'type': ['string', 'null']}
+    },
+    'required': ['action', 'request_id', 'user_id', 'project_id',
+                 'start_time', 'message']
+}
diff --git a/tempest/api_schema/compute/v2/floating_ips.py b/tempest/api_schema/compute/v2/floating_ips.py
index 3ea6320..03e6aef 100644
--- a/tempest/api_schema/compute/v2/floating_ips.py
+++ b/tempest/api_schema/compute/v2/floating_ips.py
@@ -98,3 +98,22 @@
 add_remove_floating_ip = {
     'status_code': [202]
 }
+
+create_floating_ips_bulk = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'floating_ips_bulk_create': {
+                'type': 'object',
+                'properties': {
+                    'interface': {'type': ['string', 'null']},
+                    'ip_range': {'type': 'string'},
+                    'pool': {'type': ['string', 'null']},
+                },
+                'required': ['interface', 'ip_range', 'pool']
+            }
+        },
+        'required': ['floating_ips_bulk_create']
+    }
+}
diff --git a/tempest/api_schema/compute/v2/servers.py b/tempest/api_schema/compute/v2/servers.py
index 981d8f7..fe53abd 100644
--- a/tempest/api_schema/compute/v2/servers.py
+++ b/tempest/api_schema/compute/v2/servers.py
@@ -142,3 +142,57 @@
         'required': ['addresses']
     }
 }
+
+common_server_group = {
+    'type': 'object',
+    'properties': {
+        'id': {'type': 'string'},
+        'name': {'type': 'string'},
+        'policies': {
+            'type': 'array',
+            'items': {'type': 'string'}
+        },
+        # 'members' attribute contains the array of instance's UUID of
+        # instances present in server group
+        'members': {
+            'type': 'array',
+            'items': {'type': 'string'}
+        },
+        'metadata': {'type': 'object'}
+    },
+    'required': ['id', 'name', 'policies', 'members', 'metadata']
+}
+
+create_get_server_group = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'server_group': common_server_group
+        },
+        'required': ['server_group']
+    }
+}
+
+delete_server_group = {
+    'status_code': [204]
+}
+
+instance_actions_object = copy.deepcopy(servers.common_instance_actions)
+instance_actions_object[
+    'properties'].update({'instance_uuid': {'type': 'string'}})
+instance_actions_object['required'].extend(['instance_uuid'])
+
+list_instance_actions = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'instanceActions': {
+                'type': 'array',
+                'items': instance_actions_object
+            }
+        },
+        'required': ['instanceActions']
+    }
+}
diff --git a/tempest/api_schema/compute/v3/servers.py b/tempest/api_schema/compute/v3/servers.py
index 682021f..4fb2d87 100644
--- a/tempest/api_schema/compute/v3/servers.py
+++ b/tempest/api_schema/compute/v3/servers.py
@@ -95,3 +95,25 @@
         'required': ['addresses']
     }
 }
+
+update_server_metadata = copy.deepcopy(servers.update_server_metadata)
+# V3 API's response status_code is 201
+update_server_metadata['status_code'] = [201]
+
+server_actions_object = copy.deepcopy(servers.common_instance_actions)
+server_actions_object['properties'].update({'server_uuid': {'type': 'string'}})
+server_actions_object['required'].extend(['server_uuid'])
+
+list_server_actions = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'server_actions': {
+                'type': 'array',
+                'items': server_actions_object
+            }
+        },
+        'required': ['server_actions']
+    }
+}
diff --git a/tempest/cli/simple_read_only/test_cinder.py b/tempest/cli/simple_read_only/test_cinder.py
index 723333b..e9a0cee 100644
--- a/tempest/cli/simple_read_only/test_cinder.py
+++ b/tempest/cli/simple_read_only/test_cinder.py
@@ -118,6 +118,12 @@
     def test_cinder_bash_completion(self):
         self.cinder('bash-completion')
 
+    def test_cinder_qos_list(self):
+        self.cinder('qos-list')
+
+    def test_cinder_encryption_type_list(self):
+        self.cinder('encryption-type-list')
+
     def test_admin_help(self):
         help_text = self.cinder('help')
         lines = help_text.split('\n')
@@ -136,7 +142,7 @@
                                'quota-show', 'type-list', 'snapshot-list'))
         self.assertFalse(wanted_commands - commands)
 
-     # Optional arguments:
+    # Optional arguments:
 
     def test_cinder_version(self):
         self.cinder('', flags='--version')
diff --git a/tempest/cli/simple_read_only/test_keystone.py b/tempest/cli/simple_read_only/test_keystone.py
index 1efbede..dda65c1 100644
--- a/tempest/cli/simple_read_only/test_keystone.py
+++ b/tempest/cli/simple_read_only/test_keystone.py
@@ -117,6 +117,11 @@
     def test_admin_bashcompletion(self):
         self.keystone('bash-completion')
 
+    def test_admin_ec2_credentials_list(self):
+        creds = self.keystone('ec2-credentials-list')
+        creds = self.parser.listing(creds)
+        self.assertTableStruct(creds, ['tenant', 'access', 'secret'])
+
     # Optional arguments:
 
     def test_admin_version(self):
diff --git a/tempest/cli/simple_read_only/test_nova.py b/tempest/cli/simple_read_only/test_nova.py
index a3787ab..1c1ddf1 100644
--- a/tempest/cli/simple_read_only/test_nova.py
+++ b/tempest/cli/simple_read_only/test_nova.py
@@ -145,6 +145,9 @@
     def test_admin_secgroup_list_rules(self):
         self.nova('secgroup-list-rules')
 
+    def test_admin_server_group_list(self):
+        self.nova('server-group-list')
+
     def test_admin_servce_list(self):
         self.nova('service-list')
 
diff --git a/tempest/clients.py b/tempest/clients.py
index 7745d54..4050a20 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -129,6 +129,7 @@
     IdentityV3ClientJSON
 from tempest.services.identity.v3.json.identity_client import V3TokenClientJSON
 from tempest.services.identity.v3.json.policy_client import PolicyClientJSON
+from tempest.services.identity.v3.json.region_client import RegionClientJSON
 from tempest.services.identity.v3.json.service_client import \
     ServiceClientJSON
 from tempest.services.identity.v3.xml.credentials_client import \
@@ -138,6 +139,7 @@
     IdentityV3ClientXML
 from tempest.services.identity.v3.xml.identity_client import V3TokenClientXML
 from tempest.services.identity.v3.xml.policy_client import PolicyClientXML
+from tempest.services.identity.v3.xml.region_client import RegionClientXML
 from tempest.services.identity.v3.xml.service_client import \
     ServiceClientXML
 from tempest.services.identity.xml.identity_client import IdentityClientXML
@@ -248,6 +250,7 @@
             self.tenant_usages_client = TenantUsagesClientXML(
                 self.auth_provider)
             self.policy_client = PolicyClientXML(self.auth_provider)
+            self.region_client = RegionClientXML(self.auth_provider)
             self.hosts_client = HostsClientXML(self.auth_provider)
             self.hypervisor_client = HypervisorClientXML(self.auth_provider)
             self.network_client = NetworkClientXML(self.auth_provider)
@@ -334,6 +337,7 @@
             self.migrations_v3_client = MigrationsV3ClientJSON(
                 self.auth_provider)
             self.policy_client = PolicyClientJSON(self.auth_provider)
+            self.region_client = RegionClientJSON(self.auth_provider)
             self.hosts_client = HostsClientJSON(self.auth_provider)
             self.hypervisor_v3_client = HypervisorV3ClientJSON(
                 self.auth_provider)
@@ -452,6 +456,7 @@
     HEATCLIENT_VERSION = '1'
     IRONICCLIENT_VERSION = '1'
     SAHARACLIENT_VERSION = '1.1'
+    CEILOMETERCLIENT_VERSION = '2'
 
     def __init__(self, credentials):
         # FIXME(andreaf) Auth provider for client_type 'official' is
@@ -472,6 +477,8 @@
             credentials)
         self.data_processing_client = self._get_data_processing_client(
             credentials)
+        self.ceilometer_client = self._get_ceilometer_client(
+            credentials)
 
     def _get_roles(self):
         admin_credentials = auth.get_default_credentials('identity_admin')
@@ -692,3 +699,34 @@
             auth_url=auth_url)
 
         return client
+
+    def _get_ceilometer_client(self, credentials):
+        if not CONF.service_available.ceilometer:
+            return None
+
+        import ceilometerclient.client
+
+        keystone = self._get_identity_client(credentials)
+        region = CONF.identity.region
+
+        endpoint_type = CONF.telemetry.endpoint_type
+        service_type = CONF.telemetry.catalog_type
+        auth_url = CONF.identity.uri
+
+        try:
+            keystone.service_catalog.url_for(
+                attr='region',
+                filter_value=region,
+                service_type=service_type,
+                endpoint_type=endpoint_type)
+        except keystoneclient.exceptions.EndpointNotFound:
+            return None
+        else:
+            return ceilometerclient.client.get_client(
+                self.CEILOMETERCLIENT_VERSION,
+                os_username=credentials.username,
+                os_password=credentials.password,
+                os_tenant_name=credentials.tenant_name,
+                os_auth_url=auth_url,
+                os_service_type=service_type,
+                os_endpoint_type=endpoint_type)
diff --git a/tempest/stress/run_stress.py b/tempest/cmd/run_stress.py
similarity index 96%
rename from tempest/stress/run_stress.py
rename to tempest/cmd/run_stress.py
index c7c17c0..07f3f66 100755
--- a/tempest/stress/run_stress.py
+++ b/tempest/cmd/run_stress.py
@@ -51,7 +51,7 @@
         except Exception:
             next
         if 'stress' in attrs:
-            if filter_attr is not None and not filter_attr in attrs:
+            if filter_attr is not None and filter_attr not in attrs:
                 continue
             class_setup_per = getattr(test_func, "st_class_setup_per")
 
@@ -70,7 +70,29 @@
     return tests
 
 
-def main(ns):
+parser = argparse.ArgumentParser(description='Run stress tests')
+parser.add_argument('-d', '--duration', default=300, type=int,
+                    help="Duration of test in secs")
+parser.add_argument('-s', '--serial', action='store_true',
+                    help="Trigger running tests serially")
+parser.add_argument('-S', '--stop', action='store_true',
+                    default=False, help="Stop on first error")
+parser.add_argument('-n', '--number', type=int,
+                    help="How often an action is executed for each process")
+group = parser.add_mutually_exclusive_group(required=True)
+group.add_argument('-a', '--all', action='store_true',
+                   help="Execute all stress tests")
+parser.add_argument('-T', '--type',
+                    help="Filters tests of a certain type (e.g. gate)")
+parser.add_argument('-i', '--call-inherited', action='store_true',
+                    default=False,
+                    help="Call also inherited function with stress attribute")
+group.add_argument('-t', "--tests", nargs='?',
+                   help="Name of the file with test description")
+
+
+def main():
+    ns = parser.parse_args()
     result = 0
     if not ns.all:
         tests = json.load(open(ns.tests, 'r'))
@@ -97,29 +119,9 @@
     return result
 
 
-parser = argparse.ArgumentParser(description='Run stress tests')
-parser.add_argument('-d', '--duration', default=300, type=int,
-                    help="Duration of test in secs")
-parser.add_argument('-s', '--serial', action='store_true',
-                    help="Trigger running tests serially")
-parser.add_argument('-S', '--stop', action='store_true',
-                    default=False, help="Stop on first error")
-parser.add_argument('-n', '--number', type=int,
-                    help="How often an action is executed for each process")
-group = parser.add_mutually_exclusive_group(required=True)
-group.add_argument('-a', '--all', action='store_true',
-                   help="Execute all stress tests")
-parser.add_argument('-T', '--type',
-                    help="Filters tests of a certain type (e.g. gate)")
-parser.add_argument('-i', '--call-inherited', action='store_true',
-                    default=False,
-                    help="Call also inherited function with stress attribute")
-group.add_argument('-t', "--tests", nargs='?',
-                   help="Name of the file with test description")
-
 if __name__ == "__main__":
     try:
-        sys.exit(main(parser.parse_args()))
+        sys.exit(main())
     except Exception:
         LOG.exception("Failure in the stress test framework")
         sys.exit(1)
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 7b2e60b..0834cff 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -21,7 +21,7 @@
 import urlparse
 
 import httplib2
-from six.moves import configparser
+from six import moves
 
 from tempest import clients
 from tempest import config
@@ -46,7 +46,7 @@
 
 
 def change_option(option, group, value):
-    config_parse = configparser.SafeConfigParser()
+    config_parse = moves.configparser.SafeConfigParser()
     config_parse.optionxform = str
     config_parse.readfp(CONF_FILE)
     if not config_parse.has_section(group):
@@ -160,11 +160,10 @@
     extensions_client = get_extension_client(os, service)
     __, resp = extensions_client.list_extensions()
     if isinstance(resp, dict):
-        # Neutron's extension 'name' field has is not a single word (it has
-        # spaces in the string) Since that can't be used for list option the
-        # api_extension option in the network-feature-enabled group uses alias
-        # instead of name.
-        if service == 'neutron':
+        # For both Nova and Neutron we use the alias name rather than the
+        # 'name' field because the alias is considered to be the canonical
+        # name.
+        if service in ['nova', 'nova_v3', 'neutron']:
             extensions = map(lambda x: x['alias'], resp['extensions'])
         elif service == 'swift':
             # Remove Swift general information from extensions list
diff --git a/tempest/common/glance_http.py b/tempest/common/glance_http.py
index 9358851..55aca5a 100644
--- a/tempest/common/glance_http.py
+++ b/tempest/common/glance_http.py
@@ -160,6 +160,9 @@
     def json_request(self, method, url, **kwargs):
         kwargs.setdefault('headers', {})
         kwargs['headers'].setdefault('Content-Type', 'application/json')
+        if kwargs['headers']['Content-Type'] != 'application/json':
+            msg = "Only application/json content-type is supported."
+            raise exc.InvalidContentType(msg)
 
         if 'body' in kwargs:
             kwargs['body'] = json.dumps(kwargs['body'])
@@ -173,7 +176,8 @@
             except ValueError:
                 LOG.error('Could not decode response body as JSON')
         else:
-            body = None
+            msg = "Only json/application content-type is supported."
+            raise exc.InvalidContentType(msg)
 
         return resp, body
 
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 3c527f5..33128a9 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -191,17 +191,25 @@
         """
         self._skip_path = False
 
-    def expected_success(self, expected_code, read_code):
+    @classmethod
+    def expected_success(cls, expected_code, read_code):
         assert_msg = ("This function only allowed to use for HTTP status"
                       "codes which explicitly defined in the RFC 2616. {0}"
                       " is not a defined Success Code!").format(expected_code)
-        assert expected_code in HTTP_SUCCESS, assert_msg
+        if isinstance(expected_code, list):
+            for code in expected_code:
+                assert code in HTTP_SUCCESS, assert_msg
+        else:
+            assert expected_code in HTTP_SUCCESS, assert_msg
 
         # NOTE(afazekas): the http status code above 400 is processed by
         # the _error_checker method
-        if read_code < 400 and read_code != expected_code:
-                pattern = """Unexpected http success status code {0},
-                             The expected status code is {1}"""
+        if read_code < 400:
+            pattern = """Unexpected http success status code {0},
+                         The expected status code is {1}"""
+            if ((not isinstance(expected_code, list) and
+                (read_code != expected_code)) or (isinstance(expected_code,
+                list) and (read_code not in expected_code))):
                 details = pattern.format(read_code, expected_code)
                 raise exceptions.InvalidHttpSuccessCode(details)
 
@@ -555,11 +563,7 @@
         # declared in the V3 API and so we should be able to export this in
         # the response schema. For now we'll ignore it.
         if resp.status in HTTP_SUCCESS:
-            response_code = schema['status_code']
-            if resp.status not in response_code:
-                msg = ("The status code(%s) is different than the expected "
-                       "one(%s)") % (resp.status, response_code)
-                raise exceptions.InvalidHttpSuccessCode(msg)
+            cls.expected_success(schema['status_code'], resp.status)
 
             # Check the body of a response
             body_schema = schema.get('response_body')
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 95b6833..57a14a2 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -57,11 +57,6 @@
         actual_hostname = self.exec_command("hostname").rstrip()
         return expected_hostname == actual_hostname
 
-    def get_files(self, path):
-        # Return a list of comma separated files
-        command = "ls -m " + path
-        return self.exec_command(command).rstrip('\n').split(', ')
-
     def get_ram_size_in_mb(self):
         output = self.exec_command('free -m | grep Mem')
         if output:
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index d52ed7c..d8474a0 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -22,6 +22,16 @@
 LOG = logging.getLogger(__name__)
 
 
+def _console_dump(client, server_id):
+    try:
+        resp, output = client.get_console_output(server_id, None)
+        LOG.debug("Console Output for Server %s:\n%s" % (
+            server_id, output))
+    except exceptions.NotFound:
+        LOG.debug("Server %s: doesn't have a console" % server_id)
+        pass
+
+
 # NOTE(afazekas): This function needs to know a token and a subject.
 def wait_for_server_status(client, server_id, status, ready_wait=True,
                            extra_timeout=0, raise_on_error=True):
@@ -71,7 +81,9 @@
                      '/'.join((old_status, str(old_task_state))),
                      '/'.join((server_status, str(task_state))),
                      time.time() - start_time)
+
         if (server_status == 'ERROR') and raise_on_error:
+            _console_dump(client, server_id)
             raise exceptions.BuildErrorException(server_id=server_id)
 
         timed_out = int(time.time()) - start_time >= timeout
@@ -87,9 +99,11 @@
                         'timeout': timeout})
             message += ' Current status: %s.' % server_status
             message += ' Current task state: %s.' % task_state
+
             caller = misc_utils.find_test_caller()
             if caller:
                 message = '(%s) %s' % (caller, message)
+            _console_dump(client, server_id)
             raise exceptions.TimeoutException(message)
         old_status = server_status
         old_task_state = task_state
diff --git a/tempest/config.py b/tempest/config.py
index 1049f67..e3f0f2a 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -247,7 +247,11 @@
                     'for removing from a host.  -1 never offload, 0 offload '
                     'when shelved. This time should be the same as the time '
                     'of nova.conf, and some tests will run for as long as the '
-                    'time.')
+                    'time.'),
+    cfg.StrOpt('floating_ip_range',
+               default='10.0.0.0/29',
+               help='Unallocated floating IP range, which will be used to '
+                    'test the floating IP bulk feature for CRUD operation.')
 ]
 
 compute_features_group = cfg.OptGroup(name='compute-feature-enabled',
@@ -255,7 +259,7 @@
 
 ComputeFeaturesGroup = [
     cfg.BoolOpt('api_v3',
-                default=True,
+                default=False,
                 help="If false, skip all nova v3 tests."),
     cfg.BoolOpt('disk_config',
                 default=True,
@@ -263,11 +267,13 @@
     cfg.ListOpt('api_extensions',
                 default=['all'],
                 help='A list of enabled compute extensions with a special '
-                     'entry all which indicates every extension is enabled'),
+                     'entry all which indicates every extension is enabled. '
+                     'Each extension should be specified with alias name'),
     cfg.ListOpt('api_v3_extensions',
                 default=['all'],
                 help='A list of enabled v3 extensions with a special entry all'
-                     ' which indicates every extension is enabled'),
+                     ' which indicates every extension is enabled. '
+                     'Each extension should be specified with alias name'),
     cfg.BoolOpt('change_password',
                 default=False,
                 help="Does the test environment support changing the admin "
@@ -415,6 +421,10 @@
                default=1,
                help="Time in seconds between network operation status "
                     "checks."),
+    cfg.ListOpt('dns_servers',
+                default=["8.8.8.8", "8.8.4.4"],
+                help="List of dns servers whichs hould be used"
+                     " for subnet creation")
 ]
 
 network_feature_group = cfg.OptGroup(name='network-feature-enabled',
@@ -638,6 +648,10 @@
                choices=['public', 'admin', 'internal',
                         'publicURL', 'adminURL', 'internalURL'],
                help="The endpoint type to use for the telemetry service."),
+    cfg.BoolOpt('too_slow_to_test',
+                default=True,
+                help="This variable is used as flag to enable "
+                     "notification tests")
 ]
 
 
@@ -1070,8 +1084,21 @@
 class TempestConfigProxy(object):
     _config = None
 
+    _extra_log_defaults = [
+        'keystoneclient.session=INFO',
+        'paramiko.transport=INFO',
+        'requests.packages.urllib3.connectionpool=WARN'
+    ]
+
+    def _fix_log_levels(self):
+        """Tweak the oslo log defaults."""
+        for opt in logging.log_opts:
+            if opt.dest == 'default_log_levels':
+                opt.default.extend(self._extra_log_defaults)
+
     def __getattr__(self, attr):
         if not self._config:
+            self._fix_log_levels()
             self._config = TempestConfigPrivate()
 
         return getattr(self._config, attr)
diff --git a/tempest/openstack/common/versionutils.py b/tempest/openstack/common/versionutils.py
new file mode 100644
index 0000000..131046e
--- /dev/null
+++ b/tempest/openstack/common/versionutils.py
@@ -0,0 +1,148 @@
+# Copyright (c) 2013 OpenStack Foundation
+# 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.
+
+"""
+Helpers for comparing version strings.
+"""
+
+import functools
+import pkg_resources
+
+from tempest.openstack.common.gettextutils import _
+from tempest.openstack.common import log as logging
+
+
+LOG = logging.getLogger(__name__)
+
+
+class deprecated(object):
+    """A decorator to mark callables as deprecated.
+
+    This decorator logs a deprecation message when the callable it decorates is
+    used. The message will include the release where the callable was
+    deprecated, the release where it may be removed and possibly an optional
+    replacement.
+
+    Examples:
+
+    1. Specifying the required deprecated release
+
+    >>> @deprecated(as_of=deprecated.ICEHOUSE)
+    ... def a(): pass
+
+    2. Specifying a replacement:
+
+    >>> @deprecated(as_of=deprecated.ICEHOUSE, in_favor_of='f()')
+    ... def b(): pass
+
+    3. Specifying the release where the functionality may be removed:
+
+    >>> @deprecated(as_of=deprecated.ICEHOUSE, remove_in=+1)
+    ... def c(): pass
+
+    """
+
+    FOLSOM = 'F'
+    GRIZZLY = 'G'
+    HAVANA = 'H'
+    ICEHOUSE = 'I'
+
+    _RELEASES = {
+        'F': 'Folsom',
+        'G': 'Grizzly',
+        'H': 'Havana',
+        'I': 'Icehouse',
+    }
+
+    _deprecated_msg_with_alternative = _(
+        '%(what)s is deprecated as of %(as_of)s in favor of '
+        '%(in_favor_of)s and may be removed in %(remove_in)s.')
+
+    _deprecated_msg_no_alternative = _(
+        '%(what)s is deprecated as of %(as_of)s and may be '
+        'removed in %(remove_in)s. It will not be superseded.')
+
+    def __init__(self, as_of, in_favor_of=None, remove_in=2, what=None):
+        """Initialize decorator
+
+        :param as_of: the release deprecating the callable. Constants
+            are define in this class for convenience.
+        :param in_favor_of: the replacement for the callable (optional)
+        :param remove_in: an integer specifying how many releases to wait
+            before removing (default: 2)
+        :param what: name of the thing being deprecated (default: the
+            callable's name)
+
+        """
+        self.as_of = as_of
+        self.in_favor_of = in_favor_of
+        self.remove_in = remove_in
+        self.what = what
+
+    def __call__(self, func):
+        if not self.what:
+            self.what = func.__name__ + '()'
+
+        @functools.wraps(func)
+        def wrapped(*args, **kwargs):
+            msg, details = self._build_message()
+            LOG.deprecated(msg, details)
+            return func(*args, **kwargs)
+        return wrapped
+
+    def _get_safe_to_remove_release(self, release):
+        # TODO(dstanek): this method will have to be reimplemented once
+        #    when we get to the X release because once we get to the Y
+        #    release, what is Y+2?
+        new_release = chr(ord(release) + self.remove_in)
+        if new_release in self._RELEASES:
+            return self._RELEASES[new_release]
+        else:
+            return new_release
+
+    def _build_message(self):
+        details = dict(what=self.what,
+                       as_of=self._RELEASES[self.as_of],
+                       remove_in=self._get_safe_to_remove_release(self.as_of))
+
+        if self.in_favor_of:
+            details['in_favor_of'] = self.in_favor_of
+            msg = self._deprecated_msg_with_alternative
+        else:
+            msg = self._deprecated_msg_no_alternative
+        return msg, details
+
+
+def is_compatible(requested_version, current_version, same_major=True):
+    """Determine whether `requested_version` is satisfied by
+    `current_version`; in other words, `current_version` is >=
+    `requested_version`.
+
+    :param requested_version: version to check for compatibility
+    :param current_version: version to check against
+    :param same_major: if True, the major version must be identical between
+        `requested_version` and `current_version`. This is used when a
+        major-version difference indicates incompatibility between the two
+        versions. Since this is the common-case in practice, the default is
+        True.
+    :returns: True if compatible, False if not
+    """
+    requested_parts = pkg_resources.parse_version(requested_version)
+    current_parts = pkg_resources.parse_version(current_version)
+
+    if same_major and (requested_parts[0] != current_parts[0]):
+        return False
+
+    return current_parts >= requested_parts
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index f4850bb..07d8828 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -29,6 +29,7 @@
 from tempest.api.network import common as net_common
 from tempest import auth
 from tempest import clients
+from tempest.common import debug
 from tempest.common import isolated_creds
 from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
@@ -81,6 +82,7 @@
         cls.object_storage_client = cls.manager.object_storage_client
         cls.orchestration_client = cls.manager.orchestration_client
         cls.data_processing_client = cls.manager.data_processing_client
+        cls.ceilometer_client = cls.manager.ceilometer_client
         cls.resource_keys = {}
         cls.os_resources = []
 
@@ -288,6 +290,23 @@
             rules.append(sg_rule)
         return rules
 
+    def _create_security_group_nova(self, client=None,
+                                    namestart='secgroup-smoke-'):
+        if client is None:
+            client = self.compute_client
+        # Create security group
+        sg_name = data_utils.rand_name(namestart)
+        sg_desc = sg_name + " description"
+        secgroup = client.security_groups.create(sg_name, sg_desc)
+        self.assertEqual(secgroup.name, sg_name)
+        self.assertEqual(secgroup.description, sg_desc)
+        self.set_resource(sg_name, secgroup)
+
+        # Add rules to the security group
+        self._create_loginable_secgroup_rule_nova(client, secgroup.id)
+
+        return secgroup
+
     def create_server(self, client=None, name=None, image=None, flavor=None,
                       wait=True, create_kwargs={}):
         if client is None:
@@ -388,7 +407,16 @@
             username = CONF.scenario.ssh_user
         if private_key is None:
             private_key = self.keypair.private_key
-        return remote_client.RemoteClient(ip, username, pkey=private_key)
+        linux_client = remote_client.RemoteClient(ip, username,
+                                                  pkey=private_key)
+        try:
+            linux_client.validate_authentication()
+        except exceptions.SSHTimeout:
+            LOG.exception('ssh connection to %s failed' % ip)
+            debug.log_net_debug()
+            raise
+
+        return linux_client
 
     def _log_console_output(self, servers=None):
         if not servers:
@@ -446,6 +474,30 @@
         LOG.debug("image:%s" % self.image)
 
 
+# power/provision states as of icehouse
+class BaremetalPowerStates(object):
+    """Possible power states of an Ironic node."""
+    POWER_ON = 'power on'
+    POWER_OFF = 'power off'
+    REBOOT = 'rebooting'
+    SUSPEND = 'suspended'
+
+
+class BaremetalProvisionStates(object):
+    """Possible provision states of an Ironic node."""
+    NOSTATE = None
+    INIT = 'initializing'
+    ACTIVE = 'active'
+    BUILDING = 'building'
+    DEPLOYWAIT = 'wait call-back'
+    DEPLOYING = 'deploying'
+    DEPLOYFAIL = 'deploy failed'
+    DEPLOYDONE = 'deploy complete'
+    DELETING = 'deleting'
+    DELETED = 'deleted'
+    ERROR = 'error'
+
+
 class BaremetalScenarioTest(OfficialClientTest):
     @classmethod
     def setUpClass(cls):
@@ -521,6 +573,55 @@
             ports.append(self.baremetal_client.port.get(port.uuid))
         return ports
 
+    def add_keypair(self):
+        self.keypair = self.create_keypair()
+
+    def verify_connectivity(self, ip=None):
+        if ip:
+            dest = self.get_remote_client(ip)
+        else:
+            dest = self.get_remote_client(self.instance)
+        dest.validate_authentication()
+
+    def boot_instance(self):
+        create_kwargs = {
+            'key_name': self.keypair.id
+        }
+        self.instance = self.create_server(
+            wait=False, create_kwargs=create_kwargs)
+
+        self.set_resource('instance', self.instance)
+
+        self.wait_node(self.instance.id)
+        self.node = self.get_node(instance_id=self.instance.id)
+
+        self.wait_power_state(self.node.uuid, BaremetalPowerStates.POWER_ON)
+
+        self.wait_provisioning_state(
+            self.node.uuid,
+            [BaremetalProvisionStates.DEPLOYWAIT,
+             BaremetalProvisionStates.ACTIVE],
+            timeout=15)
+
+        self.wait_provisioning_state(self.node.uuid,
+                                     BaremetalProvisionStates.ACTIVE,
+                                     timeout=CONF.baremetal.active_timeout)
+
+        self.status_timeout(
+            self.compute_client.servers, self.instance.id, 'ACTIVE')
+
+        self.node = self.get_node(instance_id=self.instance.id)
+        self.instance = self.compute_client.servers.get(self.instance.id)
+
+    def terminate_instance(self):
+        self.instance.delete()
+        self.remove_resource('instance')
+        self.wait_power_state(self.node.uuid, BaremetalPowerStates.POWER_OFF)
+        self.wait_provisioning_state(
+            self.node.uuid,
+            BaremetalProvisionStates.NOSTATE,
+            timeout=CONF.baremetal.unprovision_timeout)
+
 
 class NetworkScenarioTest(OfficialClientTest):
     """
@@ -777,9 +878,56 @@
                         msg=msg)
         if should_connect:
             # no need to check ssh for negative connectivity
-            linux_client = self.get_remote_client(ip_address, username,
-                                                  private_key)
-            linux_client.validate_authentication()
+            self.get_remote_client(ip_address, username, private_key)
+
+    def _check_public_network_connectivity(self, ip_address, username,
+                                           private_key, should_connect=True,
+                                           msg=None, servers=None):
+        # The target login is assumed to have been configured for
+        # key-based authentication by cloud-init.
+        LOG.debug('checking network connections to IP %s with user: %s' %
+                  (ip_address, username))
+        try:
+            self._check_vm_connectivity(ip_address,
+                                        username,
+                                        private_key,
+                                        should_connect=should_connect)
+        except Exception as e:
+            ex_msg = 'Public network connectivity check failed'
+            if msg:
+                ex_msg += ": " + msg
+            LOG.exception(ex_msg)
+            self._log_console_output(servers)
+            # network debug is called as part of ssh init
+            if not isinstance(e, exceptions.SSHTimeout):
+                debug.log_net_debug()
+            raise
+
+    def _check_tenant_network_connectivity(self, server,
+                                           username,
+                                           private_key,
+                                           should_connect=True,
+                                           servers_for_debug=None):
+        if not CONF.network.tenant_networks_reachable:
+            msg = 'Tenant networks not configured to be reachable.'
+            LOG.info(msg)
+            return
+        # The target login is assumed to have been configured for
+        # key-based authentication by cloud-init.
+        try:
+            for net_name, ip_addresses in server.networks.iteritems():
+                for ip_address in ip_addresses:
+                    self._check_vm_connectivity(ip_address,
+                                                username,
+                                                private_key,
+                                                should_connect=should_connect)
+        except Exception as e:
+            LOG.exception('Tenant network connectivity check failed')
+            self._log_console_output(servers_for_debug)
+            # network debug is called as part of ssh init
+            if not isinstance(e, exceptions.SSHTimeout):
+                debug.log_net_debug()
+            raise
 
     def _check_remote_connectivity(self, source, dest, should_succeed=True):
         """
@@ -803,24 +951,6 @@
                                             CONF.compute.ping_timeout,
                                             1)
 
-    def _create_security_group_nova(self, client=None,
-                                    namestart='secgroup-smoke-',
-                                    tenant_id=None):
-        if client is None:
-            client = self.compute_client
-        # Create security group
-        sg_name = data_utils.rand_name(namestart)
-        sg_desc = sg_name + " description"
-        secgroup = client.security_groups.create(sg_name, sg_desc)
-        self.assertEqual(secgroup.name, sg_name)
-        self.assertEqual(secgroup.description, sg_desc)
-        self.set_resource(sg_name, secgroup)
-
-        # Add rules to the security group
-        self._create_loginable_secgroup_rule_nova(client, secgroup.id)
-
-        return secgroup
-
     def _create_security_group_neutron(self, tenant_id, client=None,
                                        namestart='secgroup-smoke-'):
         if client is None:
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index c53aa83..f197c15 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -23,31 +23,7 @@
 LOG = logging.getLogger(__name__)
 
 
-# power/provision states as of icehouse
-class PowerStates(object):
-    """Possible power states of an Ironic node."""
-    POWER_ON = 'power on'
-    POWER_OFF = 'power off'
-    REBOOT = 'rebooting'
-    SUSPEND = 'suspended'
-
-
-class ProvisionStates(object):
-    """Possible provision states of an Ironic node."""
-    NOSTATE = None
-    INIT = 'initializing'
-    ACTIVE = 'active'
-    BUILDING = 'building'
-    DEPLOYWAIT = 'wait call-back'
-    DEPLOYING = 'deploying'
-    DEPLOYFAIL = 'deploy failed'
-    DEPLOYDONE = 'deploy complete'
-    DELETING = 'deleting'
-    DELETED = 'deleted'
-    ERROR = 'error'
-
-
-class BaremetalBasicOptsPXESSH(manager.BaremetalScenarioTest):
+class BaremetalBasicOpsPXESSH(manager.BaremetalScenarioTest):
     """
     This smoke test tests the pxe_ssh Ironic driver.  It follows this basic
     set of operations:
@@ -55,8 +31,6 @@
         * Boots an instance using the keypair
         * Monitors the associated Ironic node for power and
           expected state transitions
-        * Validates Ironic node's driver_info has been properly
-          updated
         * Validates Ironic node's port data has been properly updated
         * Verifies SSH connectivity using created keypair via fixed IP
         * Associates a floating ip
@@ -65,32 +39,11 @@
         * Monitors the associated Ironic node for power and
           expected state transitions
     """
-    def add_keypair(self):
-        self.keypair = self.create_keypair()
-
     def add_floating_ip(self):
         floating_ip = self.compute_client.floating_ips.create()
         self.instance.add_floating_ip(floating_ip)
         return floating_ip.ip
 
-    def verify_connectivity(self, ip=None):
-        if ip:
-            dest = self.get_remote_client(ip)
-        else:
-            dest = self.get_remote_client(self.instance)
-        dest.validate_authentication()
-
-    def validate_driver_info(self):
-        f_id = self.instance.flavor['id']
-        flavor_extra = self.compute_client.flavors.get(f_id).get_keys()
-        driver_info = self.node.driver_info
-        self.assertEqual(driver_info['pxe_deploy_kernel'],
-                         flavor_extra['baremetal:deploy_kernel_id'])
-        self.assertEqual(driver_info['pxe_deploy_ramdisk'],
-                         flavor_extra['baremetal:deploy_ramdisk_id'])
-        self.assertEqual(driver_info['pxe_image_source'],
-                         self.instance.image['id'])
-
     def validate_ports(self):
         for port in self.get_ports(self.node.uuid):
             n_port_id = port.extra['vif_port_id']
@@ -98,48 +51,10 @@
             self.assertEqual(n_port['device_id'], self.instance.id)
             self.assertEqual(n_port['mac_address'], port.address)
 
-    def boot_instance(self):
-        create_kwargs = {
-            'key_name': self.keypair.id
-        }
-        self.instance = self.create_server(
-            wait=False, create_kwargs=create_kwargs)
-
-        self.set_resource('instance', self.instance)
-
-        self.wait_node(self.instance.id)
-        self.node = self.get_node(instance_id=self.instance.id)
-
-        self.wait_power_state(self.node.uuid, PowerStates.POWER_ON)
-
-        self.wait_provisioning_state(
-            self.node.uuid,
-            [ProvisionStates.DEPLOYWAIT, ProvisionStates.ACTIVE],
-            timeout=15)
-
-        self.wait_provisioning_state(self.node.uuid, ProvisionStates.ACTIVE,
-                                     timeout=CONF.baremetal.active_timeout)
-
-        self.status_timeout(
-            self.compute_client.servers, self.instance.id, 'ACTIVE')
-
-        self.node = self.get_node(instance_id=self.instance.id)
-        self.instance = self.compute_client.servers.get(self.instance.id)
-
-    def terminate_instance(self):
-        self.instance.delete()
-        self.remove_resource('instance')
-        self.wait_power_state(self.node.uuid, PowerStates.POWER_OFF)
-        self.wait_provisioning_state(
-            self.node.uuid,
-            ProvisionStates.NOSTATE,
-            timeout=CONF.baremetal.unprovision_timeout)
-
     @test.services('baremetal', 'compute', 'image', 'network')
     def test_baremetal_server_ops(self):
         self.add_keypair()
         self.boot_instance()
-        self.validate_driver_info()
         self.validate_ports()
         self.verify_connectivity()
         floating_ip = self.add_floating_ip()
diff --git a/tempest/scenario/test_load_balancer_basic.py b/tempest/scenario/test_load_balancer_basic.py
index 1c24b5c..03cfef5 100644
--- a/tempest/scenario/test_load_balancer_basic.py
+++ b/tempest/scenario/test_load_balancer_basic.py
@@ -148,7 +148,6 @@
             ssh_client = self.get_remote_client(
                 server_or_ip=ip,
                 private_key=private_key)
-            ssh_client.validate_authentication()
 
             # Write a backend's responce into a file
             resp = """HTTP/1.0 200 OK\r\nContent-Length: 8\r\n\r\n%s"""
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 24d2677..0406217 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -93,11 +93,12 @@
     def ssh_to_server(self):
         try:
             self.linux_client = self.get_remote_client(self.floating_ip.ip)
-            self.linux_client.validate_authentication()
-        except Exception:
+        except Exception as e:
             LOG.exception('ssh to server failed')
             self._log_console_output()
-            debug.log_net_debug()
+            # network debug is called as part of ssh init
+            if not isinstance(e, test.exceptions.SSHTimeout):
+                debug.log_net_debug()
             raise
 
     def check_partitions(self):
@@ -112,6 +113,11 @@
         volume = self.volume_client.volumes.get(self.volume.id)
         self.assertEqual('available', volume.status)
 
+    def create_and_add_security_group(self):
+        secgroup = self._create_security_group_nova()
+        self.server.add_security_group(secgroup.name)
+        self.addCleanup(self.server.remove_security_group, secgroup.name)
+
     @test.services('compute', 'volume', 'image', 'network')
     def test_minimum_basic_scenario(self):
         self.glance_image_create()
@@ -128,7 +134,7 @@
 
         self.nova_floating_ip_create()
         self.nova_floating_ip_add()
-        self._create_loginable_secgroup_rule_nova()
+        self.create_and_add_security_group()
         self.ssh_to_server()
         self.nova_reboot()
         self.ssh_to_server()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 9b435bd..f1cd320 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -15,7 +15,6 @@
 
 import testtools
 
-from tempest.common import debug
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest.openstack.common import log as logging
@@ -84,57 +83,17 @@
         self.floating_ip = self._create_floating_ip(self.server,
                                                     public_network_id)
         self.addCleanup(self.cleanup_wrapper, self.floating_ip)
-        self._wait_server_status_and_check_network_connectivity()
-
-    def _check_tenant_network_connectivity(self, server,
-                                           username,
-                                           private_key,
-                                           should_connect=True):
-        if not CONF.network.tenant_networks_reachable:
-            msg = 'Tenant networks not configured to be reachable.'
-            LOG.info(msg)
-            return
-        # The target login is assumed to have been configured for
-        # key-based authentication by cloud-init.
-        try:
-            for net_name, ip_addresses in server.networks.iteritems():
-                for ip_address in ip_addresses:
-                    self._check_vm_connectivity(ip_address,
-                                                username,
-                                                private_key,
-                                                should_connect=should_connect)
-        except Exception:
-            LOG.exception('Tenant network connectivity check failed')
-            self._log_console_output(servers=[server])
-            debug.log_ip_ns()
-            raise
-
-    def _check_public_network_connectivity(self, floating_ip,
-                                           username,
-                                           private_key,
-                                           should_connect=True):
-        # The target login is assumed to have been configured for
-        # key-based authentication by cloud-init.
-        try:
-            self._check_vm_connectivity(floating_ip, username, private_key,
-                                        should_connect=should_connect)
-        except Exception:
-            LOG.exception("Public network connectivity check failed")
-            debug.log_ip_ns()
-            raise
 
     def _check_network_connectivity(self, should_connect=True):
         username = CONF.compute.image_ssh_user
         private_key = self.keypair.private_key
-        self._check_tenant_network_connectivity(self.server,
-                                                username,
-                                                private_key,
-                                                should_connect=should_connect)
+        self._check_tenant_network_connectivity(
+            self.server, username, private_key, should_connect=should_connect,
+            servers_for_debug=[self.server])
         floating_ip = self.floating_ip.floating_ip_address
-        self._check_public_network_connectivity(floating_ip,
-                                                username,
-                                                private_key,
-                                                should_connect=should_connect)
+        self._check_public_network_connectivity(floating_ip, username,
+                                                private_key, should_connect,
+                                                servers=[self.server])
 
     def _wait_server_status_and_check_network_connectivity(self):
         self.status_timeout(self.compute_client.servers, self.server.id,
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index d5ab3d3..c84d4b9 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -87,6 +87,8 @@
 
     @classmethod
     def setUpClass(cls):
+        # Create no network resources for these tests.
+        cls.set_network_resources()
         super(TestNetworkBasicOps, cls).setUpClass()
         for ext in ['router', 'security-group']:
             if not test.is_extension_enabled(ext, 'network'):
@@ -156,24 +158,13 @@
         return dict(server=server, keypair=keypair)
 
     def _check_tenant_network_connectivity(self):
-        if not CONF.network.tenant_networks_reachable:
-            msg = 'Tenant networks not configured to be reachable.'
-            LOG.info(msg)
-            return
-        # The target login is assumed to have been configured for
-        # key-based authentication by cloud-init.
         ssh_login = CONF.compute.image_ssh_user
-        try:
-            for server, key in self.servers.iteritems():
-                for net_name, ip_addresses in server.networks.iteritems():
-                    for ip_address in ip_addresses:
-                        self._check_vm_connectivity(ip_address, ssh_login,
-                                                    key.private_key)
-        except Exception:
-            LOG.exception('Tenant connectivity check failed')
-            self._log_console_output(servers=self.servers.keys())
-            debug.log_net_debug()
-            raise
+        for server, key in self.servers.iteritems():
+            # call the common method in the parent class
+            super(TestNetworkBasicOps, self).\
+                _check_tenant_network_connectivity(
+                    server, ssh_login, key.private_key,
+                    servers_for_debug=self.servers.keys())
 
     def _create_and_associate_floating_ips(self):
         public_network_id = CONF.network.public_network_id
@@ -184,28 +175,16 @@
 
     def _check_public_network_connectivity(self, should_connect=True,
                                            msg=None):
-        # The target login is assumed to have been configured for
-        # key-based authentication by cloud-init.
         ssh_login = CONF.compute.image_ssh_user
-        LOG.debug('checking network connections')
         floating_ip, server = self.floating_ip_tuple
         ip_address = floating_ip.floating_ip_address
         private_key = None
         if should_connect:
             private_key = self.servers[server].private_key
-        try:
-            self._check_vm_connectivity(ip_address,
-                                        ssh_login,
-                                        private_key,
-                                        should_connect=should_connect)
-        except Exception:
-            ex_msg = 'Public network connectivity check failed'
-            if msg:
-                ex_msg += ": " + msg
-            LOG.exception(ex_msg)
-            self._log_console_output(servers=self.servers.keys())
-            debug.log_net_debug()
-            raise
+        # call the common method in the parent class
+        super(TestNetworkBasicOps, self)._check_public_network_connectivity(
+            ip_address, ssh_login, private_key, should_connect, msg,
+            self.servers.keys())
 
     def _disassociate_floating_ips(self):
         floating_ip, server = self.floating_ip_tuple
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 4616b82..dd89dc0 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -134,6 +134,8 @@
 
     @classmethod
     def setUpClass(cls):
+        # Create no network resources for these tests.
+        cls.set_network_resources()
         super(TestSecurityGroupsBasicOps, cls).setUpClass()
         cls.alt_creds = cls.alt_credentials()
         cls.alt_manager = clients.OfficialClientManager(cls.alt_creds)
@@ -334,6 +336,8 @@
             self.assertTrue(self._check_remote_connectivity(access_point, ip,
                                                             should_succeed),
                             msg)
+        except test.exceptions.SSHTimeout:
+            raise
         except Exception:
             debug.log_net_debug()
             raise
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 13e00a5..54f1d9e 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.common.utils import data_utils
 from tempest import config
 from tempest.openstack.common import log as logging
 from tempest.scenario import manager
@@ -68,22 +67,12 @@
     def add_keypair(self):
         self.keypair = self.create_keypair()
 
-    def create_security_group(self):
-        sg_name = data_utils.rand_name('secgroup-smoke')
-        sg_desc = sg_name + " description"
-        self.secgroup = self.compute_client.security_groups.create(sg_name,
-                                                                   sg_desc)
-        self.assertEqual(self.secgroup.name, sg_name)
-        self.assertEqual(self.secgroup.description, sg_desc)
-        self.set_resource('secgroup', self.secgroup)
-
-        # Add rules to the security group
-        self._create_loginable_secgroup_rule_nova(secgroup_id=self.secgroup.id)
-
     def boot_instance(self):
         # Create server with image and flavor from input scenario
+        security_groups = [self.security_group.name]
         create_kwargs = {
-            'key_name': self.keypair.id
+            'key_name': self.keypair.id,
+            'security_groups': security_groups
         }
         instance = self.create_server(image=self.image_ref,
                                       flavor=self.flavor_ref,
@@ -104,11 +93,10 @@
             instance.add_floating_ip(floating_ip)
             # Check ssh
             try:
-                linux_client = self.get_remote_client(
+                self.get_remote_client(
                     server_or_ip=floating_ip.ip,
                     username=self.image_utils.ssh_user(self.image_ref),
                     private_key=self.keypair.private_key)
-                linux_client.validate_authentication()
             except Exception:
                 LOG.exception('ssh to server failed')
                 self._log_console_output()
@@ -117,7 +105,7 @@
     @test.services('compute', 'network')
     def test_server_basicops(self):
         self.add_keypair()
-        self.create_security_group()
+        self.security_group = self._create_security_group_nova()
         self.boot_instance()
         self.verify_ssh()
         self.terminate_instance()
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 562020a..d41490a 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -35,8 +35,10 @@
     """
 
     def _boot_image(self, image_id):
+        security_groups = [self.security_group.name]
         create_kwargs = {
-            'key_name': self.keypair.name
+            'key_name': self.keypair.name,
+            'security_groups': security_groups
         }
         return self.create_server(image=image_id, create_kwargs=create_kwargs)
 
@@ -47,8 +49,9 @@
         try:
             return self.get_remote_client(server_or_ip)
         except Exception:
-            LOG.exception()
+            LOG.exception('Initializing SSH connection failed')
             self._log_console_output()
+            raise
 
     def _write_timestamp(self, server_or_ip):
         ssh_client = self._ssh_to_server(server_or_ip)
@@ -72,7 +75,7 @@
     def test_snapshot_pattern(self):
         # prepare for booting a instance
         self._add_keypair()
-        self._create_loginable_secgroup_rule_nova()
+        self.security_group = self._create_security_group_nova()
 
         # boot a instance and create a timestamp file in it
         server = self._boot_image(CONF.compute.image_ref)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 5235871..20561ae 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -62,8 +62,10 @@
                             volume_snapshot.id, status)
 
     def _boot_image(self, image_id):
+        security_groups = [self.security_group.name]
         create_kwargs = {
-            'key_name': self.keypair.name
+            'key_name': self.keypair.name,
+            'security_groups': security_groups
         }
         return self.create_server(image=image_id, create_kwargs=create_kwargs)
 
@@ -152,7 +154,7 @@
     def test_stamp_pattern(self):
         # prepare for booting a instance
         self._add_keypair()
-        self._create_loginable_secgroup_rule_nova()
+        self.security_group = self._create_security_group_nova()
 
         # boot an instance and create a timestamp file in it
         volume = self._create_volume()
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index faca31f..4905dbf 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -55,9 +55,11 @@
         bd_map = {
             'vda': vol_id + ':::0'
         }
+        security_groups = [self.security_group.name]
         create_kwargs = {
             'block_device_mapping': bd_map,
-            'key_name': keypair.name
+            'key_name': keypair.name,
+            'security_groups': security_groups
         }
         return self.create_server(image='', create_kwargs=create_kwargs)
 
@@ -135,7 +137,7 @@
     @test.services('compute', 'volume', 'image')
     def test_volume_boot_pattern(self):
         keypair = self.create_keypair()
-        self._create_loginable_secgroup_rule_nova()
+        self.security_group = self._create_security_group_nova()
 
         # create an instance from volume
         volume_origin = self._create_volume_from_image()
@@ -182,8 +184,10 @@
         bdms = [{'uuid': vol_id, 'source_type': 'volume',
                  'destination_type': 'volume', 'boot_index': 0,
                  'delete_on_termination': False}]
+        security_groups = [self.security_group.name]
         create_kwargs = {
             'block_device_mapping_v2': bdms,
-            'key_name': keypair.name
+            'key_name': keypair.name,
+            'security_groups': security_groups
         }
         return self.create_server(image='', create_kwargs=create_kwargs)
diff --git a/tempest/services/baremetal/base.py b/tempest/services/baremetal/base.py
index 2af287f..321b08b 100644
--- a/tempest/services/baremetal/base.py
+++ b/tempest/services/baremetal/base.py
@@ -199,3 +199,14 @@
 
         """
         return self._list_request(version, permanent=True)
+
+    def _put_request(self, resource, put_object):
+        """
+        Update specified object with JSON-patch.
+
+        """
+        uri = self._get_uri(resource)
+        put_body = json.dumps(put_object)
+
+        resp, body = self.put(uri, body=put_body)
+        return resp, body
diff --git a/tempest/services/baremetal/v1/base_v1.py b/tempest/services/baremetal/v1/base_v1.py
index 296a199..52479b5 100644
--- a/tempest/services/baremetal/v1/base_v1.py
+++ b/tempest/services/baremetal/v1/base_v1.py
@@ -226,3 +226,16 @@
         """
 
         return self._patch_request('ports', uuid, patch)
+
+    @base.handle_errors
+    def set_node_power_state(self, node_uuid, state):
+        """
+        Set power state of the specified node.
+
+        :param node_uuid: The unique identifier of the node.
+        :state: desired state to set (on/off/reboot).
+
+        """
+        target = {'target': state}
+        return self._put_request('nodes/%s/states/power' % node_uuid,
+                                 target)
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index e2e12d5..92b4ddf 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -112,3 +112,29 @@
         body = json.loads(body)
         self.validate_response(schema.floating_ip_pools, resp, body)
         return resp, body['floating_ip_pools']
+
+    def create_floating_ips_bulk(self, ip_range, pool, interface):
+        """Allocate floating IPs in bulk."""
+        post_body = {
+            'ip_range': ip_range,
+            'pool': pool,
+            'interface': interface
+        }
+        post_body = json.dumps({'floating_ips_bulk_create': post_body})
+        resp, body = self.post('os-floating-ips-bulk', post_body)
+        body = json.loads(body)
+        self.validate_response(schema.create_floating_ips_bulk, resp, body)
+        return resp, body['floating_ips_bulk_create']
+
+    def list_floating_ips_bulk(self):
+        """Returns a list of all floating IPs bulk."""
+        resp, body = self.get('os-floating-ips-bulk')
+        body = json.loads(body)
+        return resp, body['floating_ip_info']
+
+    def delete_floating_ips_bulk(self, ip_range):
+        """Deletes the provided floating IPs bulk."""
+        post_body = json.dumps({'ip_range': ip_range})
+        resp, body = self.put('os-floating-ips-bulk/delete', post_body)
+        body = json.loads(body)
+        return resp, body['floating_ips_bulk_delete']
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 70123fe..23c1e64 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -57,6 +57,7 @@
         max_count: Count of maximum number of instances to launch.
         disk_config: Determines if user or admin controls disk configuration.
         return_reservation_id: Enable/Disable the return of reservation id
+        block_device_mapping: Block device mapping for the server.
         """
         post_body = {
             'name': name,
@@ -69,7 +70,7 @@
                        'availability_zone', 'accessIPv4', 'accessIPv6',
                        'min_count', 'max_count', ('metadata', 'meta'),
                        ('OS-DCF:diskConfig', 'disk_config'),
-                       'return_reservation_id']:
+                       'return_reservation_id', 'block_device_mapping']:
             if isinstance(option, tuple):
                 post_param = option[0]
                 key = option[1]
@@ -308,6 +309,8 @@
         resp, body = self.post('servers/%s/metadata' % str(server_id),
                                post_body)
         body = json.loads(body)
+        self.validate_response(common_schema.update_server_metadata,
+                               resp, body)
         return resp, body['metadata']
 
     def get_server_metadata_item(self, server_id, key):
@@ -460,6 +463,7 @@
         resp, body = self.get("servers/%s/os-instance-actions" %
                               str(server_id))
         body = json.loads(body)
+        self.validate_response(schema.list_instance_actions, resp, body)
         return resp, body['instanceActions']
 
     def get_instance_action(self, server_id, request_id):
@@ -506,11 +510,14 @@
         resp, body = self.post('os-server-groups', post_body)
 
         body = json.loads(body)
+        self.validate_response(schema.create_get_server_group, resp, body)
         return resp, body['server_group']
 
     def delete_server_group(self, server_group_id):
         """Delete the given server-group."""
-        return self.delete("os-server-groups/%s" % str(server_group_id))
+        resp, body = self.delete("os-server-groups/%s" % str(server_group_id))
+        self.validate_response(schema.delete_server_group, resp, body)
+        return resp, body
 
     def list_server_groups(self):
         """List the server-groups."""
@@ -522,4 +529,5 @@
         """Get the details of given server_group."""
         resp, body = self.get("os-server-groups/%s" % str(server_group_id))
         body = json.loads(body)
+        self.validate_response(schema.create_get_server_group, resp, body)
         return resp, body['server_group']
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
index f397c4b..11258a6 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -55,6 +55,7 @@
         max_count: Count of maximum number of instances to launch.
         disk_config: Determines if user or admin controls disk configuration.
         return_reservation_id: Enable/Disable the return of reservation id
+        block_device_mapping: Block device mapping for the server.
         """
         post_body = {
             'name': name,
@@ -75,7 +76,9 @@
                        ('metadata', 'meta'),
                        ('os-disk-config:disk_config', 'disk_config'),
                        ('os-multiple-create:return_reservation_id',
-                        'return_reservation_id')]:
+                        'return_reservation_id'),
+                       ('os-block-device-mapping:block_device_mapping',
+                        'block_device_mapping')]:
             if isinstance(option, tuple):
                 post_param = option[0]
                 key = option[1]
@@ -324,6 +327,7 @@
         resp, body = self.post('servers/%s/metadata' % str(server_id),
                                post_body)
         body = json.loads(body)
+        self.validate_response(schema.update_server_metadata, resp, body)
         return resp, body['metadata']
 
     def get_server_metadata_item(self, server_id, key):
@@ -431,6 +435,9 @@
         return self.action(server_id, 'shelve_offload', None, **kwargs)
 
     def get_console_output(self, server_id, length):
+        if length is None:
+            # NOTE(mriedem): -1 means optional/unlimited in the nova v3 API.
+            length = -1
         return self.action(server_id, 'get_console_output', 'output',
                            common_schema.get_console_output, length=length)
 
@@ -454,6 +461,7 @@
         resp, body = self.get("servers/%s/os-server-actions" %
                               str(server_id))
         body = json.loads(body)
+        self.validate_response(schema.list_server_actions, resp, body)
         return resp, body['server_actions']
 
     def get_server_action(self, server_id, request_id):
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index c1105f9..626e655 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -318,6 +318,7 @@
         min_count: Count of minimum number of instances to launch.
         max_count: Count of maximum number of instances to launch.
         disk_config: Determines if user or admin controls disk configuration.
+        block_device_mapping: Block device mapping for the server.
         """
         server = xml_utils.Element("server",
                                    xmlns=xml_utils.XMLNS_11,
@@ -327,7 +328,8 @@
 
         for attr in ["adminPass", "accessIPv4", "accessIPv6", "key_name",
                      "user_data", "availability_zone", "min_count",
-                     "max_count", "return_reservation_id"]:
+                     "max_count", "return_reservation_id",
+                     "block_device_mapping"]:
             if attr in kwargs:
                 server.add_attr(attr, kwargs[attr])
 
diff --git a/tempest/services/data_processing/v1_1/client.py b/tempest/services/data_processing/v1_1/client.py
index 73e67c3..c2c7fd1 100644
--- a/tempest/services/data_processing/v1_1/client.py
+++ b/tempest/services/data_processing/v1_1/client.py
@@ -186,3 +186,49 @@
 
         uri = 'job-binary-internals/%s' % job_binary_id
         return self.delete(uri)
+
+    def get_job_binary_internal_data(self, job_binary_id):
+        """Returns data of a single job binary internal."""
+
+        uri = 'job-binary-internals/%s/data' % job_binary_id
+        return self.get(uri)
+
+    def list_job_binaries(self):
+        """List all job binaries for a user."""
+
+        uri = 'job-binaries'
+        return self._request_and_parse(self.get, uri, 'binaries')
+
+    def get_job_binary(self, job_binary_id):
+        """Returns the details of a single job binary."""
+
+        uri = 'job-binaries/%s' % job_binary_id
+        return self._request_and_parse(self.get, uri, 'job_binary')
+
+    def create_job_binary(self, name, url, extra=None, **kwargs):
+        """Creates job binary with specified params.
+
+        It supports passing additional params using kwargs and returns created
+        object.
+        """
+        uri = 'job-binaries'
+        body = kwargs.copy()
+        body.update({
+            'name': name,
+            'url': url,
+            'extra': extra or dict(),
+        })
+        return self._request_and_parse(self.post, uri, 'job_binary',
+                                       body=json.dumps(body))
+
+    def delete_job_binary(self, job_binary_id):
+        """Deletes the specified job binary by id."""
+
+        uri = 'job-binaries/%s' % job_binary_id
+        return self.delete(uri)
+
+    def get_job_binary_data(self, job_binary_id):
+        """Returns data of a single job binary."""
+
+        uri = 'job-binaries/%s/data' % job_binary_id
+        return self.get(uri)
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/json/identity_client.py
index 479a289..b0cab8e 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/json/identity_client.py
@@ -27,7 +27,8 @@
         self.endpoint_url = 'adminURL'
 
         # Needed for xml service client
-        self.list_tags = ["roles", "tenants", "users", "services"]
+        self.list_tags = ["roles", "tenants", "users", "services",
+                          "extensions"]
 
     def has_admin_extensions(self):
         """
@@ -237,6 +238,12 @@
         resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body)
         return resp, self._parse_resp(body)
 
+    def list_extensions(self):
+        """List all the extensions."""
+        resp, body = self.get('/extensions')
+        body = json.loads(body)
+        return resp, body['extensions']['values']
+
 
 class TokenClientJSON(IdentityClientJSON):
 
diff --git a/tempest/services/identity/v3/json/region_client.py b/tempest/services/identity/v3/json/region_client.py
new file mode 100644
index 0000000..f95d00f
--- /dev/null
+++ b/tempest/services/identity/v3/json/region_client.py
@@ -0,0 +1,80 @@
+# Copyright 2014 OpenStack Foundation
+# 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.common import rest_client
+from tempest import config
+
+CONF = config.CONF
+
+
+class RegionClientJSON(rest_client.RestClient):
+
+    def __init__(self, auth_provider):
+        super(RegionClientJSON, self).__init__(auth_provider)
+        self.service = CONF.identity.catalog_type
+        self.endpoint_url = 'adminURL'
+        self.api_version = "v3"
+
+    def create_region(self, description, **kwargs):
+        """Create region."""
+        req_body = {
+            'description': description,
+        }
+        if kwargs.get('parent_region_id'):
+            req_body['parent_region_id'] = kwargs.get('parent_region_id')
+        req_body = json.dumps({'region': req_body})
+        if kwargs.get('unique_region_id'):
+            resp, body = self.put(
+                'regions/%s' % kwargs.get('unique_region_id'), req_body)
+        else:
+            resp, body = self.post('regions', req_body)
+        body = json.loads(body)
+        return resp, body['region']
+
+    def update_region(self, region_id, **kwargs):
+        """Updates a region."""
+        post_body = {}
+        if 'description' in kwargs:
+            post_body['description'] = kwargs.get('description')
+        if 'parent_region_id' in kwargs:
+            post_body['parent_region_id'] = kwargs.get('parent_region_id')
+        post_body = json.dumps({'region': post_body})
+        resp, body = self.patch('regions/%s' % region_id, post_body)
+        body = json.loads(body)
+        return resp, body['region']
+
+    def get_region(self, region_id):
+        """Get region."""
+        url = 'regions/%s' % region_id
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['region']
+
+    def list_regions(self, params=None):
+        """List regions."""
+        url = 'regions'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['regions']
+
+    def delete_region(self, region_id):
+        """Delete region."""
+        resp, body = self.delete('regions/%s' % region_id)
+        return resp, body
diff --git a/tempest/services/identity/v3/xml/region_client.py b/tempest/services/identity/v3/xml/region_client.py
new file mode 100644
index 0000000..9f9161d
--- /dev/null
+++ b/tempest/services/identity/v3/xml/region_client.py
@@ -0,0 +1,120 @@
+# Copyright 2014 OpenStack Foundation
+# 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 urllib
+
+from lxml import etree
+
+from tempest.common import http
+from tempest.common import rest_client
+from tempest.common import xml_utils as common
+from tempest import config
+
+CONF = config.CONF
+
+XMLNS = "http://docs.openstack.org/identity/api/v3"
+
+
+class RegionClientXML(rest_client.RestClient):
+    TYPE = "xml"
+
+    def __init__(self, auth_provider):
+        super(RegionClientXML, self).__init__(auth_provider)
+        self.service = CONF.identity.catalog_type
+        self.region_url = 'adminURL'
+        self.api_version = "v3"
+
+    def _parse_array(self, node):
+        array = []
+        for child in node.getchildren():
+            tag_list = child.tag.split('}', 1)
+            if tag_list[1] == "region":
+                array.append(common.xml_to_json(child))
+        return array
+
+    def _parse_body(self, body):
+        json = common.xml_to_json(body)
+        return json
+
+    def request(self, method, url, extra_headers=False, headers=None,
+                body=None, wait=None):
+        """Overriding the existing HTTP request in super class RestClient."""
+        if extra_headers:
+            try:
+                headers.update(self.get_headers())
+            except (ValueError, TypeError):
+                headers = self.get_headers()
+        dscv = CONF.identity.disable_ssl_certificate_validation
+        self.http_obj = http.ClosingHttp(
+            disable_ssl_certificate_validation=dscv)
+        return super(RegionClientXML, self).request(method, url,
+                                                    extra_headers,
+                                                    headers=headers,
+                                                    body=body)
+
+    def create_region(self, description, **kwargs):
+        """Create region."""
+        create_region = common.Element("region",
+                                       xmlns=XMLNS,
+                                       description=description)
+        if 'parent_region_id' in kwargs:
+            create_region.append(common.Element(
+                'parent_region_id', kwargs.get('parent_region_id')))
+        if 'unique_region_id' in kwargs:
+            resp, body = self.put(
+                'regions/%s' % kwargs.get('unique_region_id'),
+                str(common.Document(create_region)))
+        else:
+            resp, body = self.post('regions',
+                                   str(common.Document(create_region)))
+        body = self._parse_body(etree.fromstring(body))
+        return resp, body
+
+    def update_region(self, region_id, **kwargs):
+        """Updates an region with given parameters.
+        """
+        description = kwargs.get('description', None)
+        update_region = common.Element("region",
+                                       xmlns=XMLNS,
+                                       description=description)
+        if 'parent_region_id' in kwargs:
+            update_region.append(common.Element('parent_region_id',
+                                 kwargs.get('parent_region_id')))
+
+        resp, body = self.patch('regions/%s' % str(region_id),
+                                str(common.Document(update_region)))
+        body = self._parse_body(etree.fromstring(body))
+        return resp, body
+
+    def get_region(self, region_id):
+        """Get Region."""
+        url = 'regions/%s' % region_id
+        resp, body = self.get(url)
+        body = self._parse_body(etree.fromstring(body))
+        return resp, body
+
+    def list_regions(self, params=None):
+        """Get the list of regions."""
+        url = 'regions'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        body = self._parse_array(etree.fromstring(body))
+        return resp, body
+
+    def delete_region(self, region_id):
+        """Delete region."""
+        resp, body = self.delete('regions/%s' % region_id)
+        return resp, body
diff --git a/tempest/services/identity/xml/identity_client.py b/tempest/services/identity/xml/identity_client.py
index b213c1a..886ce7b 100644
--- a/tempest/services/identity/xml/identity_client.py
+++ b/tempest/services/identity/xml/identity_client.py
@@ -127,6 +127,11 @@
                               str(xml.Document(put_body)))
         return resp, self._parse_resp(body)
 
+    def list_extensions(self):
+        """List all the extensions."""
+        resp, body = self.get('/extensions')
+        return resp, self._parse_resp(body)
+
 
 class TokenClientXML(identity_client.TokenClientJSON):
     TYPE = "xml"
diff --git a/tempest/services/network/network_client_base.py b/tempest/services/network/network_client_base.py
index 2a797b2..81792c4 100644
--- a/tempest/services/network/network_client_base.py
+++ b/tempest/services/network/network_client_base.py
@@ -30,6 +30,7 @@
     'members': 'lb',
     'vpnservices': 'vpn',
     'ikepolicies': 'vpn',
+    'ipsecpolicies': 'vpn',
     'metering_labels': 'metering',
     'metering_label_rules': 'metering',
     'firewall_rules': 'fw',
@@ -47,6 +48,7 @@
     'security_groups': 'security_groups',
     'security_group_rules': 'security_group_rules',
     'ikepolicy': 'ikepolicies',
+    'ipsecpolicy': 'ipsecpolicies',
     'quotas': 'quotas',
     'firewall_policy': 'firewall_policies'
 }
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index a7a6b2c..22cc948 100644
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -38,7 +38,7 @@
         return _root_tag_fetcher_and_xml_to_json_parse(body)
 
     def serialize(self, body):
-        #TODO(enikanorov): implement better json to xml conversion
+        # TODO(enikanorov): implement better json to xml conversion
         # expecting the dict with single key
         root = body.keys()[0]
         post_body = common.Element(root)
diff --git a/tempest/services/volume/json/admin/volume_types_client.py b/tempest/services/volume/json/admin/volume_types_client.py
index c9c0582..65ecc67 100644
--- a/tempest/services/volume/json/admin/volume_types_client.py
+++ b/tempest/services/volume/json/admin/volume_types_client.py
@@ -18,6 +18,7 @@
 
 from tempest.common import rest_client
 from tempest import config
+from tempest import exceptions
 
 CONF = config.CONF
 
@@ -34,6 +35,26 @@
         self.build_interval = CONF.volume.build_interval
         self.build_timeout = CONF.volume.build_timeout
 
+    def is_resource_deleted(self, resource):
+        # to use this method self.resource must be defined to respective value
+        # Resource is a dictionary containing resource id and type
+        # Resource : {"id" : resource_id
+        #             "type": resource_type}
+        try:
+            if resource['type'] == "volume-type":
+                self.get_volume_type(resource['id'])
+            elif resource['type'] == "encryption-type":
+                resp, body = self.get_encryption_type(resource['id'])
+                assert 200 == resp.status
+                if not body:
+                    return True
+            else:
+                msg = (" resource value is either not defined or incorrect.")
+                raise exceptions.UnprocessableEntity(msg)
+        except exceptions.NotFound:
+            return True
+        return False
+
     def list_volume_types(self, params=None):
         """List all the volume_types created."""
         url = 'types'
@@ -150,3 +171,7 @@
         resp, body = self.post(url, post_body)
         body = json.loads(body)
         return resp, body['encryption']
+
+    def delete_encryption_type(self, vol_type_id):
+        """Delete the encryption type for the specified volume-type."""
+        return self.delete("/types/%s/encryption/provider" % str(vol_type_id))
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index b55a037..6c97497 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -24,13 +24,13 @@
 CONF = config.CONF
 
 
-class VolumesClientJSON(rest_client.RestClient):
+class BaseVolumesClientJSON(rest_client.RestClient):
     """
-    Client class to send CRUD Volume API requests to a Cinder endpoint
+    Base client class to send CRUD Volume API requests to a Cinder endpoint
     """
 
     def __init__(self, auth_provider):
-        super(VolumesClientJSON, self).__init__(auth_provider)
+        super(BaseVolumesClientJSON, self).__init__(auth_provider)
 
         self.service = CONF.volume.catalog_type
         self.build_interval = CONF.volume.build_interval
@@ -72,7 +72,8 @@
         Creates a new Volume.
         size: Size of volume in GB.
         Following optional keyword arguments are accepted:
-        display_name: Optional Volume Name.
+        display_name: Optional Volume Name(only for V1).
+        name: Optional Volume Name(only for V2).
         metadata: A dictionary of values to be used as metadata.
         volume_type: Optional Name of volume_type for the volume
         snapshot_id: When specified the volume is created from this snapshot
@@ -150,7 +151,6 @@
     def wait_for_volume_status(self, volume_id, status):
         """Waits for a Volume to reach a given status."""
         resp, body = self.get_volume(volume_id)
-        volume_name = body['display_name']
         volume_status = body['status']
         start = int(time.time())
 
@@ -162,9 +162,10 @@
                 raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
 
             if int(time.time()) - start >= self.build_timeout:
-                message = ('Volume %s failed to reach %s status within '
-                           'the required time (%s s).' %
-                           (volume_name, status, self.build_timeout))
+                message = 'Volume %s failed to reach %s status within '\
+                          'the required time (%s s).' % (volume_id,
+                                                         status,
+                                                         self.build_timeout)
                 raise exceptions.TimeoutException(message)
 
     def is_resource_deleted(self, id):
@@ -297,3 +298,9 @@
         url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
         resp, body = self.delete(url)
         return resp, body
+
+
+class VolumesClientJSON(BaseVolumesClientJSON):
+    """
+    Client class to send CRUD Volume V1 API requests to a Cinder endpoint
+    """
diff --git a/tempest/services/volume/v2/json/volumes_client.py b/tempest/services/volume/v2/json/volumes_client.py
index df20a2a..1f16ead 100644
--- a/tempest/services/volume/v2/json/volumes_client.py
+++ b/tempest/services/volume/v2/json/volumes_client.py
@@ -13,18 +13,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import json
-import time
-import urllib
-
-from tempest.common import rest_client
-from tempest import config
-from tempest import exceptions
-
-CONF = config.CONF
+from tempest.services.volume.json import volumes_client
 
 
-class VolumesV2ClientJSON(rest_client.RestClient):
+class VolumesV2ClientJSON(volumes_client.BaseVolumesClientJSON):
     """
     Client class to send CRUD Volume V2 API requests to a Cinder endpoint
     """
@@ -33,268 +25,3 @@
         super(VolumesV2ClientJSON, self).__init__(auth_provider)
 
         self.api_version = "v2"
-        self.service = CONF.volume.catalog_type
-        self.build_interval = CONF.volume.build_interval
-        self.build_timeout = CONF.volume.build_timeout
-
-    def get_attachment_from_volume(self, volume):
-        """Return the element 'attachment' from input volumes."""
-        return volume['attachments'][0]
-
-    def list_volumes(self, params=None):
-        """List all the volumes created."""
-        url = 'volumes'
-        if params:
-                url += '?%s' % urllib.urlencode(params)
-
-        resp, body = self.get(url)
-        body = json.loads(body)
-        return resp, body['volumes']
-
-    def list_volumes_with_detail(self, params=None):
-        """List the details of all volumes."""
-        url = 'volumes/detail'
-        if params:
-                url += '?%s' % urllib.urlencode(params)
-
-        resp, body = self.get(url)
-        body = json.loads(body)
-        return resp, body['volumes']
-
-    def get_volume(self, volume_id):
-        """Returns the details of a single volume."""
-        url = "volumes/%s" % str(volume_id)
-        resp, body = self.get(url)
-        body = json.loads(body)
-        return resp, body['volume']
-
-    def create_volume(self, size=None, **kwargs):
-        """
-        Creates a new Volume.
-        size: Size of volume in GB.
-        Following optional keyword arguments are accepted:
-        name: Optional Volume Name.
-        metadata: A dictionary of values to be used as metadata.
-        volume_type: Optional Name of volume_type for the volume
-        snapshot_id: When specified the volume is created from this snapshot
-        imageRef: When specified the volume is created from this image
-        """
-        # for bug #1293885:
-        # If no size specified, read volume size from CONF
-        if size is None:
-            size = CONF.volume.volume_size
-        post_body = {'size': size}
-        post_body.update(kwargs)
-        post_body = json.dumps({'volume': post_body})
-        resp, body = self.post('volumes', post_body)
-        body = json.loads(body)
-        return resp, body['volume']
-
-    def update_volume(self, volume_id, **kwargs):
-        """Updates the Specified Volume."""
-        put_body = json.dumps({'volume': kwargs})
-        resp, body = self.put('volumes/%s' % volume_id, put_body)
-        body = json.loads(body)
-        return resp, body['volume']
-
-    def delete_volume(self, volume_id):
-        """Deletes the Specified Volume."""
-        return self.delete("volumes/%s" % str(volume_id))
-
-    def upload_volume(self, volume_id, image_name, disk_format):
-        """Uploads a volume in Glance."""
-        post_body = {
-            'image_name': image_name,
-            'disk_format': disk_format
-        }
-        post_body = json.dumps({'os-volume_upload_image': post_body})
-        url = 'volumes/%s/action' % (volume_id)
-        resp, body = self.post(url, post_body)
-        body = json.loads(body)
-        return resp, body['os-volume_upload_image']
-
-    def attach_volume(self, volume_id, instance_uuid, mountpoint):
-        """Attaches a volume to a given instance on a given mountpoint."""
-        post_body = {
-            'instance_uuid': instance_uuid,
-            'mountpoint': mountpoint,
-        }
-        post_body = json.dumps({'os-attach': post_body})
-        url = 'volumes/%s/action' % (volume_id)
-        resp, body = self.post(url, post_body)
-        return resp, body
-
-    def detach_volume(self, volume_id):
-        """Detaches a volume from an instance."""
-        post_body = {}
-        post_body = json.dumps({'os-detach': post_body})
-        url = 'volumes/%s/action' % (volume_id)
-        resp, body = self.post(url, post_body)
-        return resp, body
-
-    def reserve_volume(self, volume_id):
-        """Reserves a volume."""
-        post_body = {}
-        post_body = json.dumps({'os-reserve': post_body})
-        url = 'volumes/%s/action' % (volume_id)
-        resp, body = self.post(url, post_body)
-        return resp, body
-
-    def unreserve_volume(self, volume_id):
-        """Restore a reserved volume ."""
-        post_body = {}
-        post_body = json.dumps({'os-unreserve': post_body})
-        url = 'volumes/%s/action' % (volume_id)
-        resp, body = self.post(url, post_body)
-        return resp, body
-
-    def wait_for_volume_status(self, volume_id, status):
-        """Waits for a Volume to reach a given status."""
-        resp, body = self.get_volume(volume_id)
-        volume_name = body['name']
-        volume_status = body['status']
-        start = int(time.time())
-
-        while volume_status != status:
-            time.sleep(self.build_interval)
-            resp, body = self.get_volume(volume_id)
-            volume_status = body['status']
-            if volume_status == 'error':
-                raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
-
-            if int(time.time()) - start >= self.build_timeout:
-                message = ('Volume %s failed to reach %s status within '
-                           'the required time (%s s).' %
-                           (volume_name, status, self.build_timeout))
-                raise exceptions.TimeoutException(message)
-
-    def is_resource_deleted(self, id):
-        try:
-            self.get_volume(id)
-        except exceptions.NotFound:
-            return True
-        return False
-
-    def extend_volume(self, volume_id, extend_size):
-        """Extend a volume."""
-        post_body = {
-            'new_size': extend_size
-        }
-        post_body = json.dumps({'os-extend': post_body})
-        url = 'volumes/%s/action' % (volume_id)
-        resp, body = self.post(url, post_body)
-        return resp, body
-
-    def reset_volume_status(self, volume_id, status):
-        """Reset the Specified Volume's Status."""
-        post_body = json.dumps({'os-reset_status': {"status": status}})
-        resp, body = self.post('volumes/%s/action' % volume_id, post_body)
-        return resp, body
-
-    def volume_begin_detaching(self, volume_id):
-        """Volume Begin Detaching."""
-        post_body = json.dumps({'os-begin_detaching': {}})
-        resp, body = self.post('volumes/%s/action' % volume_id, post_body)
-        return resp, body
-
-    def volume_roll_detaching(self, volume_id):
-        """Volume Roll Detaching."""
-        post_body = json.dumps({'os-roll_detaching': {}})
-        resp, body = self.post('volumes/%s/action' % volume_id, post_body)
-        return resp, body
-
-    def create_volume_transfer(self, vol_id, name=None):
-        """Create a volume transfer."""
-        post_body = {
-            'volume_id': vol_id
-        }
-        if name:
-            post_body['name'] = name
-        post_body = json.dumps({'transfer': post_body})
-        resp, body = self.post('os-volume-transfer', post_body)
-        body = json.loads(body)
-        return resp, body['transfer']
-
-    def get_volume_transfer(self, transfer_id):
-        """Returns the details of a volume transfer."""
-        url = "os-volume-transfer/%s" % str(transfer_id)
-        resp, body = self.get(url)
-        body = json.loads(body)
-        return resp, body['transfer']
-
-    def list_volume_transfers(self, params=None):
-        """List all the volume transfers created."""
-        url = 'os-volume-transfer'
-        if params:
-            url += '?%s' % urllib.urlencode(params)
-        resp, body = self.get(url)
-        body = json.loads(body)
-        return resp, body['transfers']
-
-    def delete_volume_transfer(self, transfer_id):
-        """Delete a volume transfer."""
-        return self.delete("os-volume-transfer/%s" % str(transfer_id))
-
-    def accept_volume_transfer(self, transfer_id, transfer_auth_key):
-        """Accept a volume transfer."""
-        post_body = {
-            'auth_key': transfer_auth_key,
-        }
-        url = 'os-volume-transfer/%s/accept' % transfer_id
-        post_body = json.dumps({'accept': post_body})
-        resp, body = self.post(url, post_body)
-        body = json.loads(body)
-        return resp, body['transfer']
-
-    def update_volume_readonly(self, volume_id, readonly):
-        """Update the Specified Volume readonly."""
-        post_body = {
-            'readonly': readonly
-        }
-        post_body = json.dumps({'os-update_readonly_flag': post_body})
-        url = 'volumes/%s/action' % (volume_id)
-        resp, body = self.post(url, post_body)
-        return resp, body
-
-    def force_delete_volume(self, volume_id):
-        """Force Delete Volume."""
-        post_body = json.dumps({'os-force_delete': {}})
-        resp, body = self.post('volumes/%s/action' % volume_id, post_body)
-        return resp, body
-
-    def create_volume_metadata(self, volume_id, metadata):
-        """Create metadata for the volume."""
-        put_body = json.dumps({'metadata': metadata})
-        url = "volumes/%s/metadata" % str(volume_id)
-        resp, body = self.post(url, put_body)
-        body = json.loads(body)
-        return resp, body['metadata']
-
-    def get_volume_metadata(self, volume_id):
-        """Get metadata of the volume."""
-        url = "volumes/%s/metadata" % str(volume_id)
-        resp, body = self.get(url)
-        body = json.loads(body)
-        return resp, body['metadata']
-
-    def update_volume_metadata(self, volume_id, metadata):
-        """Update metadata for the volume."""
-        put_body = json.dumps({'metadata': metadata})
-        url = "volumes/%s/metadata" % str(volume_id)
-        resp, body = self.put(url, put_body)
-        body = json.loads(body)
-        return resp, body['metadata']
-
-    def update_volume_metadata_item(self, volume_id, id, meta_item):
-        """Update metadata item for the volume."""
-        put_body = json.dumps({'meta': meta_item})
-        url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
-        resp, body = self.put(url, put_body)
-        body = json.loads(body)
-        return resp, body['meta']
-
-    def delete_volume_metadata_item(self, volume_id, id):
-        """Delete metadata item for the volume."""
-        url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
-        resp, body = self.delete(url)
-        return resp, body
diff --git a/tempest/services/volume/v2/xml/volumes_client.py b/tempest/services/volume/v2/xml/volumes_client.py
index 1fdaf19..c1bcf6e 100644
--- a/tempest/services/volume/v2/xml/volumes_client.py
+++ b/tempest/services/volume/v2/xml/volumes_client.py
@@ -13,32 +13,23 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import time
 import urllib
 
 from lxml import etree
 
-from tempest.common import rest_client
 from tempest.common import xml_utils as common
-from tempest import config
-from tempest import exceptions
-
-CONF = config.CONF
+from tempest.services.volume.xml import volumes_client
 
 
-class VolumesV2ClientXML(rest_client.RestClient):
+class VolumesV2ClientXML(volumes_client.BaseVolumesClientXML):
     """
-    Client class to send CRUD Volume API requests to a Cinder endpoint
+    Client class to send CRUD Volume API V2 requests to a Cinder endpoint
     """
-    TYPE = "xml"
 
     def __init__(self, auth_provider):
         super(VolumesV2ClientXML, self).__init__(auth_provider)
 
         self.api_version = "v2"
-        self.service = CONF.volume.catalog_type
-        self.build_interval = CONF.compute.build_interval
-        self.build_timeout = CONF.compute.build_timeout
 
     def _parse_volume(self, body):
         vol = dict((attr, body.get(attr)) for attr in body.keys())
@@ -53,46 +44,9 @@
                                        child.getchildren())
             else:
                 vol[tag] = common.xml_to_json(child)
+        self._translate_attributes_to_json(vol)
         return vol
 
-    def get_attachment_from_volume(self, volume):
-        """Return the element 'attachment' from input volumes."""
-        return volume['attachments']['attachment']
-
-    def _check_if_bootable(self, volume):
-        """
-        Check if the volume is bootable, also change the value
-        of 'bootable' from string to boolean.
-        """
-
-        # NOTE(jdg): Version 1 of Cinder API uses lc strings
-        # We should consider being explicit in this check to
-        # avoid introducing bugs like: LP #1227837
-
-        if volume['bootable'].lower() == 'true':
-            volume['bootable'] = True
-        elif volume['bootable'].lower() == 'false':
-            volume['bootable'] = False
-        else:
-            raise ValueError(
-                'bootable flag is supposed to be either True or False,'
-                'it is %s' % volume['bootable'])
-        return volume
-
-    def list_volumes(self, params=None):
-        """List all the volumes created."""
-        url = 'volumes'
-
-        if params:
-            url += '?%s' % urllib.urlencode(params)
-
-        resp, body = self.get(url)
-        body = etree.fromstring(body)
-        volumes = []
-        if body is not None:
-            volumes += [self._parse_volume(vol) for vol in list(body)]
-        return resp, volumes
-
     def list_volumes_with_detail(self, params=None):
         """List all the details of volumes."""
         url = 'volumes/detail'
@@ -116,293 +70,3 @@
         body = self._parse_volume(etree.fromstring(body))
         body = self._check_if_bootable(body)
         return resp, body
-
-    def create_volume(self, size=None, **kwargs):
-        """Creates a new Volume.
-
-        :param size: Size of volume in GB.
-        :param name: Optional Volume Name.
-        :param metadata: An optional dictionary of values for metadata.
-        :param volume_type: Optional Name of volume_type for the volume
-        :param snapshot_id: When specified the volume is created from
-                            this snapshot
-        :param imageRef: When specified the volume is created from this
-                         image
-        """
-        # for bug #1293885:
-        # If no size specified, read volume size from CONF
-        if size is None:
-            size = CONF.volume.volume_size
-        # NOTE(afazekas): it should use a volume namespace
-        volume = common.Element("volume", xmlns=common.XMLNS_11, size=size)
-
-        if 'metadata' in kwargs:
-            _metadata = common.Element('metadata')
-            volume.append(_metadata)
-            for key, value in kwargs['metadata'].items():
-                meta = common.Element('meta')
-                meta.add_attr('key', key)
-                meta.append(common.Text(value))
-                _metadata.append(meta)
-            attr_to_add = kwargs.copy()
-            del attr_to_add['metadata']
-        else:
-            attr_to_add = kwargs
-
-        for key, value in attr_to_add.items():
-            volume.add_attr(key, value)
-
-        resp, body = self.post('volumes', str(common.Document(volume)))
-        body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def update_volume(self, volume_id, **kwargs):
-        """Updates the Specified Volume."""
-        put_body = common.Element("volume", xmlns=common.XMLNS_11, **kwargs)
-
-        resp, body = self.put('volumes/%s' % volume_id,
-                              str(common.Document(put_body)))
-        body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def delete_volume(self, volume_id):
-        """Deletes the Specified Volume."""
-        return self.delete("volumes/%s" % str(volume_id))
-
-    def wait_for_volume_status(self, volume_id, status):
-        """Waits for a Volume to reach a given status."""
-        resp, body = self.get_volume(volume_id)
-        volume_status = body['status']
-        start = int(time.time())
-
-        while volume_status != status:
-            time.sleep(self.build_interval)
-            resp, body = self.get_volume(volume_id)
-            volume_status = body['status']
-            if volume_status == 'error':
-                raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
-
-            if int(time.time()) - start >= self.build_timeout:
-                message = 'Volume %s failed to reach %s status within '\
-                          'the required time (%s s).' % (volume_id,
-                                                         status,
-                                                         self.build_timeout)
-                raise exceptions.TimeoutException(message)
-
-    def is_resource_deleted(self, id):
-        try:
-            self.get_volume(id)
-        except exceptions.NotFound:
-            return True
-        return False
-
-    def attach_volume(self, volume_id, instance_uuid, mountpoint):
-        """Attaches a volume to a given instance on a given mountpoint."""
-        post_body = common.Element("os-attach",
-                                   instance_uuid=instance_uuid,
-                                   mountpoint=mountpoint
-                                   )
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def detach_volume(self, volume_id):
-        """Detaches a volume from an instance."""
-        post_body = common.Element("os-detach")
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def upload_volume(self, volume_id, image_name, disk_format):
-        """Uploads a volume in Glance."""
-        post_body = common.Element("os-volume_upload_image",
-                                   image_name=image_name,
-                                   disk_format=disk_format)
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        volume = common.xml_to_json(etree.fromstring(body))
-        return resp, volume
-
-    def extend_volume(self, volume_id, extend_size):
-        """Extend a volume."""
-        post_body = common.Element("os-extend",
-                                   new_size=extend_size)
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def reset_volume_status(self, volume_id, status):
-        """Reset the Specified Volume's Status."""
-        post_body = common.Element("os-reset_status",
-                                   status=status
-                                   )
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def volume_begin_detaching(self, volume_id):
-        """Volume Begin Detaching."""
-        post_body = common.Element("os-begin_detaching")
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def volume_roll_detaching(self, volume_id):
-        """Volume Roll Detaching."""
-        post_body = common.Element("os-roll_detaching")
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def reserve_volume(self, volume_id):
-        """Reserves a volume."""
-        post_body = common.Element("os-reserve")
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def unreserve_volume(self, volume_id):
-        """Restore a reserved volume ."""
-        post_body = common.Element("os-unreserve")
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def create_volume_transfer(self, vol_id, name=None):
-        """Create a volume transfer."""
-        post_body = common.Element("transfer", volume_id=vol_id)
-        if name:
-            post_body.add_attr('name', name)
-        resp, body = self.post('os-volume-transfer',
-                               str(common.Document(post_body)))
-        volume = common.xml_to_json(etree.fromstring(body))
-        return resp, volume
-
-    def get_volume_transfer(self, transfer_id):
-        """Returns the details of a volume transfer."""
-        url = "os-volume-transfer/%s" % str(transfer_id)
-        resp, body = self.get(url)
-        volume = common.xml_to_json(etree.fromstring(body))
-        return resp, volume
-
-    def list_volume_transfers(self, params=None):
-        """List all the volume transfers created."""
-        url = 'os-volume-transfer'
-        if params:
-            url += '?%s' % urllib.urlencode(params)
-
-        resp, body = self.get(url)
-        body = etree.fromstring(body)
-        volumes = []
-        if body is not None:
-            volumes += [self._parse_volume_transfer(vol) for vol in list(body)]
-        return resp, volumes
-
-    def _parse_volume_transfer(self, body):
-        vol = dict((attr, body.get(attr)) for attr in body.keys())
-        for child in body.getchildren():
-            tag = child.tag
-            if tag.startswith("{"):
-                tag = tag.split("}", 1)
-            vol[tag] = common.xml_to_json(child)
-        return vol
-
-    def delete_volume_transfer(self, transfer_id):
-        """Delete a volume transfer."""
-        return self.delete("os-volume-transfer/%s" % str(transfer_id))
-
-    def accept_volume_transfer(self, transfer_id, transfer_auth_key):
-        """Accept a volume transfer."""
-        post_body = common.Element("accept", auth_key=transfer_auth_key)
-        url = 'os-volume-transfer/%s/accept' % transfer_id
-        resp, body = self.post(url, str(common.Document(post_body)))
-        volume = common.xml_to_json(etree.fromstring(body))
-        return resp, volume
-
-    def update_volume_readonly(self, volume_id, readonly):
-        """Update the Specified Volume readonly."""
-        post_body = common.Element("os-update_readonly_flag",
-                                   readonly=readonly)
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def force_delete_volume(self, volume_id):
-        """Force Delete Volume."""
-        post_body = common.Element("os-force_delete")
-        url = 'volumes/%s/action' % str(volume_id)
-        resp, body = self.post(url, str(common.Document(post_body)))
-        if body:
-            body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def _metadata_body(self, meta):
-        post_body = common.Element('metadata')
-        for k, v in meta.items():
-            data = common.Element('meta', key=k)
-            data.append(common.Text(v))
-            post_body.append(data)
-        return post_body
-
-    def _parse_key_value(self, node):
-        """Parse <foo key='key'>value</foo> data into {'key': 'value'}."""
-        data = {}
-        for node in node.getchildren():
-            data[node.get('key')] = node.text
-        return data
-
-    def create_volume_metadata(self, volume_id, metadata):
-        """Create metadata for the volume."""
-        post_body = self._metadata_body(metadata)
-        resp, body = self.post('volumes/%s/metadata' % volume_id,
-                               str(common.Document(post_body)))
-        body = self._parse_key_value(etree.fromstring(body))
-        return resp, body
-
-    def get_volume_metadata(self, volume_id):
-        """Get metadata of the volume."""
-        url = "volumes/%s/metadata" % str(volume_id)
-        resp, body = self.get(url)
-        body = self._parse_key_value(etree.fromstring(body))
-        return resp, body
-
-    def update_volume_metadata(self, volume_id, metadata):
-        """Update metadata for the volume."""
-        put_body = self._metadata_body(metadata)
-        url = "volumes/%s/metadata" % str(volume_id)
-        resp, body = self.put(url, str(common.Document(put_body)))
-        body = self._parse_key_value(etree.fromstring(body))
-        return resp, body
-
-    def update_volume_metadata_item(self, volume_id, id, meta_item):
-        """Update metadata item for the volume."""
-        for k, v in meta_item.items():
-            put_body = common.Element('meta', key=k)
-            put_body.append(common.Text(v))
-        url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
-        resp, body = self.put(url, str(common.Document(put_body)))
-        body = common.xml_to_json(etree.fromstring(body))
-        return resp, body
-
-    def delete_volume_metadata_item(self, volume_id, id):
-        """Delete metadata item for the volume."""
-        url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
-        return self.delete(url)
diff --git a/tempest/services/volume/xml/backups_client.py b/tempest/services/volume/xml/backups_client.py
index 81caaee..a691a25 100644
--- a/tempest/services/volume/xml/backups_client.py
+++ b/tempest/services/volume/xml/backups_client.py
@@ -22,5 +22,5 @@
     """
     TYPE = "xml"
 
-    #TODO(gfidente): XML client isn't yet implemented because of bug 1270589
+    # TODO(gfidente): XML client isn't yet implemented because of bug 1270589
     pass
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index 9799e55..2d4a9e9 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -32,14 +32,14 @@
 VOLUMES_TENANT_NS = VOLUME_NS_BASE + 'volume_tenant_attribute/api/v1'
 
 
-class VolumesClientXML(rest_client.RestClient):
+class BaseVolumesClientXML(rest_client.RestClient):
     """
-    Client class to send CRUD Volume API requests to a Cinder endpoint
+    Base client class to send CRUD Volume API requests to a Cinder endpoint
     """
     TYPE = "xml"
 
     def __init__(self, auth_provider):
-        super(VolumesClientXML, self).__init__(auth_provider)
+        super(BaseVolumesClientXML, self).__init__(auth_provider)
         self.service = CONF.volume.catalog_type
         self.build_interval = CONF.compute.build_interval
         self.build_timeout = CONF.compute.build_timeout
@@ -141,6 +141,8 @@
         """Creates a new Volume.
 
         :param size: Size of volume in GB.
+        :param display_name: Optional Volume Name(only for V1).
+        :param name: Optional Volume Name(only for V2).
         :param display_name: Optional Volume Name.
         :param metadata: An optional dictionary of values for metadata.
         :param volume_type: Optional Name of volume_type for the volume
@@ -428,3 +430,9 @@
         """Delete metadata item for the volume."""
         url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
         return self.delete(url)
+
+
+class VolumesClientXML(BaseVolumesClientXML):
+    """
+    Client class to send CRUD Volume API V1 requests to a Cinder endpoint
+    """
diff --git a/tempest/stress/README.rst b/tempest/stress/README.rst
index b56f96b..0a63679 100644
--- a/tempest/stress/README.rst
+++ b/tempest/stress/README.rst
@@ -34,14 +34,14 @@
 In order to use this discovery you have to be in the tempest root directory
 and execute the following:
 
-	tempest/stress/run_stress.py -a -d 30
+	run-tempest-stress -a -d 30
 
 Running the sample test
 -----------------------
 
-To test installation, do the following (from the tempest/stress directory):
+To test installation, do the following:
 
-	./run_stress.py -t etc/server-create-destroy-test.json -d 30
+	run-tempest-stress -t tempest/stress/etc/server-create-destroy-test.json -d 30
 
 This sample test tries to create a few VMs and kill a few VMs.
 
diff --git a/tempest/stress/actions/volume_attach_delete.py b/tempest/stress/actions/volume_attach_delete.py
index c2e6072..b438f52 100644
--- a/tempest/stress/actions/volume_attach_delete.py
+++ b/tempest/stress/actions/volume_attach_delete.py
@@ -28,9 +28,9 @@
         # Step 1: create volume
         name = data_utils.rand_name("volume")
         self.logger.info("creating volume: %s" % name)
-        resp, volume = self.manager.volumes_client.create_volume(size=1,
-                                                                 display_name=
-                                                                 name)
+        resp, volume = self.manager.volumes_client.create_volume(
+            size=1,
+            display_name=name)
         assert(resp.status == 200)
         self.manager.volumes_client.wait_for_volume_status(volume['id'],
                                                            'available')
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index 1bc3b06..a3ca0b7 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -81,9 +81,9 @@
         name = data_utils.rand_name("volume")
         self.logger.info("creating volume: %s" % name)
         volumes_client = self.manager.volumes_client
-        resp, self.volume = volumes_client.create_volume(size=1,
-                                                         display_name=
-                                                         name)
+        resp, self.volume = volumes_client.create_volume(
+            size=1,
+            display_name=name)
         assert(resp.status == 200)
         volumes_client.wait_for_volume_status(self.volume['id'],
                                               'available')
diff --git a/tempest/test.py b/tempest/test.py
index 748a98c..650fad7 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -107,6 +107,7 @@
         'identity': True,
         'object_storage': CONF.service_available.swift,
         'dashboard': CONF.service_available.horizon,
+        'ceilometer': CONF.service_available.ceilometer,
     }
 
     def decorator(f):
@@ -256,6 +257,12 @@
 
     network_resources = {}
 
+    # NOTE(sdague): log_format is defined inline here instead of using the oslo
+    # default because going through the config path recouples config to the
+    # stress tests too early, and depending on testr order will fail unit tests
+    log_format = ('%(asctime)s %(process)d %(levelname)-8s '
+                  '[%(name)s] %(message)s')
+
     @classmethod
     def setUpClass(cls):
         if hasattr(super(BaseTestCase, cls), 'setUpClass'):
@@ -293,9 +300,8 @@
             self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
         if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
             os.environ.get('OS_LOG_CAPTURE') != '0'):
-            log_format = '%(asctime)-15s %(message)s'
             self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
-                                                   format=log_format,
+                                                   format=self.log_format,
                                                    level=None))
 
     @classmethod
@@ -396,7 +402,7 @@
 
         :param file: the file name
         """
-        #NOTE(mkoderer): must be extended for xml support
+        # NOTE(mkoderer): must be extended for xml support
         fn = os.path.join(
             os.path.abspath(os.path.dirname(os.path.dirname(__file__))),
             "etc", "schemas", file)
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 40caf30..d0140dd 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -15,6 +15,7 @@
 import json
 
 import mock
+from oslo.config import cfg
 
 from tempest.cmd import verify_tempest_config
 from tempest import config
@@ -152,6 +153,7 @@
                                            False, True)
 
     def test_verify_nova_versions(self):
+        cfg.CONF.set_default('api_v3', True, 'compute-feature-enabled')
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, '_get_unversioned_endpoint',
             return_value='http://fake_endpoint:5000'))
@@ -280,9 +282,9 @@
 
     def test_verify_extensions_nova(self):
         def fake_list_extensions():
-            return (None, {'extensions': [{'name': 'fake1'},
-                                          {'name': 'fake2'},
-                                          {'name': 'not_fake'}]})
+            return (None, {'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(
@@ -302,9 +304,9 @@
 
     def test_verify_extensions_nova_all(self):
         def fake_list_extensions():
-            return (None, {'extensions': [{'name': 'fake1'},
-                                          {'name': 'fake2'},
-                                          {'name': 'not_fake'}]})
+            return (None, {'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(
@@ -319,9 +321,9 @@
 
     def test_verify_extensions_nova_v3(self):
         def fake_list_extensions():
-            return (None, {'extensions': [{'name': 'fake1'},
-                                          {'name': 'fake2'},
-                                          {'name': 'not_fake'}]})
+            return (None, {'extensions': [{'alias': 'fake1'},
+                                          {'alias': 'fake2'},
+                                          {'alias': 'not_fake'}]})
         fake_os = mock.MagicMock()
         fake_os.extensions_v3_client.list_extensions = fake_list_extensions
         self.useFixture(mockpatch.PatchObject(
@@ -341,9 +343,9 @@
 
     def test_verify_extensions_nova_v3_all(self):
         def fake_list_extensions():
-            return (None, {'extensions': [{'name': 'fake1'},
-                                          {'name': 'fake2'},
-                                          {'name': 'not_fake'}]})
+            return (None, {'extensions': [{'alias': 'fake1'},
+                                          {'alias': 'fake2'},
+                                          {'alias': 'not_fake'}]})
         fake_os = mock.MagicMock()
         fake_os.extensions_v3_client.list_extensions = fake_list_extensions
         self.useFixture(mockpatch.PatchObject(
diff --git a/tempest/tests/common/utils/linux/__init__.py b/tempest/tests/common/utils/linux/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/tests/common/utils/linux/__init__.py
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
new file mode 100644
index 0000000..0db4cfa
--- /dev/null
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -0,0 +1,150 @@
+# Copyright 2014 IBM Corp.
+#
+#    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 time
+
+from oslo.config import cfg
+
+from tempest.common.utils.linux import remote_client
+from tempest import config
+from tempest.openstack.common.fixture import mockpatch
+from tempest.tests import base
+from tempest.tests import fake_config
+
+
+class TestRemoteClient(base.TestCase):
+    def setUp(self):
+        super(TestRemoteClient, self).setUp()
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+        cfg.CONF.set_default('ip_version_for_ssh', 4, group='compute')
+        cfg.CONF.set_default('network_for_ssh', 'public', group='compute')
+        cfg.CONF.set_default('ssh_channel_timeout', 1, group='compute')
+
+        self.conn = remote_client.RemoteClient('127.0.0.1', 'user', 'pass')
+        self.ssh_mock = self.useFixture(mockpatch.PatchObject(self.conn,
+                                                              'ssh_client'))
+
+    def test_hostname_equals_servername_for_expected_names(self):
+        self.ssh_mock.mock.exec_command.return_value = 'fake_hostname'
+        self.assertTrue(self.conn.hostname_equals_servername('fake_hostname'))
+
+    def test_hostname_equals_servername_for_unexpected_names(self):
+        self.ssh_mock.mock.exec_command.return_value = 'fake_hostname'
+        self.assertFalse(
+            self.conn.hostname_equals_servername('unexpected_hostname'))
+
+    def test_get_ram_size(self):
+        free_output = "Mem:         48294      45738       2555          0" \
+                      "402      40346"
+        self.ssh_mock.mock.exec_command.return_value = free_output
+        self.assertEqual(self.conn.get_ram_size_in_mb(), '48294')
+
+    def test_write_to_console_regular_str(self):
+        self.conn.write_to_console('test')
+        self._assert_exec_called_with(
+            'sudo sh -c "echo \\"test\\" >/dev/console"')
+
+    def _test_write_to_console_helper(self, message, expected_call):
+        self.conn.write_to_console(message)
+        self._assert_exec_called_with(expected_call)
+
+    def test_write_to_console_special_chars(self):
+        self._test_write_to_console_helper(
+            '\`',
+            'sudo sh -c "echo \\"\\\\\\`\\" >/dev/console"')
+        self.conn.write_to_console('$')
+        self._assert_exec_called_with(
+            'sudo sh -c "echo \\"\\\\$\\" >/dev/console"')
+
+    # NOTE(maurosr): The tests below end up closer to an output format
+    # assurance than a test since it's basically using comand_exec to format
+    # the information using gnu/linux tools.
+
+    def _assert_exec_called_with(self, cmd):
+        self.ssh_mock.mock.exec_command.assert_called_with(cmd)
+
+    def test_get_number_of_vcpus(self):
+        self.ssh_mock.mock.exec_command.return_value = '16'
+        self.assertEqual(self.conn.get_number_of_vcpus(), 16)
+        self._assert_exec_called_with(
+            'cat /proc/cpuinfo | grep processor | wc -l')
+
+    def test_get_partitions(self):
+        proc_partitions = """major minor  #blocks  name
+
+8        0  1048576 vda"""
+        self.ssh_mock.mock.exec_command.return_value = proc_partitions
+        self.assertEqual(self.conn.get_partitions(), proc_partitions)
+        self._assert_exec_called_with('cat /proc/partitions')
+
+    def test_get_boot_time(self):
+        booted_at = 10000
+        uptime_sec = 5000.02
+        self.ssh_mock.mock.exec_command.return_value = uptime_sec
+        self.useFixture(mockpatch.PatchObject(
+            time, 'time', return_value=booted_at + uptime_sec))
+        self.assertEqual(self.conn.get_boot_time(),
+                         time.localtime(booted_at))
+        self._assert_exec_called_with('cut -f1 -d. /proc/uptime')
+
+    def test_ping_host(self):
+        ping_response = """PING localhost (127.0.0.1) 56(84) bytes of data.
+64 bytes from localhost (127.0.0.1): icmp_req=1 ttl=64 time=0.048 ms
+
+--- localhost ping statistics ---
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+rtt min/avg/max/mdev = 0.048/0.048/0.048/0.000 ms"""
+        self.ssh_mock.mock.exec_command.return_value = ping_response
+        self.assertEqual(self.conn.ping_host('127.0.0.1'), ping_response)
+        self._assert_exec_called_with('ping -c1 -w1 127.0.0.1')
+
+    def test_get_mac_address(self):
+        macs = """0a:0b:0c:0d:0e:0f
+a0:b0:c0:d0:e0:f0"""
+        self.ssh_mock.mock.exec_command.return_value = macs
+
+        self.assertEqual(self.conn.get_mac_address(), macs)
+        self._assert_exec_called_with(
+            "/sbin/ifconfig | awk '/HWaddr/ {print $5}'")
+
+    def test_get_ip_list(self):
+        ips = """1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
+    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
+    inet 127.0.0.1/8 scope host lo
+    inet6 ::1/128 scope host
+       valid_lft forever preferred_lft forever
+2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
+    link/ether fa:16:3e:6e:26:3b brd ff:ff:ff:ff:ff:ff
+    inet 10.0.0.4/24 brd 10.0.0.255 scope global eth0
+    inet6 fd55:faaf:e1ab:3d9:f816:3eff:fe6e:263b/64 scope global dynamic
+       valid_lft 2591936sec preferred_lft 604736sec
+    inet6 fe80::f816:3eff:fe6e:263b/64 scope link
+       valid_lft forever preferred_lft forever"""
+        self.ssh_mock.mock.exec_command.return_value = ips
+        self.assertEqual(self.conn.get_ip_list(), ips)
+        self._assert_exec_called_with('/bin/ip address')
+
+    def test_assign_static_ip(self):
+        self.ssh_mock.mock.exec_command.return_value = ''
+        ip = '10.0.0.2'
+        nic = 'eth0'
+        self.assertEqual(self.conn.assign_static_ip(nic, ip), '')
+        self._assert_exec_called_with(
+            "sudo /bin/ip addr add %s/%s dev %s" % (ip, '28', nic))
+
+    def test_turn_nic_on(self):
+        nic = 'eth0'
+        self.conn.turn_nic_on(nic)
+        self._assert_exec_called_with('sudo /bin/ip link set %s up' % nic)
diff --git a/tempest/tests/fake_http.py b/tempest/tests/fake_http.py
index 7b878af..ce2b2c0 100644
--- a/tempest/tests/fake_http.py
+++ b/tempest/tests/fake_http.py
@@ -32,7 +32,6 @@
                 'headers': headers
             }
             return (fake_headers, return_obj)
-           # return (headers, return_obj)
         elif isinstance(self.return_type, int):
             body = "fake_body"
             header_info = {
diff --git a/tempest/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py
index c76abde..5a334c5 100644
--- a/tempest/tests/stress/test_stress.py
+++ b/tempest/tests/stress/test_stress.py
@@ -18,12 +18,12 @@
 
 import tempest.cli as cli
 from tempest.openstack.common import log as logging
-import tempest.test
+from tempest.tests import base
 
 LOG = logging.getLogger(__name__)
 
 
-class StressFrameworkTest(tempest.test.BaseTestCase):
+class StressFrameworkTest(base.TestCase):
     """Basic test for the stress test framework.
     """
 
@@ -51,5 +51,5 @@
         return proc.returncode
 
     def test_help_function(self):
-        result = self._cmd("python", "-m tempest.stress.run_stress -h")
+        result = self._cmd("python", "-m tempest.cmd.run_stress -h")
         self.assertEqual(0, result)
diff --git a/tempest/tests/test_glance_http.py b/tempest/tests/test_glance_http.py
index bb2df43..88b8129 100644
--- a/tempest/tests/test_glance_http.py
+++ b/tempest/tests/test_glance_http.py
@@ -54,26 +54,37 @@
                         return_value=resp))
         return resp
 
-    def test_json_request_without_content_type_header(self):
+    def test_json_request_without_content_type_header_in_response(self):
         self._set_response_fixture({}, 200, 'fake_response_body')
-        resp, body = self.client.json_request('GET', '/images')
-        self.assertEqual(200, resp.status)
-        self.assertIsNone(body)
+        self.assertRaises(exceptions.InvalidContentType,
+                          self.client.json_request, 'GET', '/images')
 
-    def test_json_request_with_xml_content_type_header(self):
+    def test_json_request_with_xml_content_type_header_in_request(self):
+        self.assertRaises(exceptions.InvalidContentType,
+                          self.client.json_request, 'GET', '/images',
+                          headers={'Content-Type': 'application/xml'})
+
+    def test_json_request_with_xml_content_type_header_in_response(self):
         self._set_response_fixture({'content-type': 'application/xml'},
                                    200, 'fake_response_body')
-        resp, body = self.client.json_request('GET', '/images')
-        self.assertEqual(200, resp.status)
-        self.assertIsNone(body)
+        self.assertRaises(exceptions.InvalidContentType,
+                          self.client.json_request, 'GET', '/images')
 
-    def test_json_request_with_content_type_header(self):
+    def test_json_request_with_json_content_type_header_only_in_resp(self):
         self._set_response_fixture({'content-type': 'application/json'},
                                    200, 'fake_response_body')
         resp, body = self.client.json_request('GET', '/images')
         self.assertEqual(200, resp.status)
         self.assertEqual('fake_response_body', body)
 
+    def test_json_request_with_json_content_type_header_in_req_and_resp(self):
+        self._set_response_fixture({'content-type': 'application/json'},
+                                   200, 'fake_response_body')
+        resp, body = self.client.json_request('GET', '/images', headers={
+            'Content-Type': 'application/json'})
+        self.assertEqual(200, resp.status)
+        self.assertEqual('fake_response_body', body)
+
     def test_json_request_fails_to_json_loads(self):
         self._set_response_fixture({'content-type': 'application/json'},
                                    200, 'fake_response_body')
diff --git a/tempest/tests/test_rest_client.py b/tempest/tests/test_rest_client.py
index d20520c..a351bd5 100644
--- a/tempest/tests/test_rest_client.py
+++ b/tempest/tests/test_rest_client.py
@@ -541,3 +541,50 @@
         self.assertRaises(AssertionError,
                           self.negative_rest_client.send_request,
                           'OTHER', self.url, [])
+
+
+class TestExpectedSuccess(BaseRestClientTestClass):
+
+    def setUp(self):
+        self.fake_http = fake_http.fake_httplib2()
+        super(TestExpectedSuccess, self).setUp()
+
+    def test_expected_succes_int_match(self):
+        expected_code = 202
+        read_code = 202
+        resp = self.rest_client.expected_success(expected_code, read_code)
+        # Assert None resp on success
+        self.assertFalse(resp)
+
+    def test_expected_succes_int_no_match(self):
+        expected_code = 204
+        read_code = 202
+        self.assertRaises(exceptions.InvalidHttpSuccessCode,
+                          self.rest_client.expected_success,
+                          expected_code, read_code)
+
+    def test_expected_succes_list_match(self):
+        expected_code = [202, 204]
+        read_code = 202
+        resp = self.rest_client.expected_success(expected_code, read_code)
+        # Assert None resp on success
+        self.assertFalse(resp)
+
+    def test_expected_succes_list_no_match(self):
+        expected_code = [202, 204]
+        read_code = 200
+        self.assertRaises(exceptions.InvalidHttpSuccessCode,
+                          self.rest_client.expected_success,
+                          expected_code, read_code)
+
+    def test_non_success_expected_int(self):
+        expected_code = 404
+        read_code = 202
+        self.assertRaises(AssertionError, self.rest_client.expected_success,
+                          expected_code, read_code)
+
+    def test_non_success_expected_list(self):
+        expected_code = [404, 202]
+        read_code = 202
+        self.assertRaises(AssertionError, self.rest_client.expected_success,
+                          expected_code, read_code)
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 7a9b6be..485beff 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -59,6 +59,8 @@
                                               '_get_object_storage_client'))
         self.useFixture(mockpatch.PatchObject(clients.OfficialClientManager,
                                               '_get_orchestration_client'))
+        self.useFixture(mockpatch.PatchObject(clients.OfficialClientManager,
+                                              '_get_ceilometer_client'))
         iso_creds = isolated_creds.IsolatedCreds('test class',
                                                  tempest_client=False)
         self.assertTrue(isinstance(iso_creds.identity_admin_client,
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 4c39f78..d3cbc4b 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -56,8 +56,8 @@
     A_I_IMAGES_READY = all_read(ami_path, aki_path, ari_path)
     boto_logger = logging.getLogger('boto')
     level = boto_logger.logger.level
-    boto_logger.logger.setLevel(orig_logging.CRITICAL)  # suppress logging
-                                                        # for these
+    # suppress logging for boto
+    boto_logger.logger.setLevel(orig_logging.CRITICAL)
 
     def _cred_sub_check(connection_data):
         if not id_matcher.match(connection_data["aws_access_key_id"]):
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index b2eb18d..7713931 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -20,7 +20,6 @@
 from tempest import config
 from tempest import exceptions
 from tempest.openstack.common import log as logging
-from tempest import test
 from tempest.thirdparty.boto import test as boto_test
 from tempest.thirdparty.boto.utils import s3
 from tempest.thirdparty.boto.utils import wait
@@ -80,10 +79,9 @@
             if state != "available":
                 for _image in cls.images.itervalues():
                     cls.ec2_client.deregister_image(_image["image_id"])
-                raise exceptions.EC2RegisterImageException(image_id=
-                                                           image["image_id"])
+                raise exceptions.EC2RegisterImageException(
+                    image_id=image["image_id"])
 
-    @test.attr(type='smoke')
     def test_run_idempotent_instances(self):
         # EC2 run instances idempotently
 
@@ -121,7 +119,6 @@
         _terminate_reservation(reservation_1, rcuk_1)
         _terminate_reservation(reservation_2, rcuk_2)
 
-    @test.attr(type='smoke')
     def test_run_stop_terminate_instance(self):
         # EC2 run, stop and terminate instance
         image_ami = self.ec2_client.get_image(self.images["ami"]
@@ -146,7 +143,6 @@
             instance.terminate()
         self.cancelResourceCleanUp(rcuk)
 
-    @test.attr(type='smoke')
     def test_run_stop_terminate_instance_with_tags(self):
         # EC2 run, stop and terminate instance with tags
         image_ami = self.ec2_client.get_image(self.images["ami"]
@@ -193,7 +189,6 @@
             instance.terminate()
         self.cancelResourceCleanUp(rcuk)
 
-    @test.attr(type='smoke')
     def test_run_terminate_instance(self):
         # EC2 run, terminate immediately
         image_ami = self.ec2_client.get_image(self.images["ami"]
@@ -217,7 +212,6 @@
         else:
             self.assertNotEqual(instance.state, "running")
 
-    @test.attr(type='smoke')
     def test_compute_with_volumes(self):
         # EC2 1. integration test (not strict)
         image_ami = self.ec2_client.get_image(self.images["ami"]["image_id"])
diff --git a/tempest/thirdparty/boto/test_ec2_keys.py b/tempest/thirdparty/boto/test_ec2_keys.py
index dec0170..698e3e1 100644
--- a/tempest/thirdparty/boto/test_ec2_keys.py
+++ b/tempest/thirdparty/boto/test_ec2_keys.py
@@ -32,7 +32,6 @@
         cls.ec = cls.ec2_error_code
 
 # TODO(afazekas): merge create, delete, get test cases
-    @test.attr(type='smoke')
     def test_create_ec2_keypair(self):
         # EC2 create KeyPair
         key_name = data_utils.rand_name("keypair-")
@@ -42,7 +41,6 @@
                         self.client.get_key_pair(key_name)))
 
     @test.skip_because(bug="1072318")
-    @test.attr(type='smoke')
     def test_delete_ec2_keypair(self):
         # EC2 delete KeyPair
         key_name = data_utils.rand_name("keypair-")
@@ -50,7 +48,6 @@
         self.client.delete_key_pair(key_name)
         self.assertIsNone(self.client.get_key_pair(key_name))
 
-    @test.attr(type='smoke')
     def test_get_ec2_keypair(self):
         # EC2 get KeyPair
         key_name = data_utils.rand_name("keypair-")
@@ -59,7 +56,6 @@
         self.assertTrue(compare_key_pairs(keypair,
                         self.client.get_key_pair(key_name)))
 
-    @test.attr(type='smoke')
     def test_duplicate_ec2_keypair(self):
         # EC2 duplicate KeyPair
         key_name = data_utils.rand_name("keypair-")
diff --git a/tempest/thirdparty/boto/test_ec2_network.py b/tempest/thirdparty/boto/test_ec2_network.py
index d508c07..792dde3 100644
--- a/tempest/thirdparty/boto/test_ec2_network.py
+++ b/tempest/thirdparty/boto/test_ec2_network.py
@@ -26,7 +26,6 @@
 
     # Note(afazekas): these tests for things duable without an instance
     @test.skip_because(bug="1080406")
-    @test.attr(type='smoke')
     def test_disassociate_not_associated_floating_ip(self):
         # EC2 disassociate not associated floating ip
         ec2_codes = self.ec2_error_code
diff --git a/tempest/thirdparty/boto/test_ec2_security_groups.py b/tempest/thirdparty/boto/test_ec2_security_groups.py
index 86140ec..7d9bdab 100644
--- a/tempest/thirdparty/boto/test_ec2_security_groups.py
+++ b/tempest/thirdparty/boto/test_ec2_security_groups.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest.common.utils import data_utils
-from tempest import test
 from tempest.thirdparty.boto import test as boto_test
 
 
@@ -25,7 +24,6 @@
         super(EC2SecurityGroupTest, cls).setUpClass()
         cls.client = cls.os.ec2api_client
 
-    @test.attr(type='smoke')
     def test_create_authorize_security_group(self):
         # EC2 Create, authorize/revoke security group
         group_name = data_utils.rand_name("securty_group-")
diff --git a/tempest/thirdparty/boto/test_ec2_volumes.py b/tempest/thirdparty/boto/test_ec2_volumes.py
index 12dea18..b50c6b0 100644
--- a/tempest/thirdparty/boto/test_ec2_volumes.py
+++ b/tempest/thirdparty/boto/test_ec2_volumes.py
@@ -15,7 +15,6 @@
 
 from tempest import config
 from tempest.openstack.common import log as logging
-from tempest import test
 from tempest.thirdparty.boto import test as boto_test
 
 CONF = config.CONF
@@ -40,7 +39,6 @@
         cls.client = cls.os.ec2api_client
         cls.zone = CONF.boto.aws_zone
 
-    @test.attr(type='smoke')
     def test_create_get_delete(self):
         # EC2 Create, get, delete Volume
         volume = self.client.create_volume(1, self.zone)
@@ -53,7 +51,6 @@
         self.client.delete_volume(volume.id)
         self.cancelResourceCleanUp(cuk)
 
-    @test.attr(type='smoke')
     def test_create_volume_from_snapshot(self):
         # EC2 Create volume from snapshot
         volume = self.client.create_volume(1, self.zone)
diff --git a/tempest/thirdparty/boto/test_s3_buckets.py b/tempest/thirdparty/boto/test_s3_buckets.py
index af6aa8b..3a8dc89 100644
--- a/tempest/thirdparty/boto/test_s3_buckets.py
+++ b/tempest/thirdparty/boto/test_s3_buckets.py
@@ -26,7 +26,6 @@
         cls.client = cls.os.s3_client
 
     @test.skip_because(bug="1076965")
-    @test.attr(type='smoke')
     def test_create_and_get_delete_bucket(self):
         # S3 Create, get and delete bucket
         bucket_name = data_utils.rand_name("s3bucket-")
diff --git a/tempest/thirdparty/boto/test_s3_ec2_images.py b/tempest/thirdparty/boto/test_s3_ec2_images.py
index d2300ee..389e25c 100644
--- a/tempest/thirdparty/boto/test_s3_ec2_images.py
+++ b/tempest/thirdparty/boto/test_s3_ec2_images.py
@@ -17,7 +17,6 @@
 
 from tempest.common.utils import data_utils
 from tempest import config
-from tempest import test
 from tempest.thirdparty.boto import test as boto_test
 from tempest.thirdparty.boto.utils import s3
 
@@ -48,7 +47,6 @@
                                cls.bucket_name)
         s3.s3_upload_dir(bucket, cls.materials_path)
 
-    @test.attr(type='smoke')
     def test_register_get_deregister_ami_image(self):
         # Register and deregister ami image
         image = {"name": data_utils.rand_name("ami-name-"),
diff --git a/tempest/thirdparty/boto/test_s3_objects.py b/tempest/thirdparty/boto/test_s3_objects.py
index 1ae46de..db3c1cf 100644
--- a/tempest/thirdparty/boto/test_s3_objects.py
+++ b/tempest/thirdparty/boto/test_s3_objects.py
@@ -18,7 +18,6 @@
 import boto.s3.key
 
 from tempest.common.utils import data_utils
-from tempest import test
 from tempest.thirdparty.boto import test as boto_test
 
 
@@ -29,7 +28,6 @@
         super(S3BucketsTest, cls).setUpClass()
         cls.client = cls.os.s3_client
 
-    @test.attr(type='smoke')
     def test_create_get_delete_object(self):
         # S3 Create, get and delete object
         bucket_name = data_utils.rand_name("s3bucket-")
diff --git a/test-requirements.txt b/test-requirements.txt
index b9c75c8..215f28b 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,7 +1,7 @@
-hacking>=0.8.0,<0.9
+hacking>=0.9.2,<0.10
 # needed for doc build
 docutils==0.9.1
-sphinx>=1.2.1,<1.3
+sphinx>=1.1.2,!=1.2.0,<1.3
 python-subunit>=0.0.18
 oslosphinx
 mox>=0.5.3
diff --git a/tools/pretty_tox.sh b/tools/pretty_tox.sh
index f3c88f3..0a04ce6 100755
--- a/tools/pretty_tox.sh
+++ b/tools/pretty_tox.sh
@@ -3,4 +3,4 @@
 set -o pipefail
 
 TESTRARGS=$1
-python setup.py testr --slowest --testr-args="--subunit $TESTRARGS" | $(dirname $0)/subunit-trace.py
+python setup.py testr --slowest --testr-args="--subunit $TESTRARGS" | $(dirname $0)/subunit-trace.py --no-failure-debug -f
diff --git a/tools/pretty_tox_serial.sh b/tools/pretty_tox_serial.sh
index 1634b8e..db70890 100755
--- a/tools/pretty_tox_serial.sh
+++ b/tools/pretty_tox_serial.sh
@@ -7,7 +7,8 @@
 if [ ! -d .testrepository ]; then
     testr init
 fi
-testr run --subunit $TESTRARGS | $(dirname $0)/subunit-trace.py
+testr run --subunit $TESTRARGS | $(dirname $0)/subunit-trace.py -f -n
 retval=$?
 testr slowest
+
 exit $retval
diff --git a/tools/subunit-trace.py b/tools/subunit-trace.py
index 7bb88a4..c6f8eab 100755
--- a/tools/subunit-trace.py
+++ b/tools/subunit-trace.py
@@ -18,6 +18,7 @@
 
 """Trace a subunit stream in reasonable detail and high accuracy."""
 
+import argparse
 import functools
 import re
 import sys
@@ -151,7 +152,7 @@
                 stream.write("    %s\n" % line)
 
 
-def show_outcome(stream, test):
+def show_outcome(stream, test, print_failures=False):
     global RESULTS
     status = test['status']
     # TODO(sdague): ask lifeless why on this?
@@ -178,14 +179,16 @@
         FAILS.append(test)
         stream.write('{%s} %s [%s] ... FAILED\n' % (
             worker, name, duration))
-        print_attachments(stream, test, all_channels=True)
+        if not print_failures:
+            print_attachments(stream, test, all_channels=True)
     elif status == 'skip':
         stream.write('{%s} %s ... SKIPPED: %s\n' % (
             worker, name, test['details']['reason'].as_text()))
     else:
         stream.write('{%s} %s [%s] ... %s\n' % (
             worker, name, duration, test['status']))
-        print_attachments(stream, test, all_channels=True)
+        if not print_failures:
+            print_attachments(stream, test, all_channels=True)
 
     stream.flush()
 
@@ -218,6 +221,14 @@
     return count
 
 
+def run_time():
+    runtime = 0.0
+    for k, v in RESULTS.items():
+        for test in v:
+            runtime += float(get_duration(test['timestamps']).strip('s'))
+    return runtime
+
+
 def worker_stats(worker):
     tests = RESULTS[worker]
     num_tests = len(tests)
@@ -227,7 +238,8 @@
 
 def print_summary(stream):
     stream.write("\n======\nTotals\n======\n")
-    stream.write("Run: %s\n" % count_tests('status', '.*'))
+    stream.write("Run: %s in %s sec.\n" % (count_tests('status', '.*'),
+                                           run_time()))
     stream.write(" - Passed: %s\n" % count_tests('status', 'success'))
     stream.write(" - Skipped: %s\n" % count_tests('status', 'skip'))
     stream.write(" - Failed: %s\n" % count_tests('status', 'fail'))
@@ -247,12 +259,25 @@
                              (w, num, time))
 
 
+def parse_args():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--no-failure-debug', '-n', action='store_true',
+                        dest='print_failures', help='Disable printing failure '
+                        'debug infomation in realtime')
+    parser.add_argument('--fails', '-f', action='store_true',
+                        dest='post_fails', help='Print failure debug '
+                        'information after the stream is proccesed')
+    return parser.parse_args()
+
+
 def main():
+    args = parse_args()
     stream = subunit.ByteStreamToStreamResult(
         sys.stdin, non_subunit_name='stdout')
     starts = Starts(sys.stdout)
     outcomes = testtools.StreamToDict(
-        functools.partial(show_outcome, sys.stdout))
+        functools.partial(show_outcome, sys.stdout,
+                          print_failures=args.print_failures))
     summary = testtools.StreamSummary()
     result = testtools.CopyStreamResult([starts, outcomes, summary])
     result.startTestRun()
@@ -260,6 +285,8 @@
         stream.run(result)
     finally:
         result.stopTestRun()
+    if args.post_fails:
+        print_fails(sys.stdout)
     print_summary(sys.stdout)
     return (0 if summary.wasSuccessful() else 1)
 
diff --git a/tox.ini b/tox.ini
index 2110362..c1acde9 100644
--- a/tox.ini
+++ b/tox.ini
@@ -77,7 +77,7 @@
 [testenv:stress]
 sitepackages = True
 commands =
-    python -m tempest/stress/run_stress -a -d 3600 -S
+    run-tempest-stress -a -d 3600 -S
 
 [testenv:venv]
 commands = {posargs}
@@ -99,6 +99,8 @@
 
 [flake8]
 # E125 is a won't fix until https://github.com/jcrocholl/pep8/issues/126 is resolved.  For further detail see https://review.openstack.org/#/c/36788/
-ignore = E125,H404
+# H402 skipped because some docstrings aren't sentences
+# Skipped because of new hacking 0.9: H407,H405,H904,H305,E123,H307,E122,E129,E128
+ignore = E125,H402,H404,H407,H405,H904,H305,E123,H307,E122,E129,E128
 show-source = True
 exclude = .git,.venv,.tox,dist,doc,openstack,*egg