iSCSI Live Migration Support
Implement the interfaces needed to support live migration. Change-Id: I38cb9ccbae311e0e5edcef4a2d4464d45ef3db39
This commit is contained in:
parent
8429cc6185
commit
ba17efd947
|
@ -487,3 +487,82 @@ class TestISCSIAdapter(test_vol.TestVolumeAdapter):
|
|||
self.vol_drv.connection_info['data'].pop('target_iqn')
|
||||
props = self.vol_drv._get_iscsi_conn_props(vios_w, auth=False)
|
||||
self.assertIsNone(props)
|
||||
|
||||
@mock.patch('nova_powervm.virt.powervm.volume.driver.PowerVMVolumeAdapter.'
|
||||
'vios_uuids', new_callable=mock.PropertyMock)
|
||||
@mock.patch('pypowervm.tasks.hdisk.discover_iscsi')
|
||||
@mock.patch('pypowervm.tasks.storage.find_stale_lpars')
|
||||
def test_pre_live_migration(self, mock_fsl, mock_discover,
|
||||
mock_vios_uuids):
|
||||
# The mock return values
|
||||
vios_ids = ['1300C76F-9814-4A4D-B1F0-5B69352A7DEA',
|
||||
'7DBBE705-E4C4-4458-8223-3EBE07015CA9']
|
||||
mock_vios_uuids.return_value = vios_ids
|
||||
|
||||
mock_fsl.return_value = []
|
||||
mock_discover.return_value = (
|
||||
'devname', 'udid')
|
||||
|
||||
# Run the method
|
||||
migrate_data = {}
|
||||
self.vol_drv.pre_live_migration_on_destination(migrate_data)
|
||||
volume_key = 'vscsi-' + self.serial
|
||||
self.assertEqual(migrate_data, {volume_key: 'udid'})
|
||||
|
||||
# Test exception path
|
||||
mock_discover.return_value = (
|
||||
'devname', None)
|
||||
|
||||
# Run the method
|
||||
self.assertRaises(p_exc.VolumePreMigrationFailed,
|
||||
self.vol_drv.pre_live_migration_on_destination, {})
|
||||
|
||||
# Test when volume discover on a single vios
|
||||
mock_discover.reset_mock()
|
||||
mock_discover.side_effect = [('devname', 'udid'), ('devname', None)]
|
||||
self.vol_drv.pre_live_migration_on_destination(migrate_data)
|
||||
self.assertEqual(migrate_data, {volume_key: 'udid'})
|
||||
self.assertEqual(2, mock_discover.call_count)
|
||||
|
||||
# Test with bad vios_uuid
|
||||
mock_discover.reset_mock()
|
||||
mock_vios_uuids.return_value = ['fake_vios']
|
||||
self.assertRaises(p_exc.VolumePreMigrationFailed,
|
||||
self.vol_drv.pre_live_migration_on_destination, {})
|
||||
mock_discover.assert_not_called()
|
||||
|
||||
@mock.patch('nova_powervm.virt.powervm.volume.driver.PowerVMVolumeAdapter.'
|
||||
'vios_uuids', new_callable=mock.PropertyMock)
|
||||
def test_is_volume_on_vios(self, mock_vios_uuids):
|
||||
# The mock return values
|
||||
mock_vios_uuids.return_value = ['fake_vios1', 'fake_vios2']
|
||||
|
||||
with mock.patch.object(self.vol_drv,
|
||||
'_discover_volume_on_vios') as mock_discover:
|
||||
found, udid = self.vol_drv.is_volume_on_vios(self.feed[0])
|
||||
mock_discover.assert_not_called()
|
||||
self.assertFalse(found)
|
||||
self.assertIsNone(udid)
|
||||
|
||||
mock_discover.reset_mock()
|
||||
mock_discover.return_value = 'device1', 'udid1'
|
||||
vios_ids = ['1300C76F-9814-4A4D-B1F0-5B69352A7DEA',
|
||||
'7DBBE705-E4C4-4458-8223-3EBE07015CA9']
|
||||
mock_vios_uuids.return_value = vios_ids
|
||||
|
||||
found, udid = self.vol_drv.is_volume_on_vios(self.feed[0])
|
||||
mock_discover.assert_called_once_with(self.feed[0])
|
||||
self.assertTrue(found)
|
||||
self.assertEqual(udid, 'udid1')
|
||||
|
||||
mock_discover.reset_mock()
|
||||
mock_discover.return_value = None, 'udid1'
|
||||
found, udid = self.vol_drv.is_volume_on_vios(self.feed[0])
|
||||
self.assertFalse(found)
|
||||
self.assertEqual(udid, 'udid1')
|
||||
|
||||
mock_discover.reset_mock()
|
||||
mock_discover.return_value = 'device1', None
|
||||
found, udid = self.vol_drv.is_volume_on_vios(self.feed[0])
|
||||
self.assertFalse(found)
|
||||
self.assertIsNone(udid)
|
||||
|
|
|
@ -137,7 +137,32 @@ class IscsiVolumeAdapter(volume.VscsiVolumeAdapter,
|
|||
information to the live_migration command, it
|
||||
should be added to this dictionary.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
# See the connect_volume for why this is a direct call instead of
|
||||
# using the tx_mgr.feed
|
||||
vios_wraps = pvm_vios.VIOS.get(self.adapter,
|
||||
xag=[pvm_const.XAG.VIO_STOR])
|
||||
|
||||
volume_key = 'vscsi-' + self.volume_id
|
||||
for vios_w in vios_wraps:
|
||||
if vios_w.uuid not in self.vios_uuids:
|
||||
continue
|
||||
# Discover the volume on all VIOS's to trigger the
|
||||
# device configuration, which in turn will discover the
|
||||
# LUN associated with the volume. This needs to be
|
||||
# attempted on all VIOS's to determine the VIOS's that
|
||||
# will be servicing IO for this volume.
|
||||
udid = self._discover_volume_on_vios(vios_w)[1]
|
||||
if udid:
|
||||
LOG.debug("Discovered volume udid %(udid)s on vios %(name)s",
|
||||
dict(udid=udid, name=vios_w.name))
|
||||
mig_data[volume_key] = udid
|
||||
|
||||
if volume_key not in mig_data:
|
||||
LOG.debug("Failed to discover the volume")
|
||||
ex_args = dict(volume_id=self.volume_id,
|
||||
instance_name=self.instance.name)
|
||||
raise p_exc.VolumePreMigrationFailed(**ex_args)
|
||||
|
||||
def is_volume_on_vios(self, vios_w):
|
||||
"""Returns whether or not the volume is on a VIOS.
|
||||
|
@ -147,6 +172,8 @@ class IscsiVolumeAdapter(volume.VscsiVolumeAdapter,
|
|||
otherwise.
|
||||
:return: The udid of the device.
|
||||
"""
|
||||
if vios_w.uuid not in self.vios_uuids:
|
||||
return False, None
|
||||
device_name, udid = self._discover_volume_on_vios(vios_w)
|
||||
return (device_name and udid) is not None, udid
|
||||
|
||||
|
|
Loading…
Reference in New Issue