Merge "Testcase to create bulk networks in one API call"
diff --git a/run_tests.sh b/run_tests.sh
index f8636c1..f995cde 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -108,6 +108,21 @@
   fi
 }
 
+function run_tests_nose {
+    NOSE_WITH_OPENSTACK=1
+    NOSE_OPENSTACK_COLOR=1
+    NOSE_OPENSTACK_RED=15.00
+    NOSE_OPENSTACK_YELLOW=3.00
+    NOSE_OPENSTACK_SHOW_ELAPSED=1
+    NOSE_OPENSTACK_STDOUT=1
+    if [[ "x$noseargs" =~ "tempest" ]]; then
+        noseargs="$testrargs"
+    else
+        noseargs="$noseargs tempest"
+    fi
+    ${wrapper} nosetests $noseargs
+}
+
 function run_pep8 {
   echo "Running pep8 ..."
   ${wrapper} flake8
@@ -162,7 +177,13 @@
     run_coverage_start
 fi
 
-run_tests
+
+py_version=`${wrapper} python --version 2>&1`
+if [[ $py_version =~ "2.6" ]] ; then
+    run_tests_nose
+else
+    run_tests
+fi
 retval=$?
 
 if [ $nova_coverage -eq 1 ]; then
diff --git a/tempest/api/README.rst b/tempest/api/README.rst
index 617fda4..9d8dc10 100644
--- a/tempest/api/README.rst
+++ b/tempest/api/README.rst
@@ -9,15 +9,15 @@
 works with the OpenStack API as documented. The current largest
 portion of Tempest code is devoted to test cases that do exactly this.
 
-It's also important to test not only the expected possitive path on
+It's also important to test not only the expected positive path on
 APIs, but also to provide them with invalid data to ensure they fail
 in expected and documented ways. Over the course of the OpenStack
 project Tempest has discovered many fundamental bugs by doing just
 this.
 
-In order for some APIs to return meaniful results, there must be
+In order for some APIs to return meaningful results, there must be
 enough data in the system. This means these tests might start by
-spinning up a server, image, etc, then opperating on it.
+spinning up a server, image, etc, then operating on it.
 
 
 Why are these tests in tempest?
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 6d0a5b5..69e15f7 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -15,6 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api import compute
 from tempest.api.compute import base
 from tempest.common.utils.data_utils import rand_int_id
@@ -193,9 +195,10 @@
                 flag = True
         self.assertTrue(flag)
 
+    @testtools.skip("Skipped until the Bug #1209101 is resolved")
     @attr(type='gate')
-    def test_flavor_not_public_verify_entry_not_in_list_details(self):
-        # Create a flavor with os-flavor-access:is_public false should not
+    def test_list_non_public_flavor(self):
+        # Create a flavor with os-flavor-access:is_public false should
         # be present in list_details.
         # This operation requires the user to have 'admin' role
         flavor_name = rand_name(self.flavor_name_prefix)
@@ -208,13 +211,22 @@
                                                  new_flavor_id,
                                                  is_public="False")
         self.addCleanup(self.flavor_clean_up, flavor['id'])
-        flag = False
         # Verify flavor is retrieved
+        flag = False
         resp, flavors = self.client.list_flavors_with_detail()
         self.assertEqual(resp.status, 200)
         for flavor in flavors:
             if flavor['name'] == flavor_name:
                 flag = True
+        self.assertTrue(flag)
+
+        # Verify flavor is not retrieved with other user
+        flag = False
+        resp, flavors = self.user_client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        for flavor in flavors:
+            if flavor['name'] == flavor_name:
+                flag = True
         self.assertFalse(flag)
 
     @attr(type='gate')
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
index 849cebb..af76ad0 100644
--- a/tempest/api/compute/admin/test_hosts.py
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -33,13 +33,13 @@
         cls.client = cls.os_adm.hosts_client
         cls.non_admin_client = cls.os.hosts_client
 
-    @attr(type=['positive', 'gate'])
+    @attr(type='gate')
     def test_list_hosts(self):
         resp, hosts = self.client.list_hosts()
         self.assertEqual(200, resp.status)
         self.assertTrue(len(hosts) >= 2)
 
-    @attr(type='positive')
+    @attr(type='gate')
     def test_list_hosts_with_zone(self):
         resp, hosts = self.client.list_hosts()
         host = hosts[0]
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index 00a5955..5ca16f4 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -40,20 +40,20 @@
         self.assertEqual(200, resp.status)
         return hypers
 
-    @attr(type=['positive', 'gate'])
+    @attr(type='gate')
     def test_get_hypervisor_list(self):
         # List of hypervisor and available hypervisors hostname
         hypers = self._list_hypervisors()
         self.assertTrue(len(hypers) > 0)
 
-    @attr(type=['positive', 'gate'])
+    @attr(type='gate')
     def test_get_hypervisor_list_details(self):
         # Display the details of the all hypervisor
         resp, hypers = self.client.get_hypervisor_list_details()
         self.assertEqual(200, resp.status)
         self.assertTrue(len(hypers) > 0)
 
-    @attr(type=['positive', 'gate'])
+    @attr(type='gate')
     def test_get_hypervisor_show_details(self):
         # Display the details of the specified hypervisor
         hypers = self._list_hypervisors()
@@ -66,7 +66,7 @@
         self.assertEqual(details['hypervisor_hostname'],
                          hypers[0]['hypervisor_hostname'])
 
-    @attr(type=['positive', 'gate'])
+    @attr(type='gate')
     def test_get_hypervisor_show_servers(self):
         # Show instances about the specific hypervisors
         hypers = self._list_hypervisors()
@@ -77,14 +77,14 @@
         self.assertEqual(200, resp.status)
         self.assertTrue(len(hypervisors) > 0)
 
-    @attr(type=['positive', 'gate'])
+    @attr(type='gate')
     def test_get_hypervisor_stats(self):
         # Verify the stats of the all hypervisor
         resp, stats = self.client.get_hypervisor_stats()
         self.assertEqual(200, resp.status)
         self.assertTrue(len(stats) > 0)
 
-    @attr(type=['positive', 'gate'])
+    @attr(type='gate')
     def test_get_hypervisor_uptime(self):
         # Verify that GET shows the specified hypervisor uptime
         hypers = self._list_hypervisors()
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 4e42dd0..156274d 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -84,24 +84,14 @@
                          'key_pairs': 200, 'injected_file_path_bytes': 512,
                          'instances': 20, 'security_group_rules': 20,
                          'cores': 2, 'security_groups': 20}
