for h, hostspec in self._inventory.items():
if not label or label in hostspec.get('labels', []):
if as_hostspec:
- yield hostspec
- yield h
+ yield self.spec_from_dict(hostspec)
+ else:
+ yield h
def spec_from_dict(self, info):
hostname = info['hostname']
osd_count += 1
sm[n].size = osd_count
else:
- sm[n].size = spec.placement.get_host_selection_size(self._get_hosts)
+ sm[n].size = spec.placement.get_host_selection_size(self.inventory.all_specs())
sm[n].created = self.spec_store.spec_created[n]
if service_type == 'nfs':
continue
sm[n] = orchestrator.ServiceDescription(
spec=spec,
- size=spec.placement.get_host_selection_size(self._get_hosts),
+ size=spec.placement.get_host_selection_size(self.inventory.all_specs()),
running=0,
)
if service_type == 'nfs':
from typing import NamedTuple, List
import pytest
+from ceph.deployment.hostspec import HostSpec
from ceph.deployment.service_spec import ServiceSpec, PlacementSpec, ServiceSpecValidationError
from cephadm.module import HostAssignment
),
])
def test_node_assignment(service_type, placement, hosts, daemons, expected):
+ def get_hosts_func(label=None, as_hostspec=False):
+ if as_hostspec:
+ return [HostSpec(h) for h in hosts]
+ return hosts
+
+
hosts = HostAssignment(
spec=ServiceSpec(service_type, placement=placement),
- get_hosts_func=lambda label=None, as_hostspec=False: hosts,
+ get_hosts_func=get_hosts_func,
get_daemons_func=lambda _: daemons).place()
assert sorted([h.hostname for h in hosts]) == sorted(expected)
])
def test_node_assignment2(service_type, placement, hosts,
daemons, expected_len, in_set):
+ def get_hosts_func(label=None, as_hostspec=False):
+ if as_hostspec:
+ return [HostSpec(h) for h in hosts]
+ return hosts
+
hosts = HostAssignment(
spec=ServiceSpec(service_type, placement=placement),
- get_hosts_func=lambda label=None, as_hostspec=False: hosts,
+ get_hosts_func=get_hosts_func,
get_daemons_func=lambda _: daemons).place()
assert len(hosts) == expected_len
for h in [h.hostname for h in hosts]:
])
def test_node_assignment3(service_type, placement, hosts,
daemons, expected_len, must_have):
+ def get_hosts_func(label=None, as_hostspec=False):
+ if as_hostspec:
+ return [HostSpec(h) for h in hosts]
+ return hosts
+
hosts = HostAssignment(
spec=ServiceSpec(service_type, placement=placement),
- get_hosts_func=lambda label=None, as_hostspec=False: hosts,
+ get_hosts_func=get_hosts_func,
get_daemons_func=lambda _: daemons).place()
assert len(hosts) == expected_len
for h in must_have:
),
])
def test_bad_specs(service_type, placement, hosts, daemons, expected):
+ def get_hosts_func(label=None, as_hostspec=False):
+ if as_hostspec:
+ return [HostSpec(h) for h in hosts]
+ return hosts
with pytest.raises(OrchestratorValidationError) as e:
hosts = HostAssignment(
spec=ServiceSpec(service_type, placement=placement),
- get_hosts_func=lambda label=None, as_hostspec=False: hosts,
+ get_hosts_func=get_hosts_func,
get_daemons_func=lambda _: daemons).place()
assert str(e.value) == expected
import re
from collections import namedtuple
from functools import wraps
-from typing import Optional, Dict, Any, List, Union, Callable
+from typing import Optional, Dict, Any, List, Union, Callable, Iterator
import six
+from ceph.deployment.hostspec import HostSpec
+
class ServiceSpecValidationError(Exception):
"""
self.hosts = hosts
def filter_matching_hosts(self, _get_hosts_func: Callable) -> List[str]:
+ return self.filter_matching_hostspecs(_get_hosts_func(as_hostspec=True))
+
+ def filter_matching_hostspecs(self, hostspecs: Iterator[HostSpec]) -> List[str]:
if self.hosts:
- all_hosts = _get_hosts_func(label=None, as_hostspec=False)
+ all_hosts = [hs.hostname for hs in hostspecs]
return [h.hostname for h in self.hosts if h.hostname in all_hosts]
elif self.label:
- return _get_hosts_func(label=self.label, as_hostspec=False)
+ return [hs.hostname for hs in hostspecs if self.label in hs.labels]
elif self.host_pattern:
- return fnmatch.filter(_get_hosts_func(label=None, as_hostspec=False), self.host_pattern)
+ all_hosts = [hs.hostname for hs in hostspecs]
+ return fnmatch.filter(all_hosts, self.host_pattern)
else:
# This should be caught by the validation but needs to be here for
# get_host_selection_size
return []
- def get_host_selection_size(self, _get_hosts_func):
+ def get_host_selection_size(self, hostspecs: Iterator[HostSpec]):
if self.count:
return self.count
- return len(self.filter_matching_hosts(_get_hosts_func))
+ return len(self.filter_matching_hostspecs(hostspecs))
def pretty_str(self):
kv = []
import yaml
from ceph.deployment import drive_selection, translate
+from ceph.deployment.hostspec import HostSpec
from ceph.deployment.inventory import Device
from ceph.deployment.service_spec import PlacementSpec, ServiceSpecValidationError
from ceph.tests.utils import _mk_inventory, _mk_device
])
def test_DriveGroup(test_input):
dg = [DriveGroupSpec.from_json(inp) for inp in test_input][0]
- assert dg.placement.filter_matching_hosts(lambda label=None, as_hostspec=None: ['hostname']) == ['hostname']
+ assert dg.placement.filter_matching_hostspecs([HostSpec('hostname')]) == ['hostname']
assert dg.service_id == 'testing_drivegroup'
assert all([isinstance(x, Device) for x in dg.data_devices.paths])
assert dg.data_devices.paths[0].path == '/dev/sda'
def test_drivegroup_pattern():
dg = DriveGroupSpec(PlacementSpec(host_pattern='node[1-3]'), data_devices=DeviceSelection(all=True))
- assert dg.placement.filter_matching_hosts(lambda label=None, as_hostspec=None: ['node{}'.format(i) for i in range(10)]) == ['node1', 'node2', 'node3']
+ assert dg.placement.filter_matching_hostspecs([HostSpec('node{}'.format(i)) for i in range(10)]) == ['node1', 'node2', 'node3']
def test_drive_selection():