Merge "Simplify volume test classes inheritance"
diff --git a/HACKING.rst b/HACKING.rst
index fed4130..a546f8c 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -153,10 +153,25 @@
                              kwarg2=dict_of_numbers)
 
 
+openstack-common
+----------------
+
+A number of modules from openstack-common are imported into the project.
+
+These modules are "incubating" in openstack-common and are kept in sync
+with the help of openstack-common's update.py script. See:
+
+  http://wiki.openstack.org/CommonLibrary#Incubation
+
+The copy of the code should never be directly modified here. Please
+always update openstack-common first and then run the script to copy
+the changes across.
+
+
 OpenStack Trademark
 -------------------
 
-OpenStack is a registered trademark of OpenStack, LLC, and uses the
+OpenStack is a registered trademark of the OpenStack Foundation, and uses the
 following capitalization:
 
    OpenStack
diff --git a/tempest/clients.py b/tempest/clients.py
index 8d9c216..7eb17f3 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -19,8 +19,7 @@
 
 from tempest import config
 from tempest import exceptions
-from tempest.services.boto.clients import APIClientEC2
-from tempest.services.boto.clients import ObjectClientS3
+from tempest.services import botoclients
 from tempest.services.compute.json.extensions_client import \
     ExtensionsClientJSON
 from tempest.services.compute.json.flavors_client import FlavorsClientJSON
@@ -216,8 +215,8 @@
         self.image_client = ImageClientJSON(*client_args)
         self.container_client = ContainerClient(*client_args)
         self.object_client = ObjectClient(*client_args)
-        self.ec2api_client = APIClientEC2(*client_args)
-        self.s3_client = ObjectClientS3(*client_args)
+        self.ec2api_client = botoclients.APIClientEC2(*client_args)
+        self.s3_client = botoclients.ObjectClientS3(*client_args)
         self.custom_object_client = ObjectClientCustomizedHeader(*client_args)
         self.custom_account_client = \
             AccountClientCustomizedHeader(*client_args)
diff --git a/tempest/services/boto/__init__.py b/tempest/services/boto/__init__.py
deleted file mode 100644
index f744d9d..0000000
--- a/tempest/services/boto/__init__.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack, LLC
-# 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 ConfigParser import DuplicateSectionError
-from contextlib import closing
-import re
-from types import MethodType
-
-import boto
-
-from tempest.exceptions import InvalidConfiguration
-from tempest.exceptions import NotFound
-
-
-class BotoClientBase(object):
-
-    ALLOWED_METHODS = set()
-
-    def __init__(self, config,
-                 username=None, password=None,
-                 auth_url=None, tenant_name=None,
-                 *args, **kwargs):
-
-        self.connection_timeout = str(config.boto.http_socket_timeout)
-        self.num_retries = str(config.boto.num_retries)
-        self.build_timeout = config.boto.build_timeout
-        self.ks_cred = {"username": username,
-                        "password": password,
-                        "auth_url": auth_url,
-                        "tenant_name": tenant_name}
-
-    def _keystone_aws_get(self):
-        import keystoneclient.v2_0.client
-
-        keystone = keystoneclient.v2_0.client.Client(**self.ks_cred)
-        ec2_cred_list = keystone.ec2.list(keystone.auth_user_id)
-        ec2_cred = None
-        for cred in ec2_cred_list:
-            if cred.tenant_id == keystone.auth_tenant_id:
-                ec2_cred = cred
-                break
-        else:
-            ec2_cred = keystone.ec2.create(keystone.auth_user_id,
-                                           keystone.auth_tenant_id)
-        if not all((ec2_cred, ec2_cred.access, ec2_cred.secret)):
-            raise NotFound("Unable to get access and secret keys")
-        return ec2_cred
-
-    def _config_boto_timeout(self, timeout, retries):
-        try:
-            boto.config.add_section("Boto")
-        except DuplicateSectionError:
-            pass
-        boto.config.set("Boto", "http_socket_timeout", timeout)
-        boto.config.set("Boto", "num_retries", retries)
-
-    def __getattr__(self, name):
-        """Automatically creates methods for the allowed methods set."""
-        if name in self.ALLOWED_METHODS:
-            def func(self, *args, **kwargs):
-                with closing(self.get_connection()) as conn:
-                    return getattr(conn, name)(*args, **kwargs)
-
-            func.__name__ = name
-            setattr(self, name, MethodType(func, self, self.__class__))
-            setattr(self.__class__, name,
-                    MethodType(func, None, self.__class__))
-            return getattr(self, name)
-        else:
-            raise AttributeError(name)
-
-    def get_connection(self):
-        self._config_boto_timeout(self.connection_timeout, self.num_retries)
-        if not all((self.connection_data["aws_access_key_id"],
-                   self.connection_data["aws_secret_access_key"])):
-            if all(self.ks_cred.itervalues()):
-                ec2_cred = self._keystone_aws_get()
-                self.connection_data["aws_access_key_id"] = \
-                    ec2_cred.access
-                self.connection_data["aws_secret_access_key"] = \
-                    ec2_cred.secret
-            else:
-                raise InvalidConfiguration(
-                                    "Unable to get access and secret keys")
-        return self.connect_method(**self.connection_data)
diff --git a/tempest/services/boto/clients.py b/tempest/services/botoclients.py
similarity index 63%
rename from tempest/services/boto/clients.py
rename to tempest/services/botoclients.py
index 228e826..143257a 100644
--- a/tempest/services/boto/clients.py
+++ b/tempest/services/botoclients.py
@@ -15,13 +15,90 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import ConfigParser
+import contextlib
+import re
+import types
 import urlparse
 
