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
This commit is contained in:
Jay Lau 2013-11-14 22:12:27 +08:00
parent db86ec9237
commit de41588610
13 changed files with 66 additions and 20 deletions

View File

@ -3440,7 +3440,7 @@ class ComputeManager(manager.SchedulerDependentManager):
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)

View File

@ -543,12 +543,14 @@ class HyperVAPITestCase(test.NoDBTestCase):
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):

View File

@ -49,6 +49,7 @@ from nova.openstack.common import jsonutils
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 @@ class LibvirtConnTestCase(test.TestCase):
conn._hard_reboot(self.context, instance, network_info,
block_device_info)
def test_resume(self):
dummyxml = ("<domain type='kvm'><name>instance-0000000a</name>"
"<devices>"
"<disk type='file'><driver name='qemu' type='raw'/>"
"<source file='/test/disk'/>"
"<target dev='vda' bus='virtio'/></disk>"
"<disk type='file'><driver name='qemu' type='qcow2'/>"
"<source file='/test/disk.local'/>"
"<target dev='vdb' bus='virtio'/></disk>"
"</devices></domain>")
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()

View File

@ -841,7 +841,8 @@ class PowerVMDriverTestCase(test.TestCase):
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.

View File

@ -374,13 +374,13 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
@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):

View File

@ -497,7 +497,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
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 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
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 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
'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()

View File

@ -419,9 +419,16 @@ class ComputeDriver(object):
# 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,

View File

@ -198,7 +198,7 @@ class FakeDriver(driver.ComputeDriver):
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,

View File

@ -100,7 +100,7 @@ class HyperVDriver(driver.ComputeDriver):
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):

View File

@ -2032,12 +2032,12 @@ class LibvirtDriver(driver.ComputeDriver):
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))

View File

@ -201,7 +201,7 @@ class PowerVMDriver(driver.ComputeDriver):
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."))

View File

@ -203,7 +203,7 @@ class VMwareESXDriver(driver.ComputeDriver):
"""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 @@ class VMwareVCDriver(VMwareESXDriver):
_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)

View File

@ -318,7 +318,7 @@ class XenAPIDriver(driver.ComputeDriver):
"""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)