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