Verify WWN of connected iSCSI devices if passed

If a WWN has been provided in connection_properties, verify that the
found devices have that expected WWN. Fail the attachment if not. This
prevents cases where a device already exists on the host from an old
attachment that wasn't fully cleaned up, and the new attachment got
the same LUN. Using this old device could lead to data corruption.

Change-Id: I45a2221c0518213dc8132831c0bde9db4734da2b
Closes-Bug: 1813609
changes/76/633676/2
Avishay Traeger 4 years ago
parent 322554c386
commit 14be08d0b5

@ -153,6 +153,11 @@ class InvalidIOHandleObject(BrickException):
'type %(actual_type)s.')
class VolumeDeviceValidationFailed(BrickException):
message = _("Volume device validation failed for device %(device)s "
"(expected %(expected)s, found %(found)s.")
class VolumeEncryptionNotSupported(Invalid):
message = _("Volume encryption is not supported for %(volume_type)s "
"volume %(volume_id)s.")

@ -538,6 +538,9 @@ class ISCSIConnector(base.BaseLinuxConnector, base_iscsi.BaseISCSIConnector):
return symlink
def _get_connect_result(self, con_props, wwn, devices_names, mpath=None):
if 'wwn' in con_props:
self._linuxscsi.verify_sysfs_wwns(devices_names, con_props['wwn'])
device = '/dev/' + (mpath or devices_names[0])
# NOTE(geguileo): This is only necessary because of the current

@ -154,6 +154,16 @@ class LinuxSCSI(executor.Executor):
return udev_wwid
return ''
def verify_sysfs_wwns(self, device_names, expected_wwn):
"""Verify that all specified devices have the expected WWN."""
for device_name in device_names:
found_wwn = self.get_sysfs_wwn([device_name])
if found_wwn != expected_wwn:
raise exception.VolumeDeviceValidationFailed(
device=device_name, expected=expected_wwn,
found=found_wwn)
def get_scsi_wwn(self, path):
"""Read the WWN from page 0x83 value for a SCSI device."""

@ -920,6 +920,18 @@ loop0 0"""
open_mock.assert_has_calls([mock.call('/sys/block/sda/device/wwid'),
mock.call('/sys/block/sdb/device/wwid')])
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_sysfs_wwn')
def test_verify_sysfs_wwns_valid(self, get_wwn):
get_wwn.side_effect = ['123', '123', '123', '123']
self.linuxscsi.verify_sysfs_wwns(['sda', 'sdb', 'sdc', 'sdd'], '123')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_sysfs_wwn')
def test_verify_sysfs_wwns_invalid(self, get_wwn):
get_wwn.side_effect = ['123', '456', '123', '123']
self.assertRaises(exception.VolumeDeviceValidationFailed,
self.linuxscsi.verify_sysfs_wwns,
['sda', 'sdb', 'sdc', 'sdd'], '123')
@mock.patch.object(linuxscsi.priv_rootwrap, 'unlink_root')
@mock.patch('glob.glob')
@mock.patch('os.path.realpath', side_effect=['/dev/sda', '/dev/sdb',

@ -0,0 +1,9 @@
---
fixes:
- |
Adds verification that found iSCSI devices have the expected WWN
(must be provided in connection_properties). The attachment fails if
the WWNs do not match. This prevents cases where a device already
exists on the host from an old attachment that wasn't fully cleaned
up, and the new attachment got the same LUN. Using this old device
could lead to data corruption.
Loading…
Cancel
Save