def _get_spec_size(self, spec):
if spec.placement.count:
return spec.placement.count
- elif spec.placement.all_hosts:
- return len(self.inventory)
+ elif spec.placement.host_pattern:
+ return len(spec.placement.pattern_matches_hosts(self.inventory.keys()))
elif spec.placement.label:
return len(self._get_hosts(spec.placement.label))
elif spec.placement.hosts:
'grafana': PlacementSpec(count=1),
'alertmanager': PlacementSpec(count=1),
'prometheus': PlacementSpec(count=1),
- 'node-exporter': PlacementSpec(all_hosts=True),
- 'crash': PlacementSpec(all_hosts=True),
+ 'node-exporter': PlacementSpec(host_pattern='*'),
+ 'crash': PlacementSpec(host_pattern='*'),
}
spec.placement = defaults[spec.service_type]
elif spec.service_type in ['mon', 'mgr'] and \
logger.debug('Provided hosts: %s' % self.spec.placement.hosts)
return self.spec.placement.hosts
- # respect all_hosts=true
- if self.spec.placement.all_hosts:
- candidates = [
- HostPlacementSpec(x, '', '')
- for x in self.get_hosts_func(None)
- ]
- logger.debug('All hosts: {}'.format(candidates))
- return candidates
-
# respect host_pattern
if self.spec.placement.host_pattern:
candidates = [
assert self.spec.placement.count is None
assert not self.spec.placement.hosts
assert not self.spec.placement.label
- assert not self.spec.placement.all_hosts
count = 1
logger.debug('place %d over all hosts: %s' % (count, hosts))
For APIs that need to specify a host subset
"""
- def __init__(self, label=None, hosts=None, count=None, all_hosts=False, host_pattern=None):
- # type: (Optional[str], Optional[List], Optional[int], bool, Optional[str]) -> None
- if all_hosts and (count or hosts or label):
- raise ServiceSpecValidationError('cannot combine all:true and count|hosts|label')
+ def __init__(self, label=None, hosts=None, count=None, host_pattern=None):
+ # type: (Optional[str], Optional[List], Optional[int], Optional[str]) -> None
self.label = label
self.hosts = [] # type: List[HostPlacementSpec]
if hosts:
self.hosts = [HostPlacementSpec.parse(x, require_network=False) for x in hosts if x]
self.count = count # type: Optional[int]
- self.all_hosts = all_hosts # type: bool
#: An fnmatch pattern to select hosts. Can also be a single host.
self.host_pattern = host_pattern
+ self.validate()
+
def is_empty(self):
- return not self.all_hosts and \
- self.label is None and \
+ return self.label is None and \
not self.hosts and \
not self.host_pattern and \
self.count is None
kv.append('label:%s' % self.label)
if self.hosts:
kv.append('%s' % ','.join([str(h) for h in self.hosts]))
- if self.all_hosts:
- kv.append('all:true')
if self.host_pattern:
kv.append('host_pattern:{}'.format(self.host_pattern))
return ' '.join(kv)
kv.append('label=%s' % repr(self.label))
if self.hosts:
kv.append('hosts={!r}'.format(self.hosts))
- if self.all_hosts:
- kv.append('all_hosts=True')
if self.host_pattern:
kv.append('host_pattern={!r}'.format(self.host_pattern))
return "PlacementSpec(%s)" % ', '.join(kv)
'label': self.label,
'hosts': [host.to_json() for host in self.hosts] if self.hosts else [],
'count': self.count,
- 'all_hosts': self.all_hosts,
'host_pattern': self.host_pattern,
}
raise ServiceSpecValidationError('Host and label are mutually exclusive')
if self.count is not None and self.count <= 0:
raise ServiceSpecValidationError("num/count must be > 1")
- if self.host_pattern and (self.hosts or self.label or self.all_hosts):
- raise ServiceSpecValidationError('Host pattern is mutually exclusive to everything else'
- '.')
+ if self.host_pattern and self.hosts:
+ raise ServiceSpecValidationError('cannot combine host_pattern and hosts')
@classmethod
def from_string(cls, arg):
except ValueError:
pass
- all_hosts = False
if '*' in strings:
- all_hosts = True
strings.remove('*')
- if 'all:true' in strings:
- all_hosts = True
- strings.remove('all:true')
+ strings.append('host_pattern:*')
hosts = [x for x in strings
if x != '*' and 'label:' not in x and not x.startswith('host_pattern:')]
ps = PlacementSpec(count=count,
hosts=hosts,
label=labels[0] if labels else None,
- all_hosts=all_hosts,
host_pattern=host_patterns[0] if host_patterns else None)
- ps.validate()
return ps
('2 host1 host2', "PlacementSpec(count=2, hosts=[HostPlacementSpec(hostname='host1', network='', name=''), HostPlacementSpec(hostname='host2', network='', name='')])"),
('label:foo', "PlacementSpec(label='foo')"),
('3 label:foo', "PlacementSpec(count=3, label='foo')"),
- ('*', 'PlacementSpec(all_hosts=True)'),
+ ('*', "PlacementSpec(host_pattern='*')"),
])
def test_parse_placement_specs(test_input, expected):
ret = PlacementSpec.from_string(test_input)