bug 899767: fix vif-plugging with live migration

Expose vif_unplug method in virt layer, as the compute manager has to
explicitly call it on during live migration, so that network devices are
torn down even if the disk image is not.

Change-Id: Iae88c72f4fd2c7c097c23ef9e5f8fd392052f73e
This commit is contained in:
Dan Wendlandt
2011-12-12 10:34:33 -08:00
parent b43fa8b590
commit 6b6633521c
9 changed files with 50 additions and 9 deletions

View File

@@ -1735,6 +1735,12 @@ class ComputeManager(manager.SchedulerDependentManager):
# must be deleted for preparing next block migration # must be deleted for preparing next block migration
if block_migration: if block_migration:
self.driver.destroy(instance_ref, network_info) self.driver.destroy(instance_ref, network_info)
else:
# self.driver.destroy() usually performs vif unplugging
# but we must do it explicitly here when block_migration
# is false, as the network devices at the source must be
# torn down
self.driver.unplug_vifs(instance_ref, network_info)
LOG.info(_('Migrating %(i_name)s to %(dest)s finished successfully.') LOG.info(_('Migrating %(i_name)s to %(dest)s finished successfully.')
% locals()) % locals())

View File

@@ -1022,6 +1022,8 @@ class ComputeTestCase(BaseTestCase):
rpc.call(c, db.queue_get_for(c, FLAGS.compute_topic, dest), rpc.call(c, db.queue_get_for(c, FLAGS.compute_topic, dest),
{"method": "post_live_migration_at_destination", {"method": "post_live_migration_at_destination",
"args": {'instance_id': i_ref['id'], 'block_migration': False}}) "args": {'instance_id': i_ref['id'], 'block_migration': False}})
self.mox.StubOutWithMock(self.compute.driver, 'unplug_vifs')
self.compute.driver.unplug_vifs(i_ref, [])
# start test # start test
self.mox.ReplayAll() self.mox.ReplayAll()

View File

@@ -516,10 +516,14 @@ class ComputeDriver(object):
raise NotImplementedError() raise NotImplementedError()
def plug_vifs(self, instance, network_info): def plug_vifs(self, instance, network_info):
"""Plugs in VIFs to networks.""" """Plug VIFs into networks."""
# TODO(Vek): Need to pass context in for access to auth_token # TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError() raise NotImplementedError()
def unplug_vifs(self, instance, network_info):
"""Unplug VIFs from networks."""
raise NotImplementedError()
def update_host_status(self): def update_host_status(self):
"""Refresh host stats""" """Refresh host stats"""
raise NotImplementedError() raise NotImplementedError()

View File

@@ -94,7 +94,11 @@ class FakeConnection(driver.ComputeDriver):
return info_list return info_list
def plug_vifs(self, instance, network_info): def plug_vifs(self, instance, network_info):
"""Plugin VIFs into networks.""" """Plug VIFs into networks."""
pass
def unplug_vifs(self, instance, network_info):
"""Unplug VIFs from networks."""
pass pass
def spawn(self, context, instance, image_meta, def spawn(self, context, instance, image_meta,

View File

@@ -516,3 +516,11 @@ class HyperVConnection(driver.ComputeDriver):
def set_host_enabled(self, host, enabled): def set_host_enabled(self, host, enabled):
"""Sets the specified host's ability to accept new instances.""" """Sets the specified host's ability to accept new instances."""
pass pass
def plug_vifs(self, instance, network_info):
"""Plug VIFs into networks."""
pass
def unplug_vifs(self, instance, network_info):
"""Unplug VIFs from networks."""
pass

View File

@@ -290,10 +290,15 @@ class LibvirtConnection(driver.ComputeDriver):
return infos return infos
def plug_vifs(self, instance, network_info): def plug_vifs(self, instance, network_info):
"""Plugin VIFs into networks.""" """Plug VIFs into networks."""
for (network, mapping) in network_info: for (network, mapping) in network_info:
self.vif_driver.plug(instance, network, mapping) self.vif_driver.plug(instance, network, mapping)
def unplug_vifs(self, instance, network_info):
"""Unplug VIFs from networks."""
for (network, mapping) in network_info:
self.vif_driver.unplug(instance, network, mapping)
def destroy(self, instance, network_info, block_device_info=None, def destroy(self, instance, network_info, block_device_info=None,
cleanup=True): cleanup=True):
instance_name = instance['name'] instance_name = instance['name']
@@ -350,8 +355,7 @@ class LibvirtConnection(driver.ComputeDriver):
locals()) locals())
raise raise
for (network, mapping) in network_info: self.unplug_vifs(instance, network_info)
self.vif_driver.unplug(instance, network, mapping)
def _wait_for_destroy(): def _wait_for_destroy():
"""Called at an interval until the VM is gone.""" """Called at an interval until the VM is gone."""
@@ -545,6 +549,7 @@ class LibvirtConnection(driver.ComputeDriver):
# better because we cannot ensure flushing dirty buffers # better because we cannot ensure flushing dirty buffers
# in the guest OS. But, in case of KVM, shutdown() does not work... # in the guest OS. But, in case of KVM, shutdown() does not work...
self.destroy(instance, network_info, cleanup=False) self.destroy(instance, network_info, cleanup=False)
self.unplug_vifs(instance, network_info)
self.plug_vifs(instance, network_info) self.plug_vifs(instance, network_info)
self.firewall_driver.setup_basic_filtering(instance, network_info) self.firewall_driver.setup_basic_filtering(instance, network_info)
self.firewall_driver.prepare_instance_filter(instance, network_info) self.firewall_driver.prepare_instance_filter(instance, network_info)

