Merge "Adds create volume from image test"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 9280c57..ac18490 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -35,9 +35,9 @@
 
 # This should be the username of a user WITH administrative privileges
 admin_username = admin
-# The above non-administrative user's password
+# The above administrative user's password
 admin_password = secret
-# The above non-administrative user's tenant name
+# The above administrative user's tenant name
 admin_tenant_name = admin
 
 [compute]
diff --git a/run_tests.sh b/run_tests.sh
index 3f394e3..25b9729 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -33,7 +33,7 @@
 config_file=""
 update=0
 
-if ! options=$(getopt -o VNnfuswcphdsC: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,whitebox,nova-coverage,pep8,help,debug,stdout,config: -- "$@")
+if ! options=$(getopt -o VNnfuswcphdSC: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,whitebox,nova-coverage,pep8,help,debug,stdout,config: -- "$@")
 then
     # parse error
     usage
diff --git a/tempest/clients.py b/tempest/clients.py
index b3b5906..7d9a263 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -48,8 +48,11 @@
 from tempest.services.compute.xml.servers_client import ServersClientXML
 from tempest.services.compute.xml.volumes_extensions_client import \
     VolumesExtensionsClientXML
+from tempest.services.identity.v3.json.endpoints_client import \
+    EndPointClientJSON
 from tempest.services.identity.json.identity_client import IdentityClientJSON
 from tempest.services.identity.json.identity_client import TokenClientJSON
+from tempest.services.identity.v3.xml.endpoints_client import EndPointClientXML
 from tempest.services.identity.xml.identity_client import IdentityClientXML
 from tempest.services.identity.xml.identity_client import TokenClientXML
 from tempest.services.image.v1.json.image_client import ImageClientJSON
@@ -157,6 +160,11 @@
     "xml": InterfacesClientXML,
 }
 
+ENDPOINT_CLIENT = {
+    "json": EndPointClientJSON,
+    "xml": EndPointClientXML,
+}
+
 
 class Manager(object):
 
@@ -219,6 +227,7 @@
             self.security_groups_client = \
                 SECURITY_GROUPS_CLIENT[interface](*client_args)
             self.interfaces_client = INTERFACES_CLIENT[interface](*client_args)
+            self.endpoints_client = ENDPOINT_CLIENT[interface](*client_args)
         except KeyError:
             msg = "Unsupported interface type `%s'" % interface
             raise exceptions.InvalidConfiguration(msg)
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 02b5c9b..fba3b0f 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -135,12 +135,14 @@
 
         headers = {'Content-Type': 'application/json'}
         body = json.dumps(creds)
-        resp, body = self.http_obj.request(auth_url, 'POST',
-                                           headers=headers, body=body)
+        self._log_request('POST', auth_url, headers, body)
+        resp, resp_body = self.http_obj.request(auth_url, 'POST',
+                                                headers=headers, body=body)
+        self._log_response(resp, resp_body)
 
         if resp.status == 200:
             try:
-                auth_data = json.loads(body)['access']
+                auth_data = json.loads(resp_body)['access']
                 token = auth_data['token']['id']
             except Exception, e:
                 print "Failed to obtain token for user: %s" % e
@@ -155,7 +157,6 @@
                             mgmt_url = _ep[self.endpoint_url]
                     if not mgmt_url:
                         mgmt_url = ep['endpoints'][0][self.endpoint_url]
-                    tenant_id = auth_data['token']['tenant']['id']
                     break
 
             if mgmt_url is None:
@@ -166,6 +167,8 @@
         elif resp.status == 401:
             raise exceptions.AuthenticationFailure(user=user,
                                                    password=password)
+        raise exceptions.IdentityError('Unexpected status code {0}'.format(
+            resp.status))
 
     def post(self, url, body, headers):
         return self.request('POST', url, headers, body)
@@ -176,6 +179,9 @@
     def delete(self, url, headers=None):
         return self.request('DELETE', url, headers)
 
+    def patch(self, url, body, headers):
+        return self.request('PATCH', url, headers, body)
+
     def put(self, url, body, headers):
         return self.request('PUT', url, headers, body)
 
@@ -230,7 +236,7 @@
 
     def response_checker(self, method, url, headers, body, resp, resp_body):
         if (resp.status in set((204, 205, 304)) or resp.status < 200 or
-            method.upper() == 'HEAD') and resp_body:
+                method.upper() == 'HEAD') and resp_body:
             raise exceptions.ResponseWithNonEmptyBody(status=resp.status)
         #NOTE(afazekas):
         # If the HTTP Status Code is 205
@@ -388,7 +394,7 @@
 
     def is_absolute_limit(self, resp, resp_body):
         if (not isinstance(resp_body, collections.Mapping) or
-            'retry-after' not in resp):
+                'retry-after' not in resp):
             return True
         over_limit = resp_body.get('overLimit', None)
         if not over_limit:
@@ -422,6 +428,6 @@
 
     def is_absolute_limit(self, resp, resp_body):
         if (not isinstance(resp_body, collections.Mapping) or
-            'retry-after' not in resp):
+                'retry-after' not in resp):
             return True
         return 'exceed' in resp_body.get('message', 'blabla')
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 955068f..1b965f3 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -106,3 +106,29 @@
         """Unsets extra Specs from the mentioned flavor."""
         return self.delete('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
                            key))
