in server/src/main/java/com/cloud/template/TemplateManagerImpl.java [1782:2012]
public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException {
Account caller = CallContext.current().getCallingAccount();
boolean isAdmin = (_accountMgr.isAdmin(caller.getId()));
_accountMgr.checkAccess(caller, null, true, templateOwner);
String name = cmd.getTemplateName();
if ((org.apache.commons.lang3.StringUtils.isBlank(name)
|| (name.length() > VirtualMachineTemplate.MAXIMUM_TEMPLATE_NAME_LENGTH))) {
throw new InvalidParameterValueException(String.format("Template name cannot be null and cannot be more %s characters", VirtualMachineTemplate.MAXIMUM_TEMPLATE_NAME_LENGTH));
}
if (cmd.getTemplateTag() != null) {
if (!_accountService.isRootAdmin(caller.getId())) {
throw new PermissionDeniedException("Parameter templatetag can only be specified by a Root Admin, permission denied");
}
}
// do some parameter defaulting
Integer bits = cmd.getBits();
Boolean requiresHvm = cmd.getRequiresHvm();
Boolean passwordEnabled = cmd.isPasswordEnabled();
Boolean sshKeyEnabled = cmd.isSshKeyEnabled();
Boolean isPublic = cmd.isPublic();
Boolean featured = cmd.isFeatured();
int bitsValue = ((bits == null) ? 64 : bits.intValue());
boolean requiresHvmValue = ((requiresHvm == null) ? true : requiresHvm.booleanValue());
boolean passwordEnabledValue = ((passwordEnabled == null) ? false : passwordEnabled.booleanValue());
boolean sshKeyEnabledValue = ((sshKeyEnabled == null) ? false : sshKeyEnabled.booleanValue());
if (isPublic == null) {
isPublic = Boolean.FALSE;
}
boolean isDynamicScalingEnabled = cmd.isDynamicallyScalable();
// check whether template owner can create public templates
boolean allowPublicUserTemplates = AllowPublicUserTemplates.valueIn(templateOwner.getId());
final Long zoneId = cmd.getZoneId();
if (!isAdmin && !allowPublicUserTemplates && isPublic) {
throw new PermissionDeniedException("Failed to create template " + name + ", only private templates can be created.");
}
Long volumeId = cmd.getVolumeId();
Long snapshotId = cmd.getSnapshotId();
if (zoneId != null && snapshotId == null) {
throw new InvalidParameterValueException("Failed to create private template record, zone ID can only be specified together with snapshot ID.");
}
if ((volumeId == null) && (snapshotId == null)) {
throw new InvalidParameterValueException("Failed to create private template record, neither volume ID nor snapshot ID were specified.");
}
if ((volumeId != null) && (snapshotId != null)) {
throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId +
") and snapshot ID (" + snapshotId + ")");
}
HypervisorType hyperType;
VolumeVO volume = null;
SnapshotVO snapshot = null;
VMTemplateVO privateTemplate = null;
if (volumeId != null) { // create template from volume
volume = _volumeDao.findById(volumeId);
if (volume == null) {
throw new InvalidParameterValueException("Failed to create private template record, unable to find volume " + volumeId);
}
// check permissions
_accountMgr.checkAccess(caller, null, true, volume);
// Don't support creating templates from encrypted volumes (yet)
if (volume.getPassphraseId() != null) {
throw new UnsupportedOperationException("Cannot create templates from encrypted volumes");
}
// If private template is created from Volume, check that the volume
// will not be active when the private template is
// created
if (!_volumeMgr.volumeInactive(volume)) {
String msg = String.format("Unable to create private template for volume: %s; volume is attached to a non-stopped VM, please stop the VM first", volume);
if (logger.isInfoEnabled()) {
logger.info(msg);
}
throw new CloudRuntimeException(msg);
}
hyperType = _volumeDao.getHypervisorType(volumeId);
if (HypervisorType.LXC.equals(hyperType)) {
throw new InvalidParameterValueException(String.format("Template creation is not supported for LXC volume: %s", volume));
}
} else { // create template from snapshot
snapshot = _snapshotDao.findById(snapshotId);
if (snapshot == null) {
throw new InvalidParameterValueException("Failed to create private template record, unable to find snapshot " + snapshotId);
}
// Volume could be removed so find including removed to record source template id.
volume = _volumeDao.findByIdIncludingRemoved(snapshot.getVolumeId());
// Don't support creating templates from encrypted volumes (yet)
if (volume != null && volume.getPassphraseId() != null) {
throw new UnsupportedOperationException("Cannot create templates from snapshots of encrypted volumes");
}
// check permissions
_accountMgr.checkAccess(caller, null, true, snapshot);
if (snapshot.getState() != Snapshot.State.BackedUp) {
throw new InvalidParameterValueException(String.format("Snapshot %s is not in %s state yet and can't be used for template creation",
snapshot, Snapshot.State.BackedUp));
}
/*
* // bug #11428. Operation not supported if vmware and snapshots
* parent volume = ROOT if(snapshot.getHypervisorType() ==
* HypervisorType.VMware && snapshotVolume.getVolumeType() ==
* Type.DATADISK){ throw new UnsupportedServiceException(
* "operation not supported, snapshot with id " + snapshotId +
* " is created from Data Disk"); }
*/
hyperType = snapshot.getHypervisorType();
}
if (zoneId != null) {
DataCenterVO zone = _dcDao.findById(zoneId);
if (zone == null) {
throw new InvalidParameterValueException("Failed to create private template record, invalid zone specified");
}
if (DataCenter.Type.Edge.equals(zone.getType())) {
throw new InvalidParameterValueException("Failed to create private template record, Edge zones do not support template creation from snapshots");
}
}
_resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template);
_resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.secondary_storage, new Long(volume != null ? volume.getSize() : snapshot.getSize()).longValue());
if (!isAdmin || featured == null) {
featured = Boolean.FALSE;
}
Long guestOSId = cmd.getOsTypeId();
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
if (guestOS == null) {
throw new InvalidParameterValueException("GuestOS with ID: " + guestOSId + " does not exist.");
}
Long nextTemplateId = _tmpltDao.getNextInSequence(Long.class, "id");
String description = cmd.getDisplayText();
boolean isExtractable = false;
Long sourceTemplateId = null;
CPU.CPUArch arch = CPU.CPUArch.amd64;
if (volume != null) {
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
if (template != null) {
arch = template.getArch();
}
if (volume.getIsoId() != null && volume.getIsoId() != 0) {
sourceTemplateId = volume.getIsoId();
} else if (volume.getTemplateId() != null) {
sourceTemplateId = volume.getTemplateId();
}
}
String templateTag = cmd.getTemplateTag();
if (templateTag != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding template tag: " + templateTag);
}
}
privateTemplate = new VMTemplateVO(nextTemplateId, name, ImageFormat.RAW, isPublic, featured, isExtractable,
TemplateType.USER, null, requiresHvmValue, bitsValue, templateOwner.getId(), null, description,
passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag, cmd.getDetails(), sshKeyEnabledValue, isDynamicScalingEnabled, false, false, arch);
if (sourceTemplateId != null) {
if (logger.isDebugEnabled()) {
logger.debug("This template is getting created from other template, setting source template Id to: " + sourceTemplateId);
}
}
// for region wide storage, set cross zones flag
List<ImageStoreVO> stores = _imgStoreDao.findRegionImageStores();
if (!CollectionUtils.isEmpty(stores)) {
privateTemplate.setCrossZones(true);
}
privateTemplate.setSourceTemplateId(sourceTemplateId);
VMTemplateVO template = _tmpltDao.persist(privateTemplate);
// Increment the number of templates
if (template != null) {
Map<String, String> details = new HashMap<String, String>();
if (sourceTemplateId != null) {
VMTemplateVO sourceTemplate = _tmpltDao.findById(sourceTemplateId);
if (sourceTemplate != null && sourceTemplate.getDetails() != null) {
details.putAll(sourceTemplate.getDetails());
}
}
if (volume != null) {
Long vmId = volume.getInstanceId();
if (vmId != null) {
UserVmVO userVm = _userVmDao.findById(vmId);
if (userVm != null) {
_userVmDao.loadDetails(userVm);
Map<String, String> vmDetails = userVm.getDetails();
vmDetails = vmDetails.entrySet()
.stream()
.filter(map -> map.getValue() != null)
.collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
details.putAll(vmDetails);
}
}
}
if (cmd.getDetails() != null) {
details.remove(VmDetailConstants.ENCRYPTED_PASSWORD); // new password will be generated during vm deployment from password enabled template
details.putAll(cmd.getDetails());
}
if (!details.isEmpty()) {
privateTemplate.setDetails(details);
_tmpltDao.saveDetails(privateTemplate);
}
_resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.template);
_resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.secondary_storage,
new Long(volume != null ? volume.getSize() : snapshot.getSize()));
}
if (template != null) {
CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
return template;
} else {
throw new CloudRuntimeException("Failed to create a template");
}
}