Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 672E0FA9B for ; Tue, 16 Apr 2013 19:04:01 +0000 (UTC) Received: (qmail 60293 invoked by uid 500); 16 Apr 2013 19:04:00 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 60250 invoked by uid 500); 16 Apr 2013 19:04:00 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 60211 invoked by uid 99); 16 Apr 2013 19:04:00 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 16 Apr 2013 19:04:00 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id C79CD1FC09; Tue, 16 Apr 2013 19:03:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: mchen@apache.org To: commits@cloudstack.apache.org Date: Tue, 16 Apr 2013 19:04:00 -0000 Message-Id: <7d2a2849da4641209f284b446a85710c@git.apache.org> In-Reply-To: <9606a6c0ed1b4001862dd250ab2f1a07@git.apache.org> References: <9606a6c0ed1b4001862dd250ab2f1a07@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/2] git commit: updated refs/heads/object_store to 0da2da8 Fix the flow of deleteTemplateCmd. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/0da2da85 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/0da2da85 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/0da2da85 Branch: refs/heads/object_store Commit: 0da2da852b7615b19ab2b35ec9985389acacca65 Parents: 5933375 Author: Min Chen Authored: Tue Apr 16 12:03:12 2013 -0700 Committer: Min Chen Committed: Tue Apr 16 12:03:12 2013 -0700 ---------------------------------------------------------------------- .../agent/api/storage/DeleteTemplateCommand.java | 25 +- core/src/com/cloud/storage/VMTemplateVO.java | 32 +- .../resource/NfsSecondaryStorageResource.java | 132 ++++-- .../storage/datastore/db/TemplateDataStoreDao.java | 8 + .../storage/image/ImageDataFactoryImpl.java | 14 +- .../storage/image/TemplateServiceImpl.java | 50 ++- .../storage/image/store/TemplateObject.java | 13 +- .../storage/image/db/TemplateDataStoreDaoImpl.java | 53 +++- .../driver/CloudStackImageStoreDriverImpl.java | 76 ++++ .../src/com/cloud/storage/StorageManagerImpl.java | 67 ++-- .../cloud/template/HypervisorTemplateAdapter.java | 160 ++----- .../com/cloud/template/TemplateAdapterBase.java | 2 + server/src/com/cloud/template/TemplateManager.java | 15 +- .../com/cloud/template/TemplateManagerImpl.java | 346 +++++++++------ setup/db/db/schema-410to420.sql | 2 +- 15 files changed, 634 insertions(+), 361 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java b/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java index 69f465c..9b874cf 100644 --- a/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java +++ b/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java @@ -16,17 +16,26 @@ // under the License. package com.cloud.agent.api.storage; +import com.cloud.agent.api.to.DataStoreTO; + public class DeleteTemplateCommand extends ssCommand { + private DataStoreTO store; private String templatePath; + private Long templateId; + private Long accountId; public DeleteTemplateCommand() { } - public DeleteTemplateCommand(String secUrl, String templatePath) { + + public DeleteTemplateCommand(DataStoreTO store, String secUrl, String templatePath, Long templateId, Long accountId) { this.setSecUrl(secUrl); this.templatePath = templatePath; + this.templateId = templateId; + this.accountId = accountId; + this.store = store; } @Override @@ -37,4 +46,18 @@ public class DeleteTemplateCommand extends ssCommand { public String getTemplatePath() { return templatePath; } + + public Long getTemplateId() { + return templateId; + } + + public Long getAccountId() { + return accountId; + } + + public DataStoreTO getDataStore() { + return store; + } + + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/core/src/com/cloud/storage/VMTemplateVO.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/storage/VMTemplateVO.java b/core/src/com/cloud/storage/VMTemplateVO.java index e643d75..e3339fd 100755 --- a/core/src/com/cloud/storage/VMTemplateVO.java +++ b/core/src/com/cloud/storage/VMTemplateVO.java @@ -128,19 +128,16 @@ public class VMTemplateVO implements VirtualMachineTemplate, StateObject listByStoreId(long id); + public List listDestroyed(long storeId); + public void deletePrimaryRecordsForStore(long id); + List listByTemplateStore(long templateId, long storeId); + List listByTemplateStoreStatus(long templateId, long storeId, State... states); List listByTemplateStoreDownloadStatus(long templateId, long storeId, Status... status); TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId); + + TemplateDataStoreVO findByTemplate(long templateId); + + List listByTemplate(long templateId); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageDataFactoryImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageDataFactoryImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageDataFactoryImpl.java index 37204bf..d2c2520 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageDataFactoryImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageDataFactoryImpl.java @@ -28,6 +28,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.image.store.TemplateObject; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -50,6 +52,8 @@ public class ImageDataFactoryImpl implements ImageDataFactory { DataStoreManager storeMgr; @Inject VMTemplatePoolDao templatePoolDao; + @Inject + TemplateDataStoreDao templateStoreDao; @Override public TemplateInfo getTemplate(long templateId, DataStore store) { VMTemplateVO templ = imageDataDao.findById(templateId); @@ -77,13 +81,17 @@ public class ImageDataFactoryImpl implements ImageDataFactory { TemplateObject tmpl = TemplateObject.getTemplate(templ, store); return tmpl; } + + //TODO: this method is problematic, since one template can be stored in multiple image stores. + // need to see if we can get rid of this method or change to plural format. @Override public TemplateInfo getTemplate(long templateId) { VMTemplateVO templ = imageDataDao.findById(templateId); - if (templ.getImageDataStoreId() == null) { - return this.getTemplate(templateId, null); + TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplate(templateId); + DataStore store = null; + if ( tmplStore != null ){ + store = this.storeMgr.getDataStore(tmplStore.getDataStoreId(), DataStoreRole.Image); } - DataStore store = this.storeMgr.getDataStore(templ.getImageDataStoreId(), DataStoreRole.Image); return this.getTemplate(templateId, store); } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java index 3dcb86b..3838108 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java @@ -40,6 +40,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import com.cloud.storage.template.TemplateProp; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; @@ -139,6 +141,28 @@ public class TemplateServiceImpl implements TemplateService { } } + class DeleteTemplateContext extends AsyncRpcConext { + final TemplateObject template; + final AsyncCallFuture future; + + public DeleteTemplateContext(AsyncCompletionCallback callback, TemplateObject template, + AsyncCallFuture future) { + super(callback); + this.template = template; + this.future = future; + } + + public TemplateObject getTemplate() { + return template; + } + + public AsyncCallFuture getFuture() { + return future; + } + + + } + @Override public AsyncCallFuture createTemplateAsync( TemplateInfo template, DataStore store) { @@ -361,7 +385,8 @@ public class TemplateServiceImpl implements TemplateService { List userVmUsingIso = _userVmDao.listByIsoId(tInfo.getId()); //check if there is any Vm using this ISO. if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { - DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(store.getUri(), tInfo.getInstallPath()); + VMTemplateVO template = _templateDao.findById(tInfo.getId()); + DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(store.getTO(), store.getUri(), tInfo.getInstallPath(), template.getId(), template.getAccountId()); try { HostVO ssAhost = _ssvmMgr.pickSsvmHost(store); _agentMgr.sendToSecStorage(ssAhost, dtCommand, null); @@ -458,7 +483,28 @@ public class TemplateServiceImpl implements TemplateService { @Override public AsyncCallFuture deleteTemplateAsync( TemplateInfo template) { - // TODO Auto-generated method stub + TemplateObject to = (TemplateObject) template; + // update template_store_ref status + to.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested); + AsyncCallFuture future = new AsyncCallFuture(); + + DeleteTemplateContext context = new DeleteTemplateContext(null, to, future); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().deleteTemplateCallback(null, null)).setContext(context); + to.getDataStore().getDriver().deleteAsync(to, caller); + return future; + } + + public Void deleteTemplateCallback(AsyncCallbackDispatcher callback, DeleteTemplateContext context) { + CommandResult result = callback.getResult(); + TemplateObject vo = context.getTemplate(); + // we can only update state in template_store_ref table + if (result.isSuccess()) { + vo.processEvent(Event.OperationSuccessed); + } else { + vo.processEvent(Event.OperationFailed); + } + context.getFuture().complete(result); return null; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java ---------------------------------------------------------------------- diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java index 7727f12..15aad4b 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java @@ -69,9 +69,6 @@ public class TemplateObject implements TemplateInfo { return to; } - public void setImageStoreId(long id) { - this.imageVO.setImageDataStoreId(id); - } public void setSize(Long size) { this.imageVO.setSize(size); @@ -85,7 +82,7 @@ public class TemplateObject implements TemplateInfo { public DataStore getDataStore() { return this.dataStore; } - + @Override public String getUniqueName() { return this.imageVO.getUniqueName(); @@ -126,7 +123,7 @@ public class TemplateObject implements TemplateInfo { if (templateHostVO == null) { VMTemplateSwiftVO templateSwiftVO = _swiftMgr.findByTmpltId(templateForVmCreation.getId()); - if (templateSwiftVO != null) { + if (templateSwiftVO != null) { long templateSize = templateSwiftVO.getPhysicalSize(); if (templateSize == 0) { templateSize = templateSwiftVO.getSize(); @@ -172,7 +169,7 @@ public class TemplateObject implements TemplateInfo { throw new CloudRuntimeException("Failed to update state" + e.toString()); } } - + @Override public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) { try { @@ -182,14 +179,14 @@ public class TemplateObject implements TemplateInfo { throw new CloudRuntimeException("Failed to update state" + e.toString()); } } - + @Override public DataTO getTO() { DataTO to = this.dataStore.getDriver().getTO(this); if (to == null) { to = new TemplateObjectTO(this); } - + return to; } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java index e34a1ab..dd8e319 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java @@ -43,9 +43,11 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase updateStateSearch; private SearchBuilder storeSearch; + private SearchBuilder templateSearch; + private SearchBuilder storeTemplateSearch; private SearchBuilder storeTemplateStateSearch; private SearchBuilder storeTemplateDownloadStatusSearch; - private SearchBuilder storeTemplateSearch; + @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -57,12 +59,24 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase listDestroyed(long id) { + SearchCriteria sc = storeSearch.create(); + sc.setParameters("store_id", id); + sc.setParameters("destroyed", true); + return listIncludingRemovedBy(sc); + } + + @Override public void deletePrimaryRecordsForStore(long id) { SearchCriteria sc = storeSearch.create(); sc.setParameters("store_id", id); @@ -145,11 +167,21 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase listByTemplateStore(long templateId, long storeId) { + SearchCriteria sc = storeTemplateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("store_id", storeId); + sc.setParameters("destroyed", false); + return search(sc, null); + } + + @Override public List listByTemplateStoreStatus(long templateId, long storeId, State... states) { SearchCriteria sc = storeTemplateStateSearch.create(); sc.setParameters("template_id", templateId); sc.setParameters("store_id", storeId); sc.setParameters("states", (Object[])states); + sc.setParameters("destroyed", false); return search(sc, null); } @@ -157,10 +189,11 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase listByTemplateStoreDownloadStatus(long templateId, long storeId, Status... status) { - SearchCriteria sc = storeTemplateStateSearch.create(); + SearchCriteria sc = storeTemplateDownloadStatusSearch.create(); sc.setParameters("template_id", templateId); sc.setParameters("store_id", storeId); sc.setParameters("downloadState", (Object[])status); + sc.setParameters("destroyed", false); return search(sc, null); } @@ -173,6 +206,22 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase sc = templateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + return findOneIncludingRemovedBy(sc); + } + + @Override + public List listByTemplate(long templateId) { + SearchCriteria sc = templateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("destroyed", false); + return search(sc, null); + } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java ---------------------------------------------------------------------- diff --git a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java index f902385..85ebd23 100644 --- a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java +++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java @@ -34,6 +34,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.image.ImageStoreDriver; import org.apache.cloudstack.storage.image.store.ImageStoreImpl; import org.apache.cloudstack.storage.image.store.TemplateObject; @@ -44,17 +46,23 @@ import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.DeleteSnapshotBackupCommand; +import com.cloud.agent.api.storage.DeleteTemplateCommand; import com.cloud.agent.api.storage.DeleteVolumeCommand; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.SwiftTO; +import com.cloud.configuration.Resource.ResourceType; +import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.storage.DataStoreRole; import com.cloud.storage.RegisterVolumePayload; import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.SnapshotVO; +import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; @@ -68,9 +76,14 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.dao.VolumeHostDao; import com.cloud.storage.download.DownloadMonitor; import com.cloud.storage.s3.S3Manager; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.storage.swift.SwiftManager; +import com.cloud.user.Account; +import com.cloud.user.dao.AccountDao; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.UserVmDao; public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { private static final Logger s_logger = Logger @@ -92,6 +105,15 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { private SwiftManager _swiftMgr; @Inject private S3Manager _s3Mgr; + @Inject AccountDao _accountDao; + @Inject UserVmDao _userVmDao; + @Inject + SecondaryStorageVmManager _ssvmMgr; + @Inject + private AgentManager _agentMgr; + @Inject TemplateDataStoreDao _templateStoreDao; + + @Override public String grantAccess(DataObject data, EndPoint ep) { // TODO Auto-generated method stub @@ -189,6 +211,60 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { private void deleteTemplate(DataObject data, AsyncCompletionCallback callback) { + TemplateObject templateObj = (TemplateObject) data; + VMTemplateVO template = templateObj.getImage(); + ImageStoreImpl store = (ImageStoreImpl) templateObj.getDataStore(); + long storeId = store.getId(); + Long sZoneId = store.getDataCenterId(); + long templateId = template.getId(); + + Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId()); + String eventType = ""; + + if (template.getFormat().equals(ImageFormat.ISO)) { + eventType = EventTypes.EVENT_ISO_DELETE; + } else { + eventType = EventTypes.EVENT_TEMPLATE_DELETE; + } + + // TODO: need to understand why we need to mark destroyed in + // template_store_ref table here instead of in callback. + // Currently I did that in callback, so I removed previous code to mark template_host_ref + + UsageEventUtils.publishUsageEvent(eventType, account.getId(), sZoneId, templateId, null, null, null); + + List userVmUsingIso = _userVmDao.listByIsoId(templateId); + // check if there is any VM using this ISO. + if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { + HostVO ssAhost = _ssvmMgr.pickSsvmHost(store); + // get installpath of this template on image store + TemplateDataStoreVO tmplStore = _templateStoreDao.findByStoreTemplate(storeId, templateId); + String installPath = tmplStore.getInstallPath(); + if (installPath != null) { + Answer answer = _agentMgr.sendToSecStorage(ssAhost, new DeleteTemplateCommand(store.getTO(), store.getUri(), installPath, template.getId(), template.getAccountId())); + + if (answer == null || !answer.getResult()) { + s_logger.debug("Failed to deleted template at store: " + store.getName()); + CommandResult result = new CommandResult(); + result.setSucess(false); + result.setResult("Delete template failed"); + callback.complete(result); + + } else { + s_logger.debug("Deleted template at: " + installPath); + CommandResult result = new CommandResult(); + result.setSucess(false); + callback.complete(result); + } + + VMTemplateZoneVO templateZone = templateZoneDao.findByZoneTemplate(sZoneId, templateId); + + if (templateZone != null) { + templateZoneDao.remove(templateZone.getId()); + } + } + } + } private void deleteSnapshot(DataObject data, AsyncCompletionCallback callback) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/server/src/com/cloud/storage/StorageManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index a5f82a8..cd15167 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -1234,69 +1234,80 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C public void cleanupSecondaryStorage(boolean recurring) { try { // Cleanup templates in secondary storage hosts - List secondaryStorageHosts = _ssvmMgr - .listSecondaryStorageHostsInAllZones(); - for (HostVO secondaryStorageHost : secondaryStorageHosts) { + List imageStores = this.dataStoreMgr.getImageStoresByScope(new ZoneScope(null)); + for (DataStore store : imageStores) { try { - long hostId = secondaryStorageHost.getId(); - List destroyedTemplateHostVOs = _vmTemplateHostDao - .listDestroyed(hostId); + long storeId = store.getId(); + List destroyedTemplateStoreVOs = this._templateStoreDao.listDestroyed(storeId); s_logger.debug("Secondary storage garbage collector found " - + destroyedTemplateHostVOs.size() + + destroyedTemplateStoreVOs.size() + " templates to cleanup on secondary storage host: " - + secondaryStorageHost.getName()); - for (VMTemplateHostVO destroyedTemplateHostVO : destroyedTemplateHostVOs) { + + store.getName()); + for (TemplateDataStoreVO destroyedTemplateStoreVO : destroyedTemplateStoreVOs) { if (!_tmpltMgr - .templateIsDeleteable(destroyedTemplateHostVO)) { + .templateIsDeleteable(destroyedTemplateStoreVO)) { if (s_logger.isDebugEnabled()) { s_logger.debug("Not deleting template at: " - + destroyedTemplateHostVO); + + destroyedTemplateStoreVO); } continue; } if (s_logger.isDebugEnabled()) { - s_logger.debug("Deleting template host: " - + destroyedTemplateHostVO); + s_logger.debug("Deleting template store: " + + destroyedTemplateStoreVO); } - String installPath = destroyedTemplateHostVO + VMTemplateVO destroyedTemplate = this._vmTemplateDao.findById(destroyedTemplateStoreVO.getTemplateId()); + if ( destroyedTemplate == null ){ + s_logger.error("Cannot find template : " + destroyedTemplateStoreVO.getTemplateId() + " from template table"); + throw new CloudRuntimeException("Template " + destroyedTemplateStoreVO.getTemplateId() + " is found in secondary storage, but not found in template table"); + } + String installPath = destroyedTemplateStoreVO .getInstallPath(); + HostVO ssAhost = this._ssvmMgr.pickSsvmHost(store); if (installPath != null) { + Answer answer = _agentMgr.sendToSecStorage( - secondaryStorageHost, + ssAhost, new DeleteTemplateCommand( - secondaryStorageHost - .getStorageUrl(), - destroyedTemplateHostVO - .getInstallPath())); + store.getTO(), + store.getUri(), + destroyedTemplateStoreVO + .getInstallPath(), + destroyedTemplate.getId(), + destroyedTemplate.getAccountId() + + )); if (answer == null || !answer.getResult()) { s_logger.debug("Failed to delete " - + destroyedTemplateHostVO + + destroyedTemplateStoreVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails())); } else { _vmTemplateHostDao - .remove(destroyedTemplateHostVO.getId()); + .remove(destroyedTemplateStoreVO.getId()); s_logger.debug("Deleted template at: " - + destroyedTemplateHostVO + + destroyedTemplateStoreVO .getInstallPath()); } } else { - _vmTemplateHostDao.remove(destroyedTemplateHostVO + _vmTemplateHostDao.remove(destroyedTemplateStoreVO .getId()); } } } catch (Exception e) { s_logger.warn( - "problem cleaning up templates in secondary storage " - + secondaryStorageHost, e); + "problem cleaning up templates in secondary storage store " + + store.getName(), e); } } + List secondaryStorageHosts = _ssvmMgr + .listSecondaryStorageHostsInAllZones(); // Cleanup snapshot in secondary storage hosts for (HostVO secondaryStorageHost : secondaryStorageHosts) { try { @@ -2037,16 +2048,16 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (scope != null) { try { scopeType = Enum.valueOf(ScopeType.class, scope.toUpperCase()); - + } catch (Exception e) { throw new InvalidParameterValueException("invalid scope" + scope); } - + if (scopeType != ScopeType.ZONE) { throw new InvalidParameterValueException("Only zone wide cache storage is supported"); } } - + if (scopeType == ScopeType.ZONE && dcId == null) { throw new InvalidParameterValueException("zone id can't be null, if scope is zone"); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/server/src/com/cloud/template/HypervisorTemplateAdapter.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index cbffa8e..3399ca1 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -38,6 +38,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -180,7 +181,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te } for (DataStore imageStore : imageStores) { AsyncCallFuture future = this.imageService - .createTemplateAsync(this.imageFactory.getTemplate(template.getId()), imageStore); + .createTemplateAsync(this.imageFactory.getTemplate(template.getId(), imageStore), imageStore); try { future.get(); } catch (InterruptedException e) { @@ -202,123 +203,60 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te boolean success = true; VMTemplateVO template = (VMTemplateVO)profile.getTemplate(); - Long zoneId = profile.getZoneId(); - Long templateId = template.getId(); - - String zoneName; - List secondaryStorageHosts; - if (!template.isCrossZones() && zoneId != null) { - DataCenterVO zone = _dcDao.findById(zoneId); - zoneName = zone.getName(); - secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); - } else { - zoneName = "(all zones)"; - secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInAllZones(); - } - - s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); - - // Make sure the template is downloaded to all the necessary secondary storage hosts - for (HostVO secondaryStorageHost : secondaryStorageHosts) { - long hostId = secondaryStorageHost.getId(); - List templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId); - for (VMTemplateHostVO templateHostVO : templateHostVOs) { - if (templateHostVO.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) { - String errorMsg = "Please specify a template that is not currently being downloaded."; - s_logger.debug("Template: " + template.getName() + " is currently being downloaded to secondary storage host: " + secondaryStorageHost.getName() + "; cant' delete it."); - throw new CloudRuntimeException(errorMsg); - } - } - } - - Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId()); - String eventType = ""; - - if (template.getFormat().equals(ImageFormat.ISO)){ - eventType = EventTypes.EVENT_ISO_DELETE; - } else { - eventType = EventTypes.EVENT_TEMPLATE_DELETE; - } - // Iterate through all necessary secondary storage hosts and mark the template on each host as destroyed - for (HostVO secondaryStorageHost : secondaryStorageHosts) { - long hostId = secondaryStorageHost.getId(); - long sZoneId = secondaryStorageHost.getDataCenterId(); - List templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId); - for (VMTemplateHostVO templateHostVO : templateHostVOs) { - VMTemplateHostVO lock = _tmpltHostDao.acquireInLockTable(templateHostVO.getId()); - try { - if (lock == null) { - s_logger.debug("Failed to acquire lock when deleting templateHostVO with ID: " + templateHostVO.getId()); - success = false; - break; - } - UsageEventUtils.publishUsageEvent(eventType, account.getId(), sZoneId, templateId, null, null, null); - templateHostVO.setDestroyed(true); - _tmpltHostDao.update(templateHostVO.getId(), templateHostVO); - String installPath = templateHostVO.getInstallPath(); - List userVmUsingIso = _userVmDao.listByIsoId(templateId); - //check if there is any VM using this ISO. - if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { - if (installPath != null) { - Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new DeleteTemplateCommand(secondaryStorageHost.getStorageUrl(), installPath)); - - if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to delete " + templateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails())); - } else { - _tmpltHostDao.remove(templateHostVO.getId()); - s_logger.debug("Deleted template at: " + installPath); - } - } else { - _tmpltHostDao.remove(templateHostVO.getId()); - } - } - VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(sZoneId, templateId); - - if (templateZone != null) { - _tmpltZoneDao.remove(templateZone.getId()); - } - } finally { - if (lock != null) { - _tmpltHostDao.releaseFromLockTable(lock.getId()); - } - } - } - - if (!success) { - break; - } - } - - s_logger.debug("Successfully marked template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); + // find all eligible image stores for this template + List imageStores = this.templateMgr.getImageStoreByTemplate(template.getId(), profile.getZoneId()); + if ( imageStores == null || imageStores.size() == 0 ){ + throw new CloudRuntimeException("Unable to find image store to delete template "+ profile.getTemplate()); + } - // If there are no more non-destroyed template host entries for this template, delete it - if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) { - long accountId = template.getAccountId(); + // Make sure the template is downloaded to all found image stores + for (DataStore store : imageStores) { + long storeId = store.getId(); + List templateStores = _tmpltStoreDao.listByTemplateStore(template.getId(), storeId); + for (TemplateDataStoreVO templateStore : templateStores) { + if (templateStore.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) { + String errorMsg = "Please specify a template that is not currently being downloaded."; + s_logger.debug("Template: " + template.getName() + " is currently being downloaded to secondary storage host: " + store.getName() + "; cant' delete it."); + throw new CloudRuntimeException(errorMsg); + } + } + } - VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId); - try { - if (lock == null) { - s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId); - success = false; - } else if (_tmpltDao.remove(templateId)) { - // Decrement the number of templates and total secondary storage space used by the account - _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template); - _resourceLimitMgr.recalculateResourceCount(accountId, account.getDomainId(), - ResourceType.secondary_storage.getOrdinal()); - } + for (DataStore imageStore : imageStores) { + s_logger.info("Delete template from image store: " + imageStore.getName()); + AsyncCallFuture future = this.imageService + .deleteTemplateAsync(this.imageFactory.getTemplate(template.getId(), imageStore)); + try { + CommandResult result = future.get(); + success = result.isSuccess(); + if ( !success ) + break; + } catch (InterruptedException e) { + s_logger.debug("delete template Failed", e); + throw new CloudRuntimeException("delete template Failed", e); + } catch (ExecutionException e) { + s_logger.debug("delete template Failed", e); + throw new CloudRuntimeException("delete template Failed", e); + } + } - } finally { - if (lock != null) { - _tmpltDao.releaseFromLockTable(lock.getId()); - } - } + if (success) { + s_logger.info("Delete template from template table"); + // remove template from vm_templates table + if (_tmpltDao.remove(template.getId())) { + // Decrement the number of templates and total secondary storage + // space used by the account + Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId()); + _resourceLimitMgr.decrementResourceCount(template.getAccountId(), ResourceType.template); + _resourceLimitMgr.recalculateResourceCount(template.getAccountId(), account.getDomainId(), + ResourceType.secondary_storage.getOrdinal()); + } + } + return success; - s_logger.debug("Removed template: " + template.getName() + " because all of its template host refs were marked as destroyed."); - } - return success; } public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/server/src/com/cloud/template/TemplateAdapterBase.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java index 05ba35d..987e6ed 100755 --- a/server/src/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/com/cloud/template/TemplateAdapterBase.java @@ -28,6 +28,7 @@ import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; @@ -75,6 +76,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat protected @Inject DataCenterDao _dcDao; protected @Inject VMTemplateDao _tmpltDao; protected @Inject VMTemplateHostDao _tmpltHostDao; + protected @Inject TemplateDataStoreDao _tmpltStoreDao; protected @Inject VMTemplateZoneDao _tmpltZoneDao; protected @Inject UsageEventDao _usageEventDao; protected @Inject HostDao _hostDao; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0da2da85/server/src/com/cloud/template/TemplateManager.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/template/TemplateManager.java b/server/src/com/cloud/template/TemplateManager.java index af54880..a5d9482 100755 --- a/server/src/com/cloud/template/TemplateManager.java +++ b/server/src/com/cloud/template/TemplateManager.java @@ -20,6 +20,7 @@ import java.util.List; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import com.cloud.dc.DataCenterVO; import com.cloud.exception.InternalErrorException; @@ -39,7 +40,7 @@ public interface TemplateManager extends TemplateApiService{ /** * Prepares a template for vm creation for a certain storage pool. - * + * * @param template * template to prepare * @param pool @@ -52,7 +53,7 @@ public interface TemplateManager extends TemplateApiService{ /** * Copies a template from its current secondary storage server to the secondary storage server in the specified zone. - * + * * @param template * @param srcSecHost * @param srcZone @@ -66,7 +67,7 @@ public interface TemplateManager extends TemplateApiService{ /** * Deletes a template from secondary storage servers - * + * * @param userId * @param templateId * @param zoneId @@ -77,7 +78,7 @@ public interface TemplateManager extends TemplateApiService{ /** * Lists templates in the specified storage pool that are not being used by any VM. - * + * * @param pool * @return list of VMTemplateStoragePoolVO */ @@ -85,13 +86,15 @@ public interface TemplateManager extends TemplateApiService{ /** * Deletes a template in the specified storage pool. - * + * * @param templatePoolVO */ void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO); boolean templateIsDeleteable(VMTemplateHostVO templateHostRef); + boolean templateIsDeleteable(TemplateDataStoreVO templateStoreRef); + VMTemplateHostVO prepareISOForCreate(VMTemplateVO template, StoragePool pool); @@ -117,4 +120,6 @@ public interface TemplateManager extends TemplateApiService{ String getChecksum(Long hostId, String templatePath); + List getImageStoreByTemplate(long templateId, Long zoneId); + }