Skip to content

Commit f43ffb9

Browse files
anshulgangwarrajesh-battala
authored andcommitted
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 635abaf commit f43ffb9

File tree

3 files changed

+78
-31
lines changed

3 files changed

+78
-31
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);
@@ -1504,7 +1511,6 @@ public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) {
15041511
// Permissions check
15051512
_accountMgr.checkAccess(caller, null, true, volume);
15061513

1507-
15081514
// Check that the volume is currently attached to a VM
15091515
if (vmId == null) {
15101516
throw new InvalidParameterValueException("The specified volume is not attached to a VM.");
@@ -1695,6 +1701,11 @@ public Volume migrateVolume(MigrateVolumeCmd cmd) {
16951701
vm = _vmInstanceDao.findById(instanceId);
16961702
}
16971703

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

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

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

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@
8686
import org.apache.cloudstack.storage.command.DettachCommand;
8787
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
8888
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
89+
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
90+
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
8991

9092
import com.cloud.agent.AgentManager;
9193
import com.cloud.agent.api.Answer;
@@ -273,7 +275,6 @@
273275
import com.cloud.vm.dao.UserVmDao;
274276
import com.cloud.vm.dao.UserVmDetailsDao;
275277
import com.cloud.vm.dao.VMInstanceDao;
276-
import com.cloud.vm.snapshot.VMSnapshot;
277278
import com.cloud.vm.snapshot.VMSnapshotManager;
278279
import com.cloud.vm.snapshot.VMSnapshotVO;
279280
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@@ -817,6 +818,12 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE
817818
+ "; make sure the virtual machine is stopped");
818819
}
819820

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

822829
// Check resource limits for CPU and Memory.
@@ -844,19 +851,6 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE
844851
// Check that the specified service offering ID is valid
845852
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
846853

