]>
Commit | Line | Data |
---|---|---|
9f95a23c | 1 | import fnmatch |
f6b5b4d7 TL |
2 | from contextlib import contextmanager |
3 | ||
4 | from ceph.deployment.service_spec import PlacementSpec, ServiceSpec | |
adb31ebb | 5 | from ceph.utils import datetime_to_str, datetime_now |
f91f0fd5 | 6 | from cephadm.serve import CephadmServe |
f6b5b4d7 | 7 | |
9f95a23c | 8 | try: |
f91f0fd5 | 9 | from typing import Any, Iterator, List |
9f95a23c TL |
10 | except ImportError: |
11 | pass | |
9f95a23c TL |
12 | |
13 | from cephadm import CephadmOrchestrator | |
f67539c2 | 14 | from orchestrator import raise_if_exception, OrchResult, HostSpec |
9f95a23c TL |
15 | from tests import mock |
16 | ||
17 | ||
9f95a23c TL |
18 | def get_ceph_option(_, key): |
19 | return __file__ | |
20 | ||
21 | ||
22 | def _run_cephadm(ret): | |
b3b6e05e TL |
23 | def foo(s, host, entity, cmd, e, **kwargs): |
24 | if cmd == 'gather-facts': | |
25 | return '{}', '', 0 | |
f91f0fd5 | 26 | return [ret], '', 0 |
9f95a23c TL |
27 | return foo |
28 | ||
29 | ||
30 | def match_glob(val, pat): | |
31 | ok = fnmatch.fnmatchcase(val, pat) | |
32 | if not ok: | |
33 | assert pat in val | |
34 | ||
35 | ||
f6b5b4d7 TL |
36 | @contextmanager |
37 | def with_cephadm_module(module_options=None, store=None): | |
38 | """ | |
39 | :param module_options: Set opts as if they were set before module.__init__ is called | |
40 | :param store: Set the store before module.__init__ is called | |
41 | """ | |
9f95a23c | 42 | with mock.patch("cephadm.module.CephadmOrchestrator.get_ceph_option", get_ceph_option),\ |
f6b5b4d7 TL |
43 | mock.patch("cephadm.services.osd.RemoveUtil._run_mon_cmd"), \ |
44 | mock.patch("cephadm.module.CephadmOrchestrator.get_osdmap"), \ | |
45 | mock.patch("cephadm.services.osd.OSDService.get_osdspec_affinity", return_value='test_spec'), \ | |
46 | mock.patch("cephadm.module.CephadmOrchestrator.remote"): | |
9f95a23c | 47 | |
f91f0fd5 | 48 | m = CephadmOrchestrator.__new__(CephadmOrchestrator) |
f6b5b4d7 TL |
49 | if module_options is not None: |
50 | for k, v in module_options.items(): | |
51 | m._ceph_set_module_option('cephadm', k, v) | |
52 | if store is None: | |
53 | store = {} | |
54 | if '_ceph_get/mon_map' not in store: | |
55 | m.mock_store_set('_ceph_get', 'mon_map', { | |
adb31ebb | 56 | 'modified': datetime_to_str(datetime_now()), |
f6b5b4d7 TL |
57 | 'fsid': 'foobar', |
58 | }) | |
a4b75251 TL |
59 | if '_ceph_get/mgr_map' not in store: |
60 | m.mock_store_set('_ceph_get', 'mgr_map', { | |
61 | 'services': { | |
62 | 'dashboard': 'http://[::1]:8080', | |
63 | 'prometheus': 'http://[::1]:8081' | |
64 | }, | |
65 | 'modules': ['dashboard', 'prometheus'], | |
66 | }) | |
f6b5b4d7 TL |
67 | for k, v in store.items(): |
68 | m._ceph_set_store(k, v) | |
69 | ||
9f95a23c TL |
70 | m.__init__('cephadm', 0, 0) |
71 | m._cluster_fsid = "fsid" | |
72 | yield m | |
73 | ||
74 | ||
75 | def wait(m, c): | |
f67539c2 TL |
76 | # type: (CephadmOrchestrator, OrchResult) -> Any |
77 | return raise_if_exception(c) | |
f6b5b4d7 TL |
78 | |
79 | ||
80 | @contextmanager | |
a4b75251 | 81 | def with_host(m: CephadmOrchestrator, name, addr='1::4', refresh_hosts=True): |
f6b5b4d7 | 82 | # type: (CephadmOrchestrator, str) -> None |
b3b6e05e TL |
83 | with mock.patch("cephadm.utils.resolve_ip", return_value=addr): |
84 | wait(m, m.add_host(HostSpec(hostname=name))) | |
85 | if refresh_hosts: | |
86 | CephadmServe(m)._refresh_hosts_and_daemons() | |
87 | yield | |
88 | wait(m, m.remove_host(name)) | |
f6b5b4d7 TL |
89 | |
90 | ||
f67539c2 TL |
91 | def assert_rm_service(cephadm: CephadmOrchestrator, srv_name): |
92 | mon_or_mgr = cephadm.spec_store[srv_name].spec.service_type in ('mon', 'mgr') | |
93 | if mon_or_mgr: | |
94 | assert 'Unable' in wait(cephadm, cephadm.remove_service(srv_name)) | |
95 | return | |
f6b5b4d7 | 96 | assert wait(cephadm, cephadm.remove_service(srv_name)) == f'Removed service {srv_name}' |
f67539c2 TL |
97 | assert cephadm.spec_store[srv_name].deleted is not None |
98 | CephadmServe(cephadm)._check_daemons() | |
f91f0fd5 | 99 | CephadmServe(cephadm)._apply_all_services() |
f67539c2 TL |
100 | assert cephadm.spec_store[srv_name].deleted |
101 | unmanaged = cephadm.spec_store[srv_name].spec.unmanaged | |
102 | CephadmServe(cephadm)._purge_deleted_services() | |
103 | if not unmanaged: # cause then we're not deleting daemons | |
104 | assert srv_name not in cephadm.spec_store, f'{cephadm.spec_store[srv_name]!r}' | |
f6b5b4d7 TL |
105 | |
106 | ||
107 | @contextmanager | |
f67539c2 TL |
108 | def with_service(cephadm_module: CephadmOrchestrator, spec: ServiceSpec, meth=None, host: str = '') -> Iterator[List[str]]: |
109 | if spec.placement.is_empty() and host: | |
f6b5b4d7 | 110 | spec.placement = PlacementSpec(hosts=[host], count=1) |
f67539c2 TL |
111 | if meth is not None: |
112 | c = meth(cephadm_module, spec) | |
113 | assert wait(cephadm_module, c) == f'Scheduled {spec.service_name()} update...' | |
114 | else: | |
115 | c = cephadm_module.apply([spec]) | |
116 | assert wait(cephadm_module, c) == [f'Scheduled {spec.service_name()} update...'] | |
117 | ||
f6b5b4d7 TL |
118 | specs = [d.spec for d in wait(cephadm_module, cephadm_module.describe_service())] |
119 | assert spec in specs | |
120 | ||
f91f0fd5 | 121 | CephadmServe(cephadm_module)._apply_all_services() |
f6b5b4d7 TL |
122 | |
123 | dds = wait(cephadm_module, cephadm_module.list_daemons()) | |
f91f0fd5 | 124 | own_dds = [dd for dd in dds if dd.service_name() == spec.service_name()] |
f67539c2 TL |
125 | if host: |
126 | assert own_dds | |
f6b5b4d7 | 127 | |
f91f0fd5 | 128 | yield [dd.name() for dd in own_dds] |
f6b5b4d7 | 129 | |
f91f0fd5 | 130 | assert_rm_service(cephadm_module, spec.service_name()) |
f67539c2 TL |
131 | |
132 | ||
133 | def _deploy_cephadm_binary(host): | |
134 | def foo(*args, **kwargs): | |
135 | return True | |
136 | return foo |