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..'),
|
LOG.info(_('_post_live_migration() is started..'),
|
||||||
instance=instance_ref)
|
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.
|
# Detaching volumes.
|
||||||
connector = self.driver.get_volume_connector(instance_ref)
|
connector = self.driver.get_volume_connector(instance_ref)
|
||||||
for bdm in self._get_instance_volume_bdms(ctxt, instance_ref):
|
for bdm in self._get_instance_volume_bdms(ctxt, instance_ref):
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
"""Tests for compute service."""
|
"""Tests for compute service."""
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import operator
|
import operator
|
||||||
@ -28,6 +29,7 @@ import time
|
|||||||
import traceback
|
import traceback
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import mock
|
||||||
import mox
|
import mox
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
@ -4243,32 +4245,35 @@ class ComputeTestCase(BaseTestCase):
|
|||||||
'power_state': power_state.PAUSED})
|
'power_state': power_state.PAUSED})
|
||||||
|
|
||||||
# creating mocks
|
# creating mocks
|
||||||
self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
|
with contextlib.nested(
|
||||||
self.compute.driver.unfilter_instance(inst_ref, [])
|
mock.patch.object(self.compute.driver, 'post_live_migration'),
|
||||||
self.mox.StubOutWithMock(self.compute.conductor_api,
|
mock.patch.object(self.compute.driver, 'unfilter_instance'),
|
||||||
'network_migrate_instance_start')
|
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)
|
||||||
|
|
||||||
|
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,
|
migration = {'source_compute': srchost,
|
||||||
'dest_compute': dest, }
|
'dest_compute': dest, }
|
||||||
self.compute.conductor_api.network_migrate_instance_start(c, inst_ref,
|
network_migrate_instance_start.assert_has_calls([
|
||||||
migration)
|
mock.call(c, inst_ref, migration)])
|
||||||
|
post_live_migration_at_destination.assert_has_calls([
|
||||||
self.mox.StubOutWithMock(self.compute.compute_rpcapi,
|
mock.call(c, inst_ref, False, dest)])
|
||||||
'post_live_migration_at_destination')
|
unplug_vifs.assert_has_calls([mock.call(inst_ref, [])])
|
||||||
self.compute.compute_rpcapi.post_live_migration_at_destination(
|
setup_networks_on_host.assert_has_calls([
|
||||||
c, inst_ref, False, dest)
|
mock.call(c, inst_ref, self.compute.host, teardown=True)])
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
def _begin_post_live_migration_at_destination(self):
|
def _begin_post_live_migration_at_destination(self):
|
||||||
self.mox.StubOutWithMock(self.compute.network_api,
|
self.mox.StubOutWithMock(self.compute.network_api,
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
import errno
|
import errno
|
||||||
import eventlet
|
import eventlet
|
||||||
@ -27,6 +28,7 @@ import tempfile
|
|||||||
|
|
||||||
from eventlet import greenthread
|
from eventlet import greenthread
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
import mock
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
|
||||||
@ -2868,6 +2870,31 @@ class LibvirtConnTestCase(test.TestCase):
|
|||||||
|
|
||||||
db.instance_destroy(self.context, instance_ref['uuid'])
|
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):
|
def test_get_instance_disk_info_excludes_volumes(self):
|
||||||
# Test data
|
# Test data
|
||||||
instance_ref = db.instance_create(self.context, self.test_instance)
|
instance_ref = db.instance_create(self.context, self.test_instance)
|
||||||
|
@ -514,6 +514,15 @@ class ComputeDriver(object):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
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,
|
def post_live_migration_at_destination(self, ctxt, instance_ref,
|
||||||
network_info,
|
network_info,
|
||||||
block_migration=False,
|
block_migration=False,
|
||||||
|
@ -3687,6 +3687,17 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
# following normal way.
|
# following normal way.
|
||||||
self._fetch_instance_kernel_ramdisk(context, instance)
|
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,
|
def post_live_migration_at_destination(self, context,
|
||||||
instance,
|
instance,
|
||||||
network_info,
|
network_info,
|
||||||
|
Loading…
Reference in New Issue
Block a user