Merge "Make policy client methods return one value, and fix tests"
diff --git a/HACKING.rst b/HACKING.rst
index e920634..7363e7f 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -111,9 +111,9 @@
 Negative Tests
 --------------
 Newly added negative tests should use the negative test framework. First step
-is to create an interface description in a json file under `etc/schemas`.
-These descriptions consists of two important sections for the test
-(one of those is mandatory):
+is to create an interface description in a python file under
+`tempest/api_schema/request/`. These descriptions consists of two important
+sections for the test (one of those is mandatory):
 
  - A resource (part of the URL of the request): Resources needed for a test
  must be created in `setUpClass` and registered with `set_resource` e.g.:
@@ -126,21 +126,17 @@
 
     load_tests = test.NegativeAutoTest.load_tests
 
-    class SampeTestNegativeTestJSON(<your base class>, test.NegativeAutoTest):
-        _interface = 'json'
+    @test.SimpleNegativeAutoTest
+    class SampleTestNegativeTestJSON(<your base class>, test.NegativeAutoTest):
         _service = 'compute'
-        _schema_file = <your Schema file>
+        _schema = <your schema file>
 
-Negative tests must be marked with a negative attribute::
-
-    @test.attr(type=['negative', 'gate'])
-    def test_get_console_output(self):
-        self.execute(self._schema_file)
+The class decorator `SimpleNegativeAutoTest` will automatically generate test
+cases out of the given schema in the attribute `_schema`.
 
 All negative tests should be added into a separate negative test file.
 If such a file doesn't exist for the particular resource being tested a new
-test file should be added. Old XML based negative tests can be kept but should
-be renamed to `_xml.py`.
+test file should be added.
 
 Test skips because of Known Bugs
 --------------------------------
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 1a338bd..4e6dcda 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -219,7 +219,7 @@
         # Pass really long metadata while creating a server
 
         metadata = {'a': 'b' * 260}
-        self.assertRaises(exceptions.OverLimit,
+        self.assertRaises((exceptions.BadRequest, exceptions.OverLimit),
                           self.create_test_server,
                           meta=metadata)
 
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 91b95a8..e9fa960 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -12,6 +12,7 @@
 #    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_lib import exceptions
 
 from tempest.common.utils import data_utils
 from tempest import config
@@ -44,6 +45,22 @@
                                     "instances")
         cls.set_network_resources()
         super(TestLargeOpsScenario, cls).resource_setup()
+        # list of cleanup calls to be executed in reverse order
+        cls._cleanup_resources = []
+
+    @classmethod
+    def resource_cleanup(cls):
+        while cls._cleanup_resources:
+            function, args, kwargs = cls._cleanup_resources.pop(-1)
+            try:
+                function(*args, **kwargs)
+            except exceptions.NotFound:
+                pass
+        super(TestLargeOpsScenario, cls).resource_cleanup()
+
+    @classmethod
+    def addCleanupClass(cls, function, *arguments, **keywordArguments):
+        cls._cleanup_resources.append((function, arguments, keywordArguments))
 
     def _wait_for_server_status(self, status):
         for server in self.servers:
@@ -54,7 +71,14 @@
     def nova_boot(self):
         name = data_utils.rand_name('scenario-server-')
         flavor_id = CONF.compute.flavor_ref
-        secgroup = self._create_security_group()
+        # Explicitly create secgroup to avoid cleanup at the end of testcases.
+        # Since no traffic is tested, we don't need to actually add rules to
+        # secgroup
+        _, secgroup = self.security_groups_client.create_security_group(
+            'secgroup-%s' % name, 'secgroup-desc-%s' % name)
+        self.addCleanupClass(self.security_groups_client.delete_security_group,
+                             secgroup['id'])
+
         self.servers_client.create_server(
             name,
             self.image,
@@ -68,15 +92,12 @@
         for server in self.servers:
             # after deleting all servers - wait for all servers to clear
             # before cleanup continues
-            self.addCleanup(self.servers_client.wait_for_server_termination,
-                            server['id'])
+            self.addCleanupClass(self.servers_client.
+                                 wait_for_server_termination,
+                                 server['id'])
         for server in self.servers:
-            self.addCleanup_with_wait(
-                waiter_callable=(self.servers_client.
-                                 wait_for_server_termination),
-                thing_id=server['id'], thing_id_param='server_id',
-                cleanup_callable=self.delete_wrapper,
-                cleanup_args=[self.servers_client.delete_server, server['id']])
+            self.addCleanupClass(self.servers_client.delete_server,
+                                 server['id'])
         self._wait_for_server_status('ACTIVE')
 
     def _large_ops_scenario(self):
diff --git a/tempest/test.py b/tempest/test.py
index 14cf3bb..7db0376 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -414,12 +414,8 @@
         else:
             standard_tests, module, loader = args
         for test in testtools.iterate_tests(standard_tests):
-            schema_file = getattr(test, '_schema_file', None)
             schema = getattr(test, '_schema', None)
-            if schema_file is not None:
-                setattr(test, 'scenarios',
-                        NegativeAutoTest.generate_scenario(schema_file))
-            elif schema is not None:
+            if schema is not None:
                 setattr(test, 'scenarios',
                         NegativeAutoTest.generate_scenario(schema))
         return testscenarios.load_tests_apply_scenarios(*args)