]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/cephadm: For updating NFS backends in HAProxy, send a SIGHUP signal to reload... 66051/head
authorShweta Bhosale <Shweta.Bhosale1@ibm.com>
Fri, 24 Oct 2025 11:00:16 +0000 (16:30 +0530)
committerShweta Bhosale <Shweta.Bhosale1@ibm.com>
Thu, 11 Jun 2026 08:48:51 +0000 (14:18 +0530)
Fixes: https://tracker.ceph.com/issues/73633
Signed-off-by: Shweta Bhosale <Shweta.Bhosale1@ibm.com>
src/cephadm/cephadm.py
src/pybind/mgr/cephadm/serve.py
src/pybind/mgr/cephadm/services/cephadmservice.py
src/pybind/mgr/cephadm/services/ingress.py
src/pybind/mgr/cephadm/services/jaeger.py
src/pybind/mgr/cephadm/services/monitoring.py
src/pybind/mgr/cephadm/services/nfs.py
src/pybind/mgr/cephadm/utils.py

index 201b0319ba932ac883d4470f787907a9ca600c12..f5b96ff712bd9464c4281317dd6c359990f95ed7 100755 (executable)
@@ -4909,8 +4909,8 @@ def _add_deploy_parser_args(
     )
     parser_deploy.add_argument(
         '--send-signal-to-daemon',
-        action='store_true',
-        default=False,
+        type=str,
+        default=None,
         help='Send signal to daemon'
     )
 
index 4f5d37250e20080d3b7b96ef235034591605749b..2c8ef279db220879b59d382eaf77b45c5aff4e60 100644 (file)
@@ -1203,27 +1203,29 @@ class CephadmServe:
             else:
                 # method uses new action enum type
                 _scheduled_action = utils.Action.create(scheduled_action)
-                _action = svc_obj.choose_next_action(
+                _step = svc_obj.choose_next_action(
                     _scheduled_action,
                     dd.daemon_type,
                     spec,
                     curr_deps=deps,
                     last_deps=last_deps,
                 )
-                if _action is not _scheduled_action:
+                if _step.action is not _scheduled_action:
                     self.log.info(
                         (
                             'Daemon %s chose new action %s (was %s)'
                             ' (deps: %r, last_deps: %r)'
                         ),
                         dd.name(),
-                        _action,
+                        _step.action,
                         _scheduled_action,
                         deps,
                         last_deps,
                     )
                     # convert back to legacy str type
-                    action = str(_action)
+                    action = str(_step.action)
+                skip_restart_for_reconfig = _step.skip_restart_for_reconfig
+                send_signal_to_daemon = _step.send_signal_to_daemon
             action = _ceph_service_next_action(
                 action, dd.daemon_type, dd.name(), self.mgr, last_config
             )
@@ -1233,9 +1235,13 @@ class CephadmServe:
                     action = 'redeploy'
                 try:
                     daemon_spec = CephadmDaemonDeploySpec.from_daemon_description(dd)
-                    self.mgr._daemon_action(daemon_spec, action=action,
-                                            skip_restart_for_reconfig=skip_restart_for_reconfig,
-                                            send_signal_to_daemon=send_signal_to_daemon)
+                    reconfig_extras: dict[str, Any] = {}
+                    if skip_restart_for_reconfig:
+                        reconfig_extras['skip_restart_for_reconfig'] = True
+                    if send_signal_to_daemon:
+                        reconfig_extras['send_signal_to_daemon'] = send_signal_to_daemon
+                    self.mgr._daemon_action(daemon_spec, action=action, **reconfig_extras)
+
                     if self.mgr.cache.rm_scheduled_daemon_action(dd.hostname, dd.name()):
                         self.mgr.cache.save_host(dd.hostname)
                 except OrchestratorError as e:
index c95d845aa8a63aba8d115c013a10a3da175746fb..636eb0ddcc6338c958b054e4c4c44830f121627f 100644 (file)
@@ -956,13 +956,13 @@ class CephadmService(metaclass=ABCMeta):
         spec: Optional[ServiceSpec],
         curr_deps: List[str],
         last_deps: List[str],
-    ) -> utils.Action:
+    ) -> utils.NextDaemonStep:
         """Given the scheduled_action, service spec, daemon_type, and
         current and previous dependency lists return the next action that
         this service would prefer cephadm take.
         """
         if curr_deps == last_deps:
-            return scheduled_action
+            return utils.NextDaemonStep(scheduled_action)
         sym_diff = set(curr_deps).symmetric_difference(last_deps)
         logger.info(
             'Reconfigure wanted %s: deps %r -> %r (diff %r)',
@@ -971,7 +971,7 @@ class CephadmService(metaclass=ABCMeta):
             curr_deps,
             sym_diff,
         )
-        return utils.Action.RECONFIG
+        return utils.NextDaemonStep(utils.Action.RECONFIG)
 
 
 class CephService(CephadmService):
@@ -1970,7 +1970,7 @@ class CephExporterService(CephService):
         spec: Optional[ServiceSpec],
         curr_deps: List[str],
         last_deps: List[str],
-    ) -> utils.Action:
+    ) -> utils.NextDaemonStep:
         """Given the scheduled_action, service spec, daemon_type, and
         current and previous dependency lists return the next action that
         this service would prefer cephadm take.
@@ -2084,7 +2084,7 @@ def next_action_for_mgmt_stack_service(
     spec: Optional[ServiceSpec],
     curr_deps: List[str],
     last_deps: List[str],
-) -> utils.Action:
+) -> utils.NextDaemonStep:
     """This function exists to help refactor existing code to use
     choose_next_action instead of if-blocks inside serve.py.
     It avoids the need to muck around with common base classes at the
@@ -2092,7 +2092,7 @@ def next_action_for_mgmt_stack_service(
     Call this from choose_next_action.
     """
     if curr_deps == last_deps:
-        return scheduled_action
+        return utils.NextDaemonStep(scheduled_action)
     sym_diff = set(curr_deps).symmetric_difference(last_deps)
     logger.info(
         'Reconfigure wanted %s: deps %r -> %r (diff %r)',
@@ -2123,4 +2123,4 @@ def next_action_for_mgmt_stack_service(
     # If so we ought to be able to vastly simplify this...
     if any(svc in e for e in sym_diff for svc in REDEPLOY_TRIGGERS):
         action = utils.Action.REDEPLOY
-    return action
+    return utils.NextDaemonStep(action)
index 05d8525b9fd84de153f06367fe270c78336695b0..d546d73bae9da5a0b9ebf7d78c1ac850e49db1d4 100644 (file)
@@ -555,14 +555,15 @@ class IngressService(CephService):
         spec: Optional[ServiceSpec],
         curr_deps: List[str],
         last_deps: List[str],
-    ) -> utils.Action:
+    ) -> utils.NextDaemonStep:
         """Given the scheduled_action, service spec, daemon_type, and
         current and previous dependency lists return the next action that
         this service would prefer cephadm take.
         """
-        action = super().choose_next_action(
+        step = super().choose_next_action(
             scheduled_action, daemon_type, spec, curr_deps, last_deps
         )
+        action = step.action
         if (
             action is not utils.Action.REDEPLOY
             and daemon_type == 'haproxy'
@@ -570,13 +571,26 @@ class IngressService(CephService):
             and hasattr(spec, 'backend_service')
         ):
             backend_spec = self.mgr.spec_store[spec.backend_service].spec
-            if (
-                backend_spec.service_type == 'nfs'
-                and self.has_placement_changed(last_deps, spec)
-            ):
-                logger.debug(
-                    'Redeploy wanted %s: placement has changed',
-                    spec.service_name(),
-                )
-                action = utils.Action.REDEPLOY
-        return action
+            if backend_spec.service_type == 'nfs':
+                if self.has_placement_changed(last_deps, spec):
+                    logger.debug(
+                        'Redeploy wanted %s: placement has changed',
+                        spec.service_name(),
+                    )
+                    return utils.NextDaemonStep(utils.Action.REDEPLOY)
+                sym_diff = set(curr_deps).symmetric_difference(last_deps)
+                if sym_diff and all(
+                    s.startswith(f'nfs.{backend_spec.service_id}')
+                    for s in sym_diff
+                ):
+                    logger.debug(
+                        'Reconfigure HAProxy with SIGHUP due to change in NFS backend '
+                        '(%s)',
+                        spec.service_name(),
+                    )
+                    return utils.NextDaemonStep(
+                        utils.Action.RECONFIG,
+                        skip_restart_for_reconfig=True,
+                        send_signal_to_daemon='SIGHUP',
+                    )
+        return step
index 1d60680cc0f80ae99eb8fd734ea81982779dc613..8d69c53cec8f67ae947d7d80fb346cd9d82eb481 100644 (file)
@@ -1,3 +1,4 @@
+from dataclasses import replace
 from typing import List, cast, Optional, TYPE_CHECKING
 from cephadm.services.cephadmservice import CephadmService, CephadmDaemonDeploySpec
 from ceph.deployment.service_spec import TracingSpec, ServiceSpec
@@ -57,20 +58,20 @@ class JaegerAgentService(CephadmService):
         spec: Optional[ServiceSpec],
         curr_deps: List[str],
         last_deps: List[str],
-    ) -> utils.Action:
+    ) -> utils.NextDaemonStep:
         """Given the scheduled_action, service spec, daemon_type, and
         current and previous dependency lists return the next action that
         this service would prefer cephadm take.
         """
-        action = super().choose_next_action(
+        step = super().choose_next_action(
             scheduled_action, daemon_type, spec, curr_deps, last_deps
         )
         # changes to jaeger-agent deps affect the way the unit.run for
         # the daemon is written, which we rewrite on redeploy, but not
         # on reconfig.
-        if action is utils.Action.RECONFIG:
-            action = utils.Action.REDEPLOY
-        return action
+        if step.action is utils.Action.RECONFIG:
+            return replace(step, action=utils.Action.REDEPLOY)
+        return step
 
 
 @register_cephadm_service
index 86f0aa0a8e88ef05ed84c18e98d65db7c6b7be60..71a19a7583d8d835fa3460a45129719ea39905f7 100644 (file)
@@ -485,7 +485,7 @@ class AlertmanagerService(CephadmService):
         spec: Optional[ServiceSpec],
         curr_deps: List[str],
         last_deps: List[str],
-    ) -> utils.Action:
+    ) -> utils.NextDaemonStep:
         """Given the scheduled_action, service spec, daemon_type, and
         current and previous dependency lists return the next action that
         this service would prefer cephadm take.
@@ -796,7 +796,7 @@ class PrometheusService(CephadmService):
         spec: Optional[ServiceSpec],
         curr_deps: List[str],
         last_deps: List[str],
-    ) -> utils.Action:
+    ) -> utils.NextDaemonStep:
         """Given the scheduled_action, service spec, daemon_type, and
         current and previous dependency lists return the next action that
         this service would prefer cephadm take.
@@ -863,7 +863,7 @@ class NodeExporterService(CephadmService):
         spec: Optional[ServiceSpec],
         curr_deps: List[str],
         last_deps: List[str],
-    ) -> utils.Action:
+    ) -> utils.NextDaemonStep:
         """Given the scheduled_action, service spec, daemon_type, and
         current and previous dependency lists return the next action that
         this service would prefer cephadm take.