+
+    def add_flavor_access(self, flavor_id, tenant_id):
+        """Add flavor access for the specified tenant."""
+        post_body = {
+            'addTenantAccess': {
+                'tenant': tenant_id
+            }
+        }
+        post_body = json.dumps(post_body)
+        resp, body = self.post('flavors/%s/action' % flavor_id,
+                               post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['flavor_access']
+
+    def remove_flavor_access(self, flavor_id, tenant_id):
+        """Remove flavor access from the specified tenant."""
+        post_body = {
+            'removeTenantAccess': {
+                'tenant': tenant_id
+            }
+        }
+        post_body = json.dumps(post_body)
+        resp, body = self.post('flavors/%s/action' % flavor_id,
+                               post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['flavor_access']
diff --git a/tempest/services/compute/xml/flavors_client.py b/tempest/services/compute/xml/flavors_client.py
index ece362b..a6451df 100644
--- a/tempest/services/compute/xml/flavors_client.py
+++ b/tempest/services/compute/xml/flavors_client.py
@@ -147,3 +147,28 @@
         """Unsets an extra spec based on the mentioned flavor and key."""
         return self.delete('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
                            key))
+
+    def _parse_array_access(self, node):
+        return [xml_to_json(x) for x in node]
+
+    def add_flavor_access(self, flavor_id, tenant_id):
+        """Add flavor access for the specified tenant."""
+        doc = Document()
+        server = Element("addTenantAccess")
+        doc.append(server)
+        server.add_attr("tenant", tenant_id)
+        resp, body = self.post('flavors/%s/action' % str(flavor_id),
+                               str(doc), self.headers)
+        body = self._parse_array_access(etree.fromstring(body))
+        return resp, body
+
+    def remove_flavor_access(self, flavor_id, tenant_id):
+        """Remove flavor access from the specified tenant."""
+        doc = Document()
+        server = Element("removeTenantAccess")
+        doc.append(server)
+        server.add_attr("tenant", tenant_id)
+        resp, body = self.post('flavors/%s/action' % str(flavor_id),
+                               str(doc), self.headers)
+        body = self._parse_array_access(etree.fromstring(body))
+        return resp, body
diff --git a/tempest/services/identity/v3/__init__.py b/tempest/services/identity/v3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/identity/v3/__init__.py
diff --git a/tempest/services/identity/v3/json/__init__.py b/tempest/services/identity/v3/json/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/identity/v3/json/__init__.py
diff --git a/tempest/services/identity/v3/json/endpoints_client.py b/tempest/services/identity/v3/json/endpoints_client.py
new file mode 100755
index 0000000..3cb8f90
--- /dev/null
+++ b/tempest/services/identity/v3/json/endpoints_client.py
@@ -0,0 +1,87 @@
+# 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 json
+from urlparse import urlparse
+
+from tempest.common.rest_client import RestClient
+
+
+class EndPointClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(EndPointClientJSON, self).__init__(config,
+                                                 username, password,
+                                                 auth_url, tenant_name)
+        self.service = self.config.identity.catalog_type
+        self.endpoint_url = 'adminURL'
+
+    def request(self, method, url, headers=None, body=None, wait=None):
+        """Overriding the existing HTTP request in super class rest_client."""
+        self._set_auth()
+        self.base_url = self.base_url.replace(urlparse(self.base_url).path,
+                                              "/v3")
+        return super(EndPointClientJSON, self).request(method, url,
+                                                       headers=headers,
+                                                       body=body)
+
+    def list_endpoints(self):
+        """GET endpoints."""
+        resp, body = self.get('endpoints')
+        body = json.loads(body)
+        return resp, body['endpoints']
+
+    def create_endpoint(self, service_id, interface, url, **kwargs):
+        """Create endpoint."""
+        region = kwargs.get('region', None)
+        enabled = kwargs.get('enabled', None)
+        post_body = {
+            'service_id': service_id,
+            'interface': interface,
+            'url': url,
+            'region': region,
+            'enabled': enabled
+        }
+        post_body = json.dumps({'endpoint': post_body})
+        resp, body = self.post('endpoints', post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['endpoint']
+
+    def update_endpoint(self, endpoint_id, service_id=None, interface=None,
+                        url=None, region=None, enabled=None):
+        """Updates an endpoint with given parameters."""
+        post_body = {}
+        if service_id is not None:
+            post_body['service_id'] = service_id
+        if interface is not None:
+            post_body['interface'] = interface
+        if url is not None:
+            post_body['url'] = url
+        if region is not None:
+            post_body['region'] = region
+        if enabled is not None:
+            post_body['enabled'] = enabled
+        post_body = json.dumps({'endpoint': post_body})
+        resp, body = self.patch('endpoints/%s' % endpoint_id, post_body,
+                                self.headers)
+        body = json.loads(body)
+        return resp, body['endpoint']
+
+    def delete_endpoint(self, endpoint_id):
+        """Delete endpoint."""
+        resp_header, resp_body = self.delete('endpoints/%s' % endpoint_id)
+        return resp_header, resp_body
diff --git a/tempest/services/identity/v3/xml/__init__.py b/tempest/services/identity/v3/xml/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/identity/v3/xml/__init__.py
diff --git a/tempest/services/identity/v3/xml/endpoints_client.py b/tempest/services/identity/v3/xml/endpoints_client.py
new file mode 100755
index 0000000..8400976
--- /dev/null
+++ b/tempest/services/identity/v3/xml/endpoints_client.py
@@ -0,0 +1,107 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+from urlparse import urlparse
+
+import httplib2
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import Document
+from tempest.services.compute.xml.common import Element
+from tempest.services.compute.xml.common import xml_to_json
+
+XMLNS = "http://docs.openstack.org/identity/api/v3"
+
+
+class EndPointClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(EndPointClientXML, self).__init__(config, username, password,
+                                                auth_url, tenant_name)
+        self.service = self.config.identity.catalog_type
+        self.endpoint_url = 'adminURL'
+
+    def _parse_array(self, node):
+        array = []
+        for child in node.getchildren():
+            tag_list = child.tag.split('}', 1)
+            if tag_list[1] == "endpoint":
+                array.append(xml_to_json(child))
+        return array
+
+    def _parse_body(self, body):
+        json = xml_to_json(body)
+        return json
+
+    def request(self, method, url, headers=None, body=None, wait=None):
+        """Overriding the existing HTTP request in super class RestClient."""
+        dscv = self.config.identity.disable_ssl_certificate_validation
+        self.http_obj = httplib2.Http(disable_ssl_certificate_validation=dscv)
+        self._set_auth()
+        self.base_url = self.base_url.replace(urlparse(self.base_url).path,
+                                              "/v3")
+        return super(EndPointClientXML, self).request(method, url,
+                                                      headers=headers,
+                                                      body=body)
+
+    def list_endpoints(self):
+        """Get the list of endpoints."""
+        resp, body = self.get("endpoints", self.headers)
+        body = self._parse_array(etree.fromstring(body))
+        return resp, body
+
+    def create_endpoint(self, service_id, interface, url, **kwargs):
+        """Create endpoint."""
+        region = kwargs.get('region', None)
+        enabled = kwargs.get('enabled', None)
+        create_endpoint = Element("endpoint",
+                                  xmlns=XMLNS,
+                                  service_id=service_id,
+                                  interface=interface,
+                                  url=url, region=region,
+                                  enabled=enabled)
+        resp, body = self.post('endpoints', str(Document(create_endpoint)),
+                               self.headers)
+        body = self._parse_body(etree.fromstring(body))
+        return resp, body
+
+    def update_endpoint(self, endpoint_id, service_id=None, interface=None,
+                        url=None, region=None, enabled=None):
+        """Updates an endpoint with given parameters."""
+        doc = Document()
+        endpoint = Element("endpoint")
+        doc.append(endpoint)
+
+        if service_id:
+            endpoint.add_attr("service_id", service_id)
+        if interface:
+            endpoint.add_attr("interface", interface)
+        if url:
+            endpoint.add_attr("url", url)
+        if region:
+            endpoint.add_attr("region", region)
+        if enabled is not None:
+            endpoint.add_attr("enabled", enabled)
+        resp, body = self.patch('endpoints/%s' % str(endpoint_id),
+                                str(doc), self.headers)
+        body = self._parse_body(etree.fromstring(body))
+        return resp, body
+
+    def delete_endpoint(self, endpoint_id):
+        """Delete endpoint."""
+        resp_header, resp_body = self.delete('endpoints/%s' % endpoint_id)
+        return resp_header, resp_body
diff --git a/tempest/smoke.py b/tempest/smoke.py
deleted file mode 100644
index 0d4043f..0000000
--- a/tempest/smoke.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack, LLC
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import logging
-
-from tempest import test
-
-LOG = logging.getLogger(__name__)
-
-
-class SmokeTest(object):
-
-    """
-    Base test case class mixin for "smoke tests"
-
-    Smoke tests are tests that have the following characteristics:
-
-     * Test basic operations of an API, typically in an order that
-       a regular user would perform those operations
-     * Test only the correct inputs and action paths -- no fuzz or
-       random input data is sent, only valid inputs.
-     * Use only the default client tool for calling an API
-    """
-    pass
-
-
-class DefaultClientSmokeTest(test.DefaultClientTest, SmokeTest):
-
-    """
-    Base smoke test case class that provides the default clients to
-    access the various OpenStack APIs.
-    """
-
-    @classmethod
-    def tearDownClass(cls):
-        # NOTE(jaypipes): Because smoke tests are typically run in a specific
-        # order, and because test methods in smoke tests generally create
-        # resources in a particular order, we destroy resources in the reverse
-        # order in which resources are added to the smoke test class object
-        while cls.os_resources:
-            thing = cls.os_resources.pop()
-            LOG.debug("Deleting %r from shared resources of %s" %
-                      (thing, cls.__name__))
-
-            try:
-                # OpenStack resources are assumed to have a delete()
-                # method which destroys the resource...
-                thing.delete()
-            except Exception as e:
-                # If the resource is already missing, mission accomplished.
-                if e.__class__.__name__ == 'NotFound':
-                    continue
-                raise
-
-            def is_deletion_complete():
-                # Deletion testing is only required for objects whose
-                # existence cannot be checked via retrieval.
-                if isinstance(thing, dict):
-                    return True
-                try:
-                    thing.get()
-                except Exception as e:
-                    # Clients are expected to return an exception
-                    # called 'NotFound' if retrieval fails.
-                    if e.__class__.__name__ == 'NotFound':
-                        return True
-                    raise
-                return False
-
-            # Block until resource deletion has completed or timed-out
-            test.call_until_true(is_deletion_complete, 10, 1)
diff --git a/tempest/test.py b/tempest/test.py
index e0639b6..ccb2251 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -115,42 +115,91 @@
     return False
 
 
-class DefaultClientTest(TestCase):
+def status_timeout(things, thing_id, expected_status):
+    """
+    Given a thing and an expected status, do a loop, sleeping
+    for a configurable amount of time, checking for the
+    expected status to show. At any time, if the returned
+    status of the thing is ERROR, fail out.
+    """
+    def check_status():
+        # python-novaclient has resources available to its client
+        # that all implement a get() method taking an identifier
+        # for the singular resource to retrieve.
+        thing = things.get(thing_id)
+        new_status = thing.status
+        if new_status == 'ERROR':
+            self.fail("%s failed to get to expected status."
+                      "In ERROR state."
+                      % thing)
+        elif new_status == expected_status:
+            return True  # All good.
+        LOG.debug("Waiting for %s to get to %s status. "
+                  "Currently in %s status",
+                  thing, expected_status, new_status)
+    conf = config.TempestConfig()
+    if not call_until_true(check_status,
+                           conf.compute.build_timeout,
+                           conf.compute.build_interval):
+        self.fail("Timed out waiting for thing %s to become %s"
+                  % (thing_id, expected_status))
+
+
+class DefaultClientSmokeTest(TestCase):
 
     """
-    Base test case class that provides the default clients to access
-    the various OpenStack APIs.
+    Base smoke test case class that provides the default clients to
+    access the various OpenStack APIs.
+
+    Smoke tests are tests that have the following characteristics:
+
+     * Test basic operations of an API, typically in an order that
+       a regular user would perform those operations
+     * Test only the correct inputs and action paths -- no fuzz or
+       random input data is sent, only valid inputs.
+     * Use only the default client tool for calling an API
     """
 
     manager_class = manager.DefaultClientManager
 
-    def status_timeout(self, things, thing_id, expected_status):
-        """
-        Given a thing and an expected status, do a loop, sleeping
-        for a configurable amount of time, checking for the
-        expected status to show. At any time, if the returned
-        status of the thing is ERROR, fail out.
-        """
-        def check_status():
-            # python-novaclient has resources available to its client
-            # that all implement a get() method taking an identifier
-            # for the singular resource to retrieve.
-            thing = things.get(thing_id)
-            new_status = thing.status
-            if new_status == 'ERROR':
-                self.fail("%s failed to get to expected status."
-                          "In ERROR state."
-                          % thing)
-            elif new_status == expected_status:
-                return True  # All good.
-            LOG.debug("Waiting for %s to get to %s status. "
-                      "Currently in %s status",
-                      thing, expected_status, new_status)
-        if not call_until_true(check_status,
-                               self.config.compute.build_timeout,
-                               self.config.compute.build_interval):
-            self.fail("Timed out waiting for thing %s to become %s"
-                      % (thing_id, expected_status))
+    @classmethod
+    def tearDownClass(cls):
+        # NOTE(jaypipes): Because smoke tests are typically run in a specific
+        # order, and because test methods in smoke tests generally create
+        # resources in a particular order, we destroy resources in the reverse
+        # order in which resources are added to the smoke test class object
+        while cls.os_resources:
+            thing = cls.os_resources.pop()
+            LOG.debug("Deleting %r from shared resources of %s" %
+                      (thing, cls.__name__))
+
+            try:
+                # OpenStack resources are assumed to have a delete()
+                # method which destroys the resource...
+                thing.delete()
+            except Exception as e:
+                # If the resource is already missing, mission accomplished.
+                if e.__class__.__name__ == 'NotFound':
+                    continue
+                raise
+
+            def is_deletion_complete():
+                # Deletion testing is only required for objects whose
+                # existence cannot be checked via retrieval.
+                if isinstance(thing, dict):
+                    return True
+                try:
+                    thing.get()
+                except Exception as e:
+                    # Clients are expected to return an exception
+                    # called 'NotFound' if retrieval fails.
+                    if e.__class__.__name__ == 'NotFound':
+                        return True
+                    raise
+                return False
+
+            # Block until resource deletion has completed or timed-out
+            call_until_true(is_deletion_complete, 10, 1)
 
 
 class ComputeFuzzClientTest(TestCase):
@@ -161,46 +210,3 @@
     """
 
     manager_class = manager.ComputeFuzzClientManager
-
-    def status_timeout(self, client_get_method, thing_id, expected_status):
-        """
-        Given a method to get a resource and an expected status, do a loop,
-        sleeping for a configurable amount of time, checking for the
-        expected status to show. At any time, if the returned
-        status of the thing is ERROR, fail out.
-
-        :param client_get_method: The callable that will retrieve the thing
-                                  with ID :param:thing_id
-        :param thing_id: The ID of the thing to get
-        :param expected_status: String value of the expected status of the
-                                thing that we are looking for.
-
-        :code ..
-
-            Usage:
-
-            def test_some_server_action(self):
-                client = self.servers_client
-                resp, server = client.create_server('random_server')
-                self.status_timeout(client.get_server, server['id'], 'ACTIVE')
-        """
-        def check_status():
-            # Tempest REST client has resources available to its client
-            # that all implement a various get_$resource() methods taking
-            # an identifier for the singular resource to retrieve.
-            thing = client_get_method(thing_id)
-            new_status = thing['status']
-            if new_status == 'ERROR':
-                self.fail("%s failed to get to expected status."
-                          "In ERROR state."
-                          % thing)
-            elif new_status == expected_status:
-                return True  # All good.
-            LOG.debug("Waiting for %s to get to %s status. "
-                      "Currently in %s status",
-                      thing, expected_status, new_status)
-        if not call_until_true(check_status,
-                               self.config.compute.build_timeout,
-                               self.config.compute.build_interval):
-            self.fail("Timed out waiting for thing %s to become %s"
-                      % (thing_id, expected_status))
diff --git a/tempest/tests/compute/admin/test_flavors.py b/tempest/tests/compute/admin/test_flavors.py
index 32b06f8..7957009 100644
--- a/tempest/tests/compute/admin/test_flavors.py
+++ b/tempest/tests/compute/admin/test_flavors.py
@@ -48,6 +48,11 @@
         cls.swap = 1024
         cls.rxtx = 2
 
+    def flavor_clean_up(self, flavor_id):
+        resp, body = self.client.delete_flavor(flavor_id)
+        self.assertEqual(resp.status, 202)
+        self.client.wait_for_resource_deletion(flavor_id)
+
     @attr(type='positive')
     def test_create_flavor(self):
         # Create a flavor and ensure it is listed
@@ -55,43 +60,37 @@
         flavor_name = rand_name(self.flavor_name_prefix)
         new_flavor_id = rand_int_id(start=1000)
 
-        try:
-            #Create the flavor
-            resp, flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id,
-                                                     ephemeral=self.ephemeral,
-                                                     swap=self.swap,
-                                                     rxtx=self.rxtx)
-            self.assertEqual(200, resp.status)
-            self.assertEqual(flavor['name'], flavor_name)
-            self.assertEqual(flavor['vcpus'], self.vcpus)
-            self.assertEqual(flavor['disk'], self.disk)
-            self.assertEqual(flavor['ram'], self.ram)
-            self.assertEqual(int(flavor['id']), new_flavor_id)
-            self.assertEqual(flavor['swap'], self.swap)
-            self.assertEqual(flavor['rxtx_factor'], self.rxtx)
-            self.assertEqual(flavor['OS-FLV-EXT-DATA:ephemeral'],
-                             self.ephemeral)
-            if self._interface == "xml":
-                XMLNS_OS_FLV_ACCESS = "http://docs.openstack.org/compute/ext/"\
-                    "flavor_access/api/v2"
-                key = "{" + XMLNS_OS_FLV_ACCESS + "}is_public"
-                self.assertEqual(flavor[key], "True")
-            if self._interface == "json":
-                self.assertEqual(flavor['os-flavor-access:is_public'], True)
+        #Create the flavor
+        resp, flavor = self.client.create_flavor(flavor_name,
+                                                 self.ram, self.vcpus,
+                                                 self.disk,
+                                                 new_flavor_id,
+                                                 ephemeral=self.ephemeral,
+                                                 swap=self.swap,
+                                                 rxtx=self.rxtx)
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(flavor['name'], flavor_name)
+        self.assertEqual(flavor['vcpus'], self.vcpus)
+        self.assertEqual(flavor['disk'], self.disk)
+        self.assertEqual(flavor['ram'], self.ram)
+        self.assertEqual(int(flavor['id']), new_flavor_id)
+        self.assertEqual(flavor['swap'], self.swap)
+        self.assertEqual(flavor['rxtx_factor'], self.rxtx)
+        self.assertEqual(flavor['OS-FLV-EXT-DATA:ephemeral'],
+                         self.ephemeral)
+        if self._interface == "xml":
+            XMLNS_OS_FLV_ACCESS = "http://docs.openstack.org/compute/ext/"\
+                "flavor_access/api/v2"
+            key = "{" + XMLNS_OS_FLV_ACCESS + "}is_public"
+            self.assertEqual(flavor[key], "True")
+        if self._interface == "json":
+            self.assertEqual(flavor['os-flavor-access:is_public'], True)
 
-            #Verify flavor is retrieved
-            resp, flavor = self.client.get_flavor_details(new_flavor_id)
-            self.assertEqual(resp.status, 200)
-            self.assertEqual(flavor['name'], flavor_name)
-
-        finally:
-            #Delete the flavor
-            resp, body = self.client.delete_flavor(new_flavor_id)
-            self.assertEqual(resp.status, 202)
-            self.client.wait_for_resource_deletion(new_flavor_id)
+        #Verify flavor is retrieved
+        resp, flavor = self.client.get_flavor_details(new_flavor_id)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(flavor['name'], flavor_name)
 
     @attr(type='positive')
     def test_create_flavor_verify_entry_in_list_details(self):
@@ -100,29 +99,23 @@
         flavor_name = rand_name(self.flavor_name_prefix)
         new_flavor_id = rand_int_id(start=1000)
 
-        try:
-            #Create the flavor
-            resp, flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id,
-                                                     ephemeral=self.ephemeral,
-                                                     swap=self.swap,
-                                                     rxtx=self.rxtx)
-            flag = False
-            #Verify flavor is retrieved
-            resp, flavors = self.client.list_flavors_with_detail()
-            self.assertEqual(resp.status, 200)
-            for flavor in flavors:
-                if flavor['name'] == flavor_name:
-                    flag = True
-            self.assertTrue(flag)
-
-        finally:
-            #Delete the flavor
-            resp, body = self.client.delete_flavor(new_flavor_id)
-            self.assertEqual(resp.status, 202)
-            self.client.wait_for_resource_deletion(new_flavor_id)
+        #Create the flavor
+        resp, flavor = self.client.create_flavor(flavor_name,
+                                                 self.ram, self.vcpus,
+                                                 self.disk,
+                                                 new_flavor_id,
+                                                 ephemeral=self.ephemeral,
+                                                 swap=self.swap,
+                                                 rxtx=self.rxtx)
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
+        flag = False
+        #Verify flavor is retrieved
+        resp, flavors = self.client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        for flavor in flavors:
+            if flavor['name'] == flavor_name:
+                flag = True
+        self.assertTrue(flag)
 
     @attr(type='negative')
     def test_get_flavor_details_for_deleted_flavor(self):
@@ -138,11 +131,11 @@
                                                  ephemeral=self.ephemeral,
                                                  swap=self.swap,
                                                  rxtx=self.rxtx)
-        self.assertEquals(200, resp.status)
-
         # Delete the flavor
-        resp, _ = self.client.delete_flavor(new_flavor_id)
-        self.assertEqual(resp.status, 202)
+        new_flavor_id = flavor['id']
+        resp_delete, body = self.client.delete_flavor(new_flavor_id)
+        self.assertEquals(200, resp.status)
+        self.assertEquals(202, resp_delete.status)
 
         # Deleted flavors can be seen via detailed GET
         resp, flavor = self.client.get_flavor_details(new_flavor_id)
@@ -164,46 +157,40 @@
         flavor_name = rand_name(self.flavor_name_prefix)
         new_flavor_id = rand_int_id(start=1000)
 
-        try:
-            #Create the flavor
-            resp, flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id)
-            self.assertEqual(200, resp.status)
-            self.assertEqual(flavor['name'], flavor_name)
-            self.assertEqual(flavor['ram'], self.ram)
-            self.assertEqual(flavor['vcpus'], self.vcpus)
-            self.assertEqual(flavor['disk'], self.disk)
-            self.assertEqual(int(flavor['id']), new_flavor_id)
-            self.assertEqual(flavor['swap'], '')
-            self.assertEqual(int(flavor['rxtx_factor']), 1)
-            self.assertEqual(int(flavor['OS-FLV-EXT-DATA:ephemeral']), 0)
-            if self._interface == "xml":
-                XMLNS_OS_FLV_ACCESS = "http://docs.openstack.org/compute/ext/"\
-                    "flavor_access/api/v2"
-                key = "{" + XMLNS_OS_FLV_ACCESS + "}is_public"
-                self.assertEqual(flavor[key], "True")
-            if self._interface == "json":
-                self.assertEqual(flavor['os-flavor-access:is_public'], True)
+        #Create the flavor
+        resp, flavor = self.client.create_flavor(flavor_name,
+                                                 self.ram, self.vcpus,
+                                                 self.disk,
+                                                 new_flavor_id)
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(flavor['name'], flavor_name)
+        self.assertEqual(flavor['ram'], self.ram)
+        self.assertEqual(flavor['vcpus'], self.vcpus)
+        self.assertEqual(flavor['disk'], self.disk)
+        self.assertEqual(int(flavor['id']), new_flavor_id)
+        self.assertEqual(flavor['swap'], '')
+        self.assertEqual(int(flavor['rxtx_factor']), 1)
+        self.assertEqual(int(flavor['OS-FLV-EXT-DATA:ephemeral']), 0)
+        if self._interface == "xml":
+            XMLNS_OS_FLV_ACCESS = "http://docs.openstack.org/compute/ext/"\
+                "flavor_access/api/v2"
+            key = "{" + XMLNS_OS_FLV_ACCESS + "}is_public"
+            self.assertEqual(flavor[key], "True")
+        if self._interface == "json":
+            self.assertEqual(flavor['os-flavor-access:is_public'], True)
 
-            #Verify flavor is retrieved
-            resp, flavor = self.client.get_flavor_details(new_flavor_id)
-            self.assertEqual(resp.status, 200)
-            self.assertEqual(flavor['name'], flavor_name)
-            #Check if flavor is present in list
-            resp, flavors = self.client.list_flavors_with_detail()
-            self.assertEqual(resp.status, 200)
-            for flavor in flavors:
-                if flavor['name'] == flavor_name:
-                    flag = True
-            self.assertTrue(flag)
-
-        finally:
-            #Delete the flavor
-            resp, body = self.client.delete_flavor(new_flavor_id)
-            self.assertEqual(resp.status, 202)
-            self.client.wait_for_resource_deletion(new_flavor_id)
+        #Verify flavor is retrieved
+        resp, flavor = self.client.get_flavor_details(new_flavor_id)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(flavor['name'], flavor_name)
+        #Check if flavor is present in list
+        resp, flavors = self.client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        for flavor in flavors:
+            if flavor['name'] == flavor_name:
+                flag = True
+        self.assertTrue(flag)
 
     @attr(type='positive')
     def test_flavor_not_public_verify_entry_not_in_list_details(self):
@@ -213,25 +200,21 @@
         flavor_name = rand_name(self.flavor_name_prefix)
         new_flavor_id = rand_int_id(start=1000)
 
-        try:
-            #Create the flavor
-            resp, flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id,
-                                                     is_public="False")
-            flag = False
-            #Verify flavor is retrieved
-            resp, flavors = self.client.list_flavors_with_detail()
-            self.assertEqual(resp.status, 200)
-            for flavor in flavors:
-                if flavor['name'] == flavor_name:
-                    flag = True
-            self.assertFalse(flag)
-        finally:
-            #Delete the flavor
-            resp, body = self.client.delete_flavor(new_flavor_id)
-            self.assertEqual(resp.status, 202)
+        #Create the flavor
+        resp, flavor = self.client.create_flavor(flavor_name,
+                                                 self.ram, self.vcpus,
+                                                 self.disk,
+                                                 new_flavor_id,
+                                                 is_public="False")
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
+        flag = False
+        #Verify flavor is retrieved
+        resp, flavors = self.client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        for flavor in flavors:
+            if flavor['name'] == flavor_name:
+                flag = True
+        self.assertFalse(flag)
 
     def test_list_public_flavor_with_other_user(self):
         #Create a Flavor with public access.
@@ -239,76 +222,65 @@
         flavor_name = rand_name(self.flavor_name_prefix)
         new_flavor_id = rand_int_id(start=1000)
 
-        try:
             #Create the flavor
-            resp, flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id,
-                                                     is_public="True")
-            flag = False
-            self.new_client = self.flavors_client
-            #Verify flavor is retrieved with new user
-            resp, flavors = self.new_client.list_flavors_with_detail()
-            self.assertEqual(resp.status, 200)
-            for flavor in flavors:
-                if flavor['name'] == flavor_name:
-                    flag = True
-            self.assertTrue(flag)
-        finally:
-            #Delete the flavor
-            resp, body = self.client.delete_flavor(new_flavor_id)
-            self.assertEqual(resp.status, 202)
-            self.client.wait_for_resource_deletion(new_flavor_id)
+        resp, flavor = self.client.create_flavor(flavor_name,
+                                                 self.ram, self.vcpus,
+                                                 self.disk,
+                                                 new_flavor_id,
+                                                 is_public="True")
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
+        flag = False
+        self.new_client = self.flavors_client
+        #Verify flavor is retrieved with new user
+        resp, flavors = self.new_client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        for flavor in flavors:
+            if flavor['name'] == flavor_name:
+                flag = True
+        self.assertTrue(flag)
 
     @attr(type='positive')
     def test_is_public_string_variations(self):
-        try:
-            flavor_id_not_public = rand_int_id(start=1000)
-            flavor_name_not_public = rand_name(self.flavor_name_prefix)
-            flavor_id_public = rand_int_id(start=1000)
-            flavor_name_public = rand_name(self.flavor_name_prefix)
+        flavor_id_not_public = rand_int_id(start=1000)
+        flavor_name_not_public = rand_name(self.flavor_name_prefix)
+        flavor_id_public = rand_int_id(start=1000)
+        flavor_name_public = rand_name(self.flavor_name_prefix)
 
-            # Create a non public flavor
-            resp, flavor = self.client.create_flavor(flavor_name_not_public,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     flavor_id_not_public,
-                                                     is_public="False")
+        # Create a non public flavor
+        resp, flavor = self.client.create_flavor(flavor_name_not_public,
+                                                 self.ram, self.vcpus,
+                                                 self.disk,
+                                                 flavor_id_not_public,
+                                                 is_public="False")
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
 
-            # Create a public flavor
-            resp, flavor = self.client.create_flavor(flavor_name_public,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     flavor_id_public,
-                                                     is_public="True")
+        # Create a public flavor
+        resp, flavor = self.client.create_flavor(flavor_name_public,
+                                                 self.ram, self.vcpus,
+                                                 self.disk,
+                                                 flavor_id_public,
+                                                 is_public="True")
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
 
-            def _flavor_lookup(flavors, flavor_name):
-                for flavor in flavors:
-                    if flavor['name'] == flavor_name:
-                        return flavor
-                return None
+        def _flavor_lookup(flavors, flavor_name):
+            for flavor in flavors:
+                if flavor['name'] == flavor_name:
+                    return flavor
+            return None
 
-            def _test_string_variations(variations, flavor_name):
-                for string in variations:
-                    params = {'is_public': string}
-                    r, flavors = self.client.list_flavors_with_detail(params)
-                    self.assertEqual(r.status, 200)
-                    flavor = _flavor_lookup(flavors, flavor_name)
-                    self.assertNotEqual(flavor, None)
+        def _test_string_variations(variations, flavor_name):
+            for string in variations:
+                params = {'is_public': string}
+                r, flavors = self.client.list_flavors_with_detail(params)
+                self.assertEqual(r.status, 200)
+                flavor = _flavor_lookup(flavors, flavor_name)
+                self.assertNotEqual(flavor, None)
 
-            _test_string_variations(['f', 'false', 'no', '0'],
-                                    flavor_name_not_public)
+        _test_string_variations(['f', 'false', 'no', '0'],
+                                flavor_name_not_public)
 
-            _test_string_variations(['t', 'true', 'yes', '1'],
-                                    flavor_name_public)
-
-        finally:
-            # Delete flavors
-            for flavor_id in [flavor_id_not_public, flavor_id_public]:
-                resp, body = self.client.delete_flavor(flavor_id)
-                self.assertEqual(resp.status, 202)
-                self.client.wait_for_resource_deletion(flavor_id)
+        _test_string_variations(['t', 'true', 'yes', '1'],
+                                flavor_name_public)
 
     @attr(type='negative')
     def test_invalid_is_public_string(self):
diff --git a/tempest/tests/compute/admin/test_flavors_access.py b/tempest/tests/compute/admin/test_flavors_access.py
new file mode 100644
index 0000000..4cc3f57
--- /dev/null
+++ b/tempest/tests/compute/admin/test_flavors_access.py
@@ -0,0 +1,128 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NEC Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.common.utils.data_utils import rand_int_id
+from tempest.common.utils.data_utils import rand_name
+from tempest import exceptions
+from tempest.test import attr
+from tempest.tests import compute
+from tempest.tests.compute import base
+
+
+class FlavorsAccessTestJSON(base.BaseComputeAdminTest):
+
+    """
+    Tests Flavor Access API extension.
+    Add and remove Flavor Access require admin privileges.
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(FlavorsAccessTestJSON, cls).setUpClass()
+        if not compute.FLAVOR_EXTRA_DATA_ENABLED:
+            msg = "FlavorExtraData extension not enabled."
+            raise cls.skipException(msg)
+
+        cls.client = cls.os_adm.flavors_client
+        admin_client = cls._get_identity_admin_client()
+        resp, tenants = admin_client.list_tenants()
+        cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
+                         cls.flavors_client.tenant_name][0]
+
+        cls.flavor_name_prefix = 'test_flavor_access_'
+        cls.ram = 512
+        cls.vcpus = 1
+        cls.disk = 10
+
+    @attr('positive')
+    def test_flavor_access_add_remove(self):
+        #Test to add and remove flavor access to a given tenant.
+        flavor_name = rand_name(self.flavor_name_prefix)
+        new_flavor_id = rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        #Add flavor access to a tenant.
+        resp_body = {
+            "tenant_id": str(self.tenant_id),
+            "flavor_id": str(new_flavor['id']),
+        }
+        add_resp, add_body = \
+            self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
+        self.assertEqual(add_resp.status, 200)
+        self.assertIn(resp_body, add_body)
+
+        #The flavor is present in list.
+        resp, flavors = self.flavors_client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        self.assertIn(new_flavor['id'], map(lambda x: x['id'], flavors))
+
+        #Remove flavor access from a tenant.
+        remove_resp, remove_body = \
+            self.client.remove_flavor_access(new_flavor['id'], self.tenant_id)
+        self.assertEqual(remove_resp.status, 200)
+        self.assertNotIn(resp_body, remove_body)
+
+        #The flavor is not present in list.
+        resp, flavors = self.flavors_client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        self.assertNotIn(new_flavor['id'], map(lambda x: x['id'], flavors))
+
+    @attr('negative')
+    def test_flavor_non_admin_add(self):
+        #Test to add flavor access as a user without admin privileges.
+        flavor_name = rand_name(self.flavor_name_prefix)
+        new_flavor_id = rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.add_flavor_access,
+                          new_flavor['id'],
+                          self.tenant_id)
+
+    @attr('negative')
+    def test_flavor_non_admin_remove(self):
+        #Test to remove flavor access as a user without admin privileges.
+        flavor_name = rand_name(self.flavor_name_prefix)
+        new_flavor_id = rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        #Add flavor access to a tenant.
+        self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
+        self.addCleanup(self.client.remove_flavor_access,
+                        new_flavor['id'], self.tenant_id)
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.remove_flavor_access,
+                          new_flavor['id'],
+                          self.tenant_id)
+
+
+class FlavorsAdminTestXML(FlavorsAccessTestJSON):
+    _interface = 'xml'
diff --git a/tempest/tests/compute/security_groups/test_security_group_rules.py b/tempest/tests/compute/security_groups/test_security_group_rules.py
index 99d9a5d..c2032d4 100644
--- a/tempest/tests/compute/security_groups/test_security_group_rules.py
+++ b/tempest/tests/compute/security_groups/test_security_group_rules.py
@@ -33,30 +33,24 @@
     def test_security_group_rules_create(self):
         # Positive test: Creation of Security Group rule
         # should be successfull
