FC discover existing devices for removal
Due to the way Nova live migration works, we can't rely on having the device path that was discovered at connect_volume time existing in the device_info. This patch uses the existing connection_properties to rediscover the existing volume paths on the system at the time disconnect_volume is called. This ensures that whatever paths/devices are associated with at volume at disconnect_volume time exists, they will be removed. Change-Id: I699fcff5dee595caa54ca7e80f67966edd1370ef Closes-Bug: 1406161
This commit is contained in:
parent
f3088d0e57
commit
981b84c49c
@ -818,6 +818,28 @@ class FibreChannelConnector(InitiatorConnector):
|
||||
self._linuxscsi.set_execute(execute)
|
||||
self._linuxfc.set_execute(execute)
|
||||
|
||||
def _get_possible_volume_paths(self, connection_properties, hbas):
|
||||
ports = connection_properties['target_wwn']
|
||||
possible_devs = self._get_possible_devices(hbas, ports)
|
||||
|
||||
lun = connection_properties.get('target_lun', 0)
|
||||
host_paths = self._get_host_devices(possible_devs, lun)
|
||||
return host_paths
|
||||
|
||||
def _get_volume_paths(self, connection_properties):
|
||||
"""Get a list of existing paths for a volume on the system."""
|
||||
volume_paths = []
|
||||
# first fetch all of the potential paths that might exist
|
||||
# and then filter those by what's actually on the system.
|
||||
hbas = self._linuxfc.get_fc_hbas_info()
|
||||
host_paths = self._get_possible_volume_paths(connection_properties,
|
||||
hbas)
|
||||
for path in host_paths:
|
||||
if os.path.exists(path):
|
||||
volume_paths.append(path)
|
||||
|
||||
return volume_paths
|
||||
|
||||
@synchronized('connect_volume')
|
||||
def connect_volume(self, connection_properties):
|
||||
"""Attach the volume to instance_name.
|
||||
@ -831,11 +853,8 @@ class FibreChannelConnector(InitiatorConnector):
|
||||
device_info = {'type': 'block'}
|
||||
|
||||
hbas = self._linuxfc.get_fc_hbas_info()
|
||||
ports = connection_properties['target_wwn']
|
||||
possible_devs = self._get_possible_devices(hbas, ports)
|
||||
|
||||
lun = connection_properties.get('target_lun', 0)
|
||||
host_devices = self._get_host_devices(possible_devs, lun)
|
||||
host_devices = self._get_possible_volume_paths(connection_properties,
|
||||
hbas)
|
||||
|
||||
if len(host_devices) == 0:
|
||||
# this is empty because we don't have any FC HBAs
|
||||
@ -961,18 +980,16 @@ class FibreChannelConnector(InitiatorConnector):
|
||||
multipath_id = device_info['multipath_id']
|
||||
mdev_info = self._linuxscsi.find_multipath_device(multipath_id)
|
||||
devices = mdev_info['devices']
|
||||
LOG.debug("devices to remove = %s", devices)
|
||||
self._linuxscsi.flush_multipath_device(multipath_id)
|
||||
else:
|
||||
device = device_info['path']
|
||||
# now resolve this to a /dev/sdX path
|
||||
if os.path.exists(device):
|
||||
# get the /dev/sdX device from the
|
||||
# /dev/disk/by-path entry
|
||||
dev_name = os.path.realpath(device)
|
||||
dev_info = self._linuxscsi.get_device_info(dev_name)
|
||||
devices = [dev_info]
|
||||
devices = []
|
||||
volume_paths = self._get_volume_paths(connection_properties)
|
||||
for path in volume_paths:
|
||||
real_path = self._linuxscsi.get_name_from_path(path)
|
||||
device_info = self._linuxscsi.get_device_info(real_path)
|
||||
devices.append(device_info)
|
||||
|
||||
LOG.debug("devices to remove = %s", devices)
|
||||
self._remove_devices(connection_properties, devices)
|
||||
|
||||
def _remove_devices(self, connection_properties, devices):
|
||||
|
@ -920,15 +920,34 @@ class FibreChannelConnectorTestCase(ConnectorTestCase):
|
||||
'target_lun': 1,
|
||||
}}
|
||||
|
||||
@mock.patch.object(os.path, 'exists', return_value=True)
|
||||
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
|
||||
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
|
||||
def test_get_volume_paths(self, fake_fc_hbas_info,
|
||||
fake_fc_hbas, fake_exists):
|
||||
fake_fc_hbas.side_effect = self.fake_get_fc_hbas
|
||||
fake_fc_hbas_info.side_effect = self.fake_get_fc_hbas_info
|
||||
|
||||
name = 'volume-00000001'
|
||||
vol = {'id': 1, 'name': name}
|
||||
location = '10.0.2.15:3260'
|
||||
wwn = '1234567890123456'
|
||||
connection_info = self.fibrechan_connection(vol, location, wwn)
|
||||
volume_paths = self.connector._get_volume_paths(
|
||||
connection_info['data'])
|
||||
|
||||
expected = ['/dev/disk/by-path/pci-0000:05:00.2'
|
||||
'-fc-0x1234567890123456-lun-1']
|
||||
self.assertEqual(expected, volume_paths)
|
||||
|
||||
@mock.patch.object(os.path, 'exists', return_value=True)
|
||||
@mock.patch.object(os.path, 'realpath', return_value='/dev/sdb')
|
||||
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
|
||||
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
|
||||
@mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device')
|
||||
@mock.patch.object(linuxscsi.LinuxSCSI, 'remove_scsi_device')
|
||||
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
|
||||
def test_connect_volume(self, get_device_info_mock, remove_device_mock,
|
||||
find_device_mock, get_fc_hbas_info_mock,
|
||||
get_fc_hbas_info_mock,
|
||||
get_fc_hbas_mock, realpath_mock, exists_mock):
|
||||
get_fc_hbas_mock.side_effect = self.fake_get_fc_hbas
|
||||
get_fc_hbas_info_mock.side_effect = self.fake_get_fc_hbas_info
|
||||
@ -940,7 +959,6 @@ class FibreChannelConnectorTestCase(ConnectorTestCase):
|
||||
'address': '1:0:0:1',
|
||||
'host': 1, 'channel': 0,
|
||||
'id': 0, 'lun': 1}]}
|
||||
find_device_mock.return_value = devices
|
||||
get_device_info_mock.return_value = devices['devices'][0]
|
||||
|
||||
location = '10.0.2.15:3260'
|
||||
@ -957,6 +975,7 @@ class FibreChannelConnectorTestCase(ConnectorTestCase):
|
||||
exp_wwn)
|
||||
self.assertEqual(dev_info['type'], 'block')
|
||||
self.assertEqual(dev_info['path'], dev_str)
|
||||
self.assertTrue('multipath_id' not in dev_info)
|
||||
self.assertTrue('devices' not in dev_info)
|
||||
|
||||
self.connector.disconnect_volume(connection_info['data'], dev_info)
|
||||
|
Loading…
Reference in New Issue
Block a user