Merge "scenario test involving glance, cinder and nova functionalities"
diff --git a/doc/source/index.rst b/doc/source/index.rst
index f012097..00c4e9a 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -33,6 +33,13 @@
    field_guide/thirdparty
    field_guide/whitebox
 
+------------------
+API and test cases
+------------------
+.. toctree::
+   :maxdepth: 1
+
+   api/modules
 
 ==================
 Indices and tables
diff --git a/etc/logging.conf.sample b/etc/logging.conf.sample
index 685dd36..3b468f1 100644
--- a/etc/logging.conf.sample
+++ b/etc/logging.conf.sample
@@ -1,5 +1,5 @@
 [loggers]
-keys=root,tempest
+keys=root,tempest,tempest_stress
 
 [handlers]
 keys=file,syslog,devel
@@ -16,6 +16,11 @@
 handlers=file
 qualname=tempest
 
+[logger_tempest_stress]
+level=INFO
+handlers=file,devel
+qualname=tempest.stress
+
 [handler_file]
 class=FileHandler
 level=DEBUG
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 3aa0497..f1aaa07 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -10,6 +10,8 @@
 # lock/semaphore base directory
 lock_path=/tmp
 
+default_log_levels=tempest.stress=INFO,amqplib=WARN,sqlalchemy=WARN,boto=WARN,suds=INFO,keystone=INFO,eventlet.wsgi.server=WARN
+
 [identity]
 # This section contains configuration options that a variety of Tempest
 # test clients use when authenticating with different user/tenant
@@ -98,7 +100,7 @@
 fixed_network_name = private
 
 # Network id used for SSH (public, private, etc)
-network_for_ssh = private
+network_for_ssh = public
 
 # IP version of the address used for SSH
 ip_version_for_ssh = 4
@@ -267,6 +269,8 @@
 # Number of seconds to wait while looping to check the status of a
 # container to container synchronization
 container_sync_interval = 5
+# Set to True if the Account Quota middleware is enabled
+accounts_quotas_available = True
 
 [boto]
 # This section contains configuration options used when executing tests
@@ -365,6 +369,8 @@
 enabled = True
 # directory where python client binaries are located
 cli_dir = /usr/local/bin
+# Number of seconds to wait on a CLI timeout
+timeout = 15
 
 [service_available]
 # Whether or not cinder is expected to be available
diff --git a/run_tests.sh b/run_tests.sh
index a645b22..f8636c1 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -11,23 +11,22 @@
   echo "  -u, --update             Update the virtual environment with any newer package versions"
   echo "  -s, --smoke              Only run smoke tests"
   echo "  -w, --whitebox           Only run whitebox tests"
-  echo "  -t, --with-testr         Run using testr instead of nose"
+  echo "  -t, --parallel           Run testr parallel"
   echo "  -c, --nova-coverage      Enable Nova coverage collection"
   echo "  -C, --config             Config file location"
   echo "  -p, --pep8               Just run pep8"
   echo "  -h, --help               Print this usage message"
   echo "  -d, --debug              Debug this script -- set -o xtrace"
-  echo "  -S, --stdout             Don't capture stdout"
   echo "  -l, --logging            Enable logging"
   echo "  -L, --logging-config     Logging config file location.  Default is etc/logging.conf"
-  echo "  -- [NOSEOPTIONS]         After the first '--' you can pass arbitrary arguments to nosetests "
+  echo "  -- [TESTROPTIONS]        After the first '--' you can pass arbitrary arguments to testr "
 }
 
-noseargs=""
+testrargs=""
 just_pep8=0
 venv=.venv
 with_venv=tools/with_venv.sh
-with_testr=0
+parallel=0
 always_venv=0
 never_venv=0
 no_site_packages=0
@@ -39,7 +38,7 @@
 logging=0
 logging_config=etc/logging.conf
 
-if ! options=$(getopt -o VNnfuswtcphdSC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,whitebox,with-testr,nova-coverage,pep8,help,debug,stdout,config:,logging,logging-config: -- "$@")
+if ! options=$(getopt -o VNnfuswtcphdC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,whitebox,parallel,nova-coverage,pep8,help,debug,config:,logging,logging-config: -- "$@")
 then
     # parse error
     usage
@@ -60,14 +59,13 @@
     -c|--nova-coverage) let nova_coverage=1;;
     -C|--config) config_file=$2; shift;;
     -p|--pep8) let just_pep8=1;;
-    -s|--smoke) noseargs="$noseargs --attr=type=smoke";;
-    -w|--whitebox) noseargs="$noseargs --attr=type=whitebox";;
-    -t|--with-testr) with_testr=1;;
-    -S|--stdout) noseargs="$noseargs -s";;
+    -s|--smoke) testrargs="$testrargs smoke";;
+    -w|--whitebox) testrargs="$testrargs whitebox";;
+    -t|--parallel) parallel=1;;
     -l|--logging) logging=1;;
     -L|--logging-config) logging_config=$2; shift;;
-    --) [ "yes" == "$first_uu" ] || noseargs="$noseargs $1"; first_uu=no  ;;
-    *) noseargs="$noseargs $1"
+    --) [ "yes" == "$first_uu" ] || testrargs="$testrargs $1"; first_uu=no  ;;
+    *) testrargs="$testrargs $1"
   esac
   shift
 done
@@ -90,24 +88,10 @@
 
 cd `dirname "$0"`
 
-export NOSE_WITH_OPENSTACK=1
-export NOSE_OPENSTACK_COLOR=1
-export NOSE_OPENSTACK_RED=15.00
-export NOSE_OPENSTACK_YELLOW=3.00
-export NOSE_OPENSTACK_SHOW_ELAPSED=1
-export NOSE_OPENSTACK_STDOUT=1
-
 if [ $no_site_packages -eq 1 ]; then
   installvenvopts="--no-site-packages"
 fi
 
-# only add tempest default if we don't specify a test
-if [[ "x$noseargs" =~ "tempest" ]]; then
-  noseargs="$noseargs"
-else
-  noseargs="$noseargs tempest"
-fi
-
 function testr_init {
   if [ ! -d .testrepository ]; then
       ${wrapper} testr init
@@ -115,12 +99,12 @@
 }
 
 function run_tests {
-  if [ $with_testr -eq 1 ]; then
-      testr_init
-      ${wrapper} find . -type f -name "*.pyc" -delete
-      ${wrapper} testr run --parallel --subunit $noseargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
+  testr_init
+  ${wrapper} find . -type f -name "*.pyc" -delete
+  if [ $parallel -eq 1 ]; then
+      ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
   else
-      ${wrapper} $NOSETESTS
+      ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
   fi
 }
 
@@ -139,8 +123,6 @@
   ${wrapper} python tools/tempest_coverage.py -c report
 }
 
-NOSETESTS="nosetests $noseargs"
-
 if [ $never_venv -eq 0 ]
 then
   # Remove the virtual environment if --force used
@@ -187,7 +169,7 @@
     run_coverage_report
 fi
 
-if [ -z "$noseargs" ]; then
+if [ -z "$testrargs" ]; then
     run_pep8
 fi
 
diff --git a/setup.cfg b/setup.cfg
index 3b13b60..7cfc4ce 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -35,3 +35,6 @@
 #                coverage http://pypi.python.org/pypi/coverage
 #                openstack-nose https://github.com/openstack-dev/openstack-nose
 verbosity=2
+
+[pbr]
+autodoc_tree_index_modules=true
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 64f1854..14eced2 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -89,23 +89,6 @@
         self.assertRaises(exceptions.BadRequest, self.client.create_image,
                           self.server['id'], snapshot_name, meta)
 
-    @testtools.skipUnless(compute.MULTI_USER,
-                          'Need multiple users for this test.')
-    @attr(type=['negative', 'gate'])
-    def test_delete_image_of_another_tenant(self):
-        # Return an error while trying to delete another tenant's image
-        self.servers_client.wait_for_server_status(self.server['id'], 'ACTIVE')
-        snapshot_name = rand_name('test-snap-')
-        resp, body = self.client.create_image(self.server['id'], snapshot_name)
-        image_id = parse_image_id(resp['location'])
-        self.image_ids.append(image_id)
-        self.client.wait_for_image_resp_code(image_id, 200)
-        self.client.wait_for_image_status(image_id, 'ACTIVE')
-
-        # Delete image
-        self.assertRaises(exceptions.NotFound,
-                          self.alt_client.delete_image, image_id)
-
     def _get_default_flavor_disk_size(self, flavor_id):
         resp, flavor = self.flavors_client.get_flavor_details(flavor_id)
         return flavor['disk']
@@ -144,16 +127,6 @@
         self.assertEqual('204', resp['status'])
         self.client.wait_for_resource_deletion(image_id)
 
-    @testtools.skipUnless(compute.MULTI_USER,
-                          'Need multiple users for this test.')
-    @attr(type=['negative', 'gate'])
-    def test_create_image_for_server_in_another_tenant(self):
-        # Creating image of another tenant's server should be return error
-
-        snapshot_name = rand_name('test-snap-')
-        self.assertRaises(exceptions.NotFound, self.alt_client.create_image,
-                          self.server['id'], snapshot_name)
-
     @attr(type=['negative', 'gate'])
     def test_create_second_image_when_first_image_is_being_saved(self):
         # Disallow creating another image when first image is being saved
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index 697a839..5f8606e 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -107,6 +107,8 @@
                          "The fetched Security Group is different "
                          "from the created Group")
 
+    @testtools.skipIf(config.TempestConfig().service_available.neutron,
+                      "Skipped until the Bug #1182384 is resolved")
     @attr(type=['negative', 'gate'])
     def test_security_group_get_nonexistant_group(self):
         # Negative test:Should not be able to GET the details
@@ -191,6 +193,8 @@
                           self.client.delete_security_group,
                           default_security_group_id)
 
