Check host device alive before multipath id discovery

In Fibre Channel environment, when nova hard reboot a vm,
it will select the first discovered path to find out the multipath id.
If the first path was failed, but not deleted, then multipath will fail,
and reboot will fail. Actually we have alive paths to boot the VM.

Closes-Bug: 1685969

Change-Id: I252569f8b49d9838090d1a0f454103204557c916
Signed-off-by: Liu Qing <liuqing@chinac.com>
This commit is contained in:
Liu Qing 2017-04-25 10:08:43 +08:00 committed by Walter A. Boring IV (hemna)
parent 90d0b43ee3
commit 6f03dd1cea
2 changed files with 52 additions and 4 deletions

View File

@ -143,7 +143,7 @@ class FibreChannelConnector(base.BaseLinuxConnector):
for device in host_devices:
LOG.debug("Looking for Fibre Channel dev %(device)s",
{'device': device})
if os.path.exists(device):
if os.path.exists(device) and self.check_valid_device(device):
self.host_device = device
# get the /dev/sdX device. This is used
# to find the multipath device.

View File

@ -138,7 +138,9 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(linuxscsi.LinuxSCSI, 'remove_scsi_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
def test_connect_volume(self, get_device_info_mock,
@mock.patch.object(base.BaseLinuxConnector, 'check_valid_device')
def test_connect_volume(self, check_valid_device_mock,
get_device_info_mock,
get_scsi_wwn_mock,
remove_device_mock,
get_fc_hbas_info_mock,
@ -146,6 +148,7 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
realpath_mock,
exists_mock,
wait_for_rw_mock):
check_valid_device_mock.return_value = True
get_fc_hbas_mock.side_effect = self.fake_get_fc_hbas
get_fc_hbas_info_mock.side_effect = self.fake_get_fc_hbas_info
@ -262,7 +265,9 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
def test_connect_volume_multipath_rw(self, get_device_info_mock,
@mock.patch.object(base.BaseLinuxConnector, 'check_valid_device')
def test_connect_volume_multipath_rw(self, check_valid_device_mock,
get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
get_fc_hbas_mock,
@ -271,6 +276,7 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
wait_for_rw_mock,
find_mp_dev_mock):
check_valid_device_mock.return_value = True
self._test_connect_volume_multipath(get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
@ -290,7 +296,9 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
@mock.patch.object(base.BaseLinuxConnector, 'check_valid_device')
def test_connect_volume_multipath_no_access_mode(self,
check_valid_device_mock,
get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
@ -300,6 +308,7 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
wait_for_rw_mock,
find_mp_dev_mock):
check_valid_device_mock.return_value = True
self._test_connect_volume_multipath(get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
@ -319,7 +328,9 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
def test_connect_volume_multipath_ro(self, get_device_info_mock,
@mock.patch.object(base.BaseLinuxConnector, 'check_valid_device')
def test_connect_volume_multipath_ro(self, check_valid_device_mock,
get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
get_fc_hbas_mock,
@ -328,6 +339,7 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
wait_for_rw_mock,
find_mp_dev_mock):
check_valid_device_mock.return_value = True
self._test_connect_volume_multipath(get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
@ -348,7 +360,9 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
@mock.patch.object(base.BaseLinuxConnector, 'check_valid_device')
def test_connect_volume_multipath_not_found(self,
check_valid_device_mock,
get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
@ -358,6 +372,7 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
wait_for_rw_mock,
find_mp_dev_mock,
discover_mp_dev_mock):
check_valid_device_mock.return_value = True
discover_mp_dev_mock.return_value = ("/dev/disk/by-path/something",
None)
@ -401,3 +416,36 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
expected = []
actual = self.connector.get_all_available_volumes()
self.assertItemsEqual(expected, actual)
@mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'wait_for_rw')
@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, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
@mock.patch.object(base.BaseLinuxConnector, 'check_valid_device')
def test_connect_volume_device_not_valid(self, check_valid_device_mock,
get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
get_fc_hbas_mock,
realpath_mock,
exists_mock,
wait_for_rw_mock,
find_mp_dev_mock):
check_valid_device_mock.return_value = False
self.assertRaises(exception.NoFibreChannelVolumeDeviceFound,
self._test_connect_volume_multipath,
get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
get_fc_hbas_mock,
realpath_mock,
exists_mock,
wait_for_rw_mock,
find_mp_dev_mock,
'rw',
True)