Merge "Fixes whitebox testing for deleted type change"
diff --git a/HACKING.rst b/HACKING.rst
index 103f8cd..fed4130 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -56,8 +56,8 @@
   import logging
   import random
   import StringIO
+  import testtools
   import time
-  import unittest
 
   import eventlet
   import webob.exc
diff --git a/etc/TEMPEST_README.txt b/etc/TEMPEST_README.txt
index e46e195..4f907a0 100644
--- a/etc/TEMPEST_README.txt
+++ b/etc/TEMPEST_README.txt
@@ -9,6 +9,6 @@
 Use virtualenv to install all needed packages. Till then, the following
 packages must be installed:
 -httplib2
--unittest2
+-testtools
 -paramiko
 -nose
\ No newline at end of file
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index fc20d0b..e1196f0 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -18,6 +18,28 @@
 # The identity region
 region = RegionOne
 
+# This should be the username of a user WITHOUT administrative privileges
+username = demo
+# The above non-administrative user's password
+password = secret
+# The above non-administrative user's tenant name
+tenant_name = demo
+
+# This should be the username of an alternate user WITHOUT
+# administrative privileges
+alt_username = alt_demo
+# The above non-administrative user's password
+alt_password = secret
+# The above non-administrative user's tenant name
+alt_tenant_name = alt_demo
+
+# This should be the username of a user WITH administrative privileges
+admin_username = admin
+# The above non-administrative user's password
+admin_password = secret
+# The above non-administrative user's tenant name
+admin_tenant_name = admin
+
 [compute]
 # This section contains configuration options used when executing tests
 # against the OpenStack Compute API.
@@ -34,24 +56,6 @@
 # are known.
 allow_tenant_reuse = true
 
-# This should be the username of a user WITHOUT administrative privileges
-username = demo
-# The above non-administrative user's password
-password = pass
-# The above non-administrative user's tenant name
-tenant_name = demo
-
-# This should be the username of an alternate user WITHOUT
-# administrative privileges
-alt_username = alt_demo
-# The above non-administrative user's password
-alt_password = pass
-# The above non-administrative user's tenant name
-alt_tenant_name = alt_demo
-
-# The compute region
-region = RegionOne
-
 # Reference data for tests. The ref and ref_alt should be
 # distinct images/flavors.
 image_ref = {$IMAGE_ID}
@@ -73,13 +77,13 @@
 run_ssh = false
 
 # Name of a user used to authenticated to an instance
-ssh_user = {$SSH_USER}
+ssh_user = cirros
 
 # Network id used for SSH (public, private, etc)
-network_for_ssh = {$SSH_NETWORK}
+network_for_ssh = private
 
 # IP version of the address used for SSH
-ip_version_for_ssh = {$SSH_IP_VERSION}
+ip_version_for_ssh = 4
 
 # Number of seconds to wait to authenticate to an instance
 ssh_timeout = 300
@@ -107,6 +111,18 @@
 # whitebox test cases, which look at internal Nova database state,
 # SSH into VMs to check instance state, etc.
 
+# Run live migration tests (requires 2 hosts)
+live_migration_available = false
+
+# Use block live migration (Otherwise, non-block migration will be
+# performed, which requires XenServer pools in case of using XS)
+use_block_migration_for_live_migration = false
+
+# By default, rely on the status of the diskConfig extension to
+# decide if to execute disk config tests. When set to false, tests
+# are forced to skip, regardless of the extension status
+disk_config_enabled_override = true
+
 # Should we run whitebox tests for Compute?
 whitebox_enabled = true
 
@@ -119,23 +135,20 @@
 # Directory containing nova binaries such as nova-manage
 bin_dir = /usr/local/bin
 
+# Connection string to the database of Compute service
+db_uri = mysql://nova:secret@localhost/nova
+
 # Path to a private key file for SSH access to remote hosts
 path_to_private_key = /home/user/.ssh/id_rsa
 
-# Connection string to the database of Compute service
-db_uri = mysql://user:pass@localhost/nova
-
-# Run live migration tests (requires 2 hosts)
-live_migration_available = false
-
-# Use block live migration (Otherwise, non-block migration will be
-# performed, which requires XenServer pools in case of using XS)
-use_block_migration_for_live_migration = false
-
-# By default, rely on the status of the diskConfig extension to
-# decide if to execute disk config tests. When set to false, tests
-# are forced to skip, regardless of the extension status
-disk_config_enabled_override = true
+[compute-admin]
+# This should be the username of a user WITH administrative privileges
+# If not defined the admin user from the identity section will be used
+username =
+# The above administrative user's password
+password =
+# The above administrative user's tenant name
+tenant_name =
 
 [image]
 # This section contains configuration options used when executing tests
@@ -149,24 +162,6 @@
 # The version of the OpenStack Images API to use
 api_version = 1
 
-# This is the main host address of the Image API
-host = 127.0.0.1
-
-# Port that the Image API is running on
-port = 9292
-
-[compute-admin]
-# This section contains configuration options for an administrative
-# user of the Compute API. These options are used in tests that stress
-# the admin-only parts of the Compute API
-
-# This should be the username of a user WITH administrative privileges
-username = admin
-# The above administrative user's password
-password = pass
-# The above administrative user's tenant name
-tenant_name = admin
-
 [network]
 # This section contains configuration options used when executing tests
 # against the OpenStack Network API.
@@ -176,13 +171,6 @@
 # Catalog type of the Quantum Service
 catalog_type = network
 
-# This should be the username of a user WITHOUT administrative privileges
-username = demo
-# The above non-administrative user's password
-password = pass
-# The above non-administrative user's tenant name
-tenant_name = demo
-
 # A large private cidr block from which to allocate smaller blocks for
 # tenant networks.
 tenant_network_cidr = 10.100.0.0/16
@@ -229,9 +217,6 @@
 # this value as "object-store"
 catalog_type = object-store
 
-# The object-store region
-region = RegionOne
-
 # Number of seconds to time on waiting for a container to container
 # synchronization complete
 container_sync_timeout = 120
@@ -252,9 +237,6 @@
 aws_access =
 aws_secret =
 
-#Region
-aws_region = RegionOne
-
 #Image materials for S3 upload
 # ALL content of the specified directory will be uploaded to S3
 s3_materials_path = /opt/stack/devstack/files/images/s3-materials/cirros-0.3.0
diff --git a/stress/tools/nova_destroy_all.py b/stress/tools/nova_destroy_all.py
index 0070e72..00d8883 100755
--- a/stress/tools/nova_destroy_all.py
+++ b/stress/tools/nova_destroy_all.py
@@ -21,10 +21,9 @@
 
 # get the environment variables for credentials
 identity = tempest.config.TempestConfig().identity
-compute = tempest.config.TempestConfig().compute
 
-nt = client.Client(compute.username, compute.password,
-                   compute.tenant_name, identity.uri)
+nt = client.Client(identity.username, identity.password,
+                   identity.tenant_name, identity.uri)
 
 flavor_list = nt.flavors.list()
 server_list = nt.servers.list()
diff --git a/stress/tools/nova_status.py b/stress/tools/nova_status.py
index f9bc707..ee20282 100755
--- a/stress/tools/nova_status.py
+++ b/stress/tools/nova_status.py
@@ -21,12 +21,11 @@
 
 # get the environment variables for credentials
 identity = tempest.config.TempestConfig().identity
-compute = tempest.config.TempestConfig().compute
-print compute.username, compute.password,\
-    compute.tenant_name, identity.uri
+print identity.username, identity.password,\
+    identity.tenant_name, identity.uri
 
-nt = client.Client(compute.username, compute.password,
-                   compute.tenant_name, identity.uri)
+nt = client.Client(identity.username, identity.password,
+                   identity.tenant_name, identity.uri)
 
 flavor_list = nt.flavors.list()
 server_list = nt.servers.list()
diff --git a/tempest/clients.py b/tempest/clients.py
index 801bdcf..29e83bf 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -156,9 +156,9 @@
 
         # If no creds are provided, we fall back on the defaults
         # in the config file for the Compute API.