-        try:
-            #Creating a Security Group to add rules to it
-            s_name = rand_name('securitygroup-')
-            s_description = rand_name('description-')
-            resp, securitygroup = \
-                self.client.create_security_group(s_name, s_description)
-            securitygroup_id = securitygroup['id']
-            #Adding rules to the created Security Group
-            parent_group_id = securitygroup['id']
-            ip_protocol = 'tcp'
-            from_port = 22
-            to_port = 22
-            resp, rule = \
-                self.client.create_security_group_rule(parent_group_id,
-                                                       ip_protocol,
-                                                       from_port,
-                                                       to_port)
-            self.assertEqual(200, resp.status)
-        finally:
-            #Deleting the Security Group rule, created in this method
-            group_rule_id = rule['id']
-            self.client.delete_security_group_rule(group_rule_id)
-            #Deleting the Security Group created in this method
-            resp, _ = self.client.delete_security_group(securitygroup_id)
+        #Creating a Security Group to add rules to it
+        s_name = rand_name('securitygroup-')
+        s_description = rand_name('description-')
+        resp, securitygroup = \
+            self.client.create_security_group(s_name, s_description)
+        securitygroup_id = securitygroup['id']
+        self.addCleanup(self.client.delete_security_group, securitygroup_id)
+        #Adding rules to the created Security Group
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 22
+        resp, rule = \
+            self.client.create_security_group_rule(securitygroup_id,
+                                                   ip_protocol,
+                                                   from_port,
+                                                   to_port)
+        self.addCleanup(self.client.delete_security_group_rule, rule['id'])
+        self.assertEqual(200, resp.status)
 
     @attr(type='positive')
     def test_security_group_rules_create_with_optional_arguments(self):
