2121import java .util .Map ;
2222
2323import 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-
3624import org .apache .cloudstack .api .APICommand ;
3725import org .apache .cloudstack .api .ApiCommandResourceType ;
3826import org .apache .cloudstack .api .ApiConstants ;
4129import org .apache .cloudstack .api .Parameter ;
4230import org .apache .cloudstack .api .ResponseObject .ResponseView ;
4331import 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 ;
4441import org .apache .cloudstack .context .CallContext ;
42+ import org .apache .commons .lang3 .StringUtils ;
43+ import org .apache .log4j .Logger ;
4544
4645import com .cloud .event .EventTypes ;
4746import com .cloud .exception .InvalidParameterValueException ;
4847import com .cloud .exception .PermissionDeniedException ;
4948import com .cloud .exception .ResourceAllocationException ;
50- import com .cloud .projects .Project ;
5149import com .cloud .storage .Snapshot ;
5250import com .cloud .storage .Volume ;
5351import 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}
0 commit comments