skip mapped LUKS devices in osdize_dev

With BlueStore there are no file system mounts so having a simple check
for a LUKS header presence is good enough to avoid osdizing a used dev
which does not have an LVM super block indicating that a device is in
use.

Partial-Bug: #1781453

Change-Id: Idb98690f0bf11e6932fbe8c2930bb314b0dd3c48
This commit is contained in:
Dmitrii Shcherbakov 2018-07-14 01:44:33 +03:00
parent 3538759d75
commit 6ee0f95a2b
2 changed files with 137 additions and 1 deletions

View File

@ -1467,6 +1467,11 @@ def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False,
' skipping.'.format(dev))
return
if is_mapped_luks_device(dev):
log('{} is a mapped LUKS device,'
' skipping.'.format(dev))
return
if cmp_pkgrevno('ceph', '12.2.4') >= 0:
cmd = _ceph_volume(dev,
osd_journal,
@ -1678,6 +1683,29 @@ def is_active_bluestore_device(dev):
return False
def is_luks_device(dev):
"""
Determine if dev is a LUKS-formatted block device.
:param: dev: A full path to a block device to check for LUKS header
presence
:returns: boolean: indicates whether a device is used based on LUKS header.
"""
return True if _luks_uuid(dev) else False
def is_mapped_luks_device(dev):
"""
Determine if dev is a mapped LUKS device
:param: dev: A full path to a block device to be checked
:returns: boolean: indicates whether a device is mapped
"""
_, dirs, _ = next(os.walk('/sys/class/block/{}/holders/'
.format(os.path.basename(dev))))
is_held = len(dirs) > 0
return is_held and is_luks_device(dev)
def get_conf(variable):
"""
Get the value of the given configuration variable from the

View File

@ -70,13 +70,15 @@ class CephTestCase(unittest.TestCase):
@patch.object(utils, 'kv')
@patch.object(utils.subprocess, 'check_call')
@patch.object(utils, '_ceph_disk')
@patch.object(utils, 'is_mapped_luks_device')
@patch.object(utils, 'is_active_bluestore_device')
@patch.object(utils.os.path, 'exists')
@patch.object(utils, 'is_device_mounted')
@patch.object(utils, 'cmp_pkgrevno')
@patch.object(utils, 'is_block_device')
def test_osdize_dev_ceph_disk(self, _is_blk, _cmp, _mounted, _exists,
_is_active_bluestore_device, _ceph_disk,
_is_active_bluestore_device,
_is_mapped_luks_device, _ceph_disk,
_check_call, _kv):
"""Test that _ceph_disk is called for < Luminous 12.2.4"""
db = MagicMock()
@ -87,6 +89,7 @@ class CephTestCase(unittest.TestCase):
_exists.return_value = True
_cmp.return_value = -1
_ceph_disk.return_value = ['ceph-disk', 'prepare']
_is_mapped_luks_device.return_value = False
_is_active_bluestore_device.return_value = False
utils.osdize('/dev/sdb', osd_format='xfs', osd_journal=None,
bluestore=False)
@ -99,12 +102,14 @@ class CephTestCase(unittest.TestCase):
@patch.object(utils, 'kv')
@patch.object(utils.subprocess, 'check_call')
@patch.object(utils, '_ceph_volume')
@patch.object(utils, 'is_mapped_luks_device')
@patch.object(utils, 'is_active_bluestore_device')
@patch.object(utils.os.path, 'exists')
@patch.object(utils, 'is_device_mounted')
@patch.object(utils, 'cmp_pkgrevno')
@patch.object(utils, 'is_block_device')
def test_osdize_dev_ceph_volume(self, _is_blk, _cmp, _mounted, _exists,
_is_mapped_luks_device,
_is_active_bluestore_device, _ceph_volume,
_check_call, _kv):
"""Test that _ceph_volume is called for >= Luminous 12.2.4"""
@ -116,6 +121,7 @@ class CephTestCase(unittest.TestCase):
_exists.return_value = True
_cmp.return_value = 1
_ceph_volume.return_value = ['ceph-volume', 'prepare']
_is_mapped_luks_device.return_value = False
_is_active_bluestore_device.return_value = False
utils.osdize('/dev/sdb', osd_format='xfs', osd_journal=None,
bluestore=False)
@ -136,6 +142,36 @@ class CephTestCase(unittest.TestCase):
db.get.assert_called_with('osd-devices', [])
db.set.assert_not_called()
@patch.object(utils, 'kv')
@patch.object(utils.subprocess, 'check_call')
@patch.object(utils, '_ceph_volume')
@patch.object(utils, 'is_mapped_luks_device')
@patch.object(utils, 'is_active_bluestore_device')
@patch.object(utils.os.path, 'exists')
@patch.object(utils, 'is_device_mounted')
@patch.object(utils, 'cmp_pkgrevno')
@patch.object(utils, 'is_block_device')
def test_osdize_already_processed_luks_bluestore(
self, _is_blk, _cmp, _mounted,
_exists,
_is_active_bluestore_device, _is_mapped_luks_device,
_ceph_volume, _check_call, _kv):
"""Test that _ceph_volume is called for >= Luminous 12.2.4"""
db = MagicMock()
_kv.return_value = db
db.get.return_value = []
_is_blk.return_value = True
_mounted.return_value = False
_exists.return_value = True
_cmp.return_value = 1
_ceph_volume.return_value = ['ceph-volume', 'prepare']
_is_active_bluestore_device.return_value = False
_is_mapped_luks_device.return_value = True
utils.osdize('/dev/sdb', encrypt=True, osd_format=None,
osd_journal=None, bluestore=True, key_manager='vault')
db.get.assert_called_with('osd-devices', [])
db.set.assert_not_called()
@patch.object(utils.subprocess, 'check_call')
@patch.object(utils.os.path, 'exists')
@patch.object(utils, 'is_device_mounted')
@ -759,6 +795,78 @@ class CephActiveBlueStoreDeviceTestCase(unittest.TestCase):
self._test_active_bluestore_device(device='/dev/sde', active=False)
class CephLUKSDeviceTestCase(unittest.TestCase):
@patch.object(utils, '_luks_uuid')
def test_no_luks_header(self, _luks_uuid):
_luks_uuid.return_value = None
self.assertEqual(utils.is_luks_device('/dev/sdb'), False)
@patch.object(utils, '_luks_uuid')
def test_luks_header(self, _luks_uuid):
_luks_uuid.return_value = '5e1e4c89-4f68-4b9a-bd93-e25eec34e80f'
self.assertEqual(utils.is_luks_device('/dev/sdb'), True)
class CephMappedLUKSDeviceTestCase(unittest.TestCase):
@patch.object(utils.os, 'walk')
@patch.object(utils, '_luks_uuid')
def test_no_luks_header_not_mapped(self, _luks_uuid, _walk):
_luks_uuid.return_value = None
def os_walk_side_effect(path):
return {
'/sys/class/block/sdb/holders/': iter([('', [], [])]),
}[path]
_walk.side_effect = os_walk_side_effect
self.assertEqual(utils.is_mapped_luks_device('/dev/sdb'), False)
@patch.object(utils.os, 'walk')
@patch.object(utils, '_luks_uuid')
def test_luks_header_mapped(self, _luks_uuid, _walk):
_luks_uuid.return_value = 'db76d142-4782-42f2-84c6-914f9db889a0'
def os_walk_side_effect(path):
return {
'/sys/class/block/sdb/holders/': iter([('', ['dm-0'], [])]),
}[path]
_walk.side_effect = os_walk_side_effect
self.assertEqual(utils.is_mapped_luks_device('/dev/sdb'), True)
@patch.object(utils.os, 'walk')
@patch.object(utils, '_luks_uuid')
def test_luks_header_not_mapped(self, _luks_uuid, _walk):
_luks_uuid.return_value = 'db76d142-4782-42f2-84c6-914f9db889a0'
def os_walk_side_effect(path):
return {
'/sys/class/block/sdb/holders/': iter([('', [], [])]),
}[path]
_walk.side_effect = os_walk_side_effect
self.assertEqual(utils.is_mapped_luks_device('/dev/sdb'), False)
@patch.object(utils.os, 'walk')
@patch.object(utils, '_luks_uuid')
def test_no_luks_header_mapped(self, _luks_uuid, _walk):
"""
This is an edge case where a device is mapped (i.e. used for something
else) but has no LUKS header. Should be handled by other checks.
"""
_luks_uuid.return_value = None
def os_walk_side_effect(path):
return {
'/sys/class/block/sdb/holders/': iter([('', ['dm-0'], [])]),
}[path]
_walk.side_effect = os_walk_side_effect
self.assertEqual(utils.is_mapped_luks_device('/dev/sdb'), False)
class CephAllocateVolumeTestCase(unittest.TestCase):
_lvs = ['osd-data-1234', 'osd-block-1234', 'osd-journal-1234']