From: Shweta Bhosale Date: Fri, 24 Oct 2025 11:00:16 +0000 (+0530) Subject: mgr/cephadm: For updating NFS backends in HAProxy, send a SIGHUP signal to reload... X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5cfab473be7f572ade239f3f009ed9ffe9fb0f4c;p=ceph.git mgr/cephadm: For updating NFS backends in HAProxy, send a SIGHUP signal to reload the configuration instead of restart Fixes: https://tracker.ceph.com/issues/73633 Signed-off-by: Shweta Bhosale --- diff --git a/src/cephadm/cephadm.py b/src/cephadm/cephadm.py index 201b0319ba9..f5b96ff712b 100755 --- a/src/cephadm/cephadm.py +++ b/src/cephadm/cephadm.py @@ -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' ) diff --git a/src/pybind/mgr/cephadm/serve.py b/src/pybind/mgr/cephadm/serve.py index 4f5d37250e2..2c8ef279db2 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -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: diff --git a/src/pybind/mgr/cephadm/services/cephadmservice.py b/src/pybind/mgr/cephadm/services/cephadmservice.py index c95d845aa8a..636eb0ddcc6 100644 --- a/src/pybind/mgr/cephadm/services/cephadmservice.py +++ b/src/pybind/mgr/cephadm/services/cephadmservice.py @@ -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) diff --git a/src/pybind/mgr/cephadm/services/ingress.py b/src/pybind/mgr/cephadm/services/ingress.py index 05d8525b9fd..d546d73bae9 100644 --- a/src/pybind/mgr/cephadm/services/ingress.py +++ b/src/pybind/mgr/cephadm/services/ingress.py @@ -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 diff --git a/src/pybind/mgr/cephadm/services/jaeger.py b/src/pybind/mgr/cephadm/services/jaeger.py index 1d60680cc0f..8d69c53cec8 100644 --- a/src/pybind/mgr/cephadm/services/jaeger.py +++ b/src/pybind/mgr/cephadm/services/jaeger.py @@ -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 diff --git a/src/pybind/mgr/cephadm/services/monitoring.py b/src/pybind/mgr/cephadm/services/monitoring.py index 86f0aa0a8e8..71a19a7583d 100644 --- a/src/pybind/mgr/cephadm/services/monitoring.py +++ b/src/pybind/mgr/cephadm/services/monitoring.py @@ -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. diff --git a/src/pybind/mgr/cephadm/services/nfs.py b/src/pybind/mgr/cephadm/services/nfs.py index 28d5ec7bed9..45d7aad1b9c 100644 --- a/src/pybind/mgr/cephadm/services/nfs.py +++ b/src/pybind/mgr/cephadm/services/nfs.py @@ -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) diff --git a/src/pybind/mgr/cephadm/utils.py b/src/pybind/mgr/cephadm/utils.py index 8221b950af4..92725badc55 100644 --- a/src/pybind/mgr/cephadm/utils.py +++ b/src/pybind/mgr/cephadm/utils.py @@ -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)