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:
@@ -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())
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user