847-
// remove diskAndMemory VM snapshots
848-
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
849-
for (VMSnapshotVO vmSnapshotVO : vmSnapshots) {
850-
if (vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory) {
851-
if (!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, VMSnapshot.Type.DiskAndMemory)) {
852-
String errMsg = "Failed to remove VM snapshot during upgrading, snapshot id " + vmSnapshotVO.getId();
853-
s_logger.debug(errMsg);
854-
throw new CloudRuntimeException(errMsg);
855-
}
856-
857-
}
858-
}
859-
860854
_itMgr.upgradeVmDb(vmId, svcOffId);
861855
if (newServiceOffering.isDynamic()) {
862856
//save the custom values to the database.
@@ -957,19 +951,6 @@ private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map<String
957951
// Check that the specified service offering ID is valid
958952
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
959953

960-
// remove diskAndMemory VM snapshots
961-
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
962-
for (VMSnapshotVO vmSnapshotVO : vmSnapshots) {
963-
if (vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory) {
964-
if (!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, VMSnapshot.Type.DiskAndMemory)) {
965-
String errMsg = "Failed to remove VM snapshot during upgrading, snapshot id " + vmSnapshotVO.getId();
966-
s_logger.debug(errMsg);
967-
throw new CloudRuntimeException(errMsg);
968-
}
969-
970-
}
971-
}
972-
973954
_itMgr.upgradeVmDb(vmId, svcOffId);
974955
if (newServiceOffering.isDynamic()) {
975956
//save the custom values to the database.
@@ -1007,6 +988,12 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV
1007988
if (vmInstance == null) {
1008989
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
1009990
}
991+
992+
// Check that Vm does not have VM Snapshots
993+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
994+
throw new InvalidParameterValueException("NIC cannot be added to VM with VM Snapshots");
995+
}
996+
1010997
NetworkVO network = _networkDao.findById(networkId);
1011998
if (network == null) {
1012999
throw new InvalidParameterValueException("unable to find a network with id " + networkId);
@@ -1091,6 +1078,12 @@ public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws Invalid
10911078
if (vmInstance == null) {
10921079
throw new InvalidParameterValueException("Unable to find a virtual machine with id " + vmId);
10931080
}
1081+
1082+
// Check that Vm does not have VM Snapshots
1083+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
1084+
throw new InvalidParameterValueException("NIC cannot be removed from VM with VM Snapshots");
1085+
}
1086+
10941087
NicVO nic = _nicDao.findById(nicId);
10951088
if (nic == null) {
10961089
throw new InvalidParameterValueException("Unable to find a nic with id " + nicId);
@@ -1157,6 +1150,12 @@ public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) th
11571150
if (vmInstance == null) {
11581151
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
11591152
}
1153+
1154+
// Check that Vm does not have VM Snapshots
1155+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
1156+
throw new InvalidParameterValueException("NIC cannot be updated for VM with VM Snapshots");
1157+
}
1158+
11601159
NicVO nic = _nicDao.findById(nicId);
11611160
if (nic == null) {
11621161
throw new InvalidParameterValueException("unable to find a nic with id " + nicId);
@@ -1329,6 +1328,14 @@ public boolean upgradeVirtualMachine(Long vmId, Long newServiceOfferingId, Map<S
13291328
// Verify input parameters
13301329
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
13311330

1331+
if (vmInstance != null) {
1332+
// If target VM has associated VM snapshots then don't allow upgrading of VM
1333+
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
1334+
if (vmSnapshots.size() > 0) {
1335+
throw new InvalidParameterValueException("Unable to scale VM, please remove VM snapshots before scaling VM");
1336+
}
1337+
}
1338+
13321339
if (vmInstance.getState().equals(State.Stopped)) {
13331340
upgradeStoppedVirtualMachine(vmId, newServiceOfferingId, customParameters);
13341341
return true;
@@ -3830,6 +3837,11 @@ public VirtualMachine vmStorageMigration(Long vmId, StoragePool destPool) {
38303837
throw new InvalidParameterValueException("Data disks attached to the vm, can not migrate. Need to dettach data disks at first");
38313838
}
38323839

3840+
// Check that Vm does not have VM Snapshots
3841+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
3842+
throw new InvalidParameterValueException("VM's disk cannot be migrated, please remove all the VM Snapshots for this VM");
3843+
}
3844+
38333845
HypervisorType destHypervisorType = destPool.getHypervisor();
38343846
if (destHypervisorType == null) {
38353847
destHypervisorType = _clusterDao.findById(
@@ -4248,6 +4260,11 @@ public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinatio
42484260
+ destinationHost.getResourceState());
42494261
}
42504262

4263+
// Check that Vm does not have VM Snapshots
4264+
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
4265+
throw new InvalidParameterValueException("VM with VM Snapshots cannot be migrated with storage, please remove all VM snapshots");
4266+
}
4267+
42514268
List<VolumeVO> vmVolumes = _volsDao.findUsableVolumesForInstance(vm.getId());
42524269
Map<Long, Long> volToPoolObjectMap = new HashMap<Long, Long>();
42534270
if (!isVMUsingLocalStorage(vm) && destinationHost.getClusterId().equals(srcHost.getClusterId())) {
@@ -4714,8 +4731,8 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId)
47144731

47154732
// If target VM has associated VM snapshots then don't allow restore of VM
47164733
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
4717-
if (vmSnapshots.size() > 0 && vm.getHypervisorType() == HypervisorType.VMware) {
4718-
throw new InvalidParameterValueException("Unable to restore VM, please specify a VM that does not have VM snapshots");
4734+
if (vmSnapshots.size() > 0) {
4735+
throw new InvalidParameterValueException("Unable to restore VM, please remove VM snapshots before restoring VM");
47194736
}
47204737

47214738
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
@@ -258,6 +258,11 @@ public VMSnapshot allocVMSnapshot(Long vmId, String vsDisplayName, String vsDesc
258258
throw new InvalidParameterValueException("Creating VM snapshot failed due to VM:" + vmId + " is a system VM or does not exist");
259259
}
260260

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

576+
if (userVm.getState() == VirtualMachine.State.Running && vmSnapshotVo.getType() == VMSnapshot.Type.Disk || userVm.getState() == VirtualMachine.State.Stopped
577+
&& vmSnapshotVo.getType() == VMSnapshot.Type.DiskAndMemory) {
578+
throw new InvalidParameterValueException(
579+
"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"
580+
+ " snapshot");
581+
}
582+
571583
// if snapshot is not created, error out
572584
if (vmSnapshotVo.getState() != VMSnapshot.State.Ready) {
573585
throw new InvalidParameterValueException(

0 commit comments

Comments
 (0)