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