From: Shweta Bhosale Date: Mon, 18 May 2026 15:49:44 +0000 (+0530) Subject: mgr/cephadm: redeploy stopped keepalived when ingress deps change X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c20ba110400d0e6bc53a221701ba81befdfc5290;p=ceph.git mgr/cephadm: redeploy stopped keepalived when ingress deps change Fixes: https://tracker.ceph.com/issues/76304 Signed-off-by: Shweta Bhosale --- diff --git a/src/pybind/mgr/cephadm/serve.py b/src/pybind/mgr/cephadm/serve.py index 24e7e581a9e..5bbaa8fbeeb 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -1236,6 +1236,7 @@ class CephadmServe: spec, curr_deps=deps, last_deps=last_deps, + daemon=dd, ) if _step.action is not _scheduled_action: self.log.info( diff --git a/src/pybind/mgr/cephadm/services/cephadmservice.py b/src/pybind/mgr/cephadm/services/cephadmservice.py index 426b86f1b5c..37657d33e64 100644 --- a/src/pybind/mgr/cephadm/services/cephadmservice.py +++ b/src/pybind/mgr/cephadm/services/cephadmservice.py @@ -969,6 +969,7 @@ class CephadmService(metaclass=ABCMeta): spec: Optional[ServiceSpec], curr_deps: List[str], last_deps: List[str], + daemon: Optional[DaemonDescription] = None, ) -> utils.NextDaemonStep: """Given the scheduled_action, service spec, daemon_type, and current and previous dependency lists return the next action that @@ -1997,6 +1998,7 @@ class CephExporterService(CephService): spec: Optional[ServiceSpec], curr_deps: List[str], last_deps: List[str], + daemon: Optional[DaemonDescription] = None, ) -> utils.NextDaemonStep: """Given the scheduled_action, service spec, daemon_type, and current and previous dependency lists return the next action that diff --git a/src/pybind/mgr/cephadm/services/ingress.py b/src/pybind/mgr/cephadm/services/ingress.py index 84955d75549..360f84b7055 100644 --- a/src/pybind/mgr/cephadm/services/ingress.py +++ b/src/pybind/mgr/cephadm/services/ingress.py @@ -605,6 +605,7 @@ class IngressService(CephService): spec: Optional[ServiceSpec], curr_deps: List[str], last_deps: List[str], + daemon: Optional[DaemonDescription] = None, ) -> utils.NextDaemonStep: """Given the scheduled_action, service spec, daemon_type, and current and previous dependency lists return the next action that @@ -614,6 +615,20 @@ class IngressService(CephService): scheduled_action, daemon_type, spec, curr_deps, last_deps ) action = step.action + # keepalived is not systemd-enabled; when stopped, redeploy rewrites + # the unit and container so the serve loop can start the daemon again. + if ( + daemon_type == 'keepalived' + and action is utils.Action.RECONFIG + and daemon is not None + and daemon.status == DaemonDescriptionStatus.stopped + ): + logger.debug( + 'Redeploy wanted %s: keepalived deps changed (daemon stopped)', + spec.service_name() if spec else daemon_type, + ) + return utils.NextDaemonStep(utils.Action.REDEPLOY) + if ( action is not utils.Action.REDEPLOY and daemon_type == 'haproxy' diff --git a/src/pybind/mgr/cephadm/services/jaeger.py b/src/pybind/mgr/cephadm/services/jaeger.py index 8d69c53cec8..6d0b5f441a2 100644 --- a/src/pybind/mgr/cephadm/services/jaeger.py +++ b/src/pybind/mgr/cephadm/services/jaeger.py @@ -2,6 +2,7 @@ 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 +from orchestrator import DaemonDescription from .service_registry import register_cephadm_service from mgr_util import build_url from cephadm import utils @@ -58,6 +59,7 @@ class JaegerAgentService(CephadmService): spec: Optional[ServiceSpec], curr_deps: List[str], last_deps: List[str], + daemon: Optional[DaemonDescription] = None, ) -> utils.NextDaemonStep: """Given the scheduled_action, service spec, daemon_type, and current and previous dependency lists return the next action that diff --git a/src/pybind/mgr/cephadm/services/monitoring.py b/src/pybind/mgr/cephadm/services/monitoring.py index 0294fdfafa4..6d0008f0ef6 100644 --- a/src/pybind/mgr/cephadm/services/monitoring.py +++ b/src/pybind/mgr/cephadm/services/monitoring.py @@ -491,6 +491,7 @@ class AlertmanagerService(CephadmService): spec: Optional[ServiceSpec], curr_deps: List[str], last_deps: List[str], + daemon: Optional[DaemonDescription] = None, ) -> utils.NextDaemonStep: """Given the scheduled_action, service spec, daemon_type, and current and previous dependency lists return the next action that @@ -824,6 +825,7 @@ class PrometheusService(CephadmService): spec: Optional[ServiceSpec], curr_deps: List[str], last_deps: List[str], + daemon: Optional[DaemonDescription] = None, ) -> utils.NextDaemonStep: """Given the scheduled_action, service spec, daemon_type, and current and previous dependency lists return the next action that @@ -891,6 +893,7 @@ class NodeExporterService(CephadmService): spec: Optional[ServiceSpec], curr_deps: List[str], last_deps: List[str], + daemon: Optional[DaemonDescription] = None, ) -> utils.NextDaemonStep: """Given the scheduled_action, service spec, daemon_type, and current and previous dependency lists return the next action that diff --git a/src/pybind/mgr/cephadm/services/nfs.py b/src/pybind/mgr/cephadm/services/nfs.py index 45d7aad1b9c..83fc8ec945e 100644 --- a/src/pybind/mgr/cephadm/services/nfs.py +++ b/src/pybind/mgr/cephadm/services/nfs.py @@ -578,6 +578,7 @@ class NFSService(CephService): spec: Optional[ServiceSpec], curr_deps: List[str], last_deps: List[str], + daemon: Optional[DaemonDescription] = None, ) -> utils.NextDaemonStep: """Given the scheduled_action, service spec, daemon_type, and current and previous dependency lists return the next action that diff --git a/src/pybind/mgr/cephadm/tests/services/test_ingress.py b/src/pybind/mgr/cephadm/tests/services/test_ingress.py index 537e77283a9..4166f06179c 100644 --- a/src/pybind/mgr/cephadm/tests/services/test_ingress.py +++ b/src/pybind/mgr/cephadm/tests/services/test_ingress.py @@ -16,6 +16,7 @@ from cephadm.tests.fixtures import with_host, with_service, async_side_effect from ceph.utils import datetime_now from orchestrator._interface import DaemonDescription, DaemonDescriptionStatus from orchestrator import HostSpec +from cephadm import utils from cephadm.services.ingress import IngressService @@ -1459,6 +1460,86 @@ class TestIngressService: assert "Bind_addr = 10.10.2.20" in ganesha_conf +def test_keepalived_choose_next_action_redeploy_on_deps_change_when_stopped(): + mgr = MagicMock() + svc = IngressService(mgr) + spec = IngressSpec( + service_id='test', + backend_service='nfs.foo', + frontend_port=2049, + monitor_port=9049, + virtual_ip='192.168.122.100/24', + placement=PlacementSpec(hosts=['host1']), + ) + daemon = DaemonDescription( + daemon_type='keepalived', + daemon_id='test', + hostname='host1', + service_name='ingress.test', + status=DaemonDescriptionStatus.stopped, + ) + next_step = svc.choose_next_action( + utils.Action.NO_ACTION, + 'keepalived', + spec, + curr_deps=['haproxy.test'], + last_deps=['haproxy.old'], + daemon=daemon, + ) + assert next_step.action is utils.Action.REDEPLOY + + +def test_keepalived_choose_next_action_reconfig_when_running(): + mgr = MagicMock() + svc = IngressService(mgr) + spec = IngressSpec( + service_id='test', + backend_service='nfs.foo', + frontend_port=2049, + monitor_port=9049, + virtual_ip='192.168.122.100/24', + placement=PlacementSpec(hosts=['host1']), + ) + daemon = DaemonDescription( + daemon_type='keepalived', + daemon_id='test', + hostname='host1', + service_name='ingress.test', + status=DaemonDescriptionStatus.running, + ) + next_step = svc.choose_next_action( + utils.Action.NO_ACTION, + 'keepalived', + spec, + curr_deps=['haproxy.test'], + last_deps=['haproxy.old'], + daemon=daemon, + ) + assert next_step.action is utils.Action.RECONFIG + + +def test_keepalived_choose_next_action_scheduled_when_deps_unchanged(): + mgr = MagicMock() + svc = IngressService(mgr) + spec = IngressSpec( + service_id='test', + backend_service='nfs.foo', + frontend_port=2049, + monitor_port=9049, + virtual_ip='192.168.122.100/24', + placement=PlacementSpec(hosts=['host1']), + ) + deps = ['haproxy.test'] + next_step = svc.choose_next_action( + utils.Action.NO_ACTION, + 'keepalived', + spec, + curr_deps=deps, + last_deps=deps, + ) + assert next_step.action is utils.Action.NO_ACTION + + def test_keepalived_should_auto_start_colocated_haproxy(): mgr = MagicMock() mgr.cache.get_schedulable_hosts.return_value = [HostSpec('host-a')]