def test_place_on_multiple_datastores(self):
        """ Test placement can actually place vm to datastores without image.
        """
        host_datastores = self.vim_client.get_all_datastores()
        image_datastore = self._find_configured_datastore_in_host_config()
        dest_datastore = None

        for ds in host_datastores:
            if ds.id != image_datastore.id:
                dest_datastore = ds
                break

        if not dest_datastore:
            raise SkipTest()

        # Test only 2 datastores, with one image datastore and another
        # datastore.
        self.provision_hosts(
            datastores=[image_datastore.name, dest_datastore.name],
            used_for_vms=False)
        self.client_connections()

        concurrency = 3
        atmoic_lock = threading.Lock()
        results = {"count": 0}

        # Only copy image to datastore[0]
        new_image_id = str(uuid.uuid4())
        datastore = Datastore(id=image_datastore.name)
        src_image = Image("ttylinux", datastore)
        dst_image = Image(new_image_id, datastore)
        request = Host.CopyImageRequest(src_image, dst_image)
        response = self.host_client.copy_image(request)
        assert_that(response.result, is_(CopyImageResultCode.OK))

        def _thread():
            self._test_create_vm_with_ephemeral_disks(new_image_id,
                                                      concurrent=True,
                                                      new_client=True)
            with atmoic_lock:
                results["count"] += 1

        threads = []
        for i in range(concurrency):
            thread = threading.Thread(target=_thread)
            threads.append(thread)
            thread.start()

        for thread in threads:
            thread.join()

        # Make sure the new image is copied to both datastores, and clean
        # them up.
        for ds in (image_datastore, dest_datastore):
            image = Image(datastore=Datastore(id=ds.name), id=new_image_id)
            self._delete_image(image)

        assert_that(results["count"], is_(concurrency))
    def test_copy_image_not_found(self):
        datastore = self._find_configured_datastore_in_host_config()
        src_image = Image("not-found-source-id", datastore)
        dst_image = Image("destination-id", datastore)

        request = Host.CopyImageRequest(src_image, dst_image)
        response = self.host_client.copy_image(request)

        assert_that(response.result, is_(CopyImageResultCode.IMAGE_NOT_FOUND))
        def _thread():
            client = self.create_client()
            request = Host.CopyImageRequest(src_image, dst_image)
            response = client.copy_image(request)
            ok = response.result == CopyImageResultCode.OK
            existed = response.result == CopyImageResultCode.\
                DESTINATION_ALREADY_EXIST

            # Verify destination_id is in datastore
            request = Host.GetImagesRequest(datastore.id)
            response = client.get_images(request)
            assert_that(response.result, is_(GetImagesResultCode.OK))
            assert_that(response.image_ids, has_item("ttylinux"))
            assert_that(response.image_ids, has_item(new_image_id))
            assert_that(response.image_ids, has_length(image_number + 1))
            with atomic_lock:
                if ok:
                    results["ok"] += 1
                if existed:
                    results["existed"] += 1
    def _create_test_image(self, name):
        """ Create an test image for tests to use on a datastore """
        datastore = self._find_configured_datastore_in_host_config()

        # ttylinux is the default image that is copied to datastore
        # when agent starts
        src_image = Image("ttylinux", datastore)
        dst_image = Image(name, datastore)

        # Copy image
        request = Host.CopyImageRequest(src_image, dst_image)
        response = self.host_client.copy_image(request)
        assert_that(
            response.result,
            is_in([
                CopyImageResultCode.OK,
                CopyImageResultCode.DESTINATION_ALREADY_EXIST
            ]))

        return dst_image, datastore
    def test_copy_image_get_images(self):
        datastore = self._find_configured_datastore_in_host_config()
        assert_that(datastore, not_none())

        # ttylinux is the default image that is copied to datastore1
        # when agent starts
        src_image = Image("ttylinux", datastore)
        dst_image = Image("test-copy-image", datastore)

        # verify test-copy-image is not in datastore
        request = Host.GetImagesRequest(datastore.id)
        response = self.host_client.get_images(request)
        assert_that(response.result, is_(GetImagesResultCode.OK))
        assert_that(response.image_ids, has_item("ttylinux"))
        assert_that(response.image_ids, not(has_item("test-copy-image")))
        image_number = len(response.image_ids)

        # Copy image
        request = Host.CopyImageRequest(src_image, dst_image)
        response = self.host_client.copy_image(request)
        assert_that(response.result, is_(CopyImageResultCode.OK))

        # Copy image the second time should return DESTINATION_ALREADY_EXIST
        request = Host.CopyImageRequest(src_image, dst_image)
        response = self.host_client.copy_image(request)
        assert_that(response.result,
                    is_(CopyImageResultCode.DESTINATION_ALREADY_EXIST))

        # Verify test-copy-image is in datastore
        request = Host.GetImagesRequest(datastore.id)
        response = self.host_client.get_images(request)
        assert_that(response.result, is_(GetImagesResultCode.OK))
        assert_that(response.image_ids, has_item("ttylinux"))
        assert_that(response.image_ids, has_item("test-copy-image"))
        assert_that(response.image_ids, has_length(image_number + 1))

        # Create VM
        image = DiskImage("test-copy-image", 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),
        ]
        vm_wrapper = VmWrapper(self.host_client)
        reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation
        request = vm_wrapper.create_request(res_id=reservation)
        response = vm_wrapper.create(request=request)
        assert_that(response.vm, not_none())

        # Delete VM
        vm_wrapper.delete(request=vm_wrapper.delete_request(disk_ids=[]))

        # Verify test-copy-image is in datastore
        request = Host.GetImagesRequest(datastore.id)
        response = self.host_client.get_images(request)
        assert_that(response.result, is_(GetImagesResultCode.OK))
        assert_that(response.image_ids, has_item("ttylinux"))
        assert_that(response.image_ids, has_item("test-copy-image"))
        assert_that(response.image_ids, has_length(image_number + 1))

        # Copy image using datastore with name as id should succeed
        # This datastore object uses the datastore name as its id
        datastore.id = datastore.name
        dst_image2 = Image("test-copy-image2", datastore)
        request = Host.CopyImageRequest(src_image, dst_image2)
        response = self.host_client.copy_image(request)
        assert_that(response.result, is_(CopyImageResultCode.OK))

        # Clean destination image
        self._delete_image(dst_image)
        self._delete_image(dst_image2)