From 1b66ad9067cc404ebfdc8569822d226d5bffddd6 Mon Sep 17 00:00:00 2001
From: Julie Pichon <jpichon@redhat.com>
Date: Fri, 14 Sep 2018 09:59:32 +0100
Subject: [PATCH] Fix 'project purge' deleting wrong project's servers and
 volumes

Project purge would delete the servers and volumes for the project the
user is currently authenticated for, regardless of the --project flag.

Note: This change means that no server at all will be deleted if the
logged in user doesn't have the get_all_tenants permission set in the
Nova policy (default: admin_api). This doesn't appear to be an issue
with Cinder as the default rule appears to be admin_or_owner.

Change-Id: If1c54e24e1482438b81c3c32fd5fc9fdd7a7be04
Story: 1747988
Task: 13854
---
 openstackclient/common/project_purge.py       |  4 +--
 .../tests/unit/common/test_project_purge.py   | 30 +++++++++++--------
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/openstackclient/common/project_purge.py b/openstackclient/common/project_purge.py
index 5b1d007254..76ed4563b0 100644
--- a/openstackclient/common/project_purge.py
+++ b/openstackclient/common/project_purge.py
@@ -85,7 +85,7 @@ class ProjectPurge(command.Command):
         # servers
         try:
             compute_client = self.app.client_manager.compute
-            search_opts = {'tenant_id': project_id}
+            search_opts = {'tenant_id': project_id, 'all_tenants': True}
             data = compute_client.servers.list(search_opts=search_opts)
             self.delete_objects(
                 compute_client.servers.delete, data, 'server', dry_run)
@@ -110,7 +110,7 @@ class ProjectPurge(command.Command):
 
         # volumes, snapshots, backups
         volume_client = self.app.client_manager.volume
-        search_opts = {'project_id': project_id}
+        search_opts = {'project_id': project_id, 'all_tenants': True}
         try:
             data = volume_client.volume_snapshots.list(search_opts=search_opts)
             self.delete_objects(
diff --git a/openstackclient/tests/unit/common/test_project_purge.py b/openstackclient/tests/unit/common/test_project_purge.py
index 2385eae893..6e8ce188f7 100644
--- a/openstackclient/tests/unit/common/test_project_purge.py
+++ b/openstackclient/tests/unit/common/test_project_purge.py
@@ -117,10 +117,11 @@ class TestProjectPurge(TestProjectPurgeInit):
         self.projects_mock.get.assert_called_once_with(self.project.id)
         self.projects_mock.delete.assert_called_once_with(self.project.id)
         self.servers_mock.list.assert_called_once_with(
-            search_opts={'tenant_id': self.project.id})
+            search_opts={'tenant_id': self.project.id, 'all_tenants': True})
         kwargs = {'filters': {'owner': self.project.id}}
         self.images_mock.list.assert_called_once_with(**kwargs)
-        volume_search_opts = {'project_id': self.project.id}
+        volume_search_opts = {'project_id': self.project.id,
+                              'all_tenants': True}
         self.volumes_mock.list.assert_called_once_with(
             search_opts=volume_search_opts)
         self.snapshots_mock.list.assert_called_once_with(
@@ -152,10 +153,11 @@ class TestProjectPurge(TestProjectPurgeInit):
         self.projects_mock.get.assert_called_once_with(self.project.id)
         self.projects_mock.delete.assert_not_called()
         self.servers_mock.list.assert_called_once_with(
-            search_opts={'tenant_id': self.project.id})
+            search_opts={'tenant_id': self.project.id, 'all_tenants': True})
         kwargs = {'filters': {'owner': self.project.id}}
         self.images_mock.list.assert_called_once_with(**kwargs)
-        volume_search_opts = {'project_id': self.project.id}
+        volume_search_opts = {'project_id': self.project.id,
+                              'all_tenants': True}
         self.volumes_mock.list.assert_called_once_with(
             search_opts=volume_search_opts)
         self.snapshots_mock.list.assert_called_once_with(
@@ -187,10 +189,11 @@ class TestProjectPurge(TestProjectPurgeInit):
         self.projects_mock.get.assert_called_once_with(self.project.id)
         self.projects_mock.delete.assert_not_called()
         self.servers_mock.list.assert_called_once_with(
-            search_opts={'tenant_id': self.project.id})
+            search_opts={'tenant_id': self.project.id, 'all_tenants': True})
         kwargs = {'filters': {'owner': self.project.id}}
         self.images_mock.list.assert_called_once_with(**kwargs)
-        volume_search_opts = {'project_id': self.project.id}
+        volume_search_opts = {'project_id': self.project.id,
+                              'all_tenants': True}
         self.volumes_mock.list.assert_called_once_with(
             search_opts=volume_search_opts)
         self.snapshots_mock.list.assert_called_once_with(
@@ -223,10 +226,11 @@ class TestProjectPurge(TestProjectPurgeInit):
         self.projects_mock.get.assert_not_called()
         self.projects_mock.delete.assert_called_once_with(self.project.id)
         self.servers_mock.list.assert_called_once_with(
-            search_opts={'tenant_id': self.project.id})
+            search_opts={'tenant_id': self.project.id, 'all_tenants': True})
         kwargs = {'filters': {'owner': self.project.id}}
         self.images_mock.list.assert_called_once_with(**kwargs)
-        volume_search_opts = {'project_id': self.project.id}
+        volume_search_opts = {'project_id': self.project.id,
+                              'all_tenants': True}
         self.volumes_mock.list.assert_called_once_with(
             search_opts=volume_search_opts)
         self.snapshots_mock.list.assert_called_once_with(
@@ -259,10 +263,11 @@ class TestProjectPurge(TestProjectPurgeInit):
         self.projects_mock.get.assert_called_once_with(self.project.id)
         self.projects_mock.delete.assert_called_once_with(self.project.id)
         self.servers_mock.list.assert_called_once_with(
-            search_opts={'tenant_id': self.project.id})
+            search_opts={'tenant_id': self.project.id, 'all_tenants': True})
         kwargs = {'filters': {'owner': self.project.id}}
         self.images_mock.list.assert_called_once_with(**kwargs)
-        volume_search_opts = {'project_id': self.project.id}
+        volume_search_opts = {'project_id': self.project.id,
+                              'all_tenants': True}
         self.volumes_mock.list.assert_called_once_with(
             search_opts=volume_search_opts)
         self.snapshots_mock.list.assert_called_once_with(
@@ -295,10 +300,11 @@ class TestProjectPurge(TestProjectPurgeInit):
         self.projects_mock.get.assert_called_once_with(self.project.id)
         self.projects_mock.delete.assert_called_once_with(self.project.id)
         self.servers_mock.list.assert_called_once_with(
-            search_opts={'tenant_id': self.project.id})
+            search_opts={'tenant_id': self.project.id, 'all_tenants': True})
         kwargs = {'filters': {'owner': self.project.id}}
         self.images_mock.list.assert_called_once_with(**kwargs)
-        volume_search_opts = {'project_id': self.project.id}
+        volume_search_opts = {'project_id': self.project.id,
+                              'all_tenants': True}
         self.volumes_mock.list.assert_called_once_with(
             search_opts=volume_search_opts)
         self.snapshots_mock.list.assert_called_once_with(