delete snapshot at the backend
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/879a954b Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/879a954b Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/879a954b Branch: refs/heads/object_store Commit: 879a954b98bc071054770fd8625c4f4cc3e0c10c Parents: c6a5a7e Author: Edison Su <[email protected]> Authored: Tue May 14 21:57:07 2013 -0700 Committer: Edison Su <[email protected]> Committed: Tue May 14 21:58:07 2013 -0700 ---------------------------------------------------------------------- core/src/com/cloud/agent/api/SnapshotCommand.java | 4 +- .../cloud/storage/resource/StorageProcessor.java | 3 +- .../StorageSubsystemCommandHandlerBase.java | 2 + .../MockLocalNfsSecondaryStorageResource.java | 3 + .../storage/test/MockLocalHostEndPoint.java | 20 +++ .../cloudstack/storage/test/SnapshotTest.java | 85 ++++++++++---- .../storage/snapshot/SnapshotServiceImpl.java | 37 ++++++- .../snapshot/XenserverSnapshotStrategy.java | 5 +- .../cloudstack/storage/LocalHostEndpoint.java | 2 +- .../kvm/storage/KVMStorageProcessor.java | 6 + .../storage/resource/VmwareStorageProcessor.java | 13 ++ .../xen/resource/XenServerStorageProcessor.java | 30 +++++ .../driver/CloudStackImageStoreDriverImpl.java | 92 ++++++--------- .../com/cloud/template/TemplateManagerImpl.java | 9 ++ .../resource/NfsSecondaryStorageResource.java | 22 +++- 15 files changed, 240 insertions(+), 93 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/core/src/com/cloud/agent/api/SnapshotCommand.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/agent/api/SnapshotCommand.java b/core/src/com/cloud/agent/api/SnapshotCommand.java index d8abeb6..ccf9613 100644 --- a/core/src/com/cloud/agent/api/SnapshotCommand.java +++ b/core/src/com/cloud/agent/api/SnapshotCommand.java @@ -53,8 +53,8 @@ public class SnapshotCommand extends Command { public SnapshotCommand(StoragePool pool, String secondaryStorageUrl, String snapshotUuid, String snapshotName, Long dcId, Long accountId, Long volumeId) { - this.primaryStoragePoolNameLabel = pool.getUuid(); - this.primaryPool = new StorageFilerTO(pool); + // this.primaryStoragePoolNameLabel = pool.getUuid(); + //this.primaryPool = new StorageFilerTO(pool); this.snapshotUuid = snapshotUuid; this.secondaryStorageUrl = secondaryStorageUrl; this.dcId = dcId; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/core/src/com/cloud/storage/resource/StorageProcessor.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/storage/resource/StorageProcessor.java b/core/src/com/cloud/storage/resource/StorageProcessor.java index 86bfe4b..ca441ed 100644 --- a/core/src/com/cloud/storage/resource/StorageProcessor.java +++ b/core/src/com/cloud/storage/resource/StorageProcessor.java @@ -25,8 +25,6 @@ import org.apache.cloudstack.storage.command.DeleteCommand; import org.apache.cloudstack.storage.command.DettachCommand; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.to.DataTO; -import com.cloud.agent.api.to.DiskTO; public interface StorageProcessor { public Answer copyTemplateToPrimaryStorage(CopyCommand cmd); @@ -43,4 +41,5 @@ public interface StorageProcessor { public Answer createSnapshot(CreateObjectCommand cmd); public Answer deleteVolume(DeleteCommand cmd); public Answer createVolumeFromSnapshot(CopyCommand cmd); + public Answer deleteSnapshot(DeleteCommand cmd); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java index d167d61..23ccd31 100644 --- a/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java +++ b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java @@ -110,6 +110,8 @@ public class StorageSubsystemCommandHandlerBase implements StorageSubsystemComma Answer answer = null; if (data.getObjectType() == DataObjectType.VOLUME) { answer = processor.deleteVolume(cmd); + } else if (data.getObjectType() == DataObjectType.SNAPSHOT) { + answer = processor.deleteSnapshot(cmd); } else { answer = new Answer(cmd, false, "unsupported type"); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java ---------------------------------------------------------------------- diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java index 6087bd2..61c09db 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java @@ -51,6 +51,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.S3Utils; import com.cloud.utils.UriUtils; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; @Component public class MockLocalNfsSecondaryStorageResource extends @@ -67,6 +68,8 @@ public class MockLocalNfsSecondaryStorageResource extends // TODO Auto-generated catch block e.printStackTrace(); } + + createTemplateFromSnapshotXenScript = Script.findScript(getDefaultScriptsDir(), "create_privatetemplate_from_snapshot_xen.sh"); /* _storage = new JavaStorageLayer(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockLocalHostEndPoint.java ---------------------------------------------------------------------- diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockLocalHostEndPoint.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockLocalHostEndPoint.java new file mode 100644 index 0000000..31901e2 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockLocalHostEndPoint.java @@ -0,0 +1,20 @@ +package org.apache.cloudstack.storage.test; + +import org.apache.cloudstack.storage.LocalHostEndpoint; +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DownloadCommand; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.DeleteSnapshotBackupCommand; + +public class MockLocalHostEndPoint extends LocalHostEndpoint { + @Override + public Answer sendMessage(Command cmd) { + if ((cmd instanceof CopyCommand) || (cmd instanceof DownloadCommand) || (cmd instanceof DeleteSnapshotBackupCommand)) { + return resource.executeRequest(cmd); + } + // TODO Auto-generated method stub + return new Answer(cmd, false, "unsupported command:" + cmd.toString()); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java ---------------------------------------------------------------------- diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java index 264db68..2739b45 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java @@ -156,6 +156,7 @@ public class SnapshotTest extends CloudStackTestNGBase { long primaryStoreId; VMTemplateVO image; String imageStoreName = "testImageStore"; + RemoteHostEndPoint remoteEp; @Test(priority = -1) public void setUp() { ComponentContext.initComponentsLifeCycle(); @@ -250,6 +251,7 @@ public class SnapshotTest extends CloudStackTestNGBase { TemplateObjectTO to = new TemplateObjectTO(); to.setPath(this.getImageInstallPath()); to.setFormat(ImageFormat.VHD); + to.setSize(1000L); CopyCmdAnswer answer = new CopyCmdAnswer(to); templateOnStore.processEvent(Event.CreateOnlyRequested); templateOnStore.processEvent(Event.OperationSuccessed, answer); @@ -263,10 +265,10 @@ public class SnapshotTest extends CloudStackTestNGBase { hosts.add(this.host); Mockito.when(resourceMgr.listAllUpAndEnabledHosts((Type) Mockito.any(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong())).thenReturn(hosts); - RemoteHostEndPoint ep = RemoteHostEndPoint.getHypervisorHostEndPoint(this.host.getId(), this.host.getPrivateIpAddress()); - Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(ep); - Mockito.when(epSelector.select(Mockito.any(DataObject.class))).thenReturn(ep); - Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(ep); + remoteEp = RemoteHostEndPoint.getHypervisorHostEndPoint(this.host.getId(), this.host.getPrivateIpAddress()); + Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(remoteEp); + Mockito.when(epSelector.select(Mockito.any(DataObject.class))).thenReturn(remoteEp); + Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(remoteEp); Mockito.when(hyGuruMgr.getGuruProcessedCommandTargetHost(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(this.host.getId()); } @@ -360,20 +362,35 @@ public class SnapshotTest extends CloudStackTestNGBase { return null; } - //@Test + @Test public void createSnapshot() { VolumeInfo vol = createCopyBaseImage(); SnapshotVO snapshotVO = createSnapshotInDb(vol); SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); + SnapshotInfo newSnapshot = null; for (SnapshotStrategy strategy : this.snapshotStrategies) { if (strategy.canHandle(snapshot)) { - strategy.takeSnapshot(snapshot); + newSnapshot = strategy.takeSnapshot(snapshot); } } + AssertJUnit.assertNotNull(newSnapshot); + + LocalHostEndpoint ep = new MockLocalHostEndPoint(); + ep.setResource(new MockLocalNfsSecondaryStorageResource()); + Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(ep); + + //delete snapshot + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + strategy.deleteSnapshot(newSnapshot.getId()); + } + } + + Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(remoteEp); } private VMTemplateVO createTemplateInDb() { - image = new VMTemplateVO(); + VMTemplateVO image = new VMTemplateVO(); image.setTemplateType(TemplateType.USER); image.setUniqueName(UUID.randomUUID().toString()); @@ -393,9 +410,9 @@ public class SnapshotTest extends CloudStackTestNGBase { image = imageDataDao.persist(image); return image; } - - //@Test - public void createTemplateFromSnapshot() { + + @Test + public void createVolumeFromSnapshot() { VolumeInfo vol = createCopyBaseImage(); SnapshotVO snapshotVO = createSnapshotInDb(vol); SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); @@ -408,17 +425,36 @@ public class SnapshotTest extends CloudStackTestNGBase { } AssertJUnit.assertTrue(result); - LocalHostEndpoint ep = new LocalHostEndpoint(); - ep.setResource(new MockLocalNfsSecondaryStorageResource()); - Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(ep); - VMTemplateVO templateVO = createTemplateInDb(); - TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId(), DataStoreRole.Image); - DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId); - this.imageService.createTemplateFromSnapshotAsync(snapshot, tmpl, imageStore); + + VolumeVO volVO = createVolume(vol.getTemplateId(), vol.getPoolId()); + VolumeInfo newVol = this.volFactory.getVolume(volVO.getId()); + this.volumeService.createVolumeFromSnapshot(newVol, newVol.getDataStore(), snapshot); } @Test - public void createVolumeFromSnapshot() { + public void deleteSnapshot() { + VolumeInfo vol = createCopyBaseImage(); + SnapshotVO snapshotVO = createSnapshotInDb(vol); + SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); + SnapshotInfo newSnapshot = null; + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + newSnapshot = strategy.takeSnapshot(snapshot); + } + } + AssertJUnit.assertNotNull(newSnapshot); + + //create another snapshot + for (SnapshotStrategy strategy : this.snapshotStrategies) { + if (strategy.canHandle(snapshot)) { + strategy.deleteSnapshot(newSnapshot.getId()); + } + } + + } + + @Test + public void createTemplateFromSnapshot() { VolumeInfo vol = createCopyBaseImage(); SnapshotVO snapshotVO = createSnapshotInDb(vol); SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore()); @@ -431,9 +467,14 @@ public class SnapshotTest extends CloudStackTestNGBase { } AssertJUnit.assertTrue(result); - - VolumeVO volVO = createVolume(vol.getTemplateId(), vol.getPoolId()); - VolumeInfo newVol = this.volFactory.getVolume(volVO.getId()); - this.volumeService.createVolumeFromSnapshot(newVol, newVol.getDataStore(), snapshot); + LocalHostEndpoint ep = new LocalHostEndpoint(); + ep.setResource(new MockLocalNfsSecondaryStorageResource()); + Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(ep); + VMTemplateVO templateVO = createTemplateInDb(); + TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId(), DataStoreRole.Image); + DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId); + this.imageService.createTemplateFromSnapshotAsync(snapshot, tmpl, imageStore); } + + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java index 12d8057..fa6d558 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java @@ -299,6 +299,9 @@ public class SnapshotServiceImpl implements SnapshotService { try { SnapshotResult res = future.get(); + if (res.isFailed()) { + throw new CloudRuntimeException(res.getResult()); + } SnapshotInfo destSnapshot = res.getSnashot(); return destSnapshot; } catch (InterruptedException e) { @@ -319,6 +322,12 @@ public class SnapshotServiceImpl implements SnapshotService { AsyncCallFuture<SnapshotResult> future = context.future; SnapshotResult snapResult = new SnapshotResult(destSnapshot, result.getAnswer()); if (result.isFailed()) { + try { + destSnapshot.processEvent(Event.OperationFailed); + srcSnapshot.processEvent(Snapshot.Event.OperationFailed); + } catch (NoTransitionException e) { + s_logger.debug("Failed to update state: " + e.toString()); + } snapResult.setResult(result.getResult()); future.complete(snapResult); return null; @@ -397,7 +406,33 @@ public class SnapshotServiceImpl implements SnapshotService { @Override public boolean deleteSnapshot(SnapshotInfo snapInfo) { - return true; + snapInfo.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested); + + AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>(); + DeleteSnapshotContext<CommandResult> context = new DeleteSnapshotContext<CommandResult>(null, + snapInfo, future); + AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> caller = AsyncCallbackDispatcher + .create(this); + caller.setCallback( + caller.getTarget().deleteSnapshotCallback(null, null)) + .setContext(context); + DataStore store = snapInfo.getDataStore(); + store.getDriver().deleteAsync(snapInfo, caller); + + SnapshotResult result = null; + try { + result = future.get(); + if (result.isFailed()) { + throw new CloudRuntimeException(result.getResult()); + } + return true; + } catch (InterruptedException e) { + s_logger.debug("delete snapshot is failed: " + e.toString()); + } catch (ExecutionException e) { + s_logger.debug("delete snapshot is failed: " + e.toString()); + } + + return false; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java ---------------------------------------------------------------------- diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java index 072d14b..32504ee 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java @@ -139,7 +139,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase { SnapshotInfo child = snapshot.getChild(); SnapshotInfo parent = snapshot.getParent(); if (child == null) { - if (!parent.getPath().equalsIgnoreCase(snapshot.getPath())) { + if (parent == null || !parent.getPath().equalsIgnoreCase(snapshot.getPath())) { this.snapshotSvr.deleteSnapshot(snapshot); snapshot = parent; continue; @@ -178,9 +178,10 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase { } try { + /* if (snapshotOnPrimary != null) { deleteSnapshotChain(snapshotOnPrimary); - } + }*/ SnapshotInfo snapshotOnImage = this.snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image); if (snapshotOnImage != null) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java index 525a507..3267de8 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java +++ b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java @@ -36,7 +36,7 @@ import com.cloud.storage.download.DownloadListener; public class LocalHostEndpoint implements EndPoint { private ScheduledExecutorService executor; - ServerResource resource; + protected ServerResource resource; public LocalHostEndpoint() { resource = new LocalNfsSecondaryStorageResource(); executor = Executors.newScheduledThreadPool(10); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index c3fa12b..53a9308 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -409,6 +409,8 @@ public class KVMStorageProcessor implements StorageProcessor { TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(templateFolder + File.separator + templateName + ".qcow2"); + newTemplate.setSize(info.virtualSize); + newTemplate.setFormat(ImageFormat.QCOW2); return new CopyCmdAnswer(newTemplate); } catch (Exception e) { s_logger.debug("Failed to create template from volume: " + e.toString()); @@ -902,4 +904,8 @@ public class KVMStorageProcessor implements StorageProcessor { } } + @Override + public Answer deleteSnapshot(DeleteCommand cmd) { + return new Answer(cmd); + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java index 16bfaf5..d3df0f5 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -69,6 +69,7 @@ import com.cloud.hypervisor.vmware.resource.VmwareResource; import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.serializer.GsonHelper; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.JavaStorageLayer; import com.cloud.storage.StorageLayer; import com.cloud.storage.Volume; @@ -579,6 +580,7 @@ public class VmwareStorageProcessor implements StorageProcessor { TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(template.getName()); newTemplate.setFormat(ImageFormat.OVA); + newTemplate.setSize(result.third()); return new CopyCmdAnswer(newTemplate); } catch (Throwable e) { @@ -1272,4 +1274,15 @@ public class VmwareStorageProcessor implements StorageProcessor { } return new CopyCmdAnswer(details); } + + @Override + public Answer deleteSnapshot(DeleteCommand cmd) { + SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData(); + DataStoreTO store = snapshot.getDataStore(); + if (store.getRole() == DataStoreRole.Primary) { + return new Answer(cmd); + } else { + return new Answer(cmd, false, "unsupported command"); + } + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java index 0ef3519..bdc3d30 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java @@ -66,6 +66,7 @@ import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.SwiftTO; import com.cloud.exception.InternalErrorException; import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.resource.StorageProcessor; @@ -1389,6 +1390,7 @@ public class XenServerStorageProcessor implements StorageProcessor { TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(installPath); newTemplate.setFormat(ImageFormat.VHD); + newTemplate.setSize(virtualSize); CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate); return answer; } catch (Exception e) { @@ -1470,4 +1472,32 @@ public class XenServerStorageProcessor implements StorageProcessor { // In all cases return something. return new CopyCmdAnswer(details); } + + @Override + public Answer deleteSnapshot(DeleteCommand cmd) { + SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getData(); + DataStoreTO store = snapshot.getDataStore(); + if (store.getRole() == DataStoreRole.Primary) { + Connection conn = this.hypervisorResource.getConnection(); + VDI snapshotVdi = getVDIbyUuid(conn, snapshot.getPath()); + if (snapshotVdi == null) { + return new Answer(null); + } + String errMsg = null; + try { + this.deleteVDI(conn, snapshotVdi); + } catch (BadServerResponse e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } catch (XenAPIException e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } catch (XmlRpcException e) { + s_logger.debug("delete snapshot failed:" + e.toString()); + errMsg = e.toString(); + } + return new Answer(cmd, false, errMsg); + } + return new Answer(cmd, false, "unsupported storage type"); + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/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 6ebdb69..0c46d5e 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 @@ -48,6 +48,7 @@ import org.apache.cloudstack.storage.snapshot.SnapshotObject; 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.storage.DownloadAnswer; @@ -101,8 +102,6 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { @Inject private S3Manager _s3Mgr; @Inject AccountDao _accountDao; - @Inject UserVmDao _userVmDao; - @Inject UserVmJoinDao _userVmJoinDao; @Inject SecondaryStorageVmManager _ssvmMgr; @Inject @@ -280,46 +279,37 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { UsageEventUtils.publishUsageEvent(eventType, account.getId(), sZoneId, templateId, null, null, null); - List<UserVmJoinVO> userVmUsingIso = _userVmJoinDao.listActiveByIsoId(templateId); - // check if there is any VM using this ISO. - if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { - // get installpath of this template on image store - TemplateDataStoreVO tmplStore = _templateStoreDao.findByStoreTemplate(storeId, templateId); - String installPath = tmplStore.getInstallPath(); - if (installPath != null) { - DeleteTemplateCommand cmd = new DeleteTemplateCommand(store.getTO(), installPath, template.getId(), template.getAccountId()); - EndPoint ep = _epSelector.select(templateObj); - Answer answer = ep.sendMessage(cmd); - - if (answer == null || !answer.getResult()) { - s_logger.debug("Failed to deleted template at store: " + store.getName()); - CommandResult result = new CommandResult(); - result.setSuccess(false); - result.setResult("Delete template failed"); - callback.complete(result); - - } else { - s_logger.debug("Deleted template at: " + installPath); - CommandResult result = new CommandResult(); - result.setSuccess(true); - callback.complete(result); - } - - List<VMTemplateZoneVO> templateZones = templateZoneDao.listByZoneTemplate(sZoneId, templateId); - if (templateZones != null) { - for (VMTemplateZoneVO templateZone : templateZones) { - templateZoneDao.remove(templateZone.getId()); - } - } - } - } else{ - // cannot delete iso due to some VMs are using this - s_logger.debug("Cannot delete iso since some user vms are referencing it"); - CommandResult result = new CommandResult(); - result.setResult("Cannot delete iso since some user vms are referencing it"); - callback.complete(result); + // get installpath of this template on image store + TemplateDataStoreVO tmplStore = _templateStoreDao.findByStoreTemplate(storeId, templateId); + String installPath = tmplStore.getInstallPath(); + if (installPath != null) { + DeleteTemplateCommand cmd = new DeleteTemplateCommand(store.getTO(), installPath, template.getId(), template.getAccountId()); + EndPoint ep = _epSelector.select(templateObj); + Answer answer = ep.sendMessage(cmd); + + if (answer == null || !answer.getResult()) { + s_logger.debug("Failed to deleted template at store: " + store.getName()); + CommandResult result = new CommandResult(); + result.setSuccess(false); + result.setResult("Delete template failed"); + callback.complete(result); + + } else { + s_logger.debug("Deleted template at: " + installPath); + CommandResult result = new CommandResult(); + result.setSuccess(true); + callback.complete(result); + } + + List<VMTemplateZoneVO> templateZones = templateZoneDao.listByZoneTemplate(sZoneId, templateId); + if (templateZones != null) { + for (VMTemplateZoneVO templateZone : templateZones) { + templateZoneDao.remove(templateZone.getId()); + } + } } + } private void deleteSnapshot(DataObject data, AsyncCompletionCallback<CommandResult> callback) { @@ -336,29 +326,17 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { } try { - /*String secondaryStoragePoolUrl = secStore.getUri(); - Long dcId = snapshot.getDataCenterId(); - Long accountId = snapshot.getAccountId(); - Long volumeId = snapshot.getVolumeId(); - - String backupOfSnapshot = snapshotObj; - if (backupOfSnapshot == null) { - callback.complete(result); - return; - } + String secondaryStoragePoolUrl = secStore.getUri(); DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - secStore.getTO(), secondaryStoragePoolUrl, dcId, accountId, volumeId, - backupOfSnapshot, false); + secStore.getTO(), secondaryStoragePoolUrl, null, null, null, + snapshotObj.getPath(), false); EndPoint ep = _epSelector.select(secStore); Answer answer = ep.sendMessage(cmd); - if ((answer != null) && answer.getResult()) { - snapshot.setBackupSnapshotId(null); - snapshotDao.update(snapshotObj.getId(), snapshot); - } else if (answer != null) { + if (answer != null && !answer.getResult()) { result.setResult(answer.getDetails()); - }*/ + } } catch (Exception e) { s_logger.debug("failed to delete snapshot: " + snapshotObj.getId() + ": " + e.toString()); result.setResult(e.toString()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/server/src/com/cloud/template/TemplateManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 922cc34..7fee53c 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -88,6 +88,8 @@ import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DiskTO; import com.cloud.api.ApiDBUtils; +import com.cloud.api.query.dao.UserVmJoinDao; +import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobVO; import com.cloud.configuration.Config; @@ -253,6 +255,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, @Inject VolumeManager _volumeMgr; @Inject ImageStoreDao _imageStoreDao; @Inject EndPointSelector _epSelector; + @Inject UserVmJoinDao _userVmJoinDao; @Inject ConfigurationServer _configServer; @@ -1122,6 +1125,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if (template.getFormat() != ImageFormat.ISO) { throw new InvalidParameterValueException("Please specify a valid iso."); } + + List<UserVmJoinVO> userVmUsingIso = _userVmJoinDao.listActiveByIsoId(templateId); + // check if there is any VM using this ISO. + if (!userVmUsingIso.isEmpty()) { + throw new InvalidParameterValueException("Unable to delete iso, as it's used by other vms"); + } if (zoneId != null && (this._dataStoreMgr.getImageStore(zoneId) == null)) { throw new InvalidParameterValueException("Failed to find a secondary storage store in the specified zone."); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/879a954b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java ---------------------------------------------------------------------- diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index c93b99a..9324176 100755 --- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -45,6 +45,7 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.storage.command.CopyCmdAnswer; import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; import org.apache.cloudstack.storage.command.DownloadCommand; import org.apache.cloudstack.storage.command.DownloadProgressCommand; import org.apache.cloudstack.storage.template.DownloadManager; @@ -161,7 +162,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S protected String _parent = "/mnt/SecStorage"; final private String _tmpltDir = "/var/cloudstack/template"; final private String _tmpltpp = "template.properties"; - private String createTemplateFromSnapshotXenScript; + protected String createTemplateFromSnapshotXenScript; @Override public void disconnected() { @@ -223,7 +224,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return Answer.createUnsupportedCommandAnswer(cmd); } } - + protected Answer copyFromS3ToNfs(CopyCommand cmd, DataTO srcData, S3TO s3, DataTO destData, NfsTO destImageStore) { final String storagePath = destImageStore.getUrl(); final String destPath = destData.getPath(); @@ -353,7 +354,11 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S command.add("-s", snapshotName); command.add("-n", templateName); command.add("-t", destPath); - command.execute(); + String result = command.execute(); + + if (result != null && !result.equalsIgnoreCase("")) { + return new CopyCmdAnswer(result); + } Map<String, Object> params = new HashMap<String, Object>(); params.put(StorageLayer.InstanceConfigKey, _storage); @@ -1109,9 +1114,14 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S private String deleteSnapshotBackupFromLocalFileSystem(final String secondaryStorageUrl, final Long accountId, final Long volumeId, final String name, final Boolean deleteAllFlag) { - - final String lPath = determineSnapshotLocalDirectory(secondaryStorageUrl, accountId, volumeId) + File.pathSeparator - + (deleteAllFlag ? "*" : "*" + name + "*"); + String lPath = null; + int index = name.lastIndexOf(File.separator); + String snapshotPath = name.substring(0, index); + if (deleteAllFlag) { + lPath = this.getRootDir(secondaryStorageUrl) + File.separator + snapshotPath + File.separator + "*"; + } else { + lPath = this.getRootDir(secondaryStorageUrl) + File.separator + name + "*"; + } final String result = deleteLocalFile(lPath);