+    @testtools.skipIf(config.TempestConfig().service_available.neutron,
+                      "Skipped until the Bug #1182384 is resolved")
     @attr(type=['negative', 'gate'])
     def test_delete_nonexistant_security_group(self):
         # Negative test:Deletion of a nonexistant Security Group should Fail
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 66d8264..893d9e0 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -279,6 +279,15 @@
         cls.server_id = server['id']
         cls.password = server['adminPass']
 
+    @attr(type='gate')
+    def test_stop_start_server(self):
+        resp, server = self.servers_client.stop(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
+        resp, server = self.servers_client.start(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+
 
 class ServerActionsTestXML(ServerActionsTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 703f143..e09a23f 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -255,6 +255,20 @@
         self.assertRaises(exceptions.NotFound, self.client.get_server,
                           '999erra43')
 
+    @attr(type=['negative', 'gate'])
+    def test_stop_non_existent_server(self):
+        # Stop a non existent server
+        non_exist_id = rand_name('non-existent-server')
+        self.assertRaises(exceptions.NotFound, self.servers_client.stop,
+                          non_exist_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_pause_non_existent_server(self):
+        # pause a non existent server
+        non_exist_id = rand_name('non-existent-server')
+        self.assertRaises(exceptions.NotFound, self.client.pause_server,
+                          non_exist_id)
+
 
 class ServersNegativeTestXML(ServersNegativeTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
new file mode 100644
index 0000000..bc050dc
--- /dev/null
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -0,0 +1,115 @@
+# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+#
+# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
+#
+# 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 testtools
+
+from tempest.api.object_storage import base
+from tempest import clients
+from tempest.common.utils.data_utils import arbitrary_string
+from tempest.common.utils.data_utils import rand_name
+import tempest.config
+from tempest import exceptions
+from tempest.test import attr
+
+
+class AccountQuotasTest(base.BaseObjectTest):
+    accounts_quotas_available = \
+        tempest.config.TempestConfig().object_storage.accounts_quotas_available
+
+    @classmethod
+    def setUpClass(cls):
+        super(AccountQuotasTest, cls).setUpClass()
+        cls.container_name = rand_name(name="TestContainer")
+        cls.container_client.create_container(cls.container_name)
+
+        cls.data.setup_test_user()
+
+        cls.os_reselleradmin = clients.Manager(
+            cls.data.test_user,
+            cls.data.test_password,
+            cls.data.test_tenant)
+
+        # Retrieve the ResellerAdmin role id
+        reseller_role_id = None
+        try:
+            _, roles = cls.os_admin.identity_client.list_roles()
+            reseller_role_id = next(r['id'] for r in roles if r['name']
+                                    == 'ResellerAdmin')
+        except StopIteration:
+            msg = "No ResellerAdmin role found"
+            raise exceptions.NotFound(msg)
+
+        # Retrieve the ResellerAdmin tenant id
+        _, users = cls.os_admin.identity_client.get_users()
+        reseller_user_id = next(usr['id'] for usr in users if usr['name']
+                                == cls.data.test_user)
+
+        # Retrieve the ResellerAdmin tenant id
+        _, tenants = cls.os_admin.identity_client.list_tenants()
+        reseller_tenant_id = next(tnt['id'] for tnt in tenants if tnt['name']
+                                  == cls.data.test_tenant)
+
+        # Assign the newly created user the appropriate ResellerAdmin role
+        cls.os_admin.identity_client.assign_user_role(
+            reseller_tenant_id,
+            reseller_user_id,
+            reseller_role_id)
+
+        # Retrieve a ResellerAdmin auth token and use it to set a quota
+        # on the client's account
+        cls.reselleradmin_token = cls.token_client.get_token(
+            cls.data.test_user,
+            cls.data.test_password,
+            cls.data.test_tenant)
+
+        headers = {"X-Auth-Token": cls.reselleradmin_token,
+                   "X-Account-Meta-Quota-Bytes": "20"}
+
+        cls.os.custom_account_client.request("POST", "", headers, "")
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.delete_containers([cls.container_name])
+        cls.data.teardown_all()
+
+        # remove the quota from the container
+        headers = {"X-Auth-Token": cls.reselleradmin_token,
+                   "X-Remove-Account-Meta-Quota-Bytes": "x"}
+
+        cls.os.custom_account_client.request("POST", "", headers, "")
+
+        super(AccountQuotasTest, cls).tearDownClass()
+
+    @testtools.skipIf(not accounts_quotas_available,
+                      "Account Quotas middleware not available")
+    @attr(type="smoke")
+    def test_upload_valid_object(self):
+        object_name = rand_name(name="TestObject")
+        data = arbitrary_string()
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   object_name, data)
+
+        self.assertEqual(resp["status"], "201")
+
+    @testtools.skipIf(not accounts_quotas_available,
+                      "Account Quotas middleware not available")
+    @attr(type=["negative", "smoke"])
+    def test_upload_large_object(self):
+        object_name = rand_name(name="TestObject")
+        data = arbitrary_string(30)
+        self.assertRaises(exceptions.OverLimit,
+                          self.object_client.create_object,
+                          self.container_name, object_name, data)
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
new file mode 100644
index 0000000..1a31b91
--- /dev/null
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -0,0 +1,225 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack, LLC
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.object_storage import base
+from tempest.common.utils.data_utils import rand_name
+from tempest import exceptions
+from tempest.test import attr
+from tempest.test import HTTP_SUCCESS
+
+
+class ObjectTestACLs(base.BaseObjectTest):
+    @classmethod
+    def setUpClass(cls):
+        super(ObjectTestACLs, cls).setUpClass()
+        cls.data.setup_test_user()
+        cls.new_token = cls.token_client.get_token(cls.data.test_user,
+                                                   cls.data.test_password,
+                                                   cls.data.test_tenant)
+        cls.custom_headers = {'X-Auth-Token': cls.new_token}
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.data.teardown_all()
+        super(ObjectTestACLs, cls).tearDownClass()
+
+    def setUp(self):
+        super(ObjectTestACLs, self).setUp()
+        self.container_name = rand_name(name='TestContainer')
+        self.container_client.create_container(self.container_name)
+
+    def tearDown(self):
+        self.delete_containers([self.container_name])
+        super(ObjectTestACLs, self).tearDown()
+
+    @attr(type=['negative', 'gate'])
+    def test_write_object_without_using_creds(self):
+        # trying to create object with empty headers
+        # X-Auth-Token is not provided
+        object_name = rand_name(name='Object')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.create_object,
+                          self.container_name, object_name, 'data')
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_object_without_using_creds(self):
+        # create object
+        object_name = rand_name(name='Object')
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   object_name, 'data')
+        # trying to delete object with empty headers
+        # X-Auth-Token is not provided
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.delete_object,
+                          self.container_name, object_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_write_object_with_non_authorized_user(self):
+        # attempt to upload another file using non-authorized user
+        # User provided token is forbidden. ACL are not set
+        object_name = rand_name(name='Object')
+        # trying to create object with non-authorized user
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.create_object,
+                          self.container_name, object_name, 'data',
+                          metadata=self.custom_headers)
+
+    @attr(type=['negative', 'gate'])
+    def test_read_object_with_non_authorized_user(self):
+        # attempt to read object using non-authorized user
+        # User provided token is forbidden. ACL are not set
+        object_name = rand_name(name='Object')
+        resp, _ = self.object_client.create_object(
+            self.container_name, object_name, 'data')
+        self.assertEqual(resp['status'], '201')
+        # trying to get object with non authorized user token
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.get_object,
+                          self.container_name, object_name,
+                          metadata=self.custom_headers)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_object_with_non_authorized_user(self):
+        # attempt to delete object using non-authorized user
+        # User provided token is forbidden. ACL are not set
+        object_name = rand_name(name='Object')
+        resp, _ = self.object_client.create_object(
+            self.container_name, object_name, 'data')
+        self.assertEqual(resp['status'], '201')
+        # trying to delete object with non-authorized user token
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.delete_object,
+                          self.container_name, object_name,
+                          metadata=self.custom_headers)
+
+    @attr(type=['negative', 'smoke'])
+    def test_read_object_without_rights(self):
+        # attempt to read object using non-authorized user
+        # update X-Container-Read metadata ACL
+        cont_headers = {'X-Container-Read': 'badtenant:baduser'}
+        resp_meta, body = self.container_client.update_container_metadata(
+            self.container_name, metadata=cont_headers,
+            metadata_prefix='')
+        self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        # create object
+        object_name = rand_name(name='Object')
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   object_name, 'data')
+        self.assertEqual(resp['status'], '201')
+        # Trying to read the object without rights
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.get_object,
+                          self.container_name, object_name,
+                          metadata=self.custom_headers)
+
+    @attr(type=['negative', 'smoke'])
+    def test_write_object_without_rights(self):
+        # attempt to write object using non-authorized user
+        # update X-Container-Write metadata ACL
+        cont_headers = {'X-Container-Write': 'badtenant:baduser'}
+        resp_meta, body = self.container_client.update_container_metadata(
+            self.container_name, metadata=cont_headers,
+            metadata_prefix='')
+        self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        # Trying to write the object without rights
+        object_name = rand_name(name='Object')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.create_object,
+                          self.container_name,
+                          object_name, 'data',
+                          metadata=self.custom_headers)
+
+    @attr(type='smoke')
+    def test_read_object_with_rights(self):
+        # attempt to read object using authorized user
+        # update X-Container-Read metadata ACL
+        cont_headers = {'X-Container-Read':
+                        self.data.test_tenant + ':' + self.data.test_user}
+        resp_meta, body = self.container_client.update_container_metadata(
+            self.container_name, metadata=cont_headers,
+            metadata_prefix='')
+        self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        # create object
+        object_name = rand_name(name='Object')
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   object_name, 'data')
+        self.assertEqual(resp['status'], '201')
+        # Trying to read the object with rights
+        resp, _ = self.custom_object_client.get_object(
+            self.container_name, object_name,
+            metadata=self.custom_headers)
+        self.assertIn(int(resp['status']), HTTP_SUCCESS)
+
+    @attr(type='smoke')
+    def test_write_object_with_rights(self):
+        # attempt to write object using authorized user
+        # update X-Container-Write metadata ACL
+        cont_headers = {'X-Container-Write':
+                        self.data.test_tenant + ':' + self.data.test_user}
+        resp_meta, body = self.container_client.update_container_metadata(
+            self.container_name, metadata=cont_headers,
+            metadata_prefix='')
+        self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        # Trying to write the object with rights
+        object_name = rand_name(name='Object')
+        resp, _ = self.custom_object_client.create_object(
+            self.container_name,
+            object_name, 'data',
+            metadata=self.custom_headers)
+        self.assertIn(int(resp['status']), HTTP_SUCCESS)
+
+    @attr(type=['negative', 'smoke'])
+    def test_write_object_without_write_rights(self):
+        # attempt to write object using non-authorized user
+        # update X-Container-Read and X-Container-Write metadata ACL
+        cont_headers = {'X-Container-Read':
+                        self.data.test_tenant + ':' + self.data.test_user,
+                        'X-Container-Write': ''}
+        resp_meta, body = self.container_client.update_container_metadata(
+            self.container_name, metadata=cont_headers,
+            metadata_prefix='')
+        self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        # Trying to write the object without write rights
+        object_name = rand_name(name='Object')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.create_object,
+                          self.container_name,
+                          object_name, 'data',
+                          metadata=self.custom_headers)
+
+    @attr(type=['negative', 'smoke'])
+    def test_delete_object_without_write_rights(self):
+        # attempt to delete object using non-authorized user
+        # update X-Container-Read and X-Container-Write metadata ACL
+        cont_headers = {'X-Container-Read':
+                        self.data.test_tenant + ':' + self.data.test_user,
+                        'X-Container-Write': ''}
+        resp_meta, body = self.container_client.update_container_metadata(
+            self.container_name, metadata=cont_headers,
+            metadata_prefix='')
+        self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        # create object
+        object_name = rand_name(name='Object')
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   object_name, 'data')
+        self.assertEqual(resp['status'], '201')
+        # Trying to delete the object without write rights
+        self.assertRaises(exceptions.Unauthorized,
+                          self.custom_object_client.delete_object,
+                          self.container_name,
+                          object_name,
+                          metadata=self.custom_headers)
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 6136216..c8d9965 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -21,7 +21,6 @@
 from tempest.api.object_storage import base
 from tempest.common.utils.data_utils import arbitrary_string
 from tempest.common.utils.data_utils import rand_name
