示例#1
0
    def copy_disk(self, source_datastore, source_id, dest_datastore, dest_id):
        """Copy a virtual disk.

        This method is used to create a "full clone" of a vmdk.
        Underneath, this call boils down to doing a DiskLib_Clone()

        Command line equivalent:
          $ vmkfstools -i source dest

        """
        source = vmdk_path(source_datastore, source_id, IMAGE_FOLDER_NAME_PREFIX)
        dest = vmdk_path(dest_datastore, dest_id)
        self._vmdk_mkdir(dest_datastore, dest_id)
        self._host_client.copy_disk(source, dest)
        self._host_client.set_disk_uuid(dest, dest_id)
    def test_find_virtual_disk(self):
        spec = self._update_spec()
        devices = self.dummy_devices()
        for device in devices:
            spec._add_device(device)
        cfg_info = FakeConfigInfo(devices)
        device_type = vim.vm.device.VirtualDisk
        datastore = "ds1"
        filename = "folder/foo"
        path = vmdk_path(datastore, filename)

        disks = spec._get_devices_by_type(cfg_info, device_type)
        assert_that(len(disks), equal_to(0))

        spec.attach_disk(cfg_info, path)

        disks = spec._get_devices_by_type(cfg_info, device_type)
        assert_that(len(disks), equal_to(0))

        device_changes = spec.get_spec().deviceChange
        device_list = []
        for device_change in device_changes:
            device_list.append(device_change.device)

        disks = spec._get_devices_by_type(FakeConfigInfo(device_list), device_type)
        assert_that(len(disks), equal_to(1))
        assert_that(disks[0].backing.fileName, equal_to(path))
    def copy_disk(self, source_datastore, source_id, dest_datastore, dest_id):
        """Copy a virtual disk.

        This method is used to create a "full clone" of a vmdk.
        Underneath, this call boils down to doing a DiskLib_Clone()

        Command line equivalent:
          $ vmkfstools -i source dest

        """
        source = vmdk_path(source_datastore, source_id,
                           IMAGE_FOLDER_NAME_PREFIX)
        dest = vmdk_path(dest_datastore, dest_id)
        self._vmdk_mkdir(dest_datastore, dest_id)
        self._host_client.copy_disk(source, dest)
        self._host_client.set_disk_uuid(dest, dest_id)
    def test_find_virtual_disk(self):
        spec = self._update_spec()
        devices = self.dummy_devices()
        for device in devices:
            spec._add_device(device)
        cfg_info = FakeConfigInfo(devices)
        device_type = vim.vm.device.VirtualDisk
        datastore = "ds1"
        filename = "folder/foo"
        path = vmdk_path(datastore, filename)

        disks = spec._get_devices_by_type(cfg_info, device_type)
        assert_that(len(disks), equal_to(0))

        spec.attach_disk(cfg_info, path)

        disks = spec._get_devices_by_type(cfg_info, device_type)
        assert_that(len(disks), equal_to(0))

        device_changes = spec.get_spec().deviceChange
        device_list = []
        for device_change in device_changes:
            device_list.append(device_change.device)

        disks = spec._get_devices_by_type(FakeConfigInfo(device_list),
                                          device_type)
        assert_that(len(disks), equal_to(1))
        assert_that(disks[0].backing.fileName, equal_to(path))
    def test_finalize_image(self):
        """ Integration test for atomic image create """
        img_id = "test-create-image"
        tmp_img_id = "-tmp-" + img_id
        tmp_image, ds = self._create_test_image(tmp_img_id)
        tmp_image_path = datastore_path(ds.name, "image_" + tmp_img_id)
        src_vmdk = vmdk_path(ds.id, tmp_img_id, IMAGE_FOLDER_NAME_PREFIX)
        dst_vmdk = "%s/%s.vmdk" % (tmp_image_path, img_id)

        try:
            self._manage_disk(
                vim.VirtualDiskManager.MoveVirtualDisk_Task,
                sourceName=src_vmdk, destName=dst_vmdk, force=True)
        except:
            logger.error("Error moving vmdk %s" % src_vmdk,
                         exc_info=True)
            self._manage_disk(
                vim.VirtualDiskManager.DeleteVirtualDisk_Task,
                name=src_vmdk)
            raise
        dst_image = Image(img_id, ds)
        req = FinalizeImageRequest(image_id=img_id,
                                   datastore=ds.id,
                                   tmp_image_path=tmp_image_path)
        response = self.host_client.finalize_image(req)
        self.assertEqual(response.result, FinalizeImageResultCode.OK)
        request = Host.GetImagesRequest(ds.id)
        response = self.host_client.get_images(request)
        assert_that(response.result, is_(GetImagesResultCode.OK))
        assert_that(response.image_ids, has_item(img_id))

        # Issue another create call and it should fail as the source doesn't
        # exist.
        req = FinalizeImageRequest(image_id=img_id,
                                   datastore=ds.id,
                                   tmp_image_path=tmp_image_path)
        response = self.host_client.finalize_image(req)
        self.assertEqual(response.result,
                         FinalizeImageResultCode.IMAGE_NOT_FOUND)

        # Verify that we fail if the destination already exists.
        tmp_image, ds = self._create_test_image(tmp_img_id)
        req = FinalizeImageRequest(image_id=img_id,
                                   datastore=ds.id,
                                   tmp_image_path=tmp_image_path)
        response = self.host_client.finalize_image(req)
        self.assertEqual(response.result,
                         FinalizeImageResultCode.DESTINATION_ALREADY_EXIST)

        # cleanup
        self._delete_image(dst_image)
    def test_finalize_image(self):
        """ Integration test for atomic image create """
        img_id = "test-create-image"
        tmp_img_id = "-tmp-" + img_id
        tmp_image, ds = self._create_test_image(tmp_img_id)
        tmp_image_path = datastore_path(ds.name, "image_" + tmp_img_id)
        src_vmdk = vmdk_path(ds.id, tmp_img_id, IMAGE_FOLDER_NAME_PREFIX)
        dst_vmdk = "%s/%s.vmdk" % (tmp_image_path, img_id)

        try:
            self._manage_disk(vim.VirtualDiskManager.MoveVirtualDisk_Task,
                              sourceName=src_vmdk,
                              destName=dst_vmdk,
                              force=True)
        except:
            logger.error("Error moving vmdk %s" % src_vmdk, exc_info=True)
            self._manage_disk(vim.VirtualDiskManager.DeleteVirtualDisk_Task,
                              name=src_vmdk)
            raise
        dst_image = Image(img_id, ds)
        req = FinalizeImageRequest(image_id=img_id,
                                   datastore=ds.id,
                                   tmp_image_path=tmp_image_path)
        response = self.host_client.finalize_image(req)
        self.assertEqual(response.result, FinalizeImageResultCode.OK)
        request = Host.GetImagesRequest(ds.id)
        response = self.host_client.get_images(request)
        assert_that(response.result, is_(GetImagesResultCode.OK))
        assert_that(response.image_ids, has_item(img_id))

        # Issue another create call and it should fail as the source doesn't
        # exist.
        req = FinalizeImageRequest(image_id=img_id,
                                   datastore=ds.id,
                                   tmp_image_path=tmp_image_path)
        response = self.host_client.finalize_image(req)
        self.assertEqual(response.result,
                         FinalizeImageResultCode.IMAGE_NOT_FOUND)

        # Verify that we fail if the destination already exists.
        tmp_image, ds = self._create_test_image(tmp_img_id)
        req = FinalizeImageRequest(image_id=img_id,
                                   datastore=ds.id,
                                   tmp_image_path=tmp_image_path)
        response = self.host_client.finalize_image(req)
        self.assertEqual(response.result,
                         FinalizeImageResultCode.DESTINATION_ALREADY_EXIST)

        # cleanup
        self._delete_image(dst_image)
