Skip to content

Commit a4d8215

Browse files
committed
CLOUDSTACK-7688, CLOUDSTACK-7747: restricted various operations for VM with VM snapshots which breaks VM snapshots.
Now they are informed that they cannot perform the operation. To perform operation they have to remove VM snapshots of VM.
1 parent c78f14c commit a4d8215

File tree

3 files changed

+78
-33
lines changed

3 files changed

+78
-33
lines changed

server/src/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,13 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep
707707
/* Does the caller have authority to act on this volume? */
708708
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume);
709709

710+
if(volume.getInstanceId() != null) {
711+
// Check that Vm to which this volume is attached does not have VM Snapshots
712+
if (_vmSnapshotDao.findByVm(volume.getInstanceId()).size() > 0) {
713+
throw new InvalidParameterValueException("Volume cannot be resized which is attached to VM with VM Snapshots");
714+
}
715+
}
716+
710717
DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
711718
DiskOfferingVO newDiskOffering = null;
712719

@@ -977,7 +984,7 @@ private VolumeVO orchestrateResizeVolume(long volumeId, long currentSize, long n
977984
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
978985

979986
if (storagePool.isManaged() && storagePool.getHypervisor() == HypervisorType.Any && hosts != null && hosts.length > 0) {
980-
HostVO host = this._hostDao.findById(hosts[0]);
987+
HostVO host = _hostDao.findById(hosts[0]);
981988

982989
if (currentSize != newSize && host.getHypervisorType() == HypervisorType.XenServer && !userVm.getState().equals(State.Stopped)) {
983990
throw new InvalidParameterValueException(errorMsg);
@@ -1503,7 +1510,6 @@ public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) {
15031510
// Permissions check
15041511
_accountMgr.checkAccess(caller, null, true, volume);
15051512

1506-
15071513
// Check that the volume is currently attached to a VM
15081514
if (vmId == null) {
15091515
throw new InvalidParameterValueException("The specified volume is not attached to a VM.");
@@ -1693,6 +1699,11 @@ public Volume migrateVolume(MigrateVolumeCmd cmd) {
16931699
vm = _vmInstanceDao.findById(instanceId);
16941700
}
16951701

1702+
// Check that Vm to which this volume is attached does not have VM Snapshots
1703+
if (vm != null && _vmSnapshotDao.findByVm(vm.getId()).size() > 0) {
1704+
throw new InvalidParameterValueException("Volume cannot be migrated, please remove all VM snapshots for VM to which this volume is attached");
1705+
}
1706+
16961707
if (vm != null && vm.getState() == State.Running) {
16971708
// Check if the VM is GPU enabled.
16981709
if(_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
@@ -1926,6 +1937,13 @@ public Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAlloc
19261937
throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId());
19271938
}
19281939

1940+
if (volume.getInstanceId() != null) {
1941+
// Check that Vm to which this volume is attached does not have VM Snapshots
1942+
if (_vmSnapshotDao.findByVm(volume.getInstanceId()).size() > 0) {
1943+
throw new InvalidParameterValueException("Volume snapshot is not allowed, please detach it from VM with VM Snapshots");
1944+
}
1945+
}
1946+
19291947
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
19301948
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zone.getName());
19311949
}

server/src/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535
import javax.inject.Inject;
3636
import javax.naming.ConfigurationException;
3737

38-
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
39-
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
4038
import org.apache.commons.codec.binary.Base64;
4139
import org.apache.log4j.Logger;
4240

@@ -89,6 +87,8 @@
8987
import org.apache.cloudstack.storage.command.DettachCommand;
9088
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
9189
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
90+
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
91+
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
9292

9393
import com.cloud.agent.AgentManager;
9494
import com.cloud.agent.api.Answer;
@@ -276,7 +276,6 @@
276276
import com.cloud.vm.dao.UserVmDao;
277277
import com.cloud.vm.dao.UserVmDetailsDao;
278278
import com.cloud.vm.dao.VMInstanceDao;
279-
import com.cloud.vm.snapshot.VMSnapshot;
280279
import com.cloud.vm.snapshot.VMSnapshotManager;
281280
import com.cloud.vm.snapshot.VMSnapshotVO;
282281
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@@ -822,6 +821,12 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE
822821
+ "; make sure the virtual machine is stopped");
823822
}
824823

