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
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]
raise OrchestratorValidationError(
f'<count> 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()))
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,
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
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
),
# 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']
),
),
# label only + count_per_hst
NodeAssignmentTest(
- 'mgr',
+ 'mds',
PlacementSpec(label='foo', count_per_host=3),
'host1 host2 host3'.split(),
[],
),
# 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,
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)