@@ -64,75 +58,38 @@
         # with optional arguments
         # should be successfull
 
-        rule_id = None
         secgroup1 = None
         secgroup2 = None
-        try:
-            #Creating a Security Group to add rules to it
-            s_name = rand_name('securitygroup-')
-            s_description = rand_name('description-')
-            resp, securitygroup = \
-                self.client.create_security_group(s_name, s_description)
-            secgroup1 = securitygroup['id']
-            #Creating a Security Group so as to assign group_id to the rule
-            s_name2 = rand_name('securitygroup-')
-            s_description2 = rand_name('description-')
-            resp, securitygroup = \
-                self.client.create_security_group(s_name2, s_description2)
-            secgroup2 = securitygroup['id']
-            #Adding rules to the created Security Group with optional arguments
-            parent_group_id = secgroup1
-            ip_protocol = 'tcp'
-            from_port = 22
-            to_port = 22
-            cidr = '10.2.3.124/24'
-            group_id = secgroup2
-            resp, rule = \
-                self.client.create_security_group_rule(parent_group_id,
-                                                       ip_protocol,
-                                                       from_port,
-                                                       to_port,
-                                                       cidr=cidr,
-                                                       group_id=group_id)
-            rule_id = rule['id']
-            self.assertEqual(200, resp.status)
-        finally:
-            #Deleting the Security Group rule, created in this method
-            if rule_id:
-                self.client.delete_security_group_rule(rule_id)
-            #Deleting the Security Groups created in this method
-            if secgroup1:
-                self.client.delete_security_group(secgroup1)
-            if secgroup2:
-                self.client.delete_security_group(secgroup2)
-
-    @attr(type='positive')
-    def test_security_group_rules_create_delete(self):
-        # Positive test: Deletion of Security Group rule
-        # should be successfull
-        try:
-            #Creating a Security Group to add rule to it
-            s_name = rand_name('securitygroup-')
-            s_description = rand_name('description-')
-            resp, securitygroup = \
-                self.client.create_security_group(s_name, s_description)
-            securitygroup_id = securitygroup['id']
-            #Adding rules to the created Security Group
-            parent_group_id = securitygroup['id']
-            ip_protocol = 'tcp'
-            from_port = 22
-            to_port = 22
-            resp, rule = \
-                self.client.create_security_group_rule(parent_group_id,
-                                                       ip_protocol,
-                                                       from_port,
-                                                       to_port)
-        finally:
-            #Deleting the Security Group rule, created in this method
-            group_rule_id = rule['id']
-            self.client.delete_security_group_rule(group_rule_id)
-            #Deleting the Security Group created in this method
-            resp, _ = self.client.delete_security_group(securitygroup_id)
+        #Creating a Security Group to add rules to it
+        s_name = rand_name('securitygroup-')
+        s_description = rand_name('description-')
+        resp, securitygroup = \
+            self.client.create_security_group(s_name, s_description)
+        secgroup1 = securitygroup['id']
+        self.addCleanup(self.client.delete_security_group, secgroup1)
+        #Creating a Security Group so as to assign group_id to the rule
+        s_name2 = rand_name('securitygroup-')
+        s_description2 = rand_name('description-')
+        resp, securitygroup = \
+            self.client.create_security_group(s_name2, s_description2)
+        secgroup2 = securitygroup['id']
+        self.addCleanup(self.client.delete_security_group, secgroup2)
+        #Adding rules to the created Security Group with optional arguments
+        parent_group_id = secgroup1
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 22
+        cidr = '10.2.3.124/24'
+        group_id = secgroup2
+        resp, rule = \
+            self.client.create_security_group_rule(parent_group_id,
+                                                   ip_protocol,
+                                                   from_port,
+                                                   to_port,
+                                                   cidr=cidr,
+                                                   group_id=group_id)
+        self.addCleanup(self.client.delete_security_group_rule, rule['id'])
+        self.assertEqual(200, resp.status)
 
     @attr(type='negative')
     def test_security_group_rules_create_with_invalid_id(self):
