Merge "Loosen constraints on Swift status codes."
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 915e2fa..db6a7bd 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -14,9 +14,6 @@
 uri = http://127.0.0.1:5000/v2.0/
 # URL for where to find the OpenStack V3 Identity API endpoint (Keystone)
 uri_v3 = http://127.0.0.1:5000/v3/
-# Should typically be left as keystone unless you have a non-Keystone
-# authentication API service
-strategy = keystone
 # The identity region
 region = RegionOne
 
@@ -127,11 +124,11 @@
 # relax-xsm-sr-check
 block_migrate_supports_cinder_iscsi = false
 
-# By default, rely on the status of the diskConfig extension to
-# decide if to execute disk config tests. When set to false, tests
-# are forced to skip, regardless of the extension status
-disk_config_enabled_override = true
+# When set to false, disk config tests are forced to skip
+disk_config_enabled = true
 
+# When set to false, flavor extra data tests are forced to skip
+flavor_extra_enabled = true
 
 [whitebox]
 # Whitebox options for compute. Whitebox options enable the
@@ -334,3 +331,9 @@
 
 # ssh username for the image file
 ssh_user = cirros
+
+[CLI]
+# Enable cli tests
+enabled = True
+# directory where python client binaries are located
+cli_dir = /usr/local/bin/
diff --git a/requirements.txt b/requirements.txt
index 19d6e0b..df9951d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,7 +3,7 @@
 anyjson
 nose
 httplib2>=0.7.0
-testtools>=0.9.29
+testtools>=0.9.32
 lxml
 boto>=2.2.1
 paramiko
diff --git a/tempest/api/compute/__init__.py b/tempest/api/compute/__init__.py
index 98f198d..fb96b4a 100644
--- a/tempest/api/compute/__init__.py
+++ b/tempest/api/compute/__init__.py
@@ -15,7 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import clients
 from tempest.common import log as logging
 from tempest import config
 from tempest.exceptions import InvalidConfiguration
@@ -26,9 +25,8 @@
 CREATE_IMAGE_ENABLED = CONFIG.compute.create_image_enabled
 RESIZE_AVAILABLE = CONFIG.compute.resize_available
 CHANGE_PASSWORD_AVAILABLE = CONFIG.compute.change_password_available
-DISK_CONFIG_ENABLED = True
-DISK_CONFIG_ENABLED_OVERRIDE = CONFIG.compute.disk_config_enabled_override
-FLAVOR_EXTRA_DATA_ENABLED = True
+DISK_CONFIG_ENABLED = CONFIG.compute.disk_config_enabled
+FLAVOR_EXTRA_DATA_ENABLED = CONFIG.compute.flavor_extra_enabled
 MULTI_USER = True
 
 
@@ -36,27 +34,7 @@
 def generic_setup_package():
     LOG.debug("Entering tempest.api.compute.setup_package")
 
-    global MULTI_USER, DISK_CONFIG_ENABLED, FLAVOR_EXTRA_DATA_ENABLED
-    os = clients.Manager()
-    images_client = os.images_client
-    flavors_client = os.flavors_client
-    extensions_client = os.extensions_client
-    DISK_CONFIG_ENABLED = (DISK_CONFIG_ENABLED_OVERRIDE and
-                           extensions_client.is_enabled('DiskConfig'))
-    FLAVOR_EXTRA_DATA_ENABLED = extensions_client.is_enabled('FlavorExtraData')
-
-    # Validate reference data exists
-    # If not, we raise the exception here and prevent
-    # going forward...
-    image_ref = CONFIG.compute.image_ref
-    image_ref_alt = CONFIG.compute.image_ref_alt
-    images_client.get_image(image_ref)
-    images_client.get_image(image_ref_alt)
-
-    flavor_ref = CONFIG.compute.flavor_ref
-    flavor_ref_alt = CONFIG.compute.flavor_ref_alt
-    flavors_client.get_flavor_details(flavor_ref)
-    flavors_client.get_flavor_details(flavor_ref_alt)
+    global MULTI_USER
 
     # Determine if there are two regular users that can be
     # used in testing. If the test cases are allowed to create
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 0fa5a84..abc5899 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -20,6 +20,7 @@
 from tempest.api import compute
 from tempest import clients
 from tempest.common import log as logging
