Merge "cleanup resource in setUpClass if ecxeption raised"
diff --git a/HACKING.rst b/HACKING.rst
index a546f8c..eafa81b 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -153,6 +153,19 @@
                              kwarg2=dict_of_numbers)
 
 
+Test Skips
+----------
+If a test is broken because of a bug it is appropriate to skip the test until
+bug has been fixed. However, the skip message should be formatted so that
+Tempest's skip tracking tool can watch the bug status. The skip message should
+contain the string 'Bug' immediately followed by a space. Then the bug number
+should be included in the message '#' in front of the number.
+
+Example::
+
+  @testtools.skip("Skipped until the Bug #980688 is resolved")
+
+
 openstack-common
 ----------------
 
diff --git a/cli/__init__.py b/cli/__init__.py
index 6ffe229..7a92260 100644
--- a/cli/__init__.py
+++ b/cli/__init__.py
@@ -60,16 +60,22 @@
         return self.cmd_with_auth(
             'nova', action, flags, params, admin, fail_ok)
 
-    def nova_manage(self, action, flags='', params='', fail_ok=False):
+    def nova_manage(self, action, flags='', params='', fail_ok=False,
+                    merge_stderr=False):
         """Executes nova-manage command for the given action."""
         return self.cmd(
-            'nova-manage', action, flags, params, fail_ok)
+            'nova-manage', action, flags, params, fail_ok, merge_stderr)
 
     def keystone(self, action, flags='', params='', admin=True, fail_ok=False):
         """Executes keystone command for the given action."""
         return self.cmd_with_auth(
             'keystone', action, flags, params, admin, fail_ok)
 
+    def glance(self, action, flags='', params='', admin=True, fail_ok=False):
+        """Executes glance command for the given action."""
+        return self.cmd_with_auth(
+            'glance', action, flags, params, admin, fail_ok)
+
     def cmd_with_auth(self, cmd, action, flags='', params='',
                       admin=True, fail_ok=False):
         """Executes given command with auth attributes appended."""
@@ -81,14 +87,19 @@
         flags = creds + ' ' + flags
         return self.cmd(cmd, action, flags, params, fail_ok)
 
-    def cmd(self, cmd, action, flags='', params='', fail_ok=False):
+    def cmd(self, cmd, action, flags='', params='', fail_ok=False,
+            merge_stderr=False):
         """Executes specified command for the given action."""
         cmd = ' '.join([CONF.cli.cli_dir + cmd,
                         flags, action, params])
         LOG.info("running: '%s'" % cmd)
         cmd = shlex.split(cmd)
         try:
-            result = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+            if merge_stderr:
+                result = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+            else:
+                devnull = open('/dev/null', 'w')
+                result = subprocess.check_output(cmd, stderr=devnull)
         except subprocess.CalledProcessError, e:
             LOG.error("command output:\n%s" % e.output)
             raise
diff --git a/cli/simple_read_only/test_compute.py b/cli/simple_read_only/test_compute.py
index c904882..d301d38 100644
--- a/cli/simple_read_only/test_compute.py
+++ b/cli/simple_read_only/test_compute.py
@@ -22,7 +22,6 @@
 import testtools
 
 import cli
-from tempest import config
 
 
 CONF = cfg.CONF
diff --git a/cli/simple_read_only/test_compute_manage.py b/cli/simple_read_only/test_compute_manage.py
index 5768c74..bbcc5b1 100644
--- a/cli/simple_read_only/test_compute_manage.py
+++ b/cli/simple_read_only/test_compute_manage.py
@@ -18,8 +18,6 @@
 import logging
 import subprocess
 
-import testtools
-
 import cli
 
 
@@ -50,9 +48,11 @@
         self.nova_manage('', '-h')
 
     def test_version_flag(self):