-from tempest import exceptions
 from tempest.test import attr
 from tempest.test import HTTP_SUCCESS
 
@@ -230,74 +229,6 @@
             self.fail("Got exception :%s ; while copying"
                       " object across containers" % e)
 
-    @attr(type=['negative', 'gate'])
-    def test_write_object_without_using_creds(self):
-        # trying to create object with empty headers
-        object_name = rand_name(name='Object')
-        data = arbitrary_string(size=len(object_name),
-                                base_text=object_name)
-        obj_headers = {'Content-Type': 'application/json',
-                       'Accept': 'application/json'}
-        self.assertRaises(exceptions.Unauthorized,
-                          self.custom_object_client.create_object,
-                          self.container_name, object_name, data,
-                          metadata=obj_headers)
-
-    @attr(type=['negative', 'gate'])
-    def test_delete_object_without_using_creds(self):
-        # create object
-        object_name = rand_name(name='Object')
-        data = arbitrary_string(size=len(object_name),
-                                base_text=object_name)
-        resp, _ = self.object_client.create_object(self.container_name,
-                                                   object_name, data)
-        # trying to delete object with empty headers
-        self.assertRaises(exceptions.Unauthorized,
-                          self.custom_object_client.delete_object,
-                          self.container_name, object_name)
-
-    @attr(type=['negative', 'gate'])
-    def test_write_object_with_non_authorized_user(self):
-        # attempt to upload another file using non-authorized user
-        object_name = rand_name(name='Object')
-        data = arbitrary_string(size=len(object_name) * 5,
-                                base_text=object_name)
-
-        # trying to create object with non-authorized user
-        self.assertRaises(exceptions.Unauthorized,
-                          self.custom_object_client.create_object,
-                          self.container_name, object_name, data,
-                          metadata=self.custom_headers)
-
-    @attr(type=['negative', 'gate'])
-    def test_read_object_with_non_authorized_user(self):
-        object_name = rand_name(name='Object')
-        data = arbitrary_string(size=len(object_name) * 5,
-                                base_text=object_name)
-        resp, body = self.object_client.create_object(
-            self.container_name, object_name, data)
-        self.assertEqual(resp['status'], '201')
-
-        # trying to get object with non authorized user token
-        self.assertRaises(exceptions.Unauthorized,
-                          self.custom_object_client.get_object,
-                          self.container_name, object_name,
-                          metadata=self.custom_headers)
-
-    @attr(type=['negative', 'gate'])
-    def test_delete_object_with_non_authorized_user(self):
-        object_name = rand_name(name='Object')
-        data = arbitrary_string(size=len(object_name) * 5,
-                                base_text=object_name)
-        resp, body = self.object_client.create_object(
-            self.container_name, object_name, data)
-        self.assertEqual(resp['status'], '201')
-        # trying to delete object with non-authorized user token
-        self.assertRaises(exceptions.Unauthorized,
-                          self.custom_object_client.delete_object,
-                          self.container_name, object_name,
-                          metadata=self.custom_headers)
-
     @attr(type='gate')
     def test_get_object_using_temp_url(self):
         # access object using temporary URL within expiration time