+from tempest.common.utils.data_utils import parse_image_id
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 import tempest.test
@@ -73,6 +74,7 @@
         cls.flavor_ref = cls.config.compute.flavor_ref
         cls.flavor_ref_alt = cls.config.compute.flavor_ref_alt
         cls.servers = []
+        cls.images = []
 
         cls.servers_client_v3_auth = os.servers_client_v3_auth
 
@@ -174,7 +176,18 @@
                 pass
 
     @classmethod
+    def clear_images(cls):
+        for image_id in cls.images:
+            try:
+                cls.images_client.delete_image(image_id)
+            except Exception as exc:
+                LOG.info('Exception raised deleting image %s', image_id)
+                LOG.exception(exc)
+                pass
+
+    @classmethod
     def tearDownClass(cls):
+        cls.clear_images()
         cls.clear_servers()
         cls.clear_isolated_creds()
 
@@ -206,6 +219,25 @@
 
         return resp, body
 
+    @classmethod
+    def create_image_from_server(cls, server_id, **kwargs):
+        """Wrapper utility that returns a test server."""
+        name = rand_name(cls.__name__ + "-image")
+        if 'name' in kwargs:
+            name = kwargs.pop('name')
+
+        resp, image = cls.images_client.create_image(
+            server_id, name)
+        image_id = parse_image_id(resp['location'])
+        cls.images.append(image_id)
+
+        if 'wait_until' in kwargs:
+            cls.images_client.wait_for_image_status(image_id,
+                                                    kwargs['wait_until'])
+            resp, image = cls.images_client.get_image(image_id)
+
+        return resp, image
+
     def wait_for(self, condition):
         """Repeatedly calls condition() until a timeout."""
         start_time = int(time.time())
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 9db28ad..5c6b630 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -16,12 +16,15 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.common import log as logging
 from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 from tempest.test import attr
 
 
+LOG = logging.getLogger(__name__)
+
+
 class ListImageFiltersTestJSON(base.BaseComputeTest):
     _interface = 'json'
 
@@ -29,6 +32,7 @@
     def setUpClass(cls):
         super(ListImageFiltersTestJSON, cls).setUpClass()
         cls.client = cls.images_client
+        cls.image_ids = []
 
         try:
             resp, cls.server1 = cls.create_server()
@@ -38,9 +42,7 @@
                                                       'ACTIVE')
 
             # Create images to be used in the filter tests
-            image1_name = rand_name('image')
-            resp, body = cls.client.create_image(cls.server1['id'],
-                                                 image1_name)
+            resp, body = cls.create_image_from_server(cls.server1['id'])
             cls.image1_id = parse_image_id(resp['location'])
             cls.client.wait_for_image_resp_code(cls.image1_id, 200)
             cls.client.wait_for_image_status(cls.image1_id, 'ACTIVE')
@@ -49,35 +51,23 @@
             # Servers have a hidden property for when they are being imaged
             # Performing back-to-back create image calls on a single
             # server will sometimes cause failures
-            image3_name = rand_name('image')
-            resp, body = cls.client.create_image(cls.server2['id'],
-                                                 image3_name)
+            resp, body = cls.create_image_from_server(cls.server2['id'])
             cls.image3_id = parse_image_id(resp['location'])
             cls.client.wait_for_image_resp_code(cls.image3_id, 200)
             cls.client.wait_for_image_status(cls.image3_id, 'ACTIVE')
             resp, cls.image3 = cls.client.get_image(cls.image3_id)
 
-            image2_name = rand_name('image')
-            resp, body = cls.client.create_image(cls.server1['id'],
-                                                 image2_name)
+            resp, body = cls.create_image_from_server(cls.server1['id'])
             cls.image2_id = parse_image_id(resp['location'])
             cls.client.wait_for_image_resp_code(cls.image2_id, 200)
+
             cls.client.wait_for_image_status(cls.image2_id, 'ACTIVE')
             resp, cls.image2 = cls.client.get_image(cls.image2_id)
-        except Exception:
-            cls.clear_servers()
-            cls.client.delete_image(cls.image1_id)
-            cls.client.delete_image(cls.image2_id)
-            cls.client.delete_image(cls.image3_id)
+        except Exception as exc:
+            LOG.exception(exc)
+            cls.tearDownClass()
             raise
 
