You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ta...@apache.org on 2015/03/12 06:26:14 UTC

[2/3] git commit: updated refs/heads/master to 891b597

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/891b5976/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
new file mode 100644
index 0000000..ee77b03
--- /dev/null
+++ b/test/integration/testpaths/testpath_storage_migration.py
@@ -0,0 +1,3392 @@
+#_volumes 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.
+""" Test cases for Test Paths Storage Migration
+"""
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.utils import (cleanup_resources,
+                              random_gen,
+                              format_volume_to_ext3)
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             DiskOffering,
+                             Volume,
+                             Template,
+                             VirtualMachine,
+                             StoragePool,
+                             Snapshot
+                             )
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_volumes,
+                               list_virtual_machines
+                               )
+from marvin.codes import (ZONETAG1,
+                          CLUSTERTAG1)
+
+from marvin.cloudstackAPI import (deleteVolume)
+
+import hashlib
+from marvin.sshClient import SshClient
+import time
+from threading import Thread
+
+
+def GetDestinationPool(self,
+                       poolsToavoid,
+                       migrateto
+                       ):
+    """ Get destination pool which has scope same as migrateto
+    and which is not in avoid set
+    """
+
+    destinationPool = None
+
+    # Get Storage Pool Id to migrate to
+    for storagePool in self.pools:
+        if storagePool.scope == migrateto:
+            if storagePool.name not in poolsToavoid:
+                destinationPool = storagePool
+                break
+
+    return destinationPool
+
+
+def MigrateRootVolume(self,
+                      vm,
+                      destinationPool,
+                      expectexception=False):
+    """ Migrate given volume to type of storage pool mentioned in migrateto:
+
+        Inputs:
+            1. volume:           Volume to be migrated
+            2. migrate_to:       Scope of desired Storage pool to which volume
+                                 is to be migrated
+            3. expectexception:  If exception is expected while migration
+    """
+
+    if expectexception:
+        with self.assertRaises(Exception):
+            VirtualMachine.migrate(
+                vm,
+                self.apiclient,
+                # virtualmachineid=vm.id,
+                storageid=destinationPool.id,
+            )
+    else:
+        VirtualMachine.migrate(
+            vm,
+            self.apiclient,
+            # virtualmachineid=vm.id,
+            storageid=destinationPool.id,
+        )
+
+        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.assertNotEqual(
+            migrated_vm_response,
+            None,
+            "Check if virtual machine exists in ListVirtualMachines"
+        )
+
+        migrated_vm = migrated_vm_response[0]
+
+        root_volumes_cluster_list = Volume.list(
+            self.apiclient,
+            virtualmachineid=migrated_vm.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_cluster = root_volumes_cluster_list[0]
+
+        self.assertEqual(
+            root_volume_cluster.storage,
+            destinationPool.name,
+            "Check volume is on migrated pool"
+        )
+    return
+
+
+def MigrateDataVolume(self,
+                      volume,
+                      destinationPool,
+                      islive=False,
+                      expectexception=False
+                      ):
+    """ Migrate given volume to type of storage pool mentioned in migrateto:
+
+        Inputs:
+            1. volume:           Volume to be migrated
+            2. migrate_to:       Scope of desired Storage pool to which volume
+                                 is to be migrated
+            3. expectexception:  If exception is expected while migration
+    """
+
+    if expectexception:
+        with self.assertRaises(Exception):
+            Volume.migrate(
+                self.apiclient,
+                volumeid=volume.id,
+                storageid=destinationPool.id,
+                livemigrate=islive
+            )
+    else:
+        Volume.migrate(
+            self.apiclient,
+            volumeid=volume.id,
+            storageid=destinationPool.id,
+            livemigrate=islive
+        )
+
+        migrated_volume_response = list_volumes(
+            self.apiclient,
+            id=volume.id
+        )
+
+        self.assertEqual(
+            isinstance(migrated_volume_response, list),
+            True,
+            "Check list volumes response for valid list"
+        )
+
+        self.assertNotEqual(
+            migrated_volume_response,
+            None,
+            "Check if volume exists in ListVolumes"
+        )
+
+        migrated_volume = migrated_volume_response[0]
+
+        self.assertEqual(
+            str(migrated_volume.state).lower(),
+            'ready',
+            "Check migrated volume is in Ready state"
+        )
+
+        self.assertEqual(
+            migrated_volume.storage,
+            destinationPool.name,
+            "Check volume is on migrated pool"
+        )
+    return
+
+
+def createChecksum(self, virtual_machine, disk, disk_type):
+    """ Write data on the disk and return the md5 checksum"""
+
+    random_data_0 = random_gen(size=100)
+    # creating checksum(MD5)
+    m = hashlib.md5()
+    m.update(random_data_0)
+    checksum_random_data_0 = m.hexdigest()
+    try:
+        ssh_client = SshClient(
+            virtual_machine.ssh_ip,
+            virtual_machine.ssh_port,
+            virtual_machine.username,
+            virtual_machine.password
+        )
+    except Exception as e:
+        self.fail("SSH failed for VM: %s" %
+                  e)
+
+    self.debug("Formatting volume: %s to ext3" % disk.id)
+    # Format partition using ext3
+    # Note that this is the second data disk partition of virtual machine
+    # as it was already containing data disk before attaching the new volume,
+    # Hence datadiskdevice_2
+
+    format_volume_to_ext3(
+        ssh_client,
+        self.testdata["volume_write_path"][
+            virtual_machine.hypervisor][disk_type]
+    )
+    cmds = ["fdisk -l",
+            "mkdir -p %s" % self.testdata["data_write_paths"]["mount_dir"],
+            "mount -t ext3 %s1 %s" % (
+                self.testdata["volume_write_path"][
+                    virtual_machine.hypervisor][disk_type],
+                self.testdata["data_write_paths"]["mount_dir"]
+            ),
+            "mkdir -p %s/%s/%s " % (
+                self.testdata["data_write_paths"]["mount_dir"],
+                self.testdata["data_write_paths"]["sub_dir"],
+                self.testdata["data_write_paths"]["sub_lvl_dir1"],
+            ),
+            "echo %s > %s/%s/%s/%s" % (
+                random_data_0,
+                self.testdata["data_write_paths"]["mount_dir"],
+                self.testdata["data_write_paths"]["sub_dir"],
+                self.testdata["data_write_paths"]["sub_lvl_dir1"],
+                self.testdata["data_write_paths"]["random_data"]
+            ),
+            "cat %s/%s/%s/%s" % (
+                self.testdata["data_write_paths"]["mount_dir"],
+                self.testdata["data_write_paths"]["sub_dir"],
+                self.testdata["data_write_paths"]["sub_lvl_dir1"],
+                self.testdata["data_write_paths"]["random_data"]
+            )
+            ]
+
+    for c in cmds:
+        self.debug("Command: %s" % c)
+        result = ssh_client.execute(c)
+        self.debug(result)
+
+    # Unmount the storage
+    cmds = [
+        "umount %s" % (self.testdata["data_write_paths"]["mount_dir"]),
+    ]
+
+    for c in cmds:
+        self.debug("Command: %s" % c)
+        ssh_client.execute(c)
+
+    return checksum_random_data_0
+
+
+def compareChecksum(
+        self,
+        original_checksum,
+        disk_type,
+        virt_machine=None,
+        disk=None,
+        new_vm=False):
+    """
+    Create md5 checksum of the data present on the disk and compare
+    it with the given checksum
+    """
+
+    if disk_type == "datadiskdevice_1" and new_vm:
+        new_virtual_machine = VirtualMachine.create(
+            self.userapiclient,
+            self.testdata["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_cluster1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        new_virtual_machine.start(self.userapiclient)
+
+        self.debug("Attaching volume: %s to VM: %s" % (
+            disk.id,
+            new_virtual_machine.id
+        ))
+
+        new_virtual_machine.attach_volume(
+            self.apiclient,
+            disk
+        )
+
+        # Rebooting is required so that newly attached disks are detected
+        self.debug("Rebooting : %s" % new_virtual_machine.id)
+        new_virtual_machine.reboot(self.apiclient)
+
+    else:
+        # If the disk is root disk then no need to create new VM
+        # Just start the original machine on which root disk is
+        new_virtual_machine = virt_machine
+        if new_virtual_machine.state != "Running":
+            new_virtual_machine.start(self.userapiclient)
+
+    try:
+        # Login to VM to verify test directories and files
+
+        self.debug(
+            "SSH into (Public IP: ) %s " % new_virtual_machine.ssh_ip)
+        ssh = SshClient(
+            new_virtual_machine.ssh_ip,
+            new_virtual_machine.ssh_port,
+            new_virtual_machine.username,
+            new_virtual_machine.password
+        )
+    except Exception as e:
+        self.fail("SSH access failed for VM: %s, Exception: %s" %
+                  (new_virtual_machine.ipaddress, e))
+
+    # Mount datadiskdevice_1 because this is the first data disk of the new
+    # virtual machine
+    cmds = ["blkid",
+            "fdisk -l",
+            "mkdir -p %s" % self.testdata["data_write_paths"]["mount_dir"],
+            "mount -t ext3 %s1 %s" % (
+                self.testdata["volume_write_path"][
+                    new_virtual_machine.hypervisor][disk_type],
+                self.testdata["data_write_paths"]["mount_dir"]
+            ),
+            ]
+
+    for c in cmds:
+        self.debug("Command: %s" % c)
+        result = ssh.execute(c)
+        self.debug(result)
+
+    returned_data_0 = ssh.execute(
+        "cat %s/%s/%s/%s" % (
+            self.testdata["data_write_paths"]["mount_dir"],
+            self.testdata["data_write_paths"]["sub_dir"],
+            self.testdata["data_write_paths"]["sub_lvl_dir1"],
+            self.testdata["data_write_paths"]["random_data"]
+        ))
+
+    n = hashlib.md5()
+    n.update(returned_data_0[0])
+    checksum_returned_data_0 = n.hexdigest()
+
+    self.debug("returned_data_0: %s" % returned_data_0[0])
+
+    # Verify returned data
+    self.assertEqual(
+        original_checksum,
+        checksum_returned_data_0,
+        "Cheskum does not match with checksum of original data"
+    )
+
+    # Unmount the Sec Storage
+    cmds = [
+        "umount %s" % (self.testdata["data_write_paths"]["mount_dir"]),
+    ]
+
+    for c in cmds:
+        self.debug("Command: %s" % c)
+        ssh.execute(c)
+
+    if new_vm:
+        new_virtual_machine.detach_volume(
+            self.apiclient,
+            disk
+        )
+
+        new_virtual_machine.delete(self.apiclient)
+
+    return
+
+
+class TestStorageMigration(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestStorageMigration, 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)
+
+        try:
+            cls.pools = StoragePool.list(cls.apiclient, zoneid=cls.zone.id)
+        except Exception as e:
+            raise unittest.SkipTest(e)
+        try:
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.testdata["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering_zone1 = ServiceOffering.create(
+                cls.apiclient,
+                cls.testdata["service_offering"],
+                tags=ZONETAG1
+            )
+            cls._cleanup.append(cls.service_offering_zone1)
+
+            cls.service_offering_cluster1 = ServiceOffering.create(
+                cls.apiclient,
+                cls.testdata["service_offering"],
+                tags=CLUSTERTAG1
+            )
+            cls._cleanup.append(cls.service_offering_cluster1)
+
+            # If local storage is enabled, alter the offerings to use
+            # localstorage
+            if cls.zone.localstorageenabled:
+                cls.testdata["service_offering"]["storagetype"] = 'local'
+
+                cls.service_offering_local1 = ServiceOffering.create(
+                    cls.apiclient,
+                    cls.testdata["service_offering"]
+                )
+                cls._cleanup.append(cls.service_offering_local1)
+
+            # Create Disk offering
+            cls.disk_offering_zone1 = DiskOffering.create(
+                cls.apiclient,
+                cls.testdata["disk_offering"],
+                tags=ZONETAG1
+            )
+            cls._cleanup.append(cls.disk_offering_zone1)
+
+            cls.disk_offering_cluster1 = DiskOffering.create(
+                cls.apiclient,
+                cls.testdata["disk_offering"],
+                tags=CLUSTERTAG1
+            )
+            cls._cleanup.append(cls.disk_offering_cluster1)
+
+            # If local storage is enabled, alter the offerings to use
+            # localstorage
+            if cls.zone.localstorageenabled:
+                cls.testdata["disk_offering"]["storagetype"] = 'local'
+
+                cls.disk_offering_local1 = DiskOffering.create(
+                    cls.apiclient,
+                    cls.testdata["disk_offering"]
+                )
+                cls._cleanup.append(cls.disk_offering_local1)
+        except Exception as e:
+            cls.tearDownClass()
+            raise e
+        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
+
+    @attr(tags=["advanced", "basic"])
+    def test_01_migrate_root_and_data_disk_nonlive(self):
+        """ Test migrate Volume (root and data disk)
+
+        # 1. Deploy a VM on cluster wide primary storage.
+        # 2. Migrate root and data volume from cluster-to-cluster,
+        #    cluster-to-zone, cluster-to-local.
+        # 3. Deploy a VM on zone wide primary storage..
+        # 4. Migrate root and data volume from zone-to-zone, zone-to-local.
+        # 5. Deploy a VM on local storage.
+        # 6. Migrate root and data volume from local-to-local.
+
+        Each Migration has following steps:
+
+            a. Write data to disk, create checksum
+            b. Migrate the volume to suitable pool
+            c. Attach disk to VM and compare checksum with
+               checksum of data on disk, they should match
+
+        In addition to this,
+        Create snapshot of root and data disk after migration.
+        For root disk, create template from snapshot, deploy Vm and compare checksum
+        For data disk, Create volume from snapshot, attach to VM and compare checksum
+
+        """
+
+        # Skipping test case for XenSever because ZWPS scenarios present in the test case
+        # Skipping for Vmware because at a time either ZWPS or CWPS can exists in vmware
+        # so the test case for Vmware is written separately
+
+        if self.hypervisor in ["xenserver", "vmware"]:
+            self.skipTest("Skip test case for %s" % self.hypervisor)
+
+        try:
+            self.pools = StoragePool.list(self.apiclient, zoneid=self.zone.id)
+            assert len(list(storagePool for storagePool in self.pools
+                            if storagePool.scope == "ZONE")) >= 2,\
+                "There must be at least two zone wide\
+                storage pools available in the setup"
+            assert len(list(storagePool for storagePool in self.pools
+                            if storagePool.scope == "CLUSTER")) >= 2,\
+                "There must be at least two cluster wide\
+                storage pools available in the setup"
+        except Exception as e:
+            self.skipTest(e)
+
+        # Adding tags to Storage Pools
+        cluster_no = 1
+        zone_no = 1
+        self.debug("Storage Pools: %s" % self.pools)
+        for storagePool in self.pools:
+            if storagePool.scope == "ZONE":
+                StoragePool.update(
+                    self.apiclient,
+                    id=storagePool.id,
+                    tags=['zwps' + repr(zone_no)])
+                zone_no += 1
+            elif storagePool.scope == "CLUSTER":
+                StoragePool.update(
+                    self.apiclient,
+                    id=storagePool.id,
+                    tags=['cwps' + repr(cluster_no)])
+                cluster_no += 1
+
+        # Step 1
+        # Create VM on CWPS
+        vm_cluster = VirtualMachine.create(
+            self.userapiclient,
+            self.testdata["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_cluster1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        # Get ROOT Volume
+        root_volumes_cluster_list = list_volumes(
+            self.apiclient,
+            virtualmachineid=vm_cluster.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_cluster = root_volumes_cluster_list[0]
+
+        # Create DATA Volume on Cluster Wide Storage
+        data_volume_clust = Volume.create(
+            self.apiclient,
+            self.testdata["volume"],
+            zoneid=self.zone.id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            diskofferingid=self.disk_offering_cluster1.id
+        )
+
+        self.debug("Created volume with ID: %s" % data_volume_clust.id)
+
+        vm_cluster.attach_volume(
+            self.userapiclient,
+            data_volume_clust
+        )
+
+        data_volumes_cluster_list = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_volume_clust.id
+        )
+
+        root_vol_snap = Snapshot.create(
+            self.apiclient,
+            root_volume_cluster.id)
+
+        data_vol_snap = Snapshot.create(
+            self.apiclient,
+            data_volume_clust.id)
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            data_volume_clust)
+
+        # Step 2
+        # Migrate ROOT Volume from CWPS to other CWPS, this consists of below 3 steps
+        # 1. Create Checksum
+        # 2. Migrate Volume
+        # 3. Compare checksum with data on volume on new pool
+        checksum_random_root_cluster = createChecksum(
+            self,
+            vm_cluster,
+            root_volume_cluster,
+            "rootdiskdevice")
+
+        vm_cluster.stop(self.userapiclient)
+
+        destinationPool = GetDestinationPool(
+            self,
+            [root_volume_cluster.storage],
+            "CLUSTER")
+        MigrateRootVolume(self, vm_cluster, destinationPool)
+
+        vm_cluster.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_root_cluster,
+            "rootdiskdevice",
+            virt_machine=vm_cluster,
+            disk=None,
+        )
+        self.debug("Done with compare checksum")
+
+        vm_cluster.stop(self.userapiclient)
+        # Try to Migrate ROOT Volume from CWPS to ZWPS
+        destinationPool = GetDestinationPool(
+            self,
+            [root_volume_cluster.storage],
+            "ZONE")
+
+        MigrateRootVolume(
+            self,
+            vm_cluster,
+            destinationPool)
+
+        vm_cluster.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_root_cluster,
+            "rootdiskdevice",
+            virt_machine=vm_cluster,
+            disk=None,
+        )
+
+        vm_cluster.stop(self.userapiclient)
+        # Try to Migrate ROOT Volume from CWPS to Local
+        destinationPool = GetDestinationPool(
+            self,
+            [root_volume_cluster.storage],
+            "HOST")
+
+        MigrateRootVolume(
+            self,
+            vm_cluster,
+            destinationPool,
+            expectexception=True)
+
+        vm_cluster.start(self.userapiclient)
+
+        checksum_random_data_cluster = createChecksum(
+            self,
+            vm_cluster,
+            data_volumes_cluster_list[0],
+            "datadiskdevice_1")
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            data_volumes_cluster_list[0]
+        )
+
+        vm_cluster.stop(self.userapiclient)
+
+        # Migrate DATA Volume from CWPS to other CWPS - Create checksum,
+        # migrate volume, compare checksum
+
+        destinationPool = GetDestinationPool(
+            self,
+            [data_volumes_cluster_list[0].storage],
+            "CLUSTER")
+
+        MigrateDataVolume(
+            self,
+            data_volumes_cluster_list[0],
+            destinationPool)
+
+        vm_cluster.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_data_cluster,
+            "datadiskdevice_1",
+            virt_machine=None,
+            disk=data_volumes_cluster_list[0],
+            new_vm=True)
+
+        # Add more data to disks
+        data_volume_clust_2 = Volume.create(
+            self.apiclient,
+            self.testdata["volume"],
+            zoneid=self.zone.id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            diskofferingid=self.disk_offering_cluster1.id
+        )
+
+        self.debug("Created volume with ID: %s" % data_volume_clust_2.id)
+
+        vm_cluster.attach_volume(
+            self.userapiclient,
+            data_volume_clust_2
+        )
+
+        data_disk_2_volumes_cluster_list = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_volume_clust_2.id
+        )
+
+        # Ensure we can add data to newly added disks
+        createChecksum(
+            self,
+            vm_cluster,
+            data_disk_2_volumes_cluster_list[0],
+            "datadiskdevice_2")
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            data_volume_clust_2
+        )
+
+        templateFromSnapshot = Template.create_from_snapshot(
+            self.apiclient,
+            root_vol_snap,
+            self.testdata["template_2"])
+
+        vm_from_temp = VirtualMachine.create(
+            self.apiclient,
+            self.testdata["small"],
+            templateid=templateFromSnapshot.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_cluster1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        root_volumes_snap_list = Volume.list(
+            self.apiclient,
+            virtualmachineid=vm_from_temp.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_snap = root_volumes_snap_list[0]
+
+        createChecksum(
+            self,
+            vm_from_temp,
+            root_volume_snap,
+            "rootdiskdevice")
+
+        templateFromSnapshot.delete(self.apiclient)
+
+        volumeFormSnap = Volume.create_from_snapshot(
+            self.apiclient,
+            data_vol_snap.id,
+            self.testdata["volume"],
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=self.zone.id
+        )
+
+        vm_from_temp.attach_volume(
+            self.userapiclient,
+            volumeFormSnap
+        )
+
+        data_from_snap = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=volumeFormSnap.id
+        )
+
+        vm_from_temp.reboot(self.userapiclient)
+
+        createChecksum(
+            self,
+            vm_from_temp,
+            data_from_snap[0],
+            "datadiskdevice_1")
+
+        vm_from_temp.detach_volume(
+            self.userapiclient,
+            volumeFormSnap
+        )
+
+        volumeFormSnap.delete(self.apiclient)
+
+        vm_from_temp.delete(self.apiclient)
+
+        vm_cluster.stop(self.userapiclient)
+        # Try to Migrate DATA Volume from CWPS to ZWPS
+        destinationPool = GetDestinationPool(
+            self,
+            [data_volumes_cluster_list[0].storage],
+            "ZONE")
+        MigrateDataVolume(
+            self,
+            data_volumes_cluster_list[0],
+            destinationPool)
+
+        vm_cluster.start(self.userapiclient)
+        compareChecksum(
+            self,
+            checksum_random_data_cluster,
+            "datadiskdevice_1",
+            virt_machine=None,
+            disk=data_volumes_cluster_list[0],
+            new_vm=True)
+
+        vm_cluster.stop(self.userapiclient)
+        # Try to Migrate DATA Volume from CWPS to Local Storage
+        destinationPool = GetDestinationPool(
+            self,
+            [data_volumes_cluster_list[0].storage],
+            "HOST")
+        MigrateDataVolume(
+            self,
+            data_volumes_cluster_list[0],
+            destinationPool)
+
+        # Delete ROOT and DATA Volume from CWPS
+        self.debug("Deleting Volume %s" % data_volume_clust.id)
+
+        vm_cluster.detach_volume(self.apiclient, data_volume_clust)
+
+        # Delete volume:
+        data_volume_clust.delete(self.apiclient)
+
+        self.assertEqual(
+            Volume.list(
+                self.apiclient,
+                id=data_volume_clust.id,
+            ), None, "Volume list should be empty")
+
+        # Destroy and expunge VM
+        vm_cluster.delete(self.apiclient)
+
+        self.assertEqual(
+            VirtualMachine.list(
+                self.apiclient,
+                id=vm_cluster.id
+            ), None, "VM list should be empty")
+
+        # Step 3
+        # Create VM on ZWPS
+        vm_zone = VirtualMachine.create(
+            self.userapiclient,
+            self.testdata["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_zone1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        vm_zone.start(self.userapiclient)
+
+        # Get ROOT Volume Id
+        root_volumes_zone_list = list_volumes(
+            self.apiclient,
+            virtualmachineid=vm_zone.id,
+            type='ROOT',
+            listall=True
+        )
+        root_volume_zone = root_volumes_zone_list[0]
+
+        # Create DATA Volume on ZWPS
+        data_volume_zone = Volume.create(
+            self.apiclient,
+            self.testdata["volume"],
+            zoneid=self.zone.id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            diskofferingid=self.disk_offering_zone1.id
+        )
+
+        self.debug("Created volume with ID: %s" % data_volume_zone.id)
+
+        data_volumes_zone_list = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_volume_zone.id
+        )
+
+        vm_zone.attach_volume(
+            self.userapiclient,
+            data_volume_zone
+        )
+
+        # Step 4
+        # Migrate ROOT Volume from ZWPS to other ZWPS
+        checksum_random_root_zone = createChecksum(
+            self,
+            vm_zone,
+            data_volumes_zone_list[0],
+            "rootdiskdevice")
+
+        vm_zone.stop(self.userapiclient)
+
+        destinationPool = GetDestinationPool(
+            self, [
+                root_volume_zone.storage], "ZONE")
+        MigrateRootVolume(self, vm_zone, destinationPool)
+
+        vm_zone.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_root_zone,
+            "rootdiskdevice",
+            virt_machine=vm_zone,
+            disk=None,
+        )
+
+        vm_zone.stop(self.userapiclient)
+        # Try to Migrate ROOT Volume from ZWPS to Local Storage
+        destinationPool = GetDestinationPool(
+            self, [
+                root_volume_zone.storage], "HOST")
+        MigrateRootVolume(self, vm_zone, destinationPool, expectexception=True)
+
+        # Try to Migrate ROOT Volume from ZWPS to Cluster wide Storage
+
+        destinationPool = GetDestinationPool(
+            self, [
+                root_volume_zone.storage], "CLUSTER")
+        MigrateRootVolume(
+            self,
+            vm_zone,
+            destinationPool)  # , expectexception=True)
+
+        vm_zone.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_root_zone,
+            "rootdiskdevice",
+            virt_machine=vm_zone,
+            disk=None,
+        )
+
+        checksum_random_data_zone = createChecksum(
+            self,
+            vm_zone,
+            data_volumes_zone_list[0],
+            "datadiskdevice_1")
+
+        vm_zone.stop(self.userapiclient)
+
+        # Migrate DATA Volume from ZWPS to other ZWPS
+        destinationPool = GetDestinationPool(
+            self,
+            [data_volumes_zone_list[0].storage],
+            "ZONE")
+        MigrateDataVolume(self, data_volumes_zone_list[0], destinationPool)
+
+        compareChecksum(
+            self,
+            checksum_random_data_zone,
+            "datadiskdevice_1",
+            virt_machine=None,
+            disk=data_volumes_zone_list[0],
+            new_vm=True)
+
+        vm_zone.stop(self.userapiclient)
+        # Try to Migrate DATA Volume from ZWPS to Local Storage
+        destinationPool = GetDestinationPool(
+            self, [
+                data_volume_zone.storage], "HOST")
+        MigrateDataVolume(
+            self,
+            data_volume_zone,
+            destinationPool,
+            expectexception=True)
+
+        # Try to Migrate DATA Volume from ZWPS to Cluster wide Storage
+        destinationPool = GetDestinationPool(
+            self, [
+                data_volume_zone.storage], "CLUSTER")
+        MigrateDataVolume(
+            self,
+            data_volume_zone,
+            destinationPool)
+
+        vm_zone.start(self.userapiclient)
+        compareChecksum(
+            self,
+            checksum_random_data_zone,
+            "datadiskdevice_1",
+            virt_machine=None,
+            disk=data_volumes_zone_list[0],
+            new_vm=True)
+
+        # Delete ROOT and DATA Volume from ZWPS
+
+        self.debug("Deleting Volume %s" % data_volume_zone.id)
+
+        vm_zone.detach_volume(self.apiclient, data_volume_zone)
+        # Delete volume
+        data_volume_zone.delete(self.apiclient)
+
+        self.assertEqual(
+            Volume.list(
+                self.apiclient,
+                id=data_volume_zone.id,
+            ), None, "Volume list should be empty")
+
+        # Destroy and expunge VM
+        vm_zone.delete(self.apiclient)
+
+        self.assertEqual(
+            VirtualMachine.list(
+                self.apiclient,
+                id=vm_zone.id
+            ), None, "VM list should be empty")
+
+        # Step 5
+        localStoragePoolsPresent = True
+        try:
+            self.assertEqual(
+                len(list(storagePool for storagePool in self.pools
+                         if storagePool.scope == "HOST")), 2)
+        except Exception as e:
+            localStoragePoolsPresent = False
+
+        if localStoragePoolsPresent:
+            # Create VM on local storage
+            vm_local = VirtualMachine.create(
+                self.userapiclient,
+                self.testdata["small"],
+                templateid=self.template.id,
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                serviceofferingid=self.service_offering_local1.id,
+                zoneid=self.zone.id,
+                mode=self.zone.networktype
+            )
+
+            # Get ROOT Volume id
+            root_volumes_local_list = list_volumes(
+                self.apiclient,
+                virtualmachineid=vm_local.id,
+                type='ROOT',
+                listall=True
+            )
+
+            root_volume_local = root_volumes_local_list[0]
+
+            # Create DATA Volume on local storage
+            data_volume_local = Volume.create(
+                self.apiclient,
+                self.testdata["volume"],
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.account.domainid,
+                diskofferingid=self.disk_offering_local1.id
+            )
+
+            self.debug("Created volume with ID: %s" % data_volume_local.id)
+
+            data_volumes_local_list = Volume.list(
+                self.userapiclient,
+                listall=self.testdata["listall"],
+                id=data_volume_local.id
+            )
+
+            vm_local.attach_volume(
+                self.userapiclient,
+                data_volume_local
+            )
+
+            # Step 6
+            # Migrate root and data volume from Local to another Local storage
+            checksum_random_root_local = createChecksum(
+                self,
+                vm_local,
+                data_volumes_local_list[0],
+                "rootdiskdevice")
+
+            vm_local.stop(self.userapiclient)
+
+            destinationPool = GetDestinationPool(
+                self, [
+                    root_volume_local.storage], "HOST")
+            MigrateRootVolume(self, vm_local, destinationPool)
+
+            vm_local.start(self.userapiclient)
+
+            compareChecksum(
+                self,
+                checksum_random_root_local,
+                "rootdiskdevice",
+                virt_machine=vm_cluster,
+                disk=None,
+            )
+
+            checksum_random_data_local = createChecksum(
+                self,
+                vm_local,
+                data_volumes_local_list[0],
+                "datadiskdevice_1")
+
+            vm_local.stop(self.userapiclient)
+            destinationPool = GetDestinationPool(
+                self,
+                [data_volumes_local_list[0].storage],
+                "HOST")
+            MigrateDataVolume(
+                self,
+                data_volumes_local_list[0],
+                destinationPool)
+
+            vm_local.start(self.userapiclient)
+            compareChecksum(
+                self,
+                checksum_random_data_local,
+                "datadiskdevice_1",
+                virt_machine=None,
+                disk=data_volumes_local_list[0],
+                new_vm=True)
+
+            # Delete ROOT and DATA Volume from Local Storage
+
+            self.debug("Deleting Volume %s" % data_volume_local.id)
+
+            vm_local.detach_volume(self.apiclient, data_volume_local)
+            # Delete volume
+            data_volume_local.delete(self.apiclient)
+
+            self.assertEqual(
+                Volume.list(
+                    self.apiclient,
+                    id=data_volume_local.id,
+                ), None, "Volumes list should be empty")
+
+            # Destroy and expunge VM
+            vm_local.delete(self.apiclient)
+
+            self.assertEqual(
+                VirtualMachine.list(
+                    self.apiclient,
+                    id=vm_local.id
+                ), None, "VM list should be empty")
+        return
+
+    @attr(tags=["advanced", "basic"])
+    def test_02_migration_nonlive_xenserver_supported(self):
+        """ Test migrate Volume (root and data disk) for Hypervisor Xenserver
+
+        # 1. Deploy a VM on cluster wide primary storage.
+        # 2. Migrate root and data volume from
+             cluster-to-cluster,cluster-to-local.
+        # 3. Deploy a VM on local storage.
+        # 4. Migrate root and data volume from local-to-local.
+
+        Each Migration has following steps:
+
+            a. Write data to disk, create checksum
+            b. Migrate the volume to suitable pool
+            c. Attach disk to VM and compare checksum with
+               checksum of data on disk, they should match
+
+        In addition to this,
+        Create snapshot of root and data disk after migration.
+        For root disk, create template from snapshot, deploy Vm and compare checksum
+        For data disk, Create volume from snapshot, attach to VM and compare checksum
+        """
+
+        # Check if Hypervisor is Xenserver
+        if self.hypervisor != "xenserver":
+            self.skipTest("This test case is written specifically for xenserver,\
+                    it does not include ZWPS scenarios")
+
+        try:
+            self.pools = StoragePool.list(self.apiclient, zoneid=self.zone.id)
+            assert len(list(storagePool for storagePool in self.pools
+                            if storagePool.scope == "CLUSTER")) >= 2,\
+                "There must be at least two cluster wide\
+                storage pools available in the setup"
+        except Exception as e:
+            self.skipTest(e)
+
+        # Adding tags to Storage Pools
+        cluster_no = 1
+        self.debug("Storage Pools: %s" % self.pools)
+        for storagePool in self.pools:
+            if storagePool.scope == "CLUSTER":
+                StoragePool.update(
+                    self.apiclient,
+                    id=storagePool.id,
+                    tags=['cwps' + repr(cluster_no)])
+                cluster_no += 1
+        # Create VM on CWPS
+        vm_cluster = VirtualMachine.create(
+            self.userapiclient,
+            self.testdata["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_cluster1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        # Get ROOT Volume Id
+        root_volumes_cluster_list = Volume.list(
+            self.apiclient,
+            virtualmachineid=vm_cluster.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_cluster = root_volumes_cluster_list[0]
+
+        data_volume_clust = Volume.create(
+            self.apiclient,
+            self.testdata["volume"],
+            zoneid=self.zone.id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            diskofferingid=self.disk_offering_cluster1.id
+        )
+
+        self.debug("Created volume with ID: %s" % data_volume_clust.id)
+
+        vm_cluster.attach_volume(
+            self.userapiclient,
+            data_volume_clust
+        )
+
+        data_volumes_cluster_list = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_volume_clust.id
+        )
+
+        root_vol_snap = Snapshot.create(
+            self.apiclient,
+            root_volume_cluster.id)
+
+        data_vol_snap = Snapshot.create(
+            self.apiclient,
+            data_volume_clust.id)
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            data_volume_clust)
+
+        # Migrate ROOT Volume from CWPS to other CWPS
+        checksum_random_root_cluster = createChecksum(
+            self,
+            vm_cluster,
+            root_volume_cluster,
+            "rootdiskdevice")
+
+        vm_cluster.stop(self.userapiclient)
+
+        destinationPool = GetDestinationPool(
+            self,
+            [root_volume_cluster.storage],
+            "CLUSTER")
+        MigrateRootVolume(self, vm_cluster, destinationPool)
+
+        vm_cluster.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_root_cluster,
+            "rootdiskdevice",
+            virt_machine=vm_cluster,
+            disk=None,
+        )
+        self.debug("Done with compare checksum after first checksum")
+
+        vm_cluster.start(self.userapiclient)
+
+        vm_cluster.attach_volume(
+            self.userapiclient,
+            data_volume_clust
+        )
+
+        vm_cluster.reboot(self.userapiclient)
+
+        checksum_random_data_cluster = createChecksum(
+            self,
+            vm_cluster,
+            data_volumes_cluster_list[0],
+            "datadiskdevice_1")
+
+        vm_cluster.stop(self.userapiclient)
+
+        # Migrate DATA Volume from CWPS to other CWPS
+        destinationPool = GetDestinationPool(
+            self,
+            [data_volumes_cluster_list[0].storage],
+            "CLUSTER")
+
+        MigrateDataVolume(self, data_volumes_cluster_list[0], destinationPool)
+
+        vm_cluster.start(self.userapiclient)
+
+        vm_cluster.detach_volume(self.apiclient, data_volumes_cluster_list[0])
+
+        compareChecksum(
+            self,
+            checksum_random_data_cluster,
+            "datadiskdevice_1",
+            virt_machine=None,
+            disk=data_volumes_cluster_list[0],
+            new_vm=True)
+
+        # snapshot test case t14 compare checksum for same VM
+        vm_cluster.attach_volume(
+            self.apiclient,
+            data_volumes_cluster_list[0]
+        )
+
+        vm_cluster.reboot(self.apiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_data_cluster,
+            "datadiskdevice_1",
+            virt_machine=vm_cluster,
+            disk=data_volumes_cluster_list[0]
+        )
+
+        # Add more data to disks
+        data_volume_clust_2 = Volume.create(
+            self.apiclient,
+            self.testdata["volume"],
+            zoneid=self.zone.id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            diskofferingid=self.disk_offering_cluster1.id
+        )
+
+        self.debug("Created volume with ID: %s" % data_volume_clust_2.id)
+
+        vm_cluster.attach_volume(
+            self.userapiclient,
+            data_volume_clust_2
+        )
+
+        data_disk_2_volumes_cluster_list = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_volume_clust_2.id
+        )
+
+        createChecksum(
+            self,
+            vm_cluster,
+            data_disk_2_volumes_cluster_list[0],
+            "datadiskdevice_2")
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            data_volume_clust_2
+        )
+
+        vm_cluster.stop(self.userapiclient)
+        # Try to Migrate ROOT Volume from CWPS to Local
+        destinationPool = GetDestinationPool(
+            self, [
+                root_volume_cluster.storage], "HOST")
+        MigrateRootVolume(
+            self,
+            vm_cluster,
+            destinationPool,
+            expectexception=True)
+
+        # Try to Migrate DATA Volume from CWPS to Local Storage
+        destinationPool = GetDestinationPool(
+            self,
+            [data_volumes_cluster_list[0].storage],
+            "HOST")
+        MigrateDataVolume(
+            self,
+            data_volumes_cluster_list[0],
+            destinationPool,
+            expectexception=True)
+
+        # Restore snapshot to preveous stage
+        # Convert root snap to template and boot vm from that n then check data
+        # Convert data snap to volume and attach it toa VM and then check data
+
+        templateFromSnapshot = Template.create_from_snapshot(
+            self.apiclient,
+            root_vol_snap,
+            self.testdata["template_2"])
+
+        vm_from_temp = VirtualMachine.create(
+            self.apiclient,
+            self.testdata["small"],
+            templateid=templateFromSnapshot.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_cluster1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        root_volumes_snap_list = Volume.list(
+            self.apiclient,
+            virtualmachineid=vm_from_temp.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_snap = root_volumes_snap_list[0]
+
+        createChecksum(
+            self,
+            vm_from_temp,
+            root_volume_snap,
+            "rootdiskdevice")
+
+        templateFromSnapshot.delete(self.apiclient)
+
+        volumeFormSnap = Volume.create_from_snapshot(
+            self.apiclient,
+            data_vol_snap.id,
+            self.testdata["volume"],
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=self.zone.id
+        )
+
+        vm_from_temp.attach_volume(
+            self.userapiclient,
+            volumeFormSnap
+        )
+
+        data_from_snap = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=volumeFormSnap.id
+        )
+
+        vm_from_temp.reboot(self.userapiclient)
+
+        createChecksum(
+            self,
+            vm_from_temp,
+            data_from_snap[0],
+            "datadiskdevice_1")
+
+        vm_from_temp.detach_volume(
+            self.userapiclient,
+            volumeFormSnap
+        )
+
+        volumeFormSnap.delete(self.apiclient)
+
+        vm_from_temp.delete(self.apiclient)
+
+        # Delete ROOT and DATA Volume from CWPS
+        self.debug("Deleting Volume %s" % data_volume_clust.id)
+
+        vm_cluster.detach_volume(self.apiclient, data_volume_clust)
+
+        # Delete volume:
+        data_volume_clust.delete(self.apiclient)
+
+        self.assertEqual(
+            Volume.list(
+                self.apiclient,
+                id=data_volume_clust.id,
+            ), None, "Volume list should be empty")
+
+        # Destroy and expunge VM
+        vm_cluster.delete(self.apiclient)
+
+        self.assertEqual(
+            VirtualMachine.list(
+                self.apiclient,
+                id=vm_cluster.id
+            ), None, "VM list should be empty")
+
+        localStoragePoolsAvailable = True
+        try:
+            self.assertEqual(
+                len(list(storagePool for storagePool in self.pools
+                         if storagePool.scope == "HOST")), 2)
+        except Exception as e:
+            localStoragePoolsAvailable = False
+
+        if localStoragePoolsAvailable:
+            # Create VM on local storage
+            vm_local = VirtualMachine.create(
+                self.userapiclient,
+                self.testdata["small"],
+                templateid=self.template.id,
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                serviceofferingid=self.service_offering_local1.id,
+                zoneid=self.zone.id,
+                mode=self.zone.networktype
+            )
+
+            # Get ROOT Volume id
+            root_volumes_local_list = Volume.list(
+                self.apiclient,
+                virtualmachineid=vm_local.id,
+                type='ROOT',
+                listall=True
+            )
+
+            root_volume_local = root_volumes_local_list[0]
+
+            # Create DATA Volume on local storage
+            data_volume_local = Volume.create(
+                self.apiclient,
+                self.testdata["volume"],
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.account.domainid,
+                diskofferingid=self.disk_offering_local1.id
+            )
+
+            self.debug("Created volume with ID: %s" % data_volume_local.id)
+
+            data_volumes_local_list = Volume.list(
+                self.userapiclient,
+                listall=self.testdata["listall"],
+                id=data_volume_local.id
+            )
+
+            vm_local.attach_volume(
+                self.userapiclient,
+                data_volume_local
+            )
+
+            vm_local.reboot(self.userapiclient)
+
+            createChecksum(
+                self,
+                vm_local,
+                root_volume_local,
+                "rootdiskdevice")
+
+            vm_local.stop(self.userapiclient)
+
+            # Migrate root and data volume from Local to another Local storage
+            destinationPool = GetDestinationPool(
+                self, [
+                    root_volume_local.storage], "HOST")
+            MigrateRootVolume(
+                self,
+                vm_local,
+                destinationPool,
+                expectexception=True)
+
+            vm_local.detach_volume(self.apiclient, data_volume_local)
+
+            destinationPool = GetDestinationPool(
+                self,
+                [data_volumes_local_list[0].storage],
+                "HOST")
+            MigrateDataVolume(
+                self,
+                data_volumes_local_list[0],
+                destinationPool,
+                expectexception=True)
+
+            # Delete ROOT and DATA Volume from Local Storage
+
+            self.debug("Deleting Volume %s" % data_volume_local.id)
+
+            # Delete volume
+            data_volume_local.delete(self.apiclient)
+
+            self.assertEqual(
+                Volume.list(
+                    self.apiclient,
+                    id=data_volume_local.id,
+                ), None, "Volumes list should be empty")
+
+            # Destroy and expunge VM
+            vm_local.delete(self.apiclient)
+
+            self.assertEqual(
+                VirtualMachine.list(
+                    self.apiclient,
+                    id=vm_local.id
+                ), None, "VM list should be empty")
+
+        return
+
+    @attr(tags=["advanced", "basic"])
+    def test_03_migrate_root_and_data_disk_nonlive_cwps_vmware(self):
+        """ Test migrate Volume (root and data disk)
+
+        # 1. Deploy a VM on cluster wide primary storage.
+        # 2. Migrate root and data volume from cluster-to-cluster
+        # 3. Deploy a VM on local storage.
+        # 4. Migrate root and data volume from local-to-local.
+
+        Each Migration has following steps:
+
+            a. Write data to disk, create checksum
+            b. Migrate the volume to suitable pool
+            c. Attach disk to VM and compare checksum with
+               checksum of data on disk, they should match
+
+        In addition to this,
+        Create snapshot of root and data disk after migration.
+        For root disk, create template from snapshot, deploy Vm and compare checksum
+        For data disk, Create volume from snapshot, attach to VM and compare checksum
+
+        """
+        # Test case only written for Vmware hypervisor as it
+        # does not run CWPS and ZWPS scenatios together
+        if self.hypervisor is not "vmware":
+            self.skipTest("Skip test case for %s" % self.hypervisor)
+
+        try:
+            self.pools = StoragePool.list(self.apiclient, zoneid=self.zone.id)
+            assert len(list(storagePool for storagePool in self.pools
+                            if storagePool.scope == "CLUSTER")) >= 2,\
+                "There must be at least two cluster wide\
+                storage pools available in the setup"
+        except Exception as e:
+            self.skipTest(e)
+
+        # Adding tags to Storage Pools
+        cluster_no = 1
+        self.debug("Storage Pools: %s" % self.pools)
+        for storagePool in self.pools:
+            if storagePool.scope == "CLUSTER":
+                StoragePool.update(
+                    self.apiclient,
+                    id=storagePool.id,
+                    tags=['cwps' + repr(cluster_no)])
+                cluster_no += 1
+
+        # Step 1
+        # Create VM on CWPS
+        vm_cluster = VirtualMachine.create(
+            self.userapiclient,
+            self.testdata["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_cluster1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        # Get ROOT Volume Id
+        root_volumes_cluster_list = list_volumes(
+            self.apiclient,
+            virtualmachineid=vm_cluster.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_cluster = root_volumes_cluster_list[0]
+
+        # Create DATA Volume on Cluster Wide Storage
+        data_volume_clust = Volume.create(
+            self.apiclient,
+            self.testdata["volume"],
+            zoneid=self.zone.id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            diskofferingid=self.disk_offering_cluster1.id
+        )
+
+        self.debug("Created volume with ID: %s" % data_volume_clust.id)
+
+        vm_cluster.attach_volume(
+            self.userapiclient,
+            data_volume_clust
+        )
+
+        data_volumes_cluster_list = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_volume_clust.id
+        )
+
+        root_vol_snap = Snapshot.create(
+            self.apiclient,
+            root_volume_cluster.id)
+
+        data_vol_snap = Snapshot.create(
+            self.apiclient,
+            data_volume_clust.id)
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            data_volume_clust)
+
+        # Step 2
+        # Migrate ROOT Volume from CWPS to other CWPS
+        checksum_random_root_cluster = createChecksum(
+            self,
+            vm_cluster,
+            root_volume_cluster,
+            "rootdiskdevice")
+
+        vm_cluster.stop(self.userapiclient)
+
+        destinationPool = GetDestinationPool(
+            self,
+            [root_volume_cluster.storage],
+            "CLUSTER")
+        MigrateRootVolume(self, vm_cluster, destinationPool)
+
+        vm_cluster.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_root_cluster,
+            "rootdiskdevice",
+            virt_machine=vm_cluster,
+            disk=None,
+        )
+        self.debug("Done with compare checksum")
+
+        vm_cluster.start(self.userapiclient)
+        checksum_random_data_cluster = createChecksum(
+            self,
+            vm_cluster,
+            data_volumes_cluster_list[0],
+            "datadiskdevice_1")
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            data_volumes_cluster_list[0]
+        )
+
+        vm_cluster.stop(self.userapiclient)
+
+        # Migrate DATA Volume from CWPS to other CWPS
+        destinationPool = GetDestinationPool(
+            self,
+            [data_volumes_cluster_list[0].storage],
+            "CLUSTER")
+        MigrateDataVolume(
+            self,
+            data_volumes_cluster_list[0],
+            destinationPool)
+
+        vm_cluster.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_data_cluster,
+            "datadiskdevice_1",
+            virt_machine=None,
+            disk=data_volumes_cluster_list[0],
+            new_vm=True)
+
+        # snapshot test case t14 compare checksum for same VM
+        vm_cluster.attach_volume(
+            self.apiclient,
+            data_volumes_cluster_list[0]
+        )
+
+        vm_cluster.reboot(self.apiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_data_cluster,
+            "datadiskdevice_1",
+            virt_machine=vm_cluster,
+            disk=data_volumes_cluster_list[0]
+        )
+
+        # Add more data to disks
+        data_volume_clust_2 = Volume.create(
+            self.apiclient,
+            self.testdata["volume"],
+            zoneid=self.zone.id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            diskofferingid=self.disk_offering_cluster1.id
+        )
+
+        self.debug("Created volume with ID: %s" % data_volume_clust_2.id)
+
+        vm_cluster.attach_volume(
+            self.userapiclient,
+            data_volume_clust_2
+        )
+
+        data_disk_2_volumes_cluster_list = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_volume_clust_2.id
+        )
+
+        createChecksum(
+            self,
+            vm_cluster,
+            data_disk_2_volumes_cluster_list[0],
+            "datadiskdevice_2")
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            data_volume_clust_2
+        )
+
+        templateFromSnapshot = Template.create_from_snapshot(
+            self.apiclient,
+            root_vol_snap,
+            self.testdata["template_2"])
+
+        vm_from_temp = VirtualMachine.create(
+            self.apiclient,
+            self.testdata["small"],
+            templateid=templateFromSnapshot.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_cluster1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        root_volumes_snap_list = Volume.list(
+            self.apiclient,
+            virtualmachineid=vm_from_temp.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_snap = root_volumes_snap_list[0]
+
+        createChecksum(
+            self,
+            vm_from_temp,
+            root_volume_snap,
+            "rootdiskdevice")
+
+        templateFromSnapshot.delete(self.apiclient)
+
+        volumeFormSnap = Volume.create_from_snapshot(
+            self.apiclient,
+            data_vol_snap.id,
+            self.testdata["volume"],
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=self.zone.id
+        )
+
+        vm_from_temp.attach_volume(
+            self.userapiclient,
+            volumeFormSnap
+        )
+
+        data_from_snap = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=volumeFormSnap.id
+        )
+
+        vm_from_temp.reboot(self.userapiclient)
+
+        createChecksum(
+            self,
+            vm_from_temp,
+            data_from_snap[0],
+            "datadiskdevice_1")
+
+        vm_from_temp.detach_volume(
+            self.userapiclient,
+            volumeFormSnap
+        )
+
+        volumeFormSnap.delete(self.apiclient)
+
+        vm_from_temp.delete(self.apiclient)
+
+        # Delete ROOT and DATA Volume from CWPS
+        self.debug("Deleting Volume %s" % data_volume_clust.id)
+
+        vm_cluster.detach_volume(self.apiclient, data_volume_clust)
+
+        # Delete volume:
+        data_volume_clust.delete(self.apiclient)
+
+        self.assertEqual(
+            Volume.list(
+                self.apiclient,
+                id=data_volume_clust.id,
+            ), None, "Volume list should be empty")
+
+        # Destroy and expunge VM
+        vm_cluster.delete(self.apiclient)
+
+        self.assertEqual(
+            VirtualMachine.list(
+                self.apiclient,
+                id=vm_cluster.id
+            ), None, "VM list should be empty")
+
+        localStoragePoolsPresent = True
+        # Step 5
+        try:
+            self.assertEqual(
+                len(list(storagePool for storagePool in self.pools
+                         if storagePool.scope == "HOST")), 2)
+        except Exception as e:
+            localStoragePoolsPresent = False
+
+        if localStoragePoolsPresent:
+            # Create VM on local storage
+            vm_local = VirtualMachine.create(
+                self.userapiclient,
+                self.testdata["small"],
+                templateid=self.template.id,
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                serviceofferingid=self.service_offering_local1.id,
+                zoneid=self.zone.id,
+                mode=self.zone.networktype
+            )
+
+            # Get ROOT Volume id
+            root_volumes_local_list = list_volumes(
+                self.apiclient,
+                virtualmachineid=vm_local.id,
+                type='ROOT',
+                listall=True
+            )
+
+            root_volume_local = root_volumes_local_list[0]
+
+            # Create DATA Volume on local storage
+            data_volume_local = Volume.create(
+                self.apiclient,
+                self.testdata["volume"],
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.account.domainid,
+                diskofferingid=self.disk_offering_local1.id
+            )
+
+            self.debug("Created volume with ID: %s" % data_volume_local.id)
+
+            data_volumes_local_list = Volume.list(
+                self.userapiclient,
+                listall=self.testdata["listall"],
+                id=data_volume_local.id
+            )
+
+            vm_local.attach_volume(
+                self.userapiclient,
+                data_volume_local
+            )
+
+            # Step 6
+            # Migrate root and data volume from Local to another Local storage
+            checksum_random_root_local = createChecksum(
+                self,
+                vm_local,
+                data_volumes_local_list[0],
+                "rootdiskdevice")
+
+            vm_local.stop(self.userapiclient)
+
+            destinationPool = GetDestinationPool(
+                self, [
+                    root_volume_local.storage], "HOST")
+            MigrateRootVolume(self, vm_local, destinationPool)
+
+            vm_local.start(self.userapiclient)
+
+            compareChecksum(
+                self,
+                checksum_random_root_local,
+                "rootdiskdevice",
+                virt_machine=vm_cluster,
+                disk=None,
+            )
+
+            checksum_random_data_local = createChecksum(
+                self,
+                vm_local,
+                data_volumes_local_list[0],
+                "datadiskdevice_1")
+
+            vm_local.stop(self.userapiclient)
+            destinationPool = GetDestinationPool(
+                self,
+                [data_volumes_local_list[0].storage],
+                "HOST")
+            MigrateDataVolume(
+                self,
+                data_volumes_local_list[0],
+                destinationPool)
+
+            vm_local.start(self.userapiclient)
+            compareChecksum(
+                self,
+                checksum_random_data_local,
+                "datadiskdevice_1",
+                virt_machine=None,
+                disk=data_volumes_local_list[0],
+                new_vm=True)
+
+            # Delete ROOT and DATA Volume from Local Storage
+
+            self.debug("Deleting Volume %s" % data_volume_local.id)
+
+            vm_local.detach_volume(self.apiclient, data_volume_local)
+            # Delete volume
+            data_volume_local.delete(self.apiclient)
+
+            self.assertEqual(
+                Volume.list(
+                    self.apiclient,
+                    id=data_volume_local.id,
+                ), None, "Volumes list should be empty")
+
+            # Destroy and expunge VM
+            vm_local.delete(self.apiclient)
+
+            self.assertEqual(
+                VirtualMachine.list(
+                    self.apiclient,
+                    id=vm_local.id
+                ), None, "VM list should be empty")
+        return
+
+    @attr(tags=["advanced", "basic"])
+    def test_04_migrate_root_and_data_disk_nonlive_zwps_vmware(self):
+        """ Test migrate Volume (root and data disk)
+
+        # 1. Deploy a VM on zone wide primary storage..
+        # 2. Migrate root and data volume from zone-to-zone, zone-to-local.
+
+        Each Migration has following steps:
+
+            a. Write data to disk, create checksum
+            b. Migrate the volume to suitable pool
+            c. Attach disk to VM and compare checksum with
+               checksum of data on disk, they should match
+
+        """
+        # Test case only written for Vmware hypervisor as it
+        # does not run CWPS and ZWPS scenatios together
+        if self.hypervisor is not "vmware":
+            self.skipTest("Skip test case for %s" % self.hypervisor)
+
+        try:
+            self.pools = StoragePool.list(self.apiclient, zoneid=self.zone.id)
+            assert len(list(storagePool for storagePool in self.pools
+                            if storagePool.scope == "ZONE")) >= 2,\
+                "There must be at least two zone wide\
+                storage pools available in the setup"
+        except Exception as e:
+            self.skipTest(e)
+
+        # Adding tags to Storage Pools
+        zone_no = 1
+        self.debug("Storage Pools: %s" % self.pools)
+        for storagePool in self.pools:
+            if storagePool.scope == "ZONE":
+                StoragePool.update(
+                    self.apiclient,
+                    id=storagePool.id,
+                    tags=['zwps' + repr(zone_no)])
+                zone_no += 1
+
+        # Step 3
+        # Create VM on ZWPS
+        vm_zone = VirtualMachine.create(
+            self.userapiclient,
+            self.testdata["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_zone1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        vm_zone.start(self.userapiclient)
+
+        # Get ROOT Volume Id
+        root_volumes_zone_list = list_volumes(
+            self.apiclient,
+            virtualmachineid=vm_zone.id,
+            type='ROOT',
+            listall=True
+        )
+        root_volume_zone = root_volumes_zone_list[0]
+
+        # Create DATA Volume on ZWPS
+        data_volume_zone = Volume.create(
+            self.apiclient,
+            self.testdata["volume"],
+            zoneid=self.zone.id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            diskofferingid=self.disk_offering_zone1.id
+        )
+
+        self.debug("Created volume with ID: %s" % data_volume_zone.id)
+
+        data_volumes_zone_list = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_volume_zone.id
+        )
+
+        vm_zone.attach_volume(
+            self.userapiclient,
+            data_volume_zone
+        )
+
+        # Step 4
+        # Migrate ROOT Volume from ZWPS to other ZWPS
+        checksum_random_root_zone = createChecksum(
+            self,
+            vm_zone,
+            data_volumes_zone_list[0],
+            "rootdiskdevice")
+
+        vm_zone.stop(self.userapiclient)
+
+        destinationPool = GetDestinationPool(
+            self, [
+                root_volume_zone.storage], "ZONE")
+        MigrateRootVolume(self, vm_zone, destinationPool)
+
+        vm_zone.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_root_zone,
+            "rootdiskdevice",
+            virt_machine=vm_zone,
+            disk=None,
+        )
+        vm_zone.start(self.userapiclient)
+
+        compareChecksum(
+            self,
+            checksum_random_root_zone,
+            "rootdiskdevice",
+            virt_machine=vm_zone,
+            disk=None,
+        )
+
+        checksum_random_data_zone = createChecksum(
+            self,
+            vm_zone,
+            data_volumes_zone_list[0],
+            "datadiskdevice_1")
+
+        vm_zone.stop(self.userapiclient)
+
+        # Migrate DATA Volume from ZWPS to other ZWPS
+        destinationPool = GetDestinationPool(
+            self,
+            [data_volumes_zone_list[0].storage],
+            "ZONE")
+        MigrateDataVolume(self, data_volumes_zone_list[0], destinationPool)
+
+        compareChecksum(
+            self,
+            checksum_random_data_zone,
+            "datadiskdevice_1",
+            virt_machine=None,
+            disk=data_volumes_zone_list[0],
+            new_vm=True)
+
+        # Delete ROOT and DATA Volume from ZWPS
+        self.debug("Deleting Volume %s" % data_volume_zone.id)
+
+        vm_zone.detach_volume(self.apiclient, data_volume_zone)
+        # Delete volume
+        data_volume_zone.delete(self.apiclient)
+
+        self.assertEqual(
+            Volume.list(
+                self.apiclient,
+                id=data_volume_zone.id,
+            ), None, "Volume list should be empty")
+
+        # Destroy and expunge VM
+        vm_zone.delete(self.apiclient)
+
+        self.assertEqual(
+            VirtualMachine.list(
+                self.apiclient,
+                id=vm_zone.id
+            ), None, "VM list should be empty")
+        return
+
+
+class NegativeTestStorageMigration(cloudstackTestCase):
+
+    exceptionList = []
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(
+            NegativeTestStorageMigration,
+            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)
+
+        try:
+            cls.pools = StoragePool.list(cls.apiclient, zoneid=cls.zone.id)
+            assert len(list(storagePool for storagePool in cls.pools
+                            if storagePool.scope == "ZONE")) >= 2,\
+                "There must be at least two zone wide\
+                storage pools available in the setup"
+            assert len(list(storagePool for storagePool in cls.pools
+                            if storagePool.scope == "CLUSTER")) >= 2,\
+                "There must be at least two cluster wide\
+                storage pools available in the setup"
+        except Exception as e:
+            raise unittest.SkipTest(e)
+        try:
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.testdata["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering_zone1 = ServiceOffering.create(
+                cls.apiclient,
+                cls.testdata["service_offering"],
+                tags=ZONETAG1
+            )
+            cls._cleanup.append(cls.service_offering_zone1)
+
+            cls.service_offering_cluster1 = ServiceOffering.create(
+                cls.apiclient,
+                cls.testdata["service_offering"],
+                tags=CLUSTERTAG1
+            )
+            cls._cleanup.append(cls.service_offering_cluster1)
+
+            # If local storage is enabled, alter the offerings to use
+            # localstorage
+            if cls.zone.localstorageenabled:
+                cls.testdata["service_offering"]["storagetype"] = 'local'
+
+                cls.service_offering_local1 = ServiceOffering.create(
+                    cls.apiclient,
+                    cls.testdata["service_offering"]
+                )
+                cls._cleanup.append(cls.service_offering_local1)
+
+            # Create Disk offering
+            cls.disk_offering_zone1 = DiskOffering.create(
+                cls.apiclient,
+                cls.testdata["disk_offering"],
+                tags=ZONETAG1
+            )
+            cls._cleanup.append(cls.disk_offering_zone1)
+
+            cls.disk_offering_cluster1 = DiskOffering.create(
+                cls.apiclient,
+                cls.testdata["disk_offering"],
+                tags=CLUSTERTAG1
+            )
+            cls._cleanup.append(cls.disk_offering_cluster1)
+
+            # If local storage is enabled, alter the offerings to use
+            # localstorage
+            if cls.zone.localstorageenabled:
+                cls.testdata["disk_offering"]["storagetype"] = 'local'
+
+                cls.disk_offering_local1 = DiskOffering.create(
+                    cls.apiclient,
+                    cls.testdata["disk_offering"]
+                )
+                cls._cleanup.append(cls.disk_offering_local1)
+        except Exception as e:
+            cls.tearDownClass()
+            raise e
+        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 createMigrationJob(self, volume):
+        try:
+            destinationPool = None
+            for storagePool in self.pools:
+                if storagePool.scope == "CLUSTER":
+                    if storagePool.name != volume.storage:
+                        destinationPool = storagePool
+                        break
+
+            with self.assertRaises(Exception):
+                Volume.migrate(
+                    self.apiclient,
+                    volumeid=volume.id,
+                    storageid=destinationPool.id,
+                    livemigrate='false'
+                )
+        except Exception as e:
+            self.exceptionList.append(e)
+
+    def createTemplateJob(self, virtual_machine, root_volume):
+        try:
+            services = {"displaytext": "templ",
+                        "name": "vol_template",
+                        "ostypeid": virtual_machine.ostypeid}
+            with self.assertRaises(Exception):
+                Template.create(self.apiclient,
+                                services,
+                                volumeid=root_volume.id
+                                )
+
+        except Exception as e:
+            self.exceptionList.append(e)
+
+    def createDestroyVmJob(self, virtual_machine):
+        try:
+            with self.assertRaises(Exception):
+                virtual_machine.delete(self.apiclient)
+
+        except Exception as e:
+            self.exceptionList.append(e)
+
+    @attr(tags=["advanced", "basic"])
+    def test_01_migrate_data_disk_negative_test(self):
+        """ Negative test cases
+
+        # 1. Deploy a VM on cluster wide primary storage.
+        # 2. Add some data to disks and create checksum
+        # 3. Migrate root and data volume from cluster-to-cluster wide storage pool
+        # 4. While migration(ROOT disk) is in progress try following scenarios, they should fail:
+             I. Take snapshot of the disk
+             II. Create Template from the volume
+             III. Destroy the instance
+        # 5. Compare checksum after migration
+
+        """
+        # Adding tags to Storage Pools
+        cluster_no = 1
+        self.debug("Storage Pools: %s" % self.pools)
+        for storagePool in self.pools:
+            if storagePool.scope == "CLUSTER":
+                StoragePool.update(
+                    self.apiclient,
+                    id=storagePool.id,
+                    tags=['cwps' + repr(cluster_no)])
+                cluster_no += 1
+
+        # Step 1
+        # Create VM on CWPS
+        vm_cluster = VirtualMachine.create(
+            self.userapiclient,
+            self.testdata["small"],
+            templateid=self.template.id,
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.service_offering_cluster1.id,
+            diskofferingid=self.disk_offering_cluster1.id,
+            zoneid=self.zone.id,
+            mode=self.zone.networktype
+        )
+
+        # Get ROOT Volume Id
+        disk_volumes_cluster_list = list_volumes(
+            self.apiclient,
+            virtualmachineid=vm_cluster.id,
+            type='DATADISK',
+            listall=True
+        )
+
+        data_disk = disk_volumes_cluster_list[0]
+
+        root_volumes_cluster_list = list_volumes(
+            self.apiclient,
+            virtualmachineid=vm_cluster.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_cluster = root_volumes_cluster_list[0]
+
+        # Step 2
+        # Calculate checksum of ROOT and DATA Disks
+
+        checksum_root_disk = self.createChecksum(
+            self,
+            vm_cluster,
+            root_volume_cluster,
+            "rootdiskdevice")
+
+        checksum_data_disk = self.createChecksum(
+            self,
+            vm_cluster,
+            data_disk,
+            "datadiskdevice_1")
+
+        volumes = Volume.list(
+            self.userapiclient,
+            listall=self.testdata["listall"],
+            id=data_disk.id
+        )
+
+        self.assertEqual(
+            isinstance(volumes, list),
+            True,
+            "Check list response returns a valid list"
+        )
+
+        volume = volumes[0]
+
+        vm_cluster.detach_volume(
+            self.apiclient,
+            volume
+        )
+
+        vm_cluster.stop(self.userapiclient)
+
+        try:
+            destinationPool = GetDestinationPool(
+                self,
+                [root_volume_cluster.storage],
+                "CLUSTER")
+            thread_1 = Thread(
+                target=MigrateRootVolume,
+                args=(
+                    self,
+                    vm_cluster,
+                    destinationPool,
+                ))
+            thread_2 = Thread(
+                target=self.createTemplateJob,
+                args=(
+                    vm_cluster,
+                    root_volume_cluster,
+                ))
+            thread_1.start()
+            thread_2.start()
+            thread_1.join()
+            thread_2.join()
+        except:
+            self.debug("Error: unable to start thread")
+
+        try:
+            destinationPool = GetDestinationPool(
+                self,
+                [root_volume_cluster.storage],
+                "CLUSTER")
+            thread_3 = Thread(
+                target=MigrateRootVolume,
+                args=(
+                    self,
+                    vm_cluster,
+                    destinationPool,
+                ))
+            thread_4 = Thread(
+                target=self.createMigrationJob,
+                args=(
+                    root_volume_cluster,
+                ))
+            thread_3.start()
+            timeout = 60
+            while timeout >= 0:
+                if volume.state == "Migrating":
+                    break
+                timeout -= 5
+                time.sleep(5)
+            thread_4.start()
+            thread_3.join()
+            thread_4.join()
+        except:
+            self.debug("Error: unable to start thread")
+
+        vm_cluster.start(self.userapiclient)
+
+        vm_cluster.attach_volume(
+            self.apiclient,
+            volume
+        )
+
+        vm_cluster.reboot(self.userapiclient)
+
+        disk_volumes_cluster_list = list_volumes(
+            self.apiclient,
+            virtualmachineid=vm_cluster.id,
+            type='DATADISK',
+            listall=True
+        )
+
+        data_disk = disk_volumes_cluster_list[0]
+
+        root_volumes_cluster_list = list_volumes(
+            self.apiclient,
+            virtualmachineid=vm_cluster.id,
+            type='ROOT',
+            listall=True
+        )
+
+        root_volume_cluster = root_volumes_cluster_list[0]
+
+        self.debug("Done with create checksum")
+
+        compareChecksum(
+            self,
+            checksum_root_disk,
+            "rootdiskdevice",
+            virt_machine=vm_cluster
+        )
+
+        compareChecksum(
+            self,
+            checksum_data_disk,
+            "datadiskdevice_1",
+            virt_machine=vm_cluster
+        )
+
+        vm_cluster.detach_volume(
+            self.userapiclient,
+            volume
+        )
+
+        cmd = deleteVolume.deleteVolumeCmd()
+        cmd.id = volume.id
+        self.apiclient.deleteVolume(cmd)
+
+        vm_cluster.stop(self.userapiclient)
+
+        try:
+            destinationPool = GetDestinationPool(
+                self,
+                [root_volume_cluster.storage],
+                "CLUSTER")
+            thread_5 = Thread(
+                target=MigrateRootVolume,
+                args=(
+                    self,
+                    vm_cluster,
+                    destinationPool,
+                ))
+            thread_6 = Thread(
+                target=self.createDestroyVmJob,
+                args=(
+                    vm_cluster,
+                ))
+            thread_5.start()
+            thread_6.start()
+            thread_5.join()
+            thread_6.join()
+        except:
+            self.debug("Error: unable to start thread")
+
+        # Raise exception if there was any exception raised from the threads
+        if self.exceptionList:
+            for i in self.exceptionList:
+                raise(i)
+
+        vm_cluster.delete(self.apiclient)
+        return
+
+
+class TestLiveStorageMigration(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        testClient = super(TestLiveStorageMigration, 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() in ["kvm", "lxc"]:
+            raise unittest.SkipTest(
+                "Live Storage migration not supported on %s" %
+                cls.hypervisor)
+
+        try:
+            cls.pools = StoragePool.list(cls.apiclient, zoneid=cls.zone.id)
+        except Exception as e:
+            raise unittest.SkipTest(e)
+        try:
+
+            # Create an account
+            cls.account = Account.create(
+                cls.apiclient,
+                cls.testdata["account"],
+                domainid=cls.domain.id
+            )
+            cls._cleanup.append(cls.account)
+
+            # Create user api client of the account
+            cls.userapiclient = testClient.getUserApiClient(
+                UserName=cls.account.name,
+                DomainName=cls.account.domain
+            )
+            # Create Service offering
+            cls.service_offering_zone1 = ServiceOffering.create(
+                cls.apiclient,
+                cls.testdata["service_offering"],
+                tags=ZONETAG1
+            )
+            cls._cleanup.append(cls.service_offering_zone1)
+
+            cls.service_offering_cluster1 = ServiceOffering.create(
+                cls.apiclient,
+                cls.testdata["service_offering"],
+                tags=CLUSTERTAG1
+            )
+            cls._cleanup.append(cls.service_offering_cluster1)
+
+            # If local storage is enabled, alter the offerings to use
+            # localstorage
+            if cls.zone.localstorageenabled:
+                cls.testdata["service_offering"]["storagetype"] = 'local'
+
+                cls.service_offering_local1 = ServiceOffering.create(
+                    cls.apiclient,
+                    cls.testdata["service_offering"]
+                )
+                cls._cleanup.append(cls.service_offering_local1)
+
+            # Create Disk offering
+            cls.disk_offering_zone1 = DiskOffering.create(
+                cls.apiclient,
+                cls.testdata["disk_offering"],

<TRUNCATED>