Merge "Disconnect from iSCSI volume sessions after live migration"

This commit is contained in:
Jenkins 2013-09-02 07:10:30 +00:00 committed by Gerrit Code Review
commit f145d8a963
5 changed files with 82 additions and 25 deletions

View File

@ -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):

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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,