-    @classmethod
-    def tearDownClass(cls):
-        cls.client.delete_image(cls.image1_id)
-        cls.client.delete_image(cls.image2_id)
-        cls.client.delete_image(cls.image3_id)
-        super(ListImageFiltersTestJSON, cls).tearDownClass()
-
     @attr(type=['negative', 'gate'])
     def test_get_image_not_existing(self):
         # Check raises a NotFound
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index a6302e6..1acc57d 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -33,72 +33,68 @@
     def test_volume_create_get_delete(self):
         # CREATE, GET, DELETE Volume
         volume = None
-        try:
-            v_name = rand_name('Volume-%s-') % self._interface
-            metadata = {'Type': 'work'}
-            #Create volume
-            resp, volume = self.client.create_volume(size=1,
-                                                     display_name=v_name,
-                                                     metadata=metadata)
-            self.assertEqual(200, resp.status)
-            self.assertTrue('id' in volume)
-            self.assertTrue('displayName' in volume)
-            self.assertEqual(volume['displayName'], v_name,
-                             "The created volume name is not equal "
-                             "to the requested name")
-            self.assertTrue(volume['id'] is not None,
-                            "Field volume id is empty or not found.")
-            #Wait for Volume status to become ACTIVE
-            self.client.wait_for_volume_status(volume['id'], 'available')
-            #GET Volume
-            resp, fetched_volume = self.client.get_volume(volume['id'])
-            self.assertEqual(200, resp.status)
-            #Verfication of details of fetched Volume
-            self.assertEqual(v_name,
-                             fetched_volume['displayName'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-            self.assertEqual(volume['id'],
-                             fetched_volume['id'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-            self.assertEqual(metadata,
-                             fetched_volume['metadata'],
-                             'The fetched Volume is different '
-                             'from the created Volume')
-
-        finally:
-            if volume:
-                #Delete the Volume created in this method
-                resp, _ = self.client.delete_volume(volume['id'])
-                self.assertEqual(202, resp.status)
-                #Checking if the deleted Volume still exists
-                self.client.wait_for_resource_deletion(volume['id'])
+        v_name = rand_name('Volume-%s-') % self._interface
+        metadata = {'Type': 'work'}
+        #Create volume
+        resp, volume = self.client.create_volume(size=1,
+                                                 display_name=v_name,
+                                                 metadata=metadata)
+        self.addCleanup(self._delete_volume, volume)
+        self.assertEqual(200, resp.status)
+        self.assertTrue('id' in volume)
+        self.assertTrue('displayName' in volume)
+        self.assertEqual(volume['displayName'], v_name,
+                         "The created volume name is not equal "
+                         "to the requested name")
+        self.assertTrue(volume['id'] is not None,
+                        "Field volume id is empty or not found.")
+        #Wait for Volume status to become ACTIVE
+        self.client.wait_for_volume_status(volume['id'], 'available')
+        #GET Volume
+        resp, fetched_volume = self.client.get_volume(volume['id'])
+        self.assertEqual(200, resp.status)
+        #Verfication of details of fetched Volume
+        self.assertEqual(v_name,
+                         fetched_volume['displayName'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
+        self.assertEqual(volume['id'],
+                         fetched_volume['id'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
+        self.assertEqual(metadata,
+                         fetched_volume['metadata'],
+                         'The fetched Volume is different '
+                         'from the created Volume')
 
     @attr(type='gate')
     def test_volume_get_metadata_none(self):
         # CREATE, GET empty metadata dict
+        v_name = rand_name('Volume-')
+        #Create volume
+        resp, volume = self.client.create_volume(size=1,
+                                                 display_name=v_name,
+                                                 metadata={})
+        self.addCleanup(self._delete_volume, volume)
+        self.assertEqual(200, resp.status)
+        self.assertTrue('id' in volume)
+        self.assertTrue('displayName' in volume)
+        #Wait for Volume status to become ACTIVE
+        self.client.wait_for_volume_status(volume['id'], 'available')
+        #GET Volume
+        resp, fetched_volume = self.client.get_volume(volume['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(fetched_volume['metadata'], {})
+
+    def _delete_volume(self, volume):
+        #Delete the Volume created in this method
         try:
-            v_name = rand_name('Volume-')
-            #Create volume
-            resp, volume = self.client.create_volume(size=1,
-                                                     display_name=v_name,
-                                                     metadata={})
-            self.assertEqual(200, resp.status)
-            self.assertTrue('id' in volume)
-            self.assertTrue('displayName' in volume)
-            #Wait for Volume status to become ACTIVE
-            self.client.wait_for_volume_status(volume['id'], 'available')
-            #GET Volume
-            resp, fetched_volume = self.client.get_volume(volume['id'])
-            self.assertEqual(200, resp.status)
-            self.assertEqual(fetched_volume['metadata'], {})
-        finally:
-            #Delete the Volume created in this method
             resp, _ = self.client.delete_volume(volume['id'])
             self.assertEqual(202, resp.status)
             #Checking if the deleted Volume still exists
             self.client.wait_for_resource_deletion(volume['id'])
+        except KeyError:
+            return
 
 
 class VolumesGetTestXML(VolumesGetTestJSON):
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index be8afe6..c029300 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -44,7 +44,7 @@
         self.assertEqual('200', resp['status'])
         self.assertEqual(self.alt_user, user['name'])
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_create_user_by_unauthorized_user(self):
         # Non-admin should not be authorized to create a user
         self.data.setup_test_tenant()
@@ -53,7 +53,7 @@
                           self.alt_password, self.data.tenant['id'],
                           self.alt_email)
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_create_user_with_empty_name(self):
         # User with an empty name should not be created
         self.data.setup_test_tenant()
@@ -69,7 +69,7 @@
                           'a' * 256, self.alt_password,
                           self.data.tenant['id'], self.alt_email)
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_create_user_with_duplicate_name(self):
         # Duplicate user should not be created
         self.data.setup_test_user()
@@ -78,7 +78,7 @@
                           self.data.tenant['id'], self.data.test_email)
 
     @testtools.skip("Until Bug #999084 is fixed")
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_create_user_with_empty_password(self):
         # User with an empty password should not be created
         self.data.setup_test_tenant()
@@ -87,7 +87,7 @@
                           self.alt_email)
 
     @testtools.skip("Until Bug #999084 is fixed")
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_create_user_with_long_password(self):
         # User having password exceeding max length should not be created
         self.data.setup_test_tenant()
@@ -96,21 +96,21 @@
                           self.alt_email)
 
     @testtools.skip("Until Bug #999084 is fixed")
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_create_user_with_invalid_email_format(self):
         # Email format should be validated while creating a user
         self.data.setup_test_tenant()
         self.assertRaises(exceptions.BadRequest, self.client.create_user,
                           self.alt_user, '', self.data.tenant['id'], '12345')
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_create_user_for_non_existant_tenant(self):
         # Attempt to create a user in a non-existent tenant should fail
         self.assertRaises(exceptions.NotFound, self.client.create_user,
                           self.alt_user, self.alt_password, '49ffgg99999',
                           self.alt_email)
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_create_user_request_without_a_token(self):
         # Request to create a user without a valid token should fail
         self.data.setup_test_tenant()
@@ -136,7 +136,7 @@
         resp, body = self.client.delete_user(user['id'])
         self.assertEquals('204', resp['status'])
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_delete_users_by_unauthorized_user(self):
         # Non admin user should not be authorized to delete a user
         self.data.setup_test_user()
@@ -144,7 +144,7 @@
                           self.non_admin_client.delete_user,
                           self.data.user['id'])
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_delete_non_existant_user(self):
         # Attempt to delete a non-existent user should fail
         self.assertRaises(exceptions.NotFound, self.client.delete_user,
@@ -163,7 +163,7 @@
                                             self.data.test_tenant)
         self.assertEqual('200', resp['status'])
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_authentication_for_disabled_user(self):
         # Disabled user's token should not get authenticated
         self.data.setup_test_user()
@@ -173,7 +173,7 @@
                           self.data.test_password,
                           self.data.test_tenant)
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_authentication_when_tenant_is_disabled(self):
         # User's token for a disabled tenant should not be authenticated
         self.data.setup_test_user()
@@ -183,7 +183,7 @@
                           self.data.test_password,
                           self.data.test_tenant)
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_authentication_with_invalid_tenant(self):
         # User's token for an invalid tenant should not be authenticated
         self.data.setup_test_user()
@@ -192,7 +192,7 @@
                           self.data.test_password,
                           'junktenant1234')
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_authentication_with_invalid_username(self):
         # Non-existent user's token should not get authenticated
         self.data.setup_test_user()
@@ -200,7 +200,7 @@
                           'junkuser123', self.data.test_password,
                           self.data.test_tenant)
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_authentication_with_invalid_password(self):
         # User's token with invalid password should not be authenticated
         self.data.setup_test_user()
