cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From e...@apache.org
Subject [1/2] git commit: updated refs/heads/master to bbdec1c
Date Thu, 02 Apr 2015 13:56:06 GMT
Repository: cloudstack
Updated Branches:
  refs/heads/master 20a663a30 -> bbdec1c8d


CLOUDSTACK-8357 Add Test cases for vMotion support on VMFS as primary storage


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/dedc860a
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/dedc860a
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/dedc860a

Branch: refs/heads/master
Commit: dedc860a62bbfc12971b3661fc654f3b8687c1ca
Parents: c05e37b
Author: Abhinav Roy <abhinav.roy@citrix.com>
Authored: Wed Apr 1 23:18:40 2015 +0530
Committer: Abhinav Roy <abhinav.roy@citrix.com>
Committed: Wed Apr 1 23:18:40 2015 +0530

----------------------------------------------------------------------
 .../testpaths/testpath_storage_migration.py     | 457 ++++++++++++++++++-
 tools/marvin/marvin/lib/base.py                 |  20 +-
 2 files changed, 474 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/dedc860a/test/integration/testpaths/testpath_storage_migration.py
----------------------------------------------------------------------
diff --git a/test/integration/testpaths/testpath_storage_migration.py b/test/integration/testpaths/testpath_storage_migration.py
index 2a92914..4f8ee65 100644
--- a/test/integration/testpaths/testpath_storage_migration.py
+++ b/test/integration/testpaths/testpath_storage_migration.py
@@ -34,7 +34,10 @@ from marvin.lib.common import (get_domain,
                                get_zone,
                                get_template,
                                list_volumes,
-                               list_virtual_machines
+                               list_virtual_machines,
+                               list_storage_pools,
+                               list_clusters,
+                               list_hosts
                                )
 from marvin.codes import (ZONETAG1,
                           CLUSTERTAG1)
@@ -3391,3 +3394,455 @@ class TestLiveStorageMigration(cloudstackTestCase):
             ), None, "Volume list should be empty")
 
         return
