diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java index df5e205dbd6..fe3f2410cbe 100644 --- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java @@ -802,6 +802,16 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic throw new InvalidParameterValueException("No such volume"); } + /* Does the caller have authority to act on this volume? */ + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + + if(volume.getInstanceId() != null) { + // Check that Vm to which this volume is attached does not have VM Snapshots + if (_vmSnapshotDao.findByVm(volume.getInstanceId()).size() > 0) { + throw new InvalidParameterValueException("Volume cannot be resized which is attached to VM with VM Snapshots"); + } + } + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); DiskOfferingVO newDiskOffering = null; @@ -974,6 +984,16 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic hosts = new long[] {userVm.getLastHostId()}; } + StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId()); + + if (storagePool.isManaged() && storagePool.getHypervisor() == HypervisorType.Any && hosts != null && hosts.length > 0) { + HostVO host = _hostDao.findById(hosts[0]); + + if (currentSize != newSize && host.getHypervisorType() == HypervisorType.XenServer && !userVm.getState().equals(State.Stopped)) { + throw new InvalidParameterValueException(errorMsg); + } + } + /* Xen only works offline, SR does not support VDI.resizeOnline */ if (_volsDao.getHypervisorType(volume.getId()) == HypervisorType.XenServer && !userVm.getState().equals(State.Stopped)) { throw new InvalidParameterValueException("VM must be stopped or disk detached in order to resize with the Xen HV"); @@ -1403,11 +1423,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic // Permissions check _accountMgr.checkAccess(caller, null, true, volume); - // Check that the volume is a data volume - if (volume.getVolumeType() != Volume.Type.DATADISK) { - throw new InvalidParameterValueException("Please specify a data volume."); - } - // Check that the volume is currently attached to a VM if (vmId == null) { throw new InvalidParameterValueException("The specified volume is not attached to a VM."); @@ -1570,6 +1585,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic vm = _vmInstanceDao.findById(instanceId); } + // Check that Vm to which this volume is attached does not have VM Snapshots + if (vm != null && _vmSnapshotDao.findByVm(vm.getId()).size() > 0) { + throw new InvalidParameterValueException("Volume cannot be migrated, please remove all VM snapshots for VM to which this volume is attached"); + } + if (vm != null && vm.getState() == State.Running) { // Check if the underlying hypervisor supports storage motion. Long hostId = vm.getHostId(); @@ -1796,6 +1816,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId()); } + if (volume.getInstanceId() != null) { + // Check that Vm to which this volume is attached does not have VM Snapshots + if (_vmSnapshotDao.findByVm(volume.getInstanceId()).size() > 0) { + throw new InvalidParameterValueException("Volume snapshot is not allowed, please detach it from VM with VM Snapshots"); + } + } + if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zone.getName()); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index ca1c5d83253..c5e4286ad49 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -81,6 +81,8 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -263,7 +265,6 @@ import com.cloud.vm.dao.UserVmCloneSettingDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; -import com.cloud.vm.snapshot.VMSnapshot; import com.cloud.vm.snapshot.VMSnapshotManager; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; @@ -821,6 +822,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir "; make sure the virtual machine is stopped"); } + // If target VM has associated VM snapshots then don't allow upgrading of VM + List vmSnapshots = _vmSnapshotDao.findByVm(vmId); + if (vmSnapshots.size() > 0) { + throw new InvalidParameterValueException("Unable to change service offering for VM, please remove VM snapshots before changing service offering of VM"); + } + _accountMgr.checkAccess(caller, null, true, vmInstance); // Check resource limits for CPU and Memory. @@ -850,19 +857,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // Check that the specified service offering ID is valid _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering); - // remove diskAndMemory VM snapshots - List vmSnapshots = _vmSnapshotDao.findByVm(vmId); - for (VMSnapshotVO vmSnapshotVO : vmSnapshots) { - if(vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory){ - if(!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, VMSnapshot.Type.DiskAndMemory)){ - String errMsg = "Failed to remove VM snapshot during upgrading, snapshot id " + vmSnapshotVO.getId(); - s_logger.debug(errMsg); - throw new CloudRuntimeException(errMsg); - } - - } - } - _itMgr.upgradeVmDb(vmId, svcOffId); if (newServiceOffering.isDynamic()) { //save the custom values to the database. @@ -929,19 +923,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // Check that the specified service offering ID is valid _itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering); - // remove diskAndMemory VM snapshots - List vmSnapshots = _vmSnapshotDao.findByVm(vmId); - for (VMSnapshotVO vmSnapshotVO : vmSnapshots) { - if(vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory){ - if(!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, VMSnapshot.Type.DiskAndMemory)){ - String errMsg = "Failed to remove VM snapshot during upgrading, snapshot id " + vmSnapshotVO.getId(); - s_logger.debug(errMsg); - throw new CloudRuntimeException(errMsg); - } - - } - } - _itMgr.upgradeVmDb(vmId, svcOffId); if (newServiceOffering.isDynamic()) { //save the custom values to the database. @@ -979,6 +960,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if(vmInstance == null) { throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); } + + // Check that Vm does not have VM Snapshots + if (_vmSnapshotDao.findByVm(vmId).size() > 0) { + throw new InvalidParameterValueException("NIC cannot be added to VM with VM Snapshots"); + } + NetworkVO network = _networkDao.findById(networkId); if(network == null) { throw new InvalidParameterValueException("unable to find a network with id " + networkId); @@ -1062,6 +1049,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if(vmInstance == null) { throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); } + + // Check that Vm does not have VM Snapshots + if (_vmSnapshotDao.findByVm(vmId).size() > 0) { + throw new InvalidParameterValueException("NIC cannot be removed from VM with VM Snapshots"); + } + NicVO nic = _nicDao.findById(nicId); if (nic == null){ throw new InvalidParameterValueException("unable to find a nic with id " + nicId); @@ -1119,6 +1112,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (vmInstance == null){ throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); } + + // Check that Vm does not have VM Snapshots + if (_vmSnapshotDao.findByVm(vmId).size() > 0) { + throw new InvalidParameterValueException("NIC cannot be updated for VM with VM Snapshots"); + } + NicVO nic = _nicDao.findById(nicId); if (nic == null){ throw new InvalidParameterValueException("unable to find a nic with id " + nicId); @@ -1291,6 +1290,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // Verify input parameters VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId); + if (vmInstance != null) { + // If target VM has associated VM snapshots then don't allow upgrading of VM + List vmSnapshots = _vmSnapshotDao.findByVm(vmId); + if (vmSnapshots.size() > 0) { + throw new InvalidParameterValueException("Unable to scale VM, please remove VM snapshots before scaling VM"); + } + } + if (vmInstance.getState().equals(State.Stopped)) { upgradeStoppedVirtualMachine(vmId, newServiceOfferingId, customParameters); return true; @@ -4043,6 +4050,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir "Data disks attached to the vm, can not migrate. Need to dettach data disks at first"); } + // Check that Vm does not have VM Snapshots + if (_vmSnapshotDao.findByVm(vmId).size() > 0) { + throw new InvalidParameterValueException("VM's disk cannot be migrated, please remove all the VM Snapshots for this VM"); + } + HypervisorType destHypervisorType = destPool.getHypervisor(); if (destHypervisorType == null) { destHypervisorType = _clusterDao.findById( @@ -4486,6 +4498,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir "status: " + destinationHost.getState() + ", state: " + destinationHost.getResourceState()); } + // Check that Vm does not have VM Snapshots + if (_vmSnapshotDao.findByVm(vmId).size() > 0) { + throw new InvalidParameterValueException("VM with VM Snapshots cannot be migrated with storage, please remove all VM snapshots"); + } + List vmVolumes = _volsDao.findUsableVolumesForInstance(vm.getId()); Map volToPoolObjectMap = new HashMap(); if (!isVMUsingLocalStorage(vm) && destinationHost.getClusterId().equals(srcHost.getClusterId())) { @@ -5012,22 +5029,34 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } VolumeVO root = rootVols.get(0); - Long templateId = root.getTemplateId(); - boolean isISO = false; - if(templateId == null) { - // Assuming that for a vm deployed using ISO, template ID is set to NULL - isISO = true; - templateId = vm.getIsoId(); - } + if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null ){ + Long templateId = root.getTemplateId(); + boolean isISO = false; + if (templateId == null) { + // Assuming that for a vm deployed using ISO, template ID is set to NULL + isISO = true; + templateId = vm.getIsoId(); + } - VMTemplateVO template = null; - //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly - if(newTemplateId != null) { - template = _templateDao.findById(newTemplateId); - _accountMgr.checkAccess(caller, null, true, template); - if (isISO) { - if (!template.getFormat().equals(ImageFormat.ISO)) { - throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM "); + // If target VM has associated VM snapshots then don't allow restore of VM + List vmSnapshots = _vmSnapshotDao.findByVm(vmId); + if (vmSnapshots.size() > 0) { + throw new InvalidParameterValueException("Unable to restore VM, please remove VM snapshots before restoring VM"); + } + + VMTemplateVO template = null; + //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly + if (newTemplateId != null) { + template = _templateDao.findById(newTemplateId); + _accountMgr.checkAccess(caller, null, true, template); + if (isISO) { + if (!template.getFormat().equals(ImageFormat.ISO)) { + throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM "); + } + } else { + if (template.getFormat().equals(ImageFormat.ISO)) { + throw new InvalidParameterValueException("Invalid template id provided to restore the VM "); + } } } else { if (template.getFormat().equals(ImageFormat.ISO)) { diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java index 5ae09fde6d6..d57659a6a84 100644 --- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java +++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java @@ -262,6 +262,11 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana throw new InvalidParameterValueException("Creating VM snapshot failed due to VM:" + vmId + " is a system VM or does not exist"); } + if (_snapshotDao.listByInstanceId(vmId, Snapshot.State.BackedUp).size() > 0) { + throw new InvalidParameterValueException( + "VM snapshot for this VM is not allowed. This VM has volumes attached which has snapshots, please remove all snapshots before taking VM snapshot"); + } + // check hypervisor capabilities if(!_hypervisorCapabilitiesDao.isVmSnapshotEnabled(userVmVo.getHypervisorType(), "default")) throw new InvalidParameterValueException("VM snapshot is not enabled for hypervisor type: " + userVmVo.getHypervisorType()); @@ -577,6 +582,13 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana "VM Snapshot reverting failed due to vm is not in the state of Running or Stopped."); } + if (userVm.getState() == VirtualMachine.State.Running && vmSnapshotVo.getType() == VMSnapshot.Type.Disk || userVm.getState() == VirtualMachine.State.Stopped + && vmSnapshotVo.getType() == VMSnapshot.Type.DiskAndMemory) { + throw new InvalidParameterValueException( + "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" + + " snapshot"); + } + // if snapshot is not created, error out if (vmSnapshotVo.getState() != VMSnapshot.State.Ready) { throw new InvalidParameterValueException(