This is an automated email from the ASF dual-hosted git repository.

nvazquez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new a9c42fd  Provide option to force delete the project (#4617)
a9c42fd is described below

commit a9c42fd0cd55ee1e48ee948cf2b87b81c0cc1bd8
Author: Rakesh <[email protected]>
AuthorDate: Sun Sep 26 06:02:29 2021 +0200

    Provide option to force delete the project (#4617)
    
    * Provide a cleanup flag so that the project will
    be deleted only when there are no resources left
    in the project. If users click on delete project
    by mistake then everything is deleted.
    
    * fix travis failures
    
    Co-authored-by: Rakesh Venkatesh <[email protected]>
---
 .../java/com/cloud/projects/ProjectService.java    |  2 +-
 .../api/command/user/project/DeleteProjectCmd.java |  9 +++-
 .../com/cloud/projects/ProjectManagerImpl.java     | 51 +++++++++++++++++++++-
 .../com/cloud/projects/MockProjectManagerImpl.java |  2 +-
 tools/marvin/marvin/lib/base.py                    |  1 +
 ui/src/config/section/project.js                   |  9 +++-
 6 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/api/src/main/java/com/cloud/projects/ProjectService.java 
b/api/src/main/java/com/cloud/projects/ProjectService.java
index 4efc000..f93b3c5 100644
--- a/api/src/main/java/com/cloud/projects/ProjectService.java
+++ b/api/src/main/java/com/cloud/projects/ProjectService.java
@@ -55,7 +55,7 @@ public interface ProjectService {
      *            - project id
      * @return true if the project was deleted successfully, false otherwise
      */
-    boolean deleteProject(long id);
+    boolean deleteProject(long id, Boolean cleanup);
 
     /**
      * Gets a project by id
diff --git 
a/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectCmd.java
 
b/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectCmd.java
index 171d517..4e4a290 100644
--- 
a/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectCmd.java
+++ 
b/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectCmd.java
@@ -48,6 +48,9 @@ public class DeleteProjectCmd extends BaseAsyncCmd {
     @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = 
ProjectResponse.class, required = true, description = "id of the project to be 
deleted")
     private Long id;
 
+    @Parameter(name = ApiConstants.CLEANUP, type = CommandType.BOOLEAN, since 
= "4.16.0", description = "true if all project resources have to be cleaned up, 
false otherwise")
+    private Boolean cleanup;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -56,6 +59,10 @@ public class DeleteProjectCmd extends BaseAsyncCmd {
         return id;
     }
 
+    public Boolean isCleanup() {
+        return cleanup;
+    }
+
     @Override
     public String getCommandName() {
         return s_name;
@@ -68,7 +75,7 @@ public class DeleteProjectCmd extends BaseAsyncCmd {
     @Override
     public void execute() {
         CallContext.current().setEventDetails("Project Id: " + id);
-        boolean result = _projectService.deleteProject(id);
+        boolean result = _projectService.deleteProject(id, isCleanup());
         if (result) {
             SuccessResponse response = new SuccessResponse(getCommandName());
             this.setResponseObject(response);
diff --git a/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java 
b/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java
index 6d51c19..eb8c58b 100644
--- a/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java
+++ b/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java
@@ -27,11 +27,24 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.mail.MessagingException;
 import javax.naming.ConfigurationException;
 
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.vpc.Vpc;
+import com.cloud.network.vpc.VpcManager;
+import com.cloud.storage.VMTemplateVO;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.snapshot.VMSnapshotVO;
+import com.cloud.vm.snapshot.dao.VMSnapshotDao;
 import org.apache.cloudstack.acl.ProjectRole;
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.acl.dao.ProjectRoleDao;
@@ -125,6 +138,18 @@ public class ProjectManagerImpl extends ManagerBase 
implements ProjectManager, C
     private ProjectRoleDao projectRoleDao;
     @Inject
     private UserDao userDao;
+    @Inject
+    private VolumeDao _volumeDao;
+    @Inject
+    private UserVmDao _userVmDao;
+    @Inject
+    private VMTemplateDao _templateDao;
+    @Inject
+    private NetworkDao _networkDao;
+    @Inject
+    private VMSnapshotDao _vmSnapshotDao;
+    @Inject
+    private VpcManager _vpcMgr;
 
     protected boolean _invitationRequired = false;
     protected long _invitationTimeOut = 86400000;
@@ -285,7 +310,7 @@ public class ProjectManagerImpl extends ManagerBase 
implements ProjectManager, C
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_PROJECT_DELETE, eventDescription 
= "deleting project", async = true)
-    public boolean deleteProject(long projectId) {
+    public boolean deleteProject(long projectId, Boolean isCleanup) {
         CallContext ctx = CallContext.current();
 
         ProjectVO project = getProject(projectId);
@@ -297,7 +322,29 @@ public class ProjectManagerImpl extends ManagerBase 
implements ProjectManager, C
         CallContext.current().setProject(project);
         _accountMgr.checkAccess(ctx.getCallingAccount(), 
AccessType.ModifyProject, true, 
_accountMgr.getAccount(project.getProjectAccountId()));
 
-        return deleteProject(ctx.getCallingAccount(), ctx.getCallingUserId(), 
project);
+        if (isCleanup != null && isCleanup) {
+            return deleteProject(ctx.getCallingAccount(), 
ctx.getCallingUserId(), project);
+        } else {
+            List<VMTemplateVO> userTemplates = 
_templateDao.listByAccountId(project.getProjectAccountId());
+            List<VMSnapshotVO> vmSnapshots = 
_vmSnapshotDao.listByAccountId(project.getProjectAccountId());
+            List<UserVmVO> vms = 
_userVmDao.listByAccountId(project.getProjectAccountId());
+            List<VolumeVO> volumes = 
_volumeDao.findDetachedByAccount(project.getProjectAccountId());
+            List<NetworkVO> networks = 
_networkDao.listByOwner(project.getProjectAccountId());
+            List<? extends Vpc> vpcs = 
_vpcMgr.getVpcsForAccount(project.getProjectAccountId());
+
+            Optional<String> message = Stream.of(userTemplates, vmSnapshots, 
vms, volumes, networks, vpcs)
+                    .filter(entity -> !entity.isEmpty())
+                    .map(entity -> entity.size() + " " +  
entity.get(0).getEntityType().getSimpleName() + " to clean up")
+                    .findFirst();
+
+            if (message.isEmpty()) {
+                return deleteProject(ctx.getCallingAccount(), 
ctx.getCallingUserId(), project);
+            }
+
+            CloudRuntimeException e = new CloudRuntimeException("Can't delete 
the project yet because it has " + message.get());
+            e.addProxyObject(project.getUuid(), "projectId");
+            throw e;
+        }
     }
 
     @DB
diff --git 
a/server/src/test/java/com/cloud/projects/MockProjectManagerImpl.java 
b/server/src/test/java/com/cloud/projects/MockProjectManagerImpl.java
index f8af30f..988d675 100644
--- a/server/src/test/java/com/cloud/projects/MockProjectManagerImpl.java
+++ b/server/src/test/java/com/cloud/projects/MockProjectManagerImpl.java
@@ -37,7 +37,7 @@ public class MockProjectManagerImpl extends ManagerBase 
implements ProjectManage
     }
 
     @Override
-    public boolean deleteProject(long id) {
+    public boolean deleteProject(long id, Boolean cleanup) {
         // TODO Auto-generated method stub
         return false;
     }
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index aeb8bfb..b8c1138 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -4100,6 +4100,7 @@ class Project:
 
         cmd = deleteProject.deleteProjectCmd()
         cmd.id = self.id
+        cmd.cleanup = True
         apiclient.deleteProject(cmd)
 
     def update(self, apiclient, **kwargs):
diff --git a/ui/src/config/section/project.js b/ui/src/config/section/project.js
index 531901c..3a693c5 100644
--- a/ui/src/config/section/project.js
+++ b/ui/src/config/section/project.js
@@ -148,7 +148,14 @@ export default {
       },
       groupAction: true,
       popup: true,
-      groupMap: (selection) => { return selection.map(x => { return { id: x } 
}) }
+      groupMap: (selection) => { return selection.map(x => { return { id: x } 
}) },
+      args: (record, store) => {
+        const fields = []
+        if (store.apis.deleteProject.params.filter(x => x.name === 
'cleanup').length > 0) {
+          fields.push('cleanup')
+        }
+        return fields
+      }
     }
   ]
 }

Reply via email to