diff --git a/engine/storage/snapshot/pom.xml b/engine/storage/snapshot/pom.xml index 97ca7f21e33..eda47be41e2 100644 --- a/engine/storage/snapshot/pom.xml +++ b/engine/storage/snapshot/pom.xml @@ -37,6 +37,11 @@ test-jar test + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + 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 edd194e605b..99fc1612faa 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 @@ -36,6 +36,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl; import org.apache.cloudstack.storage.to.SnapshotObjectTO; import com.cloud.exception.InvalidParameterValueException; @@ -53,6 +54,7 @@ import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; @@ -263,6 +265,10 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase { //snapshot is deleted on backup storage, need to delete it on primary storage SnapshotDataStoreVO snapshotOnPrimary = snapshotStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary); if (snapshotOnPrimary != null) { + SnapshotInfo snapshotOnPrimaryInfo = snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Primary); + if (((PrimaryDataStoreImpl)snapshotOnPrimaryInfo.getDataStore()).getPoolType() == StoragePoolType.RBD) { + snapshotSvr.deleteSnapshot(snapshotOnPrimaryInfo); + } snapshotOnPrimary.setState(State.Destroyed); snapshotStoreDao.update(snapshotOnPrimary.getId(), snapshotOnPrimary); } @@ -371,15 +377,17 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase { try { SnapshotInfo parent = snapshot.getParent(); - if (backupedSnapshot != null && parent != null) { - Long parentSnapshotId = parent.getId(); - while (parentSnapshotId != null && parentSnapshotId != 0L) { - SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), parentSnapshotId); - if (snapshotDataStoreVO != null) { - parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId(); - snapshotStoreDao.remove(snapshotDataStoreVO.getId()); - } else { - parentSnapshotId = null; + if (backupedSnapshot != null && parent != null && primaryStore instanceof PrimaryDataStoreImpl) { + if (((PrimaryDataStoreImpl)primaryStore).getPoolType() != StoragePoolType.RBD) { + Long parentSnapshotId = parent.getId(); + while (parentSnapshotId != null && parentSnapshotId != 0L) { + SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), parentSnapshotId); + if (snapshotDataStoreVO != null) { + parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId(); + snapshotStoreDao.remove(snapshotDataStoreVO.getId()); + } else { + parentSnapshotId = null; + } } } SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), snapshot.getId()); 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 51931dbb9af..92e985e023e 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 @@ -1274,7 +1274,48 @@ public class KVMStorageProcessor implements StorageProcessor { @Override public Answer deleteSnapshot(final DeleteCommand cmd) { - return new Answer(cmd); + String snap_full_name = ""; + try { + SnapshotObjectTO snapshotTO = (SnapshotObjectTO) cmd.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) snapshotTO.getDataStore(); + VolumeObjectTO volume = snapshotTO.getVolume(); + KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid()); + KVMPhysicalDisk disk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), volume.getPath()); + String snapshotFullPath = snapshotTO.getPath(); + String snapshotName = snapshotFullPath.substring(snapshotFullPath.lastIndexOf("/") + 1); + snap_full_name = disk.getName() + "@" + snapshotName; + if (primaryPool.getType() == StoragePoolType.RBD) { + Rados r = new Rados(primaryPool.getAuthUserName()); + r.confSet("mon_host", primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort()); + r.confSet("key", primaryPool.getAuthSecret()); + r.confSet("client_mount_timeout", "30"); + r.connect(); + s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host")); + IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir()); + Rbd rbd = new Rbd(io); + RbdImage image = rbd.open(disk.getName()); + try { + s_logger.info("Attempting to remove RBD snapshot " + snap_full_name); + if (image.snapIsProtected(snapshotName)) { + s_logger.debug("Unprotecting RBD snapshot " + snap_full_name); + image.snapUnprotect(snapshotName); + } + image.snapRemove(snapshotName); + s_logger.info("Snapshot " + snap_full_name + " successfully removed from " + + primaryPool.getType().toString() + " pool."); + } finally { + rbd.close(image); + r.ioCtxDestroy(io); + } + } else { + s_logger.warn("Operation not implemented for storage pool type of " + primaryPool.getType().toString()); + throw new InternalErrorException("Operation not implemented for storage pool type of " + primaryPool.getType().toString()); + } + return new Answer(cmd, true, "Snapshot " + snap_full_name + " removed successfully."); + } catch (Exception e) { + s_logger.error(e.getMessage()); + return new Answer(cmd, false, "Failed to remove snapshot " + snap_full_name); + } } @Override