diff --git a/tempest/api/orchestration/stacks/test_instance_cfn_init.py b/tempest/api/orchestration/stacks/test_instance_cfn_init.py
index 7897b70..fe55ecf 100644
--- a/tempest/api/orchestration/stacks/test_instance_cfn_init.py
+++ b/tempest/api/orchestration/stacks/test_instance_cfn_init.py
@@ -145,7 +145,7 @@
                 'ImageId': cls.orchestration_cfg.image_ref
             })
 
-    @attr(type='gate')
+    @attr(type='slow')
     @testtools.skipIf(existing_keypair, 'Server ssh tests are disabled.')
     def test_can_log_into_created_server(self):
 
@@ -168,7 +168,7 @@
             server, 'ec2-user', pkey=self.keypair['private_key'])
         self.assertTrue(linux_client.can_authenticate())
 
-    @attr(type='gate')
+    @attr(type='slow')
     def test_stack_wait_condition_data(self):
 
         sid = self.stack_identifier
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index 00e025d..f04d23f 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -35,6 +35,9 @@
     cfg.StrOpt('cli_dir',
                default='/usr/local/bin/',
                help="directory where python client binaries are located"),
+    cfg.IntOpt('timeout',
+               default=15,
+               help="Number of seconds to wait on a CLI timeout"),
 ]
 
 CONF = cfg.CONF