@@ -234,14 +234,14 @@
                         Contains(self.data.test_user),
                         "Could not find %s" % self.data.test_user)
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_get_users_by_unauthorized_user(self):
         # Non admin user should not be authorized to get user list
         self.data.setup_test_user()
         self.assertRaises(exceptions.Unauthorized,
                           self.non_admin_client.get_users)
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_get_users_request_without_token(self):
         # Request to get list of users without a valid token should fail
         token = self.client.get_auth()
@@ -316,7 +316,7 @@
                          "Failed to find user %s in fetched list" %
                          ', '.join(m_user for m_user in missing_users))
 
-    @attr(type='gate')
+    @attr(type=['negative', 'gate'])
     def test_list_users_with_invalid_tenant(self):
         # Should not be able to return a list of all
         # users for a nonexistant tenant
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 8068284..03e73df 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -73,6 +73,7 @@
         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
+        body = None
         failure = None
         for subnet_cidr in cidr.subnet(mask_bits):
             try:
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index 8847c08..5fed581 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -45,19 +45,19 @@
 
         # count how many stacks to start with
         resp, body = self.client.list_stacks()
-        stack_count = len(body['stacks'])
 
         # create the stack
         stack_identifier = self.create_stack(
             stack_name, self.empty_template)
+        stack_id = stack_identifier.split('/')[1]
 
         # wait for create complete (with no resources it should be instant)
         self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
 
