]> git.proxmox.com Git - ceph.git/blob - ceph/src/python-common/ceph/tests/test_service_spec.py
import 15.2.5
[ceph.git] / ceph / src / python-common / ceph / tests / test_service_spec.py
1 # flake8: noqa
2 import json
3 import yaml
4
5 import pytest
6
7 from ceph.deployment.service_spec import HostPlacementSpec, PlacementSpec, \
8 ServiceSpec, ServiceSpecValidationError, RGWSpec, NFSServiceSpec, IscsiServiceSpec
9 from ceph.deployment.drive_group import DriveGroupSpec
10
11
12 @pytest.mark.parametrize("test_input,expected, require_network",
13 [("myhost", ('myhost', '', ''), False),
14 ("myhost=sname", ('myhost', '', 'sname'), False),
15 ("myhost:10.1.1.10", ('myhost', '10.1.1.10', ''), True),
16 ("myhost:10.1.1.10=sname", ('myhost', '10.1.1.10', 'sname'), True),
17 ("myhost:10.1.1.0/32", ('myhost', '10.1.1.0/32', ''), True),
18 ("myhost:10.1.1.0/32=sname", ('myhost', '10.1.1.0/32', 'sname'), True),
19 ("myhost:[v1:10.1.1.10:6789]", ('myhost', '[v1:10.1.1.10:6789]', ''), True),
20 ("myhost:[v1:10.1.1.10:6789]=sname", ('myhost', '[v1:10.1.1.10:6789]', 'sname'), True),
21 ("myhost:[v1:10.1.1.10:6789,v2:10.1.1.11:3000]", ('myhost', '[v1:10.1.1.10:6789,v2:10.1.1.11:3000]', ''), True),
22 ("myhost:[v1:10.1.1.10:6789,v2:10.1.1.11:3000]=sname", ('myhost', '[v1:10.1.1.10:6789,v2:10.1.1.11:3000]', 'sname'), True),
23 ])
24 def test_parse_host_placement_specs(test_input, expected, require_network):
25 ret = HostPlacementSpec.parse(test_input, require_network=require_network)
26 assert ret == expected
27 assert str(ret) == test_input
28
29
30 @pytest.mark.parametrize(
31 "test_input,expected",
32 [
33 ('', "PlacementSpec()"),
34 ("count:2", "PlacementSpec(count=2)"),
35 ("3", "PlacementSpec(count=3)"),
36 ("host1 host2", "PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='', name=''), HostPlacementSpec(hostname='host2', network='', name='')])"),
37 ("host1;host2", "PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='', name=''), HostPlacementSpec(hostname='host2', network='', name='')])"),
38 ("host1,host2", "PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='', name=''), HostPlacementSpec(hostname='host2', network='', name='')])"),
39 ("host1 host2=b", "PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='', name=''), HostPlacementSpec(hostname='host2', network='', name='b')])"),
40 ("host1=a host2=b", "PlacementSpec(hosts=[HostPlacementSpec(hostname='host1', network='', name='a'), HostPlacementSpec(hostname='host2', network='', name='b')])"),
41 ("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')])"),
42 ("myhost:[v1:10.1.1.10:6789]", "PlacementSpec(hosts=[HostPlacementSpec(hostname='myhost', network='[v1:10.1.1.10:6789]', name='')])"),
43 ('2 host1 host2', "PlacementSpec(count=2, hosts=[HostPlacementSpec(hostname='host1', network='', name=''), HostPlacementSpec(hostname='host2', network='', name='')])"),
44 ('label:foo', "PlacementSpec(label='foo')"),
45 ('3 label:foo', "PlacementSpec(count=3, label='foo')"),
46 ('*', "PlacementSpec(host_pattern='*')"),
47 ('3 data[1-3]', "PlacementSpec(count=3, host_pattern='data[1-3]')"),
48 ('3 data?', "PlacementSpec(count=3, host_pattern='data?')"),
49 ('3 data*', "PlacementSpec(count=3, host_pattern='data*')"),
50 ])
51 def test_parse_placement_specs(test_input, expected):
52 ret = PlacementSpec.from_string(test_input)
53 assert str(ret) == expected
54
55 @pytest.mark.parametrize(
56 "test_input",
57 [
58 ("host=a host*"),
59 ("host=a label:wrong"),
60 ("host? host*"),
61 ]
62 )
63 def test_parse_placement_specs_raises(test_input):
64 with pytest.raises(ServiceSpecValidationError):
65 PlacementSpec.from_string(test_input)
66
67 @pytest.mark.parametrize("test_input",
68 # wrong subnet
69 [("myhost:1.1.1.1/24"),
70 # wrong ip format
71 ("myhost:1"),
72 ])
73 def test_parse_host_placement_specs_raises_wrong_format(test_input):
74 with pytest.raises(ValueError):
75 HostPlacementSpec.parse(test_input)
76
77
78 def _get_dict_spec(s_type, s_id):
79 dict_spec = {
80 "service_id": s_id,
81 "service_type": s_type,
82 "placement":
83 dict(hosts=["host1:1.1.1.1"])
84 }
85 if s_type == 'nfs':
86 dict_spec['pool'] = 'pool'
87 elif s_type == 'iscsi':
88 dict_spec['pool'] = 'pool'
89 dict_spec['api_user'] = 'api_user'
90 dict_spec['api_password'] = 'api_password'
91 elif s_type == 'osd':
92 dict_spec['spec'] = {
93 'data_devices': {
94 'all': True
95 }
96 }
97 elif s_type == 'rgw':
98 dict_spec['rgw_realm'] = 'realm'
99 dict_spec['rgw_zone'] = 'zone'
100
101 return dict_spec
102
103
104 @pytest.mark.parametrize(
105 "s_type,o_spec,s_id",
106 [
107 ("mgr", ServiceSpec, 'test'),
108 ("mon", ServiceSpec, 'test'),
109 ("mds", ServiceSpec, 'test'),
110 ("rgw", RGWSpec, 'realm.zone'),
111 ("nfs", NFSServiceSpec, 'test'),
112 ("iscsi", IscsiServiceSpec, 'test'),
113 ("osd", DriveGroupSpec, 'test'),
114 ])
115 def test_servicespec_map_test(s_type, o_spec, s_id):
116 spec = ServiceSpec.from_json(_get_dict_spec(s_type, s_id))
117 assert isinstance(spec, o_spec)
118 assert isinstance(spec.placement, PlacementSpec)
119 assert isinstance(spec.placement.hosts[0], HostPlacementSpec)
120 assert spec.placement.hosts[0].hostname == 'host1'
121 assert spec.placement.hosts[0].network == '1.1.1.1'
122 assert spec.placement.hosts[0].name == ''
123 assert spec.validate() is None
124 ServiceSpec.from_json(spec.to_json())
125
126
127 def test_yaml():
128 y = """service_type: crash
129 service_name: crash
130 placement:
131 host_pattern: '*'
132 ---
133 service_type: crash
134 service_name: crash
135 placement:
136 host_pattern: '*'
137 unmanaged: true
138 ---
139 service_type: rgw
140 service_id: default-rgw-realm.eu-central-1.1
141 service_name: rgw.default-rgw-realm.eu-central-1.1
142 placement:
143 hosts:
144 - hostname: ceph-001
145 name: ''
146 network: ''
147 spec:
148 rgw_realm: default-rgw-realm
149 rgw_zone: eu-central-1
150 subcluster: '1'
151 ---
152 service_type: osd
153 service_id: osd_spec_default
154 service_name: osd.osd_spec_default
155 placement:
156 host_pattern: '*'
157 spec:
158 data_devices:
159 model: MC-55-44-XZ
160 db_devices:
161 model: SSD-123-foo
162 filter_logic: AND
163 objectstore: bluestore
164 wal_devices:
165 model: NVME-QQQQ-987
166 """
167
168 for y in y.split('---\n'):
169 data = yaml.safe_load(y)
170 object = ServiceSpec.from_json(data)
171
172 assert yaml.dump(object) == y
173 assert yaml.dump(ServiceSpec.from_json(object.to_json())) == y
174
175 @pytest.mark.parametrize("spec1, spec2, eq",
176 [
177 (
178 ServiceSpec(
179 service_type='mon'
180 ),
181 ServiceSpec(
182 service_type='mon'
183 ),
184 True
185 ),
186 (
187 ServiceSpec(
188 service_type='mon'
189 ),
190 ServiceSpec(
191 service_type='mon',
192 service_id='foo'
193 ),
194 True
195 ),
196 # Add service_type='mgr'
197 (
198 ServiceSpec(
199 service_type='osd'
200 ),
201 ServiceSpec(
202 service_type='osd',
203 ),
204 True
205 ),
206 (
207 ServiceSpec(
208 service_type='osd'
209 ),
210 DriveGroupSpec(),
211 True
212 ),
213 (
214 ServiceSpec(
215 service_type='osd'
216 ),
217 ServiceSpec(
218 service_type='osd',
219 service_id='foo',
220 ),
221 False
222 ),
223 (
224 ServiceSpec(
225 service_type='rgw'
226 ),
227 RGWSpec(),
228 True
229 ),
230 ])
231 def test_spec_hash_eq(spec1: ServiceSpec,
232 spec2: ServiceSpec,
233 eq: bool):
234
235 assert (spec1 == spec2) is eq
236
237 @pytest.mark.parametrize(
238 "s_type,s_id,s_name",
239 [
240 ('mgr', 's_id', 'mgr'),
241 ('mon', 's_id', 'mon'),
242 ('mds', 's_id', 'mds.s_id'),
243 ('rgw', 's_id', 'rgw.s_id'),
244 ('nfs', 's_id', 'nfs.s_id'),
245 ('iscsi', 's_id', 'iscsi.s_id'),
246 ('osd', 's_id', 'osd.s_id'),
247 ])
248 def test_service_name(s_type, s_id, s_name):
249 spec = ServiceSpec.from_json(_get_dict_spec(s_type, s_id))
250 spec.validate()
251 assert spec.service_name() == s_name