View File

@@ -201,9 +201,13 @@ class VMWareESXConnection(driver.ComputeDriver):
pass pass
def plug_vifs(self, instance, network_info): def plug_vifs(self, instance, network_info):
"""Plugs in VIFs to networks.""" """Plug VIFs into networks."""
self._vmops.plug_vifs(instance, network_info) self._vmops.plug_vifs(instance, network_info)
def unplug_vifs(self, instance, network_info):
"""Unplug VIFs from networks."""
self._vmops.unplug_vifs(instance, network_info)
class VMWareAPISession(object): class VMWareAPISession(object):
""" """

View File

@@ -1139,9 +1139,7 @@ class VMOps(object):
self._destroy_kernel_ramdisk(instance, vm_ref) self._destroy_kernel_ramdisk(instance, vm_ref)
self._destroy_vm(instance, vm_ref) self._destroy_vm(instance, vm_ref)
if network_info: self.unplug_vifs(instance, network_info)
for (network, mapping) in network_info:
self.vif_driver.unplug(instance, network, mapping)
def pause(self, instance): def pause(self, instance):
"""Pause VM instance.""" """Pause VM instance."""
@@ -1459,6 +1457,11 @@ class VMOps(object):
for (network, mapping) in network_info: for (network, mapping) in network_info:
self.vif_driver.plug(self._session, instance, network, mapping) self.vif_driver.plug(self._session, instance, network, mapping)
def unplug_vifs(self, instance, network_info):
if network_info:
for (network, mapping) in network_info:
self.vif_driver.unplug(instance, network, mapping)
def reset_network(self, instance, vm_ref=None): def reset_network(self, instance, vm_ref=None):
"""Creates uuid arg to pass to make_agent_call and calls it.""" """Creates uuid arg to pass to make_agent_call and calls it."""
if not vm_ref: if not vm_ref:

View File

@@ -297,8 +297,13 @@ class XenAPIConnection(driver.ComputeDriver):
self._vmops.inject_network_info(instance, network_info) self._vmops.inject_network_info(instance, network_info)
def plug_vifs(self, instance_ref, network_info): def plug_vifs(self, instance_ref, network_info):
"""Plug VIFs into networks."""
self._vmops.plug_vifs(instance_ref, network_info) self._vmops.plug_vifs(instance_ref, network_info)
def unplug_vifs(self, instance_ref, network_info):
"""Unplug VIFs from networks."""
self._vmops.unplug_vifs(instance_ref, network_info)
def get_info(self, instance_name): def get_info(self, instance_name):
"""Return data about VM instance""" """Return data about VM instance"""
return self._vmops.get_info(instance_name) return self._vmops.get_info(instance_name)