示例#7
0
    def _copy_to_tmp_image(self, source_datastore, source_id, dest_datastore,
                           dest_id):
        """ Copy an image into a temp location.
            1. Lock a tmp image destination file with an exclusive lock. This
            is to prevent the GC thread from garbage collecting directories
            that are actively being used.
            The temp directory name contains a random UUID to prevent
            collisions with concurrent copies
            2. Create the temp directory.
            3. Copy the metadata file over.
            4. Copy the vmdk over.

            @return the tmp image directory on success.
        """
        ds_type = self._get_datastore_type(dest_datastore)
        if ds_type == DatastoreType.VSAN:
            tmp_image_dir = os_datastore_path(
                dest_datastore,
                compond_path_join(IMAGE_FOLDER_NAME_PREFIX, dest_id),
                compond_path_join(TMP_IMAGE_FOLDER_NAME_PREFIX,
                                  str(uuid.uuid4())))
        else:
            tmp_image_dir = os_datastore_path(
                dest_datastore,
                compond_path_join(TMP_IMAGE_FOLDER_NAME_PREFIX,
                                  str(uuid.uuid4())))

        # Create the temp directory
        self._host_client.make_directory(tmp_image_dir)

        # Copy the metadata file if it exists.
        source_meta = os_metadata_path(source_datastore, source_id,
                                       IMAGE_FOLDER_NAME_PREFIX)
        if os.path.exists(source_meta):
            try:
                dest_meta = os.path.join(tmp_image_dir,
                                         metadata_filename(dest_id))
                shutil.copy(source_meta, dest_meta)
            except:
                self._logger.exception("Failed to copy metadata file %s",
                                       source_meta)
                raise

        # Create the timestamp file
        self._create_image_timestamp_file(tmp_image_dir)

        self._host_client.copy_disk(
            vmdk_path(source_datastore, source_id, IMAGE_FOLDER_NAME_PREFIX),
            os.path.join(tmp_image_dir, "%s.vmdk" % dest_id))
        return tmp_image_dir
    def _copy_to_tmp_image(self, source_datastore, source_id, dest_datastore, dest_id):
        """ Copy an image into a temp location.
            1. Lock a tmp image destination file with an exclusive lock. This
            is to prevent the GC thread from garbage collecting directories
            that are actively being used.
            The temp directory name contains a random UUID to prevent
            collisions with concurrent copies
            2. Create the temp directory.
            3. Copy the metadata file over.
            4. Copy the vmdk over.

            @return the tmp image directory on success.
        """
        ds_type = self._get_datastore_type(dest_datastore)
        if ds_type == DatastoreType.VSAN:
            tmp_image_dir = os_datastore_path(dest_datastore,
                                              compond_path_join(IMAGE_FOLDER_NAME_PREFIX, dest_id),
                                              compond_path_join(TMP_IMAGE_FOLDER_NAME_PREFIX, str(uuid.uuid4())))
        else:
            tmp_image_dir = os_datastore_path(dest_datastore,
                                              compond_path_join(TMP_IMAGE_FOLDER_NAME_PREFIX, str(uuid.uuid4())))

        # Create the temp directory
        self._host_client.make_directory(tmp_image_dir)

        # Copy the metadata file if it exists.
        source_meta = os_metadata_path(source_datastore, source_id, IMAGE_FOLDER_NAME_PREFIX)
        if os.path.exists(source_meta):
            try:
                dest_meta = os.path.join(tmp_image_dir, metadata_filename(dest_id))
                shutil.copy(source_meta, dest_meta)
            except:
                self._logger.exception("Failed to copy metadata file %s", source_meta)
                raise

        # Create the timestamp file
        self._create_image_timestamp_file(tmp_image_dir)

        self._host_client.copy_disk(vmdk_path(source_datastore, source_id, IMAGE_FOLDER_NAME_PREFIX),
                                    os.path.join(tmp_image_dir, "%s.vmdk" % dest_id))
        return tmp_image_dir
    def test_create_image_from_vm(self):
        """ Integration test for creating an image from a VM """
        img_id = "test-new-im-from-vm-%s" % new_id()
        tmp_img_id = "-tmp-" + img_id
        tmp_image, ds = self._create_test_image(tmp_img_id)

        tmp_image_path = datastore_path(ds.id, "image_" + tmp_img_id)
        src_vmdk = vmdk_path(ds.id, tmp_img_id, IMAGE_FOLDER_NAME_PREFIX)
        vm_wrapper = VmWrapper(self.host_client)

        try:
            self._manage_disk(
                vim.VirtualDiskManager.DeleteVirtualDisk_Task,
                name=src_vmdk)
        except:
            logger.error(
                "Error deleting vmdk when setting up tmp image %s" % src_vmdk,
                exc_info=True)
            raise

        dst_image = Image(img_id, ds)

        image = DiskImage("ttylinux", CloneType.COPY_ON_WRITE)
        disks = [
            Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, False, True,
                 image=image,
                 capacity_gb=0, flavor_info=self.DEFAULT_DISK_FLAVOR),
            Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, True, True,
                 capacity_gb=1, flavor_info=self.DEFAULT_DISK_FLAVOR),
            Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, True, True,
                 capacity_gb=2, flavor_info=self.DEFAULT_DISK_FLAVOR)
        ]
        reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_wrapper.create(request=request)

        # VM in wrong state
        vm_wrapper.power(Host.PowerVmOp.ON, Host.PowerVmOpResultCode.OK)
        time.sleep(10)
        vm_wrapper.create_image_from_vm(
            image_id=img_id,
            datastore=ds.id,
            tmp_image_path=tmp_image_path,
            expect=Host.CreateImageFromVmResultCode.INVALID_VM_POWER_STATE)

        vm_wrapper.power(Host.PowerVmOp.OFF, Host.PowerVmOpResultCode.OK)
        time.sleep(10)

        # Happy case
        vm_wrapper.create_image_from_vm(
            image_id=img_id,
            datastore=ds.id,
            tmp_image_path=tmp_image_path,
            expect=Host.CreateImageFromVmResultCode.OK)

        request = Host.GetImagesRequest(ds.id)
        response = self.host_client.get_images(request)
        assert_that(response.result, is_(GetImagesResultCode.OK))
        assert_that(response.image_ids, has_item(img_id))

        # Issue another create call and it should fail as the source doesn't
        # exist.
        req = FinalizeImageRequest(image_id=img_id,
                                   datastore=ds.id,
                                   tmp_image_path=tmp_image_path)
        response = self.host_client.finalize_image(req)
        self.assertEqual(response.result,
                         FinalizeImageResultCode.IMAGE_NOT_FOUND)

        # Verify that we fail if the destination already exists.
        tmp_image, ds = self._create_test_image(tmp_img_id)
        vm_wrapper.create_image_from_vm(
            image_id=tmp_img_id,
            datastore=ds.id,
            tmp_image_path=tmp_image_path,
            expect=Host.CreateImageFromVmResultCode.IMAGE_ALREADY_EXIST)

        vm_wrapper.delete()

        # VM to create image from is gone.
        vm_wrapper.create_image_from_vm(
            image_id=img_id,
            datastore=ds.id,
            tmp_image_path=tmp_image_path,
            expect=Host.CreateImageFromVmResultCode.VM_NOT_FOUND)

        # Create a VM using the new image created
        vm_wrapper2 = VmWrapper(self.host_client)
        image = DiskImage(img_id, CloneType.COPY_ON_WRITE)
        disks = [
            Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, False, True,
                 image=image,
                 capacity_gb=0, flavor_info=self.DEFAULT_DISK_FLAVOR),
        ]
        reservation = vm_wrapper2.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper2.create_request(res_id=reservation)
        vm_wrapper2.create(request=request)
        vm_wrapper2.power(Host.PowerVmOp.ON, Host.PowerVmOpResultCode.OK)
        vm_wrapper2.power(Host.PowerVmOp.OFF, Host.PowerVmOpResultCode.OK)
        vm_wrapper2.delete()

        # cleanup
        self._delete_image(dst_image)
示例#10
0
 def move_disk(self, source_datastore, source_id, dest_datastore, dest_id):
     source = vmdk_path(source_datastore, source_id)
     dest = vmdk_path(dest_datastore, dest_id)
     self._vmdk_mkdir(dest_datastore, dest_id)
     self._host_client.move_disk(source, dest)
     self._vmdk_rmdir(source_datastore, source_id)
示例#11
0
 def delete_disk(self, datastore, disk_id):
     name = vmdk_path(datastore, disk_id)
     self._host_client.delete_disk(name)
     self._vmdk_rmdir(datastore, disk_id)
示例#12
0
 def create_disk(self, datastore, disk_id, size):
     name = vmdk_path(datastore, disk_id)
     self._vmdk_mkdir(datastore, disk_id)
     self._host_client.create_disk(name, size)
     self._host_client.set_disk_uuid(name, disk_id)
示例#13
0
 def _query_uuid(self, datastore, disk_id):
     name = vmdk_path(datastore, disk_id)
     return self._host_client.query_disk_uuid(name)
示例#14
0
 def move_disk(self, source_datastore, source_id, dest_datastore, dest_id):
     source = vmdk_path(source_datastore, source_id)
     dest = vmdk_path(dest_datastore, dest_id)
     self._vmdk_mkdir(dest_datastore, dest_id)
     self._host_client.move_disk(source, dest)
     self._vmdk_rmdir(source_datastore, source_id)