diff --git a/tempest/cli/simple_read_only/test_compute.py b/tempest/cli/simple_read_only/test_compute.py
index e60e238..4c7f604 100644
--- a/tempest/cli/simple_read_only/test_compute.py
+++ b/tempest/cli/simple_read_only/test_compute.py
@@ -176,7 +176,7 @@
         self.nova('list', flags='--debug')
 
     def test_admin_timeout(self):
-        self.nova('list', flags='--timeout 2')
+        self.nova('list', flags='--timeout %d' % CONF.cli.timeout)
 
     def test_admin_timing(self):
         self.nova('list', flags='--timing')
diff --git a/tempest/cli/simple_read_only/test_keystone.py b/tempest/cli/simple_read_only/test_keystone.py
index 4002081..4c7982b 100644
--- a/tempest/cli/simple_read_only/test_keystone.py
+++ b/tempest/cli/simple_read_only/test_keystone.py
@@ -18,9 +18,13 @@
 import re
 import subprocess
 
+from oslo.config import cfg
+
 import tempest.cli
 from tempest.openstack.common import log as logging
 
+CONF = cfg.CONF
+
 
 LOG = logging.getLogger(__name__)
 
@@ -117,4 +121,4 @@
         self.keystone('catalog', flags='--debug')
 
     def test_admin_timeout(self):
-        self.keystone('catalog', flags='--timeout 15')
+        self.keystone('catalog', flags='--timeout %d' % CONF.cli.timeout)
diff --git a/tempest/config.py b/tempest/config.py
index 19170ae..9b1a91e 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -366,6 +366,9 @@
                default=5,
                help="Number of seconds to wait while looping to check the"
                     "status of a container to container synchronization"),
+    cfg.BoolOpt('accounts_quotas_available',
+                default=True,
+                help="Set to True if the Account Quota middleware is enabled"),
 ]
 
 
diff --git a/tempest/stress/README.rst b/tempest/stress/README.rst
index 31642b0..7c180f6 100644
--- a/tempest/stress/README.rst
+++ b/tempest/stress/README.rst
@@ -23,7 +23,8 @@
 	target_controller = "hostname or ip of controller node (for nova-manage)
 	log_check_interval = "time between checking logs for errors (default 60s)"
 
-
+To activate logging on your console please make sure that you activate `use_stderr`
+in tempest.conf or use the default `logging.conf.sample` file.
 
 Running the sample test
 -----------------------
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index bfcf34f..1bd9485 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -17,13 +17,16 @@
 #    limitations under the License.
 
 from tempest import clients
+from tempest.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
 
 
-def cleanup(logger):
+def cleanup():
     admin_manager = clients.AdminManager()
 
     _, body = admin_manager.servers_client.list_servers({"all_tenants": True})
