diff --git a/test/integration/component/test_rootvolume_resize.py b/test/integration/component/test_rootvolume_resize.py new file mode 100644 index 00000000000..59488e691f5 --- /dev/null +++ b/test/integration/component/test_rootvolume_resize.py @@ -0,0 +1,1139 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for testing resize of root volume functionality + + Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/ + Root+Resize+Support + + Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-9829 +""" +# Import Local Modules +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.lib.base import (Account, + ServiceOffering, + VirtualMachine, + Resources, + Domain, + Volume, + Snapshot, + Template, + VmSnapshot, + Host, + Configurations, + StoragePool) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + matchResourceCount, + list_snapshots, + list_hosts, + list_configurations, + list_storage_pools) +from marvin.lib.utils import (cleanup_resources, + validateList) +from marvin.codes import (PASS, + FAIL, + FAILED, + RESOURCE_PRIMARY_STORAGE, + INVALID_INPUT) +from marvin.lib.utils import checkVolumeSize +import time +from marvin.sshClient import SshClient + + +class TestResizeVolume(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls.testClient = super(TestResizeVolume, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.hypervisor = (cls.testClient.getHypervisorInfo()).lower() + cls.storageID = None + # Fill services from the external config file + cls.services = cls.testClient.getParsedTestDataConfig() + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone( + cls.api_client, + cls.testClient.getZoneForTests()) + cls.services["mode"] = cls.zone.networktype + cls._cleanup = [] + cls.unsupportedStorageType = False + cls.unsupportedHypervisorType = False + cls.updateclone = False + if cls.hypervisor not in ['xenserver',"kvm","vmware"]: + cls.unsupportedHypervisorType=True + return + cls.template = get_template( + cls.api_client, + cls.zone.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls.services["volume"]["zoneid"] = cls.zone.id + try: + cls.parent_domain = Domain.create(cls.api_client, + services=cls.services[ + "domain"], + parentdomainid=cls.domain.id) + cls.parentd_admin = Account.create(cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.parent_domain.id) + cls._cleanup.append(cls.parentd_admin) + cls._cleanup.append(cls.parent_domain) + list_pool_resp = list_storage_pools(cls.api_client, + account=cls.parentd_admin.name,domainid=cls.parent_domain.id) + res = validateList(list_pool_resp) + if res[2]== INVALID_INPUT: + raise Exception("Failed to list storage pool-no storagepools found ") + #Identify the storage pool type and set vmware fullclone to true if storage is VMFS + if cls.hypervisor == 'vmware': + for strpool in list_pool_resp: + if strpool.type.lower() == "vmfs" or strpool.type.lower()== "networkfilesystem": + list_config_storage_response = list_configurations( + cls.api_client + , name= + "vmware.create.full.clone",storageid=strpool.id) + res = validateList(list_config_storage_response) + if res[2]== INVALID_INPUT: + raise Exception("Failed to list configurations ") + if list_config_storage_response[0].value == "false": + Configurations.update(cls.api_client, + "vmware.create.full.clone", + value="true",storageid=strpool.id) + cls.updateclone = True + StoragePool.update(cls.api_client,id=strpool.id,tags="scsi") + cls.storageID = strpool.id + cls.unsupportedStorageType = False + break + else: + cls.unsupportedStorageType = True + # Creating service offering with normal config + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"]) + cls.services_offering_vmware=ServiceOffering.create( + cls.api_client,cls.services["service_offering"],tags="scsi") + cls._cleanup.extend([cls.service_offering,cls.services_offering_vmware]) + + except Exception as e: + cls.tearDownClass() + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + + if cls.updateclone: + Configurations.update(cls.api_client, + "vmware.create.full.clone", + value="false",storageid=cls.storageID) + + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + if self.unsupportedStorageType: + self.skipTest("Tests are Skipped - unsupported Storage type used ") + elif self.unsupportedHypervisorType: + self.skipTest("Tests are Skipped - unsupported Hypervisor type used") + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + # Clean up, terminate the created instance, volumes and snapshots + + cleanup_resources(self.apiclient, self.cleanup) + pass + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def updateResourceLimits(self, accountLimit=None, domainLimit=None): + """Update primary storage limits of the parent domain and its + child domains""" + try: + if domainLimit: + # Update resource limit for domain + Resources.updateLimit(self.apiclient, resourcetype=10, + max=domainLimit, + domainid=self.parent_domain.id) + if accountLimit: + # Update resource limit for domain + Resources.updateLimit(self.apiclient, + resourcetype=10, + max=accountLimit, + account=self.parentd_admin.name, + domainid=self.parent_domain.id) + except Exception as e: + return [FAIL, e] + return [PASS, None] + + + def setupAccounts(self): + try: + self.parent_domain = Domain.create(self.apiclient, + services=self.services[ + "domain"], + parentdomainid=self.domain.id) + self.parentd_admin = Account.create(self.apiclient, + self.services["account"], + admin=True, + domainid=self.parent_domain.id) + # Cleanup the resources created at end of test + self.cleanup.append(self.parent_domain) + self.cleanup.append(self.parentd_admin) + + + except Exception as e: + return [FAIL, e] + return [PASS, None] + + def chk_volume_resize(self, apiclient, vm): + + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + # get root vol from created vm, verify its size + list_volume_response = Volume.list( + apiclient, + virtualmachineid=vm.id, + type='ROOT', + listall='True' + ) + rootvolume = list_volume_response[0] + if vm.state == "Running" and \ + (vm.hypervisor.lower() == "xenserver" or \ + vm.hypervisor.lower() == "vmware"): + self.virtual_machine.stop(apiclient) + time.sleep(self.services["sleep"]) + if vm.hypervisor.lower() == "vmware": + rootdiskcontroller = self.getDiskController(vm) + if rootdiskcontroller!="scsi": + raise Exception("root volume resize only supported on scsi disk ," + "please check rootdiskcontroller type") + + rootvolobj = Volume(rootvolume.__dict__) + newsize = (rootvolume.size >> 30) + 2 + success = False + if rootvolume is not None: + try: + rootvolobj.resize(apiclient, size=newsize) + if vm.hypervisor.lower() == "xenserver" or \ + vm.hypervisor.lower() == "vmware": + self.virtual_machine.start(apiclient) + time.sleep(self.services["sleep"]) + ssh = SshClient(self.virtual_machine.ssh_ip, 22, + "root", "password") + newsizeinbytes = newsize * 1024 * 1024 * 1024 + + if vm.hypervisor.lower() == "xenserver": + volume_name = "/dev/xvd" + \ + chr(ord('a') + + int( + list_volume_response[0].deviceid)) + self.debug(" Using XenServer" + " volume_name: %s" % volume_name) + ret = checkVolumeSize(ssh_handle=ssh, + volume_name=volume_name, + size_to_verify=newsizeinbytes) + success = True + elif vm.hypervisor.lower() == "kvm": + volume_name = "/dev/vd" + chr(ord('a') + int + (list_volume_response[0] + .deviceid)) + self.debug(" Using KVM volume_name:" + " %s" % volume_name) + ret = checkVolumeSize(ssh_handle=ssh, + volume_name=volume_name, + size_to_verify=newsizeinbytes) + success = True + elif vm.hypervisor.lower() == "vmware": + ret = checkVolumeSize(ssh_handle=ssh, + volume_name="/dev/sdb", + size_to_verify=newsizeinbytes) + success = True + self.debug(" Volume Size Expected %s " + " Actual :%s" % (newsizeinbytes, ret[1])) + except Exception as e: + # need to write the rootdisk controller code. + if vm.hypervisor == "vmware" and rootdiskcontroller == "ide": + assert "Found unsupported root disk " \ + "controller :ide" in e.message, \ + "able to resize ide root volume Testcase failed" + else: + raise Exception("fail to resize the volume: %s" % e) + else: + self.debug("hypervisor %s unsupported for test " + ", verifying it errors properly" % self.hypervisor) + success = False + return success + + def getDiskController(self, vm, diskcontroller="ide"): + + if vm.hypervisor.lower() == "vmware": + try: + qresultvmuuid = self.dbclient.execute( + "select id from vm_instance where uuid = '%s' ;" % + vm.id + ) + self.assertNotEqual( + len(qresultvmuuid), + 0, + "Check DB Query result set" + ) + vmid = int(qresultvmuuid[0][0]) + qresult = self.dbclient.execute( + "select rootDiskController from" + " user_vm_details where id = '%s';" % vmid + ) + self.debug("Query result: %s" % qresult) + diskcontroller = qresult[0][0] + except Exception as e: + raise Exception("Warning: Exception while" + " checking usage event for the " + "root_volume_resize : %s" % e) + return diskcontroller + + @attr(tags=["advanced"], required_hardware="true") + def test_01_create__snapshot_new_resized_rootvolume_size(self): + """Test create snapshot on resized root volume + + # Validate the following + + # 1. Deploy a VM without any disk offering (only root disk) + # 2. Perform(resize) of the root volume + # 3. Perform snapshot on resized volume + """ + + # deploy a vm + + try: + if self.updateclone: + + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.services_offering_vmware.id, + mode=self.zone.networktype + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id, + mode=self.zone.networktype + ) + + # listVirtual machine + list_vms = VirtualMachine.list(self.apiclient, + id=self.virtual_machine.id) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" % + self.virtual_machine.id + ) + res = validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list response") + + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + self.assertEqual( + vm.name, + self.virtual_machine.name, + "Virtual Machine names do not match" + ) + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + result = self.chk_volume_resize(self.apiclient, vm) + if result: + # get root vol from created vm, verify it is correct size + list_volume_response = Volume.list( + self.apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + res = validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listVolumes returned invalid object in response") + rootvolume = list_volume_response[0] + self.debug("Creating a Snapshot from root volume: " + "%s" % rootvolume.id) + snapshot = Snapshot.create( + self.apiclient, + rootvolume.id, + account=self.parentd_admin.name, + domainid=self.parent_domain.id + ) + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id + ) + res = validateList(snapshots) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list response") + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check resource id in list resources call" + ) + else: + self.debug("Volume resize is failed") + + except Exception as e: + raise Exception("Exception while performing" + " the snapshot on resized root volume" + " test case: %s" % e) + + self.cleanup.append(self.virtual_machine) + self.cleanup.append(snapshot) + + return + + @attr(tags=["advanced"], required_hardware="true") + def test_02_create__template_new_resized_rootvolume_size(self): + """Test create Template resized root volume + + # Validate the following + + # 1. Deploy a VM without any disk offering (only root disk) + # 2. Perform(resize) of the root volume + # 3. Stop the vm + # 4. Create a template from resized root volume + """ + + result = self.setupAccounts() + self.assertEqual(result[0], PASS, result[1]) + apiclient = self.testClient.getUserApiClient( + UserName=self.parentd_admin.name, + DomainName=self.parentd_admin.domain) + self.assertNotEqual(apiclient, FAILED, "Failed to get api client\ + of account: %s" % self.parentd_admin.name) + + # deploy a vm + try: + if self.updateclone: + + self.virtual_machine = VirtualMachine.create( + apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.services_offering_vmware.id, + mode=self.zone.networktype + ) + else: + self.virtual_machine = VirtualMachine.create( + apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id, + mode=self.zone.networktype + ) + + # listVirtual macine + list_vms = VirtualMachine.list(apiclient, + id=self.virtual_machine.id) + self.debug("Verify listVirtualMachines response" + " for virtual machine: %s" % self.virtual_machine.id + ) + res = validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list response") + self.cleanup.append(self.virtual_machine) + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + self.assertEqual( + vm.name, + self.virtual_machine.name, + "Virtual Machine names do not match" + ) + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + # get root vol from created vm, verify it is correct size + list_volume_response = Volume.list( + apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + res = validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listVolumes returned invalid object in response") + rootvolume = list_volume_response[0] + newsize = (rootvolume.size >> 30) + 2 + result = self.chk_volume_resize(apiclient, vm) + if result: + try: + # create a template from stopped VM instances root volume + if vm.state == "Running": + self.virtual_machine.stop(apiclient) + template_from_root = Template.create( + apiclient, + self.services["template"], + volumeid=rootvolume.id, + account=self.parentd_admin.name, + domainid=self.parent_domain.id) + list_template_response = Template.list( + apiclient, + id=template_from_root.id, + templatefilter="all") + res = validateList(list_template_response) + self.assertNotEqual(res[2], INVALID_INPUT, "Check if template exists in ListTemplates") + # Deploy new virtual machine using template + self.virtual_machine2 = VirtualMachine.create( + apiclient, + self.services["virtual_machine"], + templateid=template_from_root.id, + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id, + ) + + vm_response = VirtualMachine.list( + apiclient, + id=self.virtual_machine2.id, + account=self.parentd_admin.name, + domainid=self.parent_domain.id + ) + res = validateList(vm_response) + self.assertNotEqual(res[2], INVALID_INPUT, "Check for list VM response return valid list") + self.cleanup.append(self.virtual_machine2) + self.cleanup.reverse() + vm2 = vm_response[0] + self.assertEqual( + vm2.state, + 'Running', + "Check the state of VM created from Template" + ) + list_volume_response = Volume.list( + apiclient, + virtualmachineid=vm2.id, + type='ROOT', + listall='True' + ) + self.assertEqual( + list_volume_response[0].size, + (newsize * 1024 * 1024 * 1024), + + "Check for root volume size not matched with template size" + ) + except Exception as e: + raise Exception("Exception while resizing the " + "root volume: %s" % e) + + else: + self.debug(" volume resize failed for root volume") + except Exception as e: + raise Exception("Exception while performing" + " template creation from " + "resized_root_volume : %s" % e) + + return + + @attr(tags=["advanced"], required_hardware="true") + def test_03_vmsnapshot__on_resized_rootvolume_vm(self): + """Test vmsnapshot on resized root volume + + # Validate the following + + # 1. Deploy a VM without any disk offering (only root disk) + # 2. Perform(resize) of the root volume + # 3. Perform VM snapshot on VM + """ + + # deploy a vm + + try: + if self.updateclone: + + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.services_offering_vmware.id, + mode=self.zone.networktype + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id, + mode=self.zone.networktype + ) + + # listVirtual macine + list_vms = VirtualMachine.list(self.apiclient, + id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + res = validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list response") + self.cleanup.append(self.virtual_machine) + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + # get root vol from created vm, verify it is correct size + list_volume_response = Volume.list( + self.apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + res = validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listVolumes returned invalid object in response") + rootvolume = list_volume_response[0] + newsize = (rootvolume.size >> 30) + 2 + result = self.chk_volume_resize(self.apiclient, vm) + if result: + try: + virtualmachine_snapshot = VmSnapshot.create \ + (self.apiclient, self.virtual_machine.id) + virtulmachine_snapshot_list = VmSnapshot. \ + list(self.apiclient, + vmsnapshotid=virtualmachine_snapshot.id) + status = validateList(virtulmachine_snapshot_list) + self.assertEquals( + PASS, + status[0], + "Listing of configuration failed") + self.assertEqual(virtualmachine_snapshot.id, + virtulmachine_snapshot_list[0].id, + "Virtual Machine Snapshot id do not match") + except Exception as e: + raise Exception("Exception while performing" + " vmsnapshot: %s" % e) + else: + self.debug("volume resize failed for root volume") + except Exception as e: + raise Exception("Exception while performing" + " vmsnapshot on resized volume Test: %s" % e) + + + @attr(tags=["advanced"], required_hardware="true") + def test_04_vmreset_after_migrate_vm__rootvolume_resized(self): + """Test migrate vm after root volume resize + + # Validate the following + + # 1. Deploy a VM without any disk offering (only root disk) + # 2. Perform(resize) of the root volume + # 3. migrate vm from host to another + # 4. perform vm reset after vm migration + + """ + + try: + if self.updateclone: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.services_offering_vmware.id, + mode=self.zone.networktype + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id, + mode=self.zone.networktype + ) + + # listVirtual macine + list_vms = VirtualMachine.list(self.apiclient, + id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + res = validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list response") + self.cleanup.append(self.virtual_machine) + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + # get root vol from created vm, verify it is correct size + list_volume_response = Volume.list( + self.apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + res = validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listVolumes returned invalid object in response") + rootvolume = list_volume_response[0] + result = self.chk_volume_resize(self.apiclient, vm) + if result: + try: + list_host_response = list_hosts( + self.apiclient, + id=self.virtual_machine.hostid + ) + res = validateList(list_host_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listHosts returned invalid object in response") + + sourcehost = list_host_response[0] + try: + self.list_hosts_suitable = Host.listForMigration \ + (self.apiclient, + virtualmachineid=self.virtual_machine.id + ) + except Exception as e: + self.debug("Not found suitable host") + raise Exception("Exception while getting hosts" + " list suitable for migration: %s" % e) + self.virtualmachine_migrate_response = \ + self.virtual_machine.migrate( + self.apiclient, + self.list_hosts_suitable[0].id) + list_vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id, + hostid=self.list_hosts_suitable[0].id) + + res = validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "listVirtualMachines returned " + "invalid object in response") + + self.virtual_machine_reset = self.virtual_machine.restore \ + (self.apiclient, + self.services["virtual_machine"]["template"]) + list_restorevolume_response = Volume.list( + self.apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + restorerootvolume = list_restorevolume_response[0] + self.assertEqual(rootvolume.size, restorerootvolume.size, + "root volume and restore root" + " volume size differs") + except Exception as e: + raise Exception("Warning: Exception " + "during VM migration: %s" % e) + + except Exception as e: + raise Exception("Warning: Exception during executing" + " the test-migrate_vm_after_rootvolume_resize: %s" % e) + + return + + @attr(tags=["advanced"], required_hardware="true") + def test_5_vmdeployment_with_size(self): + """Test vm deployment with new rootdisk size parameter + + # Validate the following + # 1. Deploy a VM without any disk offering (only root disk) + # 2. Verify the root disksize after deployment + + """ + templateSize = (self.template.size / (1024 ** 3)) + newsize = templateSize + 2 + # deploy a vm + try: + if self.updateclone: + + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.services_offering_vmware.id, + mode=self.zone.networktype + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id, + mode=self.zone.networktype + ) + + # listVirtual macine + list_vms = VirtualMachine.list(self.apiclient, + id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" + % self.virtual_machine.id + ) + res = validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list response") + self.cleanup.append(self.virtual_machine) + vm = list_vms[0] + ssh = SshClient(self.virtual_machine.ssh_ip, 22, "root", + "password") + newsize = newsize * 1024 * 1024 * 1024 + list_volume_response = Volume.list( + self.apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + res = validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listVolumes returned invalid object in response") + if vm.hypervisor.lower() == "xenserver": + volume_name = "/dev/xvd" + chr(ord('a') + int( + list_volume_response[0].deviceid)) + self.debug(" Using XenServer" + " volume_name: %s" % volume_name) + ret = checkVolumeSize(ssh_handle=ssh, + volume_name=volume_name, + size_to_verify=newsize) + elif vm.hypervisor.lower() == "kvm": + volume_name = "/dev/vd" + chr(ord('a') + + int( + list_volume_response[0].deviceid)) + self.debug(" Using KVM volume_name: %s" % volume_name) + ret = checkVolumeSize(ssh_handle=ssh, + volume_name=volume_name, + size_to_verify=newsize) + elif vm.hypervisor.lower() == "vmware": + ret = checkVolumeSize(ssh_handle=ssh, + volume_name="/dev/sdb", + size_to_verify=newsize) + self.debug(" Volume Size Expected %s" + " Actual :%s" % (newsize, ret[1])) + except Exception as e: + raise Exception("Warning: Exception during" + " VM deployment with new" + " rootdisk paramter : %s" % e) + + + @attr(tags=["advanced"], required_hardware="true") + def test_6_resized_rootvolume_with_lessvalue(self): + """Test resize root volume with less than original volume size + + # Validate the following + + # 1. Deploy a VM without any disk offering (only root disk) + # 2. Perform(resize) of the root volume with less + than current root volume + # 3. Check for proper error message + + """ + + # deploy a vm + try: + if self.updateclone: + + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.services_offering_vmware.id, + mode=self.zone.networktype + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id, + mode=self.zone.networktype + ) + + # listVirtual macine + time.sleep(self.services["sleep"]) + list_vms = VirtualMachine.list(self.apiclient, + id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + res = validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list response") + self.cleanup.append(self.virtual_machine) + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + # get root vol from created vm, verify it is correct size + list_volume_response = Volume.list( + self.apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + res = validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listVolumes returned invalid object in response") + if vm.state == "Running" and ( + vm.hypervisor.lower() == "xenserver" or + vm.hypervisor.lower() == "vmware"): + self.virtual_machine.stop(self.apiclient) + time.sleep(self.services["sleep"]) + + rootvolume = list_volume_response[0] + # converting json response to Volume Object + rootvol = Volume(rootvolume.__dict__) + newsize = (rootvolume.size >> 30) - 1 + success = False + if rootvolume is not None: + try: + rootvol.resize(self.apiclient, size=newsize) + except Exception as e: + assert "Shrink operation on ROOT volume not supported" \ + in e.message, \ + "TestCase Failed,able to resize root volume or error message is not matched" + except Exception as e: + raise Exception("Warning: Exception " + "during executing test resize" + " volume with less value : %s" % e) + + @attr(tags=["advanced"], required_hrdware="true") + def test_7_usage_events_after_rootvolume_resized_(self): + """Test check usage events after root volume resize + + # Validate the following + + # 1. Deploy a VM without any disk offering (only root disk) + # 2. Perform(resize) of the root volume + # 3. Check the corresponding usage events + """ + + # deploy a vm + try: + if self.updateclone: + + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.services_offering_vmware.id, + mode=self.zone.networktype + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id, + mode=self.zone.networktype + ) + # listVirtual macine + time.sleep(self.services["sleep"]) + list_vms = VirtualMachine.list(self.apiclient, + id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" + % self.virtual_machine.id + ) + res = validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list response") + self.cleanup.append(self.virtual_machine) + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + # get root vol from created vm, verify it is correct size + list_volume_response = Volume.list( + self.apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + res = validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listVolumes returned invalid object in response") + if vm.state == "Running" and ( + vm.hypervisor.lower() == "xenserver" or + vm.hypervisor.lower() == "vmware"): + self.virtual_machine.stop(self.apiclient) + time.sleep(self.services["sleep"]) + rootvolume = list_volume_response[0] + # converting json response to Volume Object + rootvol = Volume(rootvolume.__dict__) + newsize = (rootvolume.size >> 30) + 2 + success = False + if rootvolume is not None: + try: + rootvol.resize(self.apiclient, size=newsize) + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" + % self.parentd_admin.id) + + res = validateList(qresultset) + self.assertNotEqual(res[2], INVALID_INPUT, "Check DB Query result set") + qresult = qresultset[0] + account_id = qresult[0] + self.debug("select type,size from usage_event" + " where account_id = '%s';" + % account_id) + qresultsize = self.dbclient.execute( + "select size from usage_event where account_id = '%s' " + "and type='VOLUME.RESIZE' ORDER BY ID DESC LIMIT 1;" + % account_id + ) + res = validateList(qresultsize) + self.assertNotEqual(res[2], INVALID_INPUT, "Check DB Query result set") + qresult = int(qresultsize[0][0]) + self.debug("Query result: %s" % qresult) + self.assertEquals( + qresult, + (newsize * 1024 * 1024 * 1024), + "Usage event not logged properly with right volume" + " size please check ") + except Exception as e: + raise Exception("Warning: Exception while checking usage " + "event for the root volume resize : %s" + % e) + except Exception as e: + raise Exception("Warning: Exception performing " + "usage_events_after_rootvolume_resized Test : %s" + % e) + + @attr(tags=["advanced"], required_hardware="true") + def test_08_increase_volume_size_within_account_limit(self): + """Test increasing volume size within the account limit and verify + primary storage usage + + # Validate the following + # 1. Create a domain and its admin account + # 2. Set account primary storage limit well beyond (20 GB volume + + # template size of VM) + # 3. Deploy a VM without any disk offering (only root disk) + # + # 4. Increase (resize) the volume to 20 GB + # 6. Resize operation should be successful and primary storage count + # for account should be updated successfully""" + + # Setting up account and domain hierarchy + + result = self.setupAccounts() + self.assertEqual(result[0], PASS, result[1]) + apiclient = self.testClient.getUserApiClient( + UserName=self.parentd_admin.name, + DomainName=self.parentd_admin.domain) + self.assertNotEqual(apiclient, FAILED, "Failed to get api client\ + of account: %s" % self.parentd_admin.name) + + templateSize = (self.template.size / (1024 ** 3)) + accountLimit = (templateSize + 20) + response = self.updateResourceLimits(accountLimit=accountLimit) + self.assertEqual(response[0], PASS, response[1]) + + try: + + if self.updateclone: + + self.virtual_machine = VirtualMachine.create( + apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.services_offering_vmware.id + ) + else: + self.virtual_machine = VirtualMachine.create( + apiclient, self.services["virtual_machine"], + accountid=self.parentd_admin.name, + domainid=self.parent_domain.id, + serviceofferingid=self.service_offering.id + ) + list_vms = VirtualMachine.list(apiclient, + id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + self.assertEqual( + isinstance(list_vms, list), + True, + "List VM response was not a valid list" + ) + self.cleanup.append(self.virtual_machine) + self.cleanup.reverse() + vm = list_vms[0] + list_volume_response = Volume.list( + apiclient, + virtualmachineid= + self.virtual_machine.id, + type='ROOT', + listall='True' + ) + res = validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "listVolumes returned invalid object in response") + if vm.state == "Running" and \ + (vm.hypervisor.lower() == "xenserver" or + vm.hypervisor.lower() == "vmware"): + self.virtual_machine.stop(self.apiclient) + time.sleep(self.services["sleep"]) + rootvolume = list_volume_response[0] + # converting json response to Volume Object + rootvol = Volume(rootvolume.__dict__) + newsize = (rootvolume.size >> 30) + 20 + if rootvolume is not None: + try: + rootvol.resize(apiclient, size=newsize) + response = matchResourceCount( + self.apiclient, newsize, + RESOURCE_PRIMARY_STORAGE, + accountid=self.parentd_admin.id) + if response[0] == FAIL: + raise Exception(response[1]) + except Exception as e: + self.fail("Failed with exception: %s" % e) + + except Exception as e: + raise Exception("Warning: Exception while checking primary" + " storage capacity after root " + "volume resize : %s" % e) + + return \ No newline at end of file diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index c0cc28a57a8..61188e4560c 100755 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -3858,7 +3858,7 @@ class Configurations: """Manage Configuration""" @classmethod - def update(cls, apiclient, name, value=None, zoneid=None): + def update(cls, apiclient, name, value=None, zoneid=None, clusterid=None, storageid=None): """Updates the specified configuration""" cmd = updateConfiguration.updateConfigurationCmd() @@ -3867,8 +3867,13 @@ class Configurations: if zoneid: cmd.zoneid = zoneid + if clusterid: + cmd.clusterid = clusterid + if storageid: + cmd.storageid=storageid apiclient.updateConfiguration(cmd) + @classmethod def list(cls, apiclient, **kwargs): """Lists configurations"""