Skip to content

Commit 0735b91

Browse files
authored
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.
1 parent cc45bff commit 0735b91

2 files changed

Lines changed: 94 additions & 51 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java

Lines changed: 78 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,6 @@
2121
import java.util.Map;
2222

2323
import org.apache.cloudstack.acl.SecurityChecker;
24-
import org.apache.cloudstack.api.command.user.UserCmd;
25-
import org.apache.cloudstack.api.response.GuestOSResponse;
26-
import org.apache.cloudstack.api.response.SnapshotResponse;
27-
import org.apache.cloudstack.api.response.TemplateResponse;
28-
import org.apache.cloudstack.api.response.UserVmResponse;
29-
import org.apache.cloudstack.api.response.VolumeResponse;
30-
import org.apache.cloudstack.api.response.ProjectResponse;
31-
32-
import org.apache.cloudstack.api.response.ZoneResponse;
33-
import org.apache.commons.lang3.StringUtils;
34-
import org.apache.log4j.Logger;
35-
3624
import org.apache.cloudstack.api.APICommand;
3725
import org.apache.cloudstack.api.ApiCommandResourceType;
3826
import org.apache.cloudstack.api.ApiConstants;
@@ -41,13 +29,23 @@
4129
import org.apache.cloudstack.api.Parameter;
4230
import org.apache.cloudstack.api.ResponseObject.ResponseView;
4331
import org.apache.cloudstack.api.ServerApiException;
32+
import org.apache.cloudstack.api.command.user.UserCmd;
33+
import org.apache.cloudstack.api.response.DomainResponse;
34+
import org.apache.cloudstack.api.response.GuestOSResponse;
35+
import org.apache.cloudstack.api.response.ProjectResponse;
36+
import org.apache.cloudstack.api.response.SnapshotResponse;
37+
import org.apache.cloudstack.api.response.TemplateResponse;
38+
import org.apache.cloudstack.api.response.UserVmResponse;
39+
import org.apache.cloudstack.api.response.VolumeResponse;
40+
import org.apache.cloudstack.api.response.ZoneResponse;
4441
import org.apache.cloudstack.context.CallContext;
42+
import org.apache.commons.lang3.StringUtils;
43+
import org.apache.log4j.Logger;
4544

4645
import com.cloud.event.EventTypes;
4746
import com.cloud.exception.InvalidParameterValueException;
4847
import com.cloud.exception.PermissionDeniedException;
4948
import com.cloud.exception.ResourceAllocationException;
50-
import com.cloud.projects.Project;
5149
import com.cloud.storage.Snapshot;
5250
import com.cloud.storage.Volume;
5351
import com.cloud.template.VirtualMachineTemplate;
@@ -139,6 +137,19 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd {
139137
@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")
140138
private Long zoneId;
141139

140+
@Parameter(name = ApiConstants.DOMAIN_ID,
141+
type = CommandType.UUID,
142+
entityType = DomainResponse.class,
143+
description = "an optional domainId. If the account parameter is used, domainId must also be used.",
144+
since = "4.19.0")
145+
private Long domainId;
146+
147+
@Parameter(name = ApiConstants.ACCOUNT,
148+
type = CommandType.STRING,
149+
description = "an optional accountName. Must be used with domainId.",
150+
since = "4.19.0")
151+
private String accountName;
152+
142153
// ///////////////////////////////////////////////////
143154
// ///////////////// Accessors ///////////////////////
144155
// ///////////////////////////////////////////////////
@@ -217,6 +228,14 @@ public Long getZoneId() {
217228
return zoneId;
218229
}
219230

231+
public Long getDomainId() {
232+
return domainId;
233+
}
234+
235+
public String getAccountName() {
236+
return accountName;
237+
}
238+
220239
// ///////////////////////////////////////////////////
221240
// ///////////// API Implementation///////////////////
222241
// ///////////////////////////////////////////////////
@@ -232,47 +251,12 @@ public static String getResultObjectName() {
232251

233252
@Override
234253
public long getEntityOwnerId() {
235-
Long volumeId = getVolumeId();
236-
Long snapshotId = getSnapshotId();
237254
Account callingAccount = CallContext.current().getCallingAccount();
238-
if (volumeId != null) {
239-
Volume volume = _entityMgr.findById(Volume.class, volumeId);
240-
if (volume != null) {
241-
_accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, volume);
242-
} else {
243-
throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
244-
}
245-
} else {
246-
Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId);
247-
if (snapshot != null) {
248-
_accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, snapshot);
249-
} else {
250-
throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId);
251-
}
252-
}
253-
254-
if(projectId != null){
255-
final Project project = _projectService.getProject(projectId);
256-
if (project != null) {
257-
if (project.getState() == Project.State.Active) {
258-
Account projectAccount= _accountService.getAccount(project.getProjectAccountId());
259-
_accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, projectAccount);
260-
return project.getProjectAccountId();
261-
} else {
262-
final PermissionDeniedException ex =
263-
new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() +
264-
" as it's no longer active");
265-
ex.addProxyObject(project.getUuid(), "projectId");
266-
throw ex;
267-
}
268-
} else {
269-
throw new InvalidParameterValueException("Unable to find project by id");
270-
}
271-
}
272-
273-
return callingAccount.getId();
255+
ensureAccessCheck(callingAccount);
256+
return findAccountIdToUse(callingAccount);
274257
}
275258

