shwetaag commented on a change in pull request #2107: CLOUDSTACK-8996: Reducing 
Virtual Machine Deployments
URL: https://github.com/apache/cloudstack/pull/2107#discussion_r117218018
 
 

 ##########
 File path: test/integration/testpaths/testpath_reduce_vm_deployments.py
 ##########
 @@ -0,0 +1,2073 @@
+# 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.
+""" BVT tests for Virtual Machine Life Cycle
+"""
+# Import Local Modules
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.cloudstackAPI import (destroyVirtualMachine,
+                                  attachIso,
+                                  detachIso,
+                                  updateServiceOffering,
+                                  scaleVirtualMachine,
+                                  rebootVirtualMachine,
+                                  changeServiceForVirtualMachine)
+from marvin.lib.utils import (cleanup_resources,
+                              validateList,
+                              random_gen,
+                              is_snapshot_on_nfs,
+                              isAlmostEqual)
+from marvin.lib.base import (Account,
+                             DiskOffering,
+                             AffinityGroup,
+                             Snapshot,
+                             Volume,
+                             ServiceOffering,
+                             VirtualMachine,
+                             Host,
+                             Iso,
+                             Router,
+                             Configurations)
+from marvin.lib.common import (get_domain,
+                               list_volumes,
+                               list_hosts,
+                               list_service_offering,
+                               list_virtual_machines,
+                               list_snapshots,
+                               get_zone,
+                               get_template)
+from marvin.codes import FAILED, PASS
+from marvin.sshClient import SshClient
+from nose.plugins.attrib import attr
+
+# Import System modules
+import time
+import re
+import random
+import string
+
+_multiprocess_shared_ = True
+
+
+class TestDeployVMandVMLifeCycle(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestDeployVMandVMLifeCycle, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = testClient.getParsedTestDataConfig()
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        # Get Zone, Domain and templates
+        domain = get_domain(cls.apiclient)
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.services['mode'] = cls.zone.networktype
+        cls.domain = get_domain(cls.apiclient)
+
+        # if local storage is enabled, alter the offerings to use localstorage
+        # this step is needed for devcloud
+        if cls.zone.localstorageenabled:
+            cls.services["service_offerings"]["tiny"]["storagetype"] = 'local'
+            cls.services["service_offerings"]["small"]["storagetype"] = 'local'
+            cls.services["service_offerings"][
+                "medium"]["storagetype"] = 'local'
+
+        cls.template = get_template(
+            cls.apiclient,
+            cls.zone.id,
+            cls.services["ostype"]
+        )
+        if cls.template == FAILED:
+            assert False, \
+                "get_template() failed to return template with description" \
+                " %s" % cls.services["ostype"]
+
+        # Set Zones and disk offerings
+        cls.services["small"]["zoneid"] = cls.zone.id
+        cls.services["small"]["template"] = cls.template.id
+
+        cls.services["iso1"]["zoneid"] = cls.zone.id
+
+        cls._cleanup = []
+
+        # Create VMs, NAT Rules etc
+        cls.account = Account.create(
+            cls.apiclient,
+            cls.services["account"],
+            domainid=domain.id
+        )
+
+        cls.small_offering = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["service_offerings"]["small"]
+        )
+
+        cls.medium_offering = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["service_offerings"]["medium"]
+        )
+
+        cls.big_offering = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["service_offerings"]["big"]
+        )
+
+        cls.service_offering_1 = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["service_offerings"]["tiny"]
+        )
+
+        cls.service_offering_2 = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["service_offerings"]["tiny"]
+        )
+
+        # create small and large virtual machines
+        cls.small_virtual_machine = VirtualMachine.create(
+            cls.apiclient,
+            cls.services["small"],
+            accountid=cls.account.name,
+            domainid=cls.account.domainid,
+            serviceofferingid=cls.small_offering.id,
+            mode=cls.services["mode"]
+        )
+        cls.medium_virtual_machine = VirtualMachine.create(
+            cls.apiclient,
+            cls.services["small"],
+            accountid=cls.account.name,
+            domainid=cls.account.domainid,
+            serviceofferingid=cls.medium_offering.id,
+            mode=cls.services["mode"]
+        )
+        cls.virtual_machine = VirtualMachine.create(
+            cls.apiclient,
+            cls.services["small"],
+            accountid=cls.account.name,
+            domainid=cls.account.domainid,
+            serviceofferingid=cls.small_offering.id,
+            mode=cls.services["mode"]
+        )
+        cls._cleanup.extend([cls.account,
+                             cls.small_offering,
+                             cls.medium_offering,
+                             cls.big_offering,
+                             cls.service_offering_1,
+                             cls.service_offering_2])
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.apiclient = super(
+            TestDeployVMandVMLifeCycle,
+            cls).getClsTestClient().getApiClient()
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    def setUp(self):
+        self.dbclient = self.testClient.getDbConnection()
+        self.cleanup = []
+
+    def tearDown(self):
+        try:
+            # Clean up, terminate the created ISOs
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+
+    @attr(
+        tags=[
+            "devcloud",
+            "advanced",
+            "advancedns",
+            "smoke",
+            "basic",
+            "sg"],
+        required_hardware="false",
+        BugId="CLOUDSTACK-6984")
+    def test_01_vm_operations(self):
+        """Test Stop Virtual Machine
+        """
+
+        # Validate the following
+        # 1. Should Not be able to login to the VM.
+        # 2. listVM command should return
+        # Validate the following
+        # 3. listVM command should return this VM.State
+        #    of this VM should be Running".
+        #    this VM.State of this VM should be ""Stopped"".
+        # 4. Should be able to login to the VM.
+        # 5. listVM command should return the deployed VM.
+        #    State of this VM should be "Running"
+        # 6. Should not be able to login to the VM.
+        # 7. listVM command should return this VM.State
+        #    of this VM should be "Destroyed".
+        # 8. listVM command should return this VM.
+        #    State of this VM should be "Stopped".
+        # 9. We should be able to Start this VM successfully.
+        # 10. Environment has enough hosts for migration
+        # 11. DeployVM on suitable host (with another host in the cluster)
+        # 12. Migrate the VM and assert migration successful
+
+        try:
+            self.small_virtual_machine.stop(self.apiclient)
+        except Exception as e:
+            self.fail("Failed to stop VM: %s" % e)
+
+        self.debug("Starting VM - ID: %s" % self.small_virtual_machine.id)
+        self.small_virtual_machine.start(self.apiclient)
+
+        list_vm_response = VirtualMachine.list(
+            self.apiclient,
+            id=self.small_virtual_machine.id
+        )
+        self.assertEqual(
+            isinstance(list_vm_response, list),
+            True,
+            "Check list response returns a valid list"
+        )
+
+        self.assertNotEqual(
+            len(list_vm_response),
+            0,
+            "Check VM avaliable in List Virtual Machines"
+        )
+
+        self.debug(
+            "Verify listVirtualMachines response for virtual machine: %s"
+            % self.small_virtual_machine.id
+        )
+        self.assertEqual(
+            list_vm_response[0].state,
+            "Running",
+            "Check virtual machine is in running state"
+        )
+        self.debug("Rebooting VM - ID: %s" % self.small_virtual_machine.id)
+        self.small_virtual_machine.reboot(self.apiclient)
+
+        list_vm_response = VirtualMachine.list(
+            self.apiclient,
+            id=self.small_virtual_machine.id
+        )
+        self.assertEqual(
+            isinstance(list_vm_response, list),
+            True,
+            "Check list response returns a valid list"
+        )
+
+        self.assertNotEqual(
+            len(list_vm_response),
+            0,
+            "Check VM avaliable in List Virtual Machines"
+        )
+
+        self.assertEqual(
+            list_vm_response[0].state,
+            "Running",
+            "Check virtual machine is in running state"
+        )
+        self.debug("Destroy VM - ID: %s" % self.small_virtual_machine.id)
+        self.small_virtual_machine.delete(self.apiclient, expunge=False)
+
+        list_vm_response = VirtualMachine.list(
+            self.apiclient,
+            id=self.small_virtual_machine.id
+        )
+        self.assertEqual(
+            isinstance(list_vm_response, list),
+            True,
+            "Check list response returns a valid list"
+        )
+
+        self.assertNotEqual(
+            len(list_vm_response),
+            0,
+            "Check VM avaliable in List Virtual Machines"
+        )
+
+        self.assertEqual(
+            list_vm_response[0].state,
+            "Destroyed",
+            "Check virtual machine is in destroyed state"
+        )
+        suitable_hosts = None
+
+        hosts = Host.list(
+            self.apiclient,
+            zoneid=self.zone.id,
+            type='Routing'
+        )
+        self.assertEqual(
+            validateList(hosts)[0],
+            PASS,
+            "hosts list validation failed")
+
+        if len(hosts) < 2:
+            self.skipTest(
+                "At least two hosts should be present in"
+                " the zone for migration")
+
+        if self.hypervisor.lower() in ["lxc"]:
+            self.skipTest("Migration is not supported on LXC")
+
+        # For KVM, two hosts used for migration should  be present
+        #  in same cluster
+        # For XenServer and VMware, migration is possible between
+        #  hosts belonging to different clusters
+        # with the help of XenMotion and Vmotion respectively.
+
+        if self.hypervisor.lower() in ["kvm", "simulator"]:
+            # identify suitable host
+            clusters = [h.clusterid for h in hosts]
+            # find hosts withe same clusterid
+            clusters = [
+                cluster for index,
+                cluster in enumerate(clusters) if clusters.count(cluster) > 1]
+
+            if len(clusters) <= 1:
+                self.skipTest(
+                    "In " +
+                    self.hypervisor.lower() +
+                    " Live Migration needs two hosts within same cluster")
+
+            suitable_hosts = [
+                host for host in hosts if host.clusterid == clusters[0]]
+        else:
+            suitable_hosts = hosts
+
+        target_host = suitable_hosts[0]
+        migrate_host = suitable_hosts[1]
+
+        # deploy VM on target host
+        self.vm_to_migrate = VirtualMachine.create(
+            self.apiclient,
+            self.services["small"],
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.small_offering.id,
+            mode=self.services["mode"],
+            hostid=target_host.id
+        )
+        self.debug("Migrating VM-ID: %s to Host: %s" % (
+            self.vm_to_migrate.id,
+            migrate_host.id
+        ))
+
+        self.vm_to_migrate.migrate(self.apiclient, migrate_host.id)
+
+        retries_cnt = 3
+        while retries_cnt >= 0:
+            list_vm_response = VirtualMachine.list(self.apiclient,
+                                                   id=self.vm_to_migrate.id)
+            self.assertNotEqual(
+                list_vm_response,
+                None,
+                "Check virtual machine is listed"
+            )
+            vm_response = list_vm_response[0]
+            self.assertEqual(
+                vm_response.id,
+                self.vm_to_migrate.id,
+                "Check virtual machine ID of migrated VM")
+            self.assertEqual(
+                vm_response.hostid,
+                migrate_host.id,
+                "Check destination hostID of migrated VM")
+            retries_cnt = retries_cnt - 1
+        return
+
+    @attr(configuration="expunge.interval")
+    @attr(configuration="expunge.delay")
+    @attr(
+        tags=[
+            "devcloud",
+            "advanced",
+            "advancedns",
+            "smoke",
+            "basic",
+            "sg"],
+        required_hardware="false")
+    def test_02_expunge_vm(self):
+        """Test destroy(expunge) Virtual Machine
+        """
+        # Validate the following
+        # 1. listVM command should NOT  return this VM any more.
+
+        self.debug("Expunge VM-ID: %s" % self.small_virtual_machine.id)
+
+        cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
+        cmd.id = self.small_virtual_machine.id
+        self.apiclient.destroyVirtualMachine(cmd)
+
+        config = Configurations.list(
+            self.apiclient,
+            name='expunge.delay'
+        )
+
+        expunge_delay = int(config[0].value)
+        time.sleep(expunge_delay * 2)
+
+        # VM should be destroyed unless expunge thread hasn't run
+        # Wait for two cycles of the expunge thread
+        config = Configurations.list(
+            self.apiclient,
+            name='expunge.interval'
+        )
+        expunge_cycle = int(config[0].value)
+        wait_time = expunge_cycle * 4
+        while wait_time >= 0:
+            list_vm_response = VirtualMachine.list(
+                self.apiclient,
+                id=self.small_virtual_machine.id
+            )
+            if not list_vm_response:
+                break
+            self.debug("Waiting for VM to expunge")
+            # time.sleep(expunge_cycle)
+            wait_time = wait_time - expunge_cycle
+
+        self.debug("listVirtualMachines response: %s" % list_vm_response)
+
+        self.assertEqual(
+            list_vm_response,
+            None,
+            "Check Expunged virtual machine is in"
+            " listVirtualMachines response")
+        return
+
+    @attr(
+        tags=[
+            "advanced",
+            "advancedns",
+            "smoke",
+            "basic",
+            "sg"],
+        required_hardware="true")
+    def test_03_attachAndDetach_iso(self):
+        """Test for attach and detach ISO to virtual machine"""
+
+        # Validate the following
+        # 1. Create ISO
+        # 2. Attach ISO to VM
+        # 3. Log in to the VM.
+        # 4. The device should be available for use
+        # 5. Detach ISO
+        # 6. Check the device is properly detached by logging into VM
+
+        if self.hypervisor.lower() in ["lxc"]:
+            self.skipTest("ISOs are not supported on LXC")
+
+        iso = Iso.create(
+            self.apiclient,
+            self.services["iso1"],
+            account=self.account.name,
+            domainid=self.account.domainid
+        )
+
+        self.debug("Successfully created ISO with ID: %s" % iso.id)
+        try:
+            iso.download(self.apiclient)
+        except Exception as e:
+            self.fail("Exception while downloading ISO %s: %s"
+                      % (iso.id, e))
+
+        self.debug("Attach ISO with ID: %s to VM ID: %s" % (
+            iso.id,
+            self.virtual_machine.id
+        ))
+        # Attach ISO to virtual machine
+        cmd = attachIso.attachIsoCmd()
+        cmd.id = iso.id
+        cmd.virtualmachineid = self.virtual_machine.id
+        self.apiclient.attachIso(cmd)
+
+        try:
+            ssh_client = self.virtual_machine.get_ssh_client()
+        except Exception as e:
+            self.fail("SSH failed for virtual machine: %s - %s" %
+                      (self.virtual_machine.ipaddress, e))
+
+        mount_dir = "/mnt/tmp"
+        cmds = "mkdir -p %s" % mount_dir
+        self.assert_(
+            ssh_client.execute(cmds) == [],
+            "mkdir failed within guest")
+
+        for diskdevice in self.services["diskdevice"]:
+            res = ssh_client.execute(
+                "mount -rt iso9660 {} {}".format(diskdevice, mount_dir))
+            if res == []:
+                self.services["mount"] = diskdevice
+                break
+        else:
+            self.fail("No mount points matched. Mount was unsuccessful")
+
+        c = "mount |grep %s|head -1" % self.services["mount"]
+        res = ssh_client.execute(c)
+        size = ssh_client.execute("du %s | tail -1" % self.services["mount"])
+        self.debug("Found a mount point at %s with size %s" % (res, size))
+
+        # Get ISO size
+        iso_response = Iso.list(
+            self.apiclient,
+            id=iso.id
+        )
+        self.assertEqual(
+            isinstance(iso_response, list),
+            True,
+            "Check list response returns a valid list"
+        )
+
+        try:
+            # Unmount ISO
+            command = "umount %s" % mount_dir
+            ssh_client.execute(command)
+        except Exception as e:
+            self.fail("SSH failed for virtual machine: %s - %s" %
+                      (self.virtual_machine.ipaddress, e))
+
+        # Detach from VM
+        cmd = detachIso.detachIsoCmd()
+        cmd.virtualmachineid = self.virtual_machine.id
+        self.apiclient.detachIso(cmd)
 
 Review comment:
   again use library functions for detach iso .. Its always a good idea to no 
call api commands from test cases
 
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to