]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/python-common/ceph/deployment/drive_selection/selector.py
import quincy beta 17.1.0
[ceph.git] / ceph / src / python-common / ceph / deployment / drive_selection / selector.py
index a54df3268a823cbd0076a0390028427d2d0acdee..8aed3d19794f5bd12167377c000b7a190d43d7ba 100644 (file)
@@ -1,18 +1,27 @@
 import logging
 
-try:
-    from typing import List, Optional
-except ImportError:
-    pass
+from typing import List, Optional, Dict, Callable
 
 from ..inventory import Device
-from ..drive_group import DriveGroupSpec, DeviceSelection
+from ..drive_group import DriveGroupSpec, DeviceSelection, DriveGroupValidationError
 
 from .filter import FilterGenerator
+from .matchers import _MatchInvalid
 
 logger = logging.getLogger(__name__)
 
 
+def to_dg_exception(f: Callable) -> Callable[['DriveSelection', str,
+                                              Optional['DeviceSelection']],
+                                             List['Device']]:
+    def wrapper(self: 'DriveSelection', name: str, ds: Optional['DeviceSelection']) -> List[Device]:
+        try:
+            return f(self, ds)
+        except _MatchInvalid as e:
+            raise DriveGroupValidationError(f'{self.spec.service_id}.{name}', e.args[0])
+    return wrapper
+
+
 class DriveSelection(object):
     def __init__(self,
                  spec,  # type: DriveGroupSpec
@@ -23,10 +32,10 @@ class DriveSelection(object):
         self.spec = spec
         self.existing_daemons = existing_daemons or 0
 
-        self._data = self.assign_devices(self.spec.data_devices)
-        self._wal = self.assign_devices(self.spec.wal_devices)
-        self._db = self.assign_devices(self.spec.db_devices)
-        self._journal = self.assign_devices(self.spec.journal_devices)
+        self._data = self.assign_devices('data_devices', self.spec.data_devices)
+        self._wal = self.assign_devices('wal_devices', self.spec.wal_devices)
+        self._db = self.assign_devices('db_devices', self.spec.db_devices)
+        self._journal = self.assign_devices('journal_devices', self.spec.journal_devices)
 
     def data_devices(self):
         # type: () -> List[Device]
@@ -79,6 +88,7 @@ class DriveSelection(object):
             raise Exception(
                 "Disk {} doesn't have a 'path' identifier".format(disk))
 
+    @to_dg_exception
     def assign_devices(self, device_filter):
         # type: (Optional[DeviceSelection]) -> List[Device]
         """ Assign drives based on used filters
@@ -149,3 +159,14 @@ class DriveSelection(object):
                 self.disks.remove(taken_device)
 
         return sorted([x for x in devices], key=lambda dev: dev.path)
+
+    def __repr__(self) -> str:
+        selection: Dict[str, List[str]] = {
+            'data devices': [d.path for d in self._data],
+            'wal_devices': [d.path for d in self._wal],
+            'db devices': [d.path for d in self._db],
+            'journal devices': [d.path for d in self._journal]
+        }
+        return "DeviceSelection({})".format(
+            ', '.join('{}={}'.format(key, selection[key]) for key in selection.keys())
+        )