824+
// If target VM has associated VM snapshots then don't allow upgrading of VM
825+
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
826+
if (vmSnapshots.size() > 0) {
827+
throw new InvalidParameterValueException("Unable to change service offering for VM, please remove VM snapshots before changing service offering of VM");
828+
}
829+
825830
_accountMgr.checkAccess(caller, null, true, vmInstance);
826831

827832
// Check resource limits for CPU and Memory.
@@ -849,19 +854,6 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE
849854
// Check that the specified service offering ID is valid
850855
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
851856

852-
// remove diskAndMemory VM snapshots
853-
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
854-
for (VMSnapshotVO vmSnapshotVO : vmSnapshots) {
855-
if (vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory) {
856-
if (!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, VMSnapshot.Type.DiskAndMemory)) {
857-
String errMsg = "Failed to remove VM snapshot during upgrading, snapshot id " + vmSnapshotVO.getId();
858-
s_logger.debug(errMsg);
859-
throw new CloudRuntimeException(errMsg);
860-
}
861-
862-
}
863-
}
864-
865857
_itMgr.upgradeVmDb(vmId, svcOffId);
866858
if (newServiceOffering.isDynamic()) {
867859
//save the custom values to the database.
@@ -962,19 +954,6 @@ private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map<String
962954
// Check that the specified service offering ID is valid
963955
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
964956

965-
// remove diskAndMemory VM snapshots
966-
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
967-
for (VMSnapshotVO vmSnapshotVO : vmSnapshots) {
968-
if (vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory) {
969-
if (!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, VMSnapshot.Type.DiskAndMemory)) {
970-
String errMsg = "Failed to remove VM snapshot during upgrading, snapshot id " + vmSnapshotVO.getId();
971-
s_logger.debug(errMsg);
972-
throw new CloudRuntimeException(errMsg);
973-
}
974-
975-
}
976-
}
977-
978957
_itMgr.upgradeVmDb(vmId, svcOffId);
979958
if (newServiceOffering.isDynamic()) {
980959
//save the custom values to the database.
@@ -1012,6 +991,12 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV
1012991
if (vmInstance == null) {
1013992
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
1014993
}
994+
995+
// Check that Vm does not have VM Snapshots
996+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
997+
throw new InvalidParameterValueException("NIC cannot be added to VM with VM Snapshots");
998+
}
999+
10151000
NetworkVO network = _networkDao.findById(networkId);
10161001
if (network == null) {
10171002
throw new InvalidParameterValueException("unable to find a network with id " + networkId);
@@ -1096,6 +1081,12 @@ public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws Invalid
10961081
if (vmInstance == null) {
10971082
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
10981083
}
1084+
1085+
// Check that Vm does not have VM Snapshots
1086+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
1087+
throw new InvalidParameterValueException("NIC cannot be removed from VM with VM Snapshots");
1088+
}
1089+
10991090
NicVO nic = _nicDao.findById(nicId);
11001091
if (nic == null) {
11011092
throw new InvalidParameterValueException("unable to find a nic with id " + nicId);
@@ -1153,6 +1144,12 @@ public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) th
11531144
if (vmInstance == null) {
11541145
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
11551146
}
1147+
1148+
// Check that Vm does not have VM Snapshots
1149+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
1150+
throw new InvalidParameterValueException("NIC cannot be updated for VM with VM Snapshots");
1151+
}
1152+
11561153
NicVO nic = _nicDao.findById(nicId);
11571154
if (nic == null) {
11581155
throw new InvalidParameterValueException("unable to find a nic with id " + nicId);
@@ -1325,6 +1322,14 @@ public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId, Map<S
13251322
// Verify input parameters
13261323
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
13271324

1325+
if (vmInstance != null) {
1326+
// If target VM has associated VM snapshots then don't allow upgrading of VM
1327+
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
1328+
if (vmSnapshots.size() > 0) {
1329+
throw new InvalidParameterValueException("Unable to scale VM, please remove VM snapshots before scaling VM");
1330+
}
1331+
}
1332+
13281333
if (vmInstance.getState().equals(State.Stopped)) {
13291334
upgradeStoppedVirtualMachine(vmId, newServiceOfferingId, customParameters);
13301335
return true;
@@ -3813,6 +3818,11 @@ public VirtualMachine vmStorageMigration(Long vmId, StoragePool destPool) {
38133818
throw new InvalidParameterValueException("Data disks attached to the vm, can not migrate. Need to dettach data disks at first");
38143819
}
38153820

3821+
// Check that Vm does not have VM Snapshots
3822+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
3823+
throw new InvalidParameterValueException("VM's disk cannot be migrated, please remove all the VM Snapshots for this VM");
3824+
}
3825+
38163826
HypervisorType destHypervisorType = destPool.getHypervisor();
38173827
if (destHypervisorType == null) {
38183828
destHypervisorType = _clusterDao.findById(
@@ -4231,6 +4241,11 @@ public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinatio
42314241
+ destinationHost.getResourceState());
42324242
}
42334243

4244+
// Check that Vm does not have VM Snapshots
4245+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
4246+
throw new InvalidParameterValueException("VM with VM Snapshots cannot be migrated with storage, please remove all VM snapshots");
4247+
}
4248+
42344249
List<VolumeVO> vmVolumes = _volsDao.findUsableVolumesForInstance(vm.getId());
42354250
Map<Long, Long> volToPoolObjectMap = new HashMap<Long, Long>();
42364251
if (!isVMUsingLocalStorage(vm) && destinationHost.getClusterId().equals(srcHost.getClusterId())) {
@@ -4697,8 +4712,8 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId)
46974712

