]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
python-common/drivegroups: implement option to change filter_logic
authorJoshua Schmid <jschmid@suse.de>
Wed, 1 Jul 2020 09:10:14 +0000 (11:10 +0200)
committerJoshua Schmid <jschmid@suse.de>
Thu, 9 Jul 2020 13:23:07 +0000 (15:23 +0200)
Filters are applied to disks using an AND gate by default. In some
scenarios you can only achieve the desired behavior when using an OR
gate without expanding the available filters.

This patch allows to switch between `AND` and `OR` gates.

Signed-off-by: Joshua Schmid <jschmid@suse.de>
src/pybind/mgr/cephadm/tests/test_spec.py
src/python-common/ceph/deployment/drive_group.py
src/python-common/ceph/deployment/drive_selection/selector.py
src/python-common/ceph/tests/test_drive_group.py
src/python-common/ceph/tests/test_service_spec.py
src/python-common/ceph/tests/utils.py

index 1a048d82d6f32ca8a277e304d119032c1f840aaf..338759cf11ce7b0102869b190b84aeab91ecebad 100644 (file)
@@ -102,6 +102,7 @@ def test_spec_octopus(spec_json):
             spec = j_c.pop('spec')
             j_c.update(spec)
         j_c.pop('objectstore', None)
+        j_c.pop('filter_logic', None)
         return j_c
     assert spec_json == convert_to_old_style_json(spec.to_json())
 
index 96f93fb8db62a602f3de4443ff84dd74922823e0..40d0cae7605fa102e0d484e65b109f7a771e8f61 100644 (file)
@@ -143,7 +143,7 @@ class DriveGroupSpec(ServiceSpec):
         "db_slots", "wal_slots", "block_db_size", "placement", "service_id", "service_type",
         "data_devices", "db_devices", "wal_devices", "journal_devices",
         "data_directories", "osds_per_device", "objectstore", "osd_id_claims",
-        "journal_size", "unmanaged"
+        "journal_size", "unmanaged", "filter_logic"
     ]
 
     def __init__(self,
@@ -165,6 +165,7 @@ class DriveGroupSpec(ServiceSpec):
                  journal_size=None,  # type: Optional[int]
                  service_type=None,  # type: Optional[str]
                  unmanaged=False,  # type: bool
+                 filter_logic='AND'  # type: str
                  ):
         assert service_type is None or service_type == 'osd'
         super(DriveGroupSpec, self).__init__('osd', service_id=service_id,
@@ -215,6 +216,10 @@ class DriveGroupSpec(ServiceSpec):
         #: See :ref:`orchestrator-osd-replace`
         self.osd_id_claims = osd_id_claims or dict()
 
+        #: The logic gate we use to match disks with filters.
+        #: defaults to 'AND'
+        self.filter_logic = filter_logic.upper()
+
     @classmethod
     def _from_json_impl(cls, json_drive_group):
         # type: (dict) -> DriveGroupSpec
@@ -296,6 +301,9 @@ class DriveGroupSpec(ServiceSpec):
         if self.block_db_size is not None and type(self.block_db_size) != int:
             raise DriveGroupValidationError('block_db_size must be of type int')
 
+        if self.filter_logic not in ['AND', 'OR']:
+            raise DriveGroupValidationError('filter_logic must be either <AND> or <OR>')
+
     def __repr__(self):
         keys = [
             key for key in self._supported_features if getattr(self, key) is not None
index cdc21caa52ff2a6d6622b6f79f9ead16bd023bee..921f125616c25fd925a16f74bc6fef6c22273001 100644 (file)
@@ -134,11 +134,19 @@ class DriveSelection(object):
             if disk in devices:
                 continue
 
-            if not all(m.compare(disk) for m in FilterGenerator(device_filter)):
-                logger.debug(
-                    "Ignoring disk {}. Filter did not match".format(
-                        disk.path))
-                continue
+            if self.spec.filter_logic == 'AND':
+                if not all(m.compare(disk) for m in FilterGenerator(device_filter)):
+                    logger.debug(
+                        "Ignoring disk {}. Not all filter did match the disk".format(
+                            disk.path))
+                    continue
+
+            if self.spec.filter_logic == 'OR':
+                if not any(m.compare(disk) for m in FilterGenerator(device_filter)):
+                    logger.debug(
+                        "Ignoring disk {}. No filter matched the disk".format(
+                            disk.path))
+                    continue
 
             logger.debug('Adding disk {}'.format(disk.path))
             devices.append(disk)
index ba3cd6ec949f95f719d49aaa767fb4d9c6509586..85b2f3c217cd55ca9c8a3e8b5edf53a2e4bfdfb6 100644 (file)
@@ -43,6 +43,16 @@ placement:
   host_pattern: '*'
 data_devices:
   limit: 1
+"""),
+
+        yaml.safe_load("""
+service_type: osd
+service_id: mydg
+placement:
+  host_pattern: '*'
+data_devices:
+  all: True
+filter_logic: XOR
 """)
     )
 ])
@@ -182,3 +192,19 @@ def test_ceph_volume_command_7():
     sel = drive_selection.DriveSelection(spec, inventory)
     cmd = translate.to_ceph_volume(sel, ['0', '1']).run()
     assert cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --osd-ids 0 1 --yes --no-systemd'
+
+
+def test_ceph_volume_command_8():
+    spec = DriveGroupSpec(placement=PlacementSpec(host_pattern='*'),
+                          data_devices=DeviceSelection(rotational=True, model='INTEL SSDS'),
+                          db_devices=DeviceSelection(model='INTEL SSDP'),
+                          filter_logic='OR',
+                          osd_id_claims={}
+                          )
+    inventory = _mk_inventory(_mk_device(rotational=True,  size='1.82 TB',  model='ST2000DM001-1ER1') +  # data
+                              _mk_device(rotational=False, size="223.0 GB", model='INTEL SSDSC2KG24') +  # data
+                              _mk_device(rotational=False, size="349.0 GB", model='INTEL SSDPED1K375GA')  # wal/db
+                              )
+    sel = drive_selection.DriveSelection(spec, inventory)
+    cmd = translate.to_ceph_volume(sel, []).run()
+    assert cmd == 'lvm batch --no-auto /dev/sda /dev/sdb --db-devices /dev/sdc --yes --no-systemd'
index 7d12ff5d358203bef021074e28e78ff459dc5560..5f15ae45a90e57d2849a24ae3463402f7bdbf9c5 100644 (file)
@@ -151,6 +151,7 @@ spec:
     model: MC-55-44-XZ
   db_devices:
     model: SSD-123-foo
+  filter_logic: AND
   objectstore: bluestore
   wal_devices:
     model: NVME-QQQQ-987
index ebba43094bc10451044d7d459c366753d80d7fde..04b8a4e38955425441d5b80d2c8dbb6f71b2d6a1 100644 (file)
@@ -8,12 +8,14 @@ except ImportError:
 
 def _mk_device(rotational=True,
                locked=False,
-               size="394.27 GB"):
+               size="394.27 GB",
+               vendor='Vendor',
+               model='Model'):
     return [Device(
         path='??',
         sys_api={
             "rotational": '1' if rotational else '0',
-            "vendor": "Vendor",
+            "vendor": vendor,
             "human_readable_size": size,
             "partitions": {},
             "locked": int(locked),
@@ -21,7 +23,7 @@ def _mk_device(rotational=True,
             "removable": "0",
             "path": "??",
             "support_discard": "",
-            "model": "Model",
+            "model": model,
             "ro": "0",
             "nr_requests": "128",
             "size": 423347879936  # ignore coversion from human_readable_size