| # 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 |
| import 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": |
| 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": |
| 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") |
| @attr(tags=["TODO"], 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: |
| if 'kvm' in self.hypervisor.lower(): |
| self.virtual_machine.stop(self.apiclient) |
| 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.assertEqual( |
| 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("Issue CLOUDSTACK-10080: 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 - CLOUDSTACK-10079") |
| 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_05_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 parameter : %s" % e) |
| |
| |
| @attr(tags=["advanced"], required_hardware="true") |
| def test_06_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": |
| 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 and 'vmware' in vm.hypervisor.lower(): |
| 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) |
| if rootvol is not None and 'kvm' or 'xenserver' in vm.hypervisor.lower(): |
| rootvol.resize(self.apiclient, size=newsize) |
| |
| # @attr(tags=["advanced"], required_hrdware="true") |
| @attr(tags=["TODO"], required_hrdware="true") |
| def test_07_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": |
| 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.assertEqual( |
| 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": |
| 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 |