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());
+ }
}