Merge "Mising CLI test for Keystone"
diff --git a/README.rst b/README.rst
index 9daf873..4393ae9 100644
--- a/README.rst
+++ b/README.rst
@@ -7,7 +7,7 @@
 deployment.
 
 Design Principles
-----------
+-----------------
 Tempest Design Principles that we strive to live by.
 
 - Tempest should be able to run against any OpenStack cloud, be it a
@@ -127,6 +127,6 @@
 of tempest when running with Python 2.6. Additionally, to enable testr to work
 with tempest using python 2.6 the discover module from the unittest-ext
 project has to be patched to switch the unittest.TestSuite to use
-unittest2.TestSuite instead. See::
+unittest2.TestSuite instead. See:
 
 https://code.google.com/p/unittest-ext/issues/detail?id=79
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 1c32b9c..c45273e 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -33,14 +33,6 @@
    field_guide/thirdparty
    field_guide/unit_tests
 
-------------------
-API and test cases
-------------------
-.. toctree::
-   :maxdepth: 1
-
-   api/modules
-
 ==================
 Indices and tables
 ==================
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 37d4d53..9f2f924 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -711,6 +711,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 +980,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/tempest/api/baremetal/test_ports.py b/tempest/api/baremetal/test_ports.py
index 8b76811..aeb77e3 100644
--- a/tempest/api/baremetal/test_ports.py
+++ b/tempest/api/baremetal/test_ports.py
@@ -165,8 +165,8 @@
         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)
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/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/test_cluster_templates.py b/tempest/api/data_processing/test_cluster_templates.py
new file mode 100644
index 0000000..c08d6ba
--- /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/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..2df3f7f 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -247,11 +247,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 +287,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_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_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/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_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/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_schema/compute/servers.py b/tempest/api_schema/compute/servers.py
index 2002927..4e8c201 100644
--- a/tempest/api_schema/compute/servers.py
+++ b/tempest/api_schema/compute/servers.py
@@ -84,9 +84,13 @@
                     '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']
             }
         }
     }
@@ -114,6 +118,8 @@
 
 list_server_metadata = copy.deepcopy(set_server_metadata)
 
+update_server_metadata = copy.deepcopy(set_server_metadata)
+
 delete_server_metadata_item = {
     'status_code': [204]
 }
diff --git a/tempest/api_schema/compute/v3/servers.py b/tempest/api_schema/compute/v3/servers.py
index 682021f..6716249 100644
--- a/tempest/api_schema/compute/v3/servers.py
+++ b/tempest/api_schema/compute/v3/servers.py
@@ -95,3 +95,7 @@
         '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]
diff --git a/tempest/cli/simple_read_only/test_cinder.py b/tempest/cli/simple_read_only/test_cinder.py
index 723333b..9001302 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')
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..7532bf2 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)
diff --git a/tempest/config.py b/tempest/config.py
index a06c9a6..6d9fda6 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -415,6 +415,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 +642,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")
 ]
 
 
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index f4850bb..7703d4d 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
@@ -446,6 +447,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 +546,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):
     """
@@ -781,6 +855,51 @@
                                                   private_key)
             linux_client.validate_authentication()
 
+    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:
+            ex_msg = 'Public network connectivity check failed'
+            if msg:
+                ex_msg += ": " + msg
+            LOG.exception(ex_msg)
+            self._log_console_output(servers)
+            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:
+            LOG.exception('Tenant network connectivity check failed')
+            self._log_console_output(servers_for_debug)
+            debug.log_net_debug()
+            raise
+
     def _check_remote_connectivity(self, source, dest, should_succeed=True):
         """
         check ping server via source ssh connection
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index c53aa83..82c6b5d 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:
@@ -65,21 +41,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()
@@ -98,43 +64,6 @@
             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()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index e0d5779..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
@@ -85,55 +84,16 @@
                                                     public_network_id)
         self.addCleanup(self.cleanup_wrapper, self.floating_ip)
 
-    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..21782ee 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -156,24 +156,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 +173,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/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 70123fe..36bb02f 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -308,6 +308,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):
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
index f397c4b..f15f370 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -324,6 +324,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 +432,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)
 
diff --git a/tempest/services/data_processing/v1_1/client.py b/tempest/services/data_processing/v1_1/client.py
index 73e67c3..4465968 100644
--- a/tempest/services/data_processing/v1_1/client.py
+++ b/tempest/services/data_processing/v1_1/client.py
@@ -186,3 +186,9 @@
 
         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)
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/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py
index 757d484..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.
     """
 
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..9bfefe1 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()
 
@@ -247,12 +250,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 +276,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)