From 8978229436b9bd38e9274239ae1f67e0c96350b5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 9 Mar 2021 18:26:43 -0500 Subject: [PATCH] mgr/cephadm/schedule: pass per-type allow_colo to the scheduler Signed-off-by: Sage Weil (cherry picked from commit 927694ba4aeed42b2fa70c962c96e3ef5882d46c) --- src/pybind/mgr/cephadm/schedule.py | 11 +++++++++ src/pybind/mgr/cephadm/serve.py | 1 + .../mgr/cephadm/services/cephadmservice.py | 9 ++++++++ .../mgr/cephadm/tests/test_scheduling.py | 23 +++++++++++-------- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/pybind/mgr/cephadm/schedule.py b/src/pybind/mgr/cephadm/schedule.py index e64991cee8a8b..6148b6a181dee 100644 --- a/src/pybind/mgr/cephadm/schedule.py +++ b/src/pybind/mgr/cephadm/schedule.py @@ -59,6 +59,7 @@ class HostAssignment(object): daemons: List[orchestrator.DaemonDescription], filter_new_host=None, # type: Optional[Callable[[str],bool]] scheduler=None, # type: Optional[BaseScheduler] + allow_colo: bool = False, ): assert spec self.spec = spec # type: ServiceSpec @@ -67,6 +68,7 @@ class HostAssignment(object): self.filter_new_host = filter_new_host self.service_name = spec.service_name() self.daemons = daemons + self.allow_colo = allow_colo def hosts_by_label(self, label: str) -> List[orchestrator.HostSpec]: return [h for h in self.hosts if label in h.labels] @@ -81,6 +83,15 @@ class HostAssignment(object): raise OrchestratorValidationError( f' can not be 0 for {self.spec.one_line_str()}') + if ( + self.spec.placement.count_per_host is not None + and self.spec.placement.count_per_host > 1 + and not self.allow_colo + ): + raise OrchestratorValidationError( + f'Cannot place more than one {self.spec.service_type} per host' + ) + if self.spec.placement.hosts: explicit_hostnames = {h.hostname for h in self.spec.placement.hosts} unknown_hosts = explicit_hostnames.difference(set(self.get_hostnames())) diff --git a/src/pybind/mgr/cephadm/serve.py b/src/pybind/mgr/cephadm/serve.py index 3c9e38fe67541..fcd371f0f6aaf 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -554,6 +554,7 @@ class CephadmServe: daemons=daemons, filter_new_host=matches_network if service_type == 'mon' else virtual_ip_allowed if service_type == 'ha-rgw' else None, + allow_colo=svc.allow_colo(), ) try: diff --git a/src/pybind/mgr/cephadm/services/cephadmservice.py b/src/pybind/mgr/cephadm/services/cephadmservice.py index 52f22133e4787..7cb10f1aa36fd 100644 --- a/src/pybind/mgr/cephadm/services/cephadmservice.py +++ b/src/pybind/mgr/cephadm/services/cephadmservice.py @@ -97,6 +97,9 @@ class CephadmService(metaclass=ABCMeta): def __init__(self, mgr: "CephadmOrchestrator"): self.mgr: "CephadmOrchestrator" = mgr + def allow_colo(self) -> bool: + return False + def make_daemon_spec(self, host: str, daemon_id: str, network: str, @@ -610,6 +613,9 @@ class MgrService(CephService): class MdsService(CephService): TYPE = 'mds' + def allow_colo(self) -> bool: + return True + def config(self, spec: ServiceSpec, daemon_id: str) -> None: assert self.TYPE == spec.service_type assert spec.service_id @@ -782,6 +788,9 @@ class RgwService(CephService): class RbdMirrorService(CephService): TYPE = 'rbd-mirror' + def allow_colo(self) -> bool: + return True + def prepare_create(self, daemon_spec: CephadmDaemonDeploySpec) -> CephadmDaemonDeploySpec: assert self.TYPE == daemon_spec.daemon_type daemon_id, _ = daemon_spec.daemon_id, daemon_spec.host diff --git a/src/pybind/mgr/cephadm/tests/test_scheduling.py b/src/pybind/mgr/cephadm/tests/test_scheduling.py index 0dbd414b6c9b7..2b370588bd5fa 100644 --- a/src/pybind/mgr/cephadm/tests/test_scheduling.py +++ b/src/pybind/mgr/cephadm/tests/test_scheduling.py @@ -353,12 +353,12 @@ class NodeAssignmentTest(NamedTuple): ), # all_hosts + count_per_host NodeAssignmentTest( - 'mgr', + 'mds', PlacementSpec(host_pattern='*', count_per_host=2), 'host1 host2 host3'.split(), [ - DaemonDescription('mgr', 'a', 'host1'), - DaemonDescription('mgr', 'b', 'host2'), + DaemonDescription('mds', 'a', 'host1'), + DaemonDescription('mds', 'b', 'host2'), ], ['host1', 'host2', 'host3', 'host1', 'host2', 'host3'] ), @@ -433,7 +433,7 @@ class NodeAssignmentTest(NamedTuple): ), # label only + count_per_hst NodeAssignmentTest( - 'mgr', + 'mds', PlacementSpec(label='foo', count_per_host=3), 'host1 host2 host3'.split(), [], @@ -450,17 +450,21 @@ class NodeAssignmentTest(NamedTuple): ), # host_pattern + count_per_host NodeAssignmentTest( - 'mgr', - PlacementSpec(host_pattern='mgr*', count_per_host=3), - 'mgrhost1 mgrhost2 datahost'.split(), + 'mds', + PlacementSpec(host_pattern='mds*', count_per_host=3), + 'mdshost1 mdshost2 datahost'.split(), [], - ['mgrhost1', 'mgrhost2', 'mgrhost1', 'mgrhost2', 'mgrhost1', 'mgrhost2'] + ['mdshost1', 'mdshost2', 'mdshost1', 'mdshost2', 'mdshost1', 'mdshost2'] ), ]) def test_node_assignment(service_type, placement, hosts, daemons, expected): service_id = None + allow_colo = False if service_type == 'rgw': service_id = 'realm.zone' + elif service_type == 'mds': + service_id = 'myfs' + allow_colo = True spec = ServiceSpec(service_type=service_type, service_id=service_id, @@ -469,7 +473,8 @@ def test_node_assignment(service_type, placement, hosts, daemons, expected): hosts = HostAssignment( spec=spec, hosts=[HostSpec(h, labels=['foo']) for h in hosts], - daemons=daemons + daemons=daemons, + allow_colo=allow_colo ).place() assert sorted([h.hostname for h in hosts]) == sorted(expected) -- 2.39.5