def test_place_on_datastore_tag(self):
        host_config_request = Host.GetConfigRequest()
        res = self.host_client.get_host_config(host_config_request)
        self.assertEqual(res.result, GetConfigResultCode.OK)

        datastores = res.hostConfig.datastores
        for datastore in datastores:
            tag = self._type_to_tag(datastore.type)
            if not tag:
                continue

            vm_wrapper = VmWrapper(self.host_client)

            # Test place disks with only datastore constraint
            disk = Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, False, True, capacity_gb=0)
            resource_constraints = self._create_constraints([datastore.id], [])
            vm_wrapper.place(vm_disks=[disk], vm_constraints=resource_constraints)

            # Test place disks with datastore and datastore tag constraint
            disk = Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, False, True, capacity_gb=0)
            resource_constraints = self._create_constraints([datastore.id], [tag])
            vm_wrapper.place(vm_disks=[disk], vm_constraints=resource_constraints, expect=PlaceResultCode.OK)

            # Test place disks with the wrong datastore tag
            for other_tag in self._other_tags(tag):
                disk = Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, False, True, capacity_gb=0)
                resource_constraints = self._create_constraints([datastore.id], [other_tag])
                vm_wrapper.place(vm_disks=[disk], vm_constraints=resource_constraints,
                                 expect=PlaceResultCode.NO_SUCH_RESOURCE)
    def test_start_image_scanner(self):
        """
        Test image scanner. Make sure the idle images are reported correctly.
        """
        datastore = self._find_configured_datastore_in_host_config()

        image_id_1 = new_id()
        dst_image_1, _ = self._create_test_image(image_id_1)

        image_id_2 = new_id()
        dst_image_2, _ = self._create_test_image(image_id_2)
        disk_image_2 = DiskImage(image_id_2, CloneType.COPY_ON_WRITE)

        disks = [
            Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, False, True,
                 image=disk_image_2,
                 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)
        ]
        vm_wrapper = VmWrapper(self.host_client)
        reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_wrapper.create(request=request)
        logger.info("Image scan, Vm id: %s" % vm_wrapper.id)

        # Start image scanner
        start_scan_request = StartImageScanRequest()
        start_scan_request.datastore_id = datastore.id
        start_scan_request.scan_rate = 600
        start_scan_request.timeout = 30
        start_scan_response = self.host_client.start_image_scan(start_scan_request)
        self.assertEqual(start_scan_response.result, StartImageOperationResultCode.OK)
        self._get_and_check_inactive_images(datastore.id, image_id_1, True)
        get_inactive_images_response = self._get_and_check_inactive_images(datastore.id, image_id_2, False)

        # Start image sweeper
        start_sweep_request = StartImageSweepRequest()
        start_sweep_request.datastore_id = datastore.id
        start_sweep_request.image_descs = get_inactive_images_response.image_descs
        start_sweep_request.sweep_rate = 600
        start_sweep_request.timeout = 30
        start_sweep_request.grace_period = 0
        start_sweep_response = self.host_client.start_image_sweep(start_sweep_request)
        self.assertEqual(start_sweep_response.result, StartImageOperationResultCode.OK)

        self._get_and_check_deleted_images(datastore.id, image_id_1, True)
        # cleanup
        vm_wrapper.delete()
        self._delete_image(dst_image_1, DeleteDirectoryResultCode.DIRECTORY_NOT_FOUND)
        self._delete_image(dst_image_2)
    def test_place_on_datastore_tag(self):
        host_config_request = Host.GetConfigRequest()
        res = self.host_client.get_host_config(host_config_request)
        self.assertEqual(res.result, GetConfigResultCode.OK)

        datastores = res.hostConfig.datastores
        for datastore in datastores:
            tag = self._type_to_tag(datastore.type)
            if not tag:
                continue

            vm_wrapper = VmWrapper(self.host_client)

            # Test place disks with only datastore constraint
            disk = Disk(new_id(),
                        self.DEFAULT_DISK_FLAVOR.name,
                        False,
                        True,
                        capacity_gb=0)
            resource_constraints = self._create_constraints([datastore.id], [])
            vm_wrapper.place(vm_disks=[disk],
                             vm_constraints=resource_constraints)

            # Test place disks with datastore and datastore tag constraint
            disk = Disk(new_id(),
                        self.DEFAULT_DISK_FLAVOR.name,
                        False,
                        True,
                        capacity_gb=0)
            resource_constraints = self._create_constraints([datastore.id],
                                                            [tag])
            vm_wrapper.place(vm_disks=[disk],
                             vm_constraints=resource_constraints,
                             expect=PlaceResultCode.OK)

            # Test place disks with the wrong datastore tag
            for other_tag in self._other_tags(tag):
                disk = Disk(new_id(),
                            self.DEFAULT_DISK_FLAVOR.name,
                            False,
                            True,
                            capacity_gb=0)
                resource_constraints = self._create_constraints([datastore.id],
                                                                [other_tag])
                vm_wrapper.place(vm_disks=[disk],
                                 vm_constraints=resource_constraints,
                                 expect=PlaceResultCode.NO_SUCH_RESOURCE)
    def test_disk_uuids(self):
        # Create a vm without a root disk and blank disk then attach another
        # persistent disk. Then verify that only the uuids of the
        # ephemeral and persistent disks are updated to match their cloud ids.

        vm_wrapper = VmWrapper(self.host_client)

        disk_id_root = new_id()
        disk_id_ephemeral = new_id()
        disk_id_persistent = new_id()

        image = DiskImage("ttylinux", CloneType.COPY_ON_WRITE)
        disks = [
            Disk(disk_id_root, self.DEFAULT_DISK_FLAVOR.name, False, True,
                 image=image,
                 capacity_gb=0, flavor_info=self.DEFAULT_DISK_FLAVOR),
            Disk(disk_id_ephemeral, self.DEFAULT_DISK_FLAVOR.name, True, True,
                 capacity_gb=1, 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_id = vm_wrapper.create(request=request).vm.id

        # create one persistent disk
        disk = Disk(disk_id_persistent, self.DEFAULT_DISK_FLAVOR.name, True, True,
                    capacity_gb=1, flavor_info=self.DEFAULT_DISK_FLAVOR)
        reservation = vm_wrapper.place_and_reserve(disk=disk).reservation
        vm_wrapper.create_disk(disk, reservation, validate=True)
        vm_wrapper.attach_disks(vm_id, [disk_id_persistent])

        vim_vm = self.vim_client.get_vm(vm_id)

        disk_uuid_map = dict([(dev.backing.uuid, dev.backing.fileName)
                              for dev in vim_vm.config.hardware.device
                              if isinstance(dev, vim.vm.device.VirtualDisk)])

        # Assert that the UUID assigned to the ephemeral and persistent disks
        # matches their ids
        for disk_id in (disk_id_ephemeral, disk_id_persistent):
            self.assertTrue(disk_id in disk_uuid_map and
                            disk_id in disk_uuid_map[disk_id])
        # Assert that no such assignment is done for link-clone root disk.
        self.assertFalse(disk_id_root in disk_uuid_map)

        vm_wrapper.detach_disks(vm_id, [disk_id_persistent])
        vm_wrapper.delete(request=vm_wrapper.delete_request())
        vm_wrapper.delete_disks([disk_id_persistent], validate=True)
    def test_force_delete_vm(self):
        vm_wrapper = VmWrapper(self.host_client)

        # create a vm without disk
        reservation = vm_wrapper.place_and_reserve().reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id

        # create 2 disks
        disks = [
            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=1, flavor_info=self.DEFAULT_DISK_FLAVOR)
        ]

        for disk in disks:
            reservation = vm_wrapper.place_and_reserve(disk=disk).reservation
            vm_wrapper.create_disk(disk, reservation, validate=True)

        # attach disks
        disk_ids = [disk.id for disk in disks]
        vm_wrapper.attach_disks(vm_id, disk_ids)

        # delete vm fails without force
        vm_wrapper.delete(request=vm_wrapper.delete_request(),
                          expect=Host.DeleteVmResultCode.OPERATION_NOT_ALLOWED)

        # delete vm with force succeeds
        vm_wrapper.delete(request=vm_wrapper.delete_request(force=True))
        for disk_id in disk_ids:
            vm_wrapper.get_disk(disk_id, expect_found=False)
    def test_detach_cdrom(self):
        """
        Tests detach iso from VM.
        Verify Detaching a real iso from a VM.
        """
        if not self._remote_iso_file:
            raise SkipTest("ISO file on server not provided")

        si = self.get_service_instance()
        file_manager = si.RetrieveContent().fileManager
        iso_path = self._generate_new_iso_ds_path()
        self._make_new_iso_copy(file_manager, iso_path)
        iso_path_2 = self._generate_new_iso_ds_path()
        self._make_new_iso_copy(file_manager, iso_path_2)

        vm_wrapper = VmWrapper(self.host_client)
        reservation = vm_wrapper.place_and_reserve().reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id

        vm_wrapper.attach_iso(vm_id, iso_path,
                              Host.AttachISOResultCode.OK)
        vm_wrapper.detach_iso(vm_id, True,
                              Host.DetachISOResultCode.OK)

        vm_wrapper.attach_iso(vm_id, iso_path_2,
                              Host.AttachISOResultCode.OK)
        # verify detach works when powered on
        vm_wrapper.power(Host.PowerVmOp.ON)
        vm_wrapper.detach_iso(vm_id, True,
                              Host.DetachISOResultCode.OK)
        vm_wrapper.power(Host.PowerVmOp.OFF)

        vm_wrapper.delete(request=vm_wrapper.delete_request())
    def test_detach_cdrom_failure(self):
        """ Tests failures of detach iso from VM. """
        vm_wrapper = VmWrapper(self.host_client)
        reservation = vm_wrapper.place_and_reserve().reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id

        # no prior attach of iso
        vm_wrapper.detach_iso(vm_id, True,
                              Host.DetachISOResultCode.ISO_NOT_ATTACHED)

        # nonexistent VM id
        fake_id = str(uuid.uuid4())
        vm_wrapper.detach_iso(fake_id, True,
                              Host.DetachISOResultCode.VM_NOT_FOUND)

        # Attaching nonexistent iso path still should succeed as long
        # as a valid datastore path format is used
        random = str(uuid.uuid4())
        vm_wrapper.attach_iso(vm_id, "[] /tmp/%s_nonexistent_.iso" % random,
                              Host.AttachISOResultCode.OK)
        # Not supporting detach without delete yet.
        vm_wrapper.detach_iso(vm_id, False,
                              Host.DetachISOResultCode.SYSTEM_ERROR)
        # But detach a non-exist iso should work.
        vm_wrapper.detach_iso(vm_id, True,
                              Host.DetachISOResultCode.OK)

        vm_wrapper.delete(request=vm_wrapper.delete_request())
    def test_attach_cdrom(self):
        """
        Tests attach iso code path.
        1. Attach an iso to a non existent VM. Check correct error
        2. Attach a non existent iso file to a valid VM. Check correct error
        3. Attach a real iso if specified to a VM. Verify it succeeds.
        Test should pass the iso path as [datastore_name]/path/to/iso.iso
        """

        if not self._remote_iso_file:
            raise SkipTest("ISO file on server not provided")

        si = self.get_service_instance()
        file_manager = si.RetrieveContent().fileManager
        iso_path = self._generate_new_iso_ds_path()
        iso_path_2 = self._generate_new_iso_ds_path()

        vm_wrapper = VmWrapper(self.host_client)
        image = DiskImage("ttylinux", CloneType.COPY_ON_WRITE)
        disks = [
            Disk(new_id(), "default", False, True, image=image, capacity_gb=1,
                 flavor_info=self.DEFAULT_DISK_FLAVOR),
        ]

        # Create disk and VM.
        reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id

        # Verify the result when the VM is not found.
        fake_id = str(uuid.uuid4())
        vm_wrapper.attach_iso(fake_id, "/tmp/foo.iso",
                              Host.AttachISOResultCode.VM_NOT_FOUND)

        # Verify the result when the the iso doesn't exist.
        vm_wrapper.attach_iso(vm_id, "/tmp/foo.iso",
                              Host.AttachISOResultCode.SYSTEM_ERROR)

        self._make_new_iso_copy(file_manager, iso_path)
        self._make_new_iso_copy(file_manager, iso_path_2)

        # Doing enough attaches will indirectly verify that we do not grow the
        # device list on reattach.
        for i in xrange(3):
            # verify attach works
            vm_wrapper.attach_iso(vm_id, iso_path)
            # verify re-attach to another iso works
            vm_wrapper.attach_iso(vm_id, iso_path_2)

        vm_wrapper.power(Host.PowerVmOp.ON)
        # Verify reattach fails when vm is powered on.
        vm_wrapper.attach_iso(vm_id, iso_path,
                              Host.AttachISOResultCode.ISO_ATTACHED_ERROR)
        vm_wrapper.power(Host.PowerVmOp.OFF)

        vm_wrapper.detach_iso(vm_id, True)
        vm_wrapper.attach_iso(vm_id, iso_path)
        vm_wrapper.detach_iso(vm_id, True)

        self.clear()
    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)
    def test_start_image_scanner(self):
        """
        Test image scanner. Make sure the idle images are reported correctly.
        """
        datastore = self._find_configured_datastore_in_host_config()

        image_id_1 = new_id()
        dst_image_1, _ = self._create_test_image(image_id_1)

        image_id_2 = new_id()
        dst_image_2, _ = self._create_test_image(image_id_2)
        disk_image_2 = DiskImage(image_id_2, CloneType.COPY_ON_WRITE)

        disks = [
            Disk(new_id(),
                 self.DEFAULT_DISK_FLAVOR.name,
                 False,
                 True,
                 image=disk_image_2,
                 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)
        ]
        vm_wrapper = VmWrapper(self.host_client)
        reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_wrapper.create(request=request)
        logger.info("Image scan, Vm id: %s" % vm_wrapper.id)

        # Start image scanner
        start_scan_request = StartImageScanRequest()
        start_scan_request.datastore_id = datastore.id
        start_scan_request.scan_rate = 600
        start_scan_request.timeout = 30
        start_scan_response = self.host_client.start_image_scan(
            start_scan_request)
        self.assertEqual(start_scan_response.result,
                         StartImageOperationResultCode.OK)
        self._get_and_check_inactive_images(datastore.id, image_id_1, True)
        get_inactive_images_response = self._get_and_check_inactive_images(
            datastore.id, image_id_2, False)

        # Start image sweeper
        start_sweep_request = StartImageSweepRequest()
        start_sweep_request.datastore_id = datastore.id
        start_sweep_request.image_descs = get_inactive_images_response.image_descs
        start_sweep_request.sweep_rate = 600
        start_sweep_request.timeout = 30
        start_sweep_request.grace_period = 0
        start_sweep_response = self.host_client.start_image_sweep(
            start_sweep_request)
        self.assertEqual(start_sweep_response.result,
                         StartImageOperationResultCode.OK)

        self._get_and_check_deleted_images(datastore.id, image_id_1, True)
        # cleanup
        vm_wrapper.delete()
        self._delete_image(dst_image_1,
                           DeleteDirectoryResultCode.DIRECTORY_NOT_FOUND)
        self._delete_image(dst_image_2)
    def test_disk_uuids(self):
        # Create a vm without a root disk and blank disk then attach another
        # persistent disk. Then verify that only the uuids of the
        # ephemeral and persistent disks are updated to match their cloud ids.

        vm_wrapper = VmWrapper(self.host_client)

        disk_id_root = new_id()
        disk_id_ephemeral = new_id()
        disk_id_persistent = new_id()

        image = DiskImage("ttylinux", CloneType.COPY_ON_WRITE)
        disks = [
            Disk(disk_id_root,
                 self.DEFAULT_DISK_FLAVOR.name,
                 False,
                 True,
                 image=image,
                 capacity_gb=0,
                 flavor_info=self.DEFAULT_DISK_FLAVOR),
            Disk(disk_id_ephemeral,
                 self.DEFAULT_DISK_FLAVOR.name,
                 True,
                 True,
                 capacity_gb=1,
                 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_id = vm_wrapper.create(request=request).vm.id

        # create one persistent disk
        disk = Disk(disk_id_persistent,
                    self.DEFAULT_DISK_FLAVOR.name,
                    True,
                    True,
                    capacity_gb=1,
                    flavor_info=self.DEFAULT_DISK_FLAVOR)
        reservation = vm_wrapper.place_and_reserve(disk=disk).reservation
        vm_wrapper.create_disk(disk, reservation, validate=True)
        vm_wrapper.attach_disks(vm_id, [disk_id_persistent])

        vim_vm = self.vim_client.get_vm(vm_id)

        disk_uuid_map = dict([(dev.backing.uuid, dev.backing.fileName)
                              for dev in vim_vm.config.hardware.device
                              if isinstance(dev, vim.vm.device.VirtualDisk)])

        # Assert that the UUID assigned to the ephemeral and persistent disks
        # matches their ids
        for disk_id in (disk_id_ephemeral, disk_id_persistent):
            self.assertTrue(disk_id in disk_uuid_map
                            and disk_id in disk_uuid_map[disk_id])
        # Assert that no such assignment is done for link-clone root disk.
        self.assertFalse(disk_id_root in disk_uuid_map)

        vm_wrapper.detach_disks(vm_id, [disk_id_persistent])
        vm_wrapper.delete(request=vm_wrapper.delete_request())
        vm_wrapper.delete_disks([disk_id_persistent], validate=True)
    def test_force_delete_vm(self):
        vm_wrapper = VmWrapper(self.host_client)

        # create a vm without disk
        reservation = vm_wrapper.place_and_reserve().reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id

        # create 2 disks
        disks = [
            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=1,
                 flavor_info=self.DEFAULT_DISK_FLAVOR)
        ]

        for disk in disks:
            reservation = vm_wrapper.place_and_reserve(disk=disk).reservation
            vm_wrapper.create_disk(disk, reservation, validate=True)

        # attach disks
        disk_ids = [disk.id for disk in disks]
        vm_wrapper.attach_disks(vm_id, disk_ids)

        # delete vm fails without force
        vm_wrapper.delete(request=vm_wrapper.delete_request(),
                          expect=Host.DeleteVmResultCode.OPERATION_NOT_ALLOWED)

        # delete vm with force succeeds
        vm_wrapper.delete(request=vm_wrapper.delete_request(force=True))
        for disk_id in disk_ids:
            vm_wrapper.get_disk(disk_id, expect_found=False)
    def test_detach_cdrom(self):
        """
        Tests detach iso from VM.
        Verify Detaching a real iso from a VM.
        """
        if not self._remote_iso_file:
            raise SkipTest("ISO file on server not provided")

        si = self.get_service_instance()
        file_manager = si.RetrieveContent().fileManager
        iso_path = self._generate_new_iso_ds_path()
        self._make_new_iso_copy(file_manager, iso_path)
        iso_path_2 = self._generate_new_iso_ds_path()
        self._make_new_iso_copy(file_manager, iso_path_2)

        vm_wrapper = VmWrapper(self.host_client)
        reservation = vm_wrapper.place_and_reserve().reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id

        vm_wrapper.attach_iso(vm_id, iso_path, Host.AttachISOResultCode.OK)
        vm_wrapper.detach_iso(vm_id, True, Host.DetachISOResultCode.OK)

        vm_wrapper.attach_iso(vm_id, iso_path_2, Host.AttachISOResultCode.OK)
        # verify detach works when powered on
        vm_wrapper.power(Host.PowerVmOp.ON)
        vm_wrapper.detach_iso(vm_id, True, Host.DetachISOResultCode.OK)
        vm_wrapper.power(Host.PowerVmOp.OFF)

        vm_wrapper.delete(request=vm_wrapper.delete_request())
    def test_detach_cdrom_failure(self):
        """ Tests failures of detach iso from VM. """
        vm_wrapper = VmWrapper(self.host_client)
        reservation = vm_wrapper.place_and_reserve().reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id

        # no prior attach of iso
        vm_wrapper.detach_iso(vm_id, True,
                              Host.DetachISOResultCode.ISO_NOT_ATTACHED)

        # nonexistent VM id
        fake_id = str(uuid.uuid4())
        vm_wrapper.detach_iso(fake_id, True,
                              Host.DetachISOResultCode.VM_NOT_FOUND)

        # Attaching nonexistent iso path still should succeed as long
        # as a valid datastore path format is used
        random = str(uuid.uuid4())
        vm_wrapper.attach_iso(vm_id, "[] /tmp/%s_nonexistent_.iso" % random,
                              Host.AttachISOResultCode.OK)
        # Not supporting detach without delete yet.
        vm_wrapper.detach_iso(vm_id, False,
                              Host.DetachISOResultCode.SYSTEM_ERROR)
        # But detach a non-exist iso should work.
        vm_wrapper.detach_iso(vm_id, True, Host.DetachISOResultCode.OK)

        vm_wrapper.delete(request=vm_wrapper.delete_request())
    def test_attach_cdrom(self):
        """
        Tests attach iso code path.
        1. Attach an iso to a non existent VM. Check correct error
        2. Attach a non existent iso file to a valid VM. Check correct error
        3. Attach a real iso if specified to a VM. Verify it succeeds.
        Test should pass the iso path as [datastore_name]/path/to/iso.iso
        """

        if not self._remote_iso_file:
            raise SkipTest("ISO file on server not provided")

        si = self.get_service_instance()
        file_manager = si.RetrieveContent().fileManager
        iso_path = self._generate_new_iso_ds_path()
        iso_path_2 = self._generate_new_iso_ds_path()

        vm_wrapper = VmWrapper(self.host_client)
        image = DiskImage("ttylinux", CloneType.COPY_ON_WRITE)
        disks = [
            Disk(new_id(),
                 "default",
                 False,
                 True,
                 image=image,
                 capacity_gb=1,
                 flavor_info=self.DEFAULT_DISK_FLAVOR),
        ]

        # Create disk and VM.
        reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id

        # Verify the result when the VM is not found.
        fake_id = str(uuid.uuid4())
        vm_wrapper.attach_iso(fake_id, "/tmp/foo.iso",
                              Host.AttachISOResultCode.VM_NOT_FOUND)

        # Verify the result when the the iso doesn't exist.
        vm_wrapper.attach_iso(vm_id, "/tmp/foo.iso",
                              Host.AttachISOResultCode.SYSTEM_ERROR)

        self._make_new_iso_copy(file_manager, iso_path)
        self._make_new_iso_copy(file_manager, iso_path_2)

        # Doing enough attaches will indirectly verify that we do not grow the
        # device list on reattach.
        for i in xrange(3):
            # verify attach works
            vm_wrapper.attach_iso(vm_id, iso_path)
            # verify re-attach to another iso works
            vm_wrapper.attach_iso(vm_id, iso_path_2)

        vm_wrapper.power(Host.PowerVmOp.ON)
        # Verify reattach fails when vm is powered on.
        vm_wrapper.attach_iso(vm_id, iso_path,
                              Host.AttachISOResultCode.ISO_ATTACHED_ERROR)
        vm_wrapper.power(Host.PowerVmOp.OFF)

        vm_wrapper.detach_iso(vm_id, True)
        vm_wrapper.attach_iso(vm_id, iso_path)
        vm_wrapper.detach_iso(vm_id, True)

        self.clear()
    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)