diff --git a/tempest/tests/compute/security_groups/test_security_groups.py b/tempest/tests/compute/security_groups/test_security_groups.py
index 70a01a0..d0afde4 100644
--- a/tempest/tests/compute/security_groups/test_security_groups.py
+++ b/tempest/tests/compute/security_groups/test_security_groups.py
@@ -29,79 +29,80 @@
         super(SecurityGroupsTestJSON, cls).setUpClass()
         cls.client = cls.security_groups_client
 
+    def _delete_security_group(self, securitygroup_id):
+        resp, _ = self.client.delete_security_group(securitygroup_id)
+        self.assertEqual(202, resp.status)
+
     @attr(type='positive')
     def test_security_groups_create_list_delete(self):
         # Positive test:Should return the list of Security Groups
-        try:
-            #Create 3 Security Groups
-            security_group_list = list()
-            for i in range(3):
-                s_name = rand_name('securitygroup-')
-                s_description = rand_name('description-')
-                resp, securitygroup = \
-                    self.client.create_security_group(s_name, s_description)
-                self.assertEqual(200, resp.status)
-                security_group_list.append(securitygroup)
-            #Fetch all Security Groups and verify the list
-            #has all created Security Groups
-            resp, fetched_list = self.client.list_security_groups()
-            self.assertEqual(200, resp.status)
-            #Now check if all the created Security Groups are in fetched list
-            missing_sgs = \
-                [sg for sg in security_group_list if sg not in fetched_list]
-            self.assertFalse(missing_sgs,
-                             "Failed to find Security Group %s in fetched "
-                             "list" % ', '.join(m_group['name']
-                                                for m_group in missing_sgs))
-        finally:
-            #Delete all the Security Groups created in this method
-            for securitygroup in security_group_list:
-                resp, _ = \
-                    self.client.delete_security_group(securitygroup['id'])
-                self.assertEqual(202, resp.status)
-
-    @attr(type='positive')
-    def test_security_group_create_delete(self):
-        # Security Group should be created, verified and deleted
-        try:
+        #Create 3 Security Groups
+        security_group_list = list()
+        for i in range(3):
             s_name = rand_name('securitygroup-')
             s_description = rand_name('description-')
             resp, securitygroup = \
                 self.client.create_security_group(s_name, s_description)
             self.assertEqual(200, resp.status)