-    logger.debug("Cleanup::remove %s servers" % len(body['servers']))
+    LOG.info("Cleanup::remove %s servers" % len(body['servers']))
     for s in body['servers']:
         try:
             admin_manager.servers_client.delete_server(s['id'])
@@ -37,7 +40,7 @@
             pass
 
     _, keypairs = admin_manager.keypairs_client.list_keypairs()
-    logger.debug("Cleanup::remove %s keypairs" % len(keypairs))
+    LOG.info("Cleanup::remove %s keypairs" % len(keypairs))
     for k in keypairs:
         try:
             admin_manager.keypairs_client.delete_keypair(k['name'])
@@ -45,7 +48,7 @@
             pass
 
     _, floating_ips = admin_manager.floating_ips_client.list_floating_ips()
-    logger.debug("Cleanup::remove %s floating ips" % len(floating_ips))
+    LOG.info("Cleanup::remove %s floating ips" % len(floating_ips))
     for f in floating_ips:
         try:
             admin_manager.floating_ips_client.delete_floating_ip(f['id'])
@@ -53,13 +56,13 @@
             pass
 
     _, users = admin_manager.identity_client.get_users()
-    logger.debug("Cleanup::remove %s users" % len(users))
+    LOG.info("Cleanup::remove %s users" % len(users))
     for user in users:
         if user['name'].startswith("stress_user"):
             admin_manager.identity_client.delete_user(user['id'])
 
     _, tenants = admin_manager.identity_client.list_tenants()
-    logger.debug("Cleanup::remove %s tenants" % len(tenants))
+    LOG.info("Cleanup::remove %s tenants" % len(tenants))
     for tenant in tenants:
         if tenant['name'].startswith("stress_tenant"):
             admin_manager.identity_client.delete_tenant(tenant['id'])
@@ -69,7 +72,7 @@
 
     _, snaps = admin_manager.snapshots_client.\
         list_snapshots({"all_tenants": True})
-    logger.debug("Cleanup::remove %s snapshots" % len(snaps))
+    LOG.info("Cleanup::remove %s snapshots" % len(snaps))
     for v in snaps:
         try:
             admin_manager.snapshots_client.\
@@ -85,7 +88,7 @@
             pass
 
     _, vols = admin_manager.volumes_client.list_volumes({"all_tenants": True})
-    logger.debug("Cleanup::remove %s volumes" % len(vols))
+    LOG.info("Cleanup::remove %s volumes" % len(vols))
     for v in vols:
         try:
             admin_manager.volumes_client.\
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index d9b95e0..efc57a9 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -12,7 +12,6 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 
-import logging
 import multiprocessing
 import signal
 import time
@@ -22,30 +21,12 @@
 from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 from tempest.openstack.common import importutils
+from tempest.openstack.common import log as logging
 from tempest.stress import cleanup
 
 admin_manager = clients.AdminManager()
 
-# setup logging to file
-logging.basicConfig(
-    format='%(asctime)s %(process)d %(name)-20s %(levelname)-8s %(message)s',
-    datefmt='%m-%d %H:%M:%S',
-    filename="stress.debug.log",
-    filemode="w",
-    level=logging.DEBUG,
-)
-
-# define a Handler which writes INFO messages or higher to the sys.stdout
-_console = logging.StreamHandler()
-_console.setLevel(logging.INFO)
-# set a format which is simpler for console use
-format_str = '%(asctime)s %(process)d %(name)-20s: %(levelname)-8s %(message)s'
-_formatter = logging.Formatter(format_str)
-# tell the handler to use this format
-_console.setFormatter(_formatter)
-# add the handler to the root logger
-logger = logging.getLogger('tempest.stress')
-logger.addHandler(_console)
+LOG = logging.getLogger(__name__)
 processes = []
 
 
@@ -90,7 +71,7 @@
         if not errors:
             return None
         if len(errors) > 0:
-            logger.error('%s: %s' % (node, errors))
+            LOG.error('%s: %s' % (node, errors))
             return errors
     return None
 
@@ -147,13 +128,13 @@
                                           tenant_name=tenant_name)
 
             test_obj = importutils.import_class(test['action'])
-            test_run = test_obj(manager, logger, max_runs, stop_on_error)
+            test_run = test_obj(manager, max_runs, stop_on_error)
 
             kwargs = test.get('kwargs', {})
             test_run.setUp(**dict(kwargs.iteritems()))
 
-            logger.debug("calling Target Object %s" %
-                         test_run.__class__.__name__)
+            LOG.debug("calling Target Object %s" %
+                      test_run.__class__.__name__)
 
             mp_manager = multiprocessing.Manager()
             shared_statistic = mp_manager.dict()
@@ -208,24 +189,24 @@
     sum_fails = 0
     sum_runs = 0
 
-    logger.info("Statistics (per process):")
+    LOG.info("Statistics (per process):")
     for process in processes:
         if process['statistic']['fails'] > 0:
             had_errors = True
         sum_runs += process['statistic']['runs']
         sum_fails += process['statistic']['fails']
