]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/cephadm: add config section to ServiceSpec
authorSage Weil <sage@newdream.net>
Tue, 23 Feb 2021 18:47:59 +0000 (13:47 -0500)
committerSage Weil <sage@newdream.net>
Fri, 26 Feb 2021 13:28:28 +0000 (08:28 -0500)
Signed-off-by: Sage Weil <sage@newdream.net>
src/pybind/mgr/cephadm/serve.py
src/python-common/ceph/deployment/service_spec.py

index 927bcaee191149797c7caeab3266e33edd9c8776..ee21e1cd9b7be3a30820de5cf0389d20cd47781d 100644 (file)
@@ -25,6 +25,9 @@ from cephadm.services.cephadmservice import CephadmDaemonDeploySpec
 from cephadm.schedule import HostAssignment
 from cephadm.utils import forall_hosts, cephadmNoImage, is_repo_digest, \
     CephadmNoImage, CEPH_UPGRADE_ORDER, ContainerInspectInfo
+from mgr_module import MonCommandFailed
+
+from . import utils
 
 if TYPE_CHECKING:
     from cephadm.module import CephadmOrchestrator
@@ -448,6 +451,34 @@ class CephadmServe:
 
         return r
 
+    def _apply_service_config(self, spec: ServiceSpec) -> None:
+        if spec.config:
+            section = utils.name_to_config_section(spec.service_name())
+            for k, v in spec.config.items():
+                try:
+                    current = self.mgr.get_foreign_ceph_option(section, k)
+                except KeyError:
+                    self.log.warning(
+                        f'Ignoring invalid {spec.service_name()} config option {k}'
+                    )
+                    self.mgr.events.for_service(
+                        spec, OrchestratorEvent.ERROR, f'Invalid config option {k}'
+                    )
+                    continue
+                if current != v:
+                    self.log.debug(f'setting [{section}] {k} = {v}')
+                    try:
+                        self.mgr.check_mon_command({
+                            'prefix': 'config set',
+                            'name': k,
+                            'value': str(v),
+                            'who': section,
+                        })
+                    except MonCommandFailed as e:
+                        self.log.warning(
+                            f'Failed to set {spec.service_name()} option {k}: {e}'
+                        )
+
     def _apply_service(self, spec: ServiceSpec) -> bool:
         """
         Schedule a service.  Deploy new daemons or remove old ones, depending
@@ -465,6 +496,8 @@ class CephadmServe:
             return False
         self.log.debug('Applying service %s spec' % service_name)
 
+        self._apply_service_config(spec)
+
         if service_type == 'osd':
             self.mgr.osd_service.create_from_spec(cast(DriveGroupSpec, spec))
             # TODO: return True would result in a busy loop
index 68b456393e6ab96ea2ee880389c391a88752b778..dde78ac4101a72f19c64ec7c057fbb18bf7fb422 100644 (file)
@@ -429,6 +429,7 @@ class ServiceSpec(object):
                  service_id: Optional[str] = None,
                  placement: Optional[PlacementSpec] = None,
                  count: Optional[int] = None,
+                 config: Optional[Dict[str, str]] = None,
                  unmanaged: bool = False,
                  preview_only: bool = False,
                  ):
@@ -442,6 +443,10 @@ class ServiceSpec(object):
         self.unmanaged = unmanaged
         self.preview_only = preview_only
 
+        self.config: Optional[Dict[str, str]] = None
+        if config:
+            self.config = {k.replace(' ', '_'): v for k, v in config.items()}
+
     @classmethod
     @handle_type_error
     def from_json(cls: Type[ServiceSpecT], json_spec: Dict) -> ServiceSpecT:
@@ -465,6 +470,8 @@ class ServiceSpec(object):
 
             service_type: nfs
             service_id: foo
+            config:
+              some_option: the_value
             spec:
               pool: mypool
               namespace: myns
@@ -584,12 +591,14 @@ class NFSServiceSpec(ServiceSpec):
                  namespace: Optional[str] = None,
                  placement: Optional[PlacementSpec] = None,
                  unmanaged: bool = False,
-                 preview_only: bool = False
+                 preview_only: bool = False,
+                 config: Optional[Dict[str, str]] = None,
                  ):
         assert service_type == 'nfs'
         super(NFSServiceSpec, self).__init__(
             'nfs', service_id=service_id,
-            placement=placement, unmanaged=unmanaged, preview_only=preview_only)
+            placement=placement, unmanaged=unmanaged, preview_only=preview_only,
+            config=config)
 
         #: RADOS pool where NFS client recovery data is stored.
         self.pool = pool
@@ -640,6 +649,7 @@ class RGWSpec(ServiceSpec):
                  unmanaged: bool = False,
                  ssl: bool = False,
                  preview_only: bool = False,
+                 config: Optional[Dict[str, str]] = None,
                  ):
         assert service_type == 'rgw', service_type
         if service_id:
@@ -657,7 +667,7 @@ class RGWSpec(ServiceSpec):
         super(RGWSpec, self).__init__(
             'rgw', service_id=service_id,
             placement=placement, unmanaged=unmanaged,
-            preview_only=preview_only)
+            preview_only=preview_only, config=config)
 
         self.rgw_realm = rgw_realm
         self.rgw_zone = rgw_zone
@@ -713,12 +723,14 @@ class IscsiServiceSpec(ServiceSpec):
                  ssl_key: Optional[str] = None,
                  placement: Optional[PlacementSpec] = None,
                  unmanaged: bool = False,
-                 preview_only: bool = False
+                 preview_only: bool = False,
+                 config: Optional[Dict[str, str]] = None,
                  ):
         assert service_type == 'iscsi'
         super(IscsiServiceSpec, self).__init__('iscsi', service_id=service_id,
                                                placement=placement, unmanaged=unmanaged,
-                                               preview_only=preview_only)
+                                               preview_only=preview_only,
+                                               config=config)
 
         #: RADOS pool where ceph-iscsi config data is stored.
         self.pool = pool
@@ -758,12 +770,13 @@ class AlertManagerSpec(ServiceSpec):
                  unmanaged: bool = False,
                  preview_only: bool = False,
                  user_data: Optional[Dict[str, Any]] = None,
+                 config: Optional[Dict[str, str]] = None,
                  ):
         assert service_type == 'alertmanager'
         super(AlertManagerSpec, self).__init__(
             'alertmanager', service_id=service_id,
             placement=placement, unmanaged=unmanaged,
-            preview_only=preview_only)
+            preview_only=preview_only, config=config)
 
         # Custom configuration.
         #
@@ -789,6 +802,7 @@ class HA_RGWSpec(ServiceSpec):
     def __init__(self,
                  service_type: str = 'ha-rgw',
                  service_id: Optional[str] = None,
+                 config: Optional[Dict[str, str]] = None,
                  placement: Optional[PlacementSpec] = None,
                  virtual_ip_interface: Optional[str] = None,
                  virtual_ip_address: Optional[str] = None,
@@ -810,7 +824,8 @@ class HA_RGWSpec(ServiceSpec):
                  definitive_host_list: Optional[List[HostPlacementSpec]] = None
                  ):
         assert service_type == 'ha-rgw'
-        super(HA_RGWSpec, self).__init__('ha-rgw', service_id=service_id, placement=placement)
+        super(HA_RGWSpec, self).__init__('ha-rgw', service_id=service_id,
+                                         placement=placement, config=config)
 
         self.virtual_ip_interface = virtual_ip_interface
         self.virtual_ip_address = virtual_ip_address
@@ -878,6 +893,7 @@ class CustomContainerSpec(ServiceSpec):
     def __init__(self,
                  service_type: str = 'container',
                  service_id: Optional[str] = None,
+                 config: Optional[Dict[str, str]] = None,
                  placement: Optional[PlacementSpec] = None,
                  unmanaged: bool = False,
                  preview_only: bool = False,
@@ -901,7 +917,7 @@ class CustomContainerSpec(ServiceSpec):
         super(CustomContainerSpec, self).__init__(
             service_type, service_id,
             placement=placement, unmanaged=unmanaged,
-            preview_only=preview_only)
+            preview_only=preview_only, config=config)
 
         self.image = image
         self.entrypoint = entrypoint