From de4158861000dedc204314c545cc5682aa38f5f1 Mon Sep 17 00:00:00 2001 From: Jay Lau Date: Thu, 14 Nov 2013 22:12:27 +0800 Subject: [PATCH] Add context as parameter for resume Now for KVM when resume an instance with block storage, nova compute will throw exception and failed to resume the VM. The root cause is that when resume a VM with block storage, libvirt driver needs to call conductor via rpcapi to update block device, but the function of resume() do not have context, this will cause RPC api failed. Change-Id: I712777ed1d893a2b6463d30c407b0a677e37b602 Closes-Bug: #1241337 --- nova/compute/manager.py | 2 +- nova/tests/virt/hyperv/test_hypervapi.py | 6 ++-- nova/tests/virt/libvirt/test_libvirt.py | 36 +++++++++++++++++++++ nova/tests/virt/powervm/test_powervm.py | 3 +- nova/tests/virt/test_virt_drivers.py | 4 +-- nova/tests/virt/vmwareapi/test_vmwareapi.py | 6 ++-- nova/virt/driver.py | 13 ++++++-- nova/virt/fake.py | 2 +- nova/virt/hyperv/driver.py | 2 +- nova/virt/libvirt/driver.py | 4 +-- nova/virt/powervm/driver.py | 2 +- nova/virt/vmwareapi/driver.py | 4 +-- nova/virt/xenapi/driver.py | 2 +- 13 files changed, 66 insertions(+), 20 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 141c3148688..c8975ccd7f0 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -3440,7 +3440,7 @@ def resume_instance(self, context, instance): block_device_info = self._get_instance_volume_block_device_info( context, instance) - self.driver.resume(instance, network_info, + self.driver.resume(context, instance, network_info, block_device_info) instance.power_state = self._get_power_state(context, instance) diff --git a/nova/tests/virt/hyperv/test_hypervapi.py b/nova/tests/virt/hyperv/test_hypervapi.py index 1f937af8f47..7909ef03da3 100644 --- a/nova/tests/virt/hyperv/test_hypervapi.py +++ b/nova/tests/virt/hyperv/test_hypervapi.py @@ -543,12 +543,14 @@ def test_suspend_already_suspended(self): constants.HYPERV_VM_STATE_SUSPENDED) def test_resume(self): - self._test_vm_state_change(lambda i: self._conn.resume(i, None), + self._test_vm_state_change(lambda i: self._conn.resume(self._context, + i, None), constants.HYPERV_VM_STATE_SUSPENDED, constants.HYPERV_VM_STATE_ENABLED) def test_resume_already_running(self): - self._test_vm_state_change(lambda i: self._conn.resume(i, None), None, + self._test_vm_state_change(lambda i: self._conn.resume(self._context, + i, None), None, constants.HYPERV_VM_STATE_ENABLED) def test_power_off(self): diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py index 89f79bb26f3..c0dc97fea25 100644 --- a/nova/tests/virt/libvirt/test_libvirt.py +++ b/nova/tests/virt/libvirt/test_libvirt.py @@ -49,6 +49,7 @@ from nova.openstack.common import loopingcall from nova.openstack.common import processutils from nova.openstack.common import uuidutils +from nova.pci import pci_manager from nova import test from nova.tests import fake_network import nova.tests.image.fake @@ -4358,6 +4359,41 @@ def fake_get_info(instance_name): conn._hard_reboot(self.context, instance, network_info, block_device_info) + def test_resume(self): + dummyxml = ("instance-0000000a" + "" + "" + "" + "" + "" + "" + "" + "") + instance = db.instance_create(self.context, self.test_instance) + network_info = _fake_network_info(self.stubs, 1) + block_device_info = None + conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + with contextlib.nested( + mock.patch.object(conn, '_get_existing_domain_xml', + return_value=dummyxml), + mock.patch.object(conn, '_create_domain_and_network', + return_value='fake_dom'), + mock.patch.object(conn, '_attach_pci_devices'), + mock.patch.object(pci_manager, 'get_instance_pci_devs', + return_value='fake_pci_devs'), + ) as (_get_existing_domain_xml, _create_domain_and_network, + _attach_pci_devices, get_instance_pci_devs): + conn.resume(self.context, instance, network_info, + block_device_info) + _get_existing_domain_xml.assert_has_calls([mock.call(instance, + network_info, block_device_info)]) + _create_domain_and_network.assert_has_calls([mock.call(dummyxml, + instance, network_info, + block_device_info=block_device_info, + context=self.context)]) + _attach_pci_devices.assert_has_calls([mock.call('fake_dom', + 'fake_pci_devs')]) + def test_destroy_undefines(self): mock = self.mox.CreateMock(libvirt.virDomain) mock.ID() diff --git a/nova/tests/virt/powervm/test_powervm.py b/nova/tests/virt/powervm/test_powervm.py index ef55aa38c72..b0542c95c8b 100644 --- a/nova/tests/virt/powervm/test_powervm.py +++ b/nova/tests/virt/powervm/test_powervm.py @@ -841,7 +841,8 @@ def test_suspend(self): def test_resume(self): # Check to make sure the method raises NotImplementedError. self.assertRaises(NotImplementedError, self.powervm_connection.resume, - instance=None, network_info=None) + context.get_admin_context(), instance=None, + network_info=None) def test_host_power_action(self): # Check to make sure the method raises NotImplementedError. diff --git a/nova/tests/virt/test_virt_drivers.py b/nova/tests/virt/test_virt_drivers.py index d16f09354a5..f96e64ab52d 100644 --- a/nova/tests/virt/test_virt_drivers.py +++ b/nova/tests/virt/test_virt_drivers.py @@ -374,13 +374,13 @@ def test_suspend(self): @catch_notimplementederror def test_resume_unsuspended_instance(self): instance_ref, network_info = self._get_running_instance() - self.connection.resume(instance_ref, network_info) + self.connection.resume(self.ctxt, instance_ref, network_info) @catch_notimplementederror def test_resume_suspended_instance(self): instance_ref, network_info = self._get_running_instance() self.connection.suspend(instance_ref) - self.connection.resume(instance_ref, network_info) + self.connection.resume(self.ctxt, instance_ref, network_info) @catch_notimplementederror def test_destroy_instance_nonexistent(self): diff --git a/nova/tests/virt/vmwareapi/test_vmwareapi.py b/nova/tests/virt/vmwareapi/test_vmwareapi.py index 2dbe7ec7c9c..56e19b29686 100644 --- a/nova/tests/virt/vmwareapi/test_vmwareapi.py +++ b/nova/tests/virt/vmwareapi/test_vmwareapi.py @@ -497,7 +497,7 @@ def test_resume(self): info = self.conn.get_info({'uuid': self.uuid, 'node': self.instance_node}) self._check_vm_info(info, power_state.SUSPENDED) - self.conn.resume(self.instance, self.network_info) + self.conn.resume(self.context, self.instance, self.network_info) info = self.conn.get_info({'uuid': self.uuid, 'node': self.instance_node}) self._check_vm_info(info, power_state.RUNNING) @@ -505,7 +505,7 @@ def test_resume(self): def test_resume_non_existent(self): self._create_instance_in_the_db() self.assertRaises(exception.InstanceNotFound, self.conn.resume, - self.instance, self.network_info) + self.context, self.instance, self.network_info) def test_resume_not_suspended(self): self._create_vm() @@ -513,7 +513,7 @@ def test_resume_not_suspended(self): 'node': self.instance_node}) self._check_vm_info(info, power_state.RUNNING) self.assertRaises(exception.InstanceResumeFailure, self.conn.resume, - self.instance, self.network_info) + self.context, self.instance, self.network_info) def test_power_on(self): self._create_vm() diff --git a/nova/virt/driver.py b/nova/virt/driver.py index f7c1d6ec04d..77040b24e11 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -419,9 +419,16 @@ def suspend(self, instance): # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() - def resume(self, instance, network_info, block_device_info=None): - """resume the specified instance.""" - # TODO(Vek): Need to pass context in for access to auth_token + def resume(self, context, instance, network_info, block_device_info=None): + """ + resume the specified instance. + + :param context: the context for the resume + :param instance: the instance being resumed + :param network_info: + :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` + :param block_device_info: instance volume block device info + """ raise NotImplementedError() def resume_state_on_host_boot(self, context, instance, network_info, diff --git a/nova/virt/fake.py b/nova/virt/fake.py index b7e4c359026..a4815c71da2 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -198,7 +198,7 @@ def unpause(self, instance): def suspend(self, instance): pass - def resume(self, instance, network_info, block_device_info=None): + def resume(self, context, instance, network_info, block_device_info=None): pass def destroy(self, context, instance, network_info, block_device_info=None, diff --git a/nova/virt/hyperv/driver.py b/nova/virt/hyperv/driver.py index d374f4ec545..e161989e652 100644 --- a/nova/virt/hyperv/driver.py +++ b/nova/virt/hyperv/driver.py @@ -100,7 +100,7 @@ def unpause(self, instance): def suspend(self, instance): self._vmops.suspend(instance) - def resume(self, instance, network_info, block_device_info=None): + def resume(self, context, instance, network_info, block_device_info=None): self._vmops.resume(instance) def power_off(self, instance): diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index b48a12d1835..c6587eb4965 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -2032,12 +2032,12 @@ def suspend(self, instance): pci_manager.get_instance_pci_devs(instance)) dom.managedSave(0) - def resume(self, instance, network_info, block_device_info=None): + def resume(self, context, instance, network_info, block_device_info=None): """resume the specified instance.""" xml = self._get_existing_domain_xml(instance, network_info, block_device_info) dom = self._create_domain_and_network(xml, instance, network_info, - block_device_info) + block_device_info=block_device_info, context=context) self._attach_pci_devices(dom, pci_manager.get_instance_pci_devs(instance)) diff --git a/nova/virt/powervm/driver.py b/nova/virt/powervm/driver.py index 8ab5d37e2a2..b0617b3694c 100644 --- a/nova/virt/powervm/driver.py +++ b/nova/virt/powervm/driver.py @@ -201,7 +201,7 @@ def suspend(self, instance): raise NotImplementedError(_("Suspend is not supported by the" "PowerVM driver.")) - def resume(self, instance, network_info, block_device_info=None): + def resume(self, context, instance, network_info, block_device_info=None): """resume the specified instance.""" raise NotImplementedError(_("Resume is not supported by the" "PowerVM driver.")) diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index da628327019..8f0d8debb3b 100644 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -203,7 +203,7 @@ def suspend(self, instance): """Suspend the specified instance.""" self._vmops.suspend(instance) - def resume(self, instance, network_info, block_device_info=None): + def resume(self, context, instance, network_info, block_device_info=None): """Resume the suspended VM instance.""" self._vmops.resume(instance) @@ -676,7 +676,7 @@ def suspend(self, instance): _vmops = self._get_vmops_for_compute_node(instance['node']) _vmops.suspend(instance) - def resume(self, instance, network_info, block_device_info=None): + def resume(self, context, instance, network_info, block_device_info=None): """Resume the suspended VM instance.""" _vmops = self._get_vmops_for_compute_node(instance['node']) _vmops.resume(instance) diff --git a/nova/virt/xenapi/driver.py b/nova/virt/xenapi/driver.py index aae27a2b5c6..041e11b5069 100644 --- a/nova/virt/xenapi/driver.py +++ b/nova/virt/xenapi/driver.py @@ -318,7 +318,7 @@ def suspend(self, instance): """suspend the specified instance.""" self._vmops.suspend(instance) - def resume(self, instance, network_info, block_device_info=None): + def resume(self, context, instance, network_info, block_device_info=None): """resume the specified instance.""" self._vmops.resume(instance)