You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by sh...@apache.org on 2023/11/16 12:09:46 UTC

(cloudstack) branch main updated: api: introduce domainid and account parameter in createTemplate API (#8210)

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

shwstppr 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 0735b91037d api: introduce domainid and account parameter in createTemplate API (#8210)
0735b91037d is described below

commit 0735b91037dec0e006e6dbbd79e09d9db3ccae56
Author: Manoj Kumar <ma...@gmail.com>
AuthorDate: Thu Nov 16 17:39:38 2023 +0530

    api: introduce domainid and account parameter in createTemplate API (#8210)
    
    Introduces domainid and account as optional parameter for createTemplate API. It will allow admin to create templates for specified domain belonging to specific account.
---
 .../command/user/template/CreateTemplateCmd.java   | 129 +++++++++++++--------
 .../user/template/CreateTemplateCmdTest.java       |  16 +++
 2 files changed, 94 insertions(+), 51 deletions(-)

diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
index 73a6155c8c5..6c39ab6d3c7 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
@@ -21,18 +21,6 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.cloudstack.acl.SecurityChecker;
-import org.apache.cloudstack.api.command.user.UserCmd;
-import org.apache.cloudstack.api.response.GuestOSResponse;
-import org.apache.cloudstack.api.response.SnapshotResponse;
-import org.apache.cloudstack.api.response.TemplateResponse;
-import org.apache.cloudstack.api.response.UserVmResponse;
-import org.apache.cloudstack.api.response.VolumeResponse;
-import org.apache.cloudstack.api.response.ProjectResponse;
-
-import org.apache.cloudstack.api.response.ZoneResponse;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.log4j.Logger;
-
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiCommandResourceType;
 import org.apache.cloudstack.api.ApiConstants;
@@ -41,13 +29,23 @@ import org.apache.cloudstack.api.BaseAsyncCreateCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.ResponseObject.ResponseView;
 import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.command.user.UserCmd;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.GuestOSResponse;
+import org.apache.cloudstack.api.response.ProjectResponse;
+import org.apache.cloudstack.api.response.SnapshotResponse;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
 import org.apache.cloudstack.context.CallContext;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
 
 import com.cloud.event.EventTypes;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.PermissionDeniedException;
 import com.cloud.exception.ResourceAllocationException;
-import com.cloud.projects.Project;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.Volume;
 import com.cloud.template.VirtualMachineTemplate;
@@ -139,6 +137,19 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd {
     @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = "the zone for the template. Can be specified with snapshot only", since = "4.19.0")
     private Long zoneId;
 
+    @Parameter(name = ApiConstants.DOMAIN_ID,
+          type = CommandType.UUID,
+          entityType = DomainResponse.class,
+          description = "an optional domainId. If the account parameter is used, domainId must also be used.",
+          since = "4.19.0")
+    private Long domainId;
+
+    @Parameter(name = ApiConstants.ACCOUNT,
+          type = CommandType.STRING,
+          description = "an optional accountName. Must be used with domainId.",
+          since = "4.19.0")
+    private String accountName;
+
     // ///////////////////////////////////////////////////
     // ///////////////// Accessors ///////////////////////
     // ///////////////////////////////////////////////////
@@ -217,6 +228,14 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd {
         return zoneId;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
     // ///////////////////////////////////////////////////
     // ///////////// API Implementation///////////////////
     // ///////////////////////////////////////////////////
@@ -232,47 +251,12 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd {
 
     @Override
     public long getEntityOwnerId() {
-        Long volumeId = getVolumeId();
-        Long snapshotId = getSnapshotId();
         Account callingAccount = CallContext.current().getCallingAccount();
-        if (volumeId != null) {
-            Volume volume = _entityMgr.findById(Volume.class, volumeId);
-            if (volume != null) {
-                _accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, volume);
-            } else {
-                throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
-            }
-        } else {
-            Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId);
-            if (snapshot != null) {
-                _accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, snapshot);
-            } else {
-                throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId);
-            }
-        }
-
-        if(projectId != null){
-            final Project project = _projectService.getProject(projectId);
-            if (project != null) {
-                if (project.getState() == Project.State.Active) {
-                    Account projectAccount= _accountService.getAccount(project.getProjectAccountId());
-                    _accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, projectAccount);
-                    return project.getProjectAccountId();
-                } else {
-                    final PermissionDeniedException ex =
-                            new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() +
-                                    " as it's no longer active");
-                    ex.addProxyObject(project.getUuid(), "projectId");
-                    throw ex;
-                }
-            } else {
-                throw new InvalidParameterValueException("Unable to find project by id");
-            }
-        }
-
-        return callingAccount.getId();
+        ensureAccessCheck(callingAccount);
+        return findAccountIdToUse(callingAccount);
     }
 
+
     @Override
     public String getEventType() {
         return EventTypes.EVENT_TEMPLATE_CREATE;
@@ -330,4 +314,47 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd {
         }
 
     }
+
+    /***
+     * Performs access check on volume and snapshot for given account
+     * @param account
+     */
+    private void ensureAccessCheck(Account account) {
+        if (volumeId != null) {
+            Volume volume = _entityMgr.findById(Volume.class, volumeId);
+            if (volume != null) {
+                _accountService.checkAccess(account, SecurityChecker.AccessType.UseEntry, false, volume);
+            } else {
+                throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
+            }
+        } else {
+            Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId);
+            if (snapshot != null) {
+                _accountService.checkAccess(account, SecurityChecker.AccessType.UseEntry, false, snapshot);
+            } else {
+                throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId);
+            }
+        }
+    }
+
+    /***
+     * Find accountId based on accountName and domainId or projectId
+     * if not found, return callingAccountId for further use
+     * @param callingAccount
+     * @return accountId
+     */
+    private Long findAccountIdToUse(Account callingAccount) {
+        Long accountIdToUse = null;
+        try {
+            accountIdToUse = _accountService.finalyzeAccountId(accountName, domainId, projectId, true);
+        } catch (InvalidParameterValueException | PermissionDeniedException ex) {
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug(String.format("An exception occurred while finalizing account id with accountName, domainId and projectId" +
+                      "using callingAccountId=%s", callingAccount.getUuid()), ex);
+            }
+            s_logger.warn("Unable to find accountId associated with accountName=" + accountName + " and domainId="
+                  + domainId + " or projectId=" + projectId + ", using callingAccountId=" + callingAccount.getUuid());
+        }
+        return accountIdToUse != null ? accountIdToUse : callingAccount.getAccountId();
+    }
 }
diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmdTest.java
index d8af670a7b2..55e9c8dba1e 100644
--- a/api/src/test/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmdTest.java
+++ b/api/src/test/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmdTest.java
@@ -29,4 +29,20 @@ public class CreateTemplateCmdTest {
         ReflectionTestUtils.setField(cmd, "zoneId", id);
         Assert.assertEquals(id, cmd.getZoneId());
     }
+
+    @Test
+    public void testDomainId() {
+        final CreateTemplateCmd cmd = new CreateTemplateCmd();
+        Long id = 2L;
+        ReflectionTestUtils.setField(cmd, "domainId", id);
+        Assert.assertEquals(id, cmd.getDomainId());
+    }
+
+    @Test
+    public void testGetAccountName() {
+        final CreateTemplateCmd cmd = new CreateTemplateCmd();
+        String accountName = "user1";
+        ReflectionTestUtils.setField(cmd, "accountName", accountName);
+        Assert.assertEquals(accountName, cmd.getAccountName());
+    }
 }