-        self.assertNotEqual("", self.nova_manage('', '--version'))
+        # Bug 1159957: nova-manage --version writes to stderr
+        self.assertNotEqual("", self.nova_manage('', '--version',
+                                                 merge_stderr=True))
         self.assertEqual(self.nova_manage('version'),
-                         self.nova_manage('', '--version'))
+                         self.nova_manage('', '--version', merge_stderr=True))
 
     def test_debug_flag(self):
         self.assertNotEqual("", self.nova_manage('instance_type list',
@@ -68,8 +68,8 @@
 
     def test_flavor_list(self):
         self.assertNotEqual("", self.nova_manage('flavor list'))
-        self.assertNotEqual(self.nova_manage('instance_type list'),
-                            self.nova_manage('flavor list'))
+        self.assertEqual(self.nova_manage('instance_type list'),
+                         self.nova_manage('flavor list'))
 
     def test_db_archive_deleted_rows(self):
         # make sure command doesn't error out
diff --git a/cli/simple_read_only/test_glance.py b/cli/simple_read_only/test_glance.py
new file mode 100644
index 0000000..f9822cc
--- /dev/null
+++ b/cli/simple_read_only/test_glance.py
@@ -0,0 +1,66 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import logging
+import re
+import subprocess
+
+import cli
+
+
+LOG = logging.getLogger(__name__)
+
+
+class SimpleReadOnlyGlanceClientTest(cli.ClientTestBase):
+    """Basic, read-only tests for Glance CLI client.
+
+    Checks return values and output of read-only commands.
+    These tests do not presume any content, nor do they create
+    their own. They only verify the structure of output if present.
+    """
+
+    def test_glance_fake_action(self):
+        self.assertRaises(subprocess.CalledProcessError,
+                          self.glance,
+                          'this-does-not-exist')
+
+    def test_glance_image_list(self):
+        out = self.glance('image-list')
+        endpoints = self.parser.listing(out)
+        self.assertTableStruct(endpoints, [
+            'ID', 'Name', 'Disk Format', 'Container Format',
+            'Size', 'Status'])
+
+    def test_glance_help(self):
+        help_text = self.glance('help')
+        lines = help_text.split('\n')
+        self.assertTrue(lines[0].startswith('usage: glance'))
+
+        commands = []
+        cmds_start = lines.index('Positional arguments:')
+        cmds_end = lines.index('Optional arguments:')
+        command_pattern = re.compile('^ {4}([a-z0-9\-\_]+)')
+        for line in lines[cmds_start:cmds_end]:
+            match = command_pattern.match(line)
+            if match:
+                commands.append(match.group(1))
+        commands = set(commands)
+        wanted_commands = set(('image-create', 'image-delete', 'help',
+                               'image-download', 'image-show', 'image-update',
+                               'member-add', 'member-create', 'member-delete',
+                               'member-list'))
+        self.assertFalse(wanted_commands - commands)
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 02bfdcb..9280c57 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -178,7 +178,7 @@
 tenant_network_cidr = 10.100.0.0/16
 
 # The mask bits used to partition the tenant block.
-tenant_network_mask_bits = 29
+tenant_network_mask_bits = 28
 
 # If tenant networks are reachable, connectivity checks will be
 # performed directly against addresses on those networks.
diff --git a/run_tests.sh b/run_tests.sh
index 93edfaf..3f394e3 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -95,14 +95,7 @@
 
 function run_pep8 {
   echo "Running pep8 ..."
-  srcfiles="`find tempest -type f -name "*.py"`"
-  srcfiles+=" `find tools -type f -name "*.py"`"
-  srcfiles+=" `find stress -type f -name "*.py"`"
-  srcfiles+=" setup.py"
-
-  ignore='--ignore=E121,E122,E125,E126'
-
-    ${wrapper} python tools/hacking.py ${ignore} ${srcfiles}
+  ${wrapper} tools/check_source.sh
 }
 
 function run_coverage_start {
diff --git a/setup.py b/setup.py
index 1f071bb..1507797 100755
--- a/setup.py
+++ b/setup.py
@@ -25,7 +25,7 @@
 depend_links = common_setup.parse_dependency_links()
 
 setuptools.setup(name='tempest',
-                 version="2012.2",
+                 version=common_setup.get_version('tempest', "2013.2"),
                  description='Integration test tools',
                  author='OpenStack',
                  author_email='openstack-qa@lists.launchpad.net',
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index d68b9ed..02b5c9b 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -161,12 +161,6 @@
             if mgmt_url is None:
                 raise exceptions.EndpointNotFound(service)
 
-            if service == 'network':
-                # Keystone does not return the correct endpoint for
-                # quantum. Handle this separately.
-                mgmt_url = (mgmt_url + self.config.network.api_version +
-                            "/tenants/" + tenant_id)
-
             return token, mgmt_url
 
         elif resp.status == 401:
@@ -320,6 +314,10 @@
             except KeyError:
                 ctype = 'application/json'
 
+        # It is not an error response
+        if resp.status < 400:
+            return
+
         JSON_ENC = ['application/json; charset=UTF-8', 'application/json',
                     'application/json; charset=utf-8']
         # NOTE(mtreinish): This is for compatibility with Glance and swift
diff --git a/tempest/common/utils/data_utils.py b/tempest/common/utils/data_utils.py
index 82982b8..e75b54f 100644
--- a/tempest/common/utils/data_utils.py
+++ b/tempest/common/utils/data_utils.py
@@ -24,10 +24,10 @@
 
 
 def rand_name(name='test'):
-    return name + str(random.randint(1, 999999))
+    return name + str(random.randint(1, 0x7fffffff))
 
 
-def rand_int_id(start=0, end=999999):
+def rand_int_id(start=0, end=0x7fffffff):
     return random.randint(start, end)
 
 
diff --git a/tempest/config.py b/tempest/config.py
index 3a4a8c9..9c41660 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -260,9 +260,6 @@
     cfg.StrOpt('catalog_type',
                default='network',
                help='Catalog type of the Quantum service.'),
-    cfg.StrOpt('api_version',
-               default="v1.1",
-               help="Version of Quantum API"),
     cfg.StrOpt('tenant_network_cidr',
                default="10.100.0.0/16",
                help="The cidr block to allocate tenant networks from"),
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
index 330e80b..37d4131 100644
--- a/tempest/services/compute/json/quotas_client.py
+++ b/tempest/services/compute/json/quotas_client.py
@@ -37,7 +37,7 @@
 
     def update_quota_set(self, tenant_id, injected_file_content_bytes=None,
                          metadata_items=None, ram=None, floating_ips=None,
-                         key_pairs=None, instances=None,
+                         fixed_ips=None, key_pairs=None, instances=None,
                          security_group_rules=None, injected_files=None,
                          cores=None, injected_file_path_bytes=None,
                          security_groups=None):
@@ -59,6 +59,9 @@
         if floating_ips is not None:
             post_body['floating_ips'] = floating_ips
 
+        if fixed_ips is not None:
+            post_body['fixed_ips'] = fixed_ips
+
         if key_pairs is not None:
             post_body['key_pairs'] = key_pairs
 
diff --git a/tempest/services/compute/json/security_groups_client.py b/tempest/services/compute/json/security_groups_client.py
index 7f430d8..1dc11c4 100644
--- a/tempest/services/compute/json/security_groups_client.py
+++ b/tempest/services/compute/json/security_groups_client.py
@@ -19,6 +19,7 @@
 import urllib
 
 from tempest.common.rest_client import RestClient
+from tempest import exceptions
 
 
 class SecurityGroupsClientJSON(RestClient):
diff --git a/tempest/services/compute/xml/images_client.py b/tempest/services/compute/xml/images_client.py
index 3b01efb..27bb979 100644
--- a/tempest/services/compute/xml/images_client.py
+++ b/tempest/services/compute/xml/images_client.py
@@ -77,6 +77,19 @@
             data['images'].append(self._parse_image(image))
         return data
 
+    def _parse_key_value(self, node):
+        """Parse <foo key='key'>value</foo> data into {'key': 'value'}."""
+        data = {}
+        for node in node.getchildren():
+            data[node.get('key')] = node.text
+        return data
+
+    def _parse_metadata(self, node):
+        """Parse the response body without children."""
+        data = {}
+        data[node.get('key')] = node.text
+        return data
+
     def create_image(self, server_id, name, meta=None):
         """Creates an image of the original server."""
         post_body = Element('createImage', name=name)
@@ -153,51 +166,53 @@
             if int(time.time()) - start >= self.build_timeout:
                 raise exceptions.TimeoutException
 
+    def _metadata_body(self, meta):
+        post_body = Element('metadata')
+        for k, v in meta.items():
+            data = Element('meta', key=k)
+            data.append(Text(v))
+            post_body.append(data)
+        return post_body
+
     def list_image_metadata(self, image_id):
         """Lists all metadata items for an image."""
         resp, body = self.get("images/%s/metadata" % str(image_id),
                               self.headers)
-        body = xml_to_json(etree.fromstring(body))
-        return resp, body['metadata']
-
-    def _metadata_body(image_id, meta):
-        post_body = Document('metadata')
-        for k, v in meta:
-            text = Text(v)
-            metadata = Element('meta', text, key=k)
-            post_body.append(metadata)
-        return post_body
+        body = self._parse_key_value(etree.fromstring(body))
+        return resp, body
 
     def set_image_metadata(self, image_id, meta):
         """Sets the metadata for an image."""
-        post_body = self._metadata_body(image_id, meta)
-        resp, body = self.put('images/%s/metadata' % str(image_id),
-                              post_body, self.headers)
-        body = xml_to_json(etree.fromstring(body))
-        return resp, body['metadata']
+        post_body = self._metadata_body(meta)
+        resp, body = self.put('images/%s/metadata' % image_id,
+                              str(Document(post_body)), self.headers)
+        body = self._parse_key_value(etree.fromstring(body))
+        return resp, body
 
     def update_image_metadata(self, image_id, meta):
         """Updates the metadata for an image."""
-        post_body = self._metadata_body(image_id, meta)
+        post_body = self._metadata_body(meta)
         resp, body = self.post('images/%s/metadata' % str(image_id),
-                               post_body, self.headers)
-        body = xml_to_json(etree.fromstring(body))
-        return resp, body['metadata']
+                               str(Document(post_body)), self.headers)
+        body = self._parse_key_value(etree.fromstring(body))
+        return resp, body
 
     def get_image_metadata_item(self, image_id, key):
         """Returns the value for a specific image metadata key."""
         resp, body = self.get("images/%s/metadata/%s.xml" %
                               (str(image_id), key), self.headers)
-        body = xml_to_json(etree.fromstring(body))
-        return resp, body['meta']
+        body = self._parse_metadata(etree.fromstring(body))
+        return resp, body
 
     def set_image_metadata_item(self, image_id, key, meta):
         """Sets the value for a specific image metadata key."""
-        post_body = Document('meta', Text(meta), key=key)
-        resp, body = self.post('images/%s/metadata/%s' % (str(image_id), key),
-                               post_body, self.headers)
+        for k, v in meta.items():
+            post_body = Element('meta', key=key)
+            post_body.append(Text(v))
+        resp, body = self.put('images/%s/metadata/%s' % (str(image_id), key),
+                              str(Document(post_body)), self.headers)
         body = xml_to_json(etree.fromstring(body))
-        return resp, body['meta']
+        return resp, body
 
     def update_image_metadata_item(self, image_id, key, meta):
         """Sets the value for a specific image metadata key."""
@@ -209,6 +224,5 @@
 
     def delete_image_metadata_item(self, image_id, key):
         """Deletes a single image metadata key/value pair."""
-        resp, body = self.delete("images/%s/metadata/%s" % (str(image_id), key,
-                                 self.headers))
-        return resp, body
+        return self.delete("images/%s/metadata/%s" % (str(image_id), key),
+                           self.headers)
diff --git a/tempest/services/compute/xml/quotas_client.py b/tempest/services/compute/xml/quotas_client.py
index 0437205..20e04b4 100644
--- a/tempest/services/compute/xml/quotas_client.py
+++ b/tempest/services/compute/xml/quotas_client.py
@@ -57,7 +57,7 @@
 
     def update_quota_set(self, tenant_id, injected_file_content_bytes=None,
                          metadata_items=None, ram=None, floating_ips=None,
-                         key_pairs=None, instances=None,
+                         fixed_ips=None, key_pairs=None, instances=None,
                          security_group_rules=None, injected_files=None,
                          cores=None, injected_file_path_bytes=None,
                          security_groups=None):
@@ -80,6 +80,9 @@
         if floating_ips is not None:
             post_body.add_attr('floating_ips', floating_ips)
 
+        if fixed_ips is not None:
+            post_body.add_attr('fixed_ips', fixed_ips)
+
         if key_pairs is not None:
             post_body.add_attr('key_pairs', key_pairs)
 
diff --git a/tempest/services/compute/xml/security_groups_client.py b/tempest/services/compute/xml/security_groups_client.py
index 7db60a1..10f1a42 100644
--- a/tempest/services/compute/xml/security_groups_client.py
+++ b/tempest/services/compute/xml/security_groups_client.py
@@ -19,6 +19,7 @@
 import urllib
 
 from tempest.common.rest_client import RestClientXML
+from tempest import exceptions
 from tempest.services.compute.xml.common import Document
 from tempest.services.compute.xml.common import Element
 from tempest.services.compute.xml.common import Text
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index 008417b..15dfd74 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -94,6 +94,11 @@
         json['addresses'] = json_addresses
     else:
         json = xml_to_json(xml_dom)
+    diskConfig = '{http://docs.openstack.org/compute/ext/disk_config/api/v1.1'\
+                 '}diskConfig'
+    if diskConfig in json:
+        json['OS-DCF:diskConfig'] = json[diskConfig]
+        del json[diskConfig]
     return json
 
 
@@ -234,6 +239,11 @@
             if attr in kwargs:
                 server.add_attr(attr, kwargs[attr])
 
+        if 'disk_config' in kwargs:
+            server.add_attr('xmlns:OS-DCF', "http://docs.openstack.org/"
+                            "compute/ext/disk_config/api/v1.1")
+            server.add_attr('OS-DCF:diskConfig', kwargs['disk_config'])
+
         if 'security_groups' in kwargs:
             secgroups = Element("security_groups")
             server.append(secgroups)
@@ -357,6 +367,12 @@
 
     def rebuild(self, server_id, image_ref, **kwargs):
         kwargs['imageRef'] = image_ref
+        if 'disk_config' in kwargs:
+            kwargs['OS-DCF:diskConfig'] = kwargs['disk_config']
+            del kwargs['disk_config']
+            kwargs['xmlns:OS-DCF'] = "http://docs.openstack.org/"\
+                                     "compute/ext/disk_config/api/v1.1"
+            kwargs['xmlns:atom'] = "http://www.w3.org/2005/Atom"
         if 'xmlns' not in kwargs:
             kwargs['xmlns'] = XMLNS_11
 
@@ -381,8 +397,11 @@
 
     def resize(self, server_id, flavor_ref, **kwargs):
         if 'disk_config' in kwargs:
-            raise NotImplementedError("Sorry, disk_config not "
-                                      "supported via XML yet")
+            kwargs['OS-DCF:diskConfig'] = kwargs['disk_config']
+            del kwargs['disk_config']
+            kwargs['xmlns:OS-DCF'] = "http://docs.openstack.org/"\
+                                     "compute/ext/disk_config/api/v1.1"
+            kwargs['xmlns:atom'] = "http://www.w3.org/2005/Atom"
         kwargs['flavorRef'] = flavor_ref
         return self.action(server_id, 'resize', None, **kwargs)
 
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index 77c9cd2..9c7269f 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -18,13 +18,17 @@
 import copy
 import errno
 import json
+import logging
 import os
+import time
 import urllib
 
 from tempest.common import glance_http
 from tempest.common.rest_client import RestClient
 from tempest import exceptions
 
+LOG = logging.getLogger(__name__)
+
 
 class ImageClientJSON(RestClient):
 
@@ -59,8 +63,13 @@
     def _image_meta_to_headers(self, fields):
         headers = {}
         fields_copy = copy.deepcopy(fields)
+        copy_from = fields_copy.pop('copy_from', None)
+        if copy_from is not None:
+            headers['x-glance-api-copy-from'] = copy_from
         for key, value in fields_copy.pop('properties', {}).iteritems():
             headers['x-image-meta-property-%s' % key] = str(value)
+        for key, value in fields_copy.pop('api', {}).iteritems():
+            headers['x-glance-api-property-%s' % key] = str(value)
         for key, value in fields_copy.iteritems():
             headers['x-image-meta-%s' % key] = str(value)
         return headers
@@ -130,7 +139,7 @@
 
         headers = {}
 
-        for option in ['is_public', 'location', 'properties']:
+        for option in ['is_public', 'location', 'properties', 'copy_from']:
             if option in kwargs:
                 params[option] = kwargs.get(option)
 
@@ -187,10 +196,15 @@
         body = json.loads(body)
         return resp, body['images']
 
+    def get_image_meta(self, image_id):
+        url = 'v1/images/%s' % image_id
+        resp, __ = self.head(url)
+        body = self._image_meta_from_headers(resp)
+        return resp, body
+
     def get_image(self, image_id):
         url = 'v1/images/%s' % image_id
-        resp, __ = self.get(url)
-        body = self._image_meta_from_headers(resp)
+        resp, body = self.get(url)
         return resp, body
 
     def is_resource_deleted(self, id):
@@ -231,3 +245,34 @@
         resp, data = self.put(url, body, self.headers)
         data = json.loads(data)
         return resp, data
+
+    #NOTE(afazekas): just for the wait function
+    def _get_image_status(self, image_id):
+        resp, meta = self.get_image_meta(image_id)
+        status = meta['status']
+        return status
+
+    #NOTE(afazkas): Wait reinvented again. It is not in the correct layer
+    def wait_for_image_status(self, image_id, status):
+        """Waits for a Image to reach a given status."""
+        start_time = time.time()
+        old_value = value = self._get_image_status(image_id)
+        while True:
+            dtime = time.time() - start_time
+            time.sleep(self.build_interval)
+            if value != old_value:
+                LOG.info('Value transition from "%s" to "%s"'
+                         'in %d second(s).', old_value,
+                         value, dtime)
+            if (value == status):
+                return value
+
+            if dtime > self.build_timeout:
+                message = ('Time Limit Exceeded! (%ds)'
+                           'while waiting for %s, '
+                           'but we got %s.' %
+                           (self.build_timeout, status, value))
+                raise exceptions.TimeoutException(message)
+            time.sleep(self.build_interval)
+            old_value = value
+            value = self._get_image_status(image_id)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 34342c9..4758ddd 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -4,98 +4,112 @@
 
 class NetworkClient(RestClient):
 
+    """
+    Tempest REST client for Quantum. Uses v2 of the Quantum API, since the
+    V1 API has been removed from the code base.
+
+    Implements the following operations for each one of the basic Quantum
+    abstractions (networks, sub-networks and ports):
+
+    create
+    delete
+    list
+    show
+    """
+
     def __init__(self, config, username, password, auth_url, tenant_name=None):
         super(NetworkClient, self).__init__(config, username, password,
                                             auth_url, tenant_name)
         self.service = self.config.network.catalog_type
+        self.version = '2.0'
+        self.uri_prefix = "v%s" % (self.version)
 
     def list_networks(self):
-        resp, body = self.get('networks')
+        uri = '%s/networks' % (self.uri_prefix)
+        resp, body = self.get(uri, self.headers)
         body = json.loads(body)
         return resp, body
 
-    def create_network(self, name, key="network"):
+    def create_network(self, name):
         post_body = {
-            key: {
+            'network': {
                 'name': name,
             }
         }
-        headers = {'Content-Type': 'application/json'}
         body = json.dumps(post_body)
-        resp, body = self.post('networks', headers=headers, body=body)
+        uri = '%s/networks' % (self.uri_prefix)
+        resp, body = self.post(uri, headers=self.headers, body=body)
         body = json.loads(body)
         return resp, body
 
-    def list_networks_details(self):
-        resp, body = self.get('networks/detail')
-        body = json.loads(body)
-        return resp, body
-
-    def get_network(self, uuid):
-        resp, body = self.get('networks/%s' % uuid)
-        body = json.loads(body)
-        return resp, body
-
-    def get_network_details(self, uuid):
-        resp, body = self.get('networks/%s/detail' % uuid)
+    def show_network(self, uuid):
+        uri = '%s/networks/%s' % (self.uri_prefix, uuid)
+        resp, body = self.get(uri, self.headers)
         body = json.loads(body)
         return resp, body
 
     def delete_network(self, uuid):
-        resp, body = self.delete('networks/%s' % uuid)
+        uri = '%s/networks/%s' % (self.uri_prefix, uuid)
+        resp, body = self.delete(uri, self.headers)
         return resp, body
 
-    def create_port(self, network_id, zone, state=None, key='port'):
+    def create_subnet(self, net_uuid, cidr):
+        post_body = dict(
+            subnet=dict(
+                ip_version=4,
+                network_id=net_uuid,
+                cidr=cidr),)
+        body = json.dumps(post_body)
+        uri = '%s/subnets' % (self.uri_prefix)
+        resp, body = self.post(uri, headers=self.headers, body=body)
+        body = json.loads(body)
+        return resp, body
+
+    def delete_subnet(self, uuid):
+        uri = '%s/subnets/%s' % (self.uri_prefix, uuid)
+        resp, body = self.delete(uri, self.headers)
+        return resp, body
+
+    def list_subnets(self):
+        uri = '%s/subnets' % (self.uri_prefix)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def show_subnet(self, uuid):
+        uri = '%s/subnets/%s' % (self.uri_prefix, uuid)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def create_port(self, network_id, state=None):
         if not state:
-            state = 'ACTIVE'
+            state = True
         post_body = {
-            key: {
-                'state': state,
-                'nova_id': zone
+            'port': {
+                'network_id': network_id,
+                'admin_state_up': state,
             }
         }
-        headers = {'Content-Type': 'application/json'}
         body = json.dumps(post_body)
-        resp, body = self.post('networks/%s/ports.json' % network_id,
-                               headers=headers, body=body)
+        uri = '%s/ports' % (self.uri_prefix)
+        resp, body = self.post(uri, headers=self.headers, body=body)
         body = json.loads(body)
         return resp, body
 
-    def delete_port(self, network_id, port_id):
-        resp, body = self.delete('networks/%s/ports/%s.json' %
-                                 (network_id, port_id))
+    def delete_port(self, port_id):
+        uri = '%s/ports/%s' % (self.uri_prefix, port_id)
+        resp, body = self.delete(uri, self.headers)
         return resp, body
 
-    def list_ports(self, network_id):
-        resp, body = self.get('networks/%s/ports.json' % network_id)
+    def list_ports(self):
+        uri = '%s/ports' % (self.uri_prefix)
+        resp, body = self.get(uri, self.headers)
         body = json.loads(body)
         return resp, body
 
-    def list_port_details(self, network_id):
-        url = 'networks/%s/ports/detail.json' % network_id
-        resp, body = self.get(url)
-        body = json.loads(body)
-        return resp, body
-
-    def attach_port(self, network_id, port_id, interface_id):
-        post_body = {
-            'attachment': {
-                'id': interface_id
-            }
-        }
-        headers = {'Content-Type': 'application/json'}
-        body = json.dumps(post_body)
-        url = 'networks/%s/ports/%s/attachment.json' % (network_id, port_id)
-        resp, body = self.put(url, headers=headers, body=body)
-        return resp, body
-
-    def detach_port(self, network_id, port_id):
-        url = 'networks/%s/ports/%s/attachment.json' % (network_id, port_id)
-        resp, body = self.delete(url)
-        return resp, body
-
-    def list_port_attachment(self, network_id, port_id):
-        url = 'networks/%s/ports/%s/attachment.json' % (network_id, port_id)
-        resp, body = self.get(url)
+    def show_port(self, port_id):
+        uri = '%s/ports/%s' % (self.uri_prefix, port_id)
+        resp, body = self.get(uri, self.headers)
         body = json.loads(body)
         return resp, body
diff --git a/tempest/tests/boto/test_s3_objects.py b/tempest/tests/boto/test_s3_objects.py
index c735215..dcb7c86 100644
--- a/tempest/tests/boto/test_s3_objects.py
+++ b/tempest/tests/boto/test_s3_objects.py
@@ -18,7 +18,6 @@
 from contextlib import closing
 
 from boto.s3.key import Key
-import testtools
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
diff --git a/tempest/tests/compute/admin/test_flavors.py b/tempest/tests/compute/admin/test_flavors.py
index 7fabf7a..32b06f8 100644
--- a/tempest/tests/compute/admin/test_flavors.py
+++ b/tempest/tests/compute/admin/test_flavors.py
@@ -39,6 +39,7 @@
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
+        cls.user_client = cls.os.flavors_client
         cls.flavor_name_prefix = 'test_flavor_'
         cls.ram = 512
         cls.vcpus = 1
@@ -315,7 +316,22 @@
                           self.client.list_flavors_with_detail,
                           {'is_public': 'invalid'})
 
-#TODO(afazekas): Negative tests with regular user
+    @attr(type='negative')
+    def test_create_flavor_as_user(self):
+        flavor_name = rand_name(self.flavor_name_prefix)
+        new_flavor_id = rand_int_id(start=1000)
+
+        self.assertRaises(exceptions.Unauthorized,
+                          self.user_client.create_flavor,
+                          flavor_name, self.ram, self.vcpus, self.disk,
+                          new_flavor_id, ephemeral=self.ephemeral,
+                          swap=self.swap, rxtx=self.rxtx)
+
+    @attr(type='negative')
+    def test_delete_flavor_as_user(self):
+        self.assertRaises(exceptions.Unauthorized,
+                          self.user_client.delete_flavor,
+                          self.flavor_ref_alt)
 
 
 class FlavorsAdminTestXML(FlavorsAdminTestJSON):
diff --git a/tempest/tests/compute/admin/test_quotas.py b/tempest/tests/compute/admin/test_quotas.py
index befcad3..5a9b6f9 100644
--- a/tempest/tests/compute/admin/test_quotas.py
+++ b/tempest/tests/compute/admin/test_quotas.py
@@ -44,7 +44,7 @@
         cls.default_quota_set = {'injected_file_content_bytes': 10240,
                                  'metadata_items': 128, 'injected_files': 5,
                                  'ram': 51200, 'floating_ips': 10,
-                                 'fixed_ips': 10, 'key_pairs': 100,
+                                 'fixed_ips': -1, 'key_pairs': 100,
                                  'injected_file_path_bytes': 255,
                                  'instances': 10, 'security_group_rules': 20,
                                  'cores': 20, 'security_groups': 10}
@@ -60,9 +60,6 @@
 
     @attr(type='smoke')
     def test_get_default_quotas(self):
-        # Tempest two step
-        self.skipTest('Skipped until the Bug 1125468 is resolved')
-
         # Admin can get the default resource quota set for a tenant
         expected_quota_set = self.default_quota_set.copy()
         expected_quota_set['id'] = self.demo_tenant_id
@@ -74,9 +71,6 @@
             self.fail("Admin could not get the default quota set for a tenant")
 
     def test_update_all_quota_resources_for_tenant(self):
-        # Tempest two step
-        self.skipTest('Skipped until the Bug 1125468 is resolved')
-
         # Admin can update all the resource quota limits for a tenant
         new_quota_set = {'injected_file_content_bytes': 20480,
                          'metadata_items': 256, 'injected_files': 10,
@@ -89,6 +83,8 @@
             resp, quota_set = self.adm_client.update_quota_set(
                 self.demo_tenant_id,
                 **new_quota_set)
+            self.addCleanup(self.adm_client.update_quota_set,
+                            self.demo_tenant_id, **self.default_quota_set)
             self.assertEqual(200, resp.status)
             self.assertEqual(new_quota_set, quota_set)
         except Exception:
@@ -103,12 +99,11 @@
 
     #TODO(afazekas): merge these test cases
     def test_get_updated_quotas(self):
-        # Tempest two step
-        self.skipTest('Skipped until the Bug 1125468 is resolved')
-
         # Verify that GET shows the updated quota set
         self.adm_client.update_quota_set(self.demo_tenant_id,
                                          ram='5120')
+        self.addCleanup(self.adm_client.update_quota_set,
+                        self.demo_tenant_id, **self.default_quota_set)
         try:
             resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
             self.assertEqual(200, resp.status)
diff --git a/tempest/tests/compute/base.py b/tempest/tests/compute/base.py
index 6155858..87aa889 100644
--- a/tempest/tests/compute/base.py
+++ b/tempest/tests/compute/base.py
@@ -96,47 +96,45 @@
         operate in an isolated tenant container.
         """
         admin_client = cls._get_identity_admin_client()
-        rand_name_root = rand_name(cls.__name__)
-        if cls.isolated_creds:
-            # Main user already created. Create the alt one...
-            rand_name_root += '-alt'
-        username = rand_name_root + "-user"
-        email = rand_name_root + "@example.com"
-        tenant_name = rand_name_root + "-tenant"
-        tenant_desc = tenant_name + "-desc"
         password = "pass"
 
-        try:
-            resp, tenant = admin_client.create_tenant(name=tenant_name,
-                                                      description=tenant_desc)
-        except exceptions.Duplicate:
-            if cls.config.compute.allow_tenant_reuse:
-                tenant = admin_client.get_tenant_by_name(tenant_name)
-                LOG.info('Re-using existing tenant %s' % tenant)
-            else:
-                msg = ('Unable to create isolated tenant %s because ' +
-                       'it already exists. If this is related to a ' +
-                       'previous test failure, try using ' +
-                       'allow_tenant_reuse in tempest.conf') % tenant_name
-                raise exceptions.Duplicate(msg)
+        while True:
+            try:
+                rand_name_root = rand_name(cls.__name__)
+                if cls.isolated_creds:
+                # Main user already created. Create the alt one...
+                    rand_name_root += '-alt'
+                tenant_name = rand_name_root + "-tenant"
+                tenant_desc = tenant_name + "-desc"
 
-        try:
-            resp, user = admin_client.create_user(username,
-                                                  password,
-                                                  tenant['id'],
-                                                  email)
-        except exceptions.Duplicate:
-            if cls.config.compute.allow_tenant_reuse:
-                user = admin_client.get_user_by_username(tenant['id'],
-                                                         username)
-                LOG.info('Re-using existing user %s' % user)
-            else:
-                msg = ('Unable to create isolated user %s because ' +
-                       'it already exists. If this is related to a ' +
-                       'previous test failure, try using ' +
-                       'allow_tenant_reuse in tempest.conf') % tenant_name
-                raise exceptions.Duplicate(msg)
+                resp, tenant = admin_client.create_tenant(
+                    name=tenant_name, description=tenant_desc)
+                break
+            except exceptions.Duplicate:
+                if cls.config.compute.allow_tenant_reuse:
+                    tenant = admin_client.get_tenant_by_name(tenant_name)
+                    LOG.info('Re-using existing tenant %s', tenant)
+                    break
 
+        while True:
+            try:
+                rand_name_root = rand_name(cls.__name__)
+                if cls.isolated_creds:
+                # Main user already created. Create the alt one...
+                    rand_name_root += '-alt'
+                username = rand_name_root + "-user"
+                email = rand_name_root + "@example.com"
+                resp, user = admin_client.create_user(username,
+                                                      password,
+                                                      tenant['id'],
+                                                      email)
+                break
+            except exceptions.Duplicate:
+                if cls.config.compute.allow_tenant_reuse:
+                    user = admin_client.get_user_by_username(tenant['id'],
+                                                             username)
+                    LOG.info('Re-using existing user %s', user)
+                    break
         # Store the complete creds (including UUID ids...) for later
         # but return just the username, tenant_name, password tuple
         # that the various clients will use.
diff --git a/tempest/tests/compute/images/test_image_metadata.py b/tempest/tests/compute/images/test_image_metadata.py
index 918075c..5d6439b 100644
--- a/tempest/tests/compute/images/test_image_metadata.py
+++ b/tempest/tests/compute/images/test_image_metadata.py
@@ -21,12 +21,12 @@
 from tempest.tests.compute import base
 
 
-class ImagesMetadataTest(base.BaseComputeTest):
+class ImagesMetadataTestJSON(base.BaseComputeTest):
     _interface = 'json'
 
     @classmethod
     def setUpClass(cls):
-        super(ImagesMetadataTest, cls).setUpClass()
+        super(ImagesMetadataTestJSON, cls).setUpClass()
         cls.servers_client = cls.servers_client
         cls.client = cls.images_client
 
@@ -44,10 +44,10 @@
     @classmethod
     def tearDownClass(cls):
         cls.client.delete_image(cls.image_id)
-        super(ImagesMetadataTest, cls).tearDownClass()
+        super(ImagesMetadataTestJSON, cls).tearDownClass()
 
     def setUp(self):
-        super(ImagesMetadataTest, self).setUp()
+        super(ImagesMetadataTestJSON, self).setUp()
         meta = {'key1': 'value1', 'key2': 'value2'}
         resp, _ = self.client.set_image_metadata(self.image_id, meta)
         self.assertEqual(resp.status, 200)
@@ -143,3 +143,7 @@
         # item from nonexistant image
         self.assertRaises(exceptions.NotFound,
                           self.client.delete_image_metadata_item, 999, 'key1')
+
+
+class ImagesMetadataTestXML(ImagesMetadataTestJSON):
+    _interface = 'xml'
diff --git a/tempest/tests/compute/images/test_images_oneserver.py b/tempest/tests/compute/images/test_images_oneserver.py
index 9412d39..ca3dbb5 100644
--- a/tempest/tests/compute/images/test_images_oneserver.py
+++ b/tempest/tests/compute/images/test_images_oneserver.py
@@ -41,7 +41,12 @@
         super(ImagesOneServerTestJSON, cls).setUpClass()
         cls.client = cls.images_client
         cls.servers_client = cls.servers_client
-        resp, cls.server = cls.create_server(wait_until='ACTIVE')
+
+        try:
+            resp, cls.server = cls.create_server(wait_until='ACTIVE')
+        except Exception:
+            cls.tearDownClass()
+            raise
 
         cls.image_ids = []
 
diff --git a/tempest/tests/compute/images/test_list_image_filters.py b/tempest/tests/compute/images/test_list_image_filters.py
index 0607a33..b1a6f77 100644
--- a/tempest/tests/compute/images/test_list_image_filters.py
+++ b/tempest/tests/compute/images/test_list_image_filters.py
@@ -22,12 +22,12 @@
 from tempest.tests.compute import base
 
 
-class ListImageFiltersTest(base.BaseComputeTest):
+class ListImageFiltersTestJSON(base.BaseComputeTest):
     _interface = 'json'
 
     @classmethod
     def setUpClass(cls):
-        super(ListImageFiltersTest, cls).setUpClass()
+        super(ListImageFiltersTestJSON, cls).setUpClass()
         cls.client = cls.images_client
 
         try:
@@ -76,7 +76,7 @@
         cls.client.delete_image(cls.image1_id)
         cls.client.delete_image(cls.image2_id)
         cls.client.delete_image(cls.image3_id)
-        super(ListImageFiltersTest, cls).tearDownClass()
+        super(ListImageFiltersTestJSON, cls).tearDownClass()
 
     @attr(type='negative')
     def test_get_image_not_existing(self):
@@ -151,7 +151,9 @@
         # Verify only the expected number of results are returned
         params = {'limit': '1'}
         resp, images = self.client.list_images(params)
-        self.assertEqual(1, len(images))
+        #when _interface='xml', one element for images_links in images
+        #ref: Question #224349
+        self.assertEqual(1, len([x for x in images if 'id' in x]))
 
     @attr(type='positive')
     def test_list_images_filter_by_changes_since(self):
@@ -237,3 +239,7 @@
     def test_get_nonexistant_image(self):
         # Negative test: GET on non existant image should fail
         self.assertRaises(exceptions.NotFound, self.client.get_image, 999)
+
+
+class ListImageFiltersTestXML(ListImageFiltersTestJSON):
+    _interface = 'xml'
diff --git a/tempest/tests/compute/images/test_list_images.py b/tempest/tests/compute/images/test_list_images.py
index d583a95..ec9e7bc 100644
--- a/tempest/tests/compute/images/test_list_images.py
+++ b/tempest/tests/compute/images/test_list_images.py
@@ -19,17 +19,17 @@
 from tempest.tests.compute import base
 
 
-class ListImagesTest(base.BaseComputeTest):
+class ListImagesTestJSON(base.BaseComputeTest):
     _interface = 'json'
 
     @classmethod
     def setUpClass(cls):
-        super(ListImagesTest, cls).setUpClass()
+        super(ListImagesTestJSON, cls).setUpClass()
         cls.client = cls.images_client
 
     @classmethod
     def tearDownClass(cls):
-        super(ListImagesTest, cls).tearDownClass()
+        super(ListImagesTestJSON, cls).tearDownClass()
 
     @attr(type='smoke')
     def test_get_image(self):
@@ -50,3 +50,7 @@
         resp, images = self.client.list_images_with_detail()
         found = any([i for i in images if i['id'] == self.image_ref])
         self.assertTrue(found)
+
+
+class ListImagesTestXML(ListImagesTestJSON):
+    _interface = 'xml'
diff --git a/tempest/tests/compute/servers/test_create_server.py b/tempest/tests/compute/servers/test_create_server.py
index aaab9fa..b522992 100644
--- a/tempest/tests/compute/servers/test_create_server.py
+++ b/tempest/tests/compute/servers/test_create_server.py
@@ -33,7 +33,7 @@
 class ServersTestJSON(base.BaseComputeTest):
     _interface = 'json'
     run_ssh = tempest.config.TempestConfig().compute.run_ssh
-    disk_config = None
+    disk_config = 'AUTO'
 
     @classmethod
     def setUpClass(cls):
@@ -118,18 +118,6 @@
 
 
 @attr(type='positive')
-class ServersTestAutoDisk(ServersTestJSON):
-    disk_config = 'AUTO'
-
-    @classmethod
-    def setUpClass(cls):
-        if not compute.DISK_CONFIG_ENABLED:
-            msg = "DiskConfig extension not enabled."
-            raise cls.skipException(msg)
-        super(ServersTestAutoDisk, cls).setUpClass()
-
-
-@attr(type='positive')
 class ServersTestManualDisk(ServersTestJSON):
     disk_config = 'MANUAL'
 
diff --git a/tempest/tests/compute/servers/test_disk_config.py b/tempest/tests/compute/servers/test_disk_config.py
index 2fbb876..fe1c271 100644
--- a/tempest/tests/compute/servers/test_disk_config.py
+++ b/tempest/tests/compute/servers/test_disk_config.py
@@ -22,7 +22,7 @@
 from tempest.tests.compute import base
 
 
-class TestServerDiskConfig(base.BaseComputeTest):
+class ServerDiskConfigTestJSON(base.BaseComputeTest):
     _interface = 'json'
 
     @classmethod
@@ -30,7 +30,7 @@
         if not compute.DISK_CONFIG_ENABLED:
             msg = "DiskConfig extension not enabled."
             raise cls.skipException(msg)
-        super(TestServerDiskConfig, cls).setUpClass()
+        super(ServerDiskConfigTestJSON, cls).setUpClass()
         cls.client = cls.os.servers_client
 
     @attr(type='positive')
@@ -120,3 +120,7 @@
 
         #Delete the server
         resp, body = self.client.delete_server(server['id'])
+
+
+class ServerDiskConfigTestXML(ServerDiskConfigTestJSON):
+    _interface = 'xml'
diff --git a/tempest/tests/compute/servers/test_list_server_filters.py b/tempest/tests/compute/servers/test_list_server_filters.py
index ff599fe..4d2b99f 100644
--- a/tempest/tests/compute/servers/test_list_server_filters.py
+++ b/tempest/tests/compute/servers/test_list_server_filters.py
@@ -126,11 +126,12 @@
         self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
 
     @attr(type='positive')
-    def test_list_servers_detailed_filter_by_limit(self):
+    def test_list_servers_filter_by_limit(self):
         # Verify only the expected number of servers are returned
         params = {'limit': 1}
-        resp, servers = self.client.list_servers_with_detail(params)
-        self.assertEqual(1, len(servers['servers']))
+        resp, servers = self.client.list_servers(params)
+        #when _interface='xml', one element for servers_links in servers
+        self.assertEqual(1, len([x for x in servers['servers'] if 'id' in x]))
 
     @utils.skip_unless_attr('multiple_images', 'Only one image found')
     @attr(type='positive')
diff --git a/tempest/tests/compute/servers/test_list_servers_negative.py b/tempest/tests/compute/servers/test_list_servers_negative.py
index 01b11e0..0559206 100644
--- a/tempest/tests/compute/servers/test_list_servers_negative.py
+++ b/tempest/tests/compute/servers/test_list_servers_negative.py
@@ -22,12 +22,12 @@
 from tempest.tests.compute import base
 
 
-class ListServersNegativeTest(base.BaseComputeTest):
+class ListServersNegativeTestJSON(base.BaseComputeTest):
     _interface = 'json'
 
     @classmethod
     def setUpClass(cls):
-        super(ListServersNegativeTest, cls).setUpClass()
+        super(ListServersNegativeTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
         cls.servers = []
 
@@ -138,7 +138,8 @@
         # List servers by specifying limits
         resp, body = self.client.list_servers({'limit': 1})
         self.assertEqual('200', resp['status'])
-        self.assertEqual(1, len(body['servers']))
+        #when _interface='xml', one element for servers_links in servers
+        self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
 
     def test_list_servers_by_limits_greater_than_actual_count(self):
         # List servers by specifying a greater value for limit
@@ -187,3 +188,7 @@
                   if srv['id'] in deleted_ids]
         self.assertEqual('200', resp['status'])
         self.assertEqual([], actual)
+
+
+class ListServersNegativeTestXML(ListServersNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/tests/compute/servers/test_server_addresses.py b/tempest/tests/compute/servers/test_server_addresses.py
index cb8e85e..05fa320 100644
--- a/tempest/tests/compute/servers/test_server_addresses.py
+++ b/tempest/tests/compute/servers/test_server_addresses.py
@@ -15,7 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 from tempest.test import attr
 from tempest.tests.compute import base
diff --git a/tempest/tests/compute/servers/test_server_rescue.py b/tempest/tests/compute/servers/test_server_rescue.py
index 5fc730a..29c9944 100644
--- a/tempest/tests/compute/servers/test_server_rescue.py
+++ b/tempest/tests/compute/servers/test_server_rescue.py
@@ -15,17 +15,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import base64
-import time
-
 import testtools
 
 from tempest.common.utils.data_utils import rand_name
-from tempest.common.utils.linux.remote_client import RemoteClient
 import tempest.config
 from tempest import exceptions
 from tempest.test import attr
-from tempest.tests import compute
 from tempest.tests.compute import base
 
 
@@ -112,6 +107,11 @@
     def _delete(self, volume_id):
         self.volumes_extensions_client.delete_volume(volume_id)
 
+    def _unrescue(self, server_id):
+        resp, body = self.servers_client.unrescue_server(server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+
     @attr(type='smoke')
     def test_rescue_unrescue_instance(self):
         resp, body = self.servers_client.rescue_server(
@@ -123,9 +123,8 @@
         self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
 
     @attr(type='negative')
-    @testtools.skip("Skipped until Bug #1126163 is resolved")
     def test_rescued_vm_reboot(self):
-        self.assertRaises(exceptions.BadRequest, self.servers_client.reboot,
+        self.assertRaises(exceptions.Duplicate, self.servers_client.reboot,
                           self.rescue_id, 'HARD')
 
     @attr(type='negative')
@@ -135,37 +134,21 @@
                           self.rescue_id,
                           self.image_ref_alt)
 
-    @attr(type='positive')
-    @testtools.skip("Skipped due to Bug #1126187")
+    @attr(type='negative')
     def test_rescued_vm_attach_volume(self):
-        client = self.volumes_extensions_client
-
         # Rescue the server
         self.servers_client.rescue_server(self.server_id, self.password)
         self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
+        self.addCleanup(self._unrescue, self.server_id)
 
         # Attach the volume to the server
-        resp, body = \
-        self.servers_client.attach_volume(self.server_id,
-                                          self.volume_to_attach['id'],
-                                          device='/dev/%s' % self.device)
-        self.assertEqual(200, resp.status)
-        client.wait_for_volume_status(self.volume_to_attach['id'], 'in-use')
+        self.assertRaises(exceptions.Duplicate,
+                          self.servers_client.attach_volume,
+                          self.server_id,
+                          self.volume_to_attach['id'],
+                          device='/dev/%s' % self.device)
 
-        # Detach the volume to the server
-        resp, body = \
-        self.servers_client.detach_volume(self.server_id,
-                                          self.volume_to_attach['id'])
-        self.assertEqual(202, resp.status)
-        client.wait_for_volume_status(self.volume_to_attach['id'], 'available')
-
-        # Unrescue the server
-        resp, body = self.servers_client.unrescue_server(self.server_id)
-        self.assertEqual(202, resp.status)
-        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
-
-    @attr(type='positive')
-    @testtools.skip("Skipped until Bug #1126187 is resolved")
+    @attr(type='negative')
     def test_rescued_vm_detach_volume(self):
         # Attach the volume to the server
         self.servers_client.attach_volume(self.server_id,
@@ -177,19 +160,13 @@
         # Rescue the server
         self.servers_client.rescue_server(self.server_id, self.password)
         self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
+        self.addCleanup(self._unrescue, self.server_id)
 
-        # Detach the volume to the server
-        resp, body = \
-        self.servers_client.detach_volume(self.server_id,
-                                          self.volume_to_detach['id'])
-        self.assertEqual(202, resp.status)
-        client = self.volumes_extensions_client
-        client.wait_for_volume_status(self.volume_to_detach['id'], 'available')
-
-        # Unrescue the server
-        resp, body = self.servers_client.unrescue_server(self.server_id)
-        self.assertEqual(202, resp.status)
-        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+        # Detach the volume from the server expecting failure
+        self.assertRaises(exceptions.Duplicate,
+                          self.servers_client.detach_volume,
+                          self.server_id,
+                          self.volume_to_detach['id'])
 
     @attr(type='positive')
     def test_rescued_vm_associate_dissociate_floating_ip(self):
diff --git a/tempest/tests/compute/test_authorization.py b/tempest/tests/compute/test_authorization.py
index 4ca197a..91cf39f 100644
--- a/tempest/tests/compute/test_authorization.py
+++ b/tempest/tests/compute/test_authorization.py
@@ -15,8 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
-
 from tempest import clients
 from tempest.common.utils.data_utils import parse_image_id
 from tempest.common.utils.data_utils import rand_name
@@ -25,7 +23,7 @@
 from tempest.tests.compute import base
 
 
-class AuthorizationTest(base.BaseComputeTest):
+class AuthorizationTestJSON(base.BaseComputeTest):
     _interface = 'json'
 
     @classmethod
@@ -34,7 +32,7 @@
             msg = "Need >1 user"
             raise cls.skipException(msg)
 
-        super(AuthorizationTest, cls).setUpClass()
+        super(AuthorizationTestJSON, cls).setUpClass()
 
         cls.client = cls.os.servers_client
         cls.images_client = cls.os.images_client
@@ -73,18 +71,15 @@
 
         name = rand_name('security')
         description = rand_name('description')
-        resp, cls.security_group = \
-        cls.security_client.create_security_group(name, description)
+        resp, cls.security_group = cls.security_client.create_security_group(
+            name, description)
 
         parent_group_id = cls.security_group['id']
         ip_protocol = 'tcp'
         from_port = 22
         to_port = 22
-        resp, cls.rule =\
-        cls.security_client.create_security_group_rule(
-                                        parent_group_id,
-                                        ip_protocol, from_port,
-                                        to_port)
+        resp, cls.rule = cls.security_client.create_security_group_rule(
+            parent_group_id, ip_protocol, from_port, to_port)
 
     @classmethod
     def tearDownClass(cls):
@@ -92,7 +87,7 @@
             cls.images_client.delete_image(cls.image['id'])
             cls.keypairs_client.delete_keypair(cls.keypairname)
             cls.security_client.delete_security_group(cls.security_group['id'])
-        super(AuthorizationTest, cls).tearDownClass()
+        super(AuthorizationTestJSON, cls).tearDownClass()
 
     def test_get_server_for_alt_account_fails(self):
         # A GET request for a server on another user's account should fail
@@ -280,7 +275,7 @@
             self.alt_security_client.base_url = self.saved_base_url
             if resp['status'] is not None:
                 self.alt_security_client.delete_security_group_rule(
-                                        body['id'])  # BUG
+                    body['id'])  # BUG
                 self.fail("Create security group rule request should not "
                           "happen if the tenant id does not match the"
                           " current user")
@@ -354,3 +349,7 @@
         self.assertRaises(exceptions.NotFound,
                           self.alt_client.get_console_output,
                           self.server['id'], 10)
+
+
+class AuthorizationTestXML(AuthorizationTestJSON):
+    _interface = 'xml'
diff --git a/tempest/tests/compute/test_quotas.py b/tempest/tests/compute/test_quotas.py
index 233d639..a84d041 100644
--- a/tempest/tests/compute/test_quotas.py
+++ b/tempest/tests/compute/test_quotas.py
@@ -33,14 +33,11 @@
 
     @attr(type='smoke')
     def test_get_default_quotas(self):
-        # Tempest two step
-        self.skipTest('Skipped until the Bug 1125468 is resolved')
-
         # User can get the default quota set for it's tenant
         expected_quota_set = {'injected_file_content_bytes': 10240,
                               'metadata_items': 128, 'injected_files': 5,
                               'ram': 51200, 'floating_ips': 10,
-                              'fixed_ips': 10, 'key_pairs': 100,
+                              'fixed_ips': -1, 'key_pairs': 100,
                               'injected_file_path_bytes': 255, 'instances': 10,
                               'security_group_rules': 20, 'cores': 20,
                               'id': self.tenant_id, 'security_groups': 10}
diff --git a/tempest/tests/compute/volumes/test_attach_volume.py b/tempest/tests/compute/volumes/test_attach_volume.py
index d9abe41..1b52ccf 100644
--- a/tempest/tests/compute/volumes/test_attach_volume.py
+++ b/tempest/tests/compute/volumes/test_attach_volume.py
@@ -17,7 +17,6 @@
 
 import testtools
 
-from tempest.common.utils.data_utils import rand_name
 from tempest.common.utils.linux.remote_client import RemoteClient
 import tempest.config
 from tempest.test import attr
@@ -92,7 +91,7 @@
             self.assertTrue(self.device in partitions)
 
             self._detach(server['id'], volume['id'])
-            attached = False
+            self.attached = False
 
             self.servers_client.stop(server['id'])
             self.servers_client.wait_for_server_status(server['id'], 'SHUTOFF')
diff --git a/tempest/tests/identity/admin/test_users.py b/tempest/tests/identity/admin/test_users.py
index 80c6fc9..0573b21 100644
--- a/tempest/tests/identity/admin/test_users.py
+++ b/tempest/tests/identity/admin/test_users.py
@@ -326,17 +326,9 @@
         invalid_id.append(rand_name("dddd@#%%^$"))
         invalid_id.append('!@#()$%^&*?<>{}[]')
         #List the users with invalid tenant id
-        fail = list()
         for invalid in invalid_id:
-            try:
-                resp, body = self.client.list_users_for_tenant(invalid)
-            except exceptions.NotFound:
-                pass
-            else:
-                fail.append(invalid)
-        if len(fail) != 0:
-            self.fail('Should raise Not Found when list users with invalid'
-                      'tenant ids %s' % fail)
+            self.assertRaises(exceptions.NotFound,
+                              self.client.list_users_for_tenant, invalid)
 
 
 class UsersTestXML(UsersTestJSON):
diff --git a/tempest/tests/image/base.py b/tempest/tests/image/base.py
index 65d81b6..f12e957 100644
--- a/tempest/tests/image/base.py
+++ b/tempest/tests/image/base.py
@@ -15,7 +15,6 @@
 #    under the License.
 
 import logging
-import time
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
diff --git a/tempest/tests/image/v1/test_images.py b/tempest/tests/image/v1/test_images.py
index af09b79..1b6fa10 100644
--- a/tempest/tests/image/v1/test_images.py
+++ b/tempest/tests/image/v1/test_images.py
@@ -17,7 +17,6 @@
 
 import cStringIO as StringIO
 
-from tempest import clients
 from tempest import exceptions
 from tempest.test import attr
 from tempest.tests.image import base
@@ -68,13 +67,55 @@
                                        container_format='bare',
                                        disk_format='raw', is_public=True,
                                        location='http://example.com'
-                                                '/someimage.iso')
+                                                '/someimage.iso',
+                                       properties={'key1': 'value1',
+                                                   'key2': 'value2'})
         self.assertTrue('id' in body)
         image_id = body.get('id')
         self.created_images.append(image_id)
         self.assertEqual('New Remote Image', body.get('name'))
         self.assertTrue(body.get('is_public'))
         self.assertEqual('active', body.get('status'))
+        properties = body.get('properties')
+        self.assertEqual(properties['key1'], 'value1')
+        self.assertEqual(properties['key2'], 'value2')
+
+    def test_register_http_image(self):
+        container_client = self.os.container_client
+        object_client = self.os.object_client
+        container_name = "image_container"
+        object_name = "test_image.img"
+        container_client.create_container(container_name)
+        self.addCleanup(container_client.delete_container, container_name)
+        cont_headers = {'X-Container-Read': '.r:*'}
+        resp, _ = container_client.update_container_metadata(
+                    container_name,
+                    metadata=cont_headers,
+                    metadata_prefix='')
+        self.assertEqual(resp['status'], '204')
+
+        data = "TESTIMAGE"
+        resp, _ = object_client.create_object(container_name,
+                                              object_name, data)
+        self.addCleanup(object_client.delete_object, container_name,
+                        object_name)
+        self.assertEqual(resp['status'], '201')
+        object_url = '/'.join((object_client.base_url,
+                               container_name,
+                               object_name))
+        resp, body = self.create_image(name='New Http Image',
+                                       container_format='bare',
+                                       disk_format='raw', is_public=True,
+                                       copy_from=object_url)
+        self.assertTrue('id' in body)
+        image_id = body.get('id')
+        self.created_images.append(image_id)
+        self.assertEqual('New Http Image', body.get('name'))
+        self.assertTrue(body.get('is_public'))
+        self.client.wait_for_image_status(image_id, 'active')
+        resp, body = self.client.get_image(image_id)
+        self.assertEqual(resp['status'], '200')
+        self.assertEqual(body, data)
 
 
 class ListImagesTest(base.BaseV1ImageTest):
diff --git a/tempest/tests/image/v2/test_images.py b/tempest/tests/image/v2/test_images.py
index 19a7a95..eddeb78 100644
--- a/tempest/tests/image/v2/test_images.py
+++ b/tempest/tests/image/v2/test_images.py
@@ -19,7 +19,6 @@
 import cStringIO as StringIO
 import random
 
-from tempest import clients
 from tempest import exceptions
 from tempest.test import attr
 from tempest.tests.image import base
diff --git a/tempest/tests/network/base.py b/tempest/tests/network/base.py
index 1b09513..e0e40cb 100644
--- a/tempest/tests/network/base.py
+++ b/tempest/tests/network/base.py
@@ -15,31 +15,73 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import netaddr
 
 from tempest import clients
 from tempest.common.utils.data_utils import rand_name
+from tempest import exceptions
 import tempest.test
 
 
 class BaseNetworkTest(tempest.test.BaseTestCase):
 
+    """
+    Base class for the Quantum tests that use the Tempest Quantum REST client
+
+    Per the Quantum API Guide, API v1.x was removed from the source code tree
+    (docs.openstack.org/api/openstack-network/2.0/content/Overview-d1e71.html)
+    Therefore, v2.x of the Quantum API is assumed. It is also assumed that the
+    following options are defined in the [network] section of etc/tempest.conf:
+
+        tenant_network_cidr with a block of cidr's from which smaller blocks
+        can be allocated for tenant networks
+
+        tenant_network_mask_bits with the mask bits to be used to partition the
+        block defined by tenant-network_cidr
+    """
+
     @classmethod
     def setUpClass(cls):
         os = clients.Manager()
-
-        if not os.config.network.quantum_available:
+        cls.network_cfg = os.config.network
+        if not cls.network_cfg.quantum_available:
             raise cls.skipException("Quantum support is required")
+        cls.client = os.network_client
+        cls.networks = []
+        cls.subnets = []
 
     @classmethod
     def tearDownClass(cls):
+        for subnet in cls.subnets:
+            cls.client.delete_subnet(subnet['id'])
         for network in cls.networks:
             cls.client.delete_network(network['id'])
 
-    def create_network(self, network_name=None):
+    @classmethod
+    def create_network(cls, network_name=None):
         """Wrapper utility that returns a test network."""
-        network_name = network_name or rand_name('test-network')
+        network_name = network_name or rand_name('test-network-')
 
-        resp, body = self.client.create_network(network_name)
+        resp, body = cls.client.create_network(network_name)
         network = body['network']
-        self.networks.append(network)
+        cls.networks.append(network)
         return network
+
+    @classmethod
+    def create_subnet(cls, network):
+        """Wrapper utility that returns a test subnet."""
+        cidr = netaddr.IPNetwork(cls.network_cfg.tenant_network_cidr)
+        mask_bits = cls.network_cfg.tenant_network_mask_bits
+        # Find a cidr that is not in use yet and create a subnet with it
+        for subnet_cidr in cidr.subnet(mask_bits):
+            try:
+                resp, body = cls.client.create_subnet(network['id'],
+                                                      str(subnet_cidr))
+                break
+            except exceptions.BadRequest as e:
+                is_overlapping_cidr = 'overlaps with another subnet' in str(e)
+                if not is_overlapping_cidr:
+                    raise
+        subnet = body['subnet']
+        cls.subnets.append(subnet)
+        return subnet
diff --git a/tempest/tests/network/common.py b/tempest/tests/network/common.py
new file mode 100644
index 0000000..0bb806f
--- /dev/null
+++ b/tempest/tests/network/common.py
@@ -0,0 +1,316 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import subprocess
+
+import netaddr
+
+from quantumclient.common import exceptions as exc
+from tempest.common.utils.data_utils import rand_name
+from tempest import smoke
+from tempest import test
+
+
+class AttributeDict(dict):
+
+    """
+    Provide attribute access (dict.key) to dictionary values.
+    """
+
+    def __getattr__(self, name):
+        """Allow attribute access for all keys in the dict."""
+        if name in self:
+            return self[name]
+        return super(AttributeDict, self).__getattribute__(name)
+
+
+class DeletableResource(AttributeDict):
+
+    """
+    Support deletion of quantum resources (networks, subnets) via a
+    delete() method, as is supported by keystone and nova resources.
+    """
+
+    def __init__(self, *args, **kwargs):
+        self.client = kwargs.pop('client', None)
+        super(DeletableResource, self).__init__(*args, **kwargs)
+
+    def __str__(self):
+        return '<%s id="%s" name="%s">' % (self.__class__.__name__,
+                                           self.id, self.name)
+
+    def delete(self):
+        raise NotImplemented()
+
+
+class DeletableNetwork(DeletableResource):
+
+    def delete(self):
+        self.client.delete_network(self.id)
+
+
+class DeletableSubnet(DeletableResource):
+
+    _router_ids = set()
+
+    def add_to_router(self, router_id):
+        self._router_ids.add(router_id)
+        body = dict(subnet_id=self.id)
+        self.client.add_interface_router(router_id, body=body)
+
+    def delete(self):
+        for router_id in self._router_ids.copy():
+            body = dict(subnet_id=self.id)
+            self.client.remove_interface_router(router_id, body=body)
+            self._router_ids.remove(router_id)
+        self.client.delete_subnet(self.id)
+
+
+class DeletableRouter(DeletableResource):
+
+    def add_gateway(self, network_id):
+        body = dict(network_id=network_id)
+        self.client.add_gateway_router(self.id, body=body)
+
+    def delete(self):
+        self.client.remove_gateway_router(self.id)
+        self.client.delete_router(self.id)
+
+
+class DeletableFloatingIp(DeletableResource):
+
+    def delete(self):
+        self.client.delete_floatingip(self.id)
+
+
+class DeletablePort(DeletableResource):
+
+    def delete(self):
+        self.client.delete_port(self.id)
+
+
+class TestNetworkSmokeCommon(smoke.DefaultClientSmokeTest):
+    """
+    Base class for network smoke tests
+    """
+
+    @classmethod
+    def check_preconditions(cls):
+        if (cls.config.network.quantum_available):
+            cls.enabled = True
+            #verify that quantum_available is telling the truth
+            try:
+                cls.network_client.list_networks()
+            except exc.EndpointNotFound:
+                cls.enabled = False
+                raise
+        else:
+            cls.enabled = False
+            msg = 'Quantum not available'
+            raise cls.skipException(msg)
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestNetworkSmokeCommon, cls).setUpClass()
+        cfg = cls.config.network
+        cls.tenant_id = cls.manager._get_identity_client(
+            cls.config.identity.username,
+            cls.config.identity.password,
+            cls.config.identity.tenant_name).tenant_id
+
+    def _create_keypair(self, client, namestart='keypair-smoke-'):
+        kp_name = rand_name(namestart)
+        keypair = client.keypairs.create(kp_name)
+        try:
+            self.assertEqual(keypair.id, kp_name)
+            self.set_resource(kp_name, keypair)
+        except AttributeError:
+            self.fail("Keypair object not successfully created.")
+        return keypair
+
+    def _create_security_group(self, client, namestart='secgroup-smoke-'):
+        # Create security group
+        sg_name = rand_name(namestart)
+        sg_desc = sg_name + " description"
+        secgroup = client.security_groups.create(sg_name, sg_desc)
+        try:
+            self.assertEqual(secgroup.name, sg_name)
+            self.assertEqual(secgroup.description, sg_desc)
+            self.set_resource(sg_name, secgroup)
+        except AttributeError:
+            self.fail("SecurityGroup object not successfully created.")
+
+        # Add rules to the security group
+        rulesets = [
+            {
+                # ssh
+                'ip_protocol': 'tcp',
+                'from_port': 22,
+                'to_port': 22,
+                'cidr': '0.0.0.0/0',
+                'group_id': secgroup.id
+            },
+            {
+                # ping
+                'ip_protocol': 'icmp',
+                'from_port': -1,
+                'to_port': -1,
+                'cidr': '0.0.0.0/0',
+                'group_id': secgroup.id
+            }
+        ]
+        for ruleset in rulesets:
+            try:
+                client.security_group_rules.create(secgroup.id, **ruleset)
+            except Exception:
+                self.fail("Failed to create rule in security group.")
+
+        return secgroup
+
+    def _create_network(self, tenant_id, namestart='network-smoke-'):
+        name = rand_name(namestart)
+        body = dict(
+            network=dict(
+                name=name,
+                tenant_id=tenant_id,
+            ),
+        )
+        result = self.network_client.create_network(body=body)
+        network = DeletableNetwork(client=self.network_client,
+                                   **result['network'])
+        self.assertEqual(network.name, name)
+        self.set_resource(name, network)
+        return network
+
+    def _list_networks(self):
+        nets = self.network_client.list_networks()
+        return nets['networks']
+
+    def _list_subnets(self):
+        subnets = self.network_client.list_subnets()
+        return subnets['subnets']
+
+    def _list_routers(self):
+        routers = self.network_client.list_routers()
+        return routers['routers']
+
+    def _create_subnet(self, network, namestart='subnet-smoke-'):
+        """
+        Create a subnet for the given network within the cidr block
+        configured for tenant networks.
+        """
+        cfg = self.config.network
+        tenant_cidr = netaddr.IPNetwork(cfg.tenant_network_cidr)
+        result = None
+        # Repeatedly attempt subnet creation with sequential cidr
+        # blocks until an unallocated block is found.
+        for subnet_cidr in tenant_cidr.subnet(cfg.tenant_network_mask_bits):
+            body = dict(
+                subnet=dict(
+                    ip_version=4,
+                    network_id=network.id,
+                    tenant_id=network.tenant_id,
+                    cidr=str(subnet_cidr),
+                ),
+            )
+            try:
+                result = self.network_client.create_subnet(body=body)
+                break
+            except exc.QuantumClientException as e:
+                is_overlapping_cidr = 'overlaps with another subnet' in str(e)
+                if not is_overlapping_cidr:
+                    raise
+        self.assertIsNotNone(result, 'Unable to allocate tenant network')
+        subnet = DeletableSubnet(client=self.network_client,
+                                 **result['subnet'])
+        self.assertEqual(subnet.cidr, str(subnet_cidr))
+        self.set_resource(rand_name(namestart), subnet)
+        return subnet
+
+    def _create_port(self, network, namestart='port-quotatest-'):
+        name = rand_name(namestart)
+        body = dict(
+            port=dict(name=name,
+                      network_id=network.id,
+                      tenant_id=network.tenant_id))
+        try:
+            result = self.network_client.create_port(body=body)
+        except Exception as e:
+            raise
+        self.assertIsNotNone(result, 'Unable to allocate port')
+        port = DeletablePort(client=self.network_client,
+                             **result['port'])
+        self.set_resource(name, port)
+        return port
+
+    def _create_server(self, client, network, name, key_name, security_groups):
+        flavor_id = self.config.compute.flavor_ref
+        base_image_id = self.config.compute.image_ref
+        create_kwargs = {
+            'nics': [
+                {'net-id': network.id},
+            ],
+            'key_name': key_name,
+            'security_groups': security_groups,
+        }
+        server = client.servers.create(name, base_image_id, flavor_id,
+                                       **create_kwargs)
+        try:
+            self.assertEqual(server.name, name)
+            self.set_resource(name, server)
+        except AttributeError:
+            self.fail("Server not successfully created.")
+        self.status_timeout(client.servers, server.id, 'ACTIVE')
+        # The instance retrieved on creation is missing network
+        # details, necessitating retrieval after it becomes active to
+        # ensure correct details.
+        server = client.servers.get(server.id)
+        self.set_resource(name, server)
+        return server
+
+    def _create_floating_ip(self, server, external_network_id):
+        result = self.network_client.list_ports(device_id=server.id)
+        ports = result.get('ports', [])
+        self.assertEqual(len(ports), 1,
+                         "Unable to determine which port to target.")
+        port_id = ports[0]['id']
+        body = dict(
+            floatingip=dict(
+                floating_network_id=external_network_id,
+                port_id=port_id,
+                tenant_id=server.tenant_id,
+            )
+        )
+        result = self.network_client.create_floatingip(body=body)
+        floating_ip = DeletableFloatingIp(client=self.network_client,
+                                          **result['floatingip'])
+        self.set_resource(rand_name('floatingip-'), floating_ip)
+        return floating_ip
+
+    def _ping_ip_address(self, ip_address):
+        cmd = ['ping', '-c1', '-w1', ip_address]
+
+        def ping():
+            proc = subprocess.Popen(cmd,
+                                    stdout=subprocess.PIPE,
+                                    stderr=subprocess.PIPE)
+            proc.wait()
+            if proc.returncode == 0:
+                return True
+
+        # TODO(mnewby) Allow configuration of execution and sleep duration.
+        return test.call_until_true(ping, 20, 1)
diff --git a/tempest/tests/network/test_network_basic_ops.py b/tempest/tests/network/test_network_basic_ops.py
index aed368e..a38a5c0 100644
--- a/tempest/tests/network/test_network_basic_ops.py
+++ b/tempest/tests/network/test_network_basic_ops.py
@@ -1,6 +1,7 @@
 # vim: tabstop=4 shiftwidth=4 softtabstop=4
 
 # Copyright 2012 OpenStack, LLC
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -15,94 +16,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
-import subprocess
-
-import netaddr
-
-from quantumclient.common import exceptions as exc
-
 from tempest.common.utils.data_utils import rand_name
-from tempest import smoke
-from tempest import test
+from tempest.tests.network.common import DeletableRouter
+from tempest.tests.network.common import TestNetworkSmokeCommon
 
 
-LOG = logging.getLogger(__name__)
-
-
-class AttributeDict(dict):
-
-    """
-    Provide attribute access (dict.key) to dictionary values.
-    """
-
-    def __getattr__(self, name):
-        """Allow attribute access for all keys in the dict."""
-        if name in self:
-            return self[name]
-        return super(AttributeDict, self).__getattribute__(name)
-
-
-class DeletableResource(AttributeDict):
-
-    """
-    Support deletion of quantum resources (networks, subnets) via a
-    delete() method, as is supported by keystone and nova resources.
-    """
-
-    def __init__(self, *args, **kwargs):
-        self.client = kwargs.pop('client', None)
-        super(DeletableResource, self).__init__(*args, **kwargs)
-
-    def __str__(self):
-        return '<%s id="%s" name="%s">' % (self.__class__.__name__,
-                                           self.id, self.name)
-
-    def delete(self):
-        raise NotImplemented()
-
-
-class DeletableNetwork(DeletableResource):
-
-    def delete(self):
-        self.client.delete_network(self.id)
-
-
-class DeletableSubnet(DeletableResource):
-
-    _router_ids = set()
-
-    def add_to_router(self, router_id):
-        self._router_ids.add(router_id)
-        body = dict(subnet_id=self.id)
-        self.client.add_interface_router(router_id, body=body)
-
-    def delete(self):
-        for router_id in self._router_ids.copy():
-            body = dict(subnet_id=self.id)
-            self.client.remove_interface_router(router_id, body=body)
-            self._router_ids.remove(router_id)
-        self.client.delete_subnet(self.id)
-
-
-class DeletableRouter(DeletableResource):
-
-    def add_gateway(self, network_id):
-        body = dict(network_id=network_id)
-        self.client.add_gateway_router(self.id, body=body)
-
-    def delete(self):
-        self.client.remove_gateway_router(self.id)
-        self.client.delete_router(self.id)
-
-
-class DeletableFloatingIp(DeletableResource):
-
-    def delete(self):
-        self.client.delete_floatingip(self.id)
-
-
-class TestNetworkBasicOps(smoke.DefaultClientSmokeTest):
+class TestNetworkBasicOps(TestNetworkSmokeCommon):
 
     """
     This smoke test suite assumes that Nova has been configured to
@@ -165,19 +84,12 @@
 
     @classmethod
     def check_preconditions(cls):
+        super(TestNetworkBasicOps, cls).check_preconditions()
         cfg = cls.config.network
-        msg = None
         if not (cfg.tenant_networks_reachable or cfg.public_network_id):
             msg = ('Either tenant_networks_reachable must be "true", or '
                    'public_network_id must be defined.')
-        else:
-            try:
-                cls.network_client.list_networks()
-            except exc.QuantumClientException:
-                msg = 'Unable to connect to Quantum service.'
-
-        cls.enabled = not bool(msg)
-        if msg:
+            cls.enabled = False
             raise cls.skipException(msg)
 
     @classmethod
@@ -198,55 +110,6 @@
         cls.servers = []
         cls.floating_ips = {}
 
-    def _create_keypair(self, client):
-        kp_name = rand_name('keypair-smoke-')
-        keypair = client.keypairs.create(kp_name)
-        try:
-            self.assertEqual(keypair.id, kp_name)
-            self.set_resource(kp_name, keypair)
-        except AttributeError:
-            self.fail("Keypair object not successfully created.")
-        return keypair
-
-    def _create_security_group(self, client):
-        # Create security group
-        sg_name = rand_name('secgroup-smoke-')
-        sg_desc = sg_name + " description"
-        secgroup = client.security_groups.create(sg_name, sg_desc)
-        try:
-            self.assertEqual(secgroup.name, sg_name)
-            self.assertEqual(secgroup.description, sg_desc)
-            self.set_resource(sg_name, secgroup)
-        except AttributeError:
-            self.fail("SecurityGroup object not successfully created.")
-
-        # Add rules to the security group
-        rulesets = [
-            {
-                # ssh
-                'ip_protocol': 'tcp',
-                'from_port': 22,
-                'to_port': 22,
-                'cidr': '0.0.0.0/0',
-                'group_id': secgroup.id
-            },
-            {
-                # ping
-                'ip_protocol': 'icmp',
-                'from_port': -1,
-                'to_port': -1,
-                'cidr': '0.0.0.0/0',
-                'group_id': secgroup.id
-            }
-        ]
-        for ruleset in rulesets:
-            try:
-                client.security_group_rules.create(secgroup.id, **ruleset)
-            except Exception:
-                self.fail("Failed to create rule in security group.")
-
-        return secgroup
-
     def _get_router(self, tenant_id):
         """Retrieve a router for the given tenant id.
 
@@ -270,8 +133,8 @@
             raise Exception("Neither of 'public_router_id' or "
                             "'public_network_id' has been defined.")
 
-    def _create_router(self, tenant_id):
-        name = rand_name('router-smoke-')
+    def _create_router(self, tenant_id, namestart='router-smoke-'):
+        name = rand_name(namestart)
         body = dict(
             router=dict(
                 name=name,
@@ -286,124 +149,6 @@
         self.set_resource(name, router)
         return router
 
-    def _create_network(self, tenant_id):
-        name = rand_name('network-smoke-')
-        body = dict(
-            network=dict(
-                name=name,
-                tenant_id=tenant_id,
-            ),
-        )
-        result = self.network_client.create_network(body=body)
-        network = DeletableNetwork(client=self.network_client,
-                                   **result['network'])
-        self.assertEqual(network.name, name)
-        self.set_resource(name, network)
-        return network
-
-    def _list_networks(self):
-        nets = self.network_client.list_networks()
-        return nets['networks']
-
-    def _list_subnets(self):
-        subnets = self.network_client.list_subnets()
-        return subnets['subnets']
-
-    def _list_routers(self):
-        routers = self.network_client.list_routers()
-        return routers['routers']
-
-    def _create_subnet(self, network):
-        """
-        Create a subnet for the given network within the cidr block
-        configured for tenant networks.
-        """
-        cfg = self.config.network
-        tenant_cidr = netaddr.IPNetwork(cfg.tenant_network_cidr)
-        result = None
-        # Repeatedly attempt subnet creation with sequential cidr
-        # blocks until an unallocated block is found.
-        for subnet_cidr in tenant_cidr.subnet(cfg.tenant_network_mask_bits):
-            body = dict(
-                subnet=dict(
-                ip_version=4,
-                network_id=network.id,
-                tenant_id=network.tenant_id,
-                cidr=str(subnet_cidr),
-                ),
-            )
-            try:
-                result = self.network_client.create_subnet(body=body)
-                break
-            except exc.QuantumClientException as e:
-                is_overlapping_cidr = 'overlaps with another subnet' in str(e)
-                if not is_overlapping_cidr:
-                    raise
-        self.assertIsNotNone(result, 'Unable to allocate tenant network')
-        subnet = DeletableSubnet(client=self.network_client,
-                                 **result['subnet'])
-        self.assertEqual(subnet.cidr, str(subnet_cidr))
-        self.set_resource(rand_name('subnet-smoke-'), subnet)
-        return subnet
-
-    def _create_server(self, client, network, name, key_name, security_groups):
-        flavor_id = self.config.compute.flavor_ref
-        base_image_id = self.config.compute.image_ref
-        create_kwargs = {
-            'nics': [
-                {'net-id': network.id},
-            ],
-            'key_name': key_name,
-            'security_groups': security_groups,
-        }
-        server = client.servers.create(name, base_image_id, flavor_id,
-                                       **create_kwargs)
-        try:
-            self.assertEqual(server.name, name)
-            self.set_resource(name, server)
-        except AttributeError:
-            self.fail("Server not successfully created.")
-        self.status_timeout(client.servers, server.id, 'ACTIVE')
-        # The instance retrieved on creation is missing network
-        # details, necessitating retrieval after it becomes active to
-        # ensure correct details.
-        server = client.servers.get(server.id)
-        self.set_resource(name, server)
-        return server
-
-    def _create_floating_ip(self, server, external_network_id):
-        result = self.network_client.list_ports(device_id=server.id)
-        ports = result.get('ports', [])
-        self.assertEqual(len(ports), 1,
-                         "Unable to determine which port to target.")
-        port_id = ports[0]['id']
-        body = dict(
-            floatingip=dict(
-                floating_network_id=external_network_id,
-                port_id=port_id,
-                tenant_id=server.tenant_id,
-            )
-        )
-        result = self.network_client.create_floatingip(body=body)
-        floating_ip = DeletableFloatingIp(client=self.network_client,
-                                          **result['floatingip'])
-        self.set_resource(rand_name('floatingip-'), floating_ip)
-        return floating_ip
-
-    def _ping_ip_address(self, ip_address):
-        cmd = ['ping', '-c1', '-w1', ip_address]
-
-        def ping():
-            proc = subprocess.Popen(cmd,
-                                    stdout=subprocess.PIPE,
-                                    stderr=subprocess.PIPE)
-            proc.wait()
-            if proc.returncode == 0:
-                return True
-
-        # TODO(mnewby) Allow configuration of execution and sleep duration.
-        return test.call_until_true(ping, 20, 1)
-
     def test_001_create_keypairs(self):
         self.keypairs[self.tenant_id] = self._create_keypair(
             self.compute_client)
@@ -428,31 +173,21 @@
         seen_names = [n['name'] for n in seen_nets]
         seen_ids = [n['id'] for n in seen_nets]
         for mynet in self.networks:
-            assert mynet.name in seen_names, \
-            "Did not see expected network with name %s" % mynet.name
-            assert mynet.id in seen_ids, \
-            "Did not see expected network with id %s" % mynet.id
+            self.assertIn(mynet.name, seen_names)
+            self.assertIn(mynet.id, seen_ids)
         seen_subnets = self._list_subnets()
         seen_net_ids = [n['network_id'] for n in seen_subnets]
         seen_subnet_ids = [n['id'] for n in seen_subnets]
         for mynet in self.networks:
-            assert mynet.id in seen_net_ids, \
-            "Did not see subnet belonging to network %s/%s" % \
-            (mynet.name, mynet.id)
+            self.assertIn(mynet.id, seen_net_ids)
         for mysubnet in self.subnets:
-            assert mysubnet.id in seen_subnet_ids, \
-            "Did not see expected subnet with id %s" % \
-            mysubnet.id
+            self.assertIn(mysubnet.id, seen_subnet_ids)
         seen_routers = self._list_routers()
         seen_router_ids = [n['id'] for n in seen_routers]
         seen_router_names = [n['name'] for n in seen_routers]
         for myrouter in self.routers:
-            assert myrouter.name in seen_router_names, \
-            "Did not see expected router with name %s" % \
-            myrouter.name
-            assert myrouter.id in seen_router_ids, \
-            "Did not see expected router with id %s" % \
-            myrouter.id
+            self.assertIn(myrouter.name, seen_router_names)
+            self.assertIn(myrouter.id, seen_router_ids)
 
     def test_005_create_servers(self):
         if not (self.keypairs or self.security_groups or self.networks):
diff --git a/tempest/tests/network/test_network_quota_basic.py b/tempest/tests/network/test_network_quota_basic.py
new file mode 100644
index 0000000..eaec708
--- /dev/null
+++ b/tempest/tests/network/test_network_quota_basic.py
@@ -0,0 +1,92 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from quantumclient.common import exceptions as exc
+from tempest.tests.network.common import TestNetworkSmokeCommon
+
+MAX_REASONABLE_ITERATIONS = 51  # more than enough. Default for port is 50.
+
+
+class TestNetworkQuotaBasic(TestNetworkSmokeCommon):
+    """
+    This test suite contains tests that each loop trying to grab a
+    particular resource until a quota limit is hit.
+    For sanity, there is a maximum number of iterations - if this is hit
+    the test fails. Covers network, subnet, port.
+    """
+
+    @classmethod
+    def check_preconditions(cls):
+        super(TestNetworkQuotaBasic, cls).check_preconditions()
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestNetworkQuotaBasic, cls).setUpClass()
+        cls.check_preconditions()
+        cls.networks = []
+        cls.subnets = []
+        cls.ports = []
+
+    def test_create_network_until_quota_hit(self):
+        hit_limit = False
+        for n in xrange(MAX_REASONABLE_ITERATIONS):
+            try:
+                self.networks.append(
+                    self._create_network(self.tenant_id,
+                                         namestart='network-quotatest-'))
+            except exc.QuantumClientException as e:
+                if (e.status_code != 409):
+                    raise
+                hit_limit = True
+                break
+        self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
+
+    def test_create_subnet_until_quota_hit(self):
+        if not self.networks:
+            self.networks.append(
+                self._create_network(self.tenant_id,
+                                     namestart='network-quotatest-'))
+        hit_limit = False
+        for n in xrange(MAX_REASONABLE_ITERATIONS):
+            try:
+                self.subnets.append(
+                    self._create_subnet(self.networks[0],
+                                        namestart='subnet-quotatest-'))
+            except exc.QuantumClientException as e:
+                if (e.status_code != 409):
+                    raise
+                hit_limit = True
+                break
+        self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
+
+    def test_create_ports_until_quota_hit(self):
+        if not self.networks:
+            self.networks.append(
+                self._create_network(self.tenant_id,
+                                     namestart='network-quotatest-'))
+        hit_limit = False
+        for n in xrange(MAX_REASONABLE_ITERATIONS):
+            try:
+                self.ports.append(
+                    self._create_port(self.networks[0],
+                                      namestart='port-quotatest-'))
+            except exc.QuantumClientException as e:
+                if (e.status_code != 409):
+                    raise
+                hit_limit = True
+                break
+        self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
diff --git a/tempest/tests/network/test_networks.py b/tempest/tests/network/test_networks.py
index 136279f..e61bc62 100644
--- a/tempest/tests/network/test_networks.py
+++ b/tempest/tests/network/test_networks.py
@@ -15,51 +15,84 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.test import attr
+import netaddr
 
 from tempest.common.utils.data_utils import rand_name
+from tempest import exceptions
+from tempest.test import attr
 from tempest.tests.network import base
 
 
 class NetworksTest(base.BaseNetworkTest):
 
+    """
+    Tests the following operations in the Quantum API using the REST client for
+    Quantum:
+
+        create a network for a tenant
+        list tenant's networks
+        show a tenant network details
+        create a subnet for a tenant
+        list tenant's subnets
+        show a tenant subnet details
+
+    v2.0 of the Quantum API is assumed. It is also assumed that the following
+    options are defined in the [network] section of etc/tempest.conf:
+
+        tenant_network_cidr with a block of cidr's from which smaller blocks
+        can be allocated for tenant networks
+
+        tenant_network_mask_bits with the mask bits to be used to partition the
+        block defined by tenant-network_cidr
+    """
+
     @classmethod
     def setUpClass(cls):
         super(NetworksTest, cls).setUpClass()
         cls.network = cls.create_network()
         cls.name = cls.network['name']
+        cls.subnet = cls.create_subnet(cls.network)
+        cls.cidr = cls.subnet['cidr']
 
     @attr(type='positive')
-    def test_create_delete_network(self):
-        # Creates and deletes a network for a tenant
-        name = rand_name('network')
+    def test_create_delete_network_subnet(self):
+        # Creates a network
+        name = rand_name('network-')
         resp, body = self.client.create_network(name)
-        self.assertEqual('202', resp['status'])
+        self.assertEqual('201', resp['status'])
         network = body['network']
         self.assertTrue(network['id'] is not None)
+        # Find a cidr that is not in use yet and create a subnet with it
+        cidr = netaddr.IPNetwork(self.network_cfg.tenant_network_cidr)
+        mask_bits = self.network_cfg.tenant_network_mask_bits
+        for subnet_cidr in cidr.subnet(mask_bits):
+            try:
+                resp, body = self.client.create_subnet(network['id'],
+                                                       str(subnet_cidr))
+                break
+            except exceptions.BadRequest as e:
+                is_overlapping_cidr = 'overlaps with another subnet' in str(e)
+                if not is_overlapping_cidr:
+                    raise
+        self.assertEqual('201', resp['status'])
+        subnet = body['subnet']
+        self.assertTrue(subnet['id'] is not None)
+        #Deletes subnet and network
+        resp, body = self.client.delete_subnet(subnet['id'])
+        self.assertEqual('204', resp['status'])
         resp, body = self.client.delete_network(network['id'])
         self.assertEqual('204', resp['status'])
 
     @attr(type='positive')
     def test_show_network(self):
         # Verifies the details of a network
-        resp, body = self.client.get_network(self.network['id'])
+        resp, body = self.client.show_network(self.network['id'])
         self.assertEqual('200', resp['status'])
         network = body['network']
         self.assertEqual(self.network['id'], network['id'])
         self.assertEqual(self.name, network['name'])
 
     @attr(type='positive')
-    def test_show_network_details(self):
-        # Verifies the full details of a network
-        resp, body = self.client.get_network_details(self.network['id'])
-        self.assertEqual('200', resp['status'])
-        network = body['network']
-        self.assertEqual(self.network['id'], network['id'])
-        self.assertEqual(self.name, network['name'])
-        self.assertEqual(len(network['ports']), 0)
-
-    @attr(type='positive')
     def test_list_networks(self):
         # Verify the network exists in the list of all networks
         resp, body = self.client.list_networks()
@@ -68,9 +101,18 @@
         self.assertTrue(found)
 
     @attr(type='positive')
-    def test_list_networks_with_detail(self):
-        # Verify the network exists in the detailed list of all networks
-        resp, body = self.client.list_networks_details()
-        networks = body['networks']
-        found = any(n for n in networks if n['id'] == self.network['id'])
+    def test_show_subnet(self):
+        # Verifies the details of a subnet
+        resp, body = self.client.show_subnet(self.subnet['id'])
+        self.assertEqual('200', resp['status'])
+        subnet = body['subnet']
+        self.assertEqual(self.subnet['id'], subnet['id'])
+        self.assertEqual(self.cidr, subnet['cidr'])
+
+    @attr(type='positive')
+    def test_list_subnets(self):
+        # Verify the subnet exists in the list of all subnets
+        resp, body = self.client.list_subnets()
+        subnets = body['subnets']
+        found = any(n for n in subnets if n['id'] == self.subnet['id'])
         self.assertTrue(found)
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 f528cec..13fcbbf 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,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
 import uuid
 
 from tempest.common.utils.data_utils import rand_name
diff --git a/tempest/tests/volume/admin/test_volume_types_negative.py b/tempest/tests/volume/admin/test_volume_types_negative.py
index 1b11d68..daf804d 100644
--- a/tempest/tests/volume/admin/test_volume_types_negative.py
+++ b/tempest/tests/volume/admin/test_volume_types_negative.py
@@ -15,7 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
 import uuid
 
 from tempest import exceptions
diff --git a/tools/check_source.sh b/tools/check_source.sh
new file mode 100755
index 0000000..089ad70
--- /dev/null
+++ b/tools/check_source.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+python tools/hacking.py --ignore=E122,E125,E126 --repeat --show-source --exclude=.venv,.tox,dist,doc,openstack,*egg .
+pep8_ret=$?
+
+pyflakes tempest stress setup.py tools cli bin | grep "imported but unused"
+unused_ret=$?
+
+ret=0
+if [ $pep8_ret != 0 ]; then
+    echo "hacking.py/pep8 test FAILED!" >&2
+    (( ret += 1  ))
+else
+    echo "hacking.py/pep8 test OK!" >&2
+fi
+
+if [ $unused_ret == 0 ]; then
+    echo "Unused import test FAILED!" >&2
+    (( ret += 2  ))
+else
+    echo "Unused import test OK!" >&2
+fi
+
+exit $ret
diff --git a/tools/hacking.py b/tools/hacking.py
index 617682d..7e46b74 100755
--- a/tools/hacking.py
+++ b/tools/hacking.py
@@ -21,7 +21,6 @@
 built on top of pep8.py
 """
 
-import fnmatch
 import inspect
 import logging
 import os
@@ -323,6 +322,30 @@
                 return (pos, "T404: test functions must "
                         "not have doc strings")
 
+SKIP_DECORATOR = '@testtools.skip('
+
+
+def tempest_skip_bugs(physical_line):
+    """Check skip lines for proper bug entries
+
+    T601: Bug not in skip line
+    T602: Bug in message formatted incorrectly
+    """
+
+    pos = physical_line.find(SKIP_DECORATOR)
+
+    skip_re = re.compile(r'^\s*@testtools.skip.*')
+
+    if pos != -1 and skip_re.match(physical_line):
+        bug = re.compile(r'^.*\bbug\b.*', re.IGNORECASE)
+        if bug.match(physical_line) is None:
+            return (pos, 'T601: skips must have an associated bug')
+
+        bug_re = re.compile(r'.*skip\(.*Bug\s\#\d+', re.IGNORECASE)
+
+        if bug_re.match(physical_line) is None:
+            return (pos, 'T602: Bug number formatted incorrectly')
+
 
 FORMAT_RE = re.compile("%(?:"
                        "%|"           # Ignore plain percents
diff --git a/tools/install_venv.py b/tools/install_venv.py
index 20dcefa..ef7b0a8 100644
--- a/tools/install_venv.py
+++ b/tools/install_venv.py
@@ -21,9 +21,7 @@
 
 """Installation script for Tempest's development virtualenv."""
 
-import optparse
 import os
-import subprocess
 import sys
 
 import install_venv_common as install_venv
diff --git a/tools/pip-requires b/tools/pip-requires
index e85cced..758442c 100644
--- a/tools/pip-requires
+++ b/tools/pip-requires
@@ -14,3 +14,6 @@
 keyring
 testrepository
 oslo.config>=1.1.0
+# Needed for whitebox testing
+sqlalchemy
+MySQL-python
diff --git a/tools/tempest_coverage.py b/tools/tempest_coverage.py
index a46d0fb..c385eae 100755
--- a/tools/tempest_coverage.py
+++ b/tools/tempest_coverage.py
@@ -16,7 +16,6 @@
 
 import json
 import os
-import re
 import shutil
 import sys
 
@@ -24,7 +23,6 @@
 
 from tempest.common.rest_client import RestClient
 from tempest import config
-from tempest.tests.compute import base
 
 CONF = config.TempestConfig()
 
diff --git a/tools/test-requires b/tools/test-requires
index 4801391..f701dab 100644
--- a/tools/test-requires
+++ b/tools/test-requires
@@ -1,6 +1,5 @@
 pep8==1.3.3
 pylint==0.19
-# Needed for whitebox testing
-sqlalchemy
-MySQL-python
+#TODO(afazekas): ensure pg_config installed
 psycopg2
+pyflakes
diff --git a/tox.ini b/tox.ini
index 92ce6bc..85a0d86 100644
--- a/tox.ini
+++ b/tox.ini
@@ -19,4 +19,4 @@
            python -m tools/tempest_coverage -c report --html
 
 [testenv:pep8]
-commands = python tools/hacking.py --ignore=E122,E125,E126 --repeat --show-source --exclude=.venv,.tox,dist,doc,openstack,*egg .
+commands = bash tools/check_source.sh