// @Test public void testCopyBaseImage() { DataStore primaryStore = createPrimaryDataStore(); primaryStoreId = primaryStore.getId(); primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); VolumeVO volume = createVolume(image.getId(), primaryStore.getId()); VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); AsyncCallFuture<VolumeApiResult> future = this.volumeService.createVolumeFromTemplateAsync( volInfo, this.primaryStoreId, this.templateFactory.getTemplate(this.image.getId(), DataStoreRole.Image)); try { VolumeApiResult result = future.get(); AssertJUnit.assertTrue(result.isSuccess()); VolumeInfo newVol = result.getVolume(); this.volumeService.destroyVolume(newVol.getId()); VolumeInfo vol = this.volFactory.getVolume(volume.getId()); this.volumeService.expungeVolumeAsync(vol); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ConcurrentOperationException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
@Test public void testCreateTemplateFromVolume() { DataStore primaryStore = createPrimaryDataStore(); primaryStoreId = primaryStore.getId(); primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); VolumeVO volume = createVolume(null, primaryStore.getId()); VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); AsyncCallFuture<VolumeApiResult> future = this.volumeService.createVolumeAsync(volInfo, primaryStore); try { VolumeApiResult result = future.get(); AssertJUnit.assertTrue(result.isSuccess()); volInfo = result.getVolume(); VMTemplateVO templateVO = createTemplateInDb(); TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId(), DataStoreRole.Image); DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId); this.imageService.createTemplateFromVolumeAsync(volInfo, tmpl, imageStore); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
@Test public void testDeleteDisk() { DataStore primaryStore = createPrimaryDataStore(); primaryStoreId = primaryStore.getId(); primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); VolumeVO volume = createVolume(null, primaryStore.getId()); VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); AsyncCallFuture<VolumeApiResult> future = this.volumeService.createVolumeAsync(volInfo, primaryStore); try { VolumeApiResult result = future.get(); VolumeInfo vol = result.getVolume(); this.volumeService.destroyVolume(volInfo.getId()); volInfo = this.volFactory.getVolume(vol.getId()); this.volumeService.expungeVolumeAsync(volInfo); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ConcurrentOperationException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
@Override public void createAsync( DataStore dataStore, DataObject dataObject, AsyncCompletionCallback<CreateCmdResult> callback) { String iqn = null; String errMsg = null; if (dataObject.getType() == DataObjectType.VOLUME) { VolumeInfo volumeInfo = (VolumeInfo) dataObject; AccountVO account = _accountDao.findById(volumeInfo.getAccountId()); String sfAccountName = getSfAccountName(account.getUuid(), account.getAccountId()); long storagePoolId = dataStore.getId(); SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId); if (!sfAccountExists(sfAccountName, sfConnection)) { SolidFireUtil.SolidFireAccount sfAccount = createSolidFireAccount(sfAccountName, sfConnection); updateCsDbWithAccountInfo(account.getId(), sfAccount); } SolidFireUtil.SolidFireVolume sfVolume = createSolidFireVolume(volumeInfo, sfConnection); iqn = sfVolume.getIqn(); VolumeVO volume = this._volumeDao.findById(volumeInfo.getId()); volume.set_iScsiName(iqn); volume.setFolder(String.valueOf(sfVolume.getId())); volume.setPoolType(StoragePoolType.IscsiLUN); volume.setPoolId(storagePoolId); _volumeDao.update(volume.getId(), volume); StoragePoolVO storagePool = _storagePoolDao.findById(dataStore.getId()); long capacityBytes = storagePool.getCapacityBytes(); long usedBytes = storagePool.getUsedBytes(); usedBytes += volumeInfo.getSize(); storagePool.setUsedBytes(usedBytes > capacityBytes ? capacityBytes : usedBytes); _storagePoolDao.update(storagePoolId, storagePool); } else { errMsg = "Invalid DataObjectType (" + dataObject.getType() + ") passed to createAsync"; } // path = iqn // size is pulled from DataObject instance, if errMsg is null CreateCmdResult result = new CreateCmdResult(iqn, new Answer(null, errMsg == null, errMsg)); result.setResult(errMsg); callback.complete(result); }
@Test public void testCreateDataDisk() { DataStore primaryStore = createPrimaryDataStore(); primaryStoreId = primaryStore.getId(); primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId); VolumeVO volume = createVolume(null, primaryStore.getId()); VolumeInfo volInfo = this.volFactory.getVolume(volume.getId()); this.volumeService.createVolumeAsync(volInfo, primaryStore); }
// @Test(priority=3) public void createAndDeleteDataDisk() { DataStore primaryStore = this.primaryStore; VolumeVO volume = createVolume(null, primaryStore.getId()); VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore); AsyncCallFuture<VolumeApiResult> future = volumeService.createVolumeAsync(vol, primaryStore); try { future.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } // delete the volume vol = volumeFactory.getVolume(volume.getId(), primaryStore); future = volumeService.expungeVolumeAsync(vol); try { future.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
@Override public void addSystemVMTemplatesToSecondary(DataStore store) { long storeId = store.getId(); List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates(); for (VMTemplateVO tmplt : rtngTmplts) { TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); if (tmpltStore == null) { tmpltStore = new TemplateDataStoreVO( storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH + tmplt.getId() + File.separator, tmplt.getUrl()); tmpltStore.setSize(0L); tmpltStore.setPhysicalSize(0); // no size information for // pre-seeded system vm templates tmpltStore.setDataStoreRole(store.getRole()); _vmTemplateStoreDao.persist(tmpltStore); } } }
protected Void createTemplateAsyncCallback( AsyncCallbackDispatcher<? extends BaseImageStoreDriverImpl, DownloadAnswer> callback, CreateContext<CreateCmdResult> context) { if (s_logger.isDebugEnabled()) { s_logger.debug("Performing image store createTemplate async callback"); } DownloadAnswer answer = callback.getResult(); DataObject obj = context.data; DataStore store = obj.getDataStore(); TemplateDataStoreVO tmpltStoreVO = _templateStoreDao.findByStoreTemplate(store.getId(), obj.getId()); if (tmpltStoreVO != null) { if (tmpltStoreVO.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { if (s_logger.isDebugEnabled()) { s_logger.debug( "Template is already in DOWNLOADED state, ignore further incoming DownloadAnswer"); } return null; } TemplateDataStoreVO updateBuilder = _templateStoreDao.createForUpdate(); updateBuilder.setDownloadPercent(answer.getDownloadPct()); updateBuilder.setDownloadState(answer.getDownloadStatus()); updateBuilder.setLastUpdated(new Date()); updateBuilder.setErrorString(answer.getErrorString()); updateBuilder.setJobId(answer.getJobId()); updateBuilder.setLocalDownloadPath(answer.getDownloadPath()); updateBuilder.setInstallPath(answer.getInstallPath()); updateBuilder.setSize(answer.getTemplateSize()); updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); _templateStoreDao.update(tmpltStoreVO.getId(), updateBuilder); // update size in vm_template table VMTemplateVO tmlptUpdater = _templateDao.createForUpdate(); tmlptUpdater.setSize(answer.getTemplateSize()); _templateDao.update(obj.getId(), tmlptUpdater); } AsyncCompletionCallback<CreateCmdResult> caller = context.getParentCallback(); if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) { CreateCmdResult result = new CreateCmdResult(null, null); result.setSuccess(false); result.setResult(answer.getErrorString()); caller.complete(result); } else if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { if (answer.getCheckSum() != null) { VMTemplateVO templateDaoBuilder = _templateDao.createForUpdate(); templateDaoBuilder.setChecksum(answer.getCheckSum()); _templateDao.update(obj.getId(), templateDaoBuilder); } CreateCmdResult result = new CreateCmdResult(null, null); caller.complete(result); } 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; }
@Test(priority = 2) public void createVolumeFromTemplate() { DataStore primaryStore = this.primaryStore; TemplateInfo te = createTemplate(); VolumeVO volume = createVolume(te.getId(), primaryStore.getId()); VolumeInfo vol = volumeFactory.getVolume(volume.getId(), primaryStore); // ve.createVolumeFromTemplate(primaryStore.getId(), new VHD(), te); AsyncCallFuture<VolumeApiResult> future = volumeService.createVolumeFromTemplateAsync(vol, primaryStore.getId(), te); try { future.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
@Override public void createAsync( DataStore dataStore, DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) { CreateContext<CreateCmdResult> context = new CreateContext<CreateCmdResult>(callback, data); AsyncCallbackDispatcher<BaseImageStoreDriverImpl, DownloadAnswer> caller = AsyncCallbackDispatcher.create(this); caller.setContext(context); if (data.getType() == DataObjectType.TEMPLATE) { caller.setCallback(caller.getTarget().createTemplateAsyncCallback(null, null)); if (s_logger.isDebugEnabled()) { s_logger.debug("Downloading template to data store " + dataStore.getId()); } _downloadMonitor.downloadTemplateToStorage(data, caller); } else if (data.getType() == DataObjectType.VOLUME) { caller.setCallback(caller.getTarget().createVolumeAsyncCallback(null, null)); if (s_logger.isDebugEnabled()) { s_logger.debug("Downloading volume to data store " + dataStore.getId()); } _downloadMonitor.downloadVolumeToStorage(data, caller); } }
@Override public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor( hypervisorType, scope.getScopeId()); s_logger.debug("In createPool. Attaching the pool to each of the hosts."); List<HostVO> poolHosts = new ArrayList<HostVO>(); for (HostVO host : hosts) { try { this.storageMgr.connectHostToSharedPool(host.getId(), dataStore.getId()); poolHosts.add(host); } catch (Exception e) { s_logger.warn("Unable to establish a connection between " + host + " and " + dataStore, e); } } if (poolHosts.isEmpty()) { s_logger.warn("No host can access storage pool " + dataStore + " in this zone."); primaryDataStoreDao.expunge(dataStore.getId()); throw new CloudRuntimeException( "Failed to create storage pool as it is not accessible to hosts."); } this.dataStoreHelper.attachZone(dataStore, hypervisorType); return true; }
@Override public void deleteAsync( DataStore dataStore, DataObject dataObject, AsyncCompletionCallback<CommandResult> callback) { String errMsg = null; if (dataObject.getType() == DataObjectType.VOLUME) { VolumeInfo volumeInfo = (VolumeInfo) dataObject; AccountVO account = _accountDao.findById(volumeInfo.getAccountId()); AccountDetailVO accountDetails = _accountDetailsDao.findDetail(account.getAccountId(), SolidFireUtil.ACCOUNT_ID); long sfAccountId = Long.parseLong(accountDetails.getValue()); long storagePoolId = dataStore.getId(); SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId); deleteSolidFireVolume(volumeInfo, sfConnection); _volumeDao.deleteVolumesByInstance(volumeInfo.getId()); // if (!sfAccountHasVolume(sfAccountId, sfConnection)) { // // delete the account from the SolidFire SAN // deleteSolidFireAccount(sfAccountId, sfConnection); // // // delete the info in the account_details table // // that's related to the SolidFire account // _accountDetailsDao.deleteDetails(account.getAccountId()); // } StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId); long usedBytes = storagePool.getUsedBytes(); usedBytes -= volumeInfo.getSize(); storagePool.setUsedBytes(usedBytes < 0 ? 0 : usedBytes); _storagePoolDao.update(storagePoolId, storagePool); } else { errMsg = "Invalid DataObjectType (" + dataObject.getType() + ") passed to deleteAsync"; } CommandResult result = new CommandResult(); result.setResult(errMsg); callback.complete(result); }
@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); } } }
private Map<String, TemplateProp> listTemplate(DataStore ssStore) { ListTemplateCommand cmd = new ListTemplateCommand(ssStore.getTO()); EndPoint ep = _epSelector.select(ssStore); 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(cmd, false, errMsg); } else { answer = ep.sendMessage(cmd); } if (answer != null && answer.getResult()) { ListTemplateAnswer tanswer = (ListTemplateAnswer) answer; return tanswer.getTemplateInfo(); } else { if (s_logger.isDebugEnabled()) { s_logger.debug("can not list template for secondary storage host " + ssStore.getId()); } } return null; }
@Override public void downloadTemplateToStorage( DataObject template, AsyncCompletionCallback<DownloadAnswer> callback) { if (template != null) { long templateId = template.getId(); DataStore store = template.getDataStore(); if (isTemplateUpdateable(templateId, store.getId())) { if (template.getUri() != null) { initiateTemplateDownload(template, callback); } else { s_logger.info("Template url is null, cannot download"); DownloadAnswer ans = new DownloadAnswer("Template url is null", Status.UNKNOWN); callback.complete(ans); } } else { s_logger.info("Template download is already in progress or already downloaded"); DownloadAnswer ans = new DownloadAnswer( "Template download is already in progress or already downloaded", Status.UNKNOWN); callback.complete(ans); } } }
@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); } } } }
@DB @Override public boolean deleteDataStore(DataStore store) { List<StoragePoolHostVO> hostPoolRecords = _storagePoolHostDao.listByPoolId(store.getId()); StoragePool pool = (StoragePool) store; boolean deleteFlag = false; // find the hypervisor where the storage is attached to. HypervisorType hType = null; if (hostPoolRecords.size() > 0) { hType = getHypervisorType(hostPoolRecords.get(0).getHostId()); } // Remove the SR associated with the Xenserver for (StoragePoolHostVO host : hostPoolRecords) { DeleteStoragePoolCommand deleteCmd = new DeleteStoragePoolCommand(pool); final Answer answer = agentMgr.easySend(host.getHostId(), deleteCmd); if (answer != null && answer.getResult()) { deleteFlag = true; // if host is KVM hypervisor then send deleteStoragepoolcmd to all the kvm hosts. if (HypervisorType.KVM != hType) { break; } } else { if (answer != null) { s_logger.debug("Failed to delete storage pool: " + answer.getResult()); } } } if (!deleteFlag) { throw new CloudRuntimeException("Failed to delete storage pool on host"); } return dataStoreHelper.deletePrimaryDataStore(store); }
@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; }
@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(); } }
@Override public void downloadVolumeToStorage( DataObject volume, AsyncCompletionCallback<DownloadAnswer> callback) { boolean downloadJobExists = false; VolumeDataStoreVO volumeHost = null; DataStore store = volume.getDataStore(); VolumeInfo volInfo = (VolumeInfo) volume; RegisterVolumePayload payload = (RegisterVolumePayload) volInfo.getpayload(); String url = payload.getUrl(); String checkSum = payload.getChecksum(); ImageFormat format = ImageFormat.valueOf(payload.getFormat()); volumeHost = _volumeStoreDao.findByStoreVolume(store.getId(), volume.getId()); if (volumeHost == null) { volumeHost = new VolumeDataStoreVO( store.getId(), volume.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, "jobid0000", null, url, checkSum); _volumeStoreDao.persist(volumeHost); } else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) { downloadJobExists = true; } Long maxVolumeSizeInBytes = getMaxVolumeSizeInBytes(); if (volumeHost != null) { start(); Volume vol = _volumeDao.findById(volume.getId()); DownloadCommand dcmd = new DownloadCommand( (VolumeObjectTO) (volume.getTO()), maxVolumeSizeInBytes, checkSum, url, format); dcmd.setProxy(getHttpProxy()); if (downloadJobExists) { dcmd = new DownloadProgressCommand(dcmd, volumeHost.getJobId(), RequestType.GET_OR_RESTART); dcmd.setResourceType(ResourceType.VOLUME); } EndPoint ep = _epSelector.select(volume); if (ep == null) { s_logger.warn("There is no secondary storage VM for image store " + store.getName()); return; } DownloadListener dl = new DownloadListener(ep, store, volume, _timer, this, dcmd, callback); ComponentContext.inject(dl); // auto-wired those injected fields in DownloadListener if (downloadJobExists) { dl.setCurrState(volumeHost.getDownloadState()); } try { ep.sendMessageAsync(dcmd, new UploadListener.Callback(ep.getId(), dl)); } catch (Exception e) { s_logger.warn( "Unable to start /resume download of volume " + volume.getId() + " to " + store.getName(), e); dl.setDisconnected(); dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); } } }
private void initiateTemplateDownload( DataObject template, AsyncCompletionCallback<DownloadAnswer> callback) { boolean downloadJobExists = false; TemplateDataStoreVO vmTemplateStore = null; DataStore store = template.getDataStore(); vmTemplateStore = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId()); if (vmTemplateStore == null) { vmTemplateStore = new TemplateDataStoreVO( store.getId(), template.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, "jobid0000", null, template.getUri()); vmTemplateStore.setDataStoreRole(store.getRole()); vmTemplateStore = _vmTemplateStoreDao.persist(vmTemplateStore); } else if ((vmTemplateStore.getJobId() != null) && (vmTemplateStore.getJobId().length() > 2)) { downloadJobExists = true; } Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes(); if (vmTemplateStore != null) { start(); VirtualMachineTemplate tmpl = _templateDao.findById(template.getId()); DownloadCommand dcmd = new DownloadCommand((TemplateObjectTO) (template.getTO()), maxTemplateSizeInBytes); dcmd.setProxy(getHttpProxy()); if (downloadJobExists) { dcmd = new DownloadProgressCommand( dcmd, vmTemplateStore.getJobId(), RequestType.GET_OR_RESTART); } if (vmTemplateStore.isCopy()) { dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd); } EndPoint ep = _epSelector.select(template); if (ep == null) { String errMsg = "There is no secondary storage VM for downloading template to image store " + store.getName(); s_logger.warn(errMsg); throw new CloudRuntimeException(errMsg); } DownloadListener dl = new DownloadListener(ep, store, template, _timer, this, dcmd, callback); ComponentContext.inject(dl); // initialize those auto-wired field in download listener. if (downloadJobExists) { // due to handling existing download job issues, we still keep // downloadState in template_store_ref to avoid big change in // DownloadListener to use // new ObjectInDataStore.State transition. TODO: fix this later // to be able to remove downloadState from template_store_ref. s_logger.info("found existing download job"); dl.setCurrState(vmTemplateStore.getDownloadState()); } try { ep.sendMessageAsync(dcmd, new UploadListener.Callback(ep.getId(), dl)); } catch (Exception e) { s_logger.warn( "Unable to start /resume download of template " + template.getId() + " to " + store.getName(), e); dl.setDisconnected(); dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); } } }