]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr: add types to MODULE_OPTIONS 36146/head
authorErnesto Puerta <epuertat@redhat.com>
Thu, 16 Jul 2020 18:21:14 +0000 (20:21 +0200)
committerErnesto Puerta <epuertat@redhat.com>
Mon, 14 Dec 2020 09:23:59 +0000 (10:23 +0100)
Uses a typed Option class for MODULE_OPTIONS and replaces those in the
modules that are checked by mypy.

Fixes: https://tracker.ceph.com/issues/46577
Signed-off-by: Ernesto Puerta <epuertat@redhat.com>
src/pybind/mgr/cephadm/module.py
src/pybind/mgr/mgr_module.py
src/pybind/mgr/orchestrator/module.py
src/pybind/mgr/progress/module.py
src/pybind/mgr/prometheus/module.py
src/pybind/mgr/rook/module.py
src/pybind/mgr/snap_schedule/module.py
src/pybind/mgr/stats/module.py
src/pybind/mgr/volumes/module.py
src/python-common/requirements.txt

index db7c83ed2513b9093ac6cf119fa100ec9e96815c..1286f8815ac4d6ef1ac71dfca47ae5d6f4520239 100644 (file)
@@ -29,7 +29,7 @@ from ceph.deployment.service_spec import \
 from cephadm.serve import CephadmServe
 from cephadm.services.cephadmservice import CephadmDaemonSpec
 
-from mgr_module import MgrModule, HandleCommandResult
+from mgr_module import MgrModule, HandleCommandResult, Option
 from mgr_util import create_self_signed_cert, verify_tls, ServerConfigException
 import secrets
 import orchestrator
@@ -137,161 +137,161 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
 
     instance = None
     NATIVE_OPTIONS = []  # type: List[Any]
-    MODULE_OPTIONS: List[dict] = [
-        {
-            'name': 'ssh_config_file',
-            'type': 'str',
-            'default': None,
-            'desc': 'customized SSH config file to connect to managed hosts',
-        },
-        {
-            'name': 'device_cache_timeout',
-            'type': 'secs',
-            'default': 30 * 60,
-            'desc': 'seconds to cache device inventory',
-        },
-        {
-            'name': 'daemon_cache_timeout',
-            'type': 'secs',
-            'default': 10 * 60,
-            'desc': 'seconds to cache service (daemon) inventory',
-        },
-        {
-            'name': 'facts_cache_timeout',
-            'type': 'secs',
-            'default': 1 * 60,
-            'desc': 'seconds to cache host facts data',
-        },
-        {
-            'name': 'host_check_interval',
-            'type': 'secs',
-            'default': 10 * 60,
-            'desc': 'how frequently to perform a host check',
-        },
-        {
-            'name': 'mode',
-            'type': 'str',
-            'enum_allowed': ['root', 'cephadm-package'],
-            'default': 'root',
-            'desc': 'mode for remote execution of cephadm',
-        },
-        {
-            'name': 'container_image_base',
-            'default': 'docker.io/ceph/ceph',
-            'desc': 'Container image name, without the tag',
-            'runtime': True,
-        },
-        {
-            'name': 'container_image_prometheus',
-            'default': 'docker.io/prom/prometheus:v2.18.1',
-            'desc': 'Prometheus container image',
-        },
-        {
-            'name': 'container_image_grafana',
-            'default': 'docker.io/ceph/ceph-grafana:6.6.2',
-            'desc': 'Prometheus container image',
-        },
-        {
-            'name': 'container_image_alertmanager',
-            'default': 'docker.io/prom/alertmanager:v0.20.0',
-            'desc': 'Prometheus container image',
-        },
-        {
-            'name': 'container_image_node_exporter',
-            'default': 'docker.io/prom/node-exporter:v0.18.1',
-            'desc': 'Prometheus container image',
-        },
-        {
-            'name': 'warn_on_stray_hosts',
-            'type': 'bool',
-            'default': True,
-            'desc': 'raise a health warning if daemons are detected on a host '
-                    'that is not managed by cephadm',
-        },
-        {
-            'name': 'warn_on_stray_daemons',
-            'type': 'bool',
-            'default': True,
-            'desc': 'raise a health warning if daemons are detected '
-                    'that are not managed by cephadm',
-        },
-        {
-            'name': 'warn_on_failed_host_check',
-            'type': 'bool',
-            'default': True,
-            'desc': 'raise a health warning if the host check fails',
-        },
-        {
-            'name': 'log_to_cluster',
-            'type': 'bool',
-            'default': True,
-            'desc': 'log to the "cephadm" cluster log channel"',
-        },
-        {
-            'name': 'allow_ptrace',
-            'type': 'bool',
-            'default': False,
-            'desc': 'allow SYS_PTRACE capability on ceph containers',
-            'long_desc': 'The SYS_PTRACE capability is needed to attach to a '
-                         'process with gdb or strace.  Enabling this options '
-                         'can allow debugging daemons that encounter problems '
-                         'at runtime.',
-        },
-        {
-            'name': 'container_init',
-            'type': 'bool',
-            'default': False,
-            'desc': 'Run podman/docker with `--init`',
-        },
-        {
-            'name': 'prometheus_alerts_path',
-            'type': 'str',
-            'default': '/etc/prometheus/ceph/ceph_default_alerts.yml',
-            'desc': 'location of alerts to include in prometheus deployments',
-        },
-        {
-            'name': 'migration_current',
-            'type': 'int',
-            'default': None,
-            'desc': 'internal - do not modify',
+    MODULE_OPTIONS = [
+        Option(
+            'ssh_config_file',
+            type='str',
+            default=None,
+            desc='customized SSH config file to connect to managed hosts',
+        ),
+        Option(
+            'device_cache_timeout',
+            type='secs',
+            default=30 * 60,
+            desc='seconds to cache device inventory',
+        ),
+        Option(
+            'daemon_cache_timeout',
+            type='secs',
+            default=10 * 60,
+            desc='seconds to cache service (daemon) inventory',
+        ),
+        Option(
+            'facts_cache_timeout',
+            type='secs',
+            default=1 * 60,
+            desc='seconds to cache host facts data',
+        ),
+        Option(
+            'host_check_interval',
+            type='secs',
+            default=10 * 60,
+            desc='how frequently to perform a host check',
+        ),
+        Option(
+            'mode',
+            type='str',
+            enum_allowed=['root', 'cephadm-package'],
+            default='root',
+            desc='mode for remote execution of cephadm',
+        ),
+        Option(
+            'container_image_base',
+            default='docker.io/ceph/ceph',
+            desc='Container image name, without the tag',
+            runtime=True,
+        ),
+        Option(
+            'container_image_prometheus',
+            default='docker.io/prom/prometheus:v2.18.1',
+            desc='Prometheus container image',
+        ),
+        Option(
+            'container_image_grafana',
+            default='docker.io/ceph/ceph-grafana:6.6.2',
+            desc='Prometheus container image',
+        ),
+        Option(
+            'container_image_alertmanager',
+            default='docker.io/prom/alertmanager:v0.20.0',
+            desc='Prometheus container image',
+        ),
+        Option(
+            'container_image_node_exporter',
+            default='docker.io/prom/node-exporter:v0.18.1',
+            desc='Prometheus container image',
+        ),
+        Option(
+            'warn_on_stray_hosts',
+            type='bool',
+            default=True,
+            desc='raise a health warning if daemons are detected on a host '
+            'that is not managed by cephadm',
+        ),
+        Option(
+            'warn_on_stray_daemons',
+            type='bool',
+            default=True,
+            desc='raise a health warning if daemons are detected '
+            'that are not managed by cephadm',
+        ),
+        Option(
+            'warn_on_failed_host_check',
+            type='bool',
+            default=True,
+            desc='raise a health warning if the host check fails',
+        ),
+        Option(
+            'log_to_cluster',
+            type='bool',
+            default=True,
+            desc='log to the "cephadm" cluster log channel"',
+        ),
+        Option(
+            'allow_ptrace',
+            type='bool',
+            default=False,
+            desc='allow SYS_PTRACE capability on ceph containers',
+            long_desc='The SYS_PTRACE capability is needed to attach to a '
+            'process with gdb or strace.  Enabling this options '
+            'can allow debugging daemons that encounter problems '
+            'at runtime.',
+        ),
+        Option(
+            'container_init',
+            type='bool',
+            default=False,
+            desc='Run podman/docker with `--init`'
+        ),
+        Option(
+            'prometheus_alerts_path',
+            type='str',
+            default='/etc/prometheus/ceph/ceph_default_alerts.yml',
+            desc='location of alerts to include in prometheus deployments',
+        ),
+        Option(
+            'migration_current',
+            type='int',
+            default=None,
+            desc='internal - do not modify',
             # used to track track spec and other data migrations.
-        },
-        {
-            'name': 'config_dashboard',
-            'type': 'bool',
-            'default': True,
-            'desc': 'manage configs like API endpoints in Dashboard.'
-        },
-        {
-            'name': 'manage_etc_ceph_ceph_conf',
-            'type': 'bool',
-            'default': False,
-            'desc': 'Manage and own /etc/ceph/ceph.conf on the hosts.',
-        },
-        {
-            'name': 'registry_url',
-            'type': 'str',
-            'default': None,
-            'desc': 'Custom repository url'
-        },
-        {
-            'name': 'registry_username',
-            'type': 'str',
-            'default': None,
-            'desc': 'Custom repository username'
-        },
-        {
-            'name': 'registry_password',
-            'type': 'str',
-            'default': None,
-            'desc': 'Custom repository password'
-        },
-        {
-            'name': 'use_repo_digest',
-            'type': 'bool',
-            'default': False,
-            'desc': 'Automatically convert image tags to image digest. Make sure all daemons use the same image',
-        }
+        ),
+        Option(
+            'config_dashboard',
+            type='bool',
+            default=True,
+            desc='manage configs like API endpoints in Dashboard.'
+        ),
+        Option(
+            'manage_etc_ceph_ceph_conf',
+            type='bool',
+            default=False,
+            desc='Manage and own /etc/ceph/ceph.conf on the hosts.',
+        ),
+        Option(
+            'registry_url',
+            type='str',
+            default=None,
+            desc='Custom repository url'
+        ),
+        Option(
+            'registry_username',
+            type='str',
+            default=None,
+            desc='Custom repository username'
+        ),
+        Option(
+            'registry_password',
+            type='str',
+            default=None,
+            desc='Custom repository password'
+        ),
+        Option(
+            'use_repo_digest',
+            type='bool',
+            default=False,
+            desc='Automatically convert image tags to image digest. Make sure all daemons use the same image',
+        ),
     ]
 
     def __init__(self, *args: Any, **kwargs: Any):
index cf0614d76ed64ad2f2d06468a0d3f144a86ed96c..548255745e2dc2ef45e2d08dbf338337ae8cbef3 100644 (file)
@@ -1,10 +1,15 @@
 import ceph_module  # noqa
 
-try:
-    from typing import Set, Tuple, Iterator, Any, Dict, Optional, Callable, List
-except ImportError:
-    # just for type checking
-    pass
+from typing import Set, Tuple, Iterator, Any, Dict, Optional, Callable, List, \
+    Union, TYPE_CHECKING, NamedTuple
+if TYPE_CHECKING:
+    import sys
+    if sys.version_info >= (3, 8):
+        from typing import Literal
+    else:
+        from typing_extensions import Literal
+
+
 import logging
 import errno
 import json
@@ -354,27 +359,37 @@ def CLIWriteCommand(prefix, args="", desc=""):
 def _get_localized_key(prefix, key):
     return '{}/{}'.format(prefix, key)
 
+"""
+MODULE_OPTIONS types and Option Class
+"""
+if TYPE_CHECKING:
+    OptionTypeLabel = Literal[
+        'uint', 'int', 'str', 'float', 'bool', 'addr', 'addrvec', 'uuid', 'size', 'secs']
 
-class Option(dict):
-    """
-    Helper class to declare options for MODULE_OPTIONS list.
 
-    Caveat: it uses argument names matching Python keywords (type, min, max),
-    so any further processing should happen in a separate method.
+# common/options.h: value_t
+OptionValue = Optional[Union[bool, int, float, str]]
 
-    TODO: type validation.
+
+class Option(Dict):
+    """
+    Helper class to declare options for MODULE_OPTIONS list.
+    TODO: Replace with typing.TypedDict when in python_version >= 3.8
     """
 
     def __init__(
-            self, name,
-            default=None,
-            type='str',
-            desc=None, longdesc=None,
-            min=None, max=None,
-            enum_allowed=None,
-            see_also=None,
-            tags=None,
-            runtime=False,
+            self,
+            name: str,
+            default: OptionValue=None,
+            type: 'OptionTypeLabel'='str',
+            desc: Optional[str]=None,
+            long_desc: Optional[str]=None,
+            min: OptionValue=None,
+            max: OptionValue=None,
+            enum_allowed: Optional[List[str]]=None,
+            tags: Optional[List[str]]=None,
+            see_also: Optional[List[str]]=None,
+            runtime: bool=False,
     ):
         super(Option, self).__init__(
             (k, v) for k, v in vars().items()
@@ -600,7 +615,7 @@ class MgrStandbyModule(ceph_module.BaseMgrStandbyModule, MgrModuleLoggingMixin):
     from their active peer), and to configuration settings (read only).
     """
 
-    MODULE_OPTIONS = []  # type: List[Dict[str, Any]]
+    MODULE_OPTIONS: List[Option] = []
     MODULE_OPTION_DEFAULTS = {}  # type: Dict[str, Any]
 
     def __init__(self, module_name, capsule):
@@ -663,13 +678,11 @@ class MgrStandbyModule(ceph_module.BaseMgrStandbyModule, MgrModuleLoggingMixin):
     def get_mgr_id(self):
         return self._ceph_get_mgr_id()
 
-    def get_module_option(self, key, default=None):
+    def get_module_option(self, key: str, default: OptionValue=None) -> OptionValue:
         """
         Retrieve the value of a persistent configuration setting
 
-        :param str key:
         :param default: the default value of the config if it is not found
-        :return: str
         """
         r = self._ceph_get_module_option(key)
         if r is None:
@@ -692,7 +705,7 @@ class MgrStandbyModule(ceph_module.BaseMgrStandbyModule, MgrModuleLoggingMixin):
     def get_active_uri(self):
         return self._ceph_get_active_uri()
 
-    def get_localized_module_option(self, key, default=None):
+    def get_localized_module_option(self, key: str, default: OptionValue=None) -> OptionValue:
         r = self._ceph_get_module_option(key, self.get_mgr_id())
         if r is None:
             return self.MODULE_OPTION_DEFAULTS.get(key, default)
@@ -702,7 +715,7 @@ class MgrStandbyModule(ceph_module.BaseMgrStandbyModule, MgrModuleLoggingMixin):
 
 class MgrModule(ceph_module.BaseMgrModule, MgrModuleLoggingMixin):
     COMMANDS = []  # type: List[Any]
-    MODULE_OPTIONS = []  # type: List[dict]
+    MODULE_OPTIONS: List[Option] = []
     MODULE_OPTION_DEFAULTS = {}  # type: Dict[str, Any]
 
     # Priority definitions for perf counters
@@ -1248,28 +1261,23 @@ class MgrModule(ceph_module.BaseMgrModule, MgrModuleLoggingMixin):
         else:
             return r
 
-    def get_module_option(self, key, default=None):
+    def get_module_option(self, key: str, default: OptionValue=None) -> OptionValue:
         """
         Retrieve the value of a persistent configuration setting
-
-        :param str key:
-        :param str default:
-        :return: str
         """
         self._validate_module_option(key)
         return self._get_module_option(key, default)
 
-    def get_module_option_ex(self, module, key, default=None):
+    def get_module_option_ex(self, module: str, key: str, default: OptionValue=None) -> OptionValue:
         """
         Retrieve the value of a persistent configuration setting
         for the specified module.
 
-        :param str module: The name of the module, e.g. 'dashboard'
+        :param module: The name of the module, e.g. 'dashboard'
             or 'telemetry'.
-        :param str key: The configuration key, e.g. 'server_addr'.
-        :param str,None default: The default value to use when the
+        :param key: The configuration key, e.g. 'server_addr'.
+        :param default: The default value to use when the
             returned value is ``None``. Defaults to ``None``.
-        :return: str,int,bool,float,None
         """
         if module == self.module_name:
             self._validate_module_option(key)
@@ -1289,12 +1297,9 @@ class MgrModule(ceph_module.BaseMgrModule, MgrModuleLoggingMixin):
     def _set_localized(self, key, val, setter):
         return setter(_get_localized_key(self.get_mgr_id(), key), val)
 
-    def get_localized_module_option(self, key, default=None):
+    def get_localized_module_option(self, key: str, default: OptionValue=None) -> OptionValue:
         """
         Retrieve localized configuration for this ceph-mgr instance
-        :param str key:
-        :param str default:
-        :return: str
         """
         self._validate_module_option(key)
         return self._get_module_option(key, default, self.get_mgr_id())
index 2c68519897c99d1194ab171d1a14982b2d3a1261..8a89a13a69fec3d87bd9cd0f57e897c420612006 100644 (file)
@@ -13,7 +13,7 @@ from ceph.deployment.drive_group import DriveGroupSpec, DeviceSelection
 from ceph.deployment.service_spec import PlacementSpec, ServiceSpec
 
 from mgr_util import format_bytes, to_pretty_timedelta, format_dimless
-from mgr_module import MgrModule, HandleCommandResult
+from mgr_module import MgrModule, HandleCommandResult, Option
 
 from ._interface import OrchestratorClientMixin, DeviceLightLoc, _cli_read_command, \
     raise_if_exception, _cli_write_command, TrivialReadCompletion, OrchestratorError, \
@@ -135,15 +135,14 @@ def preview_table_services(data):
 class OrchestratorCli(OrchestratorClientMixin, MgrModule,
                       metaclass=CLICommandMeta):
     MODULE_OPTIONS = [
-        {
-            'name': 'orchestrator',
-            'type': 'str',
-            'default': None,
-            'desc': 'Orchestrator backend',
-            'enum_allowed': ['cephadm', 'rook',
-                             'test_orchestrator'],
-            'runtime': True,
-        },
+        Option(
+            'orchestrator',
+            type='str',
+            default=None,
+            desc='Orchestrator backend',
+            enum_allowed=['cephadm', 'rook', 'test_orchestrator'],
+            runtime=True,
+        )
     ]
     NATIVE_OPTIONS = []  # type: List[dict]
 
@@ -633,38 +632,38 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule,
 usage:
   ceph orch apply osd -i <json_file/yaml_file> [--dry-run]
   ceph orch apply osd --all-available-devices [--dry-run] [--unmanaged]
-  
+
 Restrictions:
-  
+
   Mutexes:
   * -i, --all-available-devices
   * -i, --unmanaged (this would overwrite the osdspec loaded from a file)
-  
+
   Parameters:
-  
+
   * --unmanaged
      Only works with --all-available-devices.
-  
+
 Description:
-  
+
   * -i
     An inbuf object like a file or a json/yaml blob containing a valid OSDSpec
-    
+
   * --all-available-devices
     The most simple OSDSpec there is. Takes all as 'available' marked devices
     and creates standalone OSDs on them.
-    
+
   * --unmanaged
     Set a the unmanaged flag for all--available-devices (default is False)
-    
+
 Examples:
 
    # ceph orch apply osd -i <file.yml|json>
-   
+
    Applies one or more OSDSpecs found in <file>
-   
+
    # ceph orch osd apply --all-available-devices --unmanaged=true
-   
+
    Creates and applies simple OSDSpec with the unmanaged flag set to <true>
 """
 
index a5748ead805f9907ac236729d81db95fe3f84aaa..ff54bac987347e8d7e7956b27200594daf7c22bc 100644 (file)
@@ -4,7 +4,7 @@ try:
 except ImportError:
     TYPE_CHECKING = False
 
-from mgr_module import MgrModule, OSDMap
+from mgr_module import MgrModule, OSDMap, Option
 from mgr_util import to_pretty_timedelta
 from datetime import timedelta
 import os
@@ -54,7 +54,7 @@ class Event(object):
     def refs(self):
         # type: () -> List[str]
         return self._refs
+
     @property
     def add_to_ceph_s(self):
         # type: () -> bool
@@ -427,27 +427,26 @@ class Module(MgrModule):
     ]
 
     MODULE_OPTIONS = [
-        {
-            'name': 'max_completed_events',
-            'default': 50,
-            'type': 'int',
-            'desc': 'number of past completed events to remember',
-            'runtime': True,
-        },
-        {
-            'name': 'persist_interval',
-            'default': 5,
-            'type': 'secs',
-            'desc': 'how frequently to persist completed events',
-            'runtime': True,
-        },
-        {
-            'name': 'enabled',
-            'default': True,
-            'type': 'bool',
-            
-        }
-    ]  # type: List[Dict[str, Any]]
+        Option(
+            'max_completed_events',
+            default=50,
+            type='int',
+            desc='number of past completed events to remember',
+            runtime=True
+        ),
+        Option(
+            'persist_interval',
+            default=5,
+            type='secs',
+            desc='how frequently to persist completed events',
+            runtime=True
+        ),
+        Option(
+            'enabled',
+            default=True,
+            type='bool',
+        )
+    ]
 
     def __init__(self, *args, **kwargs):
         super(Module, self).__init__(*args, **kwargs)
@@ -632,17 +631,17 @@ class Module(MgrModule):
             ))
             self._osdmap_changed(old_osdmap, self._latest_osdmap)
         elif notify_type == "pg_summary":
-            # if there are no events we will skip this here to avoid 
+            # if there are no events we will skip this here to avoid
             # expensive get calls
             if len(self._events) == 0:
                 return
+
             global_event = False
             data = self.get("pg_stats")
             ready = self.get("pg_ready")
             for ev_id in list(self._events):
                 ev = self._events[ev_id]
-                # Check for types of events 
+                # Check for types of events
                 # we have to update
                 if isinstance(ev, PgRecoveryEvent):
                     ev.pg_update(data, ready, self.log)
@@ -653,7 +652,7 @@ class Module(MgrModule):
                     self.maybe_complete(ev)
 
             if not global_event:
-                # If there is no global event 
+                # If there is no global event
                 # we create one
                 self._pg_state_changed(data)
 
@@ -848,7 +847,7 @@ class Module(MgrModule):
         self.clear_all_progress_events()
 
     def _handle_clear(self):
-        self.clear()  
+        self.clear()
         return 0, "", ""
 
     def handle_command(self, _, cmd):
index 8e9b9317d9933a10505722c7bdadb1eec5c90a47..e83bdd26efffa4dcad480a53fdf3c8b3b0c3245c 100644 (file)
@@ -9,12 +9,12 @@ import re
 import socket
 import threading
 import time
-from mgr_module import MgrModule, MgrStandbyModule, PG_STATES
+from mgr_module import MgrModule, MgrStandbyModule, PG_STATES, Option
 from mgr_util import get_default_addr, profile_method
 from rbd import RBD
 from collections import namedtuple
 try:
-    from typing import DefaultDict, Optional, Dict, Any, Set
+    from typing import DefaultDict, Optional, Dict, Any, Set, cast
 except ImportError:
     pass
 
@@ -247,12 +247,31 @@ class Module(MgrModule):
     ]
 
     MODULE_OPTIONS = [
-        {'name': 'server_addr'},
-        {'name': 'server_port'},
-        {'name': 'scrape_interval'},
-        {'name': 'stale_cache_strategy'},
-        {'name': 'rbd_stats_pools'},
-        {'name': 'rbd_stats_pools_refresh_interval', 'type': 'int', 'default': 300},
+        Option(
+            'server_addr'
+        ),
+        Option(
+            'server_port',
+            type='int'
+        ),
+        Option(
+            'scrape_interval',
+            type='float',
+            default=15.0
+        ),
+        Option(
+            'stale_cache_strategy',
+            default='log'
+        ),
+        Option(
+            'rbd_stats_pools',
+            default=''
+        ),
+        Option(
+            name='rbd_stats_pools_refresh_interval',
+            type='int',
+            default=300
+        )
     ]
 
     STALE_CACHE_FAIL = 'fail'
@@ -264,8 +283,8 @@ class Module(MgrModule):
         self.shutdown_event = threading.Event()
         self.collect_lock = threading.Lock()
         self.collect_time = 0.0
-        self.scrape_interval = 15.0
-        self.stale_cache_strategy = self.STALE_CACHE_FAIL
+        self.scrape_interval: float = 15.0
+        self.stale_cache_strategy: str = self.STALE_CACHE_FAIL
         self.collect_cache = None
         self.rbd_stats = {
             'pools': {},
@@ -825,7 +844,7 @@ class Module(MgrModule):
         # list of pool[/namespace] entries. If no namespace is specifed the
         # stats are collected for every namespace in the pool. The wildcard
         # '*' can be used to indicate all pools or namespaces
-        pools_string = self.get_localized_module_option('rbd_stats_pools', '')
+        pools_string = cast(str, self.get_localized_module_option('rbd_stats_pools'))
         pool_keys = []
         for x in re.split('[\s,]+', pools_string):
             if not x:
@@ -1249,9 +1268,9 @@ class Module(MgrModule):
                     raise cherrypy.HTTPError(503, msg)
 
         # Make the cache timeout for collecting configurable
-        self.scrape_interval = float(self.get_localized_module_option('scrape_interval', 15.0))
+        self.scrape_interval = cast(float, self.get_localized_module_option('scrape_interval'))
 
-        self.stale_cache_strategy = self.get_localized_module_option('stale_cache_strategy', 'log')
+        self.stale_cache_strategy = cast(str, self.get_localized_module_option('stale_cache_strategy'))
         if self.stale_cache_strategy not in [self.STALE_CACHE_FAIL,
                                              self.STALE_CACHE_RETURN]:
             self.stale_cache_strategy = self.STALE_CACHE_FAIL
@@ -1276,7 +1295,7 @@ class Module(MgrModule):
 
         cherrypy.config.update({
             'server.socket_host': server_addr,
-            'server.socket_port': int(server_port),
+            'server.socket_port': server_port,
             'engine.autoreload.on': False
         })
         cherrypy.tree.mount(Root(), "/")
@@ -1313,7 +1332,7 @@ class StandbyModule(MgrStandbyModule):
                       (server_addr, server_port))
         cherrypy.config.update({
             'server.socket_host': server_addr,
-            'server.socket_port': int(server_port),
+            'server.socket_port': server_port,
             'engine.autoreload.on': False
         })
 
index 362319a8f694a60bd8831f029512e0dd1df18b6a..bfed1471ec5a0dbb07a82cabf8d820de7247e58e 100644 (file)
@@ -30,7 +30,7 @@ except ImportError:
     client = None
     config = None
 
-from mgr_module import MgrModule
+from mgr_module import MgrModule, Option
 import orchestrator
 
 from .rook_cluster import RookCluster
@@ -98,9 +98,9 @@ class RookOrchestrator(MgrModule, orchestrator.Orchestrator):
     Right now, we are calling the k8s API synchronously.
     """
 
-    MODULE_OPTIONS = [
+    MODULE_OPTIONS: List[Option] = [
         # TODO: configure k8s API addr instead of assuming local
-    ]  # type: List[Dict[str, Any]]
+    ]
 
     def process(self, completions):
         # type: (List[RookCompletion]) -> None
index 62768fbe6293d6241533ac5f2c49cdebc33081eb..460d979b83e6d1b5438326340e7b66438ba6b111 100644 (file)
@@ -7,20 +7,20 @@ import errno
 import json
 import sqlite3
 from .fs.schedule_client import SnapSchedClient
-from mgr_module import MgrModule, CLIReadCommand, CLIWriteCommand
+from mgr_module import MgrModule, CLIReadCommand, CLIWriteCommand, Option
 from mgr_util import CephfsConnectionException
 from threading import Event
 
 
 class Module(MgrModule):
     MODULE_OPTIONS = [
-        {
-            'name':    'allow_m_granularity',
-            'type':    'bool',
-            'default': False,
-            'desc':    'allow minute scheduled snapshots',
-            'runtime': True,
-        },
+        Option(
+            'allow_m_granularity',
+            type='bool',
+            default=False,
+            desc='allow minute scheduled snapshots',
+            runtime=True,
+        ),
     ]
 
     def __init__(self, *args, **kwargs):
index ecacd180d5357ddefcc6ba862eef3fb4838cbb96..a4bc44630d637168eb8a6f6d94f926520bde7a43 100644 (file)
@@ -5,7 +5,7 @@ performance stats for ceph filesystem (for now...)
 import json
 from typing import List, Dict
 
-from mgr_module import MgrModule
+from mgr_module import MgrModule, Option
 
 from .fs.perf_stats import FSPerfStats
 
@@ -20,7 +20,7 @@ class Module(MgrModule):
             "perm": "r"
         },
     ]
-    MODULE_OPTIONS = [] # type: List[Dict]
+    MODULE_OPTIONS: List[Option] = []
 
     def __init__(self, *args, **kwargs):
         super(Module, self).__init__(*args, **kwargs)
index 805bd5455dcf489f1c5aace57b7379aa19482c1f..62d8ba4eb3191ae499281a7f0904e1777358b208 100644 (file)
@@ -4,7 +4,7 @@ import logging
 import traceback
 import threading
 
-from mgr_module import MgrModule
+from mgr_module import MgrModule, Option
 import orchestrator
 
 from .fs.volume import VolumeClient
@@ -396,12 +396,12 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
     ]
 
     MODULE_OPTIONS = [
-        {
-            'name': 'max_concurrent_clones',
-            'type': 'int',
-            'default': 4,
-            'desc': 'Number of asynchronous cloner threads',
-        }
+        Option(
+            'max_concurrent_clones',
+            type='int',
+            default=4,
+            desc='Number of asynchronous cloner threads',
+        )
     ]
 
     def __init__(self, *args, **kwargs):
index 987dd0d2892d1b9bf3a9940e3f64941917da52f8..432fcd5e376d3f742e9daf711de5f56120cf741b 100644 (file)
@@ -4,3 +4,4 @@ mypy==0.790; python_version >= '3'
 pytest-mypy; python_version >= '3'
 pytest >= 2.1.3; python_version >= '3'
 pyyaml
+typing-extensions; python_version < '3.8'