示例#15
0
 def delete_disk(self, datastore, disk_id):
     name = vmdk_path(datastore, disk_id)
     self._host_client.delete_disk(name)
     self._vmdk_rmdir(datastore, disk_id)
示例#16
0
 def create_disk(self, datastore, disk_id, size):
     name = vmdk_path(datastore, disk_id)
     self._vmdk_mkdir(datastore, disk_id)
     self._host_client.create_disk(name, size)
     self._host_client.set_disk_uuid(name, disk_id)
示例#17
0
 def _query_uuid(self, datastore, disk_id):
     name = vmdk_path(datastore, disk_id)
     return self._host_client.query_disk_uuid(name)
    def test_create_image_from_vm(self):
        """ Integration test for creating an image from a VM """
        img_id = "test-new-im-from-vm-%s" % new_id()
        tmp_img_id = "-tmp-" + img_id
        tmp_image, ds = self._create_test_image(tmp_img_id)

        tmp_image_path = datastore_path(ds.id, "image_" + tmp_img_id)
        src_vmdk = vmdk_path(ds.id, tmp_img_id, IMAGE_FOLDER_NAME_PREFIX)
        vm_wrapper = VmWrapper(self.host_client)

        try:
            self._manage_disk(vim.VirtualDiskManager.DeleteVirtualDisk_Task,
                              name=src_vmdk)
        except:
            logger.error("Error deleting vmdk when setting up tmp image %s" %
                         src_vmdk,
                         exc_info=True)
            raise

        dst_image = Image(img_id, ds)

        image = DiskImage("ttylinux", CloneType.COPY_ON_WRITE)
        disks = [
            Disk(new_id(),
                 self.DEFAULT_DISK_FLAVOR.name,
                 False,
                 True,
                 image=image,
                 capacity_gb=0,
                 flavor_info=self.DEFAULT_DISK_FLAVOR),
            Disk(new_id(),
                 self.DEFAULT_DISK_FLAVOR.name,
                 True,
                 True,
                 capacity_gb=1,
                 flavor_info=self.DEFAULT_DISK_FLAVOR),
            Disk(new_id(),
                 self.DEFAULT_DISK_FLAVOR.name,
                 True,
                 True,
                 capacity_gb=2,
                 flavor_info=self.DEFAULT_DISK_FLAVOR)
        ]
        reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_wrapper.create(request=request)

        # VM in wrong state
        vm_wrapper.power(Host.PowerVmOp.ON, Host.PowerVmOpResultCode.OK)
        time.sleep(10)
        vm_wrapper.create_image_from_vm(
            image_id=img_id,
            datastore=ds.id,
            tmp_image_path=tmp_image_path,
            expect=Host.CreateImageFromVmResultCode.INVALID_VM_POWER_STATE)

        vm_wrapper.power(Host.PowerVmOp.OFF, Host.PowerVmOpResultCode.OK)
        time.sleep(10)

        # Happy case
        vm_wrapper.create_image_from_vm(
            image_id=img_id,
            datastore=ds.id,
            tmp_image_path=tmp_image_path,
            expect=Host.CreateImageFromVmResultCode.OK)

        request = Host.GetImagesRequest(ds.id)
        response = self.host_client.get_images(request)
        assert_that(response.result, is_(GetImagesResultCode.OK))
        assert_that(response.image_ids, has_item(img_id))

        # Issue another create call and it should fail as the source doesn't
        # exist.
        req = FinalizeImageRequest(image_id=img_id,
                                   datastore=ds.id,
                                   tmp_image_path=tmp_image_path)
        response = self.host_client.finalize_image(req)
        self.assertEqual(response.result,
                         FinalizeImageResultCode.IMAGE_NOT_FOUND)

        # Verify that we fail if the destination already exists.
        tmp_image, ds = self._create_test_image(tmp_img_id)
        vm_wrapper.create_image_from_vm(
            image_id=tmp_img_id,
            datastore=ds.id,
            tmp_image_path=tmp_image_path,
            expect=Host.CreateImageFromVmResultCode.IMAGE_ALREADY_EXIST)

        vm_wrapper.delete()

        # VM to create image from is gone.
        vm_wrapper.create_image_from_vm(
            image_id=img_id,
            datastore=ds.id,
            tmp_image_path=tmp_image_path,
            expect=Host.CreateImageFromVmResultCode.VM_NOT_FOUND)

        # Create a VM using the new image created
        vm_wrapper2 = VmWrapper(self.host_client)
        image = DiskImage(img_id, CloneType.COPY_ON_WRITE)
        disks = [
            Disk(new_id(),
                 self.DEFAULT_DISK_FLAVOR.name,
                 False,
                 True,
                 image=image,
                 capacity_gb=0,
                 flavor_info=self.DEFAULT_DISK_FLAVOR),
        ]
        reservation = vm_wrapper2.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper2.create_request(res_id=reservation)
        vm_wrapper2.create(request=request)
        vm_wrapper2.power(Host.PowerVmOp.ON, Host.PowerVmOpResultCode.OK)
        vm_wrapper2.power(Host.PowerVmOp.OFF, Host.PowerVmOpResultCode.OK)
        vm_wrapper2.delete()

        # cleanup
        self._delete_image(dst_image)