private TemplateInfo createTemplate() { try { DataStore store = createImageStore(); VMTemplateVO image = createImageData(); TemplateInfo template = imageDataFactory.getTemplate(image.getId(), store); // AsyncCallFuture<TemplateApiResult> future = // imageService.createTemplateAsync(template, store); // future.get(); template = imageDataFactory.getTemplate(image.getId(), store); /* * imageProviderMgr.configure("image Provider", new HashMap<String, * Object>()); VMTemplateVO image = createImageData(); * ImageDataStoreProvider defaultProvider = * imageProviderMgr.getProvider("DefaultProvider"); * ImageDataStoreLifeCycle lifeCycle = * defaultProvider.getLifeCycle(); ImageDataStore store = * lifeCycle.registerDataStore("defaultHttpStore", new * HashMap<String, String>()); * imageService.registerTemplate(image.getId(), * store.getImageDataStoreId()); TemplateEntity te = * imageService.getTemplateEntity(image.getId()); return te; */ return template; } catch (Exception e) { Assert.fail("failed", e); return null; } }
@Override public AsyncCallFuture<TemplateApiResult> copyTemplate( TemplateInfo srcTemplate, DataStore destStore) { // generate a URL from source template ssvm to download to destination data store String url = generateCopyUrl(srcTemplate); if (url == null) { s_logger.warn( "Unable to start/resume copy of template " + srcTemplate.getUniqueName() + " to " + destStore.getName() + ", no secondary storage vm in running state in source zone"); throw new CloudRuntimeException("No secondary VM in running state in source template zone "); } TemplateObject tmplForCopy = (TemplateObject) _templateFactory.getTemplate(srcTemplate, destStore); if (s_logger.isDebugEnabled()) { s_logger.debug("Setting source template url to " + url); } tmplForCopy.setUrl(url); if (s_logger.isDebugEnabled()) { s_logger.debug("Mark template_store_ref entry as Creating"); } AsyncCallFuture<TemplateApiResult> future = new AsyncCallFuture<TemplateApiResult>(); DataObject templateOnStore = destStore.create(tmplForCopy); templateOnStore.processEvent(Event.CreateOnlyRequested); if (s_logger.isDebugEnabled()) { s_logger.debug("Invoke datastore driver createAsync to create template on destination store"); } try { TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null, (TemplateObject) templateOnStore, future); AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this); caller .setCallback(caller.getTarget().copyTemplateCrossZoneCallBack(null, null)) .setContext(context); destStore.getDriver().createAsync(destStore, templateOnStore, caller); } catch (CloudRuntimeException ex) { // clean up already persisted template_store_ref entry in case of createTemplateCallback is // never called TemplateDataStoreVO templateStoreVO = _vmTemplateStoreDao.findByStoreTemplate(destStore.getId(), srcTemplate.getId()); if (templateStoreVO != null) { TemplateInfo tmplObj = _templateFactory.getTemplate(srcTemplate, destStore); tmplObj.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); } TemplateApiResult res = new TemplateApiResult((TemplateObject) templateOnStore); res.setResult(ex.getMessage()); future.complete(res); } return future; }
private AsyncCallFuture<TemplateApiResult> syncToRegionStoreAsync( TemplateInfo template, DataStore store) { AsyncCallFuture<TemplateApiResult> future = new AsyncCallFuture<TemplateApiResult>(); // no need to create entry on template_store_ref here, since entries are already created when // prepareSecondaryStorageForMigration is invoked. // But we need to set default install path so that sync can be done in the right s3 path TemplateInfo templateOnStore = _templateFactory.getTemplate(template, store); String installPath = TemplateConstants.DEFAULT_TMPLT_ROOT_DIR + "/" + TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR + template.getAccountId() + "/" + template.getId() + "/" + template.getUniqueName(); ((TemplateObject) templateOnStore).setInstallPath(installPath); TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null, (TemplateObject) templateOnStore, future); AsyncCallbackDispatcher<TemplateServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().syncTemplateCallBack(null, null)).setContext(context); _motionSrv.copyAsync(template, templateOnStore, caller); return future; }
// This routine is used to push templates currently on cache store, but not in region store to // region store. // used in migrating existing NFS secondary storage to S3. @Override public void syncTemplateToRegionStore(long templateId, DataStore store) { if (_storeMgr.isRegionStore(store)) { if (s_logger.isDebugEnabled()) { s_logger.debug("Sync template " + templateId + " from cache to object store..."); } // if template is on region wide object store, check if it is really downloaded there (by // checking install_path). Sync template to region // wide store if it is not there physically. TemplateInfo tmplOnStore = _templateFactory.getTemplate(templateId, store); if (tmplOnStore == null) { throw new CloudRuntimeException( "Cannot find an entry in template_store_ref for template " + templateId + " on region store: " + store.getName()); } if (tmplOnStore.getInstallPath() == null || tmplOnStore.getInstallPath().length() == 0) { // template is not on region store yet, sync to region store TemplateInfo srcTemplate = _templateFactory.getReadyTemplateOnCache(templateId); if (srcTemplate == null) { throw new CloudRuntimeException( "Cannot find template " + templateId + " on cache store"); } AsyncCallFuture<TemplateApiResult> future = syncToRegionStoreAsync(srcTemplate, store); try { TemplateApiResult result = future.get(); if (result.isFailed()) { throw new CloudRuntimeException( "sync template from cache to region wide store failed for image store " + store.getName() + ":" + result.getResult()); } _cacheMgr.releaseCacheObject( srcTemplate); // reduce reference count for template on cache, so it can recycled by // schedule } catch (Exception ex) { throw new CloudRuntimeException( "sync template from cache to region wide store failed for image store " + store.getName()); } } } }
@Override public void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId) { Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>(); List<DataStore> stores = _storeMgr.getImageStoresByScope(new ZoneScope(dcId)); if (stores == null || stores.isEmpty()) { return; } /* Download all the templates in zone with the same hypervisortype */ for (DataStore store : stores) { List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates(); List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); for (VMTemplateVO rtngTmplt : rtngTmplts) { if (rtngTmplt.getHypervisorType() == hostHyper) { toBeDownloaded.add(rtngTmplt); } } for (VMTemplateVO builtinTmplt : defaultBuiltin) { if (builtinTmplt.getHypervisorType() == hostHyper) { toBeDownloaded.add(builtinTmplt); } } for (VMTemplateVO template : toBeDownloaded) { TemplateDataStoreVO tmpltHost = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId()); if (tmpltHost == null || tmpltHost.getState() != ObjectInDataStoreStateMachine.State.Ready) { associateTemplateToZone(template.getId(), dcId); s_logger.info( "Downloading builtin template " + template.getUniqueName() + " to data center: " + dcId); TemplateInfo tmplt = _templateFactory.getTemplate(template.getId(), DataStoreRole.Image); createTemplateAsync(tmplt, store, null); } } } }
@Override public void createTemplateAsync( TemplateInfo template, DataStore store, AsyncCompletionCallback<TemplateApiResult> callback) { // persist template_store_ref entry TemplateObject templateOnStore = (TemplateObject) store.create(template); // update template_store_ref and template state try { templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested); } catch (Exception e) { TemplateApiResult result = new TemplateApiResult(templateOnStore); result.setResult(e.toString()); result.setSuccess(false); if (callback != null) { callback.complete(result); } return; } try { TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(callback, templateOnStore, null); AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context); store.getDriver().createAsync(store, templateOnStore, caller); } catch (CloudRuntimeException ex) { // clean up already persisted template_store_ref entry in case of createTemplateCallback is // never called TemplateDataStoreVO templateStoreVO = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId()); if (templateStoreVO != null) { TemplateInfo tmplObj = _templateFactory.getTemplate(template, store); tmplObj.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); } TemplateApiResult result = new TemplateApiResult(template); result.setResult(ex.getMessage()); if (callback != null) { callback.complete(result); } } }
@Override public void downloadBootstrapSysTemplate(DataStore store) { Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>(); List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates(); for (VMTemplateVO rtngTmplt : rtngTmplts) { toBeDownloaded.add(rtngTmplt); } List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(store.getScope().getScopeId()); if (availHypers.isEmpty()) { /* * This is for cloudzone, local secondary storage resource started * before cluster created */ availHypers.add(HypervisorType.KVM); } /* Baremetal need not to download any template */ availHypers.remove(HypervisorType.BareMetal); availHypers.add(HypervisorType.None); // bug 9809: resume ISO // download. for (VMTemplateVO template : toBeDownloaded) { if (availHypers.contains(template.getHypervisorType())) { // only download sys template applicable for current hypervisor TemplateDataStoreVO tmpltHost = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId()); if (tmpltHost == null || tmpltHost.getState() != ObjectInDataStoreStateMachine.State.Ready) { TemplateInfo tmplt = _templateFactory.getTemplate(template.getId(), DataStoreRole.Image); createTemplateAsync(tmplt, store, null); } } } }
@Override public void handleTemplateSync(DataStore store) { if (store == null) { s_logger.warn("Huh? image store is null"); return; } long storeId = store.getId(); // add lock to make template sync for a data store only be done once String lockString = "templatesync.storeId:" + storeId; GlobalLock syncLock = GlobalLock.getInternLock(lockString); try { if (syncLock.lock(3)) { try { Long zoneId = store.getScope().getScopeId(); Map<String, TemplateProp> templateInfos = listTemplate(store); if (templateInfos == null) { return; } Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>(); List<VMTemplateVO> allTemplates = null; if (zoneId == null) { // region wide store allTemplates = _templateDao.listAllActive(); } else { // zone wide store allTemplates = _templateDao.listAllInZone(zoneId); } List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates(); List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); if (rtngTmplts != null) { for (VMTemplateVO rtngTmplt : rtngTmplts) { if (!allTemplates.contains(rtngTmplt)) { allTemplates.add(rtngTmplt); } } } if (defaultBuiltin != null) { for (VMTemplateVO builtinTmplt : defaultBuiltin) { if (!allTemplates.contains(builtinTmplt)) { allTemplates.add(builtinTmplt); } } } toBeDownloaded.addAll(allTemplates); for (VMTemplateVO tmplt : allTemplates) { String uniqueName = tmplt.getUniqueName(); TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); if (templateInfos.containsKey(uniqueName)) { TemplateProp tmpltInfo = templateInfos.remove(uniqueName); toBeDownloaded.remove(tmplt); if (tmpltStore != null) { s_logger.info("Template Sync found " + uniqueName + " already in the image store"); if (tmpltStore.getDownloadState() != Status.DOWNLOADED) { tmpltStore.setErrorString(""); } if (tmpltInfo.isCorrupted()) { tmpltStore.setDownloadState(Status.DOWNLOAD_ERROR); String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + " is corrupted on secondary storage " + tmpltStore.getId(); tmpltStore.setErrorString(msg); s_logger.info("msg"); if (tmplt.getUrl() == null) { msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + "is corrupted, please check in image store: " + tmpltStore.getDataStoreId(); s_logger.warn(msg); } else { s_logger.info( "Removing template_store_ref entry for corrupted template " + tmplt.getName()); _vmTemplateStoreDao.remove(tmpltStore.getId()); toBeDownloaded.add(tmplt); } } else { tmpltStore.setDownloadPercent(100); tmpltStore.setDownloadState(Status.DOWNLOADED); tmpltStore.setState(ObjectInDataStoreStateMachine.State.Ready); tmpltStore.setInstallPath(tmpltInfo.getInstallPath()); tmpltStore.setSize(tmpltInfo.getSize()); tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); tmpltStore.setLastUpdated(new Date()); // update size in vm_template table VMTemplateVO tmlpt = _templateDao.findById(tmplt.getId()); tmlpt.setSize(tmpltInfo.getSize()); _templateDao.update(tmplt.getId(), tmlpt); // Skipping limit checks for SYSTEM Account and for the templates created from // volumes or snapshots // which already got checked and incremented during createTemplate API call. if (tmpltInfo.getSize() > 0 && tmplt.getAccountId() != Account.ACCOUNT_ID_SYSTEM && tmplt.getUrl() != null) { long accountId = tmplt.getAccountId(); try { _resourceLimitMgr.checkResourceLimit( _accountMgr.getAccount(accountId), com.cloud.configuration.Resource.ResourceType.secondary_storage, tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl())); } catch (ResourceAllocationException e) { s_logger.warn(e.getMessage()); _alertMgr.sendAlert( AlertManager.AlertType.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId, null, e.getMessage(), e.getMessage()); } finally { _resourceLimitMgr.recalculateResourceCount( accountId, _accountMgr.getAccount(accountId).getDomainId(), com.cloud.configuration.Resource.ResourceType.secondary_storage .getOrdinal()); } } } _vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore); } else { tmpltStore = new TemplateDataStoreVO( storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl()); tmpltStore.setSize(tmpltInfo.getSize()); tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); tmpltStore.setDataStoreRole(store.getRole()); _vmTemplateStoreDao.persist(tmpltStore); // update size in vm_template table VMTemplateVO tmlpt = _templateDao.findById(tmplt.getId()); tmlpt.setSize(tmpltInfo.getSize()); _templateDao.update(tmplt.getId(), tmlpt); associateTemplateToZone(tmplt.getId(), zoneId); } } else { s_logger.info( "Template Sync did not find " + uniqueName + " on image store " + storeId + ", may request download based on available hypervisor types"); if (tmpltStore != null) { if (isRegionStore(store) && tmpltStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED && tmpltStore.getState() == State.Ready && tmpltStore.getInstallPath() == null) { s_logger.info( "Keep fake entry in template store table for migration of previous NFS to object store"); } else { s_logger.info( "Removing leftover template " + uniqueName + " entry from template store table"); // remove those leftover entries _vmTemplateStoreDao.remove(tmpltStore.getId()); } } } } if (toBeDownloaded.size() > 0) { /* Only download templates whose hypervirsor type is in the zone */ List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId); if (availHypers.isEmpty()) { /* * This is for cloudzone, local secondary storage resource * started before cluster created */ availHypers.add(HypervisorType.KVM); } /* Baremetal need not to download any template */ availHypers.remove(HypervisorType.BareMetal); availHypers.add(HypervisorType.None); // bug 9809: resume ISO // download. for (VMTemplateVO tmplt : toBeDownloaded) { if (tmplt.getUrl() == null) { // If url is null we can't s_logger.info( "Skip downloading template " + tmplt.getUniqueName() + " since no url is specified."); continue; } // if this is private template, skip sync to a new image store if (!tmplt.isPublicTemplate() && !tmplt.isFeatured() && tmplt.getTemplateType() != TemplateType.SYSTEM) { s_logger.info( "Skip sync downloading private template " + tmplt.getUniqueName() + " to a new image store"); continue; } // if this is a region store, and there is already an DOWNLOADED entry there without // install_path information, which // means that this is a duplicate entry from migration of previous NFS to staging. if (isRegionStore(store)) { TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); if (tmpltStore != null && tmpltStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED && tmpltStore.getState() == State.Ready && tmpltStore.getInstallPath() == null) { s_logger.info("Skip sync template for migration of previous NFS to object store"); continue; } } if (availHypers.contains(tmplt.getHypervisorType())) { s_logger.info( "Downloading template " + tmplt.getUniqueName() + " to image store " + store.getName()); associateTemplateToZone(tmplt.getId(), zoneId); TemplateInfo tmpl = _templateFactory.getTemplate(tmplt.getId(), DataStoreRole.Image); createTemplateAsync(tmpl, store, null); } else { s_logger.info( "Skip downloading template " + tmplt.getUniqueName() + " since current data center does not have hypervisor " + tmplt.getHypervisorType().toString()); } } } for (String uniqueName : templateInfos.keySet()) { TemplateProp tInfo = templateInfos.get(uniqueName); if (_tmpltMgr.templateIsDeleteable(tInfo.getId())) { // we cannot directly call deleteTemplateSync here to // reuse delete logic since in this case, our db does not have // this template at all. TemplateObjectTO tmplTO = new TemplateObjectTO(); tmplTO.setDataStore(store.getTO()); tmplTO.setPath(tInfo.getInstallPath()); tmplTO.setId(tInfo.getId()); DeleteCommand dtCommand = new DeleteCommand(tmplTO); EndPoint ep = _epSelector.select(store); Answer answer = null; if (ep == null) { String errMsg = "No remote endpoint to send command, check if host or ssvm is down?"; s_logger.error(errMsg); answer = new Answer(dtCommand, false, errMsg); } else { answer = ep.sendMessage(dtCommand); } if (answer == null || !answer.getResult()) { s_logger.info("Failed to deleted template at store: " + store.getName()); } else { String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + storeId; s_logger.info(description); } } } } finally { syncLock.unlock(); } } else { s_logger.info( "Couldn't get global lock on " + lockString + ", another thread may be doing template sync on data store " + storeId + " now."); } } finally { syncLock.releaseRef(); } }
@Test(priority = -1) public void setUp() { ComponentContext.initComponentsLifeCycle(); host = hostDao.findByGuid(this.getHostGuid()); if (host != null) { dcId = host.getDataCenterId(); clusterId = host.getClusterId(); podId = host.getPodId(); imageStore = this.imageStoreDao.findByName(imageStoreName); } else { // create data center DataCenterVO dc = new DataCenterVO( UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", null, null, NetworkType.Basic, null, null, true, true, null, null); dc = dcDao.persist(dc); dcId = dc.getId(); // create pod HostPodVO pod = new HostPodVO( UUID.randomUUID().toString(), dc.getId(), this.getHostGateway(), this.getHostCidr(), 8, "test"); pod = podDao.persist(pod); podId = pod.getId(); // create xen cluster ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); cluster.setHypervisorType(HypervisorType.VMware.toString()); cluster.setClusterType(ClusterType.ExternalManaged); cluster.setManagedState(ManagedState.Managed); cluster = clusterDao.persist(cluster); clusterId = cluster.getId(); // setup vcenter ClusterDetailsVO clusterDetailVO = new ClusterDetailsVO(cluster.getId(), "url", null); this.clusterDetailsDao.persist(clusterDetailVO); clusterDetailVO = new ClusterDetailsVO(cluster.getId(), "username", null); this.clusterDetailsDao.persist(clusterDetailVO); clusterDetailVO = new ClusterDetailsVO(cluster.getId(), "password", null); this.clusterDetailsDao.persist(clusterDetailVO); // create xen host host = new HostVO(this.getHostGuid()); host.setName("devcloud vmware host"); host.setType(Host.Type.Routing); host.setPrivateIpAddress(this.getHostIp()); host.setDataCenterId(dc.getId()); host.setVersion("6.0.1"); host.setAvailable(true); host.setSetup(true); host.setPodId(podId); host.setLastPinged(0); host.setResourceState(ResourceState.Enabled); host.setHypervisorType(HypervisorType.VMware); host.setClusterId(cluster.getId()); host = hostDao.persist(host); imageStore = new ImageStoreVO(); imageStore.setName(imageStoreName); imageStore.setDataCenterId(dcId); imageStore.setProviderName("CloudStack ImageStore Provider"); imageStore.setRole(DataStoreRole.Image); imageStore.setUrl(this.getSecondaryStorage()); imageStore.setUuid(UUID.randomUUID().toString()); imageStore.setProtocol("nfs"); imageStore = imageStoreDao.persist(imageStore); } image = new VMTemplateVO(); image.setTemplateType(TemplateType.USER); image.setUrl(this.getTemplateUrl()); image.setUniqueName(UUID.randomUUID().toString()); image.setName(UUID.randomUUID().toString()); image.setPublicTemplate(true); image.setFeatured(true); image.setRequiresHvm(true); image.setBits(64); image.setFormat(Storage.ImageFormat.VHD); image.setEnablePassword(true); image.setEnableSshKey(true); image.setGuestOSId(1); image.setBootable(true); image.setPrepopulate(true); image.setCrossZones(true); image.setExtractable(true); image = imageDataDao.persist(image); /* * TemplateDataStoreVO templateStore = new TemplateDataStoreVO(); * * templateStore.setDataStoreId(imageStore.getId()); * templateStore.setDownloadPercent(100); * templateStore.setDownloadState(Status.DOWNLOADED); * templateStore.setDownloadUrl(imageStore.getUrl()); * templateStore.setInstallPath(this.getImageInstallPath()); * templateStore.setTemplateId(image.getId()); * templateStoreDao.persist(templateStore); */ DataStore store = this.dataStoreMgr.getDataStore(imageStore.getId(), DataStoreRole.Image); TemplateInfo template = templateFactory.getTemplate(image.getId(), DataStoreRole.Image); DataObject templateOnStore = store.create(template); TemplateObjectTO to = new TemplateObjectTO(); to.setPath(this.getImageInstallPath()); CopyCmdAnswer answer = new CopyCmdAnswer(to); templateOnStore.processEvent(Event.CreateOnlyRequested); templateOnStore.processEvent(Event.OperationSuccessed, answer); }
@Override public AsyncCallFuture<TemplateApiResult> copyTemplate( TemplateInfo srcTemplate, DataStore destStore) { // for vmware template, we need to check if ova packing is needed, since template created from // snapshot does not have .ova file // we invoke createEntityExtractURL to trigger ova packing. Ideally, we can directly use // extractURL to pass to following createTemplate. // Need to understand what is the background to use two different urls for copy and extract. if (srcTemplate.getFormat() == ImageFormat.OVA) { ImageStoreEntity tmpltStore = (ImageStoreEntity) srcTemplate.getDataStore(); tmpltStore.createEntityExtractUrl( srcTemplate.getInstallPath(), srcTemplate.getFormat(), srcTemplate); } // generate a URL from source template ssvm to download to destination data store String url = generateCopyUrl(srcTemplate); if (url == null) { s_logger.warn( "Unable to start/resume copy of template " + srcTemplate.getUniqueName() + " to " + destStore.getName() + ", no secondary storage vm in running state in source zone"); throw new CloudRuntimeException("No secondary VM in running state in source template zone "); } TemplateObject tmplForCopy = (TemplateObject) _templateFactory.getTemplate(srcTemplate, destStore); if (s_logger.isDebugEnabled()) { s_logger.debug("Setting source template url to " + url); } tmplForCopy.setUrl(url); if (s_logger.isDebugEnabled()) { s_logger.debug("Mark template_store_ref entry as Creating"); } AsyncCallFuture<TemplateApiResult> future = new AsyncCallFuture<TemplateApiResult>(); DataObject templateOnStore = destStore.create(tmplForCopy); templateOnStore.processEvent(Event.CreateOnlyRequested); if (s_logger.isDebugEnabled()) { s_logger.debug("Invoke datastore driver createAsync to create template on destination store"); } try { TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null, (TemplateObject) templateOnStore, future); AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this); caller .setCallback(caller.getTarget().copyTemplateCrossZoneCallBack(null, null)) .setContext(context); destStore.getDriver().createAsync(destStore, templateOnStore, caller); } catch (CloudRuntimeException ex) { // clean up already persisted template_store_ref entry in case of createTemplateCallback is // never called TemplateDataStoreVO templateStoreVO = _vmTemplateStoreDao.findByStoreTemplate(destStore.getId(), srcTemplate.getId()); if (templateStoreVO != null) { TemplateInfo tmplObj = _templateFactory.getTemplate(srcTemplate, destStore); tmplObj.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); } TemplateApiResult res = new TemplateApiResult((TemplateObject) templateOnStore); res.setResult(ex.getMessage()); future.complete(res); } return future; }