index 28d5ec7bed9c2d476fdd2e9250213d69a0d5ec9a..45d7aad1b9c3b7aea7a266f36496fd0be9d26961 100644 (file)
@@ -578,13 +578,13 @@ class NFSService(CephService):
         spec: Optional[ServiceSpec],
         curr_deps: List[str],
         last_deps: List[str],
-    ) -> utils.Action:
+    ) -> utils.NextDaemonStep:
         """Given the scheduled_action, service spec, daemon_type, and
         current and previous dependency lists return the next action that
         this service would prefer cephadm take.
         """
         if curr_deps == last_deps:
-            return scheduled_action
+            return utils.NextDaemonStep(scheduled_action)
         sym_diff = set(curr_deps).symmetric_difference(last_deps)
         logger.info(
             'Reconfigure wanted %s: deps %r -> %r (diff %r)',
@@ -598,4 +598,4 @@ class NFSService(CephService):
         only_kmip_updated = all(s.startswith('kmip') for s in sym_diff)
         if not only_kmip_updated:
             action = utils.Action.REDEPLOY
-        return action
+        return utils.NextDaemonStep(action)
index 8221b950af4155fb79805ceff8bb96a15713c4c9..92725badc55af920aedc031755a10f5c8751c01c 100644 (file)
@@ -1,6 +1,7 @@
 import logging
 import json
 import socket
+from dataclasses import dataclass
 from enum import Enum
 from functools import wraps
 from typing import (
@@ -92,6 +93,16 @@ class Action(str, Enum):
         return self.value
 
 
+@dataclass(frozen=True)
+class NextDaemonStep:
+    """Result of CephadmService.choose_next_action: high-level action plus
+    optional reconfig hints (e.g. HAProxy reload via signal instead of restart).
+    """
+    action: Action
+    skip_restart_for_reconfig: bool = False
+    send_signal_to_daemon: Optional[str] = None
+
+
 def name_to_config_section(name: str) -> ConfEntity:
     """
     Map from daemon names to ceph entity names (as seen in config)