diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorStorageProcessor.java b/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorStorageProcessor.java index 9d86bc31b71..b493f6e2bcd 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorStorageProcessor.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorStorageProcessor.java @@ -86,9 +86,17 @@ public class SimulatorStorageProcessor implements StorageProcessor { @Override public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) { + long size = 100; + DataTO dataTO = cmd.getDestTO(); + if (dataTO instanceof VolumeObjectTO) { + VolumeObjectTO destVolume = (VolumeObjectTO)dataTO; + if (destVolume.getSize() != null) { + size = destVolume.getSize(); + } + } VolumeObjectTO volume = new VolumeObjectTO(); volume.setPath(UUID.randomUUID().toString()); - volume.setSize(100); + volume.setSize(size); volume.setFormat(Storage.ImageFormat.RAW); return new CopyCmdAnswer(volume); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index df50f5a9162..230708cc720 100644 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -311,9 +311,8 @@ import com.cloud.storage.snapshot.SnapshotApiService; public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService, Configurable { private static final Logger s_logger = Logger.getLogger(UserVmManagerImpl.class); - private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3 - - // seconds + private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3 seconds + private static final long GB_TO_BYTES = 1024 * 1024 * 1024; @Inject EntityManager _entityMgr; @@ -3251,6 +3250,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir _templateDao.loadDetails(template); } + HypervisorType hypervisorType = null; + if (template.getHypervisorType() == null || template.getHypervisorType() == HypervisorType.None) { + if (hypervisor == null || hypervisor == HypervisorType.None) { + throw new InvalidParameterValueException("hypervisor parameter is needed to deploy VM or the hypervisor parameter value passed is invalid"); + } + hypervisorType = hypervisor; + } else { + if (hypervisor != null && hypervisor != HypervisorType.None && hypervisor != template.getHypervisorType()) { + throw new InvalidParameterValueException("Hypervisor passed to the deployVm call, is different from the hypervisor type of the template"); + } + hypervisorType = template.getHypervisorType(); + } + long accountId = owner.getId(); assert !(requestedIps != null && (defaultIps.getIp4Address() != null || defaultIps.getIp6Address() != null)) : "requestedIp list and defaultNetworkIp should never be specified together"; @@ -3283,11 +3295,25 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } // check if account/domain is with in resource limits to create a new vm boolean isIso = Storage.ImageFormat.ISO == template.getFormat(); - // For baremetal, size can be null - Long tmp = _templateDao.findById(template.getId()).getSize(); long size = 0; - if (tmp != null) { - size = tmp; + // custom root disk size, resizes base template to larger size + if (customParameters.containsKey("rootdisksize")) { + // only KVM, XenServer and VMware supports rootdisksize override + if (!(hypervisorType == HypervisorType.KVM || hypervisorType == HypervisorType.XenServer || hypervisorType == HypervisorType.VMware || hypervisorType == HypervisorType.Simulator)) { + throw new InvalidParameterValueException("Hypervisor " + hypervisorType + " does not support rootdisksize override"); + } + + Long rootDiskSize = NumbersUtil.parseLong(customParameters.get("rootdisksize"), -1); + if (rootDiskSize <= 0) { + throw new InvalidParameterValueException("Root disk size should be a positive number."); + } + size = rootDiskSize * GB_TO_BYTES; + } else { + // For baremetal, size can be null + Long templateSize = _templateDao.findById(template.getId()).getSize(); + if (templateSize != null) { + size = templateSize; + } } if (diskOfferingId != null) { DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId); @@ -3301,7 +3327,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir throw new InvalidParameterValueException("VM Creation failed. Volume size: " + diskSize + "GB is out of allowed range. Max: " + customDiskOfferingMaxSize + " Min:" + customDiskOfferingMinSize); } - size=size+diskSize*(1024*1024*1024); + size += diskSize * GB_TO_BYTES; } size += _diskOfferingDao.findById(diskOfferingId).getDiskSize(); } @@ -3359,19 +3385,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } - HypervisorType hypervisorType = null; - if (template.getHypervisorType() == null || template.getHypervisorType() == HypervisorType.None) { - if (hypervisor == null || hypervisor == HypervisorType.None) { - throw new InvalidParameterValueException("hypervisor parameter is needed to deploy VM or the hypervisor parameter value passed is invalid"); - } - hypervisorType = hypervisor; - } else { - if (hypervisor != null && hypervisor != HypervisorType.None && hypervisor != template.getHypervisorType()) { - throw new InvalidParameterValueException("Hypervisor passed to the deployVm call, is different from the hypervisor type of the template"); - } - hypervisorType = template.getHypervisorType(); - } - if (hypervisorType != HypervisorType.BareMetal) { // check if we have available pools for vm deployment long availablePools = _storagePoolDao.countPoolsByStatus(StoragePoolStatus.Up); @@ -3635,8 +3648,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return Transaction.execute(new TransactionCallbackWithException() { @Override public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCapacityException { - UserVmVO vm = new UserVmVO(id, instanceName, displayName, template.getId(), hypervisorType, template.getGuestOSId(), offering.getOfferHA(), offering - .getLimitCpuUse(), owner.getDomainId(), owner.getId(), userId, offering.getId(), userData, hostName, diskOfferingId); + UserVmVO vm = new UserVmVO(id, instanceName, displayName, template.getId(), hypervisorType, template.getGuestOSId(), offering.getOfferHA(), + offering.getLimitCpuUse(), owner.getDomainId(), owner.getId(), userId, offering.getId(), userData, hostName, diskOfferingId); vm.setUuid(uuidName); vm.setDynamicallyScalable(template.isDynamicallyScalable()); @@ -3658,16 +3671,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir Long rootDiskSize = null; // custom root disk size, resizes base template to larger size if (customParameters.containsKey("rootdisksize")) { - if (NumbersUtil.parseLong(customParameters.get("rootdisksize"), -1) <= 0) { - throw new InvalidParameterValueException("rootdisk size should be a non zero number."); - } + // already verified for positive number rootDiskSize = Long.parseLong(customParameters.get("rootdisksize")); - // only KVM, XenServer and VMware supports rootdisksize override - if (!(hypervisorType == HypervisorType.KVM || hypervisorType == HypervisorType.XenServer || hypervisorType == HypervisorType.VMware)) { - throw new InvalidParameterValueException("Hypervisor " + hypervisorType + " does not support rootdisksize override"); - } - VMTemplateVO templateVO = _templateDao.findById(template.getId()); if (templateVO == null) { throw new InvalidParameterValueException("Unable to look up template by id " + template.getId()); @@ -3767,20 +3773,22 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir { // rootdisksize must be larger than template. if ((rootDiskSize << 30) < templateVO.getSize()) { - Long templateVOSizeGB = templateVO.getSize() / 1024 / 1024 / 1024; - s_logger.error("unsupported: rootdisksize override is smaller than template size " + templateVO.getSize() + "B (" + templateVOSizeGB + "GB)"); - throw new InvalidParameterValueException("unsupported: rootdisksize override is smaller than template size " + templateVO.getSize() + "B (" + templateVOSizeGB + "GB)"); + Long templateVOSizeGB = templateVO.getSize() / GB_TO_BYTES; + String error = "Unsupported: rootdisksize override is smaller than template size " + templateVO.getSize() + "B (" + templateVOSizeGB + "GB)"; + s_logger.error(error); + throw new InvalidParameterValueException(error); } else if ((rootDiskSize << 30) > templateVO.getSize()) { - if (hypervisorType == HypervisorType.VMware && (vm.getDetails() == null || vm.getDetails().get("rootDiskController") == null)) { + if (hypervisorType == HypervisorType.VMware && (vm.getDetails() == null || vm.getDetails().get("rootDiskController") == null)) { s_logger.warn("If Root disk controller parameter is not overridden, then Root disk resize may fail because current Root disk controller value is NULL."); - } else if (hypervisorType == HypervisorType.VMware && !vm.getDetails().get("rootDiskController").toLowerCase().contains("scsi")) { - s_logger.error("Found unsupported root disk controller : " + vm.getDetails().get("rootDiskController")); - throw new InvalidParameterValueException("Found unsupported root disk controller :" + vm.getDetails().get("rootDiskController")); - } else { - s_logger.debug("Rootdisksize override validation successful. Template root disk size "+(templateVO.getSize() / 1024 / 1024 / 1024)+ " GB" + " Root disk size specified "+ rootDiskSize+" GB"); - } + } else if (hypervisorType == HypervisorType.VMware && !vm.getDetails().get("rootDiskController").toLowerCase().contains("scsi")) { + String error = "Found unsupported root disk controller: " + vm.getDetails().get("rootDiskController"); + s_logger.error(error); + throw new InvalidParameterValueException(error); + } else { + s_logger.debug("Rootdisksize override validation successful. Template root disk size " + (templateVO.getSize() / GB_TO_BYTES) + "GB Root disk size specified " + rootDiskSize + "GB"); + } } else { - s_logger.debug("Root disk size specified is " + (rootDiskSize << 30) + " and Template root disk size is " + templateVO.getSize()+" . Both are equal so no need to override"); + s_logger.debug("Root disk size specified is " + (rootDiskSize << 30) + "B and Template root disk size is " + templateVO.getSize() + "B. Both are equal so no need to override"); customParameters.remove("rootdisksize"); } } diff --git a/test/integration/smoke/test_deploy_vm_root_resize.py b/test/integration/smoke/test_deploy_vm_root_resize.py index e23bbcec6d2..8317b8db422 100644 --- a/test/integration/smoke/test_deploy_vm_root_resize.py +++ b/test/integration/smoke/test_deploy_vm_root_resize.py @@ -22,13 +22,14 @@ from marvin.cloudstackTestCase import cloudstackTestCase #Import Integration Libraries #base - contains all resources as entities and defines create, delete, list operations on them from marvin.lib.base import Account, VirtualMachine, ServiceOffering,\ - Configurations,StoragePool,Template + Configurations, StoragePool, Template #utils - utility classes for common cleanup, external library wrappers etc -from marvin.lib.utils import cleanup_resources,validateList +from marvin.lib.utils import cleanup_resources, validateList from marvin.lib.common import get_zone, get_domain, get_template,\ - list_volumes,list_storage_pools,list_configurations -from marvin.codes import FAILED,INVALID_INPUT -from marvin.cloudstackAPI import * + list_volumes, list_storage_pools, list_configurations,\ + matchResourceCount +from marvin.codes import FAILED, INVALID_INPUT, PASS,\ + RESOURCE_PRIMARY_STORAGE from nose.plugins.attrib import attr from marvin.sshClient import SshClient import time @@ -203,7 +204,7 @@ class TestDeployVmRootSize(cloudstackTestCase): except Exception: return False - @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="true") + @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="false") def test_00_deploy_vm_root_resize(self): """Test deploy virtual machine with root resize @@ -214,30 +215,34 @@ class TestDeployVmRootSize(cloudstackTestCase): """ newrootsize = (self.template.size >> 30) + 2 - if(self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == - 'xenserver'or self.hypervisor.lower() == 'vmware' ): + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): + + accounts = Account.list(self.apiclient, id=self.account.id) + self.assertEqual(validateList(accounts)[0], PASS, + "accounts list validation failed") + initialResourceCount = int(accounts[0].primarystoragetotal) if self.hypervisor=="vmware": self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.services_offering_vmware.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.services_offering_vmware.id, + templateid=self.tempobj.id, + rootdisksize=newrootsize + ) else: self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) self.debug( @@ -246,8 +251,8 @@ class TestDeployVmRootSize(cloudstackTestCase): ) res=validateList(list_vms) - self.assertNotEqual(res[2],INVALID_INPUT," Invalid list VM " - "response") + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " + "response") self.cleanup.append(self.virtual_machine) vm = list_vms[0] @@ -275,8 +280,8 @@ class TestDeployVmRootSize(cloudstackTestCase): listall=True ) res=validateList(list_volume_response) - self.assertNotEqual(res[2],INVALID_INPUT," Invalid list VM " - "response") + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " + "response") rootvolume = list_volume_response[0] success = False if rootvolume is not None and rootvolume.size == (newrootsize << 30): @@ -288,6 +293,11 @@ class TestDeployVmRootSize(cloudstackTestCase): "Check if the root volume resized appropriately" ) + response = matchResourceCount( + self.apiclient, (initialResourceCount + newrootsize), + RESOURCE_PRIMARY_STORAGE, + accountid=self.account.id) + self.assertEqual(response[0], PASS, response[1]) else: self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.hypervisor) newrootsize = (self.template.size >> 30) + 2 @@ -307,22 +317,22 @@ class TestDeployVmRootSize(cloudstackTestCase): if re.search("Hypervisor \S+ does not support rootdisksize override", str(ex)): success = True else: - self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) - @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="true") + @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="false") def test_01_deploy_vm_root_resize(self): """Test proper failure to deploy virtual machine with rootdisksize of 0 """ newrootsize=0 success=False - if(self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == - 'xenserver'or self.hypervisor.lower() == 'vmware' ): + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): try: if self.hypervisor=="vmware": - self.virtual_machine = VirtualMachine.create( + self.virtual_machine = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, accountid=self.account.name, @@ -331,9 +341,49 @@ class TestDeployVmRootSize(cloudstackTestCase): templateid=self.template.id, rootdisksize=newrootsize ) - else: - self.virtual_machine = VirtualMachine.create( + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: + if "Root disk size should be a positive number" in str(ex): + success = True + else: + self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if passing 0 as rootdisksize fails appropriately") + else: + self.debug("test 01 does not support hypervisor type " + self.hypervisor) + + @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="false", BugId="CLOUDSTACK-6984") + def test_02_deploy_vm_root_resize(self): + """Test proper failure to deploy virtual machine with rootdisksize less than template size + """ + newrootsize = (self.template.size >> 30) - 1 + success=False + self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") + + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): + try: + if self.hypervisor=="vmware": + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.services_offering_vmware.id, + templateid=self.tempobj.id, + rootdisksize=newrootsize + ) + else: + self.virtual_machine = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, accountid=self.account.name, @@ -342,57 +392,15 @@ class TestDeployVmRootSize(cloudstackTestCase): templateid=self.template.id, rootdisksize=newrootsize ) - except Exception as ex: - if "rootdisk size should be a non zero number" in str(ex): - success = True - else: - self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); - self.assertEqual(success, True, "Check if passing 0 as rootdisksize fails appropriately") - else: - self.debug("test 01 does not support hypervisor type " + self.hypervisor) - - @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="true", BugId="CLOUDSTACK-6984") - def test_02_deploy_vm_root_resize(self): - """Test proper failure to deploy virtual machine with rootdisksize less than template size - """ - newrootsize = (self.template.size >> 30) - 1 - success=False - self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") - - if(self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == - 'xenserver'or self.hypervisor.lower() == 'vmware' ): - try: - if self.hypervisor=="vmware": - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.services_offering_vmware.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - - else: - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) except Exception as ex: if "rootdisksize override is smaller than template size" in str(ex): success = True else: - self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") else: - self.debug("test 02 does not support hypervisor type " + - self.hypervisor) + self.debug("test 02 does not support hypervisor type " + self.hypervisor) def tearDown(self): try: