]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/cephadm: SNMP: use of python3 enums
authorSebastian Wagner <sewagner@redhat.com>
Thu, 16 Dec 2021 16:43:47 +0000 (17:43 +0100)
committerSebastian Wagner <sewagner@redhat.com>
Tue, 18 Jan 2022 10:45:18 +0000 (11:45 +0100)
Little reason to duplicate things ourselves

Signed-off-by: Sebastian Wagner <sewagner@redhat.com>
(cherry picked from commit 0039accb2caedf99166b88cc5b75736b6a7fd5c2)

Conflicts:
src/pybind/mgr/orchestrator/module.py
src/python-common/ceph/deployment/service_spec.py
src/python-common/ceph/tests/test_service_spec.py

src/pybind/mgr/cephadm/tests/test_spec.py
src/pybind/mgr/orchestrator/module.py
src/python-common/ceph/deployment/service_spec.py
src/python-common/ceph/tests/test_service_spec.py

index 84fd9273868779ef1231a09de02db03eedbcbe93..2b113dfd98e136a6ef94411bd4ff5e7b9099ce62 100644 (file)
@@ -719,7 +719,7 @@ auth_protocol: SHA
 privacy_protocol: weewah
 snmp_destination: 192.168.1.42:162
 snmp_version: V3
-"""), 'privacy_protocol unsupported. Must be one of AES, DES'),
+"""), 'privacy_protocol unsupported. Must be one of DES, AES'),
         (YAMLdoc("""
 ---
 service_type: snmp-gateway
index 7d04c2d4e743eaa8a615f3272cb10bb6d2f1ba6a..4176a7adeeed51cd77e0c873460e5759773ac13b 100644 (file)
@@ -11,7 +11,7 @@ from prettytable import PrettyTable
 from ceph.deployment.inventory import Device
 from ceph.deployment.drive_group import DriveGroupSpec, DeviceSelection
 from ceph.deployment.service_spec import PlacementSpec, ServiceSpec, \
-    SNMPGatewaySpec, SNMPVersion, SNMPAuthType, SNMPPrivacyType
+    SNMPGatewaySpec
 from ceph.deployment.hostspec import SpecValidationError
 from ceph.utils import datetime_now
 
@@ -1161,12 +1161,12 @@ Usage:
 
     @_cli_write_command('orch apply snmp-gateway')
     def _apply_snmp_gateway(self,
-                            snmp_version: SNMPVersion,
+                            snmp_version: SNMPGatewaySpec.SNMPVersion,
                             destination: str,
                             port: int = 9464,
                             engine_id: Optional[str] = None,
-                            auth_protocol: Optional[SNMPAuthType] = None,
-                            privacy_protocol: Optional[SNMPPrivacyType] = None,
+                            auth_protocol: Optional[SNMPGatewaySpec.SNMPAuthType] = None,
+                            privacy_protocol: Optional[SNMPGatewaySpec.SNMPPrivacyType] = None,
                             placement: Optional[str] = None,
                             unmanaged: bool = False,
                             dry_run: bool = False,
@@ -1185,17 +1185,14 @@ Usage:
         except (OSError, yaml.YAMLError):
             raise OrchestratorValidationError('credentials file must be valid YAML')
 
-        auth = None if not auth_protocol else auth_protocol.value
-        priv = None if not privacy_protocol else privacy_protocol.value
-
         spec = SNMPGatewaySpec(
-            snmp_version=snmp_version.value,
+            snmp_version=snmp_version,
             port=port,
             credentials=credentials,
             snmp_destination=destination,
             engine_id=engine_id,
-            auth_protocol=auth,
-            privacy_protocol=priv,
+            auth_protocol=auth_protocol,
+            privacy_protocol=privacy_protocol,
             placement=PlacementSpec.from_string(placement),
             unmanaged=unmanaged,
             preview_only=dry_run
index 124b48889795a6ff72c809c2e7283ee9a2b57fbd..fea2ec766feadd326d15e0c3720595d9a3a36302 100644 (file)
@@ -16,20 +16,6 @@ from ceph.utils import is_hex
 ServiceSpecT = TypeVar('ServiceSpecT', bound='ServiceSpec')
 FuncT = TypeVar('FuncT', bound=Callable)
 
-class SNMPVersion(enum.Enum):
-    V2c = 'V2c'
-    V3 = 'V3'
-
-
-class SNMPAuthType(enum.Enum):
-    MD5 = 'MD5'
-    SHA = 'SHA'
-
-
-class SNMPPrivacyType(enum.Enum):
-    DES = 'DES'
-    AES = 'AES'
-
 
 def assert_valid_host(name: str) -> None:
     p = re.compile('^[a-zA-Z0-9-]+$')
@@ -1151,6 +1137,27 @@ yaml.add_representer(GrafanaSpec, ServiceSpec.yaml_representer)
 
 
 class SNMPGatewaySpec(ServiceSpec):
+    class SNMPVersion(str, enum.Enum):
+        V2c = 'V2c'
+        V3 = 'V3'
+
+        def to_json(self) -> str:
+            return self.value
+
+    class SNMPAuthType(str, enum.Enum):
+        MD5 = 'MD5'
+        SHA = 'SHA'
+
+        def to_json(self) -> str:
+            return self.value
+
+    class SNMPPrivacyType(str, enum.Enum):
+        DES = 'DES'
+        AES = 'AES'
+
+        def to_json(self) -> str:
+            return self.value
+
     valid_destination_types = [
         'Name:Port',
         'IPv4:Port'
@@ -1158,12 +1165,12 @@ class SNMPGatewaySpec(ServiceSpec):
 
     def __init__(self,
                  service_type: str = 'snmp-gateway',
-                 snmp_version: Optional[str] = None,
+                 snmp_version: Optional[SNMPVersion] = None,
                  snmp_destination: str = '',
                  credentials: Dict[str, str] = {},
                  engine_id: Optional[str] = None,
-                 auth_protocol: Optional[str] = None,
-                 privacy_protocol: Optional[str] = None,
+                 auth_protocol: Optional[SNMPAuthType] = None,
+                 privacy_protocol: Optional[SNMPPrivacyType] = None,
                  placement: Optional[PlacementSpec] = None,
                  unmanaged: bool = False,
                  preview_only: bool = False,
@@ -1186,6 +1193,25 @@ class SNMPGatewaySpec(ServiceSpec):
         self.auth_protocol = auth_protocol
         self.privacy_protocol = privacy_protocol
 
+    @classmethod
+    def _from_json_impl(cls, json_spec: dict) -> 'SNMPGatewaySpec':
+
+        cpy = json_spec.copy()
+        types = [
+            ('snmp_version', SNMPGatewaySpec.SNMPVersion),
+            ('auth_protocol', SNMPGatewaySpec.SNMPAuthType),
+            ('privacy_protocol', SNMPGatewaySpec.SNMPPrivacyType),
+        ]
+        for d in cpy, cpy.get('spec', {}):
+            for key, enum_cls in types:
+                try:
+                    if key in d:
+                        d[key] = enum_cls(d[key])
+                except ValueError:
+                    raise SpecValidationError(f'{key} unsupported. Must be one of '
+                                              f'{", ".join(enum_cls)}')
+        return super(SNMPGatewaySpec, cls)._from_json_impl(cpy)
+
     @property
     def ports(self) -> List[int]:
         return [self.port]
@@ -1196,14 +1222,6 @@ class SNMPGatewaySpec(ServiceSpec):
     def validate(self) -> None:
         super(SNMPGatewaySpec, self).validate()
 
-        def _check_type(name: str, value: Optional[str], options: List[str]) -> None:
-            if not value:
-                return
-            if value not in options:
-                raise SpecValidationError(
-                    f'{name} unsupported. Must be one of {", ".join(sorted(options))}'
-                )
-
         if not self.credentials:
             raise SpecValidationError(
                 'Missing authentication information (credentials). '
@@ -1214,16 +1232,6 @@ class SNMPGatewaySpec(ServiceSpec):
                 'Missing SNMP version (snmp_version)'
             )
 
-        _check_type('snmp_version',
-                    self.snmp_version,
-                    list(set(opt.value for opt in SNMPVersion)))
-        _check_type('auth_protocol',
-                    self.auth_protocol,
-                    list(set(opt.value for opt in SNMPAuthType)))
-        _check_type('privacy_protocol',
-                    self.privacy_protocol,
-                    list(set(opt.value for opt in SNMPPrivacyType)))
-
         creds_requirement = {
             'V2c': ['snmp_community'],
             'V3': ['snmp_v3_auth_username', 'snmp_v3_auth_password']
index 04225e2e1a231ae1b4db91fcc73a27a135eb6a0c..93ae36b49a96a61f01b0781bcd22ec9e1d84cf33 100644 (file)
@@ -561,6 +561,23 @@ service_id: foo
 placement:
   count_per_host: 0
 """, "count-per-host must be >= 1",),
+    ("""
+service_type: snmp-gateway
+service_name: snmp-gateway
+placement:
+  count: 1
+spec:
+  credentials:
+    snmp_v3_auth_password: mypassword
+    snmp_v3_auth_username: myuser
+    snmp_v3_priv_password: mysecret
+  port: 9464
+  engine_id: 8000c53f0000000000
+  privacy_protocol: WEIRD
+  snmp_destination: 192.168.122.1:162
+  auth_protocol: BIZARRE
+  snmp_version: V3
+""", "auth_protocol unsupported. Must be one of MD5, SHA"),
     ])
 def test_service_spec_validation_error(y, error_match):
     data = yaml.safe_load(y)