-        logger.info(" Process %d (%s): Run %d actions (%d failed)" %
-                    (process['p_number'],
-                     process['action'],
-                     process['statistic']['runs'],
+        LOG.info(" Process %d (%s): Run %d actions (%d failed)" %
+                 (process['p_number'],
+                  process['action'],
+                  process['statistic']['runs'],
                      process['statistic']['fails']))
-    logger.info("Summary:")
-    logger.info("Run %d actions (%d failed)" %
-                (sum_runs, sum_fails))
+    LOG.info("Summary:")
+    LOG.info("Run %d actions (%d failed)" %
+             (sum_runs, sum_fails))
 
     if not had_errors:
-        logger.info("cleaning up")
-        cleanup.cleanup(logger)
+        LOG.info("cleaning up")
+        cleanup.cleanup()
     if had_errors:
         return 1
     else:
diff --git a/tempest/stress/stressaction.py b/tempest/stress/stressaction.py
index ab09adc..3719841 100644
--- a/tempest/stress/stressaction.py
+++ b/tempest/stress/stressaction.py
@@ -17,12 +17,15 @@
 import signal
 import sys
 
+from tempest.openstack.common import log as logging
+
 
 class StressAction(object):
 
-    def __init__(self, manager, logger, max_runs=None, stop_on_error=False):
+    def __init__(self, manager, max_runs=None, stop_on_error=False):
+        full_cname = self.__module__ + "." + self.__class__.__name__
+        self.logger = logging.getLogger(full_cname)
         self.manager = manager
-        self.logger = logger
         self.max_runs = max_runs
         self.stop_on_error = stop_on_error
 
diff --git a/tempest/stress/tools/cleanup.py b/tempest/stress/tools/cleanup.py
index b6a26cd..3885ba0 100755
--- a/tempest/stress/tools/cleanup.py
+++ b/tempest/stress/tools/cleanup.py
@@ -14,15 +14,6 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 
-import logging
-
 from tempest.stress import cleanup
 
-_console = logging.StreamHandler()
-_console.setLevel(logging.DEBUG)
-# add the handler to the root logger
-logger = logging.getLogger('tempest.stress.cleanup')
-logger.addHandler(logging.StreamHandler())
-logger.setLevel(logging.DEBUG)
-
-cleanup.cleanup(logger)
+cleanup.cleanup()
diff --git a/tools/pretty_tox_serial.sh b/tools/pretty_tox_serial.sh
index 490d263..dd7b682 100755
--- a/tools/pretty_tox_serial.sh
+++ b/tools/pretty_tox_serial.sh
@@ -5,5 +5,5 @@
 if [ ! -d .testrepository ]; then
     testr init
 fi
-testr run --subunit $TESTRARGS | subunit-2to1 | tools/colorizer.py
+testr run --subunit $TESTRARGS | subunit2pyunit
 testr slowest
diff --git a/tox.ini b/tox.ini
index c3562e6..53f85c1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,22 +13,11 @@
 commands =
   python setup.py testr --slowest
 
-
 [testenv:full]
 sitepackages = True
 setenv = VIRTUAL_ENV={envdir}
-         NOSE_WITH_OPENSTACK=1
-         NOSE_OPENSTACK_COLOR=1
-         NOSE_OPENSTACK_RED=15
-         NOSE_OPENSTACK_YELLOW=3
-         NOSE_OPENSTACK_SHOW_ELAPSED=1
-         NOSE_OPENSTACK_STDOUT=1
-commands =
-  nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit --xunit-file=nosetests-full.xml -sv tempest/api tempest/scenario tempest/thirdparty tempest/cli
-
-[testenv:testr-serial]
-sitepackages = True
-setenv = VIRTUAL_ENV={envdir}
+# The regex below is used to select which tests to run and exclude the slow tag:
+# See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610
 commands =
   sh tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
 
@@ -41,27 +30,15 @@
 [testenv:smoke]
 sitepackages = True
 setenv = VIRTUAL_ENV={envdir}
-         NOSE_WITH_OPENSTACK=1
-         NOSE_OPENSTACK_COLOR=1
-         NOSE_OPENSTACK_RED=15
-         NOSE_OPENSTACK_YELLOW=3
-         NOSE_OPENSTACK_SHOW_ELAPSED=1
-         NOSE_OPENSTACK_STDOUT=1
 commands =
-   nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit -sv --attr=type=smoke --xunit-file=nosetests-smoke.xml tempest
+   sh tools/pretty_tox_serial.sh 'smoke {posargs}'
 
 [testenv:coverage]
 sitepackages = True
 setenv = VIRTUAL_ENV={envdir}
-         NOSE_WITH_OPENSTACK=1
-         NOSE_OPENSTACK_COLOR=1
-         NOSE_OPENSTACK_RED=15
-         NOSE_OPENSTACK_YELLOW=3
-         NOSE_OPENSTACK_SHOW_ELAPSED=1
-         NOSE_OPENSTACK_STDOUT=1
 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
+   sh tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
    python -m tools/tempest_coverage -c report --html {posargs}
 
 [testenv:stress]