TemplateManagerImpl extends ManagerBase implements TemplateManager, TemplateApiService, Configurable { @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", create = true) public VMTemplateVO createPrivateTemplateRecord(final CreateTemplateCmd cmd, final Account templateOwner) throws ResourceAllocationException { final Account caller = CallContext.current().getCallingAccount(); final boolean isAdmin = _accountMgr.isAdmin(caller.getId()); _accountMgr.checkAccess(caller, null, true, templateOwner); final String name = cmd.getTemplateName(); if (name == null || name.length() > 32) { throw new InvalidParameterValueException("Template name cannot be null and should be less than 32 characters"); } if (cmd.getTemplateTag() != null) { if (!_accountService.isRootAdmin(caller.getId())) { throw new PermissionDeniedException("Parameter templatetag can only be specified by a Root Admin, permission denied"); } } final Integer bits = cmd.getBits(); final Boolean requiresHvm = cmd.getRequiresHvm(); final Boolean passwordEnabled = cmd.isPasswordEnabled(); Boolean isPublic = cmd.isPublic(); Boolean featured = cmd.isFeatured(); final int bitsValue = bits == null ? 64 : bits.intValue(); final boolean requiresHvmValue = requiresHvm == null ? true : requiresHvm.booleanValue(); final boolean passwordEnabledValue = passwordEnabled == null ? false : passwordEnabled.booleanValue(); if (isPublic == null) { isPublic = Boolean.FALSE; } final boolean isDynamicScalingEnabled = cmd.isDynamicallyScalable(); final boolean allowPublicUserTemplates = AllowPublicUserTemplates.valueIn(templateOwner.getId()); if (!isAdmin && !allowPublicUserTemplates && isPublic) { throw new PermissionDeniedException("Failed to create template " + name + ", only private templates can be created."); } final Long volumeId = cmd.getVolumeId(); final Long snapshotId = cmd.getSnapshotId(); 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 + ")"); } final HypervisorType hyperType; VolumeVO volume = null; SnapshotVO snapshot = null; VMTemplateVO privateTemplate = null; if (volumeId != null) { volume = _volumeDao.findById(volumeId); if (volume == null) { throw new InvalidParameterValueException("Failed to create private template record, unable to find volume " + volumeId); } _accountMgr.checkAccess(caller, null, true, volume); if (!_volumeMgr.volumeInactive(volume)) { final String msg = "Unable to create private template for volume: " + volume.getName() + "; volume is attached to a non-stopped VM, please stop the VM first"; if (s_logger.isInfoEnabled()) { s_logger.info(msg); } throw new CloudRuntimeException(msg); } hyperType = _volumeDao.getHypervisorType(volumeId); } else { snapshot = _snapshotDao.findById(snapshotId); if (snapshot == null) { throw new InvalidParameterValueException("Failed to create private template record, unable to find snapshot " + snapshotId); } volume = _volumeDao.findByIdIncludingRemoved(snapshot.getVolumeId()); _accountMgr.checkAccess(caller, null, true, snapshot); if (snapshot.getState() != Snapshot.State.BackedUp) { throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.State.BackedUp + " state yet and can't be used for template creation"); } hyperType = snapshot.getHypervisorType(); } _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; } final Long guestOSId = cmd.getOsTypeId(); final GuestOSVO guestOS = _guestOSDao.findById(guestOSId); if (guestOS == null) { throw new InvalidParameterValueException("GuestOS with ID: " + guestOSId + " does not exist."); } final Long nextTemplateId = _tmpltDao.getNextInSequence(Long.class, "id"); final String description = cmd.getDisplayText(); boolean isExtractable = false; Long sourceTemplateId = null; if (volume != null) { final VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId()); isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM; if (volume.getIsoId() != null && volume.getIsoId() != 0) { sourceTemplateId = volume.getIsoId(); } else if (volume.getTemplateId() != null) { sourceTemplateId = volume.getTemplateId(); } } final String templateTag = cmd.getTemplateTag(); if (templateTag != null) { if (s_logger.isDebugEnabled()) { s_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(), false, isDynamicScalingEnabled); if (sourceTemplateId != null) { if (s_logger.isDebugEnabled()) { s_logger.debug("This template is getting created from other template, setting source template Id to: " + sourceTemplateId); } } final List<ImageStoreVO> stores = _imgStoreDao.findRegionImageStores(); if (!CollectionUtils.isEmpty(stores)) { privateTemplate.setCrossZones(true); } privateTemplate.setSourceTemplateId(sourceTemplateId); final VMTemplateVO template = _tmpltDao.persist(privateTemplate); if (template != null) { final Map<String, String> details = new HashMap<>(); if (volume != null) { final Long vmId = volume.getInstanceId(); if (vmId != null) { final UserVmVO userVm = _userVmDao.findById(vmId); if (userVm != null) { _userVmDao.loadDetails(userVm); details.putAll(userVm.getDetails()); } } } if (cmd.getDetails() != null) { details.remove("Encrypted.Password"); 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) { return template; } else { throw new CloudRuntimeException("Failed to create a template"); } } protected  TemplateManagerImpl(); @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "creating iso") VirtualMachineTemplate registerIso(final RegisterIsoCmd cmd); @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template") VirtualMachineTemplate registerTemplate(final RegisterTemplateCmd cmd); @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating post upload template") GetUploadParamsResponse registerTemplateForPostUpload(final GetUploadParamsForTemplateCmd cmd); @Override DataStore getImageStore(final String storeUuid, final Long zoneId); @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_EXTRACT, eventDescription = "extracting ISO", async = true) String extract(final ExtractIsoCmd cmd); @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_EXTRACT, eventDescription = "extracting template", async = true) String extract(final ExtractTemplateCmd cmd); @Override VirtualMachineTemplate prepareTemplate(final long templateId, final long zoneId, final Long storageId); @Override void prepareIsoForVmProfile(final VirtualMachineProfile profile); void prepareTemplateInAllStoragePools(final VMTemplateVO template, final long zoneId); @Override @DB VMTemplateStoragePoolVO prepareTemplateForCreate(final VMTemplateVO templ, final StoragePool pool); @Override String getChecksum(final DataStore store, final String templatePath); @Override @DB boolean resetTemplateDownloadStateOnPool(final long templateStoragePoolRefId); @Override @DB boolean copy(final long userId, final VMTemplateVO template, final DataStore srcSecStore, final DataCenterVO dstZone); @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_COPY, eventDescription = "copying template", async = true) VirtualMachineTemplate copyTemplate(final CopyTemplateCmd cmd); @Override boolean delete(final long userId, final long templateId, final Long zoneId); @Override List<VMTemplateStoragePoolVO> getUnusedTemplatesInPool(final StoragePoolVO pool); @Override @DB void evictTemplateFromStoragePool(final VMTemplateStoragePoolVO templatePoolVO); @Override boolean start(); @Override boolean stop(); @Override boolean configure(final String name, final Map<String, Object> params); @Override boolean templateIsDeleteable(final VMTemplateHostVO templateHostRef); @Override boolean templateIsDeleteable(final long templateId); @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_DETACH, eventDescription = "detaching ISO", async = true) boolean detachIso(final long vmId); @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_ATTACH, eventDescription = "attaching ISO", async = true) boolean attachIso(final long isoId, final long vmId); @Override TemplateInfo prepareIso(final long isoId, final long dcId); @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_DELETE, eventDescription = "deleting template", async = true) boolean deleteTemplate(final DeleteTemplateCmd cmd); @Override @ActionEvent(eventType = EventTypes.EVENT_ISO_DELETE, eventDescription = "deleting iso", async = true) boolean deleteIso(final DeleteIsoCmd cmd); @Override List<String> listTemplatePermissions(final BaseListTemplateOrIsoPermissionsCmd cmd); @DB @Override boolean updateTemplateOrIsoPermissions(final BaseUpdateTemplateOrIsoPermissionsCmd cmd); @Override @DB @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", async = true) VirtualMachineTemplate createPrivateTemplate(final CreateTemplateCmd command); @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", create = true) VMTemplateVO createPrivateTemplateRecord(final CreateTemplateCmd cmd, final Account templateOwner); @Override Pair<String, String> getAbsoluteIsoPath(final long templateId, final long dataCenterId); @Override String getSecondaryStorageURL(final long zoneId); @Override DataStore getImageStore(final long zoneId, final long tmpltId); @Override DataStore getImageStore(final long tmpltId); @Override Long getTemplateSize(final long templateId, final long zoneId); @Override List<DataStore> getImageStoreByTemplate(final long templateId, final Long zoneId); @Override VMTemplateVO updateTemplate(final UpdateIsoCmd cmd); @Override VMTemplateVO updateTemplate(final UpdateTemplateCmd cmd); @Override String getConfigComponentName(); @Override ConfigKey<?>[] getConfigKeys(); List<TemplateAdapter> getTemplateAdapters(); @Inject void setTemplateAdapters(final List<TemplateAdapter> adapters);  }
@Test public void testCreatePrivateTemplateRecordForRegionStore() throws ResourceAllocationException { CreateTemplateCmd mockCreateCmd = mock(CreateTemplateCmd.class); when(mockCreateCmd.getTemplateName()).thenReturn("test"); when(mockCreateCmd.getTemplateTag()).thenReturn(null); when(mockCreateCmd.getBits()).thenReturn(64); when(mockCreateCmd.getRequiresHvm()).thenReturn(true); when(mockCreateCmd.isPasswordEnabled()).thenReturn(false); when(mockCreateCmd.isPublic()).thenReturn(false); when(mockCreateCmd.isFeatured()).thenReturn(false); when(mockCreateCmd.isDynamicallyScalable()).thenReturn(false); when(mockCreateCmd.getVolumeId()).thenReturn(null); when(mockCreateCmd.getSnapshotId()).thenReturn(1L); when(mockCreateCmd.getOsTypeId()).thenReturn(1L); when(mockCreateCmd.getEventDescription()).thenReturn("test"); when(mockCreateCmd.getDetails()).thenReturn(null); Account mockTemplateOwner = mock(Account.class); SnapshotVO mockSnapshot = mock(SnapshotVO.class); when(snapshotDao.findById(anyLong())).thenReturn(mockSnapshot); when(mockSnapshot.getVolumeId()).thenReturn(1L); when(mockSnapshot.getState()).thenReturn(Snapshot.State.BackedUp); when(mockSnapshot.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer); doNothing().when(resourceLimitMgr).checkResourceLimit(any(Account.class), eq(Resource.ResourceType.template)); doNothing().when(resourceLimitMgr).checkResourceLimit(any(Account.class), eq(Resource.ResourceType.secondary_storage), anyLong()); GuestOSVO mockGuestOS = mock(GuestOSVO.class); when(guestOSDao.findById(anyLong())).thenReturn(mockGuestOS); when(tmpltDao.getNextInSequence(eq(Long.class), eq("id"))).thenReturn(1L); List<ImageStoreVO> mockRegionStores = new ArrayList<>(); ImageStoreVO mockRegionStore = mock(ImageStoreVO.class); mockRegionStores.add(mockRegionStore); when(imgStoreDao.findRegionImageStores()).thenReturn(mockRegionStores); when(tmpltDao.persist(any(VMTemplateVO.class))).thenAnswer(new Answer<VMTemplateVO>() { @Override public VMTemplateVO answer(InvocationOnMock invocationOnMock) throws Throwable { Object[] args = invocationOnMock.getArguments(); return (VMTemplateVO)args[0]; } }); VMTemplateVO template = templateManager.createPrivateTemplateRecord(mockCreateCmd, mockTemplateOwner); assertTrue("Template in a region store should have cross zones set", template.isCrossZones()); }