diff --git a/core/src/com/cloud/storage/dao/VMTemplateDao.java b/core/src/com/cloud/storage/dao/VMTemplateDao.java index 05e6816a0f6..b28818dee9c 100644 --- a/core/src/com/cloud/storage/dao/VMTemplateDao.java +++ b/core/src/com/cloud/storage/dao/VMTemplateDao.java @@ -18,10 +18,9 @@ package com.cloud.storage.dao; -import java.util.List; - +import java.util.List; + import com.cloud.domain.DomainVO; -import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateVO; import com.cloud.user.Account; import com.cloud.utils.db.GenericDao; @@ -45,7 +44,16 @@ public interface VMTemplateDao extends GenericDao { //finds by the column "unique_name" public VMTemplateVO findByName(String templateName); //finds by the column "name" - public VMTemplateVO findByTemplateName(String templateName); + public VMTemplateVO findByTemplateName(String templateName); + + /** + * Find a template by name for a specific account. + * @param templateName the name to search for + * @param accountId the account to use for filtering the search results + * @return the template with the given name for the given account if it exists, null otherwise + */ + public VMTemplateVO findByTemplateNameAccountId(String templateName, Long accountId); + //public void update(VMTemplateVO template); public VMTemplateVO findRoutingTemplate(); public VMTemplateVO findConsoleProxyTemplate(); diff --git a/core/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/core/src/com/cloud/storage/dao/VMTemplateDaoImpl.java index a02d33bdb53..e929a440328 100644 --- a/core/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/core/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -55,16 +55,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem private final String SELECT_ALL = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones FROM vm_template t"; - protected static final String SELECT_ALL_IN_ZONE = + private static final String SELECT_ALL_IN_ZONE = "SELECT t.id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.removed, t.account_id, " + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones FROM vm_template t, template_zone_ref tz where t.removed is null and tz.removed is null and t.id = tz.template_id and tz.zone_id=? "; - protected SearchBuilder TemplateNameSearch; - protected SearchBuilder UniqueNameSearch; - protected SearchBuilder AccountIdSearch; - protected SearchBuilder NameSearch; + private SearchBuilder UniqueNameSearch; + private SearchBuilder AccountIdSearch; + private SearchBuilder NameSearch; + private SearchBuilder PublicSearch; + private SearchBuilder NameAccountIdSearch; - protected SearchBuilder PublicSearch; private String routerTmpltName; private String consoleProxyTmpltName; @@ -90,7 +90,15 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem sc.setParameters("name", templateName); return findOneBy(sc); } - + + @Override + public VMTemplateVO findByTemplateNameAccountId(String templateName, Long accountId) { + SearchCriteria sc = NameAccountIdSearch.create(); + sc.setParameters("name", templateName); + sc.setParameters("accountId", accountId); + return findOneBy(sc); + } + @Override public VMTemplateVO findRoutingTemplate() { SearchCriteria sc = UniqueNameSearch.create(); @@ -152,14 +160,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem consoleProxyTmpltName = "routing"; if(s_logger.isDebugEnabled()) s_logger.debug("Use console proxy template : " + consoleProxyTmpltName); - - TemplateNameSearch = createSearchBuilder(); - TemplateNameSearch.and("name", TemplateNameSearch.entity().getName(), SearchCriteria.Op.EQ); + UniqueNameSearch = createSearchBuilder(); UniqueNameSearch.and("uniqueName", UniqueNameSearch.entity().getUniqueName(), SearchCriteria.Op.EQ); NameSearch = createSearchBuilder(); NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ); - + + NameAccountIdSearch = createSearchBuilder(); + NameAccountIdSearch.and("name", NameAccountIdSearch.entity().getName(), SearchCriteria.Op.EQ); + NameAccountIdSearch.and("accountId", NameAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AccountIdSearch = createSearchBuilder(); AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); AccountIdSearch.and("publicTemplate", AccountIdSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ); diff --git a/server/src/com/cloud/api/commands/CreateTemplateCmd.java b/server/src/com/cloud/api/commands/CreateTemplateCmd.java index 8cfa65323d0..e0b18fe80a1 100644 --- a/server/src/com/cloud/api/commands/CreateTemplateCmd.java +++ b/server/src/com/cloud/api/commands/CreateTemplateCmd.java @@ -18,47 +18,20 @@ package com.cloud.api.commands; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import org.apache.log4j.Logger; -import com.cloud.api.BaseCmd; -import com.cloud.api.BaseCmd.Manager; import com.cloud.api.BaseAsyncCreateCmd; +import com.cloud.api.BaseCmd.Manager; +import com.cloud.api.Implementation; import com.cloud.api.Parameter; -import com.cloud.api.ServerApiException; -import com.cloud.async.executor.CreatePrivateTemplateResultObject; +import com.cloud.api.response.TemplateResponse; import com.cloud.serializer.SerializerHelper; -import com.cloud.server.Criteria; -import com.cloud.storage.Snapshot; import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VolumeVO; -import com.cloud.user.Account; -import com.cloud.utils.Pair; @Implementation(method="createPrivateTemplate", createMethod="createPrivateTemplateRecord", manager=Manager.UserVmManager) public class CreateTemplateCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateTemplateCmd.class.getName()); private static final String s_name = "createtemplateresponse"; - private static final List> s_properties = new ArrayList>(); - - static { - s_properties.add(new Pair(BaseCmd.Properties.BITS, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT, Boolean.TRUE)); - s_properties.add(new Pair(BaseCmd.Properties.IS_FEATURED, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.IS_PUBLIC, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.NAME, Boolean.TRUE)); - s_properties.add(new Pair(BaseCmd.Properties.OS_TYPE_ID, Boolean.TRUE)); - s_properties.add(new Pair(BaseCmd.Properties.PASSWORD_ENABLED, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.REQUIRES_HVM, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.SNAPSHOT_ID, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.VOLUME_ID, Boolean.FALSE)); - - s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.USER_ID, Boolean.FALSE)); - } ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -154,108 +127,40 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd { } @Override - public String getResponse() { + public String getResponse() { + VMTemplateVO template = (VMTemplateVO)getResponseObject(); + + TemplateResponse response = new TemplateResponse(); + response.setId(template.getId()); + response.setName(template.getName()); + response.setDisplayText(template.getDisplayText()); + response.setPublic(template.isPublicTemplate()); + response.setPasswordEnabled(template.getEnablePassword()); + response.setCrossZones(template.isCrossZones()); + + // TODO: implement +// VMTemplateHostVO templateHostRef = managerServer.findTemplateHostRef(template.getId(), volume.getDataCenterId()); +// response.setCreated(templateHostRef.getCreated()); +// response.setReady(templateHostRef != null && templateHostRef.getDownloadState() == Status.DOWNLOADED); +// if (os != null) { +// resultObject.setOsTypeId(os.getId()); +// resultObject.setOsTypeName(os.getDisplayName()); +// } else { +// resultObject.setOsTypeId(-1L); +// resultObject.setOsTypeName(""); +// } +// Account owner = managerServer.findAccountById(template.getAccountId()); +// if (owner != null) { +// resultObject.setAccount(owner.getAccountName()); +// resultObject.setDomainId(owner.getDomainId()); +// resultObject.setDomainName(managerServer.findDomainIdById(owner.getDomainId()).getName()); +// } +// DataCenterVO zone = managerServer.findDataCenterById(dataCenterId); +// if (zone != null) { +// resultObject.setZoneId(zone.getId()); +// resultObject.setZoneName(zone.getName()); +// } + + return SerializerHelper.toSerializedString(response); } - - @Override - public List> execute(Map params) { - String description = (String)params.get(BaseCmd.Properties.DISPLAY_TEXT.getName()); - String name = (String)params.get(BaseCmd.Properties.NAME.getName()); - Long volumeId = (Long)params.get(BaseCmd.Properties.VOLUME_ID.getName()); - Long guestOSId = (Long) params.get(BaseCmd.Properties.OS_TYPE_ID.getName()); - Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName()); - Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName()); - Boolean requiresHvm = (Boolean)params.get(BaseCmd.Properties.REQUIRES_HVM.getName()); - Integer bits = (Integer)params.get(BaseCmd.Properties.BITS.getName()); - Boolean passwordEnabled = (Boolean)params.get(BaseCmd.Properties.PASSWORD_ENABLED.getName()); - Boolean isPublic = (Boolean)params.get(BaseCmd.Properties.IS_PUBLIC.getName()); - Boolean featured = (Boolean)params.get(BaseCmd.Properties.IS_FEATURED.getName()); - Long snapshotId = (Long)params.get(BaseCmd.Properties.SNAPSHOT_ID.getName()); - - if (volumeId == null && snapshotId == null) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Specify at least one of the two parameters volumeId or snapshotId"); - } - VolumeVO volume = null; - // Verify input parameters - if (snapshotId != null) { - Snapshot snapshot = getManagementServer().findSnapshotById(snapshotId); - if (snapshot == null) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "No snapshot exists with the given id: " + snapshotId); - } - - if (volumeId != null) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Specify only one of the two parameters volumeId or snapshotId"); - } - // Set the volumeId to that of the snapshot. All further input parameter checks will be done w.r.t the volume. - volumeId = snapshot.getVolumeId(); - volume = getManagementServer().findAnyVolumeById(volumeId); - } else { - volume = getManagementServer().findAnyVolumeById(volumeId); - } - - if (volume == null) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a volume with id " + volumeId); - } - - boolean isAdmin = ((account == null) || isAdmin(account.getType())); - if (!isAdmin) { - if (account.getId().longValue() != volume.getAccountId()) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a volume with id " + volumeId + " for this account"); - } - } else if ((account != null) && !getManagementServer().isChildDomain(account.getDomainId(), volume.getDomainId())) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create a template from volume with id " + volumeId + ", permission denied."); - } - - if (isPublic == null) { - isPublic = Boolean.FALSE; - } - - boolean allowPublicUserTemplates = Boolean.parseBoolean(getManagementServer().getConfigurationValue("allow.public.user.templates")); - if (!isAdmin && !allowPublicUserTemplates && isPublic) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private templates can be created."); - } - - if (!isAdmin || featured == null) { - featured = Boolean.FALSE; - } - - Criteria c = new Criteria(); - c.addCriteria(Criteria.NAME, name); - c.addCriteria(Criteria.CREATED_BY, Long.valueOf(volume.getAccountId())); - List templates = getManagementServer().searchForTemplates(c); - - // If command is executed via 8096 port, set userId to the id of System account (1) - if (userId == null) { - userId = Long.valueOf(1); - } - - try { - long jobId = getManagementServer().createPrivateTemplateAsync(userId, volumeId, name, description, guestOSId, requiresHvm, bits, passwordEnabled, isPublic, featured, snapshotId); - - if (jobId == 0) { - s_logger.warn("Unable to schedule async-job for CreateTemplate command"); - } else { - if (s_logger.isDebugEnabled()) - s_logger.debug("CreateTemplate command has been accepted, job id: " + jobId); - } - - long templateId = waitInstanceCreation(jobId); - List> returnValues = new ArrayList>(); - returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); - returnValues.add(new Pair(BaseCmd.Properties.TEMPLATE_ID.getName(), Long.valueOf(templateId))); - - return returnValues; - } catch (Exception ex) { - throw new ServerApiException(BaseCmd.CREATE_PRIVATE_TEMPLATE_ERROR, "Unhandled exception while creating template name: " + name + " for volume " + volumeId + ", reason, " + ex.getMessage()); - } - } - - protected long getInstanceIdFromJobSuccessResult(String result) { - CreatePrivateTemplateResultObject resultObject = (CreatePrivateTemplateResultObject)SerializerHelper.fromSerializedString(result); - if (resultObject != null) { - return resultObject.getId(); - } - - return 0; - } } diff --git a/server/src/com/cloud/api/response/TemplateResponse.java b/server/src/com/cloud/api/response/TemplateResponse.java new file mode 100644 index 00000000000..6801d15ed33 --- /dev/null +++ b/server/src/com/cloud/api/response/TemplateResponse.java @@ -0,0 +1,184 @@ +package com.cloud.api.response; + +import java.util.Date; + +import com.cloud.api.ResponseObject; +import com.cloud.serializer.Param; + +public class TemplateResponse implements ResponseObject { + @Param(name="id") + private long id; + + @Param(name="name") + private String name; + + @Param(name="displaytext") + private String displayText; + + @Param(name="ispublic", propName="public") + private boolean isPublic; + + @Param(name="created") + private Date created; + + @Param(name="isready", propName="ready") + private boolean isReady; + + @Param(name="passwordenabled") + private boolean passwordEnabled; + + @Param(name="crossZones") + private boolean crossZones; + + @Param(name="ostypeid") + private Long osTypeId; + + @Param(name="ostypename") + private String osTypeName; + + @Param(name="accountid") + private Long accountId; + + @Param(name="account") + private String account; + + @Param(name="zoneid") + private Long zoneId; + + @Param(name="zonename") + private String zoneName; + + @Param(name="domain") + private String domainName; + + @Param(name="domainid") + private long domainId; + + public Long getZoneId() { + return zoneId; + } + + public void setZoneId(Long zoneId) { + this.zoneId = zoneId; + } + + public String getZoneName() { + return zoneName; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public Long getOsTypeId() { + return osTypeId; + } + + public void setOsTypeId(Long osTypeId) { + this.osTypeId = osTypeId; + } + + public String getOsTypeName() { + return osTypeName; + } + + public void setOsTypeName(String osTypeName) { + this.osTypeName = osTypeName; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDisplayText() { + return displayText; + } + + public void setDisplayText(String displayText) { + this.displayText = displayText; + } + + public boolean isPublic() { + return isPublic; + } + + public void setPublic(boolean isPublic) { + this.isPublic = isPublic; + } + + public Date getCreated() { + return created; + } + + public void setCreated(Date created) { + this.created = created; + } + + public boolean isReady() { + return isReady; + } + + public void setReady(boolean isReady) { + this.isReady = isReady; + } + + public boolean isPasswordEnabled() { + return passwordEnabled; + } + + public void setPasswordEnabled(boolean passwordEnabled) { + this.passwordEnabled = passwordEnabled; + } + + public boolean isCrossZones() { + return crossZones; + } + + public void setCrossZones(boolean crossZones) { + this.crossZones = crossZones; + } + + public long getDomainId() { + return domainId; + } + + public String getDomainName(){ + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + public void setDomainId(long domainId) { + this.domainId = domainId; + } +} diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java index d8b21be53e5..6dfd19c1656 100644 --- a/server/src/com/cloud/vm/UserVmManager.java +++ b/server/src/com/cloud/vm/UserVmManager.java @@ -220,7 +220,7 @@ public interface UserVmManager extends Manager, VirtualMachineManager * @param description the user give description (aka display text) for the template * @return a template if successfully created, null otherwise */ - VMTemplateVO createPrivateTemplate(CreateTemplateCmd cmd); + VMTemplateVO createPrivateTemplate(CreateTemplateCmd cmd) throws InternalErrorException; /** * @param userId The Id of the user who invoked this operation. diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 68b39470d16..b8ad9164c01 100644 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -37,8 +37,6 @@ import java.util.concurrent.TimeUnit; import javax.ejb.Local; import javax.naming.ConfigurationException; -import net.sf.ehcache.config.Configuration; - import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -85,7 +83,6 @@ import com.cloud.async.executor.OperationResponse; import com.cloud.async.executor.RebootVMExecutor; import com.cloud.async.executor.StartVMExecutor; import com.cloud.async.executor.StopVMExecutor; -import com.cloud.async.executor.UpgradeVMParam; import com.cloud.async.executor.VMExecutorHelper; import com.cloud.async.executor.VMOperationListener; import com.cloud.async.executor.VMOperationParam; @@ -141,8 +138,6 @@ import com.cloud.network.security.NetworkGroupVO; import com.cloud.offering.ServiceOffering; import com.cloud.offering.ServiceOffering.GuestIpType; import com.cloud.offerings.NetworkOfferingVO; -import com.cloud.serializer.GsonHelper; -import com.cloud.server.ManagementServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; @@ -200,7 +195,6 @@ import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.UserVmDao; -import com.google.gson.Gson; @Local(value={UserVmManager.class}) public class UserVmManagerImpl implements UserVmManager { @@ -737,9 +731,7 @@ public class UserVmManagerImpl implements UserVmManager { VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); ServiceOffering offering = _offeringDao.findById(vm.getServiceOfferingId()); - - long diskOfferingId = -1; - + // If an ISO path is passed in, boot from that ISO // Else, check if the VM already has an ISO attached to it. If so, start the VM with that ISO inserted, but don't boot from it. boolean bootFromISO = false; @@ -1199,8 +1191,7 @@ public class UserVmManagerImpl implements UserVmManager { /* * TODO: cleanup eventually - Refactored API call */ - public boolean upgradeVirtualMachine(UpgradeVMCmd cmd) throws ServerApiException, InvalidParameterValueException - { + public boolean upgradeVirtualMachine(UpgradeVMCmd cmd) throws ServerApiException, InvalidParameterValueException { Long virtualMachineId = cmd.getId(); Long serviceOfferingId = cmd.getServiceOfferingId(); Account account = (Account)UserContext.current().getAccountObject(); @@ -1264,8 +1255,9 @@ public class UserVmManagerImpl implements UserVmManager { "current service offering. Current service offering tags: " + currentTags + "; " + "new service offering tags: " + newTags); } - - long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_UPGRADE, "upgrading Vm with Id: "+vmInstance.getId()); + + // FIXME: save this eventId somewhere as part of the async process? + /*long eventId = */EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_UPGRADE, "upgrading Vm with Id: "+vmInstance.getId()); vmInstance.setServiceOfferingId(serviceOfferingId); vmInstance.setHaEnabled(_serviceOfferingDao.findById(serviceOfferingId).getOfferHA()); @@ -2630,10 +2622,10 @@ public class UserVmManagerImpl implements UserVmManager { if (!isAdmin) { if (account.getId().longValue() != volume.getAccountId()) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a volume with id " + volumeId + " for this account"); + throw new PermissionDeniedException("Unable to create a template from volume with id " + volumeId + ", permission denied."); } } else if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), volume.getDomainId())) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create a template from volume with id " + volumeId + ", permission denied."); + throw new PermissionDeniedException("Unable to create a template from volume with id " + volumeId + ", permission denied."); } String name = cmd.getTemplateName(); @@ -2646,6 +2638,11 @@ public class UserVmManagerImpl implements UserVmManager { } String uniqueName = Long.valueOf((userId == null)?1:userId).toString() + Long.valueOf(volumeId).toString() + UUID.nameUUIDFromBytes(name.getBytes()).toString(); + VMTemplateVO existingTemplate = _templateDao.findByTemplateNameAccountId(name, volume.getAccountId()); + if (existingTemplate != null) { + throw new InvalidParameterValueException("Failed to create private template " + name + ", a template with that name already exists."); + } + // do some parameter defaulting Integer bits = cmd.getBits(); Boolean requiresHvm = cmd.getRequiresHvm(); @@ -2714,22 +2711,33 @@ public class UserVmManagerImpl implements UserVmManager { // FIXME: scheduled events should get saved when the command is actually scheduled, not when it starts executing, need another callback // for when the command is scheduled? Could this fit into the setup / execute / response lifecycle? Right after setup you would // know your job is being scheduled, so you could save this kind of event in setup after verifying params. - long eventId = EventUtils.saveScheduledEvent(userId, volume.getAccountId(), EventTypes.EVENT_TEMPLATE_CREATE, "creating template" +name); + /*long eventId = */EventUtils.saveScheduledEvent(userId, volume.getAccountId(), EventTypes.EVENT_TEMPLATE_CREATE, "creating template" +name); return _templateDao.persist(privateTemplate); } @Override @DB - public VMTemplateVO createPrivateTemplate(CreateTemplateCmd command) { + public VMTemplateVO createPrivateTemplate(CreateTemplateCmd command) throws InternalErrorException { + Long userId = UserContext.current().getUserId(); + if (userId == null) { + userId = User.UID_SYSTEM; + } + Long volumeId = command.getVolumeId(); Long snapshotId = command.getSnapshotId(); + SnapshotVO snapshot = null; // Verify input parameters if (snapshotId != null) { - Snapshot snapshot = _snapshotDao.findById(snapshotId); + snapshot = _snapshotDao.findById(snapshotId); // Set the volumeId to that of the snapshot. All further input parameter checks will be done w.r.t the volume. volumeId = snapshot.getVolumeId(); + } else { + // We are create private template from volume. Create a snapshot, copy the vhd chain of the disk to secondary storage. + // For template snapshot, we use a separate snapshot method. + snapshot = createTemplateSnapshot(userId, volumeId); + snapshotId = snapshot.getId(); } // The volume below could be destroyed or removed. @@ -2749,13 +2757,13 @@ public class UserVmManagerImpl implements UserVmManager { VMTemplateVO privateTemplate = null; long templateId = command.getId(); if (snapshotId != null) { - volumeId = snapshot.getVolumeId(); volume = _volsDao.findById(volumeId); StringBuilder userFolder = new StringBuilder(); Formatter userFolderFormat = new Formatter(userFolder); userFolderFormat.format("u%06d", snapshot.getAccountId()); String uniqueName = getRandomPrivateTemplateName(); + String name = command.getTemplateName(); long zoneId = volume.getDataCenterId(); HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(zoneId); @@ -2860,14 +2868,10 @@ public class UserVmManagerImpl implements UserVmManager { // Increment the number of templates _accountMgr.incrementResourceCount(volume.getAccountId(), ResourceType.template); - } else { - // Remove the template record _templateDao.remove(templateId); } - - } return privateTemplate; }