Tempest cleanup: improve iterating over projects

Currently cleanup iterates over projects and deletes all resources
tied to a particular project. However, most of the resources can be
deleted all at once without iteration over the projects.
This will fix the mentioned bug and also make the tool much more
efficient as we'll avoid many iterations and queries.

Closes-bug: #1830943
Change-Id: I82c7899a32bee0e714e71d703195085e10ea224f
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index b4fb5a5..c54b16b 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -136,7 +136,10 @@
         self._init_admin_ids()
 
         # available services
-        self.project_services = cleanup_service.get_project_cleanup_services()
+        self.project_associated_services = (
+            cleanup_service.get_project_associated_cleanup_services())
+        self.resource_cleanup_services = (
+            cleanup_service.get_resource_cleanup_services())
         self.global_services = cleanup_service.get_global_cleanup_services()
 
         if parsed_args.init_saved_state:
@@ -180,6 +183,10 @@
             svc = service(admin_mgr, **kwargs)
             svc.run()
 
+        for service in self.resource_cleanup_services:
+            svc = service(self.admin_mgr, **kwargs)
+            svc.run()
+
         if is_dry_run:
             with open(DRY_RUN_JSON, 'w+') as f:
                 f.write(json.dumps(self.dry_run_data, sort_keys=True,
@@ -204,7 +211,7 @@
                   'is_save_state': False,
                   'project_id': project_id,
                   'got_exceptions': self.GOT_EXCEPTIONS}
-        for service in self.project_services:
+        for service in self.project_associated_services:
             svc = service(self.admin_mgr, **kwargs)
             svc.run()
 
@@ -269,7 +276,11 @@
             svc = service(admin_mgr, **kwargs)
             svc.run()
 
-        for service in self.project_services:
+        for service in self.project_associated_services:
+            svc = service(admin_mgr, **kwargs)
+            svc.run()
+
+        for service in self.resource_cleanup_services:
             svc = service(admin_mgr, **kwargs)
             svc.run()
 
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index c35cecd..2b35ebf 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -1006,31 +1006,52 @@
             self.data['domains'][domain['id']] = domain['name']
 
 
-def get_project_cleanup_services():
-    project_services = []
+def get_project_associated_cleanup_services():
+    """Returns list of project service classes.
+
+    The list contains services whose resources need to be deleted prior,
+    the project they are associated with, deletion. The resources cannot be
+    most likely deleted after the project is deleted first.
+    """
+    project_associated_services = []
     # TODO(gmann): Tempest should provide some plugin hook for cleanup
     # script extension to plugin tests also.
     if IS_NOVA:
-        project_services.append(ServerService)
-        project_services.append(KeyPairService)
-        project_services.append(ServerGroupService)
-        project_services.append(NovaQuotaService)
-    if IS_NEUTRON:
-        project_services.append(NetworkFloatingIpService)
-        if utils.is_extension_enabled('metering', 'network'):
-            project_services.append(NetworkMeteringLabelRuleService)
-            project_services.append(NetworkMeteringLabelService)
-        project_services.append(NetworkRouterService)
-        project_services.append(NetworkPortService)
-        project_services.append(NetworkSubnetService)
-        project_services.append(NetworkService)
-        project_services.append(NetworkSecGroupService)
-        project_services.append(NetworkSubnetPoolsService)
+        project_associated_services.append(NovaQuotaService)
     if IS_CINDER:
-        project_services.append(SnapshotService)
-        project_services.append(VolumeService)
-        project_services.append(VolumeQuotaService)
-    return project_services
+        project_associated_services.append(VolumeQuotaService)
+    return project_associated_services
+
+
+def get_resource_cleanup_services():
+    """Returns list of project related classes.
+
+    The list contains services whose resources are associated with a project,
+    however, their deletion is possible also after the project is deleted
+    first.
+    """
+    resource_cleanup_services = []
+    # TODO(gmann): Tempest should provide some plugin hook for cleanup
+    # script extension to plugin tests also.
+    if IS_NOVA:
+        resource_cleanup_services.append(ServerService)
+        resource_cleanup_services.append(KeyPairService)
+        resource_cleanup_services.append(ServerGroupService)
+    if IS_NEUTRON:
+        resource_cleanup_services.append(NetworkFloatingIpService)
+        if utils.is_extension_enabled('metering', 'network'):
+            resource_cleanup_services.append(NetworkMeteringLabelRuleService)
+            resource_cleanup_services.append(NetworkMeteringLabelService)
+        resource_cleanup_services.append(NetworkRouterService)
+        resource_cleanup_services.append(NetworkPortService)
+        resource_cleanup_services.append(NetworkSubnetService)
+        resource_cleanup_services.append(NetworkService)
+        resource_cleanup_services.append(NetworkSecGroupService)
+        resource_cleanup_services.append(NetworkSubnetPoolsService)
+    if IS_CINDER:
+        resource_cleanup_services.append(SnapshotService)
+        resource_cleanup_services.append(VolumeService)
+    return resource_cleanup_services
 
 
 def get_global_cleanup_services():