From 8fcdb4d628f3a55e4783f0a3df7ac7c0a36eaa43 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Thu, 11 Apr 2019 16:58:32 +0200 Subject: [PATCH] ceph-volume: batch ensure device lists are disjoint Fixes: https://tracker.ceph.com/issues/41018 Signed-off-by: Jan Fajerski --- src/ceph-volume/ceph_volume/devices/lvm/batch.py | 14 ++++++++++++-- .../ceph_volume/tests/devices/lvm/test_batch.py | 11 +++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/ceph-volume/ceph_volume/devices/lvm/batch.py b/src/ceph-volume/ceph_volume/devices/lvm/batch.py index b038ee4594a..be062a50365 100644 --- a/src/ceph-volume/ceph_volume/devices/lvm/batch.py +++ b/src/ceph-volume/ceph_volume/devices/lvm/batch.py @@ -254,7 +254,7 @@ class Batch(object): self.args = parser.parse_args(argv) self.parser = parser for dev_list in ['', 'db_', 'wal_', 'journal_']: - setattr(self, '{}usable'.format(dev_list), []) + setattr(self, '{}usable'.format(dev_list), set()) def get_devices(self): # remove devices with partitions @@ -327,6 +327,7 @@ class Batch(object): def _get_explicit_strategy(self): # TODO assert that none of the device lists overlap? self._filter_devices() + self._ensure_disjoint_device_lists() if self.args.bluestore: if self.db_usable or self.wal_usable: self.strategy = strategies.bluestore.MixedType( @@ -360,8 +361,17 @@ class Batch(object): dev_list_prop = '{}devices'.format(dev_list) if hasattr(self.args, dev_list_prop): usable_dev_list_prop = '{}usable'.format(dev_list) - usable = [d for d in getattr(self.args, dev_list_prop) if d.available] + usable = set([d for d in getattr(self.args, dev_list_prop) if + d.available]) setattr(self, usable_dev_list_prop, usable) self.filtered_devices.update({d: used_reason for d in getattr(self.args, dev_list_prop) if d.used_by_ceph}) + + def _ensure_disjoint_device_lists(self): + # check that all device lists are disjoint with each other + if not(self.usable.isdisjoint(self.db_usable) and + self.usable.isdisjoint(self.wal_usable) and + self.usable.isdisjoint(self.journal_usable) and + self.db_usable.isdisjoint(self.wal_usable)): + raise Exception('Device lists are not disjoint') diff --git a/src/ceph-volume/ceph_volume/tests/devices/lvm/test_batch.py b/src/ceph-volume/ceph_volume/tests/devices/lvm/test_batch.py index 7ad77ab1ef0..f0311028984 100644 --- a/src/ceph-volume/ceph_volume/tests/devices/lvm/test_batch.py +++ b/src/ceph-volume/ceph_volume/tests/devices/lvm/test_batch.py @@ -1,3 +1,4 @@ +import pytest from ceph_volume.devices.lvm import batch @@ -55,6 +56,16 @@ class TestBatch(object): result = b.get_devices().strip() assert result == '* /dev/vdf 20.00 GB rotational' + def test_disjoint_device_lists(self, factory): + device1 = factory(used_by_ceph=False, available=True, abspath="/dev/sda") + device2 = factory(used_by_ceph=False, available=True, abspath="/dev/sdb") + b = batch.Batch([]) + b.args.devices = [device1, device2] + b.args.db_devices = [device2] + b._filter_devices() + with pytest.raises(Exception): + b._ensure_disjoint_device_lists() + class TestFilterDevices(object): -- 2.39.5