Merge "add tests - list hosts tests using admin user"
diff --git a/doc/source/conf.py b/doc/source/conf.py
index fd8cbb5..178bf62 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -138,10 +138,10 @@
 #html_additional_pages = {}
 
 # If false, no module index is generated.
-#html_domain_indices = True
+html_domain_indices = False
 
 # If false, no index is generated.
-#html_use_index = True
+html_use_index = False
 
 # If true, the index is split into individual pages for each letter.
 #html_split_index = False
diff --git a/doc/source/index.rst b/doc/source/index.rst
index e8fdf2c..f012097 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -38,6 +38,4 @@
 Indices and tables
 ==================
 
-* :ref:`genindex`
-* :ref:`modindex`
 * :ref:`search`
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
new file mode 100644
index 0000000..cb47066
--- /dev/null
+++ b/tempest/api/compute/admin/test_servers.py
@@ -0,0 +1,64 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+#
+#    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.compute import base
+from tempest.common.utils.data_utils import rand_name
+from tempest.test import attr
+
+
+class ServersAdminTestJSON(base.BaseComputeAdminTest):
+
+    """
+    Tests Servers API using admin privileges
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServersAdminTestJSON, cls).setUpClass()
+        cls.client = cls.os_adm.servers_client
+
+        cls.s1_name = rand_name('server')
+        resp, server = cls.create_server(name=cls.s1_name,
+                                         wait_until='ACTIVE')
+        cls.s2_name = rand_name('server')
+        resp, server = cls.create_server(name=cls.s2_name,
+                                         wait_until='ACTIVE')
+
+    @attr(type='gate')
+    def test_list_servers_by_admin(self):
+        # Listing servers by admin user returns empty list by default
+        resp, body = self.client.list_servers_with_detail()
+        servers = body['servers']
+        self.assertEqual('200', resp['status'])
+        self.assertEqual([], servers)
+
+    @attr(type='gate')
+    def test_list_servers_by_admin_with_all_tenants(self):
+        # Listing servers by admin user with all tenants parameter
+        # Here should be listed all servers
+        params = {'all_tenants': ''}
+        resp, body = self.client.list_servers_with_detail(params)
+        servers = body['servers']
+        servers_name = map(lambda x: x['name'], servers)
+
+        self.assertIn(self.s1_name, servers_name)
+        self.assertIn(self.s2_name, servers_name)
+
+
+class ServersAdminTestXML(ServersAdminTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 5f53080..5cc8dc6 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -24,12 +24,12 @@
 from tempest.test import attr
 
 
-class ServersNegativeTest(base.BaseComputeTest):
+class ServersNegativeTestJSON(base.BaseComputeTest):
     _interface = 'json'
 
     @classmethod
     def setUpClass(cls):
-        super(ServersNegativeTest, cls).setUpClass()
+        super(ServersNegativeTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
         cls.img_client = cls.images_client
         cls.alt_os = clients.AltManager()
@@ -248,5 +248,5 @@
                           '999erra43')
 
 
-class ServersNegativeTestXML(ServersNegativeTest):
+class ServersNegativeTestXML(ServersNegativeTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index c029300..0bba250 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -15,7 +15,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
 from testtools.matchers._basic import Contains
 
 from tempest.api.identity import base
@@ -77,32 +76,6 @@
                           self.data.test_user, self.data.test_password,
                           self.data.tenant['id'], self.data.test_email)
 
-    @testtools.skip("Until Bug #999084 is fixed")
-    @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()
-        self.assertRaises(exceptions.BadRequest, self.client.create_user,
-                          self.alt_user, '', self.data.tenant['id'],
-                          self.alt_email)
-
-    @testtools.skip("Until Bug #999084 is fixed")
-    @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()
-        self.assertRaises(exceptions.BadRequest, self.client.create_user,
-                          self.alt_user, 'a' * 65, self.data.tenant['id'],
-                          self.alt_email)
-
-    @testtools.skip("Until Bug #999084 is fixed")
-    @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=['negative', 'gate'])
     def test_create_user_for_non_existant_tenant(self):
         # Attempt to create a user in a non-existent tenant should fail
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index fa8190a..6d6000a 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -33,6 +33,8 @@
         cls.orchestration_cfg = os.config.orchestration
         if not cls.orchestration_cfg.heat_available:
             raise cls.skipException("Heat support is required")
+        cls.build_timeout = cls.orchestration_cfg.build_timeout
+        cls.build_interval = cls.orchestration_cfg.build_interval
 
         cls.os = os
         cls.orchestration_client = os.orchestration_client
@@ -60,15 +62,15 @@
             cls.config.identity.uri
         )
 
-    def create_stack(self, stack_name, template_data, parameters={}):
-        resp, body = self.client.create_stack(
+    @classmethod
+    def create_stack(cls, stack_name, template_data, parameters={}):
+        resp, body = cls.client.create_stack(
             stack_name,
             template=template_data,
             parameters=parameters)
-        self.assertEqual('201', resp['status'])
         stack_id = resp['location'].split('/')[-1]
         stack_identifier = '%s/%s' % (stack_name, stack_id)
-        self.stacks.append(stack_identifier)
+        cls.stacks.append(stack_identifier)
         return stack_identifier
 
     @classmethod
@@ -86,11 +88,11 @@
             except Exception:
                 pass
 
-    def _create_keypair(self, namestart='keypair-heat-'):
+    @classmethod
+    def _create_keypair(cls, namestart='keypair-heat-'):
         kp_name = rand_name(namestart)
-        resp, body = self.keypairs_client.create_keypair(kp_name)
-        self.assertEqual(body['name'], kp_name)
-        self.keypairs.append(kp_name)
+        resp, body = cls.keypairs_client.create_keypair(kp_name)
+        cls.keypairs.append(kp_name)
         return body
 
     @classmethod
diff --git a/tempest/api/orchestration/stacks/test_instance_cfn_init.py b/tempest/api/orchestration/stacks/test_instance_cfn_init.py
index e3b8162..add8588 100644
--- a/tempest/api/orchestration/stacks/test_instance_cfn_init.py
+++ b/tempest/api/orchestration/stacks/test_instance_cfn_init.py
@@ -119,23 +119,21 @@
             raise cls.skipException("No image available to test")
         cls.client = cls.orchestration_client
 
-    def setUp(self):
-        super(InstanceCfnInitTestJSON, self).setUp()
         stack_name = rand_name('heat')
-        if self.orchestration_cfg.keypair_name:
-            keypair_name = self.orchestration_cfg.keypair_name
+        if cls.orchestration_cfg.keypair_name:
+            keypair_name = cls.orchestration_cfg.keypair_name
         else:
-            self.keypair = self._create_keypair()
-            keypair_name = self.keypair['name']
+            cls.keypair = cls._create_keypair()
+            keypair_name = cls.keypair['name']
 
         # create the stack
-        self.stack_identifier = self.create_stack(
+        cls.stack_identifier = cls.create_stack(
             stack_name,
-            self.template,
+            cls.template,
             parameters={
                 'KeyName': keypair_name,
-                'InstanceType': self.orchestration_cfg.instance_type,
-                'ImageId': self.orchestration_cfg.image_ref
+                'InstanceType': cls.orchestration_cfg.instance_type,
+                'ImageId': cls.orchestration_cfg.image_ref
             })
 
     @attr(type='gate')
diff --git a/tempest/config.py b/tempest/config.py
index 8795b33..f6fd1d9 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -15,9 +15,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from __future__ import print_function
+
 import os
 import sys
 
+
 from oslo.config import cfg
 
 from tempest.common import log as logging
@@ -559,7 +562,7 @@
 
         if not os.path.exists(path):
             msg = "Config file %(path)s not found" % locals()
-            print >> sys.stderr, RuntimeError(msg)
+            print(RuntimeError(msg), file=sys.stderr)
         else:
             config_files.append(path)
 
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index d4822da..6906610 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -332,15 +332,6 @@
                                req_body, self.headers)
         return resp, body
 
-    def list_servers_for_all_tenants(self):
-
-        url = self.base_url + '/servers?all_tenants=1'
-        resp = self.requests.get(url)
-        resp, body = self.get('servers', self.headers)
-
-        body = json.loads(body)
-        return resp, body['servers']
-
     def migrate_server(self, server_id, **kwargs):
         """Migrates a server to a new host."""
         return self.action(server_id, 'migrate', None, **kwargs)
diff --git a/tempest/services/orchestration/json/orchestration_client.py b/tempest/services/orchestration/json/orchestration_client.py
index 6b0e7e3..22f3f26 100644
--- a/tempest/services/orchestration/json/orchestration_client.py
+++ b/tempest/services/orchestration/json/orchestration_client.py
@@ -46,6 +46,35 @@
 
     def create_stack(self, name, disable_rollback=True, parameters={},
                      timeout_mins=60, template=None, template_url=None):
+        headers, body = self._prepare_update_create(
+            name,
+            disable_rollback,
+            parameters,
+            timeout_mins,
+            template,
+            template_url)
+        uri = 'stacks'
+        resp, body = self.post(uri, headers=headers, body=body)
+        return resp, body
+
+    def update_stack(self, stack_identifier, name, disable_rollback=True,
+                     parameters={}, timeout_mins=60, template=None,
+                     template_url=None):
+        headers, body = self._prepare_update_create(
+            name,
+            disable_rollback,
+            parameters,
+            timeout_mins,
+            template,
+            template_url)
+
+        uri = "stacks/%s" % stack_identifier
+        resp, body = self.put(uri, headers=headers, body=body)
+        return resp, body
+
+    def _prepare_update_create(self, name, disable_rollback=True,
+                               parameters={}, timeout_mins=60,
+                               template=None, template_url=None):
         post_body = {
             "stack_name": name,
             "disable_rollback": disable_rollback,
@@ -58,9 +87,13 @@
         if template_url:
             post_body['template_url'] = template_url
         body = json.dumps(post_body)
-        uri = 'stacks'
-        resp, body = self.post(uri, headers=self.headers, body=body)
-        return resp, body
+
+        # Password must be provided on stack create so that heat
+        # can perform future operations on behalf of the user
+        headers = dict(self.headers)
+        headers['X-Auth-Key'] = self.password
+        headers['X-Auth-User'] = self.user
+        return headers, body
 
     def get_stack(self, stack_identifier):
         """Returns the details of a single stack."""
diff --git a/test-requirements.txt b/test-requirements.txt
index 3912695..2185997 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,7 +3,6 @@
 pyflakes==0.7.2
 flake8==2.0
 hacking>=0.5.3,<0.6
-psycopg2
 # needed for doc build
 sphinx>=1.1.2
 
diff --git a/tox.ini b/tox.ini
index caa9403..964dbca 100644
--- a/tox.ini
+++ b/tox.ini
@@ -61,6 +61,14 @@
    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 {posargs}
 
+[testenv:stress]
+sitepackages = True
+setenv = VIRTUAL_ENV={envdir}
+commands =
+    python -m tempest/stress/run_stress tempest/stress/etc/sample-test.json -d 60
+    python -m tempest/stress/run_stress tempest/stress/etc/volume-create-delete-test.json -d 60
+
+
 [testenv:venv]
 commands = {posargs}
 deps = -r{toxinidir}/requirements.txt