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 <Shweta.Bhosale1@ibm.com>
This commit is contained in:
Shweta Bhosale 2025-10-24 16:30:16 +05:30
parent 8ef8a1e2f3
commit 5cfab473be
8 changed files with 71 additions and 39 deletions

View File

@ -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'
)

View 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:

View 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)

View 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

View 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

View 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.

View 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)

View 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)