-import boto
-from boto.ec2.regioninfo import RegionInfo
-from boto.s3.connection import OrdinaryCallingFormat
+from tempest import exceptions
 
-from tempest.services.boto import BotoClientBase
+import boto
+import boto.ec2
+import boto.s3.connection
+
+
+class BotoClientBase(object):
+
+    ALLOWED_METHODS = set()
+
+    def __init__(self, config,
+                 username=None, password=None,
+                 auth_url=None, tenant_name=None,
+                 *args, **kwargs):
+
+        self.connection_timeout = str(config.boto.http_socket_timeout)
+        self.num_retries = str(config.boto.num_retries)
+        self.build_timeout = config.boto.build_timeout
+        self.ks_cred = {"username": username,
+                        "password": password,
+                        "auth_url": auth_url,
+                        "tenant_name": tenant_name}
+
+    def _keystone_aws_get(self):
+        import keystoneclient.v2_0.client
+
+        keystone = keystoneclient.v2_0.client.Client(**self.ks_cred)
+        ec2_cred_list = keystone.ec2.list(keystone.auth_user_id)
+        ec2_cred = None
+        for cred in ec2_cred_list:
+            if cred.tenant_id == keystone.auth_tenant_id:
+                ec2_cred = cred
+                break
+        else:
+            ec2_cred = keystone.ec2.create(keystone.auth_user_id,
+                                           keystone.auth_tenant_id)
+        if not all((ec2_cred, ec2_cred.access, ec2_cred.secret)):
+            raise exceptions.NotFound("Unable to get access and secret keys")
+        return ec2_cred
+
+    def _config_boto_timeout(self, timeout, retries):
+        try:
+            boto.config.add_section("Boto")
+        except ConfigParser.DuplicateSectionError:
+            pass
+        boto.config.set("Boto", "http_socket_timeout", timeout)
+        boto.config.set("Boto", "num_retries", retries)
+
+    def __getattr__(self, name):
+        """Automatically creates methods for the allowed methods set."""
+        if name in self.ALLOWED_METHODS:
+            def func(self, *args, **kwargs):
+                with contextlib.closing(self.get_connection()) as conn:
+                    return getattr(conn, name)(*args, **kwargs)
+
+            func.__name__ = name
+            setattr(self, name, types.MethodType(func, self, self.__class__))
+            setattr(self.__class__, name,
+                    types.MethodType(func, None, self.__class__))
+            return getattr(self, name)
+        else:
+            raise AttributeError(name)
+
+    def get_connection(self):
+        self._config_boto_timeout(self.connection_timeout, self.num_retries)
+        if not all((self.connection_data["aws_access_key_id"],
+                   self.connection_data["aws_secret_access_key"])):
+            if all(self.ks_cred.itervalues()):
+                ec2_cred = self._keystone_aws_get()
+                self.connection_data["aws_access_key_id"] = \
+                    ec2_cred.access
+                self.connection_data["aws_secret_access_key"] = \
+                    ec2_cred.secret
+            else:
+                raise exceptions.InvalidConfiguration(
+                                    "Unable to get access and secret keys")
+        return self.connect_method(**self.connection_data)
 
 
 class APIClientEC2(BotoClientBase):
