Merge "Disconnect from iSCSI volume sessions after live migration"
This commit is contained in:
commit
f145d8a963
@ -3901,6 +3901,11 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
LOG.info(_('_post_live_migration() is started..'),
|
||||
instance=instance_ref)
|
||||
|
||||
# Cleanup source host post live-migration
|
||||
block_device_info = self._get_instance_volume_block_device_info(
|
||||
ctxt, instance_ref)
|
||||
self.driver.post_live_migration(ctxt, instance_ref, block_device_info)
|
||||
|
||||
# Detaching volumes.
|
||||
connector = self.driver.get_volume_connector(instance_ref)
|
||||
for bdm in self._get_instance_volume_bdms(ctxt, instance_ref):
|
||||
|
@ -19,6 +19,7 @@
|
||||
"""Tests for compute service."""
|
||||
|
||||
import base64
|
||||
import contextlib
|
||||
import copy
|
||||
import datetime
|
||||
import operator
|
||||
@ -28,6 +29,7 @@ import time
|
||||
import traceback
|
||||
import uuid
|
||||
|
||||
import mock
|
||||
import mox
|
||||
from oslo.config import cfg
|
||||
|
||||
@ -4243,32 +4245,35 @@ class ComputeTestCase(BaseTestCase):
|
||||
'power_state': power_state.PAUSED})
|
||||
|
||||
# creating mocks
|
||||
self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
|
||||
self.compute.driver.unfilter_instance(inst_ref, [])
|
||||
self.mox.StubOutWithMock(self.compute.conductor_api,
|
||||
'network_migrate_instance_start')
|
||||
migration = {'source_compute': srchost,
|
||||
'dest_compute': dest, }
|
||||
self.compute.conductor_api.network_migrate_instance_start(c, inst_ref,
|
||||
migration)
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.compute.driver, 'post_live_migration'),
|
||||
mock.patch.object(self.compute.driver, 'unfilter_instance'),
|
||||
mock.patch.object(self.compute.conductor_api,
|
||||
'network_migrate_instance_start'),
|
||||
mock.patch.object(self.compute.compute_rpcapi,
|
||||
'post_live_migration_at_destination'),
|
||||
mock.patch.object(self.compute.driver, 'unplug_vifs'),
|
||||
mock.patch.object(self.compute.network_api,
|
||||
'setup_networks_on_host')
|
||||
) as (
|
||||
post_live_migration, unfilter_instance,
|
||||
network_migrate_instance_start, post_live_migration_at_destination,
|
||||
unplug_vifs, setup_networks_on_host
|
||||
):
|
||||
self.compute._post_live_migration(c, inst_ref, dest)
|
||||
|
||||
self.mox.StubOutWithMock(self.compute.compute_rpcapi,
|
||||
'post_live_migration_at_destination')
|
||||
self.compute.compute_rpcapi.post_live_migration_at_destination(
|
||||
c, inst_ref, False, dest)
|
||||
|
||||
self.mox.StubOutWithMock(self.compute.driver, 'unplug_vifs')
|
||||
self.compute.driver.unplug_vifs(inst_ref, [])
|
||||
|
||||
self.mox.StubOutWithMock(self.compute.network_api,
|
||||
'setup_networks_on_host')
|
||||
self.compute.network_api.setup_networks_on_host(c, inst_ref,
|
||||
self.compute.host,
|
||||
teardown=True)
|
||||
|
||||
# start test
|
||||
self.mox.ReplayAll()
|
||||
self.compute._post_live_migration(c, inst_ref, dest)
|
||||
post_live_migration.assert_has_calls([
|
||||
mock.call(c, inst_ref, {'block_device_mapping': []})])
|
||||
unfilter_instance.assert_has_calls([mock.call(inst_ref, [])])
|
||||
migration = {'source_compute': srchost,
|
||||
'dest_compute': dest, }
|
||||
network_migrate_instance_start.assert_has_calls([
|
||||
mock.call(c, inst_ref, migration)])
|
||||
post_live_migration_at_destination.assert_has_calls([
|
||||
mock.call(c, inst_ref, False, dest)])
|
||||
unplug_vifs.assert_has_calls([mock.call(inst_ref, [])])
|
||||
setup_networks_on_host.assert_has_calls([
|
||||
mock.call(c, inst_ref, self.compute.host, teardown=True)])
|
||||
|
||||
def _begin_post_live_migration_at_destination(self):
|
||||
self.mox.StubOutWithMock(self.compute.network_api,
|
||||
|
@ -15,6 +15,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import contextlib
|
||||
import copy
|
||||
import errno
|
||||
import eventlet
|
||||
@ -27,6 +28,7 @@ import tempfile
|
||||
|
||||
from eventlet import greenthread
|
||||
from lxml import etree
|
||||
import mock
|
||||
from oslo.config import cfg
|
||||
from xml.dom import minidom
|
||||
|
||||
@ -2868,6 +2870,31 @@ class LibvirtConnTestCase(test.TestCase):
|
||||
|
||||
db.instance_destroy(self.context, instance_ref['uuid'])
|
||||
|
||||
def test_post_live_migration(self):
|
||||
vol = {'block_device_mapping': [
|
||||
{'connection_info': 'dummy1', 'mount_device': '/dev/sda'},
|
||||
{'connection_info': 'dummy2', 'mount_device': '/dev/sdb'}]}
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
||||
inst_ref = {'id': 'foo'}
|
||||
cntx = context.get_admin_context()
|
||||
|
||||
# Set up the mock expectations
|
||||
with contextlib.nested(
|
||||
mock.patch.object(driver, 'block_device_info_get_mapping',
|
||||
return_value=vol['block_device_mapping']),
|
||||
mock.patch.object(conn, 'volume_driver_method')
|
||||
) as (block_device_info_get_mapping, volume_driver_method):
|
||||
conn.post_live_migration(cntx, inst_ref, vol)
|
||||
|
||||
block_device_info_get_mapping.assert_has_calls([
|
||||
mock.call(vol)])
|
||||
volume_driver_method.assert_has_calls([
|
||||
mock.call('disconnect_volume',
|
||||
v['connection_info'],
|
||||
v['mount_device'].rpartition("/")[2])
|
||||
for v in vol['block_device_mapping']])
|
||||
|
||||
def test_get_instance_disk_info_excludes_volumes(self):
|
||||
# Test data
|
||||
instance_ref = db.instance_create(self.context, self.test_instance)
|
||||
|
@ -514,6 +514,15 @@ class ComputeDriver(object):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def post_live_migration(self, ctxt, instance_ref, block_device_info):
|
||||
"""Post operation of live migration at source host.
|
||||
|
||||
:param ctxt: security contet
|
||||
:instance_ref: instance object that was migrated
|
||||
:block_device_info: instance block device information
|
||||
"""
|
||||
pass
|
||||
|
||||
def post_live_migration_at_destination(self, ctxt, instance_ref,
|
||||
network_info,
|
||||
block_migration=False,
|
||||
|
@ -3687,6 +3687,17 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
# following normal way.
|
||||
self._fetch_instance_kernel_ramdisk(context, instance)
|
||||
|
||||
def post_live_migration(self, context, instance, block_device_info):
|
||||
# Disconnect from volume server
|
||||
block_device_mapping = driver.block_device_info_get_mapping(
|
||||
block_device_info)
|
||||
for vol in block_device_mapping:
|
||||
connection_info = vol['connection_info']
|
||||
disk_dev = vol['mount_device'].rpartition("/")[2]
|
||||
self.volume_driver_method('disconnect_volume',
|
||||
connection_info,
|
||||
disk_dev)
|
||||
|
||||
def post_live_migration_at_destination(self, context,
|
||||
instance,
|
||||
network_info,
|
||||
|
Loading…
Reference in New Issue
Block a user