-        self.username = username or self.config.compute.username
-        self.password = password or self.config.compute.password
-        self.tenant_name = tenant_name or self.config.compute.tenant_name
+        self.username = username or self.config.identity.username
+        self.password = password or self.config.identity.password
+        self.tenant_name = tenant_name or self.config.identity.tenant_name
 
         if None in (self.username, self.password, self.tenant_name):
             msg = ("Missing required credentials. "
@@ -208,21 +208,6 @@
             AccountClientCustomizedHeader(*client_args)
 
 
-class NonAdminManager(Manager):
-
-    """
-    Manager object that uses the alt_XXX credentials for its
-    managed client objects
-    """
-
-    def __init__(self, interface='json'):
-        conf = config.TempestConfig()
-        super(NonAdminManager, self).__init__(conf.compute.username,
-                                              conf.compute.password,
-                                              conf.compute.tenant_name,
-                                              interface=interface)
-
-
 class AltManager(Manager):
 
     """
@@ -232,26 +217,42 @@
 
     def __init__(self):
         conf = config.TempestConfig()
-        super(AltManager, self).__init__(conf.compute.alt_username,
-                                         conf.compute.alt_password,
-                                         conf.compute.alt_tenant_name)
+        super(AltManager, self).__init__(conf.identity.alt_username,
+                                         conf.identity.alt_password,
+                                         conf.identity.alt_tenant_name)
 
 
 class AdminManager(Manager):
 
     """
-    Manager object that uses the alt_XXX credentials for its
+    Manager object that uses the admin credentials for its
     managed client objects
     """
 
     def __init__(self, interface='json'):
         conf = config.TempestConfig()
-        super(AdminManager, self).__init__(conf.compute_admin.username,
-                                           conf.compute_admin.password,
-                                           conf.compute_admin.tenant_name,
+        super(AdminManager, self).__init__(conf.identity.admin_username,
+                                           conf.identity.admin_password,
+                                           conf.identity.admin_tenant_name,
                                            interface=interface)
 
 
+class ComputeAdminManager(Manager):
+
+    """
+    Manager object that uses the compute_admin credentials for its
+    managed client objects
+    """
+
+    def __init__(self, interface='json'):
+        conf = config.TempestConfig()
+        base = super(ComputeAdminManager, self)
+        base.__init__(conf.compute_admin.username,
+                      conf.compute_admin.password,
+                      conf.compute_admin.tenant_name,
+                      interface=interface)
+
+
 class ServiceManager(object):
 
     """
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 4213b10..5710f4c 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -44,7 +44,7 @@
         self.token = None
         self.base_url = None
         self.config = config
-        self.region = {'compute': self.config.compute.region}
+        self.region = {'compute': self.config.identity.region}
         self.endpoint_url = 'publicURL'
         self.strategy = self.config.identity.strategy
         self.headers = {'Content-Type': 'application/%s' % self.TYPE,
diff --git a/tempest/config.py b/tempest/config.py
index e348cce..89fa2d9 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -37,66 +37,13 @@
     cfg.StrOpt('uri',
                default=None,
                help="Full URI of the OpenStack Identity API (Keystone)"),
-    cfg.StrOpt('host',
-               default="127.0.0.1",
-               help="(DEPRECATED, use uri) Host IP for making Identity "
-                    "API requests."),
-    cfg.IntOpt('port',
-               default=8773,
-               help="(DEPRECATED, use uri) Port for the Identity service."),
-    cfg.StrOpt('api_version',
-               default="v1.1",
-               help="(DEPRECATED, use uri) Version of the Identity API"),
-    cfg.StrOpt('path',
-               default='/',
-               help="(IGNORED) Path of API request"),
-    cfg.BoolOpt('use_ssl',
-                default=False,
-                help="(DEPRECATED, use uri) Specifies if we are using https."),
     cfg.StrOpt('strategy',
                default='keystone',
                help="Which auth method does the environment use? "
                     "(basic|keystone)"),
     cfg.StrOpt('region',
-               default=None,
+               default='RegionOne',
                help="The identity region name to use."),
-]
-
-
-def register_identity_opts(conf):
-    conf.register_group(identity_group)
-    for opt in IdentityGroup:
-        conf.register_opt(opt, group='identity')
-
-    # Fall back to piecemeal identity URI for legacy support
-    authurl = data_utils.build_url(conf.identity.host,
-                                   str(conf.identity.port),
-                                   conf.identity.api_version,
-                                   path='',  # Ignore path...
-                                   use_ssl=conf.identity.use_ssl)
-
-    if not conf.identity.uri:
-        conf.identity.uri = authurl
-
-
-compute_group = cfg.OptGroup(name='compute',
-                             title='Compute Service Options')
-
-ComputeGroup = [
-    cfg.BoolOpt('allow_tenant_isolation',
-                default=False,
-                help="Allows test cases to create/destroy tenants and "
-                     "users. This option enables isolated test cases and "
-                     "better parallel execution, but also requires that "
-                     "OpenStack Identity API admin credentials are known."),
-    cfg.BoolOpt('allow_tenant_reuse',
-                default=True,
-                help="If allow_tenant_isolation is True and a tenant that "
-                     "would be created for a given test already exists (such "
-                     "as from a previously-failed run), re-use that tenant "
-                     "instead of failing because of the conflict. Note that "
-                     "this would result in the tenant being deleted at the "
-                     "end of a subsequent successful run."),
     cfg.StrOpt('username',
                default='demo',
                help="Username to use for Nova API requests."),
@@ -119,9 +66,45 @@
                default=None,
                help="API key to use when authenticating as alternate user.",
                secret=True),
-    cfg.StrOpt('region',
-               default=None,
-               help="The compute region name to use."),
+    cfg.StrOpt('admin_username',
+               default='admin',
+               help="Administrative Username to use for"
+                    "Keystone API requests."),
+    cfg.StrOpt('admin_tenant_name',
+               default='admin',
+               help="Administrative Tenant name to use for Keystone API "
+                    "requests."),
+    cfg.StrOpt('admin_password',
+               default='pass',
+               help="API key to use when authenticating as admin.",
+               secret=True),
+]
+
+
+def register_identity_opts(conf):
+    conf.register_group(identity_group)
+    for opt in IdentityGroup:
+        conf.register_opt(opt, group='identity')
+
+
+compute_group = cfg.OptGroup(name='compute',
+                             title='Compute Service Options')
+
+ComputeGroup = [
+    cfg.BoolOpt('allow_tenant_isolation',
+                default=False,
+                help="Allows test cases to create/destroy tenants and "
+                     "users. This option enables isolated test cases and "
+                     "better parallel execution, but also requires that "
+                     "OpenStack Identity API admin credentials are known."),
+    cfg.BoolOpt('allow_tenant_reuse',
+                default=True,
+                help="If allow_tenant_isolation is True and a tenant that "
+                     "would be created for a given test already exists (such "
+                     "as from a previously-failed run), re-use that tenant "
+                     "instead of failing because of the conflict. Note that "
+                     "this would result in the tenant being deleted at the "
+                     "end of a subsequent successful run."),
     cfg.StrOpt('image_ref',
                default="{$IMAGE_ID}",
                help="Valid secondary image reference to be used in tests."),
@@ -180,6 +163,14 @@
     cfg.StrOpt('log_level',
                default="ERROR",
                help="Level for logging compute API calls."),
+    cfg.StrOpt('path_to_private_key',
+               default=None,
+               help="Path to a private key file for SSH access to remote "
+                    "hosts"),
+    cfg.BoolOpt('disk_config_enabled_override',
+                default=True,
+                help="If false, skip config tests regardless of the "
+                     "extension status"),
     cfg.BoolOpt('whitebox_enabled',
                 default=False,
                 help="Does the test environment support whitebox tests for "
@@ -196,14 +187,6 @@
     cfg.StrOpt('bin_dir',
                default="/usr/local/bin/",
                help="Directory containing nova binaries such as nova-manage"),
-    cfg.StrOpt('path_to_private_key',
-               default=None,
-               help="Path to a private key file for SSH access to remote "
-                    "hosts"),
-    cfg.BoolOpt('disk_config_enabled_override',
-                default=True,
-                help="If false, skip config tests regardless of the "
-                     "extension status"),
 ]
 
 
@@ -240,13 +223,6 @@
                            title="Image Service Options")
 
 ImageGroup = [
-    cfg.StrOpt('host',
-               default='127.0.0.1',
-               help="Host IP for making Images API requests. Defaults to "
-                    "'127.0.0.1'."),
-    cfg.IntOpt('port',
-               default=9292,
-               help="Listen port of the Images service."),
     cfg.StrOpt('api_version',
                default='1',
                help="Version of the API"),
@@ -325,9 +301,6 @@
     cfg.StrOpt('catalog_type',
                default='object-store',
                help="Catalog type of the Object-Storage service."),
-    cfg.StrOpt('region',
-               default=None,
-               help='The object-store region name to use.'),
     cfg.StrOpt('container_sync_timeout',
                default=120,
                help="Number of seconds to time on waiting for a container"
@@ -360,9 +333,6 @@
     cfg.StrOpt('aws_access',
                default=None,
                help="AWS Access Key"),
-    cfg.StrOpt('aws_region',
-               default=None,
-               help="AWS Region"),
     cfg.StrOpt('s3_materials_path',
                default="/opt/stack/devstack/files/images/"
                        "s3-materials/cirros-0.3.0",
@@ -448,17 +418,21 @@
 
         register_compute_opts(cfg.CONF)
         register_identity_opts(cfg.CONF)
-        register_compute_admin_opts(cfg.CONF)
         register_image_opts(cfg.CONF)
         register_network_opts(cfg.CONF)
         register_volume_opts(cfg.CONF)
         register_object_storage_opts(cfg.CONF)
         register_boto_opts(cfg.CONF)
+        register_compute_admin_opts(cfg.CONF)
         self.compute = cfg.CONF.compute
-        self.compute_admin = cfg.CONF['compute-admin']
         self.identity = cfg.CONF.identity
         self.images = cfg.CONF.image
         self.network = cfg.CONF.network
         self.volume = cfg.CONF.volume
         self.object_storage = cfg.CONF['object-storage']
         self.boto = cfg.CONF.boto
+        self.compute_admin = cfg.CONF['compute-admin']
+        if not self.compute_admin.username:
+            self.compute_admin.username = self.identity.admin_username
+            self.compute_admin.password = self.identity.admin_password
+            self.compute_admin.tenant_name = self.identity.admin_tenant_name
diff --git a/tempest/manager.py b/tempest/manager.py
index ef9eed4..4137ec3 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -114,11 +114,11 @@
         # identified user, so a new client needs to be created for
         # each user that operations need to be performed for.
         if not username:
-            username = self.config.compute.username
+            username = self.config.identity.username
         if not password:
-            password = self.config.compute.password
+            password = self.config.identity.password
         if not tenant_name:
-            tenant_name = self.config.compute.tenant_name
+            tenant_name = self.config.identity.tenant_name
 
         if None in (username, password, tenant_name):
             msg = ("Missing required credentials for compute client. "
@@ -153,18 +153,17 @@
         # This identity client is not intended to check the security
         # of the identity service, so use admin credentials by default.
         if not username:
-            username = self.config.compute_admin.username
+            username = self.config.identity.admin_username
         if not password:
-            password = self.config.compute_admin.password
+            password = self.config.identity.admin_password
         if not tenant_name:
-            tenant_name = self.config.compute_admin.tenant_name
+            tenant_name = self.config.identity.admin_tenant_name
 
         if None in (username, password, tenant_name):
             msg = ("Missing required credentials for identity client. "
                    "username: %(username)s, password: %(password)s, "
                    "tenant_name: %(tenant_name)s") % locals()
             raise exceptions.InvalidConfiguration(msg)
-        #TODO(afazekas): Above is a code dpulication, net to be resolved
 
         auth_url = self.config.identity.uri
         dscv = self.config.identity.disable_ssl_certificate_validation
@@ -182,9 +181,9 @@
         # preferable to authenticating as a specific user because
         # working with certain resources (public routers and networks)
         # often requires admin privileges anyway.
-        username = self.config.compute_admin.username
-        password = self.config.compute_admin.password
-        tenant_name = self.config.compute_admin.tenant_name
+        username = self.config.identity.admin_username
+        password = self.config.identity.admin_password
+        tenant_name = self.config.identity.admin_tenant_name
 
         if None in (username, password, tenant_name):
             msg = ("Missing required credentials for network client. "
@@ -223,9 +222,9 @@
 
         # If no creds are provided, we fall back on the defaults
         # in the config file for the Compute API.
-        username = username or self.config.compute.username
-        password = password or self.config.compute.password
-        tenant_name = tenant_name or self.config.compute.tenant_name
+        username = username or self.config.identity.username
+        password = password or self.config.identity.password
+        tenant_name = tenant_name or self.config.identity.tenant_name
 
         if None in (username, password, tenant_name):
             msg = ("Missing required credentials. "
@@ -270,9 +269,9 @@
     def __init__(self):
         conf = tempest.config.TempestConfig()
         super(ComputeFuzzClientAltManager, self).__init__(
-            conf.compute.alt_username,
-            conf.compute.alt_password,
-            conf.compute.alt_tenant_name)
+            conf.identity.alt_username,
+            conf.identity.alt_password,
+            conf.identity.alt_tenant_name)
 
 
 class ComputeFuzzClientAdminManager(Manager):
diff --git a/tempest/services/boto/clients.py b/tempest/services/boto/clients.py
index 9cfe234..228e826 100644
--- a/tempest/services/boto/clients.py
+++ b/tempest/services/boto/clients.py
@@ -35,7 +35,7 @@
         aws_secret = config.boto.aws_secret
         purl = urlparse.urlparse(config.boto.ec2_url)
 
-        region = RegionInfo(name=config.boto.aws_region,
+        region = RegionInfo(name=config.identity.region,
                             endpoint=purl.hostname)
         port = purl.port
         if port is None:
diff --git a/tempest/services/image/service.py b/tempest/services/image/service.py
index 270bf03..66ba219 100644
--- a/tempest/services/image/service.py
+++ b/tempest/services/image/service.py
@@ -44,9 +44,9 @@
             dscv = self.config.identity.disable_ssl_certificate_validation
             auth_url = self.config.identity.uri
             keystone = keystoneclient.v2_0.client.Client(
-                    username=config.compute.username,
-                    password=config.compute.password,
-                    tenant_name=config.compute.tenant_name,
+                    username=config.identity.username,
+                    password=config.identity.password,
+                    tenant_name=config.identity.tenant_name,
                     auth_url=auth_url,
                     insecure=dscv)
             token = keystone.auth_token
diff --git a/tempest/test.py b/tempest/test.py
index dc480d1..7804e12 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -18,14 +18,14 @@
 import logging
 import time
 
-import unittest2 as unittest
+import testtools
 
 from tempest import manager
 
 LOG = logging.getLogger(__name__)
 
 
-class TestCase(unittest.TestCase):
+class TestCase(testtools.TestCase):
 
     """
     Base test case class for all Tempest tests
diff --git a/tempest/testboto.py b/tempest/testboto.py
index 29ac3ca..7031fe2 100644
--- a/tempest/testboto.py
+++ b/tempest/testboto.py
@@ -25,9 +25,8 @@
 from boto.exception import EC2ResponseError
 from boto.s3.bucket import Bucket
 from boto.s3.key import Key
-import nose
 import testresources
-import unittest2 as unittest
+import testtools
 
 from tempest.exceptions import TearDownException
 import tempest.tests.boto
@@ -123,11 +122,11 @@
     return string + ")"
 
 
-class BotoTestCase(unittest.TestCase,
+class BotoTestCase(testtools.TestCase,
                    testresources.ResourcedTestCase):
     """Recommended to use as base class for boto related test."""
 
-    resources = [('boto_init', tempest.tests.boto.generic_setup_package())]
+    resources = [('boto_init', tempest.tests.boto.BotoResource())]
 
     @classmethod
     def setUpClass(cls):
@@ -137,11 +136,11 @@
         cls._sequence = -1
         if (hasattr(cls, "EC2") and
             tempest.tests.boto.EC2_CAN_CONNECT_ERROR is not None):
-                raise nose.SkipTest("EC2 " + cls.__name__ + ": " +
+            raise cls.skipException("EC2 " + cls.__name__ + ": " +
                                     tempest.tests.boto.EC2_CAN_CONNECT_ERROR)
         if (hasattr(cls, "S3") and
             tempest.tests.boto.S3_CAN_CONNECT_ERROR is not None):
-                raise nose.SkipTest("S3 " + cls.__name__ + ": " +
+            raise cls.skipException("S3 " + cls.__name__ + ": " +
                                     tempest.tests.boto.S3_CAN_CONNECT_ERROR)
 
     @classmethod
diff --git a/tempest/tests/boto/__init__.py b/tempest/tests/boto/__init__.py
index 6d5149e..99dd8a9 100644
--- a/tempest/tests/boto/__init__.py
+++ b/tempest/tests/boto/__init__.py
@@ -26,6 +26,7 @@
 import tempest.clients
 from tempest.common.utils.file_utils import have_effective_read_access
 import tempest.config
+from testresources import TestResourceManager
 
 A_I_IMAGES_READY = False  # ari,ami,aki
 S3_CAN_CONNECT_ERROR = "Unknown Error"
@@ -96,3 +97,8 @@
     else:
         S3_CAN_CONNECT_ERROR = None
     boto_logger.setLevel(level)
+
+
+class BotoResource(TestResourceManager):
+    def make(self, dependency_resources=None):
+        return generic_setup_package()
diff --git a/tempest/tests/boto/test_ec2_instance_run.py b/tempest/tests/boto/test_ec2_instance_run.py
index 6a8778a..1adb5fb 100644
--- a/tempest/tests/boto/test_ec2_instance_run.py
+++ b/tempest/tests/boto/test_ec2_instance_run.py
@@ -20,9 +20,8 @@
 
 from boto.exception import EC2ResponseError
 from boto.s3.key import Key
-import nose
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -44,8 +43,8 @@
     def setUpClass(cls):
         super(InstanceRunTest, cls).setUpClass()
         if not tempest.tests.boto.A_I_IMAGES_READY:
-            raise nose.SkipTest("".join(("EC2 ", cls.__name__,
-                                ": requires ami/aki/ari manifest")))
+            raise cls.skipException("".join(("EC2 ", cls.__name__,
+                                    ": requires ami/aki/ari manifest")))
         cls.os = clients.Manager()
         cls.s3_client = cls.os.s3_client
         cls.ec2_client = cls.os.ec2api_client
@@ -122,7 +121,7 @@
         self.cancelResourceCleanUp(rcuk)
 
     @attr(type='smoke')
-    @unittest.skip("Skipped until the Bug #1098891 is resolved")
+    @testtools.skip("Skipped until the Bug #1098891 is resolved")
     def test_run_terminate_instance(self):
         # EC2 run, terminate immediately
         image_ami = self.ec2_client.get_image(self.images["ami"]
diff --git a/tempest/tests/boto/test_ec2_keys.py b/tempest/tests/boto/test_ec2_keys.py
index fcec02d..540374a 100644
--- a/tempest/tests/boto/test_ec2_keys.py
+++ b/tempest/tests/boto/test_ec2_keys.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -47,7 +47,7 @@
                         self.client.get_key_pair(key_name)))
 
     @attr(type='smoke')
-    @unittest.skip("Skipped until the Bug #1072318 is resolved")
+    @testtools.skip("Skipped until the Bug #1072318 is resolved")
     def test_delete_ec2_keypair(self):
         # EC2 delete KeyPair
         key_name = rand_name("keypair-")
@@ -65,7 +65,7 @@
                         self.client.get_key_pair(key_name)))
 
     @attr(type='smoke')
-    @unittest.skip("Skipped until the Bug #1072762 is resolved")
+    @testtools.skip("Skipped until the Bug #1072762 is resolved")
     def test_duplicate_ec2_keypair(self):
         # EC2 duplicate KeyPair
         key_name = rand_name("keypair-")
diff --git a/tempest/tests/boto/test_ec2_network.py b/tempest/tests/boto/test_ec2_network.py
index 27649e6..76103c2 100644
--- a/tempest/tests/boto/test_ec2_network.py
+++ b/tempest/tests/boto/test_ec2_network.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.testboto import BotoTestCase
@@ -32,7 +32,7 @@
         cls.client = cls.os.ec2api_client
 
 #Note(afazekas): these tests for things duable without an instance
-    @unittest.skip("Skipped until the Bug #1080406 is resolved")
+    @testtools.skip("Skipped until the Bug #1080406 is resolved")
     @attr(type='smoke')
     def test_disassociate_not_associated_floating_ip(self):
         # EC2 disassociate not associated floating ip
diff --git a/tempest/tests/boto/test_ec2_security_groups.py b/tempest/tests/boto/test_ec2_security_groups.py
index 09da82c..ed7bedb 100644
--- a/tempest/tests/boto/test_ec2_security_groups.py
+++ b/tempest/tests/boto/test_ec2_security_groups.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
diff --git a/tempest/tests/boto/test_ec2_volumes.py b/tempest/tests/boto/test_ec2_volumes.py
index ee7fa3f..7397cdb 100644
--- a/tempest/tests/boto/test_ec2_volumes.py
+++ b/tempest/tests/boto/test_ec2_volumes.py
@@ -19,7 +19,7 @@
 import time
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.testboto import BotoTestCase
diff --git a/tempest/tests/boto/test_s3_buckets.py b/tempest/tests/boto/test_s3_buckets.py
index beed28b..36aa319 100644
--- a/tempest/tests/boto/test_s3_buckets.py
+++ b/tempest/tests/boto/test_s3_buckets.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -33,7 +33,7 @@
         cls.client = cls.os.s3_client
         cls.config = cls.os.config
 
-    @unittest.skip("Skipped until the Bug #1076965 is resolved")
+    @testtools.skip("Skipped until the Bug #1076965 is resolved")
     @attr(type='smoke')
     def test_create_and_get_delete_bucket(self):
         # S3 Create, get and delete bucket
diff --git a/tempest/tests/boto/test_s3_ec2_images.py b/tempest/tests/boto/test_s3_ec2_images.py
index f14115a..e0dc124 100644
--- a/tempest/tests/boto/test_s3_ec2_images.py
+++ b/tempest/tests/boto/test_s3_ec2_images.py
@@ -19,9 +19,8 @@
 import os
 
 from boto.s3.key import Key
-import nose
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -38,8 +37,8 @@
     def setUpClass(cls):
         super(S3ImagesTest, cls).setUpClass()
         if not tempest.tests.boto.A_I_IMAGES_READY:
-            raise nose.SkipTest("".join(("EC2 ", cls.__name__,
-                                ": requires ami/aki/ari manifest")))
+            raise cls.skipException("".join(("EC2 ", cls.__name__,
+                                    ": requires ami/aki/ari manifest")))
         cls.os = clients.Manager()
         cls.s3_client = cls.os.s3_client
         cls.images_client = cls.os.ec2api_client
@@ -88,7 +87,7 @@
         #TODO(afazekas): double deregister ?
         self.cancelResourceCleanUp(image["cleanUp"])
 
-    @unittest.skip("Skipped until the Bug #1074904 is resolved")
+    @testtools.skip("Skipped until the Bug #1074904 is resolved")
     def test_register_get_deregister_aki_image(self):
         # Register and deregister aki image
         image = {"name": rand_name("aki-name-"),
@@ -116,7 +115,7 @@
         self.assertIn(retrieved_image.state, self.valid_image_state)
         self.cancelResourceCleanUp(image["cleanUp"])
 
-    @unittest.skip("Skipped until the Bug #1074908 and #1074904 is resolved")
+    @testtools.skip("Skipped until the Bug #1074908 and #1074904 is resolved")
     def test_register_get_deregister_ari_image(self):
         # Register and deregister ari image
         image = {"name": rand_name("ari-name-"),
diff --git a/tempest/tests/boto/test_s3_objects.py b/tempest/tests/boto/test_s3_objects.py
index 6e89539..cacd99f 100644
--- a/tempest/tests/boto/test_s3_objects.py
+++ b/tempest/tests/boto/test_s3_objects.py
@@ -19,7 +19,7 @@
 
 from boto.s3.key import Key
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -37,7 +37,7 @@
         cls.client = cls.os.s3_client
         cls.config = cls.os.config
 
-    @unittest.skip("Skipped until the Bug #1076534 is resolved")
+    @testtools.skip("Skipped until the Bug #1076534 is resolved")
     @attr(type='smoke')
     def test_create_get_delete_object(self):
         # S3 Create, get and delete object
diff --git a/tempest/tests/boto/utils/wait.py b/tempest/tests/boto/utils/wait.py
index 77fe037..c2d4ea3 100644
--- a/tempest/tests/boto/utils/wait.py
+++ b/tempest/tests/boto/utils/wait.py
@@ -20,7 +20,7 @@
 import time
 
 from boto.exception import BotoServerError
-from unittest2 import TestCase
+from testtools import TestCase
 
 import tempest.config
 
diff --git a/tempest/tests/compute/__init__.py b/tempest/tests/compute/__init__.py
index a00ec77..08e5091 100644
--- a/tempest/tests/compute/__init__.py
+++ b/tempest/tests/compute/__init__.py
@@ -17,11 +17,11 @@
 
 import logging
 
-import nose
 
 from tempest import clients
 from tempest import config
 from tempest.exceptions import InvalidConfiguration
+from testresources import TestResourceManager
 
 LOG = logging.getLogger(__name__)
 
@@ -69,14 +69,19 @@
     if CONFIG.compute.allow_tenant_isolation:
         MULTI_USER = True
     else:
-        user1 = CONFIG.compute.username
-        user2 = CONFIG.compute.alt_username
+        user1 = CONFIG.identity.username
+        user2 = CONFIG.identity.alt_username
         if user2 and user1 != user2:
-            user2_password = CONFIG.compute.alt_password
-            user2_tenant_name = CONFIG.compute.alt_tenant_name
+            user2_password = CONFIG.identity.alt_password
+            user2_tenant_name = CONFIG.identity.alt_tenant_name
             if not user2_password or not user2_tenant_name:
                 msg = ("Alternate user specified but not alternate "
                        "tenant or password: alt_tenant_name=%s alt_password=%s"
                        % (user2_tenant_name, user2_password))
                 raise InvalidConfiguration(msg)
             MULTI_USER = True
+
+
+class ComputeResource(TestResourceManager):
+    def make(self, dependency_resources=None):
+        return generic_setup_package()
diff --git a/tempest/tests/compute/admin/test_flavors.py b/tempest/tests/compute/admin/test_flavors.py
index 4859308..eb2392c 100644
--- a/tempest/tests/compute/admin/test_flavors.py
+++ b/tempest/tests/compute/admin/test_flavors.py
@@ -15,9 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.data_utils import rand_int_id
 from tempest.common.utils.data_utils import rand_name
@@ -35,7 +34,7 @@
     def setUpClass(self, cls):
         if not compute.FLAVOR_EXTRA_DATA_ENABLED:
             msg = "FlavorExtraData extension not enabled."
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
         cls.client = cls.os.flavors_client
         cls.flavor_name_prefix = 'test_flavor_'
diff --git a/tempest/tests/compute/admin/test_quotas.py b/tempest/tests/compute/admin/test_quotas.py
index eaf245a..6a7a5ea 100644
--- a/tempest/tests/compute/admin/test_quotas.py
+++ b/tempest/tests/compute/admin/test_quotas.py
@@ -27,14 +27,14 @@
     @classmethod
     def setUpClass(cls):
         super(QuotasTest, cls).setUpClass()
-        adm_user = cls.config.compute_admin.username
-        adm_pass = cls.config.compute_admin.password
-        adm_tenant = cls.config.compute_admin.tenant_name
+        c_adm_user = cls.config.compute_admin.username
+        c_adm_pass = cls.config.compute_admin.password
+        c_adm_tenant = cls.config.compute_admin.tenant_name
         auth_url = cls.config.identity.uri
 
-        cls.adm_client = adm_quotas.AdminQuotasClient(cls.config, adm_user,
-                                                      adm_pass, auth_url,
-                                                      adm_tenant)
+        cls.adm_client = adm_quotas.AdminQuotasClient(cls.config, c_adm_user,
+                                                      c_adm_pass, auth_url,
+                                                      c_adm_tenant)
         cls.client = cls.os.quotas_client
         cls.identity_admin_client = cls._get_identity_admin_client()
         resp, tenants = cls.identity_admin_client.list_tenants()
@@ -43,7 +43,7 @@
             cls.demo_tenant_id = cls.isolated_creds[0][0]['tenantId']
         else:
             cls.demo_tenant_id = [tnt['id'] for tnt in tenants if tnt['name']
-                                  == cls.config.compute.tenant_name][0]
+                                  == cls.config.identity.tenant_name][0]
 
         cls.adm_tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
                              cls.config.compute_admin.tenant_name][0]
@@ -57,12 +57,13 @@
                                  'cores': 20, 'security_groups': 10}
 
     @classmethod
-    def tearDown(cls):
+    def tearDownClass(cls):
         for server in cls.servers:
             try:
                 cls.servers_client.delete_server(server['id'])
             except exceptions.NotFound:
                 continue
+        super(QuotasTest, cls).tearDownClass()
 
     @attr(type='smoke')
     def test_get_default_quotas(self):
diff --git a/tempest/tests/compute/base.py b/tempest/tests/compute/base.py
index 3f3b3e8..2312931 100644
--- a/tempest/tests/compute/base.py
+++ b/tempest/tests/compute/base.py
@@ -18,9 +18,8 @@
 import logging
 import time
 
-import nose
 import testresources
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -34,12 +33,11 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseCompTest(unittest.TestCase,
+class BaseCompTest(testtools.TestCase,
                    testresources.ResourcedTestCase):
-
     """Base test case class for all Compute API tests."""
 
-    resources = [('compute_init', compute.generic_setup_package())]
+    resources = [('compute_init', compute.ComputeResource())]
 
     @classmethod
     def setUpClass(cls):
@@ -92,8 +90,8 @@
 
         return (
             cls.config,
-            cls.config.compute_admin.username,
-            cls.config.compute_admin.password,
+            cls.config.identity.admin_username,
+            cls.config.identity.admin_password,
             cls.config.identity.uri
         )
 
@@ -249,23 +247,23 @@
         super(BaseComputeTestXML, cls).setUpClass()
 
 
-class BaseComputeAdminTest(unittest.TestCase):
+class BaseComputeAdminTest(testtools.TestCase):
 
     """Base test case class for all Compute Admin API tests."""
 
     @classmethod
     def setUpClass(cls):
         cls.config = config.TempestConfig()
-        cls.admin_username = cls.config.compute_admin.username
-        cls.admin_password = cls.config.compute_admin.password
-        cls.admin_tenant = cls.config.compute_admin.tenant_name
+        cls.admin_username = cls.config.identity.admin_username
+        cls.admin_password = cls.config.identity.admin_password
+        cls.admin_tenant = cls.config.identity.admin_tenant_name
 
         if not cls.admin_username and cls.admin_password and cls.admin_tenant:
             msg = ("Missing Compute Admin API credentials "
                    "in configuration.")
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
-        cls.os = clients.AdminManager(interface=cls._interface)
+        cls.os = clients.ComputeAdminManager(interface=cls._interface)
 
 
 class BaseComputeAdminTestJSON(BaseComputeAdminTest):
diff --git a/tempest/tests/compute/floating_ips/test_floating_ips_actions.py b/tempest/tests/compute/floating_ips/test_floating_ips_actions.py
index 9a9914a..59faf66 100644
--- a/tempest/tests/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/tests/compute/floating_ips/test_floating_ips_actions.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
diff --git a/tempest/tests/compute/floating_ips/test_list_floating_ips.py b/tempest/tests/compute/floating_ips/test_list_floating_ips.py
index 9eec27c..ea99e89 100644
--- a/tempest/tests/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/tests/compute/floating_ips/test_list_floating_ips.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
diff --git a/tempest/tests/compute/images/test_image_metadata.py b/tempest/tests/compute/images/test_image_metadata.py
index cdf4249..94bdca7 100644
--- a/tempest/tests/compute/images/test_image_metadata.py
+++ b/tempest/tests/compute/images/test_image_metadata.py
@@ -53,6 +53,7 @@
         super(ImagesMetadataTest, cls).tearDownClass()
 
     def setUp(self):
+        super(ImagesMetadataTest, self).setUp()
         meta = {'key1': 'value1', 'key2': 'value2'}
         resp, _ = self.client.set_image_metadata(self.image_id, meta)
         self.assertEqual(resp.status, 200)
diff --git a/tempest/tests/compute/images/test_images.py b/tempest/tests/compute/images/test_images.py
index 2557f16..1fc03b8 100644
--- a/tempest/tests/compute/images/test_images.py
+++ b/tempest/tests/compute/images/test_images.py
@@ -15,9 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import parse_image_id
@@ -113,7 +112,7 @@
         self.assertRaises(exceptions.Duplicate, self.client.create_image,
                           server['id'], snapshot_name)
 
-    @unittest.skip("Until Bug 1039739 is fixed")
+    @testtools.skip("Until Bug 1039739 is fixed")
     @attr(type='negative')
     def test_create_image_when_server_is_rebooting(self):
         # Return error when creating an image of server that is rebooting
@@ -217,6 +216,7 @@
                      ImagesTestBase):
     def tearDown(self):
         ImagesTestBase.tearDown(self)
+        base.BaseComputeTestJSON.tearDown(self)
 
     @classmethod
     def setUpClass(cls):
@@ -243,6 +243,7 @@
                     ImagesTestBase):
     def tearDown(self):
         ImagesTestBase.tearDown(self)
+        base.BaseComputeTestXML.tearDown(self)
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/tests/compute/images/test_images_oneserver.py b/tempest/tests/compute/images/test_images_oneserver.py
index f8b560b..f3b1e01 100644
--- a/tempest/tests/compute/images/test_images_oneserver.py
+++ b/tempest/tests/compute/images/test_images_oneserver.py
@@ -15,9 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import parse_image_id
@@ -43,7 +42,7 @@
             self.image_ids.remove(image_id)
 
     @attr(type='negative')
-    @unittest.skip("Until Bug 1006725 is fixed")
+    @testtools.skip("Until Bug 1006725 is fixed")
     def test_create_image_specify_multibyte_character_image_name(self):
         # Return an error if the image name has multi-byte characters
         try:
@@ -56,7 +55,7 @@
                       " are used for image name")
 
     @attr(type='negative')
-    @unittest.skip("Until Bug 1005423 is fixed")
+    @testtools.skip("Until Bug 1005423 is fixed")
     def test_create_image_specify_invalid_metadata(self):
         # Return an error when creating image with invalid metadata
         try:
@@ -69,7 +68,7 @@
             self.fail("Should raise 400 Bad Request if meta data is invalid")
 
     @attr(type='negative')
-    @unittest.skip("Until Bug 1005423 is fixed")
+    @testtools.skip("Until Bug 1005423 is fixed")
     def test_create_image_specify_metadata_over_limits(self):
         # Return an error when creating image with meta data over 256 chars
         try:
@@ -82,8 +81,8 @@
             self.fail("Should raise 413 Over Limit if meta data was too long")
 
     @attr(type='negative')
-    @unittest.skipUnless(compute.MULTI_USER,
-                         'Need multiple users for this test.')
+    @testtools.skipUnless(compute.MULTI_USER,
+                          'Need multiple users for this test.')
     def test_delete_image_of_another_tenant(self):
         # Return an error while trying to delete another tenant's image
         self.servers_client.wait_for_server_status(self.server['id'], 'ACTIVE')
@@ -99,8 +98,8 @@
                           self.alt_client.delete_image, image_id)
 
     @attr(type='smoke')
-    @unittest.skipUnless(compute.CREATE_IMAGE_ENABLED,
-                         'Environment unable to create images.')
+    @testtools.skipUnless(compute.CREATE_IMAGE_ENABLED,
+                          'Environment unable to create images.')
     def test_create_delete_image(self):
 
         # Create a new image
@@ -123,8 +122,8 @@
         self.assertEqual(original_image['minDisk'], image['minDisk'])
 
     @attr(type='negative')
-    @unittest.skipUnless(compute.MULTI_USER,
-                         'Need multiple users for this test.')
+    @testtools.skipUnless(compute.MULTI_USER,
+                          'Need multiple users for this test.')
     def test_create_image_for_server_in_another_tenant(self):
         # Creating image of another tenant's server should be return error
 
@@ -157,7 +156,7 @@
                       "of the server is still being saved")
 
     @attr(type='negative')
-    @unittest.skip("Until Bug 1004564 is fixed")
+    @testtools.skip("Until Bug 1004564 is fixed")
     def test_create_image_specify_name_over_256_chars(self):
         # Return an error if snapshot name over 256 characters is passed
 
@@ -192,6 +191,7 @@
 
     def tearDown(self):
         ImagesOneServerTestBase.tearDown(self)
+        base.BaseComputeTestJSON.tearDown(self)
 
     @classmethod
     def setUpClass(cls):
@@ -220,6 +220,7 @@
 
     def tearDown(self):
         ImagesOneServerTestBase.tearDown(self)
+        base.BaseComputeTestXML.tearDown(self)
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/tests/compute/keypairs/test_keypairs.py b/tempest/tests/compute/keypairs/test_keypairs.py
index 7d95a9b..45c9079 100644
--- a/tempest/tests/compute/keypairs/test_keypairs.py
+++ b/tempest/tests/compute/keypairs/test_keypairs.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
@@ -77,7 +77,7 @@
         self.assertEqual(202, resp.status)
 
     @attr(type='positive')
-    @unittest.skip("Skipped until the Bug #980688 is resolved")
+    @testtools.skip("Skipped until the Bug #980688 is resolved")
     def test_get_keypair_detail(self):
         # Keypair should be created, Got details by name and deleted
         k_name = rand_name('keypair-')
@@ -137,7 +137,7 @@
             self.fail('Expected BadRequest for invalid public key')
 
     @attr(type='negative')
-    @unittest.skip("Skipped until the Bug #1086980 is resolved")
+    @testtools.skip("Skipped until the Bug #1086980 is resolved")
     def test_keypair_delete_nonexistant_key(self):
         # Non-existant key deletion should throw a proper error
         k_name = rand_name("keypair-non-existant-")
diff --git a/tempest/tests/compute/limits/test_absolute_limits.py b/tempest/tests/compute/limits/test_absolute_limits.py
index 89c5b25..d520b92 100644
--- a/tempest/tests/compute/limits/test_absolute_limits.py
+++ b/tempest/tests/compute/limits/test_absolute_limits.py
@@ -15,7 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import unittest2 as unittest
+import testtools
 
 from tempest.tests.compute import base
 
@@ -26,7 +26,7 @@
     def setUpClass(cls):
         cls.client = cls.limits_client
 
-    @unittest.skip("Skipped until the Bug #1025294 is resolved")
+    @testtools.skip("Skipped until the Bug #1025294 is resolved")
     def test_absLimits_get(self):
         # To check if all limits are present in the response
         resp, absolute_limits = self.client.get_absolute_limits()
diff --git a/tempest/tests/compute/servers/test_console_output.py b/tempest/tests/compute/servers/test_console_output.py
index 3ad29a1..b26220b 100644
--- a/tempest/tests/compute/servers/test_console_output.py
+++ b/tempest/tests/compute/servers/test_console_output.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
@@ -63,7 +63,7 @@
             pass
 
     @attr(type='positive')
-    @unittest.skip('Until tempest bug 1014683 is fixed.')
+    @testtools.skip('Until tempest bug 1014683 is fixed.')
     def test_get_console_output_server_id_in_reboot_status(self):
         # Positive test:Should be able to GET the console output
         # for a given server_id in reboot status
diff --git a/tempest/tests/compute/servers/test_create_server.py b/tempest/tests/compute/servers/test_create_server.py
index c5a54dc..0dcc79f 100644
--- a/tempest/tests/compute/servers/test_create_server.py
+++ b/tempest/tests/compute/servers/test_create_server.py
@@ -16,10 +16,9 @@
 #    under the License.
 
 import base64
-import nose
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 
 from tempest.common.utils.data_utils import rand_name
@@ -98,14 +97,14 @@
         self.assertTrue(found)
 
     @attr(type='positive')
-    @unittest.skipIf(not run_ssh, 'Instance validation tests are disabled.')
+    @testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
     def test_can_log_into_created_server(self):
         # Check that the user can authenticate with the generated password
         linux_client = RemoteClient(self.server, self.ssh_user, self.password)
         self.assertTrue(linux_client.can_authenticate())
 
     @attr(type='positive')
-    @unittest.skipIf(not run_ssh, 'Instance validation tests are disabled.')
+    @testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
     def test_verify_created_server_vcpus(self):
         # Verify that the number of vcpus reported by the instance matches
         # the amount stated by the flavor
@@ -114,7 +113,7 @@
         self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
 
     @attr(type='positive')
-    @unittest.skipIf(not run_ssh, 'Instance validation tests are disabled.')
+    @testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
     def test_host_name_is_same_as_server_name(self):
         # Verify the instance host name is the same as the server name
         linux_client = RemoteClient(self.server, self.ssh_user, self.password)
@@ -128,7 +127,7 @@
     def setUpClass(cls):
         if not compute.DISK_CONFIG_ENABLED:
             msg = "DiskConfig extension not enabled."
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
         super(ServersTestAutoDisk, cls).setUpClass()
         cls.disk_config = 'AUTO'
         ServersTest.setUpClass(cls)
@@ -146,7 +145,7 @@
     def setUpClass(cls):
         if not compute.DISK_CONFIG_ENABLED:
             msg = "DiskConfig extension not enabled."
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
         super(ServersTestManualDisk, cls).setUpClass()
         cls.disk_config = 'MANUAL'
         ServersTest.setUpClass(cls)
diff --git a/tempest/tests/compute/servers/test_disk_config.py b/tempest/tests/compute/servers/test_disk_config.py
index 490156b..c3a37ff 100644
--- a/tempest/tests/compute/servers/test_disk_config.py
+++ b/tempest/tests/compute/servers/test_disk_config.py
@@ -15,9 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
@@ -31,7 +30,7 @@
     def setUpClass(cls):
         if not compute.DISK_CONFIG_ENABLED:
             msg = "DiskConfig extension not enabled."
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
         super(TestServerDiskConfig, cls).setUpClass()
         cls.client = cls.os.servers_client
 
@@ -96,7 +95,7 @@
         resp, body = self.client.delete_server(server['id'])
 
     @attr(type='positive')
-    @unittest.skipUnless(compute.RESIZE_AVAILABLE, 'Resize not available.')
+    @testtools.skipUnless(compute.RESIZE_AVAILABLE, 'Resize not available.')
     def test_resize_server_from_manual_to_auto(self):
         # A server should be resized from manual to auto disk config
         name = rand_name('server')
@@ -122,7 +121,7 @@
         resp, body = self.client.delete_server(server['id'])
 
     @attr(type='positive')
-    @unittest.skipUnless(compute.RESIZE_AVAILABLE, 'Resize not available.')
+    @testtools.skipUnless(compute.RESIZE_AVAILABLE, 'Resize not available.')
     def test_resize_server_from_auto_to_manual(self):
         # A server should be resized from auto to manual disk config
         name = rand_name('server')
diff --git a/tempest/tests/compute/servers/test_list_server_filters.py b/tempest/tests/compute/servers/test_list_server_filters.py
index d943e5d..45ea3a0 100644
--- a/tempest/tests/compute/servers/test_list_server_filters.py
+++ b/tempest/tests/compute/servers/test_list_server_filters.py
@@ -16,10 +16,8 @@
 #    under the License.
 
 
-import nose
 from nose.plugins.attrib import attr
-import nose.plugins.skip
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
diff --git a/tempest/tests/compute/servers/test_list_servers_negative.py b/tempest/tests/compute/servers/test_list_servers_negative.py
index 035ffe8..eb4ea02 100644
--- a/tempest/tests/compute/servers/test_list_servers_negative.py
+++ b/tempest/tests/compute/servers/test_list_servers_negative.py
@@ -18,8 +18,7 @@
 import re
 import sys
 
-import nose
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -64,7 +63,7 @@
             tenant_name = cls.os.tenant_name
             msg = ("User/tenant %(username)s/%(tenant_name)s already have "
                    "existing server instances. Skipping test.") % locals()
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
         resp, body = cls.alt_client.list_servers()
         servers = body['servers']
@@ -74,7 +73,7 @@
             tenant_name = cls.alt_manager.tenant_name
             msg = ("Alt User/tenant %(username)s/%(tenant_name)s already have "
                    "existing server instances. Skipping test.") % locals()
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
         # The following servers are created for use
         # by the test methods in this class. These
diff --git a/tempest/tests/compute/servers/test_server_actions.py b/tempest/tests/compute/servers/test_server_actions.py
index 2fe8464..fd35461 100644
--- a/tempest/tests/compute/servers/test_server_actions.py
+++ b/tempest/tests/compute/servers/test_server_actions.py
@@ -19,7 +19,7 @@
 import time
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.data_utils import rand_name
 from tempest.common.utils.linux.remote_client import RemoteClient
@@ -35,8 +35,8 @@
     run_ssh = tempest.config.TempestConfig().compute.run_ssh
 
     @attr(type='smoke')
-    @unittest.skipUnless(compute.CHANGE_PASSWORD_AVAILABLE,
-                         'Change password not available.')
+    @testtools.skipUnless(compute.CHANGE_PASSWORD_AVAILABLE,
+                          'Change password not available.')
     def test_change_server_password(self):
         # The server's password should be set to the provided password
         new_password = 'Newpass1234'
@@ -70,7 +70,7 @@
             self.assertGreater(new_boot_time, boot_time)
 
     @attr(type='smoke')
-    @unittest.skip('Until bug 1014647 is dealt with.')
+    @testtools.skip('Until bug 1014647 is dealt with.')
     def test_reboot_server_soft(self):
         # The server should be signaled to reboot gracefully
         if self.run_ssh:
@@ -123,7 +123,7 @@
             self.assertTrue(linux_client.can_authenticate())
 
     @attr(type='smoke')
-    @unittest.skipIf(not resize_available, 'Resize not available.')
+    @testtools.skipIf(not resize_available, 'Resize not available.')
     def test_resize_server_confirm(self):
         # The server's RAM and disk space should be modified to that of
         # the provided flavor
@@ -139,7 +139,7 @@
         self.assertEqual(self.flavor_ref_alt, server['flavor']['id'])
 
     @attr(type='positive')
-    @unittest.skipIf(not resize_available, 'Resize not available.')
+    @testtools.skipIf(not resize_available, 'Resize not available.')
     def test_resize_server_revert(self):
         # The server's RAM and disk space should return to its original
         # values after a resize is reverted
diff --git a/tempest/tests/compute/servers/test_server_advanced_ops.py b/tempest/tests/compute/servers/test_server_advanced_ops.py
index 4e85b04..f949f2e 100644
--- a/tempest/tests/compute/servers/test_server_advanced_ops.py
+++ b/tempest/tests/compute/servers/test_server_advanced_ops.py
@@ -17,7 +17,6 @@
 
 import logging
 
-import nose
 
 from tempest.common.utils.data_utils import rand_name
 from tempest import test
@@ -39,13 +38,13 @@
 
         if not cls.config.compute.resize_available:
             msg = "Skipping test - resize not available on this host"
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
         resize_flavor = cls.config.compute.flavor_ref_alt
 
         if resize_flavor == cls.config.compute.flavor_ref:
             msg = "Skipping test - flavor_ref and flavor_ref_alt are identical"
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
     @classmethod
     def tearDownClass(cls):
diff --git a/tempest/tests/compute/servers/test_server_metadata.py b/tempest/tests/compute/servers/test_server_metadata.py
index 6c44c3c..7db963e 100644
--- a/tempest/tests/compute/servers/test_server_metadata.py
+++ b/tempest/tests/compute/servers/test_server_metadata.py
@@ -44,6 +44,7 @@
         super(ServerMetadataTest, cls).tearDownClass()
 
     def setUp(self):
+        super(ServerMetadataTest, self).setUp()
         meta = {'key1': 'value1', 'key2': 'value2'}
         resp, _ = self.client.set_server_metadata(self.server_id, meta)
         self.assertEqual(resp.status, 200)
diff --git a/tempest/tests/compute/servers/test_servers.py b/tempest/tests/compute/servers/test_servers.py
index 8054c1f..e0d4d44 100644
--- a/tempest/tests/compute/servers/test_servers.py
+++ b/tempest/tests/compute/servers/test_servers.py
@@ -168,7 +168,6 @@
         # deletes are running slow we could very well overrun system
         # memory
         self.clear_servers()
-
         super(ServersTestJSON, self).tearDown()
 
 
@@ -184,5 +183,4 @@
         # 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 f7624b3..ea63360 100644
--- a/tempest/tests/compute/servers/test_servers_negative.py
+++ b/tempest/tests/compute/servers/test_servers_negative.py
@@ -17,9 +17,8 @@
 
 import sys
 
-import nose
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -31,7 +30,7 @@
 
     @classmethod
     def setUpClass(cls):
-        raise nose.SkipTest("Until Bug 1046870 is fixed")
+        raise cls.skipException("Until Bug 1046870 is fixed")
         super(ServersNegativeTest, cls).setUpClass()
         cls.client = cls.servers_client
         cls.img_client = cls.images_client
diff --git a/tempest/tests/compute/servers/test_servers_whitebox.py b/tempest/tests/compute/servers/test_servers_whitebox.py
index 33519b0..502f16b 100644
--- a/tempest/tests/compute/servers/test_servers_whitebox.py
+++ b/tempest/tests/compute/servers/test_servers_whitebox.py
@@ -15,7 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
 from nose.plugins.attrib import attr
 
 from tempest import exceptions
@@ -28,7 +27,7 @@
 
     @classmethod
     def setUpClass(cls):
-        raise nose.SkipTest("Until Bug 1034129 is fixed")
+        raise cls.skipException("Until Bug 1034129 is fixed")
         super(ServersWhiteboxTest, cls).setUpClass()
         BaseIdentityAdminTest.setUpClass()
         cls.client = cls.servers_client
diff --git a/tempest/tests/compute/test_authorization.py b/tempest/tests/compute/test_authorization.py
index 78661d1..4d3b553 100644
--- a/tempest/tests/compute/test_authorization.py
+++ b/tempest/tests/compute/test_authorization.py
@@ -16,9 +16,8 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-from nose import SkipTest
 from nose.tools import raises
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import parse_image_id
@@ -34,7 +33,7 @@
     def setUpClass(cls):
         if not compute.MULTI_USER:
             msg = "Need >1 user"
-            raise SkipTest(msg)
+            raise cls.skipException(msg)
 
         super(AuthorizationTest, cls).setUpClass()
 
@@ -225,7 +224,7 @@
 
     @raises(exceptions.NotFound)
     @attr(type='negative')
-    @unittest.skip("Skipped until the Bug #1086980 is resolved")
+    @testtools.skip("Skipped until the Bug #1086980 is resolved")
     def test_delete_keypair_of_alt_account_fails(self):
         # A DELETE request for another user's keypair should fail
         self.alt_keypairs_client.delete_keypair(self.keypairname)
diff --git a/tempest/tests/compute/test_live_block_migration.py b/tempest/tests/compute/test_live_block_migration.py
index eceaaba..1b651ab 100644
--- a/tempest/tests/compute/test_live_block_migration.py
+++ b/tempest/tests/compute/test_live_block_migration.py
@@ -18,9 +18,8 @@
 import random
 import string
 
-import nose
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.linux.remote_client import RemoteClient
 from tempest import config
@@ -101,12 +100,12 @@
             return server_id
 
     @attr(type='positive')
-    @unittest.skipIf(not live_migration_available,
-                     'Block Live migration not available')
+    @testtools.skipIf(not live_migration_available,
+                      'Block Live migration not available')
     def test_001_live_block_migration(self):
         # Live block migrate an instance to another host
         if len(self._get_compute_hostnames()) < 2:
-            raise nose.SkipTest(
+            raise self.skipTest(
                 "Less than 2 compute nodes, skipping migration test.")
         server_id = self._get_an_active_server()
         actual_host = self._get_host_for_server(server_id)
@@ -116,9 +115,9 @@
         self.assertEquals(target_host, self._get_host_for_server(server_id))
 
     @attr(type='positive', bug='lp1051881')
-    @unittest.skip('Until bug 1051881 is dealt with.')
-    @unittest.skipIf(not live_migration_available,
-                     'Block Live migration not available')
+    @testtools.skip('Until bug 1051881 is dealt with.')
+    @testtools.skipIf(not live_migration_available,
+                      'Block Live migration not available')
     def test_002_invalid_host_for_migration(self):
         # Migrating to an invalid host should not change the status
 
diff --git a/tempest/tests/compute/volumes/test_attach_volume.py b/tempest/tests/compute/volumes/test_attach_volume.py
index 9581026..0e0e4a5 100644
--- a/tempest/tests/compute/volumes/test_attach_volume.py
+++ b/tempest/tests/compute/volumes/test_attach_volume.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -68,7 +68,7 @@
         return server, volume
 
     @attr(type='positive')
-    @unittest.skipIf(not run_ssh, 'SSH required for this test')
+    @testtools.skipIf(not run_ssh, 'SSH required for this test')
     def test_attach_detach_volume(self):
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
diff --git a/tempest/tests/compute/volumes/test_volumes_list.py b/tempest/tests/compute/volumes/test_volumes_list.py
index fef9c8d..cc690a5 100644
--- a/tempest/tests/compute/volumes/test_volumes_list.py
+++ b/tempest/tests/compute/volumes/test_volumes_list.py
@@ -15,7 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
 
 from tempest.common.utils.data_utils import rand_name
 from tempest.tests.compute import base
@@ -96,7 +95,7 @@
                            "test. This typically means that the backing file "
                            "size of the nova-volumes group is too small to "
                            "create the 3 volumes needed by this test case")
-                    raise nose.SkipTest(msg)
+                    raise cls.skipException(msg)
                 raise
 
     @classmethod
@@ -142,7 +141,7 @@
                            "test. This typically means that the backing file "
                            "size of the nova-volumes group is too small to "
                            "create the 3 volumes needed by this test case")
-                    raise nose.SkipTest(msg)
+                    raise cls.skipException(msg)
                 raise
 
     @classmethod
diff --git a/tempest/tests/identity/admin/test_roles.py b/tempest/tests/identity/admin/test_roles.py
index f0dd8d9..2779b51 100644
--- a/tempest/tests/identity/admin/test_roles.py
+++ b/tempest/tests/identity/admin/test_roles.py
@@ -15,7 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import unittest2 as unittest
+import testtools
 
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
diff --git a/tempest/tests/identity/admin/test_services.py b/tempest/tests/identity/admin/test_services.py
index 30dfeb0..5261b9d 100644
--- a/tempest/tests/identity/admin/test_services.py
+++ b/tempest/tests/identity/admin/test_services.py
@@ -15,7 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
 
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
@@ -76,4 +75,4 @@
     @classmethod
     def setUpClass(cls):
         super(ServicesTestXML, cls).setUpClass()
-        raise nose.SkipTest("Skipping until Bug #1061738 resolved")
+        raise cls.skipException("Skipping until Bug #1061738 resolved")
diff --git a/tempest/tests/identity/admin/test_tenants.py b/tempest/tests/identity/admin/test_tenants.py
index 578af4a..54383f1 100644
--- a/tempest/tests/identity/admin/test_tenants.py
+++ b/tempest/tests/identity/admin/test_tenants.py
@@ -15,7 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import unittest2 as unittest
+import testtools
 
 from nose.plugins.attrib import attr
 from tempest.common.utils.data_utils import rand_name
diff --git a/tempest/tests/identity/admin/test_users.py b/tempest/tests/identity/admin/test_users.py
index 7ad932b..ef7d934 100644
--- a/tempest/tests/identity/admin/test_users.py
+++ b/tempest/tests/identity/admin/test_users.py
@@ -16,11 +16,11 @@
 #    under the License.
 
 from nose.plugins.attrib import attr
-import unittest2 as unittest
-
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 from tempest.tests.identity import base
+import testtools
+from testtools.matchers._basic import Contains
 
 
 class UsersTestBase(object):
@@ -76,7 +76,7 @@
                           self.data.tenant['id'], self.data.test_email)
 
     @attr(type='negative')
-    @unittest.skip("Until Bug 999084 is fixed")
+    @testtools.skip("Until Bug 999084 is fixed")
     def test_create_user_with_empty_password(self):
         # User with an empty password should not be created
         self.data.setup_test_tenant()
@@ -85,7 +85,7 @@
                           self.alt_email)
 
     @attr(type='nagative')
-    @unittest.skip("Until Bug 999084 is fixed")
+    @testtools.skip("Until Bug 999084 is fixed")
     def test_create_user_with_long_password(self):
         # User having password exceeding max length should not be created
         self.data.setup_test_tenant()
@@ -94,7 +94,7 @@
                           self.alt_email)
 
     @attr(type='negative')
-    @unittest.skip("Until Bug 999084 is fixed")
+    @testtools.skip("Until Bug 999084 is fixed")
     def test_create_user_with_invalid_email_format(self):
         # Email format should be validated while creating a user
         self.data.setup_test_tenant()
@@ -227,8 +227,9 @@
         # Get a list of users and find the test user
         self.data.setup_test_user()
         resp, users = self.client.get_users()
-        self.assertIn(self.data.test_user, [u['name'] for u in users],
-                      "Could not find %s" % self.data.test_user)
+        self.assertThat([u['name'] for u in users],
+                        Contains(self.data.test_user),
+                        "Could not find %s" % self.data.test_user)
 
     @attr(type='negative')
     def test_get_users_by_unauthorized_user(self):
diff --git a/tempest/tests/identity/base.py b/tempest/tests/identity/base.py
index 125e46c..cbd943e 100644
--- a/tempest/tests/identity/base.py
+++ b/tempest/tests/identity/base.py
@@ -15,14 +15,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
 
 
-class BaseIdAdminTest(unittest.TestCase):
+class BaseIdAdminTest(testtools.TestCase):
 
     @classmethod
     def setUpClass(cls):
@@ -31,11 +30,11 @@
         cls.token_client = os.token_client
 
         if not cls.client.has_admin_extensions():
-            raise nose.SkipTest("Admin extensions disabled")
+            raise cls.skipException("Admin extensions disabled")
 
         cls.data = DataGenerator(cls.client)
 
-        os = clients.NonAdminManager(interface=cls._interface)
+        os = clients.Manager(interface=cls._interface)
         cls.non_admin_client = os.identity_client
 
     @classmethod
diff --git a/tempest/tests/image/test_images.py b/tempest/tests/image/test_images.py
index 2429a32..0a1a25f 100644
--- a/tempest/tests/image/test_images.py
+++ b/tempest/tests/image/test_images.py
@@ -18,10 +18,10 @@
 import cStringIO as StringIO
 import random
 
-import unittest2 as unittest
+import testtools
 
 from nose.plugins.attrib import attr
-from nose.plugins.skip import SkipTest
+
 
 GLANCE_INSTALLED = False
 try:
@@ -33,7 +33,7 @@
 from tempest import clients
 
 
-class CreateRegisterImagesTest(unittest.TestCase):
+class CreateRegisterImagesTest(testtools.TestCase):
 
     """
     Here we test the registration and creation of images
@@ -42,7 +42,7 @@
     @classmethod
     def setUpClass(cls):
         if not GLANCE_INSTALLED:
-            raise SkipTest('Glance not installed')
+            raise cls.skipException('Glance not installed')
         cls.os = clients.ServiceManager()
         cls.client = cls.os.images.get_client()
         cls.created_images = []
@@ -128,7 +128,7 @@
         self.assertEqual('active', results.status)
 
 
-class ListImagesTest(unittest.TestCase):
+class ListImagesTest(testtools.TestCase):
 
     """
     Here we test the listing of image information
@@ -137,7 +137,7 @@
     @classmethod
     def setUpClass(cls):
         if not GLANCE_INSTALLED:
-            raise SkipTest('Glance not installed')
+            raise cls.skipException('Glance not installed')
         cls.os = clients.ServiceManager()
         cls.client = cls.os.images.get_client()
         cls.created_images = []
diff --git a/tempest/tests/network/base.py b/tempest/tests/network/base.py
index 90b351d..01330cc 100644
--- a/tempest/tests/network/base.py
+++ b/tempest/tests/network/base.py
@@ -15,15 +15,14 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 
 
-class BaseNetworkTest(unittest.TestCase):
+class BaseNetworkTest(testtools.TestCase):
 
     @classmethod
     def setUpClass(cls):
@@ -40,7 +39,7 @@
         except exceptions.EndpointNotFound:
             enabled = False
             skip_msg = "No OpenStack Network API endpoint"
-            raise nose.SkipTest(skip_msg)
+            raise cls.skipException(skip_msg)
 
     @classmethod
     def tearDownClass(cls):
diff --git a/tempest/tests/network/test_network_basic_ops.py b/tempest/tests/network/test_network_basic_ops.py
index 3c99f77..bdebced 100644
--- a/tempest/tests/network/test_network_basic_ops.py
+++ b/tempest/tests/network/test_network_basic_ops.py
@@ -19,7 +19,6 @@
 import subprocess
 
 import netaddr
-import nose
 
 from quantumclient.common import exceptions as exc
 
@@ -179,7 +178,7 @@
 
         cls.enabled = not bool(msg)
         if msg:
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
     @classmethod
     def setUpClass(cls):
@@ -458,7 +457,7 @@
 
     def test_005_create_servers(self):
         if not (self.keypairs or self.security_groups or self.networks):
-            raise nose.SkipTest('Necessary resources have not been defined')
+            raise self.skipTest('Necessary resources have not been defined')
         for i, network in enumerate(self.networks):
             tenant_id = network.tenant_id
             name = rand_name('server-smoke-%d-' % i)
@@ -471,9 +470,9 @@
     def test_006_check_tenant_network_connectivity(self):
         if not self.config.network.tenant_networks_reachable:
             msg = 'Tenant networks not configured to be reachable.'
-            raise nose.SkipTest(msg)
+            raise self.skipTest(msg)
         if not self.servers:
-            raise nose.SkipTest("No VM's have been created")
+            raise self.skipTest("No VM's have been created")
         for server in self.servers:
             for net_name, ip_addresses in server.networks.iteritems():
                 for ip_address in ip_addresses:
@@ -484,9 +483,9 @@
     def test_007_assign_floating_ips(self):
         public_network_id = self.config.network.public_network_id
         if not public_network_id:
-            raise nose.SkipTest('Public network not configured')
+            raise self.skipTest('Public network not configured')
         if not self.servers:
-            raise nose.SkipTest("No VM's have been created")
+            raise self.skipTest("No VM's have been created")
         for server in self.servers:
             floating_ip = self._create_floating_ip(server, public_network_id)
             self.floating_ips.setdefault(server, [])
@@ -494,7 +493,7 @@
 
     def test_008_check_public_network_connectivity(self):
         if not self.floating_ips:
-            raise nose.SkipTest('No floating ips have been allocated.')
+            raise self.skipTest('No floating ips have been allocated.')
         for server, floating_ips in self.floating_ips.iteritems():
             for floating_ip in floating_ips:
                 ip_address = floating_ip.floating_ip_address
diff --git a/tempest/tests/object_storage/base.py b/tempest/tests/object_storage/base.py
index 5e3d0bc..8c32ffc 100644
--- a/tempest/tests/object_storage/base.py
+++ b/tempest/tests/object_storage/base.py
@@ -15,8 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 import tempest.config
@@ -24,7 +23,7 @@
 from tempest.tests.identity.base import DataGenerator
 
 
-class BaseObjectTest(unittest.TestCase):
+class BaseObjectTest(testtools.TestCase):
 
     @classmethod
     def setUpClass(cls):
@@ -50,4 +49,4 @@
         except exceptions.EndpointNotFound:
             enabled = False
             skip_msg = "No OpenStack Object Storage API endpoint"
-            raise nose.SkipTest(skip_msg)
+            raise cls.skipException(skip_msg)
diff --git a/tempest/tests/object_storage/test_container_sync.py b/tempest/tests/object_storage/test_container_sync.py
index 3dea259..597fd86 100644
--- a/tempest/tests/object_storage/test_container_sync.py
+++ b/tempest/tests/object_storage/test_container_sync.py
@@ -19,7 +19,7 @@
 from tempest.common.utils.data_utils import arbitrary_string
 from tempest.common.utils.data_utils import rand_name
 from tempest.tests.object_storage import base
-import unittest2 as unittest
+import testtools
 
 
 class ContainerSyncTest(base.BaseObjectTest):
@@ -61,7 +61,7 @@
             #Attempt to delete the container
             resp, _ = client[0].delete_container(cont_name)
 
-    @unittest.skip('Until Bug 1093743 is resolved.')
+    @testtools.skip('Until Bug 1093743 is resolved.')
     @attr(type='positive')
     def test_container_synchronization(self):
         #Container to container synchronization
diff --git a/tempest/tests/object_storage/test_object_expiry.py b/tempest/tests/object_storage/test_object_expiry.py
index 099fc16..8e6b23b 100644
--- a/tempest/tests/object_storage/test_object_expiry.py
+++ b/tempest/tests/object_storage/test_object_expiry.py
@@ -20,8 +20,8 @@
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 from tempest.tests.object_storage import base
+import testtools
 from time import sleep
-import unittest2 as unittest
 
 
 class ObjectExpiryTest(base.BaseObjectTest):
@@ -54,7 +54,7 @@
         #Attempt to delete the container
         resp, _ = cls.container_client.delete_container(cls.container_name)
 
-    @unittest.skip('Until bug 1069849 is resolved.')
+    @testtools.skip('Until bug 1069849 is resolved.')
     @attr(type='regression')
     def test_get_object_after_expiry_time(self):
         # GET object after expiry time
diff --git a/tempest/tests/object_storage/test_object_services.py b/tempest/tests/object_storage/test_object_services.py
index a65401c..d5b6d5c 100644
--- a/tempest/tests/object_storage/test_object_services.py
+++ b/tempest/tests/object_storage/test_object_services.py
@@ -21,8 +21,8 @@
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 from tempest.tests.object_storage import base
+import testtools
 from time import time
-import unittest2 as unittest
 
 
 class ObjectTest(base.BaseObjectTest):
@@ -327,7 +327,7 @@
                 self.assertIn('x-container-read', resp)
                 self.assertEqual(resp['x-container-read'], 'x')
 
-    @unittest.skip('Until Bug 1091669  is resolved.')
+    @testtools.skip('Until Bug 1091669  is resolved.')
     @attr(type='smoke')
     def test_access_public_object_with_another_user_creds(self):
         #Make container public-readable, and access the object
@@ -382,7 +382,7 @@
                 self.assertIn('x-container-read', resp)
                 self.assertEqual(resp['x-container-read'], 'x')
 
-    @unittest.skip('Until Bug #1020722 is resolved.')
+    @testtools.skip('Until Bug #1020722 is resolved.')
     @attr(type='smoke')
     def test_write_public_object_without_using_creds(self):
         #Make container public-writable, and create object
@@ -433,7 +433,7 @@
                 self.assertIn('x-container-write', resp)
                 self.assertEqual(resp['x-container-write'], 'x')
 
-    @unittest.skip('Until Bug #1020722 is resolved.')
+    @testtools.skip('Until Bug #1020722 is resolved.')
     @attr(type='smoke')
     def test_write_public_with_another_user_creds(self):
         #Make container public-writable, and create object
@@ -592,7 +592,7 @@
                           self.container_name, object_name,
                           metadata=self.custom_headers)
 
-    @unittest.skip('Until bug 1097137 is resolved.')
+    @testtools.skip('Until bug 1097137 is resolved.')
     @attr(type='positive')
     def test_get_object_using_temp_url(self):
         #Access object using temp url within expiry time
diff --git a/tempest/tests/utils.py b/tempest/tests/utils.py
index 571fc2a..0738201 100644
--- a/tempest/tests/utils.py
+++ b/tempest/tests/utils.py
@@ -17,41 +17,7 @@
 
 """Common utilities used in testing."""
 
-import nose.plugins.skip
-
-
-class skip_if(object):
-    """Decorator that skips a test if condition is true."""
-    def __init__(self, condition, msg):
-        self.condition = condition
-        self.message = msg
-
-    def __call__(self, func):
-        def _skipper(*args, **kw):
-            """Wrapped skipper function."""
-            if self.condition:
-                raise nose.SkipTest(self.message)
-            func(*args, **kw)
-        _skipper.__name__ = func.__name__
-        _skipper.__doc__ = func.__doc__
-        return _skipper
-
-
-class skip_unless(object):
-    """Decorator that skips a test if condition is not true."""
-    def __init__(self, condition, msg):
-        self.condition = condition
-        self.message = msg
-
-    def __call__(self, func):
-        def _skipper(*args, **kw):
-            """Wrapped skipper function."""
-            if not self.condition:
-                raise nose.SkipTest(self.message)
-            func(*args, **kw)
-        _skipper.__name__ = func.__name__
-        _skipper.__doc__ = func.__doc__
-        return _skipper
+from testtools import TestCase
 
 
 class skip_unless_attr(object):
@@ -66,7 +32,7 @@
             """Wrapped skipper function."""
             testobj = args[0]
             if not getattr(testobj, self.attr, False):
-                raise nose.SkipTest(self.message)
+                raise TestCase.skipException(self.message)
             func(*args, **kw)
         _skipper.__name__ = func.__name__
         _skipper.__doc__ = func.__doc__
diff --git a/tempest/tests/volume/admin/base.py b/tempest/tests/volume/admin/base.py
index d35efbc..21425be 100644
--- a/tempest/tests/volume/admin/base.py
+++ b/tempest/tests/volume/admin/base.py
@@ -15,8 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import nose
-
 
 from tempest import config
 import tempest.services.volume.json.admin.volume_types_client \
@@ -32,15 +30,15 @@
     def setUpClass(cls):
         super(BaseVolumeAdminTest, cls).setUpClass()
         cls.config = config.TempestConfig()
-        cls.adm_user = cls.config.compute_admin.username
-        cls.adm_pass = cls.config.compute_admin.password
-        cls.adm_tenant = cls.config.compute_admin.tenant_name
+        cls.adm_user = cls.config.identity.admin_username
+        cls.adm_pass = cls.config.identity.admin_password
+        cls.adm_tenant = cls.config.identity.admin_tenant_name
         cls.auth_url = cls.config.identity.uri
 
         if not cls.adm_user and cls.adm_pass and cls.adm_tenant:
             msg = ("Missing Volume Admin API credentials "
                    "in configuration.")
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
     @classmethod
     def tearDownClass(cls):
diff --git a/tempest/tests/volume/admin/test_volume_types.py b/tempest/tests/volume/admin/test_volume_types.py
index a907a79..cef8428 100644
--- a/tempest/tests/volume/admin/test_volume_types.py
+++ b/tempest/tests/volume/admin/test_volume_types.py
@@ -25,9 +25,9 @@
     @classmethod
     def setUpClass(cls):
         super(VolumeTypesTest, cls).setUpClass()
-        adm_user = cls.config.compute_admin.username
-        adm_pass = cls.config.compute_admin.password
-        adm_tenant = cls.config.compute_admin.tenant_name
+        adm_user = cls.config.identity.admin_username
+        adm_pass = cls.config.identity.admin_password
+        adm_tenant = cls.config.identity.admin_tenant_name
         auth_url = cls.config.identity.uri
 
         cls.client = volume_types_client.VolumeTypesClientJSON(cls.config,
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 c5a1fa9..d3fd8e5 100644
--- a/tempest/tests/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/tests/volume/admin/test_volume_types_extra_specs.py
@@ -26,9 +26,9 @@
     def setUpClass(cls):
         super(VolumeTypesExtraSpecsTest, cls).setUpClass()
 
-        adm_user = cls.config.compute_admin.username
-        adm_pass = cls.config.compute_admin.password
-        adm_tenant = cls.config.compute_admin.tenant_name
+        adm_user = cls.config.identity.admin_username
+        adm_pass = cls.config.identity.admin_password
+        adm_tenant = cls.config.identity.admin_tenant_name
         auth_url = cls.config.identity.uri
 
         cls.client = volume_types_client.VolumeTypesClientJSON(cls.config,
diff --git a/tempest/tests/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/tests/volume/admin/test_volume_types_extra_specs_negative.py
index d139425..e7fe701 100644
--- a/tempest/tests/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/tests/volume/admin/test_volume_types_extra_specs_negative.py
@@ -15,7 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import unittest
+import testtools
 import uuid
 
 from nose.plugins.attrib import attr
@@ -42,7 +42,7 @@
     def tearDownClass(cls):
         cls.client.delete_volume_type(cls.volume_type['id'])
 
-    @unittest.skip('Until bug 1090320 is fixed')
+    @testtools.skip('Until bug 1090320 is fixed')
     @raises(exceptions.BadRequest)
     @attr(type='negative')
     def test_update_no_body(self):
@@ -88,7 +88,7 @@
         self.client.create_volume_type_extra_specs(str(uuid.uuid4()),
                                                    extra_specs)
 
-    @unittest.skip('Until bug 1090322 is fixed')
+    @testtools.skip('Until bug 1090322 is fixed')
     @raises(exceptions.BadRequest)
     @attr(type='negative')
     def test_create_none_body(self):
@@ -96,7 +96,7 @@
         self.client.create_volume_type_extra_specs(self.volume_type['id'],
                                                    None)
 
-    @unittest.skip('Until bug 1090322 is fixed')
+    @testtools.skip('Until bug 1090322 is fixed')
     @raises(exceptions.BadRequest)
     @attr(type='negative')
     def test_create_invalid_body(self):
diff --git a/tempest/tests/volume/admin/test_volume_types_negative.py b/tempest/tests/volume/admin/test_volume_types_negative.py
index c2daef9..f53e33c 100644
--- a/tempest/tests/volume/admin/test_volume_types_negative.py
+++ b/tempest/tests/volume/admin/test_volume_types_negative.py
@@ -15,7 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import unittest
+import testtools
 import uuid
 
 from nose.plugins.attrib import attr
@@ -40,7 +40,7 @@
                                           display_name=str(uuid.uuid4()),
                                           volume_type=str(uuid.uuid4()))
 
-    @unittest.skip('Until bug 1090356 is fixed')
+    @testtools.skip('Until bug 1090356 is fixed')
     @raises(exceptions.BadRequest)
     @attr(type='negative')
     def test_create_with_empty_name(self):
diff --git a/tempest/tests/volume/base.py b/tempest/tests/volume/base.py
index 1b35170..de78c99 100644
--- a/tempest/tests/volume/base.py
+++ b/tempest/tests/volume/base.py
@@ -19,7 +19,7 @@
 import time
 
 import nose
-import unittest2 as unittest
+import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
@@ -29,7 +29,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseVolumeTest(unittest.TestCase):
+class BaseVolumeTest(testtools.TestCase):
 
     """Base test case class for all Cinder API tests."""
 
@@ -66,14 +66,14 @@
                                              cls.os.tenant_name)
         except exceptions.EndpointNotFound:
             cls.clear_isolated_creds()
-            raise nose.SkipTest(skip_msg)
+            raise cls.skipException(skip_msg)
 
     @classmethod
     def _get_identity_admin_client(cls):
         """
         Returns an instance of the Identity Admin API client
         """
-        os = clients.AdminManager()
+        os = clients.ComputeAdminManager()
         return os.identity_client
 
     @classmethod
diff --git a/tempest/tests/volume/test_volumes_list.py b/tempest/tests/volume/test_volumes_list.py
index 2fc1353..92d3d3f 100644
--- a/tempest/tests/volume/test_volumes_list.py
+++ b/tempest/tests/volume/test_volumes_list.py
@@ -94,7 +94,7 @@
                            "test. This typically means that the backing file "
                            "size of the nova-volumes group is too small to "
                            "create the 3 volumes needed by this test case")
-                    raise nose.SkipTest(msg)
+                    raise cls.skipException(msg)
                 raise
 
     @classmethod
@@ -141,7 +141,7 @@
                            "test. This typically means that the backing file "
                            "size of the nova-volumes group is too small to "
                            "create the 3 volumes needed by this test case")
-                    raise nose.SkipTest(msg)
+                    raise cls.skipException(msg)
                 raise
 
     @classmethod
diff --git a/tempest/whitebox.py b/tempest/whitebox.py
index d78b9e0..03ad63b 100644
--- a/tempest/whitebox.py
+++ b/tempest/whitebox.py
@@ -21,7 +21,6 @@
 import subprocess
 import sys
 
-import nose
 from sqlalchemy import create_engine, MetaData
 
 from tempest.common.ssh import Client
@@ -59,7 +58,7 @@
     def setUpClass(cls):
         if not compute.WHITEBOX_ENABLED:
             msg = "Whitebox testing disabled"
-            raise nose.SkipTest(msg)
+            raise cls.skipException(msg)
 
         super(ComputeWhiteboxTest, cls).setUpClass()
 
diff --git a/tools/pip-requires b/tools/pip-requires
index fcf1690..dcc859f 100644
--- a/tools/pip-requires
+++ b/tools/pip-requires
@@ -1,7 +1,7 @@
 anyjson
 nose
 httplib2>=0.7.0
-unittest2
+testtools
 lxml
 boto>=2.2.1
 paramiko
diff --git a/tools/tempest_coverage.py b/tools/tempest_coverage.py
index 6e7ac04..267eafa 100755
--- a/tools/tempest_coverage.py
+++ b/tools/tempest_coverage.py
@@ -138,9 +138,9 @@
 
 def main(argv):
     CLI = parse_opts(argv)
-    client_args = (CONF, CONF.compute_admin.username,
-                   CONF.compute_admin.password, CONF.identity.uri,
-                   CONF.compute_admin.tenant_name)
+    client_args = (CONF, CONF.identity.admin_username,
+                   CONF.identity.admin_password, CONF.identity.uri,
+                   CONF.identity.admin_tenant_name)
     coverage_client = CoverageClientJSON(*client_args)
 
     if CLI.command == 'start':