46984713
// If target VM has associated VM snapshots then don't allow restore of VM
46994714
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
4700-
if (vmSnapshots.size() > 0 && vm.getHypervisorType() == HypervisorType.VMware) {
4701-
throw new InvalidParameterValueException("Unable to restore VM, please specify a VM that does not have VM snapshots");
4715+
if (vmSnapshots.size() > 0) {
4716+
throw new InvalidParameterValueException("Unable to restore VM, please remove VM snapshots before restoring VM");
47024717
}
47034718

47044719
VMTemplateVO template = null;

server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ public VMSnapshot allocVMSnapshot(Long vmId, String vsDisplayName, String vsDesc
261261
throw new InvalidParameterValueException("Creating VM snapshot failed due to VM:" + vmId + " is a system VM or does not exist");
262262
}
263263

264+
if (_snapshotDao.listByInstanceId(vmId, Snapshot.State.BackedUp).size() > 0) {
265+
throw new InvalidParameterValueException(
266+
"VM snapshot for this VM is not allowed. This VM has volumes attached which has snapshots, please remove all snapshots before taking VM snapshot");
267+
}
268+
264269
// VM snapshot with memory is not supported for VGPU Vms
265270
if (snapshotMemory && _serviceOfferingDetailsDao.findDetail(userVmVo.getServiceOfferingId(), GPU.Keys.vgpuType.toString()) != null) {
266271
throw new InvalidParameterValueException("VM snapshot with MEMORY is not supported for vGPU enabled VMs.");
@@ -571,6 +576,13 @@ public UserVm revertToSnapshot(Long vmSnapshotId) throws InsufficientCapacityExc
571576
"VM Snapshot reverting failed due to vm is not in the state of Running or Stopped.");
572577
}
573578

579+
if (userVm.getState() == VirtualMachine.State.Running && vmSnapshotVo.getType() == VMSnapshot.Type.Disk || userVm.getState() == VirtualMachine.State.Stopped
580+
&& vmSnapshotVo.getType() == VMSnapshot.Type.DiskAndMemory) {
581+
throw new InvalidParameterValueException(
582+
"VM Snapshot revert not allowed. This will result in VM state change. You can revert running VM to disk and memory type snapshot and stopped VM to disk type"
583+
+ " snapshot");
584+
}
585+
574586
// if snapshot is not created, error out
575587
if (vmSnapshotVo.getState() != VMSnapshot.State.Ready) {
576588
throw new InvalidParameterValueException(

0 commit comments

Comments
 (0)