private String generateCopyUrl(TemplateInfo srcTemplate) { DataStore srcStore = srcTemplate.getDataStore(); EndPoint ep = _epSelector.select(srcTemplate); if (ep != null) { if (ep.getPublicAddr() == null) { s_logger.warn("A running secondary storage vm has a null public ip?"); return null; } return generateCopyUrl( ep.getPublicAddr(), ((ImageStoreEntity) srcStore).getMountPoint(), srcTemplate.getInstallPath()); } VMTemplateVO tmplt = _templateDao.findById(srcTemplate.getId()); HypervisorType hyperType = tmplt.getHypervisorType(); /*No secondary storage vm yet*/ if (hyperType != null && hyperType == HypervisorType.KVM) { return "file://" + ((ImageStoreEntity) srcStore).getMountPoint() + "/" + srcTemplate.getInstallPath(); } return null; }
@Override public void createAsync( DataStore dataStore, DataObject vol, AsyncCompletionCallback<CreateCmdResult> callback) { EndPoint ep = selector.select(vol); CreateObjectCommand createCmd = new CreateObjectCommand(null); CreateVolumeContext<CreateCmdResult> context = new CreateVolumeContext<CreateCmdResult>(callback, vol); AsyncCallbackDispatcher<SamplePrimaryDataStoreDriverImpl, Answer> caller = AsyncCallbackDispatcher.create(this); caller.setContext(context).setCallback(caller.getTarget().createAsyncCallback(null, null)); ep.sendMessageAsync(createCmd, caller); }
@Override public void deleteAsync( DataStore dataStore, DataObject data, AsyncCompletionCallback<CommandResult> callback) { CommandResult result = new CommandResult(); try { DeleteCommand cmd = new DeleteCommand(data.getTO()); EndPoint ep = _epSelector.select(data); Answer answer = ep.sendMessage(cmd); if (answer != null && !answer.getResult()) { result.setResult(answer.getDetails()); } } catch (Exception ex) { s_logger.debug("Unable to destoy " + data.getType().toString() + ": " + data.getId(), ex); result.setResult(ex.toString()); } callback.complete(result); }
@Override public void createAsync( DataStore dataStore, DataObject vol, AsyncCompletionCallback<CreateCmdResult> callback) { EndPoint ep = selector.select(vol); if (ep == null) { String errMsg = "No remote endpoint to send command, check if host or ssvm is down?"; s_logger.error(errMsg); throw new CloudRuntimeException(errMsg); } CreateObjectCommand createCmd = new CreateObjectCommand(null); CreateVolumeContext<CreateCmdResult> context = new CreateVolumeContext<CreateCmdResult>(callback, vol); AsyncCallbackDispatcher<SamplePrimaryDataStoreDriverImpl, Answer> caller = AsyncCallbackDispatcher.create(this); caller.setContext(context).setCallback(caller.getTarget().createAsyncCallback(null, null)); ep.sendMessageAsync(createCmd, caller); }
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 protected void runInContext() { // 1. Select all entries with download_state = Not_Downloaded or Download_In_Progress // 2. Get corresponding volume // 3. Get EP using _epSelector // 4. Check if SSVM is owned by this MS // 5. If owned by MS then send command to appropriate SSVM // 6. In listener check for the answer and update DB accordingly List<VolumeDataStoreVO> volumeDataStores = _volumeDataStoreDao.listByVolumeState( Volume.State.NotUploaded, Volume.State.UploadInProgress); for (VolumeDataStoreVO volumeDataStore : volumeDataStores) { try { DataStore dataStore = storeMgr.getDataStore(volumeDataStore.getDataStoreId(), DataStoreRole.Image); EndPoint ep = _epSelector.select(dataStore, volumeDataStore.getExtractUrl()); if (ep == null) { s_logger.warn( "There is no secondary storage VM for image store " + dataStore.getName()); continue; } VolumeVO volume = _volumeDao.findById(volumeDataStore.getVolumeId()); if (volume == null) { s_logger.warn("Volume with id " + volumeDataStore.getVolumeId() + " not found"); continue; } Host host = _hostDao.findById(ep.getId()); UploadStatusCommand cmd = new UploadStatusCommand(volume.getUuid(), EntityType.Volume); if (host != null && host.getManagementServerId() != null) { if (_nodeId == host.getManagementServerId().longValue()) { Answer answer = null; try { answer = ep.sendMessage(cmd); } catch (CloudRuntimeException e) { s_logger.warn( "Unable to get upload status for volume " + volume.getUuid() + ". Error details: " + e.getMessage()); answer = new UploadStatusAnswer(cmd, UploadStatus.UNKNOWN, e.getMessage()); } if (answer == null || !(answer instanceof UploadStatusAnswer)) { s_logger.warn( "No or invalid answer corresponding to UploadStatusCommand for volume " + volumeDataStore.getVolumeId()); continue; } handleVolumeStatusResponse((UploadStatusAnswer) answer, volume, volumeDataStore); } } else { String error = "Volume " + volume.getUuid() + " failed to upload as SSVM is either destroyed or SSVM agent not in 'Up' state"; handleVolumeStatusResponse( new UploadStatusAnswer(cmd, UploadStatus.ERROR, error), volume, volumeDataStore); } } catch (Throwable th) { s_logger.warn( "Exception while checking status for uploaded volume " + volumeDataStore.getExtractUrl() + ". Error details: " + th.getMessage()); if (s_logger.isTraceEnabled()) { s_logger.trace("Exception details: ", th); } } } // Handle for template upload as well List<TemplateDataStoreVO> templateDataStores = _templateDataStoreDao.listByTemplateState( VirtualMachineTemplate.State.NotUploaded, VirtualMachineTemplate.State.UploadInProgress); for (TemplateDataStoreVO templateDataStore : templateDataStores) { try { DataStore dataStore = storeMgr.getDataStore(templateDataStore.getDataStoreId(), DataStoreRole.Image); EndPoint ep = _epSelector.select(dataStore, templateDataStore.getExtractUrl()); if (ep == null) { s_logger.warn( "There is no secondary storage VM for image store " + dataStore.getName()); continue; } VMTemplateVO template = _templateDao.findById(templateDataStore.getTemplateId()); if (template == null) { s_logger.warn("Template with id " + templateDataStore.getTemplateId() + " not found"); continue; } Host host = _hostDao.findById(ep.getId()); UploadStatusCommand cmd = new UploadStatusCommand(template.getUuid(), EntityType.Template); if (host != null && host.getManagementServerId() != null) { if (_nodeId == host.getManagementServerId().longValue()) { Answer answer = null; try { answer = ep.sendMessage(cmd); } catch (CloudRuntimeException e) { s_logger.warn( "Unable to get upload status for template " + template.getUuid() + ". Error details: " + e.getMessage()); answer = new UploadStatusAnswer(cmd, UploadStatus.UNKNOWN, e.getMessage()); } if (answer == null || !(answer instanceof UploadStatusAnswer)) { s_logger.warn( "No or invalid answer corresponding to UploadStatusCommand for template " + templateDataStore.getTemplateId()); continue; } handleTemplateStatusResponse( (UploadStatusAnswer) answer, template, templateDataStore); } } else { String error = "Template " + template.getUuid() + " failed to upload as SSVM is either destroyed or SSVM agent not in 'Up' state"; handleTemplateStatusResponse( new UploadStatusAnswer(cmd, UploadStatus.ERROR, error), template, templateDataStore); } } catch (Throwable th) { s_logger.warn( "Exception while checking status for uploaded template " + templateDataStore.getExtractUrl() + ". Error details: " + th.getMessage()); if (s_logger.isTraceEnabled()) { s_logger.trace("Exception details: ", th); } } } }
@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); } } }
@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(); } }