Rediscover hdisk if connection info refreshed
Although the UDID for a VSCSI attached volume is saved in the bdm during attach, it can be lost if the connection information is 'refreshed' by the compute manager. This fix rediscovers the hdisk during detach if we cannot look it up via the UDID. One scenario where the connection info is refreshed is live migration. Change-Id: I13846c494d72d57e47082d4d0fb2a286309aa0f1
This commit is contained in:
parent
0b79b60c32
commit
b380b0e445
|
@ -68,10 +68,16 @@ class BaseVSCSITest(test.TestCase):
|
|||
@mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.getter')
|
||||
@mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
|
||||
def init_vol_adpt(mock_pvm_uuid, mock_getter):
|
||||
con_info = {'data': {'initiator_target_map': {p_wwpn1: ['t1'],
|
||||
p_wwpn2: ['t2',
|
||||
't3']},
|
||||
'target_lun': '1', 'volume_id': 'id'}}
|
||||
con_info = {
|
||||
'data': {
|
||||
'initiator_target_map': {
|
||||
p_wwpn1: ['t1'],
|
||||
p_wwpn2: ['t2', 't3']
|
||||
},
|
||||
'target_lun': '1',
|
||||
'volume_id': 'id'
|
||||
},
|
||||
}
|
||||
mock_inst = mock.MagicMock()
|
||||
mock_pvm_uuid.return_value = '1234'
|
||||
|
||||
|
@ -189,6 +195,7 @@ class TestVSCSIAdapter(BaseVSCSITest):
|
|||
# The mock return values
|
||||
mock_hdisk_from_uuid.return_value = 'device_name'
|
||||
mock_get_vm_id.return_value = 'partition_id'
|
||||
self.vol_drv._set_udid('UDIDIT!')
|
||||
|
||||
def validate_remove_maps(vios_w, vm_uuid, match_func):
|
||||
self.assertIsInstance(vios_w, pvm_vios.VIOS)
|
||||
|
@ -216,6 +223,7 @@ class TestVSCSIAdapter(BaseVSCSITest):
|
|||
mock_remove_maps.return_value = None
|
||||
mock_hdisk_from_uuid.return_value = 'device_name'
|
||||
mock_get_vm_id.return_value = 'partition_id'
|
||||
self.vol_drv._set_udid('UDIDIT!')
|
||||
|
||||
# Run the method
|
||||
self.vol_drv.disconnect_volume()
|
||||
|
@ -225,6 +233,38 @@ class TestVSCSIAdapter(BaseVSCSITest):
|
|||
self.assertEqual(0, self.ft_fx.patchers['update'].mock.call_count)
|
||||
self.assertEqual(1, len(self.vol_drv._vioses_modified))
|
||||
|
||||
@mock.patch('pypowervm.tasks.hdisk.remove_hdisk')
|
||||
@mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.hdisk_from_uuid')
|
||||
@mock.patch('pypowervm.tasks.scsi_mapper.remove_maps')
|
||||
@mock.patch('nova_powervm.virt.powervm.vm.get_vm_id')
|
||||
def test_disconnect_volume_no_udid(
|
||||
self, mock_get_vm_id, mock_remove_maps, mock_hdisk_from_uuid,
|
||||
mock_remove_hdisk):
|
||||
|
||||
# The mock return values
|
||||
mock_hdisk_from_uuid.return_value = 'device_name'
|
||||
mock_get_vm_id.return_value = 'partition_id'
|
||||
|
||||
def validate_remove_maps(vios_w, vm_uuid, match_func):
|
||||
self.assertIsInstance(vios_w, pvm_vios.VIOS)
|
||||
self.assertEqual('partition_id', vm_uuid)
|
||||
return 'removed'
|
||||
mock_remove_maps.side_effect = validate_remove_maps
|
||||
|
||||
with mock.patch.object(
|
||||
self.vol_drv, '_discover_volume_on_vios',
|
||||
return_value=('status', 'dev_name', 'udidit')):
|
||||
|
||||
# Run the method
|
||||
self.vol_drv.disconnect_volume()
|
||||
|
||||
# As initialized above, remove_maps returns True to trigger update.
|
||||
self.assertEqual(1, mock_remove_maps.call_count)
|
||||
self.assertEqual(1, self.ft_fx.patchers['update'].mock.call_count)
|
||||
mock_remove_hdisk.assert_called_once_with(
|
||||
self.adpt, mock.ANY, 'dev_name', self.vios_uuid)
|
||||
self.assertListEqual([self.vios_uuid], self.vol_drv._vioses_modified)
|
||||
|
||||
@mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.hdisk_from_uuid')
|
||||
@mock.patch('pypowervm.tasks.scsi_mapper.remove_maps')
|
||||
def test_disconnect_volume_no_valid_vio(self, mock_remove_maps,
|
||||
|
|
|
@ -250,16 +250,22 @@ class VscsiVolumeAdapter(v_driver.FibreChannelVolumeAdapter):
|
|||
"""
|
||||
LOG.debug("Disconnect volume %(vol)s from vios uuid %(uuid)s",
|
||||
dict(vol=volume_id, uuid=vios_w.uuid))
|
||||
volume_udid = None
|
||||
udid, device_name = None, None
|
||||
try:
|
||||
volume_udid = self._get_udid()
|
||||
device_name = vios_w.hdisk_from_uuid(volume_udid)
|
||||
udid = self._get_udid()
|
||||
if not udid:
|
||||
# We lost our bdm data. We'll need to discover it.
|
||||
status, device_name, udid = self._discover_volume_on_vios(
|
||||
vios_w, volume_id)
|
||||
|
||||
if udid and not device_name:
|
||||
device_name = vios_w.hdisk_from_uuid(udid)
|
||||
|
||||
if not device_name:
|
||||
LOG.warn(_LW("Disconnect Volume: No mapped device found on "
|
||||
"Virtual I/O Server %(vios)s for volume "
|
||||
"%(volume_id)s. Volume UDID: %(volume_uid)s"),
|
||||
{'volume_uid': volume_udid, 'volume_id': volume_id,
|
||||
{'volume_uid': udid, 'volume_id': volume_id,
|
||||
'vios': vios_w.name})
|
||||
return False
|
||||
|
||||
|
@ -267,7 +273,7 @@ class VscsiVolumeAdapter(v_driver.FibreChannelVolumeAdapter):
|
|||
LOG.warn(_LW("Disconnect Volume: Failed to find disk on Virtual "
|
||||
"I/O Server %(vios_name)s for volume %(volume_id)s. "
|
||||
"Volume UDID: %(volume_uid)s. Error: %(error)s"),
|
||||
{'error': e, 'volume_uid': volume_udid,
|
||||
{'error': e, 'volume_uid': udid,
|
||||
'volume_id': volume_id, 'vios_name': vios_w.name})
|
||||
return False
|
||||
|
||||
|
@ -275,7 +281,7 @@ class VscsiVolumeAdapter(v_driver.FibreChannelVolumeAdapter):
|
|||
LOG.info(_LI("Disconnect Volume: Discovered the device %(hdisk)s on "
|
||||
"Virtual I/O Server %(vios_name)s for volume "
|
||||
"%(volume_id)s. Volume UDID: %(volume_uid)s."),
|
||||
{'volume_uid': volume_udid, 'volume_id': volume_id,
|
||||
{'volume_uid': udid, 'volume_id': volume_id,
|
||||
'vios_name': vios_w.name, 'hdisk': device_name})
|
||||
|
||||
# Add the action to remove the mapping when the stg_ftsk is run.
|
||||
|
@ -405,6 +411,8 @@ class VscsiVolumeAdapter(v_driver.FibreChannelVolumeAdapter):
|
|||
try:
|
||||
return self.connection_info['data'][UDID_KEY]
|
||||
except (KeyError, ValueError):
|
||||
LOG.warn(_LW(u'Failed to retrieve device_id key from BDM for '
|
||||
# It's common to lose our specific data in the BDM. The connection
|
||||
# information can be 'refreshed' by operations like LPM and resize
|
||||
LOG.info(_LI(u'Failed to retrieve device_id key from BDM for '
|
||||
'volume id %s'), self.volume_id)
|
||||
return None
|
||||
|
|
Loading…
Reference in New Issue