| # 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" | |
| " vm_instance_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 Instance Snapshot on Instance | |
| """ | |
| # 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 |