diff --git a/core/src/com/cloud/agent/api/VMSnapshotTO.java b/core/src/com/cloud/agent/api/VMSnapshotTO.java index c7b42d25bc9..473c39a595d 100644 --- a/core/src/com/cloud/agent/api/VMSnapshotTO.java +++ b/core/src/com/cloud/agent/api/VMSnapshotTO.java @@ -16,6 +16,10 @@ // under the License. package com.cloud.agent.api; +import java.util.List; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; + import com.cloud.vm.snapshot.VMSnapshot; public class VMSnapshotTO { @@ -26,6 +30,7 @@ public class VMSnapshotTO { private Boolean current; private String description; private VMSnapshotTO parent; + private List volumes; public Long getId() { return id; @@ -87,4 +92,11 @@ public class VMSnapshotTO { this.parent = parent; } + public List getVolumes() { + return this.volumes; + } + + public void setVolumes(List volumes) { + this.volumes = volumes; + } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java index be3cce94da9..ad165ccb46c 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java @@ -27,6 +27,7 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority; import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotStrategy; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.storage.snapshot.VMSnapshotHelper; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelperImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelperImpl.java index 320a59ce207..05d40441e0d 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelperImpl.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelperImpl.java @@ -18,14 +18,25 @@ */ package org.apache.cloudstack.storage.vmsnapshot; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.snapshot.VMSnapshotHelper; +import org.apache.cloudstack.storage.to.VolumeObjectTO; + import com.cloud.agent.api.VMSnapshotTO; -import com.cloud.agent.api.to.DataTO; -import com.cloud.agent.api.to.VolumeTO; import com.cloud.exception.InvalidParameterValueException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; -import com.cloud.storage.StoragePool; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; import com.cloud.utils.fsm.NoTransitionException; @@ -36,17 +47,6 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.snapshot.VMSnapshot; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.to.VolumeObjectTO; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; public class VMSnapshotHelperImpl implements VMSnapshotHelper { @Inject diff --git a/engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java b/engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java index 8e36fafb5d2..d68eb36b8e2 100644 --- a/engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java +++ b/engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java @@ -29,7 +29,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotStrategy; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.storage.vmsnapshot.DefaultVMSnapshotStrategy; -import org.apache.cloudstack.storage.vmsnapshot.VMSnapshotHelper; +import org.apache.cloudstack.storage.snapshot.VMSnapshotHelper; import org.apache.cloudstack.test.utils.SpringUtils; import org.junit.Before; import org.junit.Test; diff --git a/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelper.java b/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelper.java index 40ced1d832c..f22659947ee 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelper.java @@ -18,14 +18,15 @@ */ package org.apache.cloudstack.storage.helper; -import com.cloud.agent.api.to.DataTO; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.Scope; -import org.apache.cloudstack.storage.to.SnapshotObjectTO; + +import com.cloud.agent.api.VMSnapshotTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.vm.VirtualMachine; public interface HypervisorHelper { DataTO introduceObject(DataTO object, Scope scope, Long storeId); boolean forgetObject(DataTO object, Scope scope, Long storeId); - SnapshotObjectTO takeSnapshot(SnapshotObjectTO snapshotObjectTO, Scope scope); - boolean revertSnapshot(SnapshotObjectTO snapshotObjectTO, Scope scope); + VMSnapshotTO quiesceVm(VirtualMachine virtualMachine); + boolean unquiesceVM(VirtualMachine virtualMachine, VMSnapshotTO vmSnapshotTO); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelperImpl.java b/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelperImpl.java index 81e6f7c69c5..713c2a98a30 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelperImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/helper/HypervisorHelperImpl.java @@ -18,25 +18,50 @@ */ package org.apache.cloudstack.storage.helper; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.to.DataTO; -import com.cloud.utils.exception.CloudRuntimeException; +import java.util.List; +import java.util.UUID; + +import javax.inject.Inject; + import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.command.ForgetObjectCmd; import org.apache.cloudstack.storage.command.IntroduceObjectAnswer; import org.apache.cloudstack.storage.command.IntroduceObjectCmd; -import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.cloudstack.storage.snapshot.VMSnapshotHelper; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; -import javax.inject.Inject; +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CreateVMSnapshotAnswer; +import com.cloud.agent.api.CreateVMSnapshotCommand; +import com.cloud.agent.api.DeleteVMSnapshotCommand; +import com.cloud.agent.api.VMSnapshotTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.snapshot.VMSnapshot; public class HypervisorHelperImpl implements HypervisorHelper { private static final Logger s_logger = Logger.getLogger(HypervisorHelperImpl.class); @Inject EndPointSelector selector; - + @Inject + VMSnapshotHelper vmSnapshotHelper; + @Inject + GuestOSDao guestOSDao; + @Inject + ConfigurationDao configurationDao; + @Inject + AgentManager agentMgr; @Override public DataTO introduceObject(DataTO object, Scope scope, Long storeId) { EndPoint ep = selector.select(scope, storeId); @@ -66,12 +91,52 @@ public class HypervisorHelperImpl implements HypervisorHelper { } @Override - public SnapshotObjectTO takeSnapshot(SnapshotObjectTO snapshotObjectTO, Scope scope) { - return null; //To change body of implemented methods use File | Settings | File Templates. + public VMSnapshotTO quiesceVm(VirtualMachine virtualMachine) { + String value = configurationDao.getValue("vmsnapshot.create.wait"); + int wait = NumbersUtil.parseInt(value, 1800); + Long hostId = vmSnapshotHelper.pickRunningHost(virtualMachine.getId()); + VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(1L, UUID.randomUUID().toString(), VMSnapshot.Type.DiskAndMemory, null, null, false, + null); + GuestOSVO guestOS = guestOSDao.findById(virtualMachine.getGuestOSId()); + List volumeTOs = vmSnapshotHelper.getVolumeTOList(virtualMachine.getId()); + CreateVMSnapshotCommand ccmd = new CreateVMSnapshotCommand(virtualMachine.getInstanceName(),vmSnapshotTO ,volumeTOs, guestOS.getDisplayName(),virtualMachine.getState()); + ccmd.setWait(wait); + try { + Answer answer = agentMgr.send(hostId, ccmd); + if (answer != null && answer.getResult()) { + CreateVMSnapshotAnswer snapshotAnswer = (CreateVMSnapshotAnswer)answer; + vmSnapshotTO.setVolumes(snapshotAnswer.getVolumeTOs()); + } else { + String errMsg = (answer != null) ? answer.getDetails() : null; + throw new CloudRuntimeException("Failed to quiesce vm, due to " + errMsg); + } + } catch (AgentUnavailableException e) { + throw new CloudRuntimeException("Failed to quiesce vm", e); + } catch (OperationTimedoutException e) { + throw new CloudRuntimeException("Failed to quiesce vm", e); + } + return vmSnapshotTO; } @Override - public boolean revertSnapshot(SnapshotObjectTO snapshotObjectTO, Scope scope) { - return false; //To change body of implemented methods use File | Settings | File Templates. + public boolean unquiesceVM(VirtualMachine virtualMachine, VMSnapshotTO vmSnapshotTO) { + Long hostId = vmSnapshotHelper.pickRunningHost(virtualMachine.getId()); + List volumeTOs = vmSnapshotHelper.getVolumeTOList(virtualMachine.getId()); + GuestOSVO guestOS = guestOSDao.findById(virtualMachine.getGuestOSId()); + + DeleteVMSnapshotCommand deleteSnapshotCommand = new DeleteVMSnapshotCommand(virtualMachine.getInstanceName(), vmSnapshotTO, volumeTOs, guestOS.getDisplayName()); + try { + Answer answer = agentMgr.send(hostId, deleteSnapshotCommand); + if (answer != null && answer.getResult()) { + return true; + } else { + String errMsg = (answer != null) ? answer.getDetails() : null; + throw new CloudRuntimeException("Failed to unquiesce vm, due to " + errMsg); + } + } catch (AgentUnavailableException e) { + throw new CloudRuntimeException("Failed to unquiesce vm", e); + } catch (OperationTimedoutException e) { + throw new CloudRuntimeException("Failed to unquiesce vm", e); + } } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelper.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/VMSnapshotHelper.java similarity index 93% rename from engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelper.java rename to engine/storage/src/org/apache/cloudstack/storage/snapshot/VMSnapshotHelper.java index 1437f800c21..262ec7742f9 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/snapshot/VMSnapshotHelper.java @@ -16,16 +16,16 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cloudstack.storage.vmsnapshot; +package org.apache.cloudstack.storage.snapshot; + +import java.util.List; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; import com.cloud.agent.api.VMSnapshotTO; -import com.cloud.agent.api.to.DataTO; import com.cloud.utils.fsm.NoTransitionException; import com.cloud.vm.snapshot.VMSnapshot; import com.cloud.vm.snapshot.VMSnapshotVO; -import org.apache.cloudstack.storage.to.VolumeObjectTO; - -import java.util.List; public interface VMSnapshotHelper { boolean vmSnapshotStateTransitTo(VMSnapshot vsnp, VMSnapshot.Event event) throws NoTransitionException;