+
+def MigrateVmWithVolume(self,vm,destinationHost,volumes,pools):
+    """
+        This method is used to migrate a vm and its volumes using migrate virtual machine
with volume API
+        INPUTS:
+               1. vm -> virtual machine object
+               2. destinationHost -> the host to which VM will be migrated
+               3. volumes -> list of volumes which are to be migrated
+               4. pools -> list of destination pools
+    """
+    vol_pool_map = {}
+    for vol,pool in zip(volumes,pools):
+        vol_pool_map.update({vol.id:pool.id})
+
+    vm.migrate_vm_with_volume(
+                                  self.apiclient,
+                                  hostid=destinationHost.id,
+                                  migrateto = vol_pool_map
+                                  )
+    vm.getState(
+                    self.apiclient,
+                    "Running"
+                )
+    #check for the VM's host and volume's storage post migration
+    migrated_vm_response = list_virtual_machines(self.apiclient, id=vm.id)
+    self.assertEqual(
+                         isinstance(migrated_vm_response, list),
+                         True,
+                         "Check list virtual machines response for valid list"
+                    )
+    self.assertEqual(
+                         migrated_vm_response[0].hostid,
+                         destinationHost.id,
+                         "VM did not migrate to a specified host"
+                    )
+
+    for vol,pool in zip(volumes,pools):
+        migrated_volume_response = list_volumes(self.apiclient, virtualmachineid = migrated_vm_response[0].id,
name=vol.name, listall = True)
+        self.assertEqual(
+                         isinstance(migrated_volume_response, list),
+                         True,
+                         "Check list virtual machines response for valid list"
+                        )
+        self.assertEqual(
+                         migrated_volume_response[0].storageid,
+                         pool.id,
+                         "Volume did not migrate to a specified pool"
+                        )
+
+        self.assertEqual(
+                         str(migrated_volume_response[0].state).lower(),
+                         'ready',
+                         "Check migrated volume is in Ready state"
+                        )
+        """
+        #Take VM snapshot to check data integrity
+        try :
+            vm_snapshot = VmSnapshot.create(self.apiclient, vmid = migrated_vm_response[0].id)
+        except Exception as e:
+            raise Exception("Warning: Exception during VM snapshot creation : %s" % e)
+        
+        #Delete the snapshot
+        try :
+            VmSnapshot.deleteVMSnapshot(self.apiclient, vmsnapshotid = vm_snapshot.id)
+        except Exception as e:
+            raise Exception("Warning: Exception during VM snapshot creation : %s" % e)
+        """
+
+        return migrated_vm_response[0]
+
+def MigrateVm(self, vm, destinationHost):
+    """
+    This method is to migrate a VM using migrate virtual machine API
+    """
+
+    vm.migrate(
+                    self.apiclient,
+                    hostid=destinationHost.id,
+                 )
+    vm.getState(
+                    self.apiclient,
+                    "Running"
+                    )
+    #check for the VM's host and volume's storage post migration
+    migrated_vm_response = list_virtual_machines(self.apiclient, id=vm.id)
+    self.assertEqual(
+                         isinstance(migrated_vm_response, list),
+                         True,
+                         "Check list virtual machines response for valid list"
+                        )
+    self.assertEqual(
+                         migrated_vm_response[0].hostid,
+                         destinationHost.id,
+                         "VM did not migrate to a specified host"
+                        )
+    return migrated_vm_response[0]
+
+def get_destination_pools_hosts(self, vm):
+    """
+    Get destination Pools for all volumes and destination Host for the VM
+    This method is use in case we use the API migrate volume with storage
+    """
+
+    destinationPools = []
+    vol_list = list_volumes(self.apiclient, virtualmachineid=vm.id, listall=True)
+    # For each volume get destination pool
+    for vol in vol_list:
+        pool = GetDestinationPool(self, vol.storage, "CLUSTER")
+        destinationPools.append(pool)
+        #Get destination host
+    destinationHost = self.GetDestinationHost(vm.hostid)
+    return destinationHost, destinationPools, vol_list
+
+
+def check_files(self, vm, destinationHost):
+    """
+    Check for VMX and VMDK files
+            INPUTS :
+                      1. vm -> The Virtual Machine object
+                      2. destinationHost -> The host to which we want to migrate the VM
+    """
+    # list volumes and their pools
+    # Here we list all the volumes of the VM , then login to the destination host
+    # and check for vmx and vmdk files in the storage
+
+    vm_volumes = list_volumes(self.apiclient, virtualmachineid = vm.id, listall=True)
+    print vm_volumes
+    for vol in vm_volumes:
+        spool  =  list_storage_pools(self.apiclient, id=vol.storageid)
+        split_path = spool[0].path.split("/")
+        pool_path = split_path[2]
+        sshclient = SshClient(host = destinationHost.ipaddress, port = 22, user = "root",
passwd = "freebsd")
+        pool_data_vmdk = sshclient.execute("ls /vmfs/volumes/" + pool_path + "/" + vm.instancename
+  "| grep vmdk")
+        pool_data_vmx = sshclient.execute("ls /vmfs/volumes/" + pool_path + "/" + vm.instancename
+  "| grep vmx")
+        if(pool_data_vmx):
+            vmx_file = vm.instancename + ".vmx"
+            if vol.type == "ROOT":
+                self.assertIn(
+                      vmx_file,
+                      pool_data_vmx,
+                      "The VMX files are missing"
+                      )
+        if(pool_data_vmdk):
+            vmdk_file1 = vol.path + ".vmdk"
+            vmdk_file2 = vol.path + "-flat.vmdk"
+
+            self.assertIn(
+                      vmdk_file1,
+                      pool_data_vmdk,
+                      "The VMDK files are missing"
+                      )
+            self.assertIn(
+                      vmdk_file2,
+                      pool_data_vmdk,
+                      "The VMDK flat files are missing"
+                      )
+    return
+
+
+class TestStorageLiveMigrationVmware(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestStorageLiveMigrationVmware, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.testdata = testClient.getParsedTestDataConfig()
+        cls.hypervisor = cls.testClient.getHypervisorInfo()
+
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.apiclient)
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+
+        cls.template = get_template(
+            cls.apiclient,
+            cls.zone.id,
+            cls.testdata["ostype"])
+
+        cls._cleanup = []
+
+        if cls.hypervisor.lower() not in [
+                "vmware",
+                "kvm",
+                "xenserver",
+                "hyper-v"]:
+            raise unittest.SkipTest(
+                "Storage migration not supported on %s" %
+                cls.hypervisor)
+        # Get Hosts in the cluster and iscsi/vmfs storages for that cluster
+        iscsi_pools = []
+        try :
+            list_vmware_clusters = list_clusters(cls.apiclient, hypervisor="vmware")
+        except Exception as e:
+            raise unittest.SkipTest(e)
+        
+        if len(list_vmware_clusters) < 1 :
+            raise unittest.SkipTest("There is no cluster available in the setup")
+        else :
+            for cluster in list_vmware_clusters :
+                try:
+                    list_esx_hosts = list_hosts(cls.apiclient, clusterid = cluster.id)
+                except Exception as e:
+                    raise unittest.SkipTest(e)
+                if len(list_esx_hosts) > 1 :
+                    try:
+                        list_storage = list_storage_pools(cls.apiclient, clusterid = cluster.id)
+                    except Exception as e:
+                        raise unittest.SkipTest(e)
+                    for storage in list_storage :
+                        if storage.type == "VMFS" :
+                            iscsi_pools.append(storage)
+                    if len(iscsi_pools) > 1:
+                        my_cluster_id = cluster.id
+                        break
+                    else :
+                        iscsi_pools = []
+        if len(iscsi_pools) < 2 :
+            raise unittest.SkipTest("Not enough resources available in the setup")
+        cls.hosts = list_esx_hosts
+        cls.pools = list_storage
+
+        # Create an account
+        cls.account = Account.create(
+            cls.apiclient,
+            cls.testdata["account"],
+            domainid=cls.domain.id
+        )
+        cls._cleanup.append(cls.account)
+
+        # Create Service offering
+        cls.service_offering = ServiceOffering.create(
+            cls.apiclient,
+            cls.testdata["service_offering"]
+        )
+        cls._cleanup.append(cls.service_offering)
+
+        # Create Disk offering
+        cls.disk_offering = DiskOffering.create(
+            cls.apiclient,
+            cls.testdata["disk_offering"]
+        )
+        # Create disk offering for resize
+        cls.resized_disk_offering = DiskOffering.create(
+            cls.apiclient,
+            cls.testdata["resized_disk_offering"]
+        )
+
+        cls._cleanup.append(cls.disk_offering)
+        cls._cleanup.append(cls.resized_disk_offering)
+
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            cleanup_resources(cls.apiclient, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+        self.cleanup = []
+
+    def tearDown(self):
+        try:
+            for storagePool in self.pools:
+                StoragePool.update(self.apiclient, id=storagePool.id, tags="")
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    def deploy_virtual_machine(self, service_offering_id, vm):
+        """
+        Function to Deploy VMs
+        """
+        virtual_machine = VirtualMachine.create(
+        self.apiclient,
+        self.testdata[vm],
+        accountid=self.account.name,
+        zoneid=self.zone.id,
+        domainid=self.account.domainid,
+        serviceofferingid=service_offering_id,
+        templateid=self.template.id,
+        )
+        virtual_machine.getState(
+                                 self.apiclient,
+                                 "Running"
+                                 )
+
+        return virtual_machine
+    
+    def GetDestinationHost(self, hostsToavoid):
+        """
+        This method gives us the destination host to which VM will be migrated
+        It takes the souce host i.e. hostsToavoid as input
+        """
+        destinationHost = None
+        for host in self.hosts:
+            if host.id not in hostsToavoid:
+                destinationHost = host
+                break
+        return destinationHost
+        
+
+    @attr(tags=["advanced", "basic", "vmware", "vmfs"])
+    def test_01_migrate_root_and_data_disk_live(self):
+        """
+        Migrate VMs/Volumes on VMware with VMFS storage
+        """
+        #List clusters and check if they have multiple hosts
+        #and multiple storages
+        #check if they storages are VMFS type
+        self.debug("---------------This is the test no 1--------------")
+        """
+        Create a VM, live migrate the VM
+        """
+        vm = "virtual_machine2"
+        virtual_machine_1 = self.deploy_virtual_machine(self.service_offering.id, vm)
+
+        #Get destination host
+        destinationHost = self.GetDestinationHost(virtual_machine_1.hostid)
+        #Migrate the VM
+        vm = MigrateVm(self, virtual_machine_1, destinationHost)
+        #self.check_files(vm,destinationHost)
+        
+        self.debug("---------------This is the test no 2--------------")
+        """
+        Migrate the ROOT Volume
+        """
+        # Get ROOT volume and destination pool
+        vol_list = list_volumes(self.apiclient, virtualmachineid=vm.id, type="ROOT", listall=True)
+        root_vol = vol_list[0]
+        destinationPool = GetDestinationPool(self, root_vol.storage, "CLUSTER")
+        #Migrate ROOT volume
+        islive = True
+        MigrateDataVolume(self, root_vol, destinationPool, islive)
+        check_files(self, vm ,destinationHost)
+        
+        self.debug("---------------This is the test no 3--------------")
+        """
+        Migrate the VM and ROOT volume
+        """
+        #Get all volumes to be migrated
+ 
+        destinationHost, destinationPools, vol_list = get_destination_pools_hosts(self, vm)
+        vm = MigrateVmWithVolume(self, virtual_machine_1, destinationHost, vol_list, destinationPools)
+
+        check_files(self, vm,destinationHost)
+
+        self.debug("---------------This is the test no 4--------------")
+        """
+        Add a data disk and migrate vm, data disk and root disk
+        """
+
+        data_disk_1 = Volume.create(
+                                    self.apiclient,
+                                    self.testdata["volume"],
+                                    zoneid=self.zone.id,
+                                    account=self.account.name,
+                                    domainid=self.account.domainid,
+                                    diskofferingid=self.disk_offering.id
+                                  )
+
+        self.debug("Created volume with ID: %s" % data_disk_1.id)
+
+        virtual_machine_1.attach_volume(
+                         self.apiclient,
+                         data_disk_1
+                         )
+
+        destinationHost, destinationPools, vol_list = get_destination_pools_hosts(self, vm)
+        vm = MigrateVmWithVolume(self, virtual_machine_1, destinationHost, vol_list, destinationPools)
+
+        check_files(self, vm,destinationHost)
+        self.debug("---------------This is the test no 5--------------")
+        """
+        Upload a Volume, Attach it to the VM, Migrate all the volumes and VM.
+        """
+
+                #upload a volume
+        self.testdata["configurableData"]["upload_volume"]["format"] = "OVA"
+        self.testdata["configurableData"]["upload_volume"]["url"] = "http://nfs1.lab.vmops.com/templates/burbank-systemvm-08012012.ova"
+        upload_volume = Volume.upload(
+                                      self.apiclient,
+                                      self.testdata["configurableData"]["upload_volume"],
+                                      account= self.account.name,
+                                      domainid= self.domain.id,
+                                      zoneid= self.zone.id
+                                      )
+        upload_volume.wait_for_upload(self.apiclient)
+        virtual_machine_1.attach_volume(
+                         self.apiclient,
+                         upload_volume
+                         )
+ 
+        destinationHost, destinationPools, vol_list = get_destination_pools_hosts(self, vm)
+        vm = MigrateVmWithVolume(self, virtual_machine_1, destinationHost, vol_list, destinationPools)
+
+        check_files(self, vm,destinationHost)
+        
+        self.debug("---------------This is the test no 6--------------")
+        """
+        Create snapshots on all the volumes, Migrate all the volumes and VM.
+        """
+        #Get ROOT Volume
+        vol_for_snap = list_volumes(self.apiclient, virtualmachineid=vm.id, listall=True)
+        for vol in vol_for_snap:
+            snapshot = Snapshot.create(
+                                        self.apiclient,
+                                        volume_id = vol.id
+                                        )
+            snapshot.validateState(
+                                   self.apiclient, 
+                                    snapshotstate="backedup", 
+                                    )
+        # Migrate all volumes and VMs
+
+        destinationHost, destinationPools, vol_list = get_destination_pools_hosts(self, vm)
+        vm = MigrateVmWithVolume(self, virtual_machine_1, destinationHost, vol_list, destinationPools)
+
+        check_files(self, vm, destinationHost)
+
+        self.debug("---------------This is the test no 7--------------")
+        """
+        Resize the data volume , Migrate all the volumes and VM.
+        """
+        data_disk_1.resize(
+                           self.apiclient,
+                           diskofferingid = self.resized_disk_offering.id
+                           )
+        # Migrate all volumes and VMs
+        destinationHost, destinationPools, vol_list = get_destination_pools_hosts(self, vm)
+        vm = MigrateVmWithVolume(self, virtual_machine_1, destinationHost, vol_list, destinationPools)
+
+        check_files(self, vm,destinationHost)
+
+        self.debug("---------------This is the test no 8--------------")
+        """
+        Restore the VM , Migrate all the volumes and VM.
+        """
+        virtual_machine_1.restore(self.apiclient)
+        virtual_machine_1.getState(
+                                     self.apiclient,
+                                     "Running"
+                                     )
+        # Migrate the VM and its volumes
+
+        destinationHost, destinationPools, vol_list = get_destination_pools_hosts(self, vm)
+        vm = MigrateVmWithVolume(self, virtual_machine_1, destinationHost, vol_list, destinationPools)
+
+        check_files(self, vm,destinationHost)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/dedc860a/tools/marvin/marvin/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 3cb04fe..91a4f60 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -651,6 +651,21 @@ class VirtualMachine:
             cmd.hostid = hostid
         apiclient.migrateVirtualMachine(cmd)
 
+    def migrate_vm_with_volume(self, apiclient, hostid=None, migrateto=None):
+        """migrate an Instance and its volumes"""
+        cmd = migrateVirtualMachineWithVolume.migrateVirtualMachineWithVolumeCmd()
+        cmd.virtualmachineid = self.id
+        if hostid:
+            cmd.hostid = hostid
+        if migrateto:
+            migrateto = []
+            for volume, pool in migrateto.items():
+                cmd.migrateto.append({
+                    'volume': volume,
+                    'pool': pool
+            })
+        apiclient.migrateVirtualMachineWithVolume(cmd)
+
     def attach_volume(self, apiclient, volume):
         """Attach volume to instance"""
         cmd = attachVolume.attachVolumeCmd()
@@ -3636,11 +3651,12 @@ class Configurations:
     """Manage Configuration"""
 
     @classmethod
-    def update(cls, apiclient, **kwargs):
+    def update(cls, apiclient, name, value=None):
         """Updates the specified configuration"""
 
         cmd = updateConfiguration.updateConfigurationCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        cmd.name = name
+        cmd.value = value
         apiclient.updateConfiguration(cmd)
 
     @classmethod


Mime
View raw message