-            self.assertTrue('id' in securitygroup)
-            securitygroup_id = securitygroup['id']
-            self.assertFalse(securitygroup_id is None)
-            self.assertTrue('name' in securitygroup)
-            securitygroup_name = securitygroup['name']
-            self.assertEqual(securitygroup_name, s_name,
-                             "The created Security Group name is "
-                             "not equal to the requested name")
-        finally:
-            #Delete Security Group created in this method
-            resp, _ = self.client.delete_security_group(securitygroup['id'])
-            self.assertEqual(202, resp.status)
+            self.addCleanup(self._delete_security_group,
+                            securitygroup['id'])
+            security_group_list.append(securitygroup)
+        #Fetch all Security Groups and verify the list
+        #has all created Security Groups
+        resp, fetched_list = self.client.list_security_groups()
+        self.assertEqual(200, resp.status)
+        #Now check if all the created Security Groups are in fetched list
+        missing_sgs = \
+            [sg for sg in security_group_list if sg not in fetched_list]
+        self.assertFalse(missing_sgs,
+                         "Failed to find Security Group %s in fetched "
+                         "list" % ', '.join(m_group['name']
+                                            for m_group in missing_sgs))
+
+    #TODO(afazekas): scheduled for delete,
+    #test_security_group_create_get_delete covers it
+    @attr(type='positive')
+    def test_security_group_create_delete(self):
+        # Security Group should be created, verified and deleted
+        s_name = rand_name('securitygroup-')
+        s_description = rand_name('description-')
+        resp, securitygroup = \
+            self.client.create_security_group(s_name, s_description)
+        self.assertTrue('id' in securitygroup)
+        securitygroup_id = securitygroup['id']
+        self.addCleanup(self._delete_security_group,
+                        securitygroup_id)
+        self.assertEqual(200, resp.status)
+        self.assertFalse(securitygroup_id is None)
+        self.assertTrue('name' in securitygroup)
+        securitygroup_name = securitygroup['name']
+        self.assertEqual(securitygroup_name, s_name,
+                         "The created Security Group name is "
+                         "not equal to the requested name")
 
     @attr(type='positive')
     def test_security_group_create_get_delete(self):
         # Security Group should be created, fetched and deleted
-        try:
-            s_name = rand_name('securitygroup-')
-            s_description = rand_name('description-')
-            resp, securitygroup = \
-                self.client.create_security_group(s_name, s_description)
-            self.assertEqual(200, resp.status)
-            #Now fetch the created Security Group by its 'id'
-            resp, fetched_group = \
-                self.client.get_security_group(securitygroup['id'])
-            self.assertEqual(200, resp.status)
-            self.assertEqual(securitygroup, fetched_group,
-                             "The fetched Security Group is different "
-                             "from the created Group")
-        finally:
-            #Delete the Security Group created in this method
-            resp, _ = self.client.delete_security_group(securitygroup['id'])
-            self.assertEqual(202, resp.status)
+        s_name = rand_name('securitygroup-')
+        s_description = rand_name('description-')
+        resp, securitygroup = \
+            self.client.create_security_group(s_name, s_description)
+        self.addCleanup(self._delete_security_group,
+                        securitygroup['id'])
+
+        self.assertEqual(200, resp.status)
+        self.assertTrue('name' in securitygroup)
+        securitygroup_name = securitygroup['name']
+        self.assertEqual(securitygroup_name, s_name,
+                         "The created Security Group name is "
+                         "not equal to the requested name")
+        #Now fetch the created Security Group by its 'id'
+        resp, fetched_group = \
+            self.client.get_security_group(securitygroup['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(securitygroup, fetched_group,
+                         "The fetched Security Group is different "
+                         "from the created Group")
 
     @attr(type='negative')
     def test_security_group_get_nonexistant_group(self):
diff --git a/tempest/tests/compute/servers/test_server_advanced_ops.py b/tempest/tests/compute/servers/test_server_advanced_ops.py
index f949f2e..ac0d7be 100644
--- a/tempest/tests/compute/servers/test_server_advanced_ops.py
+++ b/tempest/tests/compute/servers/test_server_advanced_ops.py
@@ -24,7 +24,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class TestServerAdvancedOps(test.DefaultClientTest):
+class TestServerAdvancedOps(test.DefaultClientSmokeTest):
 
     """
     This test case stresses some advanced server instance operations:
@@ -66,16 +66,16 @@
 
         self.assertEqual(self.instance.status, 'BUILD')
         instance_id = self.get_resource('instance').id
-        self.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
+        test.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
         instance = self.get_resource('instance')
         instance_id = instance.id
         resize_flavor = self.config.compute.flavor_ref_alt
         LOG.debug("Resizing instance %s from flavor %s to flavor %s",
                   instance.id, instance.flavor, resize_flavor)
         instance.resize(resize_flavor)
-        self.status_timeout(self.compute_client.servers, instance_id,
+        test.status_timeout(self.compute_client.servers, instance_id,
                             'VERIFY_RESIZE')
 
         LOG.debug("Confirming resize of instance %s", instance_id)
         instance.confirm_resize()
-        self.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
+        test.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
diff --git a/tempest/tests/compute/servers/test_server_basic_ops.py b/tempest/tests/compute/servers/test_server_basic_ops.py
index 2183193..c7fad7a 100644
--- a/tempest/tests/compute/servers/test_server_basic_ops.py
+++ b/tempest/tests/compute/servers/test_server_basic_ops.py
@@ -18,12 +18,12 @@
 import logging
 
 from tempest.common.utils.data_utils import rand_name
-from tempest import smoke
+from tempest import test
 
 LOG = logging.getLogger(__name__)
 
 
-class TestServerBasicOps(smoke.DefaultClientSmokeTest):
+class TestServerBasicOps(test.DefaultClientSmokeTest):
 
     """
     This smoke test case follows this basic set of operations:
@@ -101,7 +101,7 @@
 
     def wait_on_active(self):
         instance_id = self.get_resource('instance').id
-        self.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
+        test.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
 
     def pause_server(self):
         instance = self.get_resource('instance')
@@ -109,7 +109,7 @@
         LOG.debug("Pausing instance %s. Current status: %s",
                   instance_id, instance.status)
         instance.pause()
-        self.status_timeout(self.compute_client.servers, instance_id, 'PAUSED')
+        test.status_timeout(self.compute_client.servers, instance_id, 'PAUSED')
 
     def unpause_server(self):
         instance = self.get_resource('instance')
@@ -117,7 +117,7 @@
         LOG.debug("Unpausing instance %s. Current status: %s",
                   instance_id, instance.status)
         instance.unpause()
-        self.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
+        test.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
 
     def suspend_server(self):
         instance = self.get_resource('instance')
@@ -125,7 +125,7 @@
         LOG.debug("Suspending instance %s. Current status: %s",
                   instance_id, instance.status)
         instance.suspend()
-        self.status_timeout(self.compute_client.servers,
+        test.status_timeout(self.compute_client.servers,
                             instance_id, 'SUSPENDED')
 
     def resume_server(self):
@@ -134,7 +134,7 @@
         LOG.debug("Resuming instance %s. Current status: %s",
                   instance_id, instance.status)
         instance.resume()
-        self.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
+        test.status_timeout(self.compute_client.servers, instance_id, 'ACTIVE')
 
     def terminate_instance(self):
         instance = self.get_resource('instance')
diff --git a/tempest/tests/compute/test_live_block_migration.py b/tempest/tests/compute/test_live_block_migration.py
index e5a7d5b..e438098 100644
--- a/tempest/tests/compute/test_live_block_migration.py
+++ b/tempest/tests/compute/test_live_block_migration.py
@@ -28,6 +28,7 @@
 
 @attr(category='live-migration')
 class LiveBlockMigrationTestJSON(base.BaseComputeAdminTest):
+    _host_key = 'OS-EXT-SRV-ATTR:host'
     _interface = 'json'
 
     live_migration_available = (
@@ -58,7 +59,7 @@
         return body
 
     def _get_host_for_server(self, server_id):
-        return self._get_server_details(server_id)['OS-EXT-SRV-ATTR:host']
+        return self._get_server_details(server_id)[self._host_key]
 
     def _migrate_server_to(self, server_id, dest_host):
         _resp, body = self.admin_servers_client.live_migrate_server(
@@ -129,4 +130,6 @@
 
 
 class LiveBlockMigrationTestXML(LiveBlockMigrationTestJSON):
+    _host_key = (
+        '{http://docs.openstack.org/compute/ext/extended_status/api/v1.1}host')
     _interface = 'xml'
diff --git a/tempest/tests/identity/admin/v3/__init__.py b/tempest/tests/identity/admin/v3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/tests/identity/admin/v3/__init__.py
diff --git a/tempest/tests/identity/admin/v3/test_endpoints.py b/tempest/tests/identity/admin/v3/test_endpoints.py
new file mode 100755
index 0000000..98fab57
--- /dev/null
+++ b/tempest/tests/identity/admin/v3/test_endpoints.py
@@ -0,0 +1,149 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.common.utils.data_utils import rand_name
+from tempest.test import attr
+from tempest.tests.identity import base
+
+
+class EndPointsTestJSON(base.BaseIdentityAdminTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(EndPointsTestJSON, cls).setUpClass()
+        cls.identity_client = cls.client
+        cls.client = cls.endpoints_client
+        cls.service_ids = list()
+        s_name = rand_name('service-')
+        s_type = rand_name('type--')
+        s_description = rand_name('description-')
+        resp, cls.service_data =\
+            cls.identity_client.create_service(s_name, s_type,
+                                               description=s_description)
+        cls.service_id = cls.service_data['id']
+        cls.service_ids.append(cls.service_id)
+        #Create endpoints so as to use for LIST and GET test cases
+        cls.setup_endpoints = list()
+        for i in range(2):
+            region = rand_name('region')
+            url = rand_name('url')
+            interface = 'public'
+            resp, endpoint = cls.client.create_endpoint(
+                cls.service_id, interface, url, region=region, enabled=True)
+            cls.setup_endpoints.append(endpoint)
+
+    @classmethod
+    def tearDownClass(cls):
+        for e in cls.setup_endpoints:
+            cls.client.delete_endpoint(e['id'])
+        for s in cls.service_ids:
+            cls.identity_client.delete_service(s)
+
+    @attr('positive')
+    def test_list_endpoints(self):
+        # Get a list of endpoints
+        resp, fetched_endpoints = self.client.list_endpoints()
+        #Asserting LIST Endpoint
+        self.assertEqual(resp['status'], '200')
+        missing_endpoints =\
+            [e for e in self.setup_endpoints if e not in fetched_endpoints]
+        self.assertEqual(0, len(missing_endpoints),
+                         "Failed to find endpoint %s in fetched list" %
+                         ', '.join(str(e) for e in missing_endpoints))
+
+    @attr('positive')
+    def test_create_delete_endpoint(self):
+        region = rand_name('region')
+        url = rand_name('url')
+        interface = 'public'
+        create_flag = False
+        matched = False
+        try:
+            resp, endpoint =\
+                self.client.create_endpoint(self.service_id, interface, url,
+                                            region=region, enabled=True)
+            create_flag = True
+            #Asserting Create Endpoint response body
+            self.assertEqual(resp['status'], '201')
+            self.assertEqual(region, endpoint['region'])
+            self.assertEqual(url, endpoint['url'])
+            #Checking if created endpoint is present in the list of endpoints
+            resp, fetched_endpoints = self.client.list_endpoints()
+            for e in fetched_endpoints:
+                if endpoint['id'] == e['id']:
+                    matched = True
+            if not matched:
+                self.fail("Created endpoint does not appear in the list"
+                          " of endpoints")
+        finally:
+            if create_flag:
+                matched = False
+                #Deleting the endpoint created in this method
+                resp_header, resp_body =\
+                    self.client.delete_endpoint(endpoint['id'])
+                self.assertEqual(resp_header['status'], '204')
+                self.assertEqual(resp_body, '')
+                #Checking whether endpoint is deleted successfully
+                resp, fetched_endpoints = self.client.list_endpoints()
+                for e in fetched_endpoints:
+                    if endpoint['id'] == e['id']:
+                        matched = True
+                if matched:
+                    self.fail("Delete endpoint is not successful")
+
+    @attr('smoke')
+    def test_update_endpoint(self):
+        #Creating an endpoint so as to check update endpoint
+        #with new values
+        region1 = rand_name('region')
+        url1 = rand_name('url')
+        interface1 = 'public'
+        resp, endpoint_for_update =\
+            self.client.create_endpoint(self.service_id, interface1,
+                                        url1, region=region1,
+                                        enabled=True)
+        #Creating service so as update endpoint with new service ID
+        s_name = rand_name('service-')
+        s_type = rand_name('type--')
+        s_description = rand_name('description-')
+        resp, self.service2 =\
+            self.identity_client.create_service(s_name, s_type,
+                                                description=s_description)
+        self.service_ids.append(self.service2['id'])
+        #Updating endpoint with new values
+        service_id = self.service2['id']
+        region2 = rand_name('region')
+        url2 = rand_name('url')
+        interface2 = 'internal'
+        resp, endpoint = \
+            self.client.update_endpoint(endpoint_for_update['id'],
+                                        service_id=self.service2['id'],
+                                        interface=interface2, url=url2,
+                                        region=region2, enabled=False)
+        self.assertEqual(resp['status'], '200')
+        #Asserting if the attributes of endpoint are updated
+        self.assertEqual(self.service2['id'], endpoint['service_id'])
+        self.assertEqual(interface2, endpoint['interface'])
+        self.assertEqual(url2, endpoint['url'])
+        self.assertEqual(region2, endpoint['region'])
+        self.assertEqual('False', str(endpoint['enabled']))
+        self.addCleanup(self.client.delete_endpoint, endpoint_for_update['id'])
+
+
+class EndPointsTestXML(EndPointsTestJSON):
+    _interface = 'xml'
diff --git a/tempest/tests/identity/base.py b/tempest/tests/identity/base.py
index 168b2ff..64b8993 100644
--- a/tempest/tests/identity/base.py
+++ b/tempest/tests/identity/base.py
@@ -28,6 +28,7 @@
         os = clients.AdminManager(interface=cls._interface)
         cls.client = os.identity_client
         cls.token_client = os.token_client
+        cls.endpoints_client = os.endpoints_client
 
         if not cls.client.has_admin_extensions():
             raise cls.skipException("Admin extensions disabled")
diff --git a/tempest/tests/network/common.py b/tempest/tests/network/common.py
index 0bb806f..1cff2c4 100644
--- a/tempest/tests/network/common.py
+++ b/tempest/tests/network/common.py
@@ -21,7 +21,6 @@
 
 from quantumclient.common import exceptions as exc
 from tempest.common.utils.data_utils import rand_name
-from tempest import smoke
 from tempest import test
 
 
@@ -103,7 +102,7 @@
         self.client.delete_port(self.id)
 
 
-class TestNetworkSmokeCommon(smoke.DefaultClientSmokeTest):
+class TestNetworkSmokeCommon(test.DefaultClientSmokeTest):
     """
     Base class for network smoke tests
     """
@@ -274,7 +273,7 @@
             self.set_resource(name, server)
         except AttributeError:
             self.fail("Server not successfully created.")
-        self.status_timeout(client.servers, server.id, 'ACTIVE')
+        test.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.
diff --git a/tempest/tests/network/test_network_basic_ops.py b/tempest/tests/network/test_network_basic_ops.py
index a38a5c0..3afe8e3 100644
--- a/tempest/tests/network/test_network_basic_ops.py
+++ b/tempest/tests/network/test_network_basic_ops.py
@@ -17,11 +17,10 @@
 #    under the License.
 
 from tempest.common.utils.data_utils import rand_name
-from tempest.tests.network.common import DeletableRouter
-from tempest.tests.network.common import TestNetworkSmokeCommon
+import tempest.tests.network.common as net_common
 
 
-class TestNetworkBasicOps(TestNetworkSmokeCommon):
+class TestNetworkBasicOps(net_common.TestNetworkSmokeCommon):
 
     """
     This smoke test suite assumes that Nova has been configured to
@@ -124,7 +123,7 @@
         network_id = self.config.network.public_network_id
         if router_id:
             result = self.network_client.show_router(router_id)
-            return AttributeDict(**result['router'])
+            return net_common.AttributeDict(**result['router'])
         elif network_id:
             router = self._create_router(tenant_id)
             router.add_gateway(network_id)
@@ -143,8 +142,8 @@
             ),
         )
         result = self.network_client.create_router(body=body)
-        router = DeletableRouter(client=self.network_client,
-                                 **result['router'])
+        router = net_common.DeletableRouter(client=self.network_client,
+                                            **result['router'])
         self.assertEqual(router.name, name)
         self.set_resource(name, router)
         return router