]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/cephadm/tests/test_spec.py
2fa190a814fb98403371370c185326498fbec263
[ceph.git] / ceph / src / pybind / mgr / cephadm / tests / test_spec.py
1 import json
2
3 import pytest
4
5 from ceph.deployment.service_spec import ServiceSpec, NFSServiceSpec, RGWSpec, \
6 IscsiServiceSpec, AlertManagerSpec
7
8 from orchestrator import DaemonDescription, OrchestratorError
9
10
11 @pytest.mark.parametrize(
12 "spec_json",
13 json.loads("""[
14 {
15 "placement": {
16 "count": 1
17 },
18 "service_type": "alertmanager"
19 },
20 {
21 "placement": {
22 "host_pattern": "*"
23 },
24 "service_type": "crash"
25 },
26 {
27 "placement": {
28 "count": 1
29 },
30 "service_type": "grafana"
31 },
32 {
33 "placement": {
34 "count": 2
35 },
36 "service_type": "mgr"
37 },
38 {
39 "placement": {
40 "count": 5
41 },
42 "service_type": "mon"
43 },
44 {
45 "placement": {
46 "host_pattern": "*"
47 },
48 "service_type": "node-exporter"
49 },
50 {
51 "placement": {
52 "count": 1
53 },
54 "service_type": "prometheus"
55 },
56 {
57 "placement": {
58 "hosts": [
59 {
60 "hostname": "ceph-001",
61 "network": "",
62 "name": ""
63 }
64 ]
65 },
66 "service_type": "rgw",
67 "service_id": "default-rgw-realm.eu-central-1.1",
68 "rgw_realm": "default-rgw-realm",
69 "rgw_zone": "eu-central-1",
70 "subcluster": "1"
71 },
72 {
73 "service_type": "osd",
74 "service_id": "osd_spec_default",
75 "placement": {
76 "host_pattern": "*"
77 },
78 "data_devices": {
79 "model": "MC-55-44-XZ"
80 },
81 "db_devices": {
82 "model": "SSD-123-foo"
83 },
84 "wal_devices": {
85 "model": "NVME-QQQQ-987"
86 }
87 }
88 ]
89 """)
90 )
91 def test_spec_octopus(spec_json):
92 # https://tracker.ceph.com/issues/44934
93 # Those are real user data from early octopus.
94 # Please do not modify those JSON values.
95
96 spec = ServiceSpec.from_json(spec_json)
97 # just some verification that we can sill read old octopus specs
98 def convert_to_old_style_json(j):
99 j_c = dict(j.copy())
100 j_c.pop('service_name', None)
101 if 'spec' in j_c:
102 spec = j_c.pop('spec')
103 j_c.update(spec)
104 j_c.pop('objectstore', None)
105 j_c.pop('filter_logic', None)
106 return j_c
107 assert spec_json == convert_to_old_style_json(spec.to_json())
108
109
110 @pytest.mark.parametrize(
111 "dd_json",
112 json.loads("""[
113 {
114 "hostname": "ceph-001",
115 "container_id": "d94d7969094d",
116 "container_image_id": "0881eb8f169f5556a292b4e2c01d683172b12830a62a9225a98a8e206bb734f0",
117 "container_image_name": "docker.io/prom/alertmanager:latest",
118 "daemon_id": "ceph-001",
119 "daemon_type": "alertmanager",
120 "version": "0.20.0",
121 "status": 1,
122 "status_desc": "running",
123 "last_refresh": "2020-04-03T15:31:48.725856",
124 "created": "2020-04-02T19:23:08.829543",
125 "started": "2020-04-03T07:29:16.932838",
126 "is_active": false
127 },
128 {
129 "hostname": "ceph-001",
130 "container_id": "c4b036202241",
131 "container_image_id": "204a01f9b0b6710dd0c0af7f37ce7139c47ff0f0105d778d7104c69282dfbbf1",
132 "container_image_name": "docker.io/ceph/ceph:v15",
133 "daemon_id": "ceph-001",
134 "daemon_type": "crash",
135 "version": "15.2.0",
136 "status": 1,
137 "status_desc": "running",
138 "last_refresh": "2020-04-03T15:31:48.725903",
139 "created": "2020-04-02T19:23:11.390694",
140 "started": "2020-04-03T07:29:16.910897",
141 "is_active": false
142 },
143 {
144 "hostname": "ceph-001",
145 "container_id": "5b7b94b48f31",
146 "container_image_id": "87a51ecf0b1c9a7b187b21c1b071425dafea0d765a96d5bc371c791169b3d7f4",
147 "container_image_name": "docker.io/ceph/ceph-grafana:latest",
148 "daemon_id": "ceph-001",
149 "daemon_type": "grafana",
150 "version": "6.6.2",
151 "status": 1,
152 "status_desc": "running",
153 "last_refresh": "2020-04-03T15:31:48.725950",
154 "created": "2020-04-02T19:23:52.025088",
155 "started": "2020-04-03T07:29:16.847972",
156 "is_active": false
157 },
158 {
159 "hostname": "ceph-001",
160 "container_id": "9ca007280456",
161 "container_image_id": "204a01f9b0b6710dd0c0af7f37ce7139c47ff0f0105d778d7104c69282dfbbf1",
162 "container_image_name": "docker.io/ceph/ceph:v15",
163 "daemon_id": "ceph-001.gkjwqp",
164 "daemon_type": "mgr",
165 "version": "15.2.0",
166 "status": 1,
167 "status_desc": "running",
168 "last_refresh": "2020-04-03T15:31:48.725807",
169 "created": "2020-04-02T19:22:18.648584",
170 "started": "2020-04-03T07:29:16.856153",
171 "is_active": false
172 },
173 {
174 "hostname": "ceph-001",
175 "container_id": "3d1ba9a2b697",
176 "container_image_id": "204a01f9b0b6710dd0c0af7f37ce7139c47ff0f0105d778d7104c69282dfbbf1",
177 "container_image_name": "docker.io/ceph/ceph:v15",
178 "daemon_id": "ceph-001",
179 "daemon_type": "mon",
180 "version": "15.2.0",
181 "status": 1,
182 "status_desc": "running",
183 "last_refresh": "2020-04-03T15:31:48.725715",
184 "created": "2020-04-02T19:22:13.863300",
185 "started": "2020-04-03T07:29:17.206024",
186 "is_active": false
187 },
188 {
189 "hostname": "ceph-001",
190 "container_id": "36d026c68ba1",
191 "container_image_id": "e5a616e4b9cf68dfcad7782b78e118be4310022e874d52da85c55923fb615f87",
192 "container_image_name": "docker.io/prom/node-exporter:latest",
193 "daemon_id": "ceph-001",
194 "daemon_type": "node-exporter",
195 "version": "0.18.1",
196 "status": 1,
197 "status_desc": "running",
198 "last_refresh": "2020-04-03T15:31:48.725996",
199 "created": "2020-04-02T19:23:53.880197",
200 "started": "2020-04-03T07:29:16.880044",
201 "is_active": false
202 },
203 {
204 "hostname": "ceph-001",
205 "container_id": "faf76193cbfe",
206 "container_image_id": "204a01f9b0b6710dd0c0af7f37ce7139c47ff0f0105d778d7104c69282dfbbf1",
207 "container_image_name": "docker.io/ceph/ceph:v15",
208 "daemon_id": "0",
209 "daemon_type": "osd",
210 "version": "15.2.0",
211 "status": 1,
212 "status_desc": "running",
213 "last_refresh": "2020-04-03T15:31:48.726088",
214 "created": "2020-04-02T20:35:02.991435",
215 "started": "2020-04-03T07:29:19.373956",
216 "is_active": false
217 },
218 {
219 "hostname": "ceph-001",
220 "container_id": "f82505bae0f1",
221 "container_image_id": "204a01f9b0b6710dd0c0af7f37ce7139c47ff0f0105d778d7104c69282dfbbf1",
222 "container_image_name": "docker.io/ceph/ceph:v15",
223 "daemon_id": "1",
224 "daemon_type": "osd",
225 "version": "15.2.0",
226 "status": 1,
227 "status_desc": "running",
228 "last_refresh": "2020-04-03T15:31:48.726134",
229 "created": "2020-04-02T20:35:17.142272",
230 "started": "2020-04-03T07:29:19.374002",
231 "is_active": false
232 },
233 {
234 "hostname": "ceph-001",
235 "container_id": "2708d84cd484",
236 "container_image_id": "358a0d2395fe711bb8258e8fb4b2d7865c0a9a6463969bcd1452ee8869ea6653",
237 "container_image_name": "docker.io/prom/prometheus:latest",
238 "daemon_id": "ceph-001",
239 "daemon_type": "prometheus",
240 "version": "2.17.1",
241 "status": 1,
242 "status_desc": "running",
243 "last_refresh": "2020-04-03T15:31:48.726042",
244 "created": "2020-04-02T19:24:10.281163",
245 "started": "2020-04-03T07:29:16.926292",
246 "is_active": false
247 },
248 {
249 "hostname": "ceph-001",
250 "daemon_id": "default-rgw-realm.eu-central-1.1.ceph-001.ytywjo",
251 "daemon_type": "rgw",
252 "status": 1,
253 "status_desc": "starting",
254 "is_active": false
255 }
256 ]""")
257 )
258 def test_dd_octopus(dd_json):
259 # https://tracker.ceph.com/issues/44934
260 # Those are real user data from early octopus.
261 # Please do not modify those JSON values.
262 assert dd_json == DaemonDescription.from_json(dd_json).to_json()
263
264
265 @pytest.mark.parametrize("spec,dd,valid",
266 [
267 # https://tracker.ceph.com/issues/44934
268 (
269 RGWSpec(
270 rgw_realm="default-rgw-realm",
271 rgw_zone="eu-central-1",
272 subcluster='1',
273 ),
274 DaemonDescription(
275 daemon_type='rgw',
276 daemon_id="default-rgw-realm.eu-central-1.1.ceph-001.ytywjo",
277 hostname="ceph-001",
278 ),
279 True
280 ),
281 (
282 # no subcluster
283 RGWSpec(
284 rgw_realm="default-rgw-realm",
285 rgw_zone="eu-central-1",
286 ),
287 DaemonDescription(
288 daemon_type='rgw',
289 daemon_id="default-rgw-realm.eu-central-1.ceph-001.ytywjo",
290 hostname="ceph-001",
291 ),
292 True
293 ),
294 (
295 # with tld
296 RGWSpec(
297 rgw_realm="default-rgw-realm",
298 rgw_zone="eu-central-1",
299 subcluster='1',
300 ),
301 DaemonDescription(
302 daemon_type='rgw',
303 daemon_id="default-rgw-realm.eu-central-1.1.host.domain.tld.ytywjo",
304 hostname="host.domain.tld",
305 ),
306 True
307 ),
308 (
309 # explicit naming
310 RGWSpec(
311 rgw_realm="realm",
312 rgw_zone="zone",
313 ),
314 DaemonDescription(
315 daemon_type='rgw',
316 daemon_id="realm.zone.a",
317 hostname="smithi028",
318 ),
319 True
320 ),
321 (
322 # without host
323 RGWSpec(
324 service_type='rgw',
325 rgw_realm="default-rgw-realm",
326 rgw_zone="eu-central-1",
327 subcluster='1',
328 ),
329 DaemonDescription(
330 daemon_type='rgw',
331 daemon_id="default-rgw-realm.eu-central-1.1.hostname.ytywjo",
332 hostname=None,
333 ),
334 False
335 ),
336 (
337 # zone contains hostname
338 # https://tracker.ceph.com/issues/45294
339 RGWSpec(
340 rgw_realm="default.rgw.realm",
341 rgw_zone="ceph.001",
342 subcluster='1',
343 ),
344 DaemonDescription(
345 daemon_type='rgw',
346 daemon_id="default.rgw.realm.ceph.001.1.ceph.001.ytywjo",
347 hostname="ceph.001",
348 ),
349 True
350 ),
351
352 # https://tracker.ceph.com/issues/45293
353 (
354 ServiceSpec(
355 service_type='mds',
356 service_id="a",
357 ),
358 DaemonDescription(
359 daemon_type='mds',
360 daemon_id="a.host1.abc123",
361 hostname="host1",
362 ),
363 True
364 ),
365 (
366 # '.' char in service_id
367 ServiceSpec(
368 service_type='mds',
369 service_id="a.b.c",
370 ),
371 DaemonDescription(
372 daemon_type='mds',
373 daemon_id="a.b.c.host1.abc123",
374 hostname="host1",
375 ),
376 True
377 ),
378
379 # https://tracker.ceph.com/issues/45617
380 (
381 # daemon_id does not contain hostname
382 ServiceSpec(
383 service_type='mds',
384 service_id="a",
385 ),
386 DaemonDescription(
387 daemon_type='mds',
388 daemon_id="a",
389 hostname="host1",
390 ),
391 True
392 ),
393 (
394 # daemon_id only contains hostname
395 ServiceSpec(
396 service_type='mds',
397 service_id="host1",
398 ),
399 DaemonDescription(
400 daemon_type='mds',
401 daemon_id="host1",
402 hostname="host1",
403 ),
404 True
405 ),
406
407 # https://tracker.ceph.com/issues/45399
408 (
409 # daemon_id only contains hostname
410 ServiceSpec(
411 service_type='mds',
412 service_id="a",
413 ),
414 DaemonDescription(
415 daemon_type='mds',
416 daemon_id="a.host1.abc123",
417 hostname="host1.site",
418 ),
419 True
420 ),
421 (
422 NFSServiceSpec(
423 service_id="a",
424 ),
425 DaemonDescription(
426 daemon_type='nfs',
427 daemon_id="a.host1",
428 hostname="host1.site",
429 ),
430 True
431 ),
432
433 # https://tracker.ceph.com/issues/45293
434 (
435 NFSServiceSpec(
436 service_id="a",
437 ),
438 DaemonDescription(
439 daemon_type='nfs',
440 daemon_id="a.host1",
441 hostname="host1",
442 ),
443 True
444 ),
445 (
446 # service_id contains a '.' char
447 NFSServiceSpec(
448 service_id="a.b.c",
449 ),
450 DaemonDescription(
451 daemon_type='nfs',
452 daemon_id="a.b.c.host1",
453 hostname="host1",
454 ),
455 True
456 ),
457 (
458 # trailing chars after hostname
459 NFSServiceSpec(
460 service_id="a.b.c",
461 ),
462 DaemonDescription(
463 daemon_type='nfs',
464 daemon_id="a.b.c.host1.abc123",
465 hostname="host1",
466 ),
467 True
468 ),
469 (
470 # chars after hostname without '.'
471 NFSServiceSpec(
472 service_id="a",
473 ),
474 DaemonDescription(
475 daemon_type='nfs',
476 daemon_id="a.host1abc123",
477 hostname="host1",
478 ),
479 False
480 ),
481 (
482 # chars before hostname without '.'
483 NFSServiceSpec(
484 service_id="a",
485 ),
486 DaemonDescription(
487 daemon_type='nfs',
488 daemon_id="ahost1.abc123",
489 hostname="host1",
490 ),
491 False
492 ),
493
494 # https://tracker.ceph.com/issues/45293
495 (
496 IscsiServiceSpec(
497 service_type='iscsi',
498 service_id="a",
499 ),
500 DaemonDescription(
501 daemon_type='iscsi',
502 daemon_id="a.host1.abc123",
503 hostname="host1",
504 ),
505 True
506 ),
507 (
508 # '.' char in service_id
509 IscsiServiceSpec(
510 service_type='iscsi',
511 service_id="a.b.c",
512 ),
513 DaemonDescription(
514 daemon_type='iscsi',
515 daemon_id="a.b.c.host1.abc123",
516 hostname="host1",
517 ),
518 True
519 ),
520 ])
521 def test_daemon_description_service_name(spec: ServiceSpec,
522 dd: DaemonDescription,
523 valid: bool):
524 if valid:
525 assert spec.service_name() == dd.service_name()
526 else:
527 with pytest.raises(OrchestratorError):
528 dd.service_name()
529
530
531 def test_alertmanager_spec_1():
532 spec = AlertManagerSpec()
533 assert spec.service_type == 'alertmanager'
534 assert isinstance(spec.user_data, dict)
535 assert len(spec.user_data.keys()) == 0
536
537
538 def test_alertmanager_spec_2():
539 spec = AlertManagerSpec(user_data={'default_webhook_urls': ['foo']})
540 assert isinstance(spec.user_data, dict)
541 assert 'default_webhook_urls' in spec.user_data.keys()