@@ -35,8 +112,8 @@
         aws_secret = config.boto.aws_secret
         purl = urlparse.urlparse(config.boto.ec2_url)
 
-        region = RegionInfo(name=config.identity.region,
-                            endpoint=purl.hostname)
+        region = boto.ec2.regioninfo.RegionInfo(name=config.identity.region,
+                                                endpoint=purl.hostname)
         port = purl.port
         if port is None:
             if purl.scheme is not "https":
@@ -134,7 +211,8 @@
                                 "is_secure": purl.scheme == "https",
                                 "host": purl.hostname,
                                 "port": port,
-                                "calling_format": OrdinaryCallingFormat()}
+                                "calling_format": boto.s3.connection.
+                                OrdinaryCallingFormat()}
 
     ALLOWED_METHODS = set(('create_bucket', 'delete_bucket', 'generate_url',
                            'get_all_buckets', 'get_bucket', 'delete_key',
diff --git a/tempest/services/compute/admin/json/quotas_client.py b/tempest/services/compute/admin/json/quotas_client.py
index 0a4bd72..b886834 100644
--- a/tempest/services/compute/admin/json/quotas_client.py
+++ b/tempest/services/compute/admin/json/quotas_client.py
@@ -37,38 +37,38 @@
         """
         post_body = {}
 
-        if injected_file_content_bytes >= 0:
+        if injected_file_content_bytes is not None:
             post_body['injected_file_content_bytes'] = \
                 injected_file_content_bytes
 
-        if metadata_items >= 0:
+        if metadata_items is not None:
             post_body['metadata_items'] = metadata_items
 
-        if ram >= 0:
+        if ram is not None:
             post_body['ram'] = ram
 
-        if floating_ips >= 0:
+        if floating_ips is not None:
             post_body['floating_ips'] = floating_ips
 
-        if key_pairs >= 0:
+        if key_pairs is not None:
             post_body['key_pairs'] = key_pairs
 
-        if instances >= 0:
+        if instances is not None:
             post_body['instances'] = instances
 
-        if security_group_rules >= 0:
+        if security_group_rules is not None:
             post_body['security_group_rules'] = security_group_rules
 
-        if injected_files >= 0:
+        if injected_files is not None:
             post_body['injected_files'] = injected_files
 
-        if cores >= 0:
+        if cores is not None:
             post_body['cores'] = cores
 
-        if injected_file_path_bytes >= 0:
+        if injected_file_path_bytes is not None:
             post_body['injected_file_path_bytes'] = injected_file_path_bytes
 
-        if security_groups >= 0:
+        if security_groups is not None:
             post_body['security_groups'] = security_groups
 
         post_body = json.dumps({'quota_set': post_body})
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index a5f6ec3..e4271d9 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -105,7 +105,7 @@
 
     def is_resource_deleted(self, id):
         try:
-            self.get_volume(id, wait=True)
+            self.get_volume(id)
         except exceptions.NotFound:
             return True
         return False
diff --git a/tempest/services/compute/xml/images_client.py b/tempest/services/compute/xml/images_client.py
index bde9e16..3b01efb 100644
--- a/tempest/services/compute/xml/images_client.py
+++ b/tempest/services/compute/xml/images_client.py
@@ -39,43 +39,43 @@
         self.build_timeout = self.config.compute.build_timeout
 
     def _parse_server(self, node):
-        json = xml_to_json(node)
-        return self._parse_links(node, json)
+        data = xml_to_json(node)
+        return self._parse_links(node, data)
 
     def _parse_image(self, node):
         """Parses detailed XML image information into dictionary."""
-        json = xml_to_json(node)
+        data = xml_to_json(node)
 
-        self._parse_links(node, json)
+        self._parse_links(node, data)
 
         # parse all metadata
-        if 'metadata' in json:
+        if 'metadata' in data:
             tag = node.find('{%s}metadata' % XMLNS_11)
-            json['metadata'] = dict((x.get('key'), x.text)
+            data['metadata'] = dict((x.get('key'), x.text)
                                     for x in tag.getchildren())
 
         # parse server information
-        if 'server' in json:
+        if 'server' in data:
             tag = node.find('{%s}server' % XMLNS_11)
-            json['server'] = self._parse_server(tag)
-        return json
+            data['server'] = self._parse_server(tag)
+        return data
 
-    def _parse_links(self, node, json):
+    def _parse_links(self, node, data):
         """Append multiple links under a list."""
         # look for links
-        if 'link' in json:
+        if 'link' in data:
             # remove single link element
-            del json['link']
-            json['links'] = [xml_to_json(x) for x in
+            del data['link']
+            data['links'] = [xml_to_json(x) for x in
                              node.findall('{http://www.w3.org/2005/Atom}link')]
-        return json
+        return data
 
     def _parse_images(self, xml):
-        json = {'images': []}
+        data = {'images': []}
         images = xml.getchildren()
         for image in images:
-            json['images'].append(self._parse_image(image))
-        return json
+            data['images'].append(self._parse_image(image))
+        return data
 
     def create_image(self, server_id, name, meta=None):
         """Creates an image of the original server."""
@@ -160,9 +160,17 @@
         body = xml_to_json(etree.fromstring(body))
         return resp, body['metadata']
 
+    def _metadata_body(image_id, meta):
+        post_body = Document('metadata')
+        for k, v in meta:
+            text = Text(v)
+            metadata = Element('meta', text, key=k)
+            post_body.append(metadata)
+        return post_body
+
     def set_image_metadata(self, image_id, meta):
         """Sets the metadata for an image."""
-        post_body = json.dumps({'metadata': meta})
+        post_body = self._metadata_body(image_id, meta)
         resp, body = self.put('images/%s/metadata' % str(image_id),
                               post_body, self.headers)
         body = xml_to_json(etree.fromstring(body))
@@ -170,13 +178,7 @@
 
     def update_image_metadata(self, image_id, meta):
         """Updates the metadata for an image."""
-        post_body = Element('metadata', meta)
-        for k, v in meta:
-            metadata = Element('meta', key=k)
-            text = Text(v)
-            metadata.append(text)
-            post_body.append(metadata)
-
+        post_body = self._metadata_body(image_id, meta)
         resp, body = self.post('images/%s/metadata' % str(image_id),
                                post_body, self.headers)
         body = xml_to_json(etree.fromstring(body))
@@ -191,7 +193,15 @@
 
     def set_image_metadata_item(self, image_id, key, meta):
         """Sets the value for a specific image metadata key."""
-        post_body = json.dumps({'meta': meta})
+        post_body = Document('meta', Text(meta), key=key)
+        resp, body = self.post('images/%s/metadata/%s' % (str(image_id), key),
+                               post_body, self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body['meta']
+
+    def update_image_metadata_item(self, image_id, key, meta):
+        """Sets the value for a specific image metadata key."""
+        post_body = Document('meta', Text(meta), key=key)
         resp, body = self.put('images/%s/metadata/%s' % (str(image_id), key),
                               post_body, self.headers)
         body = xml_to_json(etree.fromstring(body))
diff --git a/tempest/services/compute/xml/volumes_extensions_client.py b/tempest/services/compute/xml/volumes_extensions_client.py
index 60ef398..69b9bac 100644
--- a/tempest/services/compute/xml/volumes_extensions_client.py
+++ b/tempest/services/compute/xml/volumes_extensions_client.py
@@ -141,7 +141,7 @@
 
     def is_resource_deleted(self, id):
         try:
-            self.get_volume(id, wait=True)
+            self.get_volume(id)
         except exceptions.NotFound:
             return True
         return False
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/json/identity_client.py
index 403a3ac..68e7d4b 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/json/identity_client.py
@@ -244,8 +244,10 @@
         if headers is None:
             headers = {}
 
+        self._log_request(method, url, headers, body)
         resp, resp_body = self.http_obj.request(url, method,
                                                 headers=headers, body=body)
+        self._log_response(resp, resp_body)
 
         if resp.status in (401, 403):
             resp_body = json.loads(resp_body)
diff --git a/tempest/services/identity/xml/identity_client.py b/tempest/services/identity/xml/identity_client.py
index 1b96ae0..2431282 100644
--- a/tempest/services/identity/xml/identity_client.py
+++ b/tempest/services/identity/xml/identity_client.py
@@ -45,8 +45,8 @@
         return array
 
     def _parse_body(self, body):
-        json = xml_to_json(body)
-        return json
+        data = xml_to_json(body)
+        return data
 
     def has_admin_extensions(self):
         """
@@ -272,9 +272,10 @@
         self.http_obj = httplib2.Http(disable_ssl_certificate_validation=dscv)
         if headers is None:
             headers = {}
-
+        self._log_request(method, url, headers, body)
         resp, resp_body = self.http_obj.request(url, method,
                                                 headers=headers, body=body)
+        self._log_response(resp, resp_body)
 
         if resp.status in (401, 403):
             resp_body = json.loads(resp_body)
diff --git a/tempest/services/image/json/image_client.py b/tempest/services/image/json/image_client.py
index d595ec3..e9276aa 100644
--- a/tempest/services/image/json/image_client.py
+++ b/tempest/services/image/json/image_client.py
@@ -16,6 +16,7 @@
 #    under the License.
 
 import copy
+import errno
 import json
 import os
 import time
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index 75e1a8b..ff1556f 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -125,7 +125,7 @@
 
     def is_resource_deleted(self, id):
         try:
-            self.get_volume(id, wait=True)
+            self.get_volume(id)
         except exceptions.NotFound:
             return True
         return False
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index 862ffae..5041869 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -151,7 +151,7 @@
 
     def is_resource_deleted(self, id):
         try:
-            self.get_volume(id, wait=True)
+            self.get_volume(id)
         except exceptions.NotFound:
             return True
         return False
diff --git a/tempest/tests/compute/base.py b/tempest/tests/compute/base.py
index f2af1fc..594535f 100644
--- a/tempest/tests/compute/base.py
+++ b/tempest/tests/compute/base.py
@@ -154,7 +154,7 @@
     @classmethod
     def clear_isolated_creds(cls):
         if not cls.isolated_creds:
-            pass
+            return
         admin_client = cls._get_identity_admin_client()
 
         for user, tenant in cls.isolated_creds:
diff --git a/tempest/tests/compute/servers/test_console_output.py b/tempest/tests/compute/servers/test_console_output.py
index 78639f8..bdf449d 100644
--- a/tempest/tests/compute/servers/test_console_output.py
+++ b/tempest/tests/compute/servers/test_console_output.py
@@ -28,7 +28,6 @@
     @classmethod
     def setUpClass(self, cls):
         cls.name = rand_name('server')
-        cls.client = cls.servers_client
         resp, server = cls.servers_client.create_server(cls.name,
                                                         cls.image_ref,
                                                         cls.flavor_ref)
@@ -45,7 +44,8 @@
         # Positive test:Should be able to GET the console output
         # for a given server_id and number of lines
         def get_output():
-            resp, output = self.client.get_console_output(self.server_id, 10)
+            resp, output = self.servers_client.get_console_output(
+                self.server_id, 10)
             self.assertEqual(200, resp.status)
             self.assertNotEqual(output, None)
             lines = len(output.split('\n'))
@@ -57,7 +57,8 @@
         # Negative test: Should not be able to get the console output
         # for an invalid server_id
         try:
-            resp, output = self.client.get_console_output('!@#$%^&*()', 10)
+            resp, output = self.servers_client.get_console_output(
+                '!@#$%^&*()', 10)
         except exceptions.NotFound:
             pass
 
@@ -72,8 +73,8 @@
                                                        'REBOOT')
             resp, server = self.servers_client.get_server(self.server_id)
             if (server['status'] == 'REBOOT'):
-                resp, output = self.client.get_console_output(self.server_id,
-                                                              10)
+                resp, output = self.servers_client.get_console_output(
+                    self.server_id, 10)
                 self.assertEqual(200, resp.status)
                 self.assertNotEqual(output, None)
                 lines = len(output.split('\n'))
diff --git a/tempest/tests/compute/servers/test_server_actions.py b/tempest/tests/compute/servers/test_server_actions.py
index c30538f..06e441a 100644
--- a/tempest/tests/compute/servers/test_server_actions.py
+++ b/tempest/tests/compute/servers/test_server_actions.py
@@ -206,6 +206,18 @@
             self.fail('The server rebuild for a non existing server should not'
                       ' be allowed')
 
+    @classmethod
+    def rebuild_servers(cls):
+        # Destroy any existing server and creates a new one
+        cls.clear_servers()
+        cls.name = rand_name('server')
+        resp, server = cls.create_server_with_extras(cls.name,
+                                                     cls.image_ref,
+                                                     cls.flavor_ref)
+        cls.server_id = server['id']
+        cls.password = server['adminPass']
+        cls.client.wait_for_server_status(cls.server_id, 'ACTIVE')
+
 
 class ServerActionsTestXML(base.BaseComputeTestXML,
                            ServerActionsTestBase):
@@ -216,30 +228,13 @@
             self.client.wait_for_server_status(self.server_id, 'ACTIVE')
         except exceptions:
             # Rebuild server if something happened to it during a test
-            self.clear_servers()
-            resp, server = self.create_server_with_extras(self.name,
-                                                          self.image_ref,
-                                                          self.flavor_ref)
-            self.server_id = server['id']
-            self.password = server['adminPass']
-            self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+            self.rebuild_servers()
 
     @classmethod
     def setUpClass(cls):
         super(ServerActionsTestXML, cls).setUpClass()
         cls.client = cls.servers_client
-        cls.name = rand_name('server')
-        resp, server = cls.create_server_with_extras(cls.name,
-                                                     cls.image_ref,
-                                                     cls.flavor_ref)
-        cls.server_id = server['id']
-        cls.password = server['adminPass']
-        cls.client.wait_for_server_status(cls.server_id, 'ACTIVE')
-
-    @classmethod
-    def tearDownClass(cls):
-        cls.clear_servers()
-        super(ServerActionsTestXML, cls).tearDownClass()
+        cls.rebuild_servers()
 
 
 class ServerActionsTestJSON(base.BaseComputeTestJSON,
@@ -251,27 +246,10 @@
             self.client.wait_for_server_status(self.server_id, 'ACTIVE')
         except exceptions:
             # Rebuild server if something happened to it during a test
-            self.clear_servers()
-            resp, server = self.create_server_with_extras(self.name,
-                                                          self.image_ref,
-                                                          self.flavor_ref)
-            self.server_id = server['id']
-            self.password = server['adminPass']
-            self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+            self.rebuild_servers()
 
     @classmethod
     def setUpClass(cls):
         super(ServerActionsTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
-        cls.name = rand_name('server')
-        resp, server = cls.create_server_with_extras(cls.name,
-                                                     cls.image_ref,
-                                                     cls.flavor_ref)
-        cls.server_id = server['id']
-        cls.password = server['adminPass']
-        cls.client.wait_for_server_status(cls.server_id, 'ACTIVE')
-
-    @classmethod
-    def tearDownClass(cls):
-        cls.clear_servers()
-        super(ServerActionsTestJSON, cls).tearDownClass()
+        cls.rebuild_servers()
diff --git a/tempest/tests/compute/servers/test_servers.py b/tempest/tests/compute/servers/test_servers.py
index fbcfe85..caf0679 100644
--- a/tempest/tests/compute/servers/test_servers.py
+++ b/tempest/tests/compute/servers/test_servers.py
@@ -161,25 +161,9 @@
         super(ServersTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
 
-    def tearDown(self):
-        # clean up any remaining servers and wait for them to fully
-        # delete. This is done because delete calls are async, and if
-        # deletes are running slow we could very well overrun system
-        # memory
-        self.clear_servers()
-        super(ServersTestJSON, self).tearDown()
-
 
 class ServersTestXML(base.BaseComputeTestXML, ServersTestBase):
     @classmethod
     def setUpClass(cls):
         super(ServersTestXML, cls).setUpClass()
         cls.client = cls.servers_client
-
-    def tearDown(self):
-        # clean up any remaining servers and wait for them to fully
-        # delete. This is done because delete calls are async, and if
-        # deletes are running slow we could very well overrun system
-        # memory
-        self.clear_servers()
-        super(ServersTestXML, self).tearDown()
diff --git a/tempest/tests/compute/servers/test_servers_negative.py b/tempest/tests/compute/servers/test_servers_negative.py
index 09d2a9c..9b528f6 100644
--- a/tempest/tests/compute/servers/test_servers_negative.py
+++ b/tempest/tests/compute/servers/test_servers_negative.py
@@ -273,3 +273,17 @@
 
         self.assertRaises(exceptions.NotFound, self.client.delete_server,
                           sys.maxint + 1)
+
+    @attr(type='negative')
+    def test_create_with_nonexistent_security_group(self):
+        # Create a server with a nonexistent security group
+        try:
+            security_groups = [{'name': 'does_not_exist'}]
+            self.create_server_with_extras('fail',
+                                           self.image_ref,
+                                           self.flavor_ref,
+                                           security_groups=security_groups)
+        except exceptions.BadRequest:
+            pass
+        else:
+            self.fail('Server was created with nonexistent security group')
diff --git a/tempest/tests/volume/admin/test_volume_types_extra_specs.py b/tempest/tests/volume/admin/test_volume_types_extra_specs.py
index 98756db..31e2879 100644
--- a/tempest/tests/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/tests/volume/admin/test_volume_types_extra_specs.py
@@ -26,7 +26,6 @@
     def setUpClass(cls):
         super(VolumeTypesExtraSpecsTest, cls).setUpClass()
         vol_type_name = rand_name('Volume-type-')
-        cls.extra_spec = {"spec1": "val1"}
         resp, cls.volume_type = cls.client.create_volume_type(vol_type_name)
 
     @classmethod
@@ -37,6 +36,12 @@
     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)
@@ -49,49 +54,46 @@
     def test_volume_type_extra_specs_update(self):
         # Update volume type extra specs
         try:
-            extra_spec = {"spec1": "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('spec1' in body,
-                            "Volume type extra spec incorrectly updated")
-            self.assertEqual(extra_spec['spec1'], body['spec1'],
-                             "Volume type extra spec incorrectly updated")
-        except Exception:
-            self.fail("Couldnt update volume type extra spec")
-
-    def test_volume_type_extra_spec_create_delete(self):
-        # Create/Delete volume type extra spec.
-        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")
-            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")
 
-    def test_volume_type_extra_spec_create_get(self):
-        # Create/get 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")
+        except Exception:
+            self.fail("Couldnt update volume type extra spec")
+
+    def test_volume_type_extra_spec_create_get_delete(self):
+        # Create/Get/Delete volume type extra spec.
         try:
-            extra_specs = {"spec1": "val1"}
+            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, fetched_vol_type_extra_spec = 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")
diff --git a/tempest/tests/volume/base.py b/tempest/tests/volume/base.py
index 480f125..4ddd670 100644
--- a/tempest/tests/volume/base.py
+++ b/tempest/tests/volume/base.py
@@ -113,7 +113,7 @@
     @classmethod
     def clear_isolated_creds(cls):
         if not cls.isolated_creds:
-            pass
+            return
         admin_client = cls._get_identity_admin_client()
 
         for user, tenant in cls.isolated_creds: