diff --git a/nova/tests/virt/xenapi/test_vm_utils.py b/nova/tests/virt/xenapi/test_vm_utils.py index f0731c7e913d..49c1c3cf751a 100644 --- a/nova/tests/virt/xenapi/test_vm_utils.py +++ b/nova/tests/virt/xenapi/test_vm_utils.py @@ -980,13 +980,10 @@ class VDIOtherConfigTestCase(VMUtilsTestBase): def VDI_add_to_other_config(ref, key, value): other_config[key] = value - def VDI_get_record(ref): - return {'other_config': {}} - # Stubbing on the session object and not class so we don't pollute # other tests self.session.VDI_add_to_other_config = VDI_add_to_other_config - self.session.VDI_get_record = VDI_get_record + self.session.VDI_get_other_config = lambda vdi: {} vm_utils._create_image(self.context, self.session, self.fake_instance, 'myvdi', 'image1', vm_utils.ImageType.DISK_VHD) @@ -1003,16 +1000,13 @@ class VDIOtherConfigTestCase(VMUtilsTestBase): def VDI_add_to_other_config(ref, key, value): other_config[key] = value - def VDI_get_record(ref): - return {'other_config': {}} - def call_plugin_serialized(*args, **kwargs): return {'root': {'uuid': 'aaaa-bbbb-cccc-dddd'}} # Stubbing on the session object and not class so we don't pollute # other tests self.session.VDI_add_to_other_config = VDI_add_to_other_config - self.session.VDI_get_record = VDI_get_record + self.session.VDI_get_other_config = lambda vdi: {} self.session.call_plugin_serialized = call_plugin_serialized self.stubs.Set(vm_utils, 'get_sr_path', lambda *a, **k: None) @@ -1900,16 +1894,25 @@ class StripBaseMirrorTestCase(VMUtilsTestBase): @mock.patch.object(vm_utils, '_try_strip_base_mirror_from_vdi') def test_strip_base_mirror_from_vdis(self, mock_strip): + def call_xenapi(method, arg): + if method == "VM.get_VBDs": + return ['VBD_ref_1', 'VBD_ref_2'] + if method == "VBD.get_VDI": + return 'VDI' + arg[3:] + return "Unexpected call_xenapi: %s.%s" % (method, arg) + session = mock.Mock() - session.call_xenapi.return_value = {"VDI": "ref", "foo": "bar"} + session.call_xenapi.side_effect = call_xenapi vm_utils.strip_base_mirror_from_vdis(session, "vm_ref") expected = [mock.call('VM.get_VBDs', "vm_ref"), - mock.call('VBD.get_record', "VDI"), - mock.call('VBD.get_record', "foo")] + mock.call('VBD.get_VDI', "VBD_ref_1"), + mock.call('VBD.get_VDI', "VBD_ref_2")] self.assertEqual(expected, session.call_xenapi.call_args_list) - expected = [mock.call(session, "ref"), mock.call(session, "ref")] + + expected = [mock.call(session, "VDI_ref_1"), + mock.call(session, "VDI_ref_2")] self.assertEqual(expected, mock_strip.call_args_list) diff --git a/nova/tests/virt/xenapi/test_vmops.py b/nova/tests/virt/xenapi/test_vmops.py index a52c90574896..bbdc0413ba36 100644 --- a/nova/tests/virt/xenapi/test_vmops.py +++ b/nova/tests/virt/xenapi/test_vmops.py @@ -41,7 +41,7 @@ class VMOpsTestBase(stubs.XenAPITestBaseNoDB): 'test_pass') self.vmops = vmops.VMOps(self._session, fake.FakeVirtAPI()) - def create_vm(self, name, state="running"): + def create_vm(self, name, state="Running"): vm_ref = xenapi_fake.create_vm(name, state) self.vms.append(vm_ref) vm = xenapi_fake.get_record("VM", vm_ref) diff --git a/nova/virt/xenapi/fake.py b/nova/virt/xenapi/fake.py index efcded9ee99a..b10864fc2de3 100644 --- a/nova/virt/xenapi/fake.py +++ b/nova/virt/xenapi/fake.py @@ -238,6 +238,7 @@ def after_VBD_create(vbd_ref, vbd_rec): def after_VM_create(vm_ref, vm_rec): """Create read-only fields in the VM record.""" + vm_rec.setdefault('domid', -1) vm_rec.setdefault('is_control_domain', False) vm_rec.setdefault('is_a_template', False) vm_rec.setdefault('memory_static_max', str(8 * units.Gi)) @@ -718,6 +719,7 @@ class SessionBase(object): raise Failure(['VM_BAD_POWER_STATE', 'fake-opaque-ref', db_ref['power_state'].lower(), 'halted']) db_ref['power_state'] = 'Running' + db_ref['domid'] = random.randrange(1, 1 << 16) def VM_clean_reboot(self, session, vm_ref): return self._VM_reboot(session, vm_ref) @@ -728,6 +730,7 @@ class SessionBase(object): def VM_hard_shutdown(self, session, vm_ref): db_ref = _db_content['VM'][vm_ref] db_ref['power_state'] = 'Halted' + db_ref['domid'] = -1 VM_clean_shutdown = VM_hard_shutdown def VM_suspend(self, session, vm_ref): diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 5f7a4e00506a..59b106019df6 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -395,8 +395,9 @@ def find_vbd_by_number(session, vm_ref, number): if vbd_refs: for vbd_ref in vbd_refs: try: - vbd_rec = session.call_xenapi("VBD.get_record", vbd_ref) - if vbd_rec['userdevice'] == str(number): + user_device = session.call_xenapi("VBD.get_userdevice", + vbd_ref) + if user_device == str(number): return vbd_ref except session.XenAPI.Failure as exc: LOG.exception(exc) @@ -559,8 +560,7 @@ def get_vdi_uuid_for_volume(session, connection_data): else: try: vdi_ref = volume_utils.introduce_vdi(session, sr_ref) - vdi_rec = session.call_xenapi("VDI.get_record", vdi_ref) - vdi_uuid = vdi_rec['uuid'] + vdi_uuid = session.call_xenapi("VDI.get_uuid", vdi_ref) except volume_utils.StorageError as exc: LOG.exception(exc) volume_utils.forget_sr(session, sr_ref) @@ -687,14 +687,15 @@ def _get_vdi_other_config(disk_type, instance=None): def _set_vdi_info(session, vdi_ref, vdi_type, name_label, description, instance): - vdi_rec = session.call_xenapi('VDI.get_record', vdi_ref) + existing_other_config = session.call_xenapi('VDI.get_other_config', + vdi_ref) session.call_xenapi('VDI.set_name_label', vdi_ref, name_label) session.call_xenapi('VDI.set_name_description', vdi_ref, description) other_config = _get_vdi_other_config(vdi_type, instance=instance) for key, value in other_config.iteritems(): - if key not in vdi_rec['other_config']: + if key not in existing_other_config: session.call_xenapi( "VDI.add_to_other_config", vdi_ref, key, value) @@ -752,9 +753,8 @@ def _try_strip_base_mirror_from_vdi(session, vdi_ref): def strip_base_mirror_from_vdis(session, vm_ref): # NOTE(johngarbutt) part of workaround for XenServer bug CA-98606 vbd_refs = session.call_xenapi("VM.get_VBDs", vm_ref) - for vbd in vbd_refs: - vbd_rec = session.call_xenapi("VBD.get_record", vbd) - vdi_ref = vbd_rec['VDI'] + for vbd_ref in vbd_refs: + vdi_ref = session.call_xenapi("VBD.get_VDI", vbd_ref) _try_strip_base_mirror_from_vdi(session, vdi_ref) @@ -1276,7 +1276,7 @@ def _get_image_vdi_label(image_id): def _create_cached_image(context, session, instance, name_label, image_id, image_type): sr_ref = safe_find_sr(session) - sr_type = session.call_xenapi('SR.get_record', sr_ref)["type"] + sr_type = session.call_xenapi('SR.get_type', sr_ref) if CONF.use_cow_images and sr_type != "ext": LOG.warning(_("Fast cloning is only supported on default local SR " @@ -1706,8 +1706,8 @@ def lookup_vm_vdis(session, vm_ref): try: vdi_ref = session.call_xenapi("VBD.get_VDI", vbd_ref) # Test valid VDI - record = session.call_xenapi("VDI.get_record", vdi_ref) - LOG.debug(_('VDI %s is still available'), record['uuid']) + vdi_uuid = session.call_xenapi("VDI.get_uuid", vdi_ref) + LOG.debug(_('VDI %s is still available'), vdi_uuid) vbd_other_config = session.call_xenapi("VBD.get_other_config", vbd_ref) if not vbd_other_config.get('osvol'): @@ -2151,8 +2151,8 @@ def cleanup_attached_vdis(session): vbd_refs = session.call_xenapi('VM.get_VBDs', this_vm_ref) for vbd_ref in vbd_refs: try: - vbd_rec = session.call_xenapi('VBD.get_record', vbd_ref) - vdi_rec = session.call_xenapi('VDI.get_record', vbd_rec['VDI']) + vdi_ref = session.call_xenapi('VBD.get_VDI', vbd_ref) + vdi_rec = session.call_xenapi('VDI.get_record', vdi_ref) except session.XenAPI.Failure as e: if e.details[0] != 'HANDLE_INVALID': raise diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 99364a8da754..f440a422450d 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -1193,8 +1193,10 @@ class VMOps(object): try: self._delete_from_xenstore(instance, location, vm_ref=vm_ref) - except KeyError: - # catch KeyError for domid if instance isn't running + except exception.InstanceNotFound: + # If the VM is not running then no need to update + # the live xenstore - the param xenstore will be + # used next time the VM is booted pass elif change[0] == '+': self._add_to_param_xenstore(vm_ref, location, @@ -1202,8 +1204,9 @@ class VMOps(object): try: self._write_to_xenstore(instance, location, change[1], vm_ref=vm_ref) - except KeyError: - # catch KeyError for domid if instance isn't running + except exception.InstanceNotFound: + # If the VM is not running then no need to update + # the live xenstore pass @utils.synchronized('xenstore-' + instance['uuid']) @@ -1636,8 +1639,9 @@ class VMOps(object): try: self._write_to_xenstore(instance, location, xs_data, vm_ref=vm_ref) - except KeyError: - # catch KeyError for domid if instance isn't running + except exception.InstanceNotFound: + # If the VM is not running, no need to update the + # live xenstore pass update_nwinfo() @@ -1647,7 +1651,7 @@ class VMOps(object): LOG.debug(_("Creating vifs"), instance=instance) # this function raises if vm_ref is not a vm_opaque_ref - self._session.call_xenapi("VM.get_record", vm_ref) + self._session.call_xenapi("VM.get_domid", vm_ref) for device, vif in enumerate(network_info): vif_rec = self.vif_driver.plug(instance, vif, @@ -1761,8 +1765,10 @@ class VMOps(object): def _get_dom_id(self, instance=None, vm_ref=None, check_rescue=False): vm_ref = vm_ref or self._get_vm_opaque_ref(instance, check_rescue) - vm_rec = self._session.call_xenapi("VM.get_record", vm_ref) - return vm_rec['domid'] + domid = self._session.call_xenapi("VM.get_domid", vm_ref) + if not domid or domid == -1: + raise exception.InstanceNotFound(instance_id=instance['name']) + return domid def _add_to_param_xenstore(self, vm_ref, key, val): """