Esempio n. 1
0
def createVmResource(image):
    disk = Disk()
    disk.flavor = "some-disk-flavor"
    disk.id = str(uuid.uuid4())
    disk.persistent = False
    disk.new_disk = True
    disk.capacity_gb = 0
    disk.image = DiskImage()
    disk.image.id = image
    disk.image.clone_type = CloneType.COPY_ON_WRITE
    disk.flavor_info = Flavor()
    disk.flavor_info.name = "some-disk-flavor"
    disk.flavor_info.cost = []

    vm = Vm()
    vm.id = str(uuid.uuid4())
    vm.flavor = "some-vm-flavor"
    vm.state = State.STOPPED
    vm.flavor_info = Flavor()
    vm.flavor_info.name = "some-vm-flavor"
    vm.flavor_info.cost = [
        QuotaLineItem("vm.cpu", "1", QuotaUnit.COUNT),
        QuotaLineItem("vm.memory", "0.5", QuotaUnit.GB)
    ]
    vm.disks = [disk]

    return vm
Esempio n. 2
0
    def _sample_vm(self):
        flavor = Flavor(name="flavor", cost=[QuotaLineItem("a", "b", 1)])
        disks = [
            Disk(stable_uuid("%s-1" % id),
                 flavor,
                 False,
                 False,
                 1,
                 datastore=Datastore("ds1")),
            Disk(stable_uuid("%s-2" % id),
                 flavor,
                 False,
                 False,
                 1,
                 datastore=Datastore("ds2")),
        ]

        vm = Vm()
        vm.id = id
        vm.flavor = "flavor"
        vm.flavor_info = flavor
        vm.disks = disks
        vm.state = State().STARTED
        vm.datastore = Datastore("ds1")

        return vm
Esempio n. 3
0
    def create_resource(self, id):
        flavor = Flavor(name="flavor", cost=[QuotaLineItem("a", "b", 1)])
        disks = [
            Disk(stable_uuid("%s-1" % id),
                 flavor,
                 False,
                 False,
                 1,
                 datastore=Datastore("ds1")),
            Disk(stable_uuid("%s-2" % id),
                 flavor,
                 False,
                 False,
                 1,
                 datastore=Datastore("ds2")),
        ]

        vm = Vm()
        vm.id = id
        vm.flavor = "flavor"
        vm.flavor_info = flavor
        vm.state = State().STARTED
        vm.datastore = Datastore("ds1")

        resource = Resource(vm, disks)

        return resource
def vm_resource():
    cost = [
        QuotaLineItem("vm.cpu", "1", QuotaUnit.COUNT),
        QuotaLineItem("vm.memory", "32", 2)]
    return Vm(id=new_id(),
              flavor="default",
              flavor_info=Flavor(name="default", cost=cost),
              state=VmPowerState.STOPPED)
 def vm_create():
     cost = [
         QuotaLineItem("vm.cpu", "1", QuotaUnit.COUNT),
         QuotaLineItem("vm.memory", "32", 2)]
     return Vm(id=new_id(),
               flavor="default",
               flavor_info=Flavor(name="default", cost=cost),
               state=VmPowerState.STOPPED,
               tenant_id="t1",
               project_id="p1")
Esempio n. 6
0
def createDisksResource():
    disk = Disk()
    disk.flavor = "some-disk-flavor"
    disk.id = str(uuid.uuid4())
    disk.persistent = True
    disk.new_disk = True
    disk.capacity_gb = 2
    disk.flavor_info = Flavor()
    disk.flavor_info.name = "some-disk-flavor"
    disk.flavor_info.cost = []
    return [disk]
class AgentCommonTests(object):

    REGEX_TIME = "^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)*$"

    DEFAULT_DISK_FLAVOR = Flavor("default", [])

    def set_host_mode(self, mode):
        response = self.host_client.set_host_mode(SetHostModeRequest(mode))
        assert_that(response.result, equal_to(SetHostModeResultCode.OK))

    def _validate_datastore_id(self, datastore_id):
        """ Check if id is in one of the expected formats. """

        # standard uuids are 36 chars
        # vmfs volume uuids are 35 chars
        # nfs volume uuids are 17 chars
        assert_that(datastore_id, matches_regexp("^[0-9a-f-]+$"))
        assert_that(len(datastore_id),
                    any_of(equal_to(17), equal_to(35), equal_to(36)))

    def _delete_image(self, image, result_code=DeleteDirectoryResultCode.OK):
        resp = self.host_client.delete_directory(
            DeleteDirectoryRequest(image.datastore.id, compond_path_join(IMAGE_FOLDER_NAME_PREFIX, image.id)))
        assert_that(resp.result, is_(result_code))

    def test_get_nfc_ticket(self):
        request = ServiceTicketRequest(
            service_type=ServiceType.NFC,
            datastore_name=self.get_image_datastore())
        response = self.host_client.get_service_ticket(request)
        assert_that(response.result, is_(ServiceTicketResultCode.OK))

        ticket = response.ticket
        assert_that(ticket, not_none())
        assert_that(ticket.port, is_(902))
        assert_that(ticket.service_type, is_("nfc"))
        assert_that(ticket.session_id, not_none())
        assert_that(ticket.ssl_thumbprint, not_none())

        # TODO(agui): try ticket with nfc client

    def test_get_vim_ticket(self):
        request = ServiceTicketRequest(ServiceType.VIM)
        response = self.host_client.get_service_ticket(request)
        assert_that(response.result, is_(ServiceTicketResultCode.OK))

    def test_get_service_ticket_not_found(self):
        request = ServiceTicketRequest(ServiceType.NFC, 'not_existed')
        response = self.host_client.get_service_ticket(request)
        assert_that(response.result, is_(ServiceTicketResultCode.NOT_FOUND))

    def test_get_mks_ticket(self):
        vm = VmWrapper(self.host_client)

        # Before VM is created, result should be VM_NOT_FOUND
        request = MksTicketRequest(vm.id)
        response = self.host_client.get_mks_ticket(request)
        assert_that(response.result, is_(MksTicketResultCode.VM_NOT_FOUND))

        # After VM created, but before VM is powered on, result should be
        # INVALID_VM_POWER_STATE
        vm.create()
        response = self.host_client.get_mks_ticket(request)
        assert_that(response.result, is_(
            MksTicketResultCode.INVALID_VM_POWER_STATE))

        # After Vm powered on, result should be OK
        vm.power(Host.PowerVmOp.ON, Host.PowerVmOpResultCode.OK)
        response = self.host_client.get_mks_ticket(request)
        assert_that(response.result, is_(MksTicketResultCode.OK))
        assert_that(response.ticket.ticket, not_none())
        assert_that(response.ticket.cfg_file, not_none())

        vm.power(Host.PowerVmOp.OFF, Host.PowerVmOpResultCode.OK)
        vm.delete()

    def test_create_delete_vm(self):
        """Test that the agent can create and delete a VM."""
        vm = VmWrapper(self.host_client)

        vm.get_vm(False)
        vm.create()

        # VM already exists
        vm.get_vm(True)
        vm.create(expect=Host.CreateVmResultCode.VM_ALREADY_EXIST)

        # VM in wrong state
        vm.power(Host.PowerVmOp.ON, Host.PowerVmOpResultCode.OK)
        vm.delete(expect=Host.DeleteVmResultCode.VM_NOT_POWERED_OFF)
        vm.power(Host.PowerVmOp.OFF, Host.PowerVmOpResultCode.OK)

        vm.delete()

        # VM no longer exists
        vm.delete(expect=Host.DeleteVmResultCode.VM_NOT_FOUND)

    def test_continuous_create_delete_vm(self):
        vm = VmWrapper(self.host_client)
        for i in xrange(10):
            vm.create()
            vm.delete()

    def _test_create_vm_with_ephemeral_disks(self, image_id, concurrent=False,
                                             new_client=False):
        if new_client:
            client = self.create_client()
        else:
            client = self.host_client
        vm_wrapper = VmWrapper(client)

        image = DiskImage(image_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),
            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)
        ]

        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())
        assert_that(response.vm.datastore, not_none())
        assert_that(response.vm.datastore.id, not_none())
        assert_that(response.vm.datastore.name, not_none())

        rc = Host.PowerVmOpResultCode
        op = Host.PowerVmOp

        vm_wrapper.power(op.ON, rc.OK)
        vm_wrapper.power(op.OFF, rc.OK)

        vm_wrapper.delete(request=vm_wrapper.delete_request(disk_ids=[]))

        # This is to test the image doesn't go away with the delete request,
        # Otherwise this create vm request will fail.
        if not concurrent:
            # create the VM with new VM_ID
            vm_wrapper = VmWrapper(client)
            reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation
            request = vm_wrapper.create_request(res_id=reservation)
            vm_wrapper.create(request=request)
            vm_wrapper.delete(request=vm_wrapper.delete_request(disk_ids=[]))

    def test_batch_get_resources(self):
        """Test that the agent can return resources in batch."""
        vms = []
        for _ in xrange(2):
            vm = VmWrapper(self.host_client)
            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)
            ]

            reservation = vm.place_and_reserve(vm_disks=disks).reservation

            request = vm.create_request(reservation)
            vm.create(request=request)
            vms.append((vm, disks))

        request = GetResourcesRequest()
        response = rpc_call(self.host_client.get_resources, request)
        assert_that(response.result, is_(GetResourcesResultCode.OK))

        assert_that(response.resources, has_len(2))
        resources = {}
        for resource in response.resources:
            resources[resource.vm.id] = resource

        for vm, disks in vms:
            assert_that(resources, has_key(vm.id))
            vm.delete(request=vm.delete_request())

    def test_create_delete_disks(self):
        """Test that the agent can create and delete disks."""
        vm_wrapper = VmWrapper(self.host_client)

        rc = Host.CreateDisksResultCode

        disk_1 = new_id()
        disk_2 = new_id()

        disks = [
            Disk(disk_1, self.DEFAULT_DISK_FLAVOR.name, True, True,
                 capacity_gb=1, flavor_info=self.DEFAULT_DISK_FLAVOR),
            Disk(disk_2, self.DEFAULT_DISK_FLAVOR.name, True, True,
                 capacity_gb=1, flavor_info=self.DEFAULT_DISK_FLAVOR),
        ]

        # Invalid reservation id
        vm_wrapper.create_disk(disks[0], new_id(), expect=rc.INVALID_RESERVATION)

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

        # Delete 2 disks: 1 - valid, 2 - valid
        disk_ids = [disk_1, disk_2]
        vm_wrapper.delete_disks(disk_ids, validate=True)

        # Delete 2 disks: 1 - invalid (deleted), 2 - invalid (deleted)
        response = vm_wrapper.delete_disks(disk_ids)
        assert_that(len(response.disk_errors), equal_to(2))
        assert_that(response.disk_errors, has_key(disk_1))
        assert_that(response.disk_errors[disk_1].result,
                    is_(DeleteDiskResultCode.DISK_NOT_FOUND))
        assert_that(response.disk_errors, has_key(disk_2))
        assert_that(response.disk_errors[disk_2].result,
                    is_(DeleteDiskResultCode.DISK_NOT_FOUND))

    def test_create_disk_from_image(self):
        """Test that the agent can clone images"""
        vm = VmWrapper(self.host_client)

        tests = [
            {"im": DiskImage("invalid", CloneType.FULL_COPY), "rc": CreateDiskResultCode.SYSTEM_ERROR},
            {"im": None, "rc": CreateDiskResultCode.OK},
            {"im": DiskImage("ttylinux", CloneType.FULL_COPY), "rc": CreateDiskResultCode.OK},
            {"im": DiskImage("ttylinux", CloneType.COPY_ON_WRITE), "rc": CreateDiskResultCode.SYSTEM_ERROR},
        ]

        for test in tests:
            disk = Disk(new_id(), self.DEFAULT_DISK_FLAVOR.name, False, True,
                        image=test["im"], flavor_info=self.DEFAULT_DISK_FLAVOR)
            if disk.image is None:
                disk.capacity_gb = 1
            else:
                disk.capacity_gb = 0

            reservation = vm.place_and_reserve(disk=disk).reservation

            response = vm.create_disk(disk, reservation)

            if test["rc"] == CreateDiskResultCode.OK:
                assert_that(response.disk_errors, has_len(1))
                assert_that(response.disk_errors, has_key(disk.id))
                assert_that(response.disk_errors[disk.id].result,
                            is_(test["rc"]))

                response = vm.delete_disks([disk.id])
                assert_that(response.disk_errors, has_len(1))
                assert_that(response.disk_errors, has_key(disk.id))
                assert_that(response.disk_errors[disk.id].result,
                            is_(DeleteDiskResultCode.OK))
            else:
                assert_that(response.disk_errors, has_len(1))
                assert_that(response.disk_errors, has_key(disk.id))
                disk_error = response.disk_errors[disk.id]
                assert_that(disk_error.result, is_(test["rc"]))

    def test_power_ops(self):
        """Test that the agent can invoke power ops on a VM."""
        vm = VmWrapper(self.host_client)

        vm.create()

        rc = Host.PowerVmOpResultCode
        op = Host.PowerVmOp

        tests = [
            {"op": op.OFF,     "rc": rc.OK},
            {"op": op.RESET,   "rc": rc.INVALID_VM_POWER_STATE},
            {"op": op.ON,      "rc": rc.OK},
            {"op": op.ON,      "rc": rc.OK},
            {"op": op.SUSPEND, "rc": rc.OK},
            {"op": op.SUSPEND, "rc": rc.OK},
            {"op": op.RESUME,  "rc": rc.OK},
            {"op": op.RESUME,  "rc": rc.OK},
            {"op": op.RESET,   "rc": rc.OK},
            {"op": op.OFF,     "rc": rc.OK},
            {"op": 1024,       "rc": rc.SYSTEM_ERROR},
        ]

        for test in tests:
            vm.power(test["op"], expect=test["rc"])

        vm.delete()

        # vm has been deleted, all power ops should result in VM_NOT_FOUND
        for power_op in [op.ON, op.OFF, op.RESET, op.SUSPEND, op.RESUME]:
            vm.power(power_op, expect=rc.VM_NOT_FOUND)

    def _find_configured_datastore_in_host_config(self):
        config_request = Host.GetConfigRequest()
        config_response = self.host_client.get_host_config(config_request)
        assert_that(config_response.hostConfig.datastores, not_none())
        assert_that(config_response.hostConfig.datastores, is_not(empty()))
        logger.debug("Configured test image datastore %s" %
                     self.get_image_datastore())
        for datastore_item in config_response.hostConfig.datastores:
            if datastore_item.name == self.get_image_datastore():
                return datastore_item
        self.fail("datastore list returned by agent does not contain %s" %
                  self.get_image_datastore())

    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 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)

    def test_get_images_datastore_not_found(self):
        request = Host.GetImagesRequest("datastore_not_there")
        response = self.host_client.get_images(request)
        assert_that(response.result, is_(
            GetImagesResultCode.DATASTORE_NOT_FOUND))

    def test_invalid_reservation(self):
        """Test that the agent rejects invalid reservations."""

        vm = VmWrapper(self.host_client)
        rc = Host.CreateVmResultCode.INVALID_RESERVATION

        # invalid reservation id
        request = vm.create_request(res_id="42")

        vm.create(request=request, expect=rc)

        # invalid flavor
        vm.set_flavor("vanilla")

        vm.create(request=request, expect=rc)

    def test_stale_generation(self):
        """Test that the agent rejects stale generations."""
        vm = VmWrapper(self.host_client)
        place_response = vm.place()
        for i in range(HostHandler.GENERATION_GAP + 1):
            logger.debug("reserve #%d" % i)
            vm.place_and_reserve()
        vm.reserve(place_response=place_response,
                   expect=Host.ReserveResultCode.STALE_GENERATION)

    def test_get_host_config(self):
        """Test that the agent responds with Host configuration"""
        request = Host.GetConfigRequest()
        response = self.host_client.get_host_config(request)
        assert_that(response.hostConfig.agent_id,
                    matches_regexp("[0-9a-f-]{36}"))
        datastores = response.hostConfig.datastores
        assert_that(datastores, has_length(len(self.get_all_datastores())))
        for datastore in datastores:
            assert_that(self.get_all_datastores(), has_item(datastore.name))
            assert_that(datastore.type, not_none())
        self._validate_datastore_id(datastores[0].id)
        assert_that(response.hostConfig.networks, not_none())
        vm_networks = [network for network in response.hostConfig.networks
                       if NetworkType.VM in network.types]
        assert_that(len(vm_networks), greater_than_or_equal_to(1))

    def test_get_mode(self):
        response = self.host_client.get_host_mode(GetHostModeRequest())
        assert_that(response.result, equal_to(GetHostModeResultCode.OK))
        # Disable this test because the host could go to other mode. Will
        # enable it after exit_maintenance is implemented
        assert_that(response.mode, equal_to(HostMode.NORMAL))

    def test_enter_maintenance(self):
        vm_wrapper = VmWrapper(self.host_client)

        # Enter entering-maintenance
        self.set_host_mode(HostMode.ENTERING_MAINTENANCE)

        # Check mode. It should be ENTERING_MAINTENANCE.
        response = self.host_client.get_host_mode(GetHostModeRequest())
        assert_that(response.result, equal_to(GetHostModeResultCode.OK))
        assert_that(response.mode, equal_to(HostMode.ENTERING_MAINTENANCE))

        # Test place. It should return INVALID_STATE.
        vm_wrapper.place(expect=PlaceResultCode.INVALID_STATE)

        # Enter maintenance
        self.set_host_mode(HostMode.MAINTENANCE)

        # Check mode. It should be MAINTENANCE.
        response = self.host_client.get_host_mode(GetHostModeRequest())
        assert_that(response.result, equal_to(GetHostModeResultCode.OK))
        assert_that(response.mode, equal_to(HostMode.MAINTENANCE))

        # Test place. It should return INVALID_STATE.
        vm_wrapper.place(expect=PlaceResultCode.INVALID_STATE)

        # Exit maintenance
        self.set_host_mode(HostMode.NORMAL)

        # Check mode. It should be NORMAL.
        response = self.host_client.get_host_mode(GetHostModeRequest())
        assert_that(response.result, equal_to(GetHostModeResultCode.OK))
        assert_that(response.mode, equal_to(HostMode.NORMAL))

        # Test place. Should be OK.
        vm_wrapper.place(expect=PlaceResultCode.OK)

    def test_get_resources_not_found(self):
        for locator in [Locator(vm=VmLocator("1234567")),
                        Locator(disk=DiskLocator("891"))]:
            request = GetResourcesRequest([locator])
            response = rpc_call(self.host_client.get_resources, request)
            assert_that(response.result, is_(GetResourcesResultCode.OK))
            assert_that(response.resources, is_([]))

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

        # create disk
        reservation = vm_wrapper.place_and_reserve(vm_disks=disks).reservation

        # create vm without network info specified
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id
        result = vm_wrapper.get_network(vm_id=vm_id)
        assert_that(len(result.network_info), is_(1))
        assert_that(result.network_info[0].network == "VM Network")

        # delete the disk and the vm
        vm_wrapper.delete(request=vm_wrapper.delete_request())

    def test_attach_detach_disks(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 3 disks
        image = DiskImage("ttylinux", CloneType.FULL_COPY)
        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=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 and disks
        vm_wrapper.delete(request=vm_wrapper.delete_request(),
                          expect=Host.DeleteVmResultCode.OPERATION_NOT_ALLOWED)
        vm_wrapper.detach_disks(vm_id, disk_ids)
        vm_wrapper.delete(request=vm_wrapper.delete_request())
        vm_wrapper.delete_disks([disk.id for disk in disks], validate=True)

    def test_attach_detach_disks_vm_suspended(self):
        vm_wrapper = VmWrapper(self.host_client)

        # create a vm
        vm_id = vm_wrapper.create().vm.id

        # create a disk
        disk = Disk(new_id(), 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)

        # suspend vm and attach disk should fail
        vm_wrapper.power(Host.PowerVmOp.ON, Host.PowerVmOpResultCode.OK)
        vm_wrapper.power(Host.PowerVmOp.SUSPEND, Host.PowerVmOpResultCode.OK)
        vm_wrapper.attach_disks(vm_id, [disk.id], expect=Host.VmDiskOpResultCode.INVALID_VM_POWER_STATE)

        # resume vm and attach disk
        vm_wrapper.power(Host.PowerVmOp.RESUME, Host.PowerVmOpResultCode.OK)
        vm_wrapper.attach_disks(vm_id, [disk.id])

        # suspend vm and detach disk should fail
        vm_wrapper.power(Host.PowerVmOp.SUSPEND, Host.PowerVmOpResultCode.OK)
        vm_wrapper.detach_disks(vm_id, [disk.id], expect=Host.VmDiskOpResultCode.INVALID_VM_POWER_STATE)

        # power off and detach disk
        vm_wrapper.power(Host.PowerVmOp.OFF, Host.PowerVmOpResultCode.OK)
        vm_wrapper.detach_disks(vm_id, [disk.id])

        # clean up
        vm_wrapper.delete_disks([disk.id])
        vm_wrapper.delete()

    def test_create_vm_with_ephemeral_disks(self):
        self._test_create_vm_with_ephemeral_disks("ttylinux")

    def _update_agent_config(self):
        """
        Update the agent config using the bootstrap interface.
        Verifies that thrift requests after a config update return back
        SYSTEM_ERROR and the agent is stopped.
        :return the request we used to configure the host with.
        """
        req = ProvisionRequest()
        req.datastores = ["bootstrap_datastore"]
        addr = ServerAddress(host="foobar", port=8835)
        req.address = addr
        req.memory_overcommit = 2.0
        res = self.control_client.provision(req)
        self.assertEqual(res.result, ProvisionResultCode.OK)

        # Now check that the agent went down and all requests fail until the
        # agent restarts.
        # Use a time greater than the restart poll thread.
        remaining_sleep_time = 15
        sleep_time = 0.5
        agent_restarted = False
        while 0 < remaining_sleep_time:
            try:
                res = self.control_client.get_agent_status()
                # Verify that the response is restarting
                self.assertEqual(res.status, AgentStatusCode.RESTARTING)
                time.sleep(sleep_time)
                remaining_sleep_time -= sleep_time
            except TTransport.TTransportException:
                agent_restarted = True
                break
            except:
                logger.debug("Caught exception, assuming restart: ",
                             exc_info=True)
                agent_restarted = True
                break
        self.assertTrue(agent_restarted)
        return req

    def _update_agent_invalid_config(self):
        """
        Negative test case to update the agent with an invalid config
        """
        req = ProvisionRequest()
        req.datastores = ["bootstrap_datastore"]
        addr = ServerAddress(host="foobar", port=8835)
        req.address = addr
        req.memory_overcommit = 0.5
        res = self.control_client.provision(req)
        self.assertEqual(res.result, ProvisionResultCode.INVALID_CONFIG)

    def _validate_post_boostrap_config(self, req):
        """
        Validates that the post boostrap config is the same as the one we had
        requested for.
        """
        host_config_request = Host.GetConfigRequest()
        res = self.host_client.get_host_config(host_config_request)
        # XXX Fix me the host config should return more useful info
        datastores = req.datastores
        self.assertEqual([ds.name for ds in res.hostConfig.datastores], datastores)

    def test_ping(self):
        """ Test ping against the control service """
        # Test runs against both real and fake hosts
        ping_req = PingRequest()
        self.control_client.ping(ping_req)

    def test_version(self):
        req = VersionRequest()
        response = self.control_client.get_version(req)
        assert_that(response.result, equal_to(VersionResultCode.OK))
        assert_that(response.version, not_none())
        assert_that(response.revision, not_none())

    def get_image_datastore(self):
        return self.get_all_datastores()[0]

    def get_all_datastores(self):
        """Get the all datastore names configured in the tested agent
        :return: list of str, datastore name
        """
        assert_that(self._datastores, not_none())
        assert_that(self._datastores, is_not(empty()))
        return self._datastores

    def test_get_network_mac_address(self):
        vm_wrapper = VmWrapper(self.host_client)

        # create a vm
        reservation = vm_wrapper.place_and_reserve().reservation
        request = vm_wrapper.create_request(res_id=reservation)
        vm_id = vm_wrapper.create(request=request).vm.id
        result = vm_wrapper.get_network(vm_id=vm_id)
        assert_that(len(result.network_info), is_(1))

        # power on the vm
        vm_wrapper.power(Host.PowerVmOp.ON, Host.PowerVmOpResultCode.OK)
        result = vm_wrapper.get_network(vm_id=vm_id)
        assert_that(len(result.network_info), is_(1))
        self.assertTrue(result.network_info[0].mac_address)

        # delete the vm
        vm_wrapper.power(Host.PowerVmOp.OFF, Host.PowerVmOpResultCode.OK)
        vm_wrapper.delete()
Esempio n. 8
0
    def test_reserve_disk(self, constraint_value, placement_id, expected):
        disk_id = "disk_id_1"
        disk_flavor = "disk_flavor_1"

        def reserve_disk_validate(vm, disks):
            assert_that(vm is None)
            assert isinstance(disks, list)
            assert_that(len(disks) is 1)
            disk = disks[0]
            assert isinstance(disk, HostDisk)
            assert_that(disk.id, equal_to(disk_id))
            assert_that(disk.flavor.name, equal_to(disk_flavor))
            reserve_constraints = disk.constraints
            if reserve_constraints:
                assert isinstance(reserve_constraints, list)
                assert_that(len(reserve_constraints) is 1)
                reserve_constraint = reserve_constraints[0]
                assert_that(
                    reserve_constraint.type is ResourceConstraintType.DATASTORE
                )
                assert_that(reserve_constraint.values, equal_to([
                    expected,
                ]))

            reserve_placement = disk.placement
            if reserve_placement:
                assert_that(
                    reserve_placement.type is ResourcePlacementType.DISK)
                assert_that(reserve_placement.resource_id, equal_to(disk_id))
                assert_that(reserve_placement.container_id, equal_to(expected))
            return "reservation_id"

        handler = HostHandler(MagicMock())
        mocked_reserve = MagicMock()
        mocked_reserve.side_effect = reserve_disk_validate
        handler.hypervisor.placement_manager = MagicMock()
        handler.hypervisor.placement_manager.reserve = mocked_reserve

        constraints = None
        placement_list = None

        if constraint_value:
            constraint = ResourceConstraint()
            constraint.values = [constraint_value]
            constraint.type = ResourceConstraintType.DATASTORE
            constraints = [constraint]

        if placement_id:
            placement = ResourcePlacement()
            placement.type = ResourcePlacementType.DISK
            placement.container_id = placement_id
            placement.resource_id = disk_id
            placement_list = ResourcePlacementList([placement])

        flavor_info = Flavor(name=disk_flavor,
                             cost=[QuotaLineItem("a", "b", 1)])
        disk = Disk(id=disk_id,
                    flavor=disk_flavor,
                    persistent=True,
                    new_disk=True,
                    capacity_gb=2,
                    flavor_info=flavor_info,
                    resource_constraints=constraints)
        request = ReserveRequest()
        request.generation = 1
        request.resource = Resource(vm=None,
                                    disks=[disk],
                                    placement_list=placement_list)

        response = handler.reserve(request)
        assert_that(response.result, equal_to(ReserveResultCode.OK))
Esempio n. 9
0
    def test_reserve_vm(self):
        disk_ids = ["disk_id_1", "disk_id_2", "disk_id_3"]
        datastore_ids = ["datastore_1", "datastore_2", "datastore_3"]
        disk_flavor = "disk_flavor_1"
        networks = ["net_1", "net_2"]
        vm_flavor = "vm_flavor_1"
        vm_id = "vm_id_1"

        def reserve_vm_validate(vm, disks):
            assert_that(vm)
            assert_that(not disks)
            assert_that(vm.id, equal_to(vm_id))
            # Check VM placement
            vm_placement = vm.placement
            assert_that(vm_placement is not None)
            assert_that(vm_placement.type is ResourcePlacementType.VM)
            assert_that(vm_placement.resource_id, equal_to(vm_id))
            assert_that(vm_placement.container_id, equal_to(datastore_ids[0]))

            # Check VM networks
            vm_networks = vm.networks
            assert_that(vm_networks is not None)
            assert_that(set(networks), equal_to(set(vm_networks)))

            disks = vm.disks
            assert_that(len(disks) is 3)
            disk_index = 0
            for vm_disk in disks:
                assert_that(vm_disk.id, equal_to(disk_ids[disk_index]))
                assert_that(vm_disk.placement is not None)
                disk_placement = vm_disk.placement
                assert_that(disk_placement.type is ResourcePlacementType.DISK)
                assert_that(disk_placement.resource_id, equal_to(vm_disk.id))
                assert_that(disk_placement.container_id,
                            equal_to(datastore_ids[disk_index]))
                disk_index += 1
            return "reservation_id"

        handler = HostHandler(MagicMock())
        mocked_reserve = MagicMock()
        mocked_reserve.side_effect = reserve_vm_validate
        handler.hypervisor.placement_manager = MagicMock()
        handler.hypervisor.placement_manager.reserve = mocked_reserve

        placements = []

        # Add VM placement info
        placement = ResourcePlacement()
        placement.type = ResourcePlacementType.VM
        placement.resource_id = vm_id
        placement.container_id = datastore_ids[0]
        placements.append(placement)

        # Add Network placement info : net_1
        placement = ResourcePlacement()
        placement.type = ResourcePlacementType.NETWORK
        placement.resource_id = vm_id
        placement.container_id = networks[0]
        placements.append(placement)

        # Add Network placement info : net_2
        placement = ResourcePlacement()
        placement.type = ResourcePlacementType.NETWORK
        placement.resource_id = vm_id
        placement.container_id = networks[1]
        placements.append(placement)

        # Add disks placement info
        index = 0
        for disk_id in disk_ids:
            placement = ResourcePlacement()
            placement.type = ResourcePlacementType.DISK
            placement.container_id = datastore_ids[index]
            index += 1
            placement.resource_id = disk_id
            placements.append(placement)

        placement_list = ResourcePlacementList(placements)

        disk_flavor_info = Flavor(name=disk_flavor,
                                  cost=[QuotaLineItem("size", "1", 1)])
        disks = []
        for disk_id in disk_ids:
            disk = Disk(id=disk_id,
                        flavor=disk_flavor,
                        persistent=True,
                        new_disk=True,
                        capacity_gb=2,
                        flavor_info=disk_flavor_info)
            disks.append(disk)

        vm_flavor_info = Flavor(name=vm_flavor,
                                cost=[QuotaLineItem("cpu", "1", 5)])

        vm = Vm(vm_id, vm_flavor, State.STOPPED, None, None, disks,
                vm_flavor_info)

        request = ReserveRequest()
        request.generation = 1
        request.resource = Resource(vm=vm,
                                    disks=None,
                                    placement_list=placement_list)

        response = handler.reserve(request)
        assert_that(response.result, equal_to(ReserveResultCode.OK))

        # test reserve under entering-maintenance-mode and maintenance mode
        state = common.services.get(ServiceName.MODE)
        state.set_mode(MODE.ENTERING_MAINTENANCE)
        request = MagicMock()
        response = handler.reserve(request)
        assert_that(response.result,
                    equal_to(ReserveResultCode.OPERATION_NOT_ALLOWED))

        state.set_mode(MODE.MAINTENANCE)
        response = handler.reserve(request)
        assert_that(response.result,
                    equal_to(ReserveResultCode.OPERATION_NOT_ALLOWED))