259+
276260
@Override
277261
public String getEventType() {
278262
return EventTypes.EVENT_TEMPLATE_CREATE;
@@ -330,4 +314,47 @@ public void execute() {
330314
}
331315

332316
}
317+
318+
/***
319+
* Performs access check on volume and snapshot for given account
320+
* @param account
321+
*/
322+
private void ensureAccessCheck(Account account) {
323+
if (volumeId != null) {
324+
Volume volume = _entityMgr.findById(Volume.class, volumeId);
325+
if (volume != null) {
326+
_accountService.checkAccess(account, SecurityChecker.AccessType.UseEntry, false, volume);
327+
} else {
328+
throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
329+
}
330+
} else {
331+
Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId);
332+
if (snapshot != null) {
333+
_accountService.checkAccess(account, SecurityChecker.AccessType.UseEntry, false, snapshot);
334+
} else {
335+
throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId);
336+
}
337+
}
338+
}
339+
340+
/***
341+
* Find accountId based on accountName and domainId or projectId
342+
* if not found, return callingAccountId for further use
343+
* @param callingAccount
344+
* @return accountId
345+
*/
346+
private Long findAccountIdToUse(Account callingAccount) {
347+
Long accountIdToUse = null;
348+
try {
349+
accountIdToUse = _accountService.finalyzeAccountId(accountName, domainId, projectId, true);
350+
} catch (InvalidParameterValueException | PermissionDeniedException ex) {
351+
if (s_logger.isDebugEnabled()) {
352+
s_logger.debug(String.format("An exception occurred while finalizing account id with accountName, domainId and projectId" +
353+
"using callingAccountId=%s", callingAccount.getUuid()), ex);
354+
}
355+
s_logger.warn("Unable to find accountId associated with accountName=" + accountName + " and domainId="
356+
+ domainId + " or projectId=" + projectId + ", using callingAccountId=" + callingAccount.getUuid());
357+
}
358+
return accountIdToUse != null ? accountIdToUse : callingAccount.getAccountId();
359+
}
333360
}

api/src/test/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmdTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,20 @@ public void testGetZoneId() {
2929
ReflectionTestUtils.setField(cmd, "zoneId", id);
3030
Assert.assertEquals(id, cmd.getZoneId());
3131
}
32+
33+
@Test
34+
public void testDomainId() {
35+
final CreateTemplateCmd cmd = new CreateTemplateCmd();
36+
Long id = 2L;
37+
ReflectionTestUtils.setField(cmd, "domainId", id);
38+
Assert.assertEquals(id, cmd.getDomainId());
39+
}
40+
41+
@Test
42+
public void testGetAccountName() {
43+
final CreateTemplateCmd cmd = new CreateTemplateCmd();
44+
String accountName = "user1";
45+
ReflectionTestUtils.setField(cmd, "accountName", accountName);
46+
Assert.assertEquals(accountName, cmd.getAccountName());
47+
}
3248
}

0 commit comments

Comments
 (0)