-        try:
-            # Update limits for all quota resources
-            resp, quota_set = self.adm_client.update_quota_set(
-                self.demo_tenant_id,
-                **new_quota_set)
-            self.addCleanup(self.adm_client.update_quota_set,
-                            self.demo_tenant_id, **self.default_quota_set)
-            self.assertEqual(200, resp.status)
-            self.assertEqual(new_quota_set, quota_set)
-        except Exception:
-            self.fail("Admin could not update quota set for the tenant")
-        finally:
-            # Reset quota resource limits to default values
-            resp, quota_set = self.adm_client.update_quota_set(
-                self.demo_tenant_id,
-                **self.default_quota_set)
-            self.assertEqual(200, resp.status, "Failed to reset quota "
-                             "defaults")
+        # Update limits for all quota resources
+        resp, quota_set = self.adm_client.update_quota_set(
+            self.demo_tenant_id,
+            **new_quota_set)
+        self.addCleanup(self.adm_client.update_quota_set,
+                        self.demo_tenant_id, **self.default_quota_set)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(new_quota_set, quota_set)
 
     # TODO(afazekas): merge these test cases
     @attr(type='gate')
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 15e28fd..acf0275 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -36,6 +36,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(BaseComputeTest, cls).setUpClass()
         if not cls.config.service_available.nova:
             skip_msg = ("%s skipped as nova is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index b8f965c..ade7604 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -20,6 +20,7 @@
 from tempest.api.compute import base
 from tempest.api import utils
 from tempest.common.utils.data_utils import rand_name
+from tempest import config
 from tempest import exceptions
 from tempest.test import attr
 
@@ -218,6 +219,8 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
+    @testtools.skipIf(config.TempestConfig().service_available.neutron,
+                      "Skipped until the Bug #1182883 is resolved")
     @attr(type='gate')
     def test_list_servers_filtered_by_ip_regex(self):
         # Filter servers by regex ip
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index e756870..a3b051e 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -1,6 +1,6 @@
 # vim: tabstop=4 shiftwidth=4 softtabstop=4
 
-# Copyright 2012 IBM Corp.
+# Copyright 2013 IBM Corp.
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -42,10 +42,11 @@
             raise cls.skipException(skip_msg)
 
     def _detach(self, server_id, volume_id):
-        self.servers_client.detach_volume(server_id, volume_id)
-        self.volumes_client.wait_for_volume_status(volume_id, 'available')
+        if self.attached:
+            self.servers_client.detach_volume(server_id, volume_id)
+            self.volumes_client.wait_for_volume_status(volume_id, 'available')
 
-    def _delete(self, volume):
+    def _delete_volume(self):
         if self.volume:
             self.volumes_client.delete_volume(self.volume['id'])
             self.volume = None
@@ -63,6 +64,7 @@
         resp, volume = self.volumes_client.create_volume(1,
                                                          display_name='test')
         self.volume = volume
+        self.addCleanup(self._delete_volume)
         self.volumes_client.wait_for_volume_status(volume['id'], 'available')
 
         # Attach the volume to the server
@@ -71,49 +73,41 @@
         self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
 
         self.attached = True
+        self.addCleanup(self._detach, server['id'], volume['id'])
 
     @testtools.skipIf(not run_ssh, 'SSH required for this test')
     @attr(type='gate')
     def test_attach_detach_volume(self):
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
-        try:
-            self._create_and_attach()
-            server = self.server
-            volume = self.volume
+        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(server['id'])
+        self.servers_client.wait_for_server_status(server['id'], 'SHUTOFF')
 
-            self.servers_client.start(server['id'])
-            self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
+        self.servers_client.start(server['id'])
+        self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
 
-            linux_client = RemoteClient(server,
-                                        self.ssh_user, server['adminPass'])
-            partitions = linux_client.get_partitions()
-            self.assertIn(self.device, partitions)
+        linux_client = RemoteClient(server,
+                                    self.ssh_user, server['adminPass'])
+        partitions = linux_client.get_partitions()
+        self.assertIn(self.device, partitions)
 
-            self._detach(server['id'], volume['id'])
-            self.attached = False
+        self._detach(server['id'], 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(server['id'])
+        self.servers_client.wait_for_server_status(server['id'], 'SHUTOFF')
 
-            self.servers_client.start(server['id'])
-            self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
+        self.servers_client.start(server['id'])
+        self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
 
-            linux_client = RemoteClient(server,
-                                        self.ssh_user, server['adminPass'])
-            partitions = linux_client.get_partitions()
-            self.assertNotIn(self.device, partitions)
-        except Exception:
-            self.fail("The test_attach_detach_volume is faild!")
-        finally:
-            if self.attached:
-                self._detach(server['id'], volume['id'])
-            # NOTE(maurosr): here we do the cleanup for volume, servers are
-            # dealt on BaseComputeTest.tearDownClass
-            self._delete(self.volume)
+        linux_client = RemoteClient(server,
+                                    self.ssh_user, server['adminPass'])
+        partitions = linux_client.get_partitions()
+        self.assertNotIn(self.device, partitions)
 
 
 class AttachVolumeTestXML(AttachVolumeTestJSON):
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 9f7b24b..d98fb71 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -53,6 +53,7 @@
             cls.client.delete_endpoint(e['id'])
         for s in cls.service_ids:
             cls.identity_client.delete_service(s)
+        super(EndPointsTestJSON, cls).tearDownClass()
 
     @attr(type='gate')
     def test_list_endpoints(self):
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 1237ce4..bfb5372 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -25,6 +25,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(BaseIdentityAdminTest, cls).setUpClass()
         os = clients.AdminManager(interface=cls._interface)
         cls.client = os.identity_client
         cls.token_client = os.token_client
@@ -45,6 +46,7 @@
     @classmethod
     def tearDownClass(cls):
         cls.data.teardown_all()
+        super(BaseIdentityAdminTest, cls).tearDownClass()
 
     def disable_user(self, user_name):
         user = self.get_user_by_name(user_name)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 4e61495..4f54a15 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -29,6 +29,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(BaseImageTest, cls).setUpClass()
         cls.created_images = []
         cls._interface = 'json'
         cls.isolated_creds = isolated_creds.IsolatedCreds(cls.__name__)
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index d3fa763..2a3b3f7 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -47,6 +47,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(BaseNetworkTest, cls).setUpClass()
         os = clients.Manager()
         cls.network_cfg = os.config.network
         if not cls.config.service_available.neutron:
@@ -64,6 +65,7 @@
             cls.client.delete_subnet(subnet['id'])
         for network in cls.networks:
             cls.client.delete_network(network['id'])
+        super(BaseNetworkTest, cls).tearDownClass()
 
     @classmethod
     def create_network(cls, network_name=None):
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
new file mode 100644
index 0000000..df85682
--- /dev/null
+++ b/tempest/api/network/test_routers.py
@@ -0,0 +1,133 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.network import base
+from tempest.common.utils.data_utils import rand_name
+from tempest.test import attr
+
+
+class RoutersTest(base.BaseNetworkTest):
+
+    @classmethod
+    def setUpClass(cls):
+        super(RoutersTest, cls).setUpClass()
+
+    def _delete_router(self, router_id):
+        resp, _ = self.client.delete_router(router_id)
+        self.assertEqual(204, resp.status)
+        # Asserting that the router is not found in the list
+        # after deletion
+        resp, list_body = self.client.list_routers()
+        self.assertEqual('200', resp['status'])
+        routers_list = list()
+        for router in list_body['routers']:
+            routers_list.append(router['id'])
+        self.assertNotIn(router_id, routers_list)
+
+    def _remove_router_interface_with_subnet_id(self, router_id, subnet_id):
+        resp, _ = self.client.remove_router_interface_with_subnet_id(
+            router_id, subnet_id)
+        self.assertEqual('200', resp['status'])
+
+    def _remove_router_interface_with_port_id(self, router_id, port_id):
+        resp, _ = self.client.remove_router_interface_with_port_id(
+            router_id, port_id)
+        self.assertEqual('200', resp['status'])
+
+    @attr(type='gate')
+    def test_create_show_list_update_delete_router(self):
+        # Create a router
+        name = rand_name('router-')
+        resp, create_body = self.client.create_router(
+            name, external_gateway_info={
+                "network_id": self.network_cfg.public_network_id},
+            admin_state_up=False)
+        self.assertEqual('201', resp['status'])
+        self.addCleanup(self._delete_router, create_body['router']['id'])
+        self.assertEqual(create_body['router']['name'], name)
+        self.assertEqual(
+            create_body['router']['external_gateway_info']['network_id'],
+            self.network_cfg.public_network_id)
+        self.assertEqual(create_body['router']['admin_state_up'], False)
+        # Show details of the created router
+        resp, show_body = self.client.show_router(
+            create_body['router']['id'])
+        self.assertEqual('200', resp['status'])
+        self.assertEqual(show_body['router']['name'], name)
+        self.assertEqual(
+            show_body['router']['external_gateway_info']['network_id'],
+            self.network_cfg.public_network_id)
+        self.assertEqual(show_body['router']['admin_state_up'], False)
+        # List routers and verify if created router is there in response
+        resp, list_body = self.client.list_routers()
+        self.assertEqual('200', resp['status'])
+        routers_list = list()
+        for router in list_body['routers']:
+            routers_list.append(router['id'])
+        self.assertIn(create_body['router']['id'], routers_list)
+        # Update the name of router and verify if it is updated
+        updated_name = 'updated ' + name
+        resp, update_body = self.client.update_router(
+            create_body['router']['id'], name=updated_name)
+        self.assertEqual('200', resp['status'])
+        self.assertEqual(update_body['router']['name'], updated_name)
+        resp, show_body = self.client.show_router(
+            create_body['router']['id'])
+        self.assertEqual(show_body['router']['name'], updated_name)
+
+    @attr(type='gate')
+    def test_add_remove_router_interface_with_subnet_id(self):
+        network = self.create_network()
+        subnet = self.create_subnet(network)
+        name = rand_name('router-')
+        resp, create_body = self.client.create_router(name)
+        self.addCleanup(self.client.delete_router, create_body['router']['id'])
+        # Add router interafce with subnet id
+        resp, interface = self.client.add_router_interface_with_subnet_id(
+            create_body['router']['id'], subnet['id'])
+        self.assertEqual('200', resp['status'])
+        self.addCleanup(self._remove_router_interface_with_subnet_id,
+                        create_body['router']['id'], subnet['id'])
+        self.assertTrue('subnet_id' in interface.keys())
+        self.assertTrue('port_id' in interface.keys())
+        # Verify router id is equal to device id in port details
+        resp, show_port_body = self.client.show_port(
+            interface['port_id'])
+        self.assertEqual(show_port_body['port']['device_id'],
+                         create_body['router']['id'])
+
+    @attr(type='gate')
+    def test_add_remove_router_interface_with_port_id(self):
+        network = self.create_network()
+        self.create_subnet(network)
+        name = rand_name('router-')
+        resp, create_body = self.client.create_router(name)
+        self.addCleanup(self.client.delete_router, create_body['router']['id'])
+        resp, port_body = self.client.create_port(network['id'])
+        # add router interface to port created above
+        resp, interface = self.client.add_router_interface_with_port_id(
+            create_body['router']['id'], port_body['port']['id'])
+        self.assertEqual('200', resp['status'])
+        self.addCleanup(self._remove_router_interface_with_port_id,
+                        create_body['router']['id'], port_body['port']['id'])
+        self.assertTrue('subnet_id' in interface.keys())
+        self.assertTrue('port_id' in interface.keys())
+        # Verify router id is equal to device id in port details
+        resp, show_port_body = self.client.show_port(
+            interface['port_id'])
+        self.assertEqual(show_port_body['port']['device_id'],
+                         create_body['router']['id'])
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 5a1fb5a..820328c 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -26,6 +26,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(BaseObjectTest, cls).setUpClass()
         if not cls.config.service_available.swift:
             skip_msg = ("%s skipped as swift is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 8b9fc8c..eaaed39 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -31,6 +31,7 @@
     @classmethod
     def tearDownClass(cls):
         cls.delete_containers(cls.containers)
+        super(ContainerTest, cls).tearDownClass()
 
     @attr(type='smoke')
     def test_create_container(self):
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 5de4df0..d18c2ad 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -50,6 +50,7 @@
     def tearDownClass(cls):
         for client in cls.clients.values():
             cls.delete_containers(cls.containers, client[0], client[1])
+        super(ContainerSyncTest, cls).tearDownClass()
 
     @testtools.skip('Until Bug #1093743 is resolved.')
     @attr(type='gate')
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index b546cec..8703480 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -41,6 +41,7 @@
         NotFound exception and also non empty container cannot be deleted.
         """
         cls.delete_containers([cls.container_name])
+        super(ObjectExpiryTest, cls).tearDownClass()
 
     @testtools.skip('Until Bug #1069849 is resolved.')
     @attr(type='gate')
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index c8d9965..c599562 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -47,6 +47,7 @@
         cls.delete_containers(cls.containers)
         # delete the user setup created
         cls.data.teardown_all()
+        super(ObjectTest, cls).tearDownClass()
 
     @attr(type='smoke')
     def test_create_object(self):
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index cda3e4f..2b93c32 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -29,6 +29,7 @@
     @classmethod
     def tearDownClass(cls):
         cls.delete_containers(cls.containers)
+        super(ContainerTest, cls).tearDownClass()
 
     def assertContainer(self, container, count, byte, versioned):
         resp, _ = self.container_client.list_container_metadata(container)
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index d06d942..745dd87 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -28,7 +28,7 @@
 
     @classmethod
     def setUpClass(cls):
-
+        super(BaseOrchestrationTest, cls).setUpClass()
         os = clients.OrchestrationManager()
         cls.orchestration_cfg = os.config.orchestration
         if not os.config.service_available.heat:
@@ -107,6 +107,7 @@
     def tearDownClass(cls):
         cls.clear_stacks()
         cls.clear_keypairs()
+        super(BaseOrchestrationTest, cls).tearDownClass()
 
     def wait_for(self, condition):
         """Repeatedly calls condition() until a timeout."""
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index b64a324..797aa71 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -81,8 +81,8 @@
                 cls.volume_id_list.append(cls.volume2['id'])
                 cls.volume_client.wait_for_volume_status(cls.volume2['id'],
                                                          'available')
-        except Exception:
-            LOG.exception("setup failed")
+        except Exception as e:
+            LOG.exception("setup failed: %s" % e)
             cls.tearDownClass()
             raise
 
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 27caaad..822f691 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -38,126 +38,111 @@
                                                                auth_url,
                                                                adm_tenant)
 
+    def _delete_volume(self, volume_id):
+        resp, _ = self.volumes_client.delete_volume(volume_id)
+        self.assertEqual(202, resp.status)
+
+    def _delete_volume_type(self, volume_type_id):
+        resp, _ = self.client.delete_volume_type(volume_type_id)
+        self.assertEqual(202, resp.status)
+
     @attr(type='smoke')
     def test_volume_type_list(self):
         # List Volume types.
-        try:
-            resp, body = self.client.list_volume_types()
-            self.assertEqual(200, resp.status)
-            self.assertTrue(type(body), list)
-        except Exception:
-            self.fail("Could not list volume types")
+        resp, body = self.client.list_volume_types()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(type(body), list)
 
     @attr(type='smoke')
     def test_create_get_delete_volume_with_volume_type_and_extra_specs(self):
         # Create/get/delete volume with volume_type and extra spec.
-        try:
-            volume = {}
-            vol_name = rand_name("volume-")
-            vol_type_name = rand_name("volume-type-")
-            proto = self.config.volume.storage_protocol
-            vendor = self.config.volume.vendor_name
-            extra_specs = {"storage_protocol": proto,
-                           "vendor_name": vendor}
-            body = {}
-            resp, body = self.client.create_volume_type(
-                vol_type_name,
-                extra_specs=extra_specs)
-            self.assertEqual(200, resp.status)
-            self.assertIn('id', body)
-            self.assertIn('name', body)
-            resp, volume = self.volumes_client.create_volume(
-                size=1, display_name=vol_name,
-                volume_type=vol_type_name)
-            self.assertEqual(200, resp.status)
-            self.assertIn('id', volume)
-            self.assertIn('display_name', volume)
-            self.assertEqual(volume['display_name'], vol_name,
-                             "The created volume name is not equal "
-                             "to the requested name")
-            self.assertTrue(volume['id'] is not None,
-                            "Field volume id is empty or not found.")
-            self.volumes_client.wait_for_volume_status(volume['id'],
-                                                       'available')
-            resp, fetched_volume = self.volumes_client.get_volume(volume['id'])
-            self.assertEqual(200, resp.status)
-            self.assertEqual(vol_name, fetched_volume['display_name'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-            self.assertEqual(volume['id'], fetched_volume['id'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-            self.assertEqual(vol_type_name, fetched_volume['volume_type'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-        except Exception:
-            self.fail("Could not create correct volume with volume_type")
-        finally:
-            if volume:
-                # Delete the Volume if it was created
-                resp, _ = self.volumes_client.delete_volume(volume['id'])
-                self.assertEqual(202, resp.status)
-
-            if body:
-                resp, _ = self.client.delete_volume_type(body['id'])
-                self.assertEqual(202, resp.status)
+        volume = {}
+        vol_name = rand_name("volume-")
+        vol_type_name = rand_name("volume-type-")
+        proto = self.config.volume.storage_protocol
+        vendor = self.config.volume.vendor_name
+        extra_specs = {"storage_protocol": proto,
+                       "vendor_name": vendor}
+        body = {}
+        resp, body = self.client.create_volume_type(
+            vol_type_name,
+            extra_specs=extra_specs)
+        self.assertEqual(200, resp.status)
+        self.assertIn('id', body)
+        self.addCleanup(self._delete_volume_type, body['id'])
+        self.assertIn('name', body)
+        resp, volume = self.volumes_client.create_volume(
+            size=1, display_name=vol_name,
+            volume_type=vol_type_name)
+        self.assertEqual(200, resp.status)
+        self.assertIn('id', volume)
+        self.addCleanup(self._delete_volume, volume['id'])
+        self.assertIn('display_name', volume)
+        self.assertEqual(volume['display_name'], vol_name,
+                         "The created volume name is not equal "
+                         "to the requested name")
+        self.assertTrue(volume['id'] is not None,
+                        "Field volume id is empty or not found.")
+        self.volumes_client.wait_for_volume_status(volume['id'],
+                                                   'available')
+        resp, fetched_volume = self.volumes_client.get_volume(volume['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(vol_name, fetched_volume['display_name'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
+        self.assertEqual(volume['id'], fetched_volume['id'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
+        self.assertEqual(vol_type_name, fetched_volume['volume_type'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
 
     @attr(type='smoke')
     def test_volume_type_create_delete(self):
         # Create/Delete volume type.
-        try:
-            name = rand_name("volume-type-")
-            extra_specs = {"storage_protocol": "iSCSI",
-                           "vendor_name": "Open Source"}
-            resp, body = self.client.create_volume_type(
-                name,
-                extra_specs=extra_specs)
-            self.assertEqual(200, resp.status)
-            self.assertIn('id', body)
-            self.assertIn('name', body)
-            self.assertEqual(body['name'], name,
-                             "The created volume_type name is not equal "
-                             "to the requested name")
-            self.assertTrue(body['id'] is not None,
-                            "Field volume_type id is empty or not found.")
-            resp, _ = self.client.delete_volume_type(body['id'])
-            self.assertEqual(202, resp.status)
-        except Exception:
-            self.fail("Could not create a volume_type")
+        name = rand_name("volume-type-")
+        extra_specs = {"storage_protocol": "iSCSI",
+                       "vendor_name": "Open Source"}
+        resp, body = self.client.create_volume_type(
+            name,
+            extra_specs=extra_specs)
+        self.assertEqual(200, resp.status)
+        self.assertIn('id', body)
+        self.addCleanup(self._delete_volume_type, body['id'])
+        self.assertIn('name', body)
+        self.assertEqual(body['name'], name,
+                         "The created volume_type name is not equal "
+                         "to the requested name")
+        self.assertTrue(body['id'] is not None,
+                        "Field volume_type id is empty or not found.")
 
     @attr(type='smoke')
     def test_volume_type_create_get(self):
         # Create/get volume type.
-        try:
-            body = {}
-            name = rand_name("volume-type-")
-            extra_specs = {"storage_protocol": "iSCSI",
-                           "vendor_name": "Open Source"}
-            resp, body = self.client.create_volume_type(
-                name,
-                extra_specs=extra_specs)
-            self.assertEqual(200, resp.status)
-            self.assertIn('id', body)
-            self.assertIn('name', body)
-            self.assertEqual(body['name'], name,
-                             "The created volume_type name is not equal "
-                             "to the requested name")
-            self.assertTrue(body['id'] is not None,
-                            "Field volume_type id is empty or not found.")
-            resp, fetched_volume_type = self.client.get_volume_type(body['id'])
-            self.assertEqual(200, resp.status)
-            self.assertEqual(name, fetched_volume_type['name'],
-                             'The fetched Volume_type is different '
-                             'from the created Volume_type')
-            self.assertEqual(str(body['id']), fetched_volume_type['id'],
-                             'The fetched Volume_type is different '
-                             'from the created Volume_type')
-            self.assertEqual(extra_specs, fetched_volume_type['extra_specs'],
-                             'The fetched Volume_type is different '
-                             'from the created Volume_type')
-        except Exception:
-            self.fail("Could not create a volume_type")
-        finally:
-            if body:
-                resp, _ = self.client.delete_volume_type(body['id'])
-                self.assertEqual(202, resp.status)
+        body = {}
+        name = rand_name("volume-type-")
+        extra_specs = {"storage_protocol": "iSCSI",
+                       "vendor_name": "Open Source"}
+        resp, body = self.client.create_volume_type(
+            name,
+            extra_specs=extra_specs)
+        self.assertEqual(200, resp.status)
+        self.assertIn('id', body)
+        self.addCleanup(self._delete_volume_type, body['id'])
+        self.assertIn('name', body)
+        self.assertEqual(body['name'], name,
+                         "The created volume_type name is not equal "
+                         "to the requested name")
+        self.assertTrue(body['id'] is not None,
+                        "Field volume_type id is empty or not found.")
+        resp, fetched_volume_type = self.client.get_volume_type(body['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(name, fetched_volume_type['name'],
+                         'The fetched Volume_type is different '
+                         'from the created Volume_type')
+        self.assertEqual(str(body['id']), fetched_volume_type['id'],
+                         'The fetched Volume_type is different '
+                         'from the created Volume_type')
+        self.assertEqual(extra_specs, fetched_volume_type['extra_specs'],
+                         'The fetched Volume_type is different '
+                         'from the created Volume_type')
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index 417f296..7d94f58 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -37,68 +37,59 @@
     @attr(type='smoke')
     def test_volume_type_extra_specs_list(self):
         # List Volume types extra specs.
-        try:
-            extra_specs = {"spec1": "val1"}
-            resp, body = self.client.create_volume_type_extra_specs(
-                self.volume_type['id'], extra_specs)
-            self.assertEqual(200, resp.status)
-            self.assertEqual(extra_specs, body,
-                             "Volume type extra spec incorrectly created")
-            resp, body = self.client.list_volume_types_extra_specs(
-                self.volume_type['id'])
-            self.assertEqual(200, resp.status)
-            self.assertTrue(type(body), dict)
-            self.assertTrue('spec1' in body, "Incorrect volume type extra"
-                            " spec returned")
-        except Exception:
-            self.fail("Could not list volume types extra specs")
+        extra_specs = {"spec1": "val1"}
+        resp, body = self.client.create_volume_type_extra_specs(
+            self.volume_type['id'], extra_specs)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(extra_specs, body,
+                         "Volume type extra spec incorrectly created")
+        resp, body = self.client.list_volume_types_extra_specs(
+            self.volume_type['id'])
+        self.assertEqual(200, resp.status)
+        self.assertTrue(type(body), dict)
+        self.assertTrue('spec1' in body, "Incorrect volume type extra"
+                        " spec returned")
 
     @attr(type='gate')
     def test_volume_type_extra_specs_update(self):
         # Update volume type extra specs
-        try:
-            extra_specs = {"spec2": "val1"}
-            resp, body = self.client.create_volume_type_extra_specs(
-                self.volume_type['id'], extra_specs)
-            self.assertEqual(200, resp.status)
-            self.assertEqual(extra_specs, body,
-                             "Volume type extra spec incorrectly created")
+        extra_specs = {"spec2": "val1"}
+        resp, body = self.client.create_volume_type_extra_specs(
+            self.volume_type['id'], extra_specs)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(extra_specs, body,
+                         "Volume type extra spec incorrectly created")
 
-            extra_spec = {"spec2": "val2"}
-            resp, body = self.client.update_volume_type_extra_specs(
-                self.volume_type['id'],
-                extra_spec.keys()[0],
-                extra_spec)
-            self.assertEqual(200, resp.status)
-            self.assertTrue('spec2' in body,
-                            "Volume type extra spec incorrectly updated")
-            self.assertEqual(extra_spec['spec2'], body['spec2'],
-                             "Volume type extra spec incorrectly updated")
-        except Exception:
-            self.fail("Couldnt update volume type extra spec")
+        extra_spec = {"spec2": "val2"}
+        resp, body = self.client.update_volume_type_extra_specs(
+            self.volume_type['id'],
+            extra_spec.keys()[0],
+            extra_spec)
+        self.assertEqual(200, resp.status)
+        self.assertTrue('spec2' in body,
+                        "Volume type extra spec incorrectly updated")
+        self.assertEqual(extra_spec['spec2'], body['spec2'],
+                         "Volume type extra spec incorrectly updated")
 
     @attr(type='smoke')
     def test_volume_type_extra_spec_create_get_delete(self):
         # Create/Get/Delete volume type extra spec.
-        try:
-            extra_specs = {"spec3": "val1"}
-            resp, body = self.client.create_volume_type_extra_specs(
-                self.volume_type['id'],
-                extra_specs)
-            self.assertEqual(200, resp.status)
-            self.assertEqual(extra_specs, body,
-                             "Volume type extra spec incorrectly created")
+        extra_specs = {"spec3": "val1"}
+        resp, body = self.client.create_volume_type_extra_specs(
+            self.volume_type['id'],
+            extra_specs)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(extra_specs, body,
+                         "Volume type extra spec incorrectly created")
 
-            resp, _ = self.client.get_volume_type_extra_specs(
-                self.volume_type['id'],
-                extra_specs.keys()[0])
-            self.assertEqual(200, resp.status)
-            self.assertEqual(extra_specs, body,
-                             "Volume type extra spec incorrectly fetched")
+        resp, _ = self.client.get_volume_type_extra_specs(
+            self.volume_type['id'],
+            extra_specs.keys()[0])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(extra_specs, body,
+                         "Volume type extra spec incorrectly fetched")
 
-            resp, _ = self.client.delete_volume_type_extra_specs(
-                self.volume_type['id'],
-                extra_specs.keys()[0])
-            self.assertEqual(202, resp.status)
-        except Exception:
-            self.fail("Could not create a volume_type extra spec")
+        resp, _ = self.client.delete_volume_type_extra_specs(
+            self.volume_type['id'],
+            extra_specs.keys()[0])
+        self.assertEqual(202, resp.status)
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 52ab5b7..7781647 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -31,6 +31,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(BaseVolumeTest, cls).setUpClass()
         cls.isolated_creds = isolated_creds.IsolatedCreds(cls.__name__)
 
         if not cls.config.service_available.cinder:
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 39f61f3..2e90f16 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -28,76 +28,65 @@
         super(VolumesGetTest, cls).setUpClass()
         cls.client = cls.volumes_client
 
+    def _delete_volume(self, volume_id):
+        resp, _ = self.client.delete_volume(volume_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_resource_deletion(volume_id)
+
     def _volume_create_get_delete(self, **kwargs):
         # Create a volume, Get it's details and Delete the volume
-        try:
-            volume = {}
-            v_name = rand_name('Volume')
-            metadata = {'Type': 'Test'}
-            # Create a volume
-            resp, volume = self.client.create_volume(size=1,
-                                                     display_name=v_name,
-                                                     metadata=metadata,
-                                                     **kwargs)
-            self.assertEqual(200, resp.status)
-            self.assertIn('id', volume)
-            self.assertIn('display_name', volume)
-            self.assertEqual(volume['display_name'], v_name,
-                             "The created volume name is not equal "
-                             "to the requested name")
-            self.assertTrue(volume['id'] is not None,
-                            "Field volume id is empty or not found.")
-            self.client.wait_for_volume_status(volume['id'], 'available')
-            # Get Volume information
-            resp, fetched_volume = self.client.get_volume(volume['id'])
-            self.assertEqual(200, resp.status)
-            self.assertEqual(v_name,
-                             fetched_volume['display_name'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-            self.assertEqual(volume['id'],
-                             fetched_volume['id'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-            self.assertEqual(metadata,
-                             fetched_volume['metadata'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-        except Exception:
-            self.fail("Could not create a volume")
-        finally:
-            if volume:
-                # Delete the Volume if it was created
-                resp, _ = self.client.delete_volume(volume['id'])
-                self.assertEqual(202, resp.status)
-                self.client.wait_for_resource_deletion(volume['id'])
+        volume = {}
+        v_name = rand_name('Volume')
+        metadata = {'Type': 'Test'}
+        # Create a volume
+        resp, volume = self.client.create_volume(size=1,
+                                                 display_name=v_name,
+                                                 metadata=metadata,
+                                                 **kwargs)
+        self.assertEqual(200, resp.status)
+        self.assertIn('id', volume)
+        self.addCleanup(self._delete_volume, volume['id'])
+        self.assertIn('display_name', volume)
+        self.assertEqual(volume['display_name'], v_name,
+                         "The created volume name is not equal "
+                         "to the requested name")
+        self.assertTrue(volume['id'] is not None,
+                        "Field volume id is empty or not found.")
+        self.client.wait_for_volume_status(volume['id'], 'available')
+        # Get Volume information
+        resp, fetched_volume = self.client.get_volume(volume['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(v_name,
+                         fetched_volume['display_name'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
+        self.assertEqual(volume['id'],
+                         fetched_volume['id'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
+        self.assertEqual(metadata,
+                         fetched_volume['metadata'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
 
     @attr(type='gate')
     def test_volume_get_metadata_none(self):
         # Create a volume without passing metadata, get details, and delete
-        try:
-            volume = {}
-            v_name = rand_name('Volume-')
-            # Create a volume without metadata
-            resp, volume = self.client.create_volume(size=1,
-                                                     display_name=v_name,
-                                                     metadata={})
-            self.assertEqual(200, resp.status)
-            self.assertIn('id', volume)
-            self.assertIn('display_name', volume)
-            self.client.wait_for_volume_status(volume['id'], 'available')
-            # GET Volume
-            resp, fetched_volume = self.client.get_volume(volume['id'])
-            self.assertEqual(200, resp.status)
-            self.assertEqual(fetched_volume['metadata'], {})
-        except Exception:
-            self.fail("Could not get volume metadata")
-        finally:
-            if volume:
-                # Delete the Volume if it was created
-                resp, _ = self.client.delete_volume(volume['id'])
-                self.assertEqual(202, resp.status)
-                self.client.wait_for_resource_deletion(volume['id'])
+        volume = {}
+        v_name = rand_name('Volume-')
+        # Create a volume without metadata
+        resp, volume = self.client.create_volume(size=1,
+                                                 display_name=v_name,
+                                                 metadata={})
+        self.assertEqual(200, resp.status)
+        self.assertIn('id', volume)
+        self.addCleanup(self._delete_volume, volume['id'])
+        self.assertIn('display_name', volume)
+        self.client.wait_for_volume_status(volume['id'], 'available')
+        # GET Volume
+        resp, fetched_volume = self.client.get_volume(volume['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(fetched_volume['metadata'], {})
 
     @attr(type='smoke')
     def test_volume_create_get_delete(self):
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 4447da0..d512ae8 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -150,6 +150,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(OfficialClientTest, cls).setUpClass()
         cls.isolated_creds = isolated_creds.IsolatedCreds(
             __name__, tempest_client=False)
         if cls.config.compute.allow_tenant_isolation:
@@ -257,6 +258,31 @@
             self.fail("Timed out waiting for thing %s to become %s"
                       % (thing_id, expected_status))
 
+    def create_server(self, client, name=None, image=None, flavor=None,
+                      create_kwargs={}):
+        if name is None:
+            name = rand_name('scenario-server-')
+        if image is None:
+            image = self.config.compute.image_ref
+        if flavor is None:
+            flavor = self.config.compute.flavor_ref
+        LOG.debug("Creating a server (name: %s, image: %s, flavor: %s)",
+                  name, image, flavor)
+        server = client.servers.create(name, image, flavor, **create_kwargs)
+        try:
+            self.assertEqual(server.name, name)
+            self.set_resource(name, server)
+        except AttributeError:
+            self.fail("Server not successfully created.")
+        self.status_timeout(client.servers, server.id, 'ACTIVE')
+        # The instance retrieved on creation is missing network
+        # details, necessitating retrieval after it becomes active to
+        # ensure correct details.
+        server = client.servers.get(server.id)
+        self.set_resource(name, server)
+        LOG.debug("Created server: %s", server)
+        return server
+
 
 class NetworkScenarioTest(OfficialClientTest):
     """
@@ -411,31 +437,6 @@
         self.set_resource(name, port)
         return port
 
-    def _create_server(self, client, network, name, key_name, security_groups):
-        flavor_id = self.config.compute.flavor_ref
-        base_image_id = self.config.compute.image_ref
-        create_kwargs = {
-            'nics': [
-                {'net-id': network.id},
-            ],
-            'key_name': key_name,
-            'security_groups': security_groups,
-        }
-        server = client.servers.create(name, base_image_id, flavor_id,
-                                       **create_kwargs)
-        try:
-            self.assertEqual(server.name, name)
-            self.set_resource(name, server)
-        except AttributeError:
-            self.fail("Server not successfully created.")
-        self.status_timeout(client.servers, server.id, 'ACTIVE')
-        # The instance retrieved on creation is missing network
-        # details, necessitating retrieval after it becomes active to
-        # ensure correct details.
-        server = client.servers.get(server.id)
-        self.set_resource(name, server)
-        return server
-
     def _create_floating_ip(self, server, external_network_id):
         result = self.network_client.list_ports(device_id=server.id)
         ports = result.get('ports', [])
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 13b31ec..b789fa2 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -90,15 +90,10 @@
         self.assertEqual(name, self.keypair.name)
 
     def nova_boot(self):
-        name = rand_name('scenario-server-')
-        client = self.compute_client
-        flavor_id = self.config.compute.flavor_ref
-        self.server = client.servers.create(name=name, image=self.image,
-                                            flavor=flavor_id,
-                                            key_name=self.keypair.name)
-        self.addCleanup(self.compute_client.servers.delete, self.server)
-        self.assertEqual(name, self.server.name)
-        self._wait_for_server_status('ACTIVE')
+        create_kwargs = {'key_name': self.keypair.name}
+        self.server = self.create_server(self.compute_client,
+                                         image=self.image,
+                                         create_kwargs=create_kwargs)
 
     def nova_list(self):
         servers = self.compute_client.servers.list()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 5311eae..99b0071 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -213,8 +213,15 @@
             name = rand_name('server-smoke-%d-' % i)
             keypair_name = self.keypairs[tenant_id].name
             security_groups = [self.security_groups[tenant_id].name]
-            server = self._create_server(self.compute_client, network,
-                                         name, keypair_name, security_groups)
+            create_kwargs = {
+                'nics': [
+                    {'net-id': network.id},
+                ],
+                'key_name': keypair_name,
+                'security_groups': security_groups,
+            }
+            server = self.create_server(self.compute_client, name=name,
+                                        create_kwargs=create_kwargs)
             self.servers.append(server)
 
     @attr(type='smoke')
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 0ec3a1d..43ac2d9 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -82,26 +82,12 @@
                 self.fail("Failed to create rule in security group.")
 
     def boot_instance(self):
-        i_name = rand_name('instance')
-        flavor_id = self.config.compute.flavor_ref
-        base_image_id = self.config.compute.image_ref
         create_kwargs = {
             'key_name': self.get_resource('keypair').id
         }
-        self.instance = self.compute_client.servers.create(
-            i_name, base_image_id, flavor_id, **create_kwargs)
-        try:
-            self.assertEqual(self.instance.name, i_name)
-            self.set_resource('instance', self.instance)
-        except AttributeError:
-            self.fail("Instance not successfully created.")
-
-        self.assertEqual(self.instance.status, 'BUILD')
-
-    def wait_on_active(self):
-        instance_id = self.get_resource('instance').id
-        self.status_timeout(
-            self.compute_client.servers, instance_id, 'ACTIVE')
+        instance = self.create_server(self.compute_client,
+                                      create_kwargs=create_kwargs)
+        self.set_resource('instance', instance)
 
     def pause_server(self):
         instance = self.get_resource('instance')
@@ -148,7 +134,6 @@
         self.create_keypair()
         self.create_security_group()
         self.boot_instance()
-        self.wait_on_active()
         self.pause_server()
         self.unpause_server()
         self.suspend_server()
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 6e305c1..e8ce1bd 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -44,20 +44,11 @@
         self.status_timeout(self.image_client.images, image_id, status)
 
     def _boot_image(self, image_id):
-        name = rand_name('scenario-server-')
-        client = self.compute_client
-        flavor_id = self.config.compute.flavor_ref
-        LOG.debug("name:%s, image:%s" % (name, image_id))
-        server = client.servers.create(name=name,
-                                       image=image_id,
-                                       flavor=flavor_id,
-                                       key_name=self.keypair.name)
-        self.addCleanup(self.compute_client.servers.delete, server)
-        self.assertEqual(name, server.name)
-        self._wait_for_server_status(server, 'ACTIVE')
-        server = client.servers.get(server)  # getting network information
-        LOG.debug("server:%s" % server)
-        return server
+        create_kwargs = {
+            'key_name': self.keypair.name
+        }
+        return self.create_server(self.compute_client, image=image_id,
+                                  create_kwargs=create_kwargs)
 
     def _add_keypair(self):
         name = rand_name('scenario-keypair-')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 4434604..038d251 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -64,20 +64,11 @@
                             volume_snapshot.id, status)
 
     def _boot_image(self, image_id):
-        name = rand_name('scenario-server-')
-        client = self.compute_client
-        flavor_id = self.config.compute.flavor_ref
-        LOG.debug("name:%s, image:%s" % (name, image_id))
-        server = client.servers.create(name=name,
-                                       image=image_id,
-                                       flavor=flavor_id,
-                                       key_name=self.keypair.name)
-        self.addCleanup(self.compute_client.servers.delete, server)
-        self.assertEqual(name, server.name)
-        self._wait_for_server_status(server, 'ACTIVE')
-        server = client.servers.get(server)  # getting network information
-        LOG.debug("server:%s" % server)
-        return server
+        create_kwargs = {
+            'key_name': self.keypair.name
+        }
+        return self.create_server(self.compute_client, image=image_id,
+                                  create_kwargs=create_kwargs)
 
     def _add_keypair(self):
         name = rand_name('scenario-keypair-')
diff --git a/tempest/scenario/test_volume_snapshot_pattern.py b/tempest/scenario/test_volume_snapshot_pattern.py
index 4d8a400..95a30ed 100644
--- a/tempest/scenario/test_volume_snapshot_pattern.py
+++ b/tempest/scenario/test_volume_snapshot_pattern.py
@@ -44,11 +44,6 @@
         return vol
 
     def _boot_instance_from_volume(self, vol_id):
-        # NOTE(gfidente): the img_uuid here is only needed because
-        # the novaclient requires it to be passed as arg
-        img_uuid = self.config.compute.image_ref
-        i_name = rand_name('instance')
-        flavor_id = self.config.compute.flavor_ref
         # NOTE(gfidente): the syntax for block_device_mapping is
         # dev_name=id:type:size:delete_on_terminate
         # where type needs to be "snap" if the server is booted
@@ -59,15 +54,8 @@
         create_kwargs = {
             'block_device_mapping': bd_map
         }
-        i = self.compute_client.servers.create(name=i_name,
-                                               image=img_uuid,
-                                               flavor=flavor_id,
-                                               **create_kwargs)
-        self.set_resource(i.id, i)
-        self.status_timeout(self.compute_client.servers,
-                            i.id,
-                            'ACTIVE')
-        return i
+        return self.create_server(self.compute_client,
+                                  create_kwargs=create_kwargs)
 
     def _create_snapshot_from_volume(self, vol_id):
         volume_snapshots = self.volume_client.volume_snapshots
diff --git a/tempest/services/compute/xml/flavors_client.py b/tempest/services/compute/xml/flavors_client.py
index 6ba31ea..3a8986c 100644
--- a/tempest/services/compute/xml/flavors_client.py
+++ b/tempest/services/compute/xml/flavors_client.py
@@ -30,6 +30,8 @@
     "http://docs.openstack.org/compute/ext/flavor_extra_data/api/v1.1"
 XMLNS_OS_FLV_ACCESS = \
     "http://docs.openstack.org/compute/ext/flavor_access/api/v1.1"
+XMLNS_OS_FLV_WITH_EXT_SPECS = \
+    "http://docs.openstack.org/compute/ext/flavor_with_extra_specs/api/v2.0"
 
 
 class FlavorsClientXML(RestClientXML):
@@ -49,6 +51,11 @@
             if k == '{%s}ephemeral' % XMLNS_OS_FLV_EXT_DATA:
                 k = 'OS-FLV-EXT-DATA:ephemeral'
 
+            if k == '{%s}extra_specs' % XMLNS_OS_FLV_WITH_EXT_SPECS:
+                k = 'OS-FLV-WITH-EXT-SPECS:extra_specs'
+                flavor[k] = dict(v)
+                continue
+
             try:
                 v = int(v)
             except ValueError:
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index cf2afb2..b19ed8d 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -23,8 +23,10 @@
     Tempest REST client for Neutron. Uses v2 of the Neutron API, since the
     V1 API has been removed from the code base.
 
-    Implements create, delete, list and show for the basic Neutron
-    abstractions (networks, sub-networks and ports):
+    Implements create, delete, update, list and show for the basic Neutron
+    abstractions (networks, sub-networks, routers and ports):
+
+    Implements add/remove interface to router using subnet ID / port ID
 
     It also implements list, show, update and reset for OpenStack Networking
     quotas
@@ -198,3 +200,89 @@
         resp, body = self.put(uri, body=body, headers=self.headers)
         body = json.loads(body)
         return resp, body
+
+    def list_routers(self):
+        uri = '%s/routers' % (self.uri_prefix)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def create_router(self, name, **kwargs):
+        post_body = {
+            'router': {
+                'name': name,
+            }
+        }
+        post_body['router']['admin_state_up'] = kwargs.get(
+            'admin_state_up', True)
+        post_body['router']['external_gateway_info'] = kwargs.get(
+            'external_gateway_info', None)
+        body = json.dumps(post_body)
+        uri = '%s/routers' % (self.uri_prefix)
+        resp, body = self.post(uri, headers=self.headers, body=body)
+        body = json.loads(body)
+        return resp, body
+
+    def delete_router(self, router_id):
+        uri = '%s/routers/%s' % (self.uri_prefix, router_id)
+        resp, body = self.delete(uri, self.headers)
+        return resp, body
+
+    def show_router(self, router_id):
+        uri = '%s/routers/%s' % (self.uri_prefix, router_id)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def update_router(self, router_id, **kwargs):
+        uri = '%s/routers/%s' % (self.uri_prefix, router_id)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        update_body = {}
+        update_body['name'] = kwargs.get('name', body['router']['name'])
+        update_body['admin_state_up'] = kwargs.get(
+            'admin_state_up', body['router']['admin_state_up'])
+        # Must uncomment/modify these lines once LP question#233187 is solved
+        #update_body['external_gateway_info'] = kwargs.get(
+        #    'external_gateway_info', body['router']['external_gateway_info'])
+        update_body = dict(router=update_body)
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def add_router_interface_with_subnet_id(self, router_id, subnet_id):
+        uri = '%s/routers/%s/add_router_interface' % (self.uri_prefix,
+              router_id)
+        update_body = {"subnet_id": subnet_id}
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def add_router_interface_with_port_id(self, router_id, port_id):
+        uri = '%s/routers/%s/add_router_interface' % (self.uri_prefix,
+              router_id)
+        update_body = {"port_id": port_id}
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def remove_router_interface_with_subnet_id(self, router_id, subnet_id):
+        uri = '%s/routers/%s/remove_router_interface' % (self.uri_prefix,
+              router_id)
+        update_body = {"subnet_id": subnet_id}
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def remove_router_interface_with_port_id(self, router_id, port_id):
+        uri = '%s/routers/%s/remove_router_interface' % (self.uri_prefix,
+              router_id)
+        update_body = {"port_id": port_id}
+        update_body = json.dumps(update_body)
+        resp, body = self.put(uri, update_body, self.headers)
+        body = json.loads(body)
+        return resp, body
diff --git a/tempest/test.py b/tempest/test.py
index 0cd0b08..7787790 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -15,6 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import atexit
 import os
 import time
 
@@ -91,6 +92,17 @@
         LOG.info("Overriding skipException to nose SkipTest")
         testtools.TestCase.skipException = nose.plugins.skip.SkipTest
 
+at_exit_set = set()
+
+
+def validate_tearDownClass():
+    if at_exit_set:
+        raise RuntimeError("tearDownClass does not calls the super's"
+                           "tearDownClass in these classes: "
+                           + str(at_exit_set))
+
+atexit.register(validate_tearDownClass)
+
 
 class BaseTestCase(testtools.TestCase,
                    testtools.testcase.WithAttributes,
@@ -98,29 +110,43 @@
 
     config = config.TempestConfig()
 
+    setUpClassCalled = False
+
     @classmethod
     def setUpClass(cls):
         if hasattr(super(BaseTestCase, cls), 'setUpClass'):
             super(BaseTestCase, cls).setUpClass()
+        cls.setUpClassCalled = True
 
-    def setUp(cls):
-        super(BaseTestCase, cls).setUp()
+    @classmethod
+    def tearDownClass(cls):
+        at_exit_set.remove(cls)
+        if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
+            super(BaseTestCase, cls).tearDownClass()
+
+    def setUp(self):
+        super(BaseTestCase, self).setUp()
+        if not self.setUpClassCalled:
+            raise RuntimeError("setUpClass does not calls the super's"
+                               "setUpClass in the "
+                               + self.__class__.__name__)
+        at_exit_set.add(self.__class__)
         test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
         try:
             test_timeout = int(test_timeout)
         except ValueError:
             test_timeout = 0
         if test_timeout > 0:
-            cls.useFixture(fixtures.Timeout(test_timeout, gentle=True))
+            self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
 
         if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
                 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
-            stdout = cls.useFixture(fixtures.StringStream('stdout')).stream
-            cls.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
+            stdout = self.useFixture(fixtures.StringStream('stdout')).stream
+            self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
         if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
                 os.environ.get('OS_STDERR_CAPTURE') == '1'):
-            stderr = cls.useFixture(fixtures.StringStream('stderr')).stream
-            cls.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
+            stderr = self.useFixture(fixtures.StringStream('stderr')).stream
+            self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
 
     @classmethod
     def _get_identity_admin_client(cls):
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 8812a10..e0c9f06 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -197,6 +197,7 @@
 
     @classmethod
     def setUpClass(cls):
+        super(BotoTestCase, cls).setUpClass()
         # The trash contains cleanup functions and paramaters in tuples
         # (function, *args, **kwargs)
         cls._resource_trash_bin = {}
@@ -261,6 +262,10 @@
                 LOG.exception(exc)
             finally:
                 del cls._resource_trash_bin[key]
+        super(BotoTestCase, cls).tearDownClass()
+        # NOTE(afazekas): let the super called even on exceptions
+        # The real exceptions already logged, if the super throws another,
+        # does not causes hidden issues
         if fail_count:
             raise exceptions.TearDownException(num=fail_count)
 
diff --git a/tox.ini b/tox.ini
index dc8980d..471fecb 100644
--- a/tox.ini
+++ b/tox.ini
@@ -27,6 +27,29 @@
 commands =
   sh tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
 
+[testenv:py26-full]
+sitepackages = True
+setenv = VIRTUAL_ENV={envdir}
+         NOSE_WITH_OPENSTACK=1
+         NOSE_OPENSTACK_COLOR=1
+         NOSE_OPENSTACK_RED=15
+         NOSE_OPENSTACK_YELLOW=3
+         NOSE_OPENSTACK_SHOW_ELAPSED=1
+         NOSE_OPENSTACK_STDOUT=1
+commands =
+  nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit -sv --xunit-file=nosetests-full.xml tempest/api tempest/scenario tempest/thirdparty tempest/cli {posargs}
+
+[testenv:py26-smoke]
+setenv = VIRTUAL_ENV={envdir}
+NOSE_WITH_OPENSTACK=1
+         NOSE_OPENSTACK_COLOR=1
+         NOSE_OPENSTACK_RED=15
+         NOSE_OPENSTACK_YELLOW=3
+         NOSE_OPENSTACK_SHOW_ELAPSED=1
+         NOSE_OPENSTACK_STDOUT=1
+commands =
+  nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit -sv --attr=type=smoke --xunit-file=nosetests-smoke.xml tempest {posargs}
+
 [testenv:smoke]
 sitepackages = True
 setenv = VIRTUAL_ENV={envdir}