Merge "Make libvirt driver return migrate data objects for source and dest checks"

This commit is contained in:
Jenkins
2015-12-22 23:57:43 +00:00
committed by Gerrit Code Review
7 changed files with 460 additions and 98 deletions
+137
View File
@@ -12,10 +12,17 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log
from oslo_serialization import jsonutils
from nova import objects
from nova.objects import base as obj_base
from nova.objects import fields
LOG = log.getLogger(__name__)
@obj_base.NovaObjectRegistry.register_if(False)
class LiveMigrateData(obj_base.NovaObject):
fields = {
@@ -39,3 +46,133 @@ class LiveMigrateData(obj_base.NovaObject):
self.is_volume_backed = legacy['is_volume_backed']
if 'migration' in legacy:
self.migration = legacy['migration']
@obj_base.NovaObjectRegistry.register
class LibvirtLiveMigrateBDMInfo(obj_base.NovaObject):
VERSION = '1.0'
fields = {
# FIXME(danms): some of these can be enums?
'serial': fields.StringField(),
'bus': fields.StringField(),
'dev': fields.StringField(),
'type': fields.StringField(),
'format': fields.StringField(nullable=True),
'boot_index': fields.IntegerField(nullable=True),
'connection_info_json': fields.StringField(),
}
# NOTE(danms): We don't have a connection_info object right
# now, and instead mostly store/pass it as JSON that we're
# careful with. When we get a connection_info object in the
# future, we should use it here, so make this easy to convert
# for later.
@property
def connection_info(self):
return jsonutils.loads(self.connection_info_json)
@connection_info.setter
def connection_info(self, info):
self.connection_info_json = jsonutils.dumps(info)
def as_disk_info(self):
info_dict = {
'dev': self.dev,
'bus': self.bus,
'type': self.type,
}
if self.obj_attr_is_set('format') and self.format:
info_dict['format'] = self.format
if self.obj_attr_is_set('boot_index') and self.boot_index is not None:
info_dict['boot_index'] = str(self.boot_index)
return info_dict
@obj_base.NovaObjectRegistry.register
class LibvirtLiveMigrateData(LiveMigrateData):
VERSION = '1.0'
fields = {
'filename': fields.StringField(),
# FIXME: image_type should be enum?
'image_type': fields.StringField(),
'block_migration': fields.BooleanField(),
'disk_over_commit': fields.BooleanField(),
'disk_available_mb': fields.IntegerField(nullable=True),
'is_shared_instance_path': fields.BooleanField(),
'is_shared_block_storage': fields.BooleanField(),
'instance_relative_path': fields.StringField(),
'graphics_listen_addr_vnc': fields.IPAddressField(nullable=True),
'graphics_listen_addr_spice': fields.IPAddressField(nullable=True),
'serial_listen_addr': fields.StringField(),
'bdms': fields.ListOfObjectsField('LibvirtLiveMigrateBDMInfo'),
}
def _bdms_to_legacy(self, legacy):
if not self.obj_attr_is_set('bdms'):
return
legacy['volume'] = {}
for bdmi in self.bdms:
legacy['volume'][bdmi.serial] = {
'disk_info': bdmi.as_disk_info(),
'connection_info': bdmi.connection_info}
def _bdms_from_legacy(self, legacy_pre_result):
self.bdms = []
volume = legacy_pre_result.get('volume', {})
for serial in volume:
vol = volume[serial]
bdmi = objects.LibvirtLiveMigrateBDMInfo(serial=serial)
bdmi.connection_info = vol['connection_info']
bdmi.bus = vol['disk_info']['bus']
bdmi.dev = vol['disk_info']['dev']
bdmi.type = vol['disk_info']['type']
if 'format' in vol:
bdmi.format = vol['disk_info']['format']
if 'boot_index' in vol:
bdmi.boot_index = int(vol['disk_info']['boot_index'])
self.bdms.append(bdmi)
def to_legacy_dict(self, pre_migration_result=False):
LOG.debug('Converting to legacy: %s' % self)
legacy = super(LibvirtLiveMigrateData, self).to_legacy_dict()
keys = (set(self.fields.keys()) -
set(LiveMigrateData.fields.keys()) - {'bdms'})
legacy.update({k: getattr(self, k) for k in keys
if self.obj_attr_is_set(k)})
graphics_vnc = legacy.pop('graphics_listen_addr_vnc', None)
graphics_spice = legacy.pop('graphics_listen_addr_spice', None)
live_result = {
'graphics_listen_addrs': {
'vnc': graphics_vnc and str(graphics_vnc),
'spice': graphics_spice and str(graphics_spice),
},
'serial_listen_addr': legacy.pop('serial_listen_addr', None),
}
if pre_migration_result:
legacy['pre_live_migration_result'] = live_result
self._bdms_to_legacy(live_result)
LOG.debug('Legacy result: %s' % legacy)
return legacy
def from_legacy_dict(self, legacy):
LOG.debug('Converting legacy dict to obj: %s' % legacy)
super(LibvirtLiveMigrateData, self).from_legacy_dict(legacy)
keys = set(self.fields.keys()) - set(LiveMigrateData.fields.keys())
for k in keys - {'bdms'}:
if k in legacy:
setattr(self, k, legacy[k])
if 'pre_live_migration_result' in legacy:
pre_result = legacy['pre_live_migration_result']
self.graphics_listen_addr_vnc = \
pre_result['graphics_listen_addrs'].get('vnc')
self.graphics_listen_addr_spice = \
pre_result['graphics_listen_addrs'].get('spice')
if 'serial_listen_addr' in pre_result:
self.serial_listen_addr = pre_result['serial_listen_addr']
self._bdms_from_legacy(pre_result)
LOG.debug('Converted object: %s' % self)
@@ -51,3 +51,141 @@ class TestLiveMigrateData(test_objects._LocalTest,
class TestRemoteLiveMigrateData(test_objects._RemoteTest,
_TestLiveMigrateData):
pass
class _TestLibvirtLiveMigrateData(object):
def test_bdm_to_disk_info(self):
obj = migrate_data.LibvirtLiveMigrateBDMInfo(
serial='foo', bus='scsi', dev='sda', type='disk')
expected_info = {
'dev': 'sda',
'bus': 'scsi',
'type': 'disk',
}
self.assertEqual(expected_info, obj.as_disk_info())
obj.format = 'raw'
obj.boot_index = 1
expected_info['format'] = 'raw'
expected_info['boot_index'] = '1'
self.assertEqual(expected_info, obj.as_disk_info())
def test_to_legacy_dict(self):
obj = migrate_data.LibvirtLiveMigrateData(
is_volume_backed=False,
filename='foo',
image_type='rbd',
block_migration=False,
disk_over_commit=False,
disk_available_mb=123,
is_shared_instance_path=False,
is_shared_block_storage=False,
instance_relative_path='foo/bar')
expected = {
'is_volume_backed': False,
'filename': 'foo',
'image_type': 'rbd',
'block_migration': False,
'disk_over_commit': False,
'disk_available_mb': 123,
'is_shared_instance_path': False,
'is_shared_block_storage': False,
'instance_relative_path': 'foo/bar',
}
self.assertEqual(expected, obj.to_legacy_dict())
def test_from_legacy_dict(self):
obj = migrate_data.LibvirtLiveMigrateData(
is_volume_backed=False,
filename='foo',
image_type='rbd',
block_migration=False,
disk_over_commit=False,
disk_available_mb=123,
is_shared_instance_path=False,
is_shared_block_storage=False,
instance_relative_path='foo/bar')
legacy = obj.to_legacy_dict()
legacy['ignore_this_thing'] = True
obj2 = migrate_data.LibvirtLiveMigrateData()
obj2.from_legacy_dict(legacy)
self.assertEqual(obj.filename, obj2.filename)
def test_to_legacy_dict_with_pre_result(self):
test_bdmi = migrate_data.LibvirtLiveMigrateBDMInfo(
serial='123',
bus='scsi',
dev='/dev/sda',
type='disk',
format='qcow2',
boot_index=1,
connection_info='myinfo')
obj = migrate_data.LibvirtLiveMigrateData(
is_volume_backed=False,
filename='foo',
image_type='rbd',
block_migration=False,
disk_over_commit=False,
disk_available_mb=123,
is_shared_instance_path=False,
is_shared_block_storage=False,
instance_relative_path='foo/bar',
graphics_listen_addr_vnc='127.0.0.1',
serial_listen_addr='127.0.0.1',
bdms=[test_bdmi])
legacy = obj.to_legacy_dict(pre_migration_result=True)
self.assertIn('pre_live_migration_result', legacy)
expected = {
'graphics_listen_addrs': {'vnc': '127.0.0.1',
'spice': None},
'serial_listen_addr': '127.0.0.1',
'volume': {
'123': {
'connection_info': 'myinfo',
'disk_info': {
'bus': 'scsi',
'dev': '/dev/sda',
'type': 'disk',
'format': 'qcow2',
'boot_index': '1',
}
}
}
}
self.assertEqual(expected, legacy['pre_live_migration_result'])
def test_from_legacy_with_pre_result(self):
test_bdmi = migrate_data.LibvirtLiveMigrateBDMInfo(
serial='123',
bus='scsi',
dev='/dev/sda',
type='disk',
format='qcow2',
boot_index=1,
connection_info='myinfo')
obj = migrate_data.LibvirtLiveMigrateData(
is_volume_backed=False,
filename='foo',
image_type='rbd',
block_migration=False,
disk_over_commit=False,
disk_available_mb=123,
is_shared_instance_path=False,
is_shared_block_storage=False,
instance_relative_path='foo/bar',
graphics_listen_addrs={'vnc': '127.0.0.1'},
serial_listen_addr='127.0.0.1',
bdms=[test_bdmi])
obj2 = migrate_data.LibvirtLiveMigrateData()
obj2.from_legacy_dict(obj.to_legacy_dict())
self.assertEqual(obj.to_legacy_dict(),
obj2.to_legacy_dict())
class TestLibvirtLiveMigrateData(test_objects._LocalTest,
_TestLibvirtLiveMigrateData):
pass
class TestRemoteLibvirtLiveMigrateData(test_objects._RemoteTest,
_TestLibvirtLiveMigrateData):
pass
+2
View File
@@ -1152,6 +1152,8 @@ object_data = {
'InstanceNUMATopology': '1.2-d944a7d6c21e1c773ffdf09c6d025954',
'InstancePCIRequest': '1.1-b1d75ebc716cb12906d9d513890092bf',
'InstancePCIRequests': '1.1-65e38083177726d806684cb1cc0136d2',
'LibvirtLiveMigrateBDMInfo': '1.0-252aabb723ca79d5469fa56f64b57811',
'LibvirtLiveMigrateData': '1.0-eb8b5f6c49ae3858213a7012558a2f3d',
'KeyPair': '1.3-bfaa2a8b148cdf11e0c72435d9dd097a',
'KeyPairList': '1.2-58b94f96e776bedaf1e192ddb2a24c4e',
'Migration': '1.2-8784125bedcea0a9227318511904e853',
+115 -49
View File
@@ -5691,12 +5691,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
# No need for the src_compute_info
return_value = drvr.check_can_live_migrate_destination(self.context,
instance_ref, None, compute_info, True)
return_value.is_volume_backed = False
self.assertThat({"filename": "file",
'image_type': 'default',
'disk_available_mb': 409600,
"disk_over_commit": False,
"block_migration": True},
matchers.DictMatches(return_value))
"block_migration": True,
"is_volume_backed": False},
matchers.DictMatches(return_value.to_legacy_dict()))
@mock.patch.object(libvirt_driver.LibvirtDriver,
'_create_shared_storage_test_file')
@@ -5718,12 +5720,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
# No need for the src_compute_info
return_value = drvr.check_can_live_migrate_destination(self.context,
instance_ref, None, compute_info, False)
return_value.is_volume_backed = False
self.assertThat({"filename": "file",
"image_type": 'default',
"block_migration": False,
"disk_over_commit": False,
"disk_available_mb": None},
matchers.DictMatches(return_value))
"disk_available_mb": None,
"is_volume_backed": False},
matchers.DictMatches(return_value.to_legacy_dict()))
@mock.patch.object(libvirt_driver.LibvirtDriver,
'_create_shared_storage_test_file',
@@ -5740,13 +5744,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
compute_info = {'cpu_info': 'asdf'}
result = drvr.check_can_live_migrate_destination(
self.context, instance_ref, compute_info, compute_info)
result.is_volume_backed = False
mock_cpu.assert_called_once_with(None, 'asdf')
expected_result = {"filename": 'fake',
"image_type": CONF.libvirt.images_type,
"block_migration": False,
"disk_over_commit": False,
"disk_available_mb": None}
self.assertDictEqual(expected_result, result)
"disk_available_mb": None,
"is_volume_backed": False}
self.assertDictEqual(expected_result, result.to_legacy_dict())
@mock.patch.object(libvirt_driver.LibvirtDriver,
'_create_shared_storage_test_file')
@@ -5771,12 +5777,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
return_value = drvr.check_can_live_migrate_destination(self.context,
instance_ref, compute_info, compute_info, False)
# NOTE(danms): Compute manager would have set this, so set it here
return_value.is_volume_backed = False
self.assertThat({"filename": "file",
"image_type": 'default',
"block_migration": False,
"disk_over_commit": False,
"disk_available_mb": None},
matchers.DictMatches(return_value))
"disk_available_mb": None,
"is_volume_backed": False},
matchers.DictMatches(return_value.to_legacy_dict()))
@mock.patch.object(fakelibvirt.Connection, 'compareCPU')
def test_check_can_live_migrate_dest_incompatible_cpu_raises(
@@ -5874,11 +5883,12 @@ class LibvirtConnTestCase(test.NoDBTestCase):
block_device_info=None,
block_device_text=None):
instance = objects.Instance(**self.test_instance)
dest_check_data = {'filename': 'file',
'image_type': 'default',
'block_migration': block_migration,
'disk_over_commit': False,
'disk_available_mb': disk_available_mb}
dest_check_data = objects.LibvirtLiveMigrateData(
filename='file',
image_type='default',
block_migration=block_migration,
disk_over_commit=False,
disk_available_mb=disk_available_mb)
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.mox.StubOutWithMock(drvr, '_is_shared_block_storage')
@@ -5903,17 +5913,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.mox.StubOutWithMock(drvr, "_assert_dest_node_has_enough_disk")
drvr._assert_dest_node_has_enough_disk(
self.context, instance, dest_check_data['disk_available_mb'],
self.context, instance, dest_check_data.disk_available_mb,
False, None)
self.mox.ReplayAll()
ret = drvr.check_can_live_migrate_source(self.context, instance,
dest_check_data)
self.assertIsInstance(ret, dict)
self.assertIsInstance(ret, objects.LibvirtLiveMigrateData)
self.assertIn('is_shared_block_storage', ret)
self.assertIn('is_shared_instance_path', ret)
self.assertEqual(ret['is_shared_instance_path'],
ret['is_shared_storage'])
def test_check_can_live_migrate_source_shared_block_storage(self):
instance, dest_check_data, drvr = self._mock_can_live_migrate_source(
@@ -6015,11 +6023,12 @@ class LibvirtConnTestCase(test.NoDBTestCase):
bdi = {'block_device_mapping': ['bdm']}
instance = objects.Instance(**self.test_instance)
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
dest_check_data = {'filename': 'file',
'image_type': 'default',
'block_migration': True,
'disk_over_commit': False,
'disk_available_mb': 100}
dest_check_data = objects.LibvirtLiveMigrateData(
filename='file',
image_type='default',
block_migration=True,
disk_over_commit=False,
disk_available_mb=100)
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.assertRaises(exception.MigrationPreCheckError,
drvr.check_can_live_migrate_source,
@@ -6073,11 +6082,11 @@ class LibvirtConnTestCase(test.NoDBTestCase):
instance = objects.Instance(**self.test_instance)
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
mock_get_instance_disk_info = mock.Mock()
data = objects.LibvirtLiveMigrateData(image_type='rbd')
with mock.patch.object(drvr, 'get_instance_disk_info',
mock_get_instance_disk_info):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.assertTrue(drvr._is_shared_block_storage(instance,
{'image_type': 'rbd'},
self.assertTrue(drvr._is_shared_block_storage(instance, data,
block_device_info=bdi))
self.assertEqual(0, mock_get_instance_disk_info.call_count)
@@ -6087,11 +6096,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
instance = objects.Instance(**self.test_instance)
mock_get_instance_disk_info = mock.Mock()
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
data = objects.LibvirtLiveMigrateData(image_type='lvm',
is_volume_backed=False,
is_shared_instance_path=False)
with mock.patch.object(drvr, 'get_instance_disk_info',
mock_get_instance_disk_info):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.assertFalse(drvr._is_shared_block_storage(
instance, {'image_type': 'lvm'},
instance, data,
block_device_info=bdi))
self.assertEqual(0, mock_get_instance_disk_info.call_count)
@@ -6101,11 +6113,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
instance = objects.Instance(**self.test_instance)
mock_get_instance_disk_info = mock.Mock()
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
data = objects.LibvirtLiveMigrateData(image_type='qcow2',
is_volume_backed=False,
is_shared_instance_path=False)
with mock.patch.object(drvr, 'get_instance_disk_info',
mock_get_instance_disk_info):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.assertFalse(drvr._is_shared_block_storage(
instance, {'image_type': 'qcow2'},
instance, data,
block_device_info=bdi))
self.assertEqual(0, mock_get_instance_disk_info.call_count)
@@ -6115,11 +6130,13 @@ class LibvirtConnTestCase(test.NoDBTestCase):
instance = objects.Instance(**self.test_instance)
mock_get_instance_disk_info = mock.Mock()
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
data = objects.LibvirtLiveMigrateData(is_shared_instance_path=False,
is_volume_backed=False)
with mock.patch.object(drvr, 'get_instance_disk_info',
mock_get_instance_disk_info):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.assertFalse(drvr._is_shared_block_storage(
instance, {'is_shared_instance_path': False},
instance, data,
block_device_info=bdi))
self.assertEqual(0, mock_get_instance_disk_info.call_count)
@@ -6128,12 +6145,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
instance = objects.Instance(**self.test_instance)
mock_get_instance_disk_info = mock.Mock()
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
data = objects.LibvirtLiveMigrateData(image_type='rbd',
is_volume_backed=False,
is_shared_instance_path=False)
with mock.patch.object(drvr, 'get_instance_disk_info',
mock_get_instance_disk_info):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.assertFalse(drvr._is_shared_block_storage(
instance, {'image_type': 'rbd',
'is_shared_instance_path': False},
instance, data,
block_device_info=bdi))
self.assertEqual(0, mock_get_instance_disk_info.call_count)
@@ -6149,10 +6168,10 @@ class LibvirtConnTestCase(test.NoDBTestCase):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
(mock_getsize, mock_lookup) =\
self._is_shared_block_storage_test_create_mocks(disks)
data = objects.LibvirtLiveMigrateData(is_volume_backed=True,
is_shared_instance_path=False)
with mock.patch.object(host.Host, 'get_domain', mock_lookup):
self.assertTrue(drvr._is_shared_block_storage(instance,
{'is_volume_backed': True,
'is_shared_instance_path': False},
self.assertTrue(drvr._is_shared_block_storage(instance, data,
block_device_info = bdi))
mock_lookup.assert_called_once_with(instance)
@@ -6173,13 +6192,13 @@ class LibvirtConnTestCase(test.NoDBTestCase):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
(mock_getsize, mock_lookup) =\
self._is_shared_block_storage_test_create_mocks(disks)
data = objects.LibvirtLiveMigrateData(is_volume_backed=True,
is_shared_instance_path=False)
with test.nested(
mock.patch.object(os.path, 'getsize', mock_getsize),
mock.patch.object(host.Host, 'get_domain', mock_lookup)):
self.assertFalse(drvr._is_shared_block_storage(
instance,
{'is_volume_backed': True,
'is_shared_instance_path': False},
instance, data,
block_device_info = bdi))
mock_getsize.assert_called_once_with('/instance/disk.local')
mock_lookup.assert_called_once_with(instance)
@@ -6193,11 +6212,13 @@ class LibvirtConnTestCase(test.NoDBTestCase):
mock_image_backend.backend.return_value = mock_backend
mock_backend.is_file_in_instance_path.return_value = True
mock_get_instance_disk_info = mock.Mock()
data = objects.LibvirtLiveMigrateData(
is_shared_instance_path=True,
image_type='foo')
with mock.patch.object(drvr, 'get_instance_disk_info',
mock_get_instance_disk_info):
self.assertTrue(drvr._is_shared_block_storage('instance',
{'is_shared_instance_path': True},
block_device_info=bdi))
self.assertTrue(drvr._is_shared_block_storage(
'instance', data, block_device_info=bdi))
self.assertEqual(0, mock_get_instance_disk_info.call_count)
def test_live_migration_update_graphics_xml(self):
@@ -7381,9 +7402,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
drvr.plug_vifs(mox.IsA(instance), nw_info)
self.mox.ReplayAll()
migrate_data = {
"block_migration": False,
"instance_relative_path": "foo",
"is_shared_block_storage": False,
"is_shared_instance_path": False,
}
result = drvr.pre_live_migration(
c, instance, vol, nw_info, None,
migrate_data={"block_migration": False})
migrate_data=migrate_data)
target_ret = {
'graphics_listen_addrs': {'spice': '127.0.0.1', 'vnc': '127.0.0.1'},
@@ -7401,7 +7428,10 @@ class LibvirtConnTestCase(test.NoDBTestCase):
'disk_info': {'bus': 'scsi',
'dev': 'sdb',
'type': 'disk'}}}}
self.assertEqual(result, target_ret)
self.assertEqual(
result.to_legacy_dict(
pre_migration_result=True)['pre_live_migration_result'],
target_ret)
def test_pre_live_migration_block_with_config_drive_mocked(self):
# Creating testdata
@@ -7421,7 +7451,9 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertRaises(exception.NoLiveMigrationForConfigDriveInLibVirt,
drvr.pre_live_migration, c, instance, vol, None,
None, {'is_shared_instance_path': False,
'is_shared_block_storage': False})
'is_shared_block_storage': False,
'block_migration': False,
'instance_relative_path': 'foo'})
@mock.patch('nova.virt.driver.block_device_info_get_mapping',
return_value=())
@@ -7441,7 +7473,10 @@ class LibvirtConnTestCase(test.NoDBTestCase):
res_data = drvr.pre_live_migration(
self.context, instance, vol, [], None,
{'is_shared_instance_path': False,
'is_shared_block_storage': False})
'is_shared_block_storage': False,
'block_migration': False,
'instance_relative_path': 'foo'})
res_data = res_data.to_legacy_dict(pre_migration_result=True)
block_device_info_get_mapping.assert_called_once_with(
{'block_device_mapping': [
{'connection_info': 'dummy', 'mount_device': '/dev/sda'},
@@ -7451,7 +7486,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertEqual({'graphics_listen_addrs': {'spice': '127.0.0.1',
'vnc': '127.0.0.1'},
'serial_listen_addr': '127.0.0.1',
'volume': {}}, res_data)
'volume': {}}, res_data['pre_live_migration_result'])
def test_pre_live_migration_vol_backed_works_correctly_mocked(self):
# Creating testdata, using temp dir.
@@ -7494,10 +7529,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
drvr.plug_vifs(mox.IsA(inst_ref), nw_info)
self.mox.ReplayAll()
migrate_data = {'is_shared_instance_path': False,
'is_shared_block_storage': False,
'is_volume_backed': True,
'block_migration': False,
'instance_relative_path': inst_ref['name']
}
'instance_relative_path': inst_ref['name'],
'disk_over_commit': False,
'disk_available_mb': 123,
'image_type': 'qcow2',
'filename': 'foo',
}
ret = drvr.pre_live_migration(c, inst_ref, vol, nw_info, None,
migrate_data)
target_ret = {
@@ -7517,7 +7557,9 @@ class LibvirtConnTestCase(test.NoDBTestCase):
'disk_info': {'bus': 'scsi',
'dev': 'sdb',
'type': 'disk'}}}}
self.assertEqual(ret, target_ret)
self.assertEqual(
ret.to_legacy_dict(True)['pre_live_migration_result'],
target_ret)
self.assertTrue(os.path.exists('%s/%s/' % (tmpdir,
inst_ref['name'])))
@@ -7560,10 +7602,31 @@ class LibvirtConnTestCase(test.NoDBTestCase):
def test_pre_live_migration_image_not_created_with_shared_storage(self):
migrate_data_set = [{'is_shared_block_storage': False,
'is_shared_instance_path': True,
'is_volume_backed': False,
'filename': 'foo',
'instance_relative_path': 'bar',
'disk_over_commit': False,
'disk_available_mb': 123,
'image_type': 'qcow2',
'block_migration': False},
{'is_shared_block_storage': True,
'is_shared_instance_path': True,
'is_volume_backed': False,
'filename': 'foo',
'instance_relative_path': 'bar',
'disk_over_commit': False,
'disk_available_mb': 123,
'image_type': 'qcow2',
'block_migration': False},
{'is_shared_block_storage': False,
'is_shared_instance_path': True,
'is_volume_backed': False,
'filename': 'foo',
'instance_relative_path': 'bar',
'disk_over_commit': False,
'disk_available_mb': 123,
'image_type': 'qcow2',
'block_migration': True}]
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
@@ -7588,11 +7651,14 @@ class LibvirtConnTestCase(test.NoDBTestCase):
disk_info=disk_info_json,
migrate_data=migrate_data)
self.assertFalse(create_image_mock.called)
self.assertIsInstance(res, dict)
self.assertIsInstance(res,
objects.LibvirtLiveMigrateData)
def test_pre_live_migration_with_not_shared_instance_path(self):
migrate_data = {'is_shared_block_storage': False,
'is_shared_instance_path': False}
'is_shared_instance_path': False,
'block_migration': False,
'instance_relative_path': 'foo'}
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance = objects.Instance(**self.test_instance)
@@ -7623,7 +7689,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
create_image_mock.assert_has_calls(
[mock.call(self.context, instance, mock.ANY, {},
fallback_from_host=instance.host)])
self.assertIsInstance(res, dict)
self.assertIsInstance(res, objects.LibvirtLiveMigrateData)
def test_get_instance_disk_info_works_correctly(self):
# Test data
+2 -1
View File
@@ -734,7 +734,8 @@ disk size: 4.4M
expected_path = os.path.join(CONF.instances_path, instance['uuid'])
self.assertEqual(expected_path, inst_path_at_dest)
migrate_data = dict(instance_relative_path='fake_relative_path')
migrate_data = objects.LibvirtLiveMigrateData(
instance_relative_path='fake_relative_path')
inst_path_at_dest = libvirt_utils.get_instance_path_at_destination(
instance, migrate_data)
expected_path = os.path.join(CONF.instances_path, 'fake_relative_path')
+65 -47
View File
@@ -78,6 +78,7 @@ from nova import image
from nova.network import model as network_model
from nova import objects
from nova.objects import fields
from nova.objects import migrate_data as migrate_data_obj
from nova.pci import manager as pci_manager
from nova.pci import utils as pci_utils
from nova import utils
@@ -5142,11 +5143,13 @@ class LibvirtDriver(driver.ComputeDriver):
# Create file on storage, to be checked on source host
filename = self._create_shared_storage_test_file()
return {"filename": filename,
"image_type": CONF.libvirt.images_type,
"block_migration": block_migration,
"disk_over_commit": disk_over_commit,
"disk_available_mb": disk_available_mb}
data = objects.LibvirtLiveMigrateData()
data.filename = filename
data.image_type = CONF.libvirt.images_type
data.block_migration = block_migration
data.disk_over_commit = disk_over_commit
data.disk_available_mb = disk_available_mb
return data
def check_can_live_migrate_destination_cleanup(self, context,
dest_check_data):
@@ -5175,13 +5178,18 @@ class LibvirtDriver(driver.ComputeDriver):
# if block migration, instances_paths should not be on shared storage.
source = CONF.host
dest_check_data.update({'is_shared_instance_path':
self._check_shared_storage_test_file(
dest_check_data['filename'])})
if not isinstance(dest_check_data, migrate_data_obj.LiveMigrateData):
md_obj = migrate_data_obj.LibvirtLiveMigrateData()
md_obj.from_legacy_dict(dest_check_data)
dest_check_data = md_obj
dest_check_data.update({'is_shared_block_storage':
self._is_shared_block_storage(instance, dest_check_data,
block_device_info)})
dest_check_data.is_shared_instance_path = (
self._check_shared_storage_test_file(
dest_check_data.filename))
dest_check_data.is_shared_block_storage = (
self._is_shared_block_storage(instance, dest_check_data,
block_device_info))
disk_info_text = self.get_instance_disk_info(
instance, block_device_info=block_device_info)
@@ -5189,15 +5197,15 @@ class LibvirtDriver(driver.ComputeDriver):
disk_info_text)
has_local_disk = self._has_local_disk(instance, disk_info_text)
if dest_check_data['block_migration']:
if (dest_check_data['is_shared_block_storage'] or
dest_check_data['is_shared_instance_path']):
if dest_check_data.block_migration:
if (dest_check_data.is_shared_block_storage or
dest_check_data.is_shared_instance_path):
reason = _("Block migration can not be used "
"with shared storage.")
raise exception.InvalidLocalStorage(reason=reason, path=source)
self._assert_dest_node_has_enough_disk(context, instance,
dest_check_data['disk_available_mb'],
dest_check_data['disk_over_commit'],
dest_check_data.disk_available_mb,
dest_check_data.disk_over_commit,
block_device_info)
if block_device_info:
bdm = block_device_info.get('block_device_mapping')
@@ -5213,8 +5221,8 @@ class LibvirtDriver(driver.ComputeDriver):
'volumes') % instance.uuid)
raise exception.MigrationPreCheckError(reason=msg)
elif not (dest_check_data['is_shared_block_storage'] or
dest_check_data['is_shared_instance_path'] or
elif not (dest_check_data.is_shared_block_storage or
dest_check_data.is_shared_instance_path or
(booted_from_volume and not has_local_disk)):
reason = _("Live migration can not be used "
"without shared storage except "
@@ -5227,13 +5235,7 @@ class LibvirtDriver(driver.ComputeDriver):
# same name to be used
instance_path = libvirt_utils.get_instance_path(instance,
relative=True)
dest_check_data['instance_relative_path'] = instance_path
# NOTE(danms): Emulate this old flag in case we're talking to
# an older client (<= Juno). We can remove this when we bump the
# compute RPC API to 4.0.
dest_check_data['is_shared_storage'] = (
dest_check_data['is_shared_instance_path'])
dest_check_data.instance_relative_path = instance_path
return dest_check_data
@@ -5250,18 +5252,19 @@ class LibvirtDriver(driver.ComputeDriver):
:param dest_check_data: dict with boolean fields image_type,
is_shared_instance_path, and is_volume_backed
"""
if (CONF.libvirt.images_type == dest_check_data.get('image_type') and
if (dest_check_data.obj_attr_is_set('image_type') and
CONF.libvirt.images_type == dest_check_data.image_type and
self.image_backend.backend().is_shared_block_storage()):
# NOTE(dgenin): currently true only for RBD image backend
return True
if (dest_check_data.get('is_shared_instance_path') and
if (dest_check_data.is_shared_instance_path and
self.image_backend.backend().is_file_in_instance_path()):
# NOTE(angdraug): file based image backends (Raw, Qcow2)
# place block device files under the instance path
return True
if (dest_check_data.get('is_volume_backed') and
if (dest_check_data.is_volume_backed and
not bool(jsonutils.loads(
self.get_instance_disk_info(instance,
block_device_info)))):
@@ -6161,12 +6164,18 @@ class LibvirtDriver(driver.ComputeDriver):
# NOTE(gcb): Failed block live migration may leave instance
# directory at destination node, ensure it is always deleted.
is_shared_instance_path = True
instance_relative_path = None
if migrate_data:
is_shared_instance_path = migrate_data.get(
'is_shared_instance_path', True)
instance_relative_path = migrate_data.get(
'instance_relative_path')
mdo = objects.LibvirtLiveMigrateData()
if instance_relative_path:
mdo.instance_relative_path = instance_relative_path
if not is_shared_instance_path:
instance_dir = libvirt_utils.get_instance_path_at_destination(
instance, migrate_data)
instance, mdo)
if os.path.exists(instance_dir):
shutil.rmtree(instance_dir)
@@ -6181,13 +6190,15 @@ class LibvirtDriver(driver.ComputeDriver):
is_shared_instance_path = True
is_block_migration = True
if migrate_data:
if not isinstance(migrate_data, migrate_data_obj.LiveMigrateData):
obj = objects.LibvirtLiveMigrateData()
obj.from_legacy_dict(migrate_data)
migrate_data = obj
LOG.debug('migrate_data in pre_live_migration: %s', migrate_data,
instance=instance)
is_shared_block_storage = migrate_data.get(
'is_shared_block_storage', True)
is_shared_instance_path = migrate_data.get(
'is_shared_instance_path', True)
is_block_migration = migrate_data.get('block_migration', True)
is_shared_block_storage = migrate_data.is_shared_block_storage
is_shared_instance_path = migrate_data.is_shared_instance_path
is_block_migration = migrate_data.block_migration
image_meta = objects.ImageMeta.from_instance(instance)
@@ -6277,25 +6288,32 @@ class LibvirtDriver(driver.ComputeDriver):
greenthread.sleep(1)
# Store vncserver_listen and latest disk device info
res_data = {'graphics_listen_addrs': {}, 'volume': {},
'serial_listen_addr': {}}
res_data['graphics_listen_addrs']['vnc'] = CONF.vnc.vncserver_listen
res_data['graphics_listen_addrs']['spice'] = CONF.spice.server_listen
res_data['serial_listen_addr'] = \
CONF.serial_console.proxyclient_address
if not migrate_data:
migrate_data = objects.LibvirtLiveMigrateData(bdms=[])
else:
migrate_data.bdms = []
migrate_data.graphics_listen_addr_vnc = CONF.vnc.vncserver_listen
migrate_data.graphics_listen_addr_spice = CONF.spice.server_listen
migrate_data.serial_listen_addr = \
CONF.serial_console.proxyclient_address
for vol in block_device_mapping:
connection_info = vol['connection_info']
if connection_info.get('serial'):
serial = connection_info['serial']
res_data['volume'][serial] = {'connection_info': {},
'disk_info': {}}
res_data['volume'][serial]['connection_info'] = \
connection_info
disk_info = blockinfo.get_info_from_bdm(
instance, CONF.libvirt.virt_type, image_meta, vol)
res_data['volume'][serial]['disk_info'] = disk_info
return res_data
bdmi = objects.LibvirtLiveMigrateBDMInfo()
bdmi.serial = connection_info['serial']
bdmi.connection_info = connection_info
bdmi.bus = disk_info['bus']
bdmi.dev = disk_info['dev']
bdmi.type = disk_info['type']
bdmi.format = disk_info.get('format')
bdmi.boot_index = disk_info.get('boot_index')
migrate_data.bdms.append(bdmi)
return migrate_data
def _try_fetch_image_cache(self, image, fetch_func, context, filename,
image_id, instance, size,
+1 -1
View File
@@ -449,7 +449,7 @@ def get_instance_path_at_destination(instance, migrate_data=None):
"""
instance_relative_path = None
if migrate_data:
instance_relative_path = migrate_data.get('instance_relative_path')
instance_relative_path = migrate_data.instance_relative_path
# NOTE(mikal): this doesn't use libvirt_utils.get_instance_path
# because we are ensuring that the same instance directory name
# is used as was at the source