-        # stack count will increment by 1
+        # check for stack in list
         resp, body = self.client.list_stacks()
-        self.assertEqual(stack_count + 1, len(body['stacks']),
-                         'Expected stack count to increment by 1')
+        list_ids = list([stack['id'] for stack in body['stacks']])
+        self.assertIn(stack_id, list_ids)
 
         # fetch the stack
         resp, body = self.client.get_stack(stack_identifier)
@@ -68,7 +68,6 @@
         self.assertEqual('CREATE_COMPLETE', body['stack_status'])
 
         # fetch the stack by id
-        stack_id = stack_identifier.split('/')[1]
         resp, body = self.client.get_stack(stack_id)
         self.assertEqual('CREATE_COMPLETE', body['stack_status'])
 
diff --git a/tempest/clients.py b/tempest/clients.py
index e778dc1..a5c7b4d 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -274,22 +274,15 @@
         self.auth_url = self.config.identity.uri
         self.auth_url_v3 = self.config.identity.uri_v3
 
-        if self.config.identity.strategy == 'keystone':
-            client_args = (self.config, self.username, self.password,
-                           self.auth_url, self.tenant_name)
+        client_args = (self.config, self.username, self.password,
+                       self.auth_url, self.tenant_name)
 
-            if self.auth_url_v3:
-                auth_version = 'v3'
-                client_args_v3_auth = (self.config, self.username,
-                                       self.password, self.auth_url_v3,
-                                       self.tenant_name, auth_version)
-            else:
-                client_args_v3_auth = None
-
+        if self.auth_url_v3:
+            auth_version = 'v3'
+            client_args_v3_auth = (self.config, self.username,
+                                   self.password, self.auth_url_v3,
+                                   self.tenant_name, auth_version)
         else:
-            client_args = (self.config, self.username, self.password,
-                           self.auth_url)
-
             client_args_v3_auth = None
 
         try:
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index baa3c03..531dfc8 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -51,7 +51,6 @@
         self.base_url = None
         self.region = {'compute': self.config.identity.region}
         self.endpoint_url = 'publicURL'
-        self.strategy = self.config.identity.strategy
         self.headers = {'Content-Type': 'application/%s' % self.TYPE,
                         'Accept': 'application/%s' % self.TYPE}
         self.build_interval = config.compute.build_interval
@@ -72,21 +71,14 @@
         Sets the token and base_url used in requests based on the strategy type
         """
 
-        if self.strategy == 'keystone':
-
-            if self.auth_version == 'v3':
-                auth_func = self.identity_auth_v3
-            else:
-                auth_func = self.keystone_auth
-
-            self.token, self.base_url = (
-                auth_func(self.user, self.password, self.auth_url,
-                          self.service, self.tenant_name))
-
+        if self.auth_version == 'v3':
+            auth_func = self.identity_auth_v3
         else:
-            self.token, self.base_url = self.basic_auth(self.user,
-                                                        self.password,
-                                                        self.auth_url)
+            auth_func = self.keystone_auth
+
+        self.token, self.base_url = (
+            auth_func(self.user, self.password, self.auth_url,
+                      self.service, self.tenant_name))
 
     def clear_auth(self):
         """
diff --git a/tempest/config.py b/tempest/config.py
index 85be7a6..7196078 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -40,10 +40,6 @@
                help="Full URI of the OpenStack Identity API (Keystone), v2"),
     cfg.StrOpt('uri_v3',
                help='Full URI of the OpenStack Identity API (Keystone), v3'),
-    cfg.StrOpt('strategy',
-               default='keystone',
-               help="Which auth method does the environment use? "
-                    "(basic|keystone)"),
     cfg.StrOpt('region',
                default='RegionOne',
                help="The identity region name to use."),
@@ -185,10 +181,12 @@
                default=None,
                help="Path to a private key file for SSH access to remote "
                     "hosts"),
-    cfg.BoolOpt('disk_config_enabled_override',
+    cfg.BoolOpt('disk_config_enabled',
                 default=True,
-                help="If false, skip config tests regardless of the "
-                     "extension status"),
+                help="If false, skip disk config tests"),
+    cfg.BoolOpt('flavor_extra_enabled',
+                default=True,
+                help="If false, skip flavor extra data test"),
 ]
 
 
diff --git a/tempest/manager.py b/tempest/manager.py
index 762bc18..4a447f3 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -115,11 +115,8 @@
         if 'tokens' not in auth_url:
             auth_url = auth_url.rstrip('/') + '/tokens'
 
-        if self.config.identity.strategy == 'keystone':
-            client_args = (self.config, username, password, auth_url,
-                           tenant_name)
-        else:
-            client_args = (self.config, username, password, auth_url)
+        client_args = (self.config, username, password, auth_url,
+                       tenant_name)
 
         self.servers_client = ServersClient(*client_args)
         self.flavors_client = FlavorsClient(*client_args)
diff --git a/tempest/services/compute/xml/security_groups_client.py b/tempest/services/compute/xml/security_groups_client.py
index 08b381c..5d86790 100644
--- a/tempest/services/compute/xml/security_groups_client.py
+++ b/tempest/services/compute/xml/security_groups_client.py
@@ -97,29 +97,20 @@
         group_id : ID of the Source group
         """
         group_rule = Element("security_group_rule")
-        parent_group = Element("parent_group_id")
-        parent_group.append(Text(content=parent_group_id))
-        ip_protocol = Element("ip_protocol")
-        ip_protocol.append(Text(content=ip_proto))
-        from_port_num = Element("from_port")
-        from_port_num.append(Text(content=str(from_port)))
-        to_port_num = Element("to_port")
-        to_port_num.append(Text(content=str(to_port)))
 
-        cidr = kwargs.get('cidr')
-        if cidr is not None:
-            cidr_num = Element("cidr")
-            cidr_num.append(Text(content=cidr))
+        elements = dict()
+        elements['cidr'] = kwargs.get('cidr')
+        elements['group_id'] = kwargs.get('group_id')
+        elements['parent_group_id'] = parent_group_id
+        elements['ip_protocol'] = ip_proto
+        elements['from_port'] = from_port
+        elements['to_port'] = to_port
 
-        group_id = kwargs.get('group_id')
-        if group_id is not None:
-            group_id_num = Element("group_id")
-            group_id_num.append(Text(content=group_id))
-
-        group_rule.append(parent_group)
-        group_rule.append(ip_protocol)
-        group_rule.append(from_port_num)
-        group_rule.append(to_port_num)
+        for k, v in elements.items():
+            if v is not None:
+                element = Element(k)
+                element.append(Text(content=str(v)))
+                group_rule.append(element)
 
         url = 'os-security-group-rules'
         resp, body = self.post(url, str(Document(group_rule)), self.headers)
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 69df472..c894612 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -34,8 +34,11 @@
     def create_object(self, container, object_name, data):
         """Create storage object."""
 
+        headers = dict(self.headers)
+        if not data:
+            headers['content-length'] = '0'
         url = "%s/%s" % (str(container), str(object_name))
-        resp, body = self.put(url, data, self.headers)
+        resp, body = self.put(url, data, headers)
         return resp, body
 
     def update_object(self, container, object_name, data):
@@ -194,6 +197,8 @@
             for key in metadata:
                 headers[str(key)] = metadata[key]
 
+        if not data:
+            headers['content-length'] = '0'
         url = "%s/%s" % (str(container), str(object_name))
         resp, body = self.put(url, data, headers=headers)
         return resp, body
diff --git a/tempest/stress/actions/volume_create_delete.py b/tempest/stress/actions/volume_create_delete.py
new file mode 100644
index 0000000..e0c95b5
--- /dev/null
+++ b/tempest/stress/actions/volume_create_delete.py
@@ -0,0 +1,30 @@
+#    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
+
+
+def create_delete(manager, logger):
+    while True:
+        name = rand_name("volume")
+        logger.info("creating %s" % name)
+        resp, volume = manager.volumes_client.create_volume(size=1,
+                                                            display_name=name)
+        assert(resp.status == 200)
+        manager.volumes_client.wait_for_volume_status(volume['id'],
+                                                      'available')
+        logger.info("created %s" % volume['id'])
+        logger.info("deleting %s" % name)
+        resp, _ = manager.volumes_client.delete_volume(volume['id'])
+        assert(resp.status == 202)
+        manager.volumes_client.wait_for_resource_deletion(volume['id'])
+        logger.info("deleted %s" % volume['id'])
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index b2cb70a..3b1c871 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -58,3 +58,16 @@
     for tenant in tenants:
         if tenant['name'].startswith("stress_tenant"):
             admin_manager.identity_client.delete_tenant(tenant['id'])
+
+    _, vols = admin_manager.volumes_client.list_volumes({"all_tenants": True})
+    for v in vols:
+        try:
+            admin_manager.volumes_client.delete_volume(v['id'])
+        except Exception:
+            pass
+
+    for v in vols:
+        try:
+            admin_manager.volumes_client.wait_for_resource_deletion(v['id'])
+        except Exception:
+            pass
diff --git a/tempest/stress/etc/volume-create-delete-test.json b/tempest/stress/etc/volume-create-delete-test.json
new file mode 100644
index 0000000..ed0aaeb
--- /dev/null
+++ b/tempest/stress/etc/volume-create-delete-test.json
@@ -0,0 +1,7 @@
+[{"action": "tempest.stress.actions.volume_create_delete.create_delete",
+  "threads": 4,
+  "use_admin": false,
+  "use_isolated_tenants": false,
+  "kwargs": {}
+  }
+]
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 7480833..89891d2 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -139,6 +139,7 @@
 
     #NOTE(afazekas): doctored test case,
     # with normal validation it would fail
+    @testtools.skip("Until Bug #1182679 is fixed")
     @attr(type='smoke')
     def test_integration_1(self):
         # EC2 1. integration test (not strict)
diff --git a/test-requirements.txt b/test-requirements.txt
index 27851da..3912695 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,8 +3,6 @@
 pyflakes==0.7.2
 flake8==2.0
 hacking>=0.5.3,<0.6
-#
-#TODO(afazekas): ensure pg_config installed
 psycopg2
 # needed for doc build
 sphinx>=1.1.2
diff --git a/tox.ini b/tox.ini
index 634b7df..caa9403 100644
--- a/tox.ini
+++ b/tox.ini
@@ -59,7 +59,7 @@
 commands =
    python -m tools/tempest_coverage -c start --combine
    nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit --xunit-file=nosetests-full.xml -sv tempest/api tempest/scenario tempest/thirdparty tempest/cli
-   python -m tools/tempest_coverage -c report --html
+   python -m tools/tempest_coverage -c report --html {posargs}
 
 [testenv:venv]
 commands = {posargs}