diff options
author | Sebastian Wagner <sebastian.wagner@suse.com> | 2020-03-09 17:08:57 +0100 |
---|---|---|
committer | Sebastian Wagner <sebastian.wagner@suse.com> | 2020-03-10 13:28:22 +0100 |
commit | 3d3e1f69a3aefbda3eacebf55ff337228a8f564f (patch) | |
tree | 2aeb59f49d8685bd0ffc75de166ee37832df40d6 | |
parent | cephadm: add host_pattern to supported scheduling (diff) | |
download | ceph-3d3e1f69a3aefbda3eacebf55ff337228a8f564f.tar.xz ceph-3d3e1f69a3aefbda3eacebf55ff337228a8f564f.zip |
python-common: Add `host_pattern` to `PlacementSpec.from_string()`
Signed-off-by: Sebastian Wagner <sebastian.wagner@suse.com>
-rw-r--r-- | src/python-common/ceph/deployment/service_spec.py | 42 | ||||
-rw-r--r-- | src/python-common/ceph/tests/test_service_spec.py | 18 | ||||
-rw-r--r-- | src/python-common/tox.ini | 4 |
3 files changed, 47 insertions, 17 deletions
diff --git a/src/python-common/ceph/deployment/service_spec.py b/src/python-common/ceph/deployment/service_spec.py index 481bad7254c..35d01facc4b 100644 --- a/src/python-common/ceph/deployment/service_spec.py +++ b/src/python-common/ceph/deployment/service_spec.py @@ -159,7 +159,18 @@ class PlacementSpec(object): return ' '.join(kv) def __repr__(self): - return "PlacementSpec(%s)" % self.pretty_str() + kv = [] + if self.count: + kv.append('count=%d' % self.count) + if self.label: + 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) @classmethod def from_json(cls, data): @@ -196,18 +207,29 @@ class PlacementSpec(object): A single integer is parsed as a count: >>> PlacementSpec.from_string('3') PlacementSpec(count=3) + A list of names is parsed as host specifications: >>> PlacementSpec.from_string('host1 host2') - PlacementSpec(label=[HostSpec(hostname='host1', network='', name=''), HostSpec(hostname='host2', network='', name='')]) + PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='', name=''), HostPlacemen\ +tSpec(hostname='host2', network='', name='')]) + You can also prefix the hosts with a count as follows: >>> PlacementSpec.from_string('2 host1 host2') - PlacementSpec(label=[HostSpec(hostname='host1', network='', name=''), HostSpec(hostname='host2', network='', name='')], count=2) + PlacementSpec(count=2, hosts=[HostPlacementSpec(hostname='host1', network='', name=''), Hos\ +tPlacementSpec(hostname='host2', network='', name='')]) + You can spefify labels using `label:<label>` >>> PlacementSpec.from_string('label:mon') - PlacementSpec(label='label:mon') + PlacementSpec(label='mon') + Labels als support a count: >>> PlacementSpec.from_string('3 label:mon') - PlacementSpec(label='label:mon', count=3) + PlacementSpec(count=3, label='mon') + + fnmatch is also supported: + >>> PlacementSpec.from_string('host_pattern:data[1-3]') + PlacementSpec(host_pattern='data[1-3]') + >>> PlacementSpec.from_string(None) PlacementSpec() """ @@ -253,15 +275,21 @@ class PlacementSpec(object): all_hosts = True strings.remove('all:true') - hosts = [x for x in strings if x != '*' and 'label:' not in x] + hosts = [x for x in strings + if x != '*' and 'label:' not in x and not x.startswith('host_pattern:')] labels = [x[6:] for x in strings if 'label:' in x] if len(labels) > 1: raise ServiceSpecValidationError('more than one label provided: {}'.format(labels)) + host_patterns = [x[13:] for x in strings if x.startswith('host_pattern:')] + if len(host_patterns) > 1: + raise ServiceSpecValidationError('more than one host_patterns provided: {}'.format( + host_patterns)) ps = PlacementSpec(count=count, hosts=hosts, label=labels[0] if labels else None, - all_hosts=all_hosts) + all_hosts=all_hosts, + host_pattern=host_patterns[0] if host_patterns else None) ps.validate() return ps diff --git a/src/python-common/ceph/tests/test_service_spec.py b/src/python-common/ceph/tests/test_service_spec.py index be33fd2da7e..19553e9d6aa 100644 --- a/src/python-common/ceph/tests/test_service_spec.py +++ b/src/python-common/ceph/tests/test_service_spec.py @@ -27,15 +27,15 @@ def test_parse_host_placement_specs(test_input, expected, require_network): "test_input,expected", [ ('', "PlacementSpec()"), - ("count:2", "PlacementSpec(count:2)"), - ("3", "PlacementSpec(count:3)"), - ("host1 host2", "PlacementSpec(host1,host2)"), - ("host1=a host2=b", "PlacementSpec(host1=a,host2=b)"), - ("host1:1.2.3.4=a host2:1.2.3.5=b", "PlacementSpec(host1:1.2.3.4=a,host2:1.2.3.5=b)"), - ('2 host1 host2', "PlacementSpec(count:2 host1,host2)"), - ('label:foo', "PlacementSpec(label:foo)"), - ('3 label:foo', "PlacementSpec(count:3 label:foo)"), - ('*', 'PlacementSpec(all:true)'), + ("count:2", "PlacementSpec(count=2)"), + ("3", "PlacementSpec(count=3)"), + ("host1 host2", "PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='', name=''), HostPlacementSpec(hostname='host2', network='', name='')])"), + ("host1=a host2=b", "PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='', name='a'), HostPlacementSpec(hostname='host2', network='', name='b')])"), + ("host1:1.2.3.4=a host2:1.2.3.5=b", "PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='1.2.3.4', name='a'), HostPlacementSpec(hostname='host2', network='1.2.3.5', name='b')])"), + ('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)'), ]) def test_parse_placement_specs(test_input, expected): ret = PlacementSpec.from_string(test_input) diff --git a/src/python-common/tox.ini b/src/python-common/tox.ini index 47b280f3369..da7037b2d81 100644 --- a/src/python-common/tox.ini +++ b/src/python-common/tox.ini @@ -5,7 +5,9 @@ skip_missing_interpreters = true [testenv:py3] deps= -rrequirements.txt -commands=pytest --mypy --mypy-ignore-missing-imports {posargs} +commands= + pytest --doctest-modules ceph/deployment/service_spec.py + pytest --mypy --mypy-ignore-missing-imports {posargs} [tool:pytest] norecursedirs = .* _* virtualenv |