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 protected void injectMockito() { List<HostVO> hosts = new ArrayList<HostVO>(); hosts.add(this.host); Mockito.when( resourceMgr.listAllUpAndEnabledHosts( (Type) Matchers.any(), Matchers.anyLong(), Matchers.anyLong(), Matchers.anyLong())) .thenReturn(hosts); RemoteHostEndPoint ep = RemoteHostEndPoint.getHypervisorHostEndPoint( this.host.getId(), this.host.getPrivateIpAddress(), this.host.getPublicIpAddress()); Mockito.when(epSelector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))) .thenReturn(ep); Mockito.when(epSelector.select(Matchers.any(DataObject.class))).thenReturn(ep); Mockito.when(epSelector.select(Matchers.any(DataStore.class))).thenReturn(ep); }
@Override protected void injectMockito() { if (host == null) { return; } List<HostVO> results = new ArrayList<HostVO>(); results.add(host); Mockito.when(hostDao.listAll()).thenReturn(results); Mockito.when(hostDao.findById(Matchers.anyLong())).thenReturn(host); Mockito.when(hostDao.findHypervisorHostInCluster(Matchers.anyLong())).thenReturn(results); List<EndPoint> eps = new ArrayList<EndPoint>(); eps.add( RemoteHostEndPoint.getHypervisorHostEndPoint( host.getId(), host.getPrivateIpAddress(), host.getPublicIpAddress())); Mockito.when(selector.selectAll(Matchers.any(DataStore.class))).thenReturn(eps); Mockito.when(selector.select(Matchers.any(DataObject.class))).thenReturn(eps.get(0)); Mockito.when(selector.select(Matchers.any(DataObject.class), Matchers.any(DataObject.class))) .thenReturn(eps.get(0)); }
@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 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(); } }