]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/cephadm/tests/test_services.py
46dfbab4d973fc0c14f3052cee4de744a7bdf101
[ceph.git] / ceph / src / pybind / mgr / cephadm / tests / test_services.py
1 import pytest
2
3 from unittest.mock import MagicMock, call, patch
4
5 from cephadm.services.cephadmservice import MonService, MgrService, MdsService, RgwService, \
6 RbdMirrorService, CrashService, CephadmDaemonDeploySpec
7 from cephadm.services.iscsi import IscsiService
8 from cephadm.services.nfs import NFSService
9 from cephadm.services.osd import OSDService
10 from cephadm.services.monitoring import GrafanaService, AlertmanagerService, PrometheusService, \
11 NodeExporterService
12 from cephadm.services.exporter import CephadmExporter
13 from ceph.deployment.service_spec import IscsiServiceSpec
14
15 from orchestrator import OrchestratorError
16 from orchestrator._interface import DaemonDescription
17
18
19 class FakeMgr:
20 def __init__(self):
21 self.config = ''
22 self.check_mon_command = MagicMock(side_effect=self._check_mon_command)
23 self.mon_command = MagicMock(side_effect=self._check_mon_command)
24 self.template = MagicMock()
25 self.log = MagicMock()
26
27 def _check_mon_command(self, cmd_dict, inbuf=None):
28 prefix = cmd_dict.get('prefix')
29 if prefix == 'get-cmd':
30 return 0, self.config, ''
31 if prefix == 'set-cmd':
32 self.config = cmd_dict.get('value')
33 return 0, 'value set', ''
34 return -1, '', 'error'
35
36 def get_minimal_ceph_conf(self) -> str:
37 return ''
38
39
40 class TestCephadmService:
41 def test_set_service_url_on_dashboard(self):
42 # pylint: disable=protected-access
43 mgr = FakeMgr()
44 service_url = 'http://svc:1000'
45 service = GrafanaService(mgr)
46 service._set_service_url_on_dashboard('svc', 'get-cmd', 'set-cmd', service_url)
47 assert mgr.config == service_url
48
49 # set-cmd should not be called if value doesn't change
50 mgr.check_mon_command.reset_mock()
51 service._set_service_url_on_dashboard('svc', 'get-cmd', 'set-cmd', service_url)
52 mgr.check_mon_command.assert_called_once_with({'prefix': 'get-cmd'})
53
54 def _get_services(self, mgr):
55 # services:
56 osd_service = OSDService(mgr)
57 nfs_service = NFSService(mgr)
58 mon_service = MonService(mgr)
59 mgr_service = MgrService(mgr)
60 mds_service = MdsService(mgr)
61 rgw_service = RgwService(mgr)
62 rbd_mirror_service = RbdMirrorService(mgr)
63 grafana_service = GrafanaService(mgr)
64 alertmanager_service = AlertmanagerService(mgr)
65 prometheus_service = PrometheusService(mgr)
66 node_exporter_service = NodeExporterService(mgr)
67 crash_service = CrashService(mgr)
68 iscsi_service = IscsiService(mgr)
69 cephadm_exporter_service = CephadmExporter(mgr)
70 cephadm_services = {
71 'mon': mon_service,
72 'mgr': mgr_service,
73 'osd': osd_service,
74 'mds': mds_service,
75 'rgw': rgw_service,
76 'rbd-mirror': rbd_mirror_service,
77 'nfs': nfs_service,
78 'grafana': grafana_service,
79 'alertmanager': alertmanager_service,
80 'prometheus': prometheus_service,
81 'node-exporter': node_exporter_service,
82 'crash': crash_service,
83 'iscsi': iscsi_service,
84 'cephadm-exporter': cephadm_exporter_service,
85 }
86 return cephadm_services
87
88 def test_get_auth_entity(self):
89 mgr = FakeMgr()
90 cephadm_services = self._get_services(mgr)
91
92 for daemon_type in ['rgw', 'rbd-mirror', 'nfs', "iscsi"]:
93 assert "client.%s.id1" % (daemon_type) == \
94 cephadm_services[daemon_type].get_auth_entity("id1", "host")
95 assert "client.%s.id1" % (daemon_type) == \
96 cephadm_services[daemon_type].get_auth_entity("id1", "")
97 assert "client.%s.id1" % (daemon_type) == \
98 cephadm_services[daemon_type].get_auth_entity("id1")
99
100 assert "client.crash.host" == \
101 cephadm_services["crash"].get_auth_entity("id1", "host")
102 with pytest.raises(OrchestratorError):
103 cephadm_services["crash"].get_auth_entity("id1", "")
104 cephadm_services["crash"].get_auth_entity("id1")
105
106 assert "mon." == cephadm_services["mon"].get_auth_entity("id1", "host")
107 assert "mon." == cephadm_services["mon"].get_auth_entity("id1", "")
108 assert "mon." == cephadm_services["mon"].get_auth_entity("id1")
109
110 assert "mgr.id1" == cephadm_services["mgr"].get_auth_entity("id1", "host")
111 assert "mgr.id1" == cephadm_services["mgr"].get_auth_entity("id1", "")
112 assert "mgr.id1" == cephadm_services["mgr"].get_auth_entity("id1")
113
114 for daemon_type in ["osd", "mds"]:
115 assert "%s.id1" % daemon_type == \
116 cephadm_services[daemon_type].get_auth_entity("id1", "host")
117 assert "%s.id1" % daemon_type == \
118 cephadm_services[daemon_type].get_auth_entity("id1", "")
119 assert "%s.id1" % daemon_type == \
120 cephadm_services[daemon_type].get_auth_entity("id1")
121
122 # services based on CephadmService shouldn't have get_auth_entity
123 with pytest.raises(AttributeError):
124 for daemon_type in ['grafana', 'alertmanager', 'prometheus', 'node-exporter', 'cephadm-exporter']:
125 cephadm_services[daemon_type].get_auth_entity("id1", "host")
126 cephadm_services[daemon_type].get_auth_entity("id1", "")
127 cephadm_services[daemon_type].get_auth_entity("id1")
128
129
130 class TestISCSIService:
131
132 mgr = FakeMgr()
133 iscsi_service = IscsiService(mgr)
134
135 iscsi_spec = IscsiServiceSpec(service_type='iscsi', service_id="a")
136 iscsi_spec.daemon_type = "iscsi"
137 iscsi_spec.daemon_id = "a"
138 iscsi_spec.spec = MagicMock()
139 iscsi_spec.spec.daemon_type = "iscsi"
140 iscsi_spec.spec.ssl_cert = ''
141 iscsi_spec.api_user = "user"
142 iscsi_spec.api_password = "password"
143 iscsi_spec.api_port = 5000
144 iscsi_spec.api_secure = False
145 iscsi_spec.ssl_cert = "cert"
146 iscsi_spec.ssl_key = "key"
147
148 mgr.spec_store = MagicMock()
149 mgr.spec_store.all_specs.get.return_value = iscsi_spec
150
151 def test_iscsi_client_caps(self):
152
153 iscsi_daemon_spec = CephadmDaemonDeploySpec(
154 host='host', daemon_id='a', service_name=self.iscsi_spec.service_name())
155
156 self.iscsi_service.prepare_create(iscsi_daemon_spec)
157
158 expected_caps = ['mon',
159 'profile rbd, allow command "osd blocklist", allow command "config-key get" with "key" prefix "iscsi/"',
160 'mgr', 'allow command "service status"',
161 'osd', 'allow rwx']
162
163 expected_call = call({'prefix': 'auth get-or-create',
164 'entity': 'client.iscsi.a',
165 'caps': expected_caps})
166 expected_call2 = call({'prefix': 'auth caps',
167 'entity': 'client.iscsi.a',
168 'caps': expected_caps})
169
170 assert expected_call in self.mgr.mon_command.mock_calls
171 assert expected_call2 in self.mgr.mon_command.mock_calls
172
173 @patch('cephadm.utils.resolve_ip')
174 def test_iscsi_dashboard_config(self, mock_resolve_ip):
175
176 self.mgr.check_mon_command = MagicMock()
177 self.mgr.check_mon_command.return_value = ('', '{"gateways": {}}', '')
178
179 # Case 1: use IPV4 address
180 id1 = DaemonDescription(daemon_type='iscsi', hostname="testhost1",
181 daemon_id="a", ip='192.168.1.1')
182 daemon_list = [id1]
183 mock_resolve_ip.return_value = '192.168.1.1'
184
185 self.iscsi_service.config_dashboard(daemon_list)
186
187 dashboard_expected_call = call({'prefix': 'dashboard iscsi-gateway-add',
188 'name': 'testhost1'},
189 'http://user:password@192.168.1.1:5000')
190
191 assert dashboard_expected_call in self.mgr.check_mon_command.mock_calls
192
193 # Case 2: use IPV6 address
194 self.mgr.check_mon_command.reset_mock()
195
196 id1 = DaemonDescription(daemon_type='iscsi', hostname="testhost1",
197 daemon_id="a", ip='FEDC:BA98:7654:3210:FEDC:BA98:7654:3210')
198 mock_resolve_ip.return_value = 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210'
199
200 self.iscsi_service.config_dashboard(daemon_list)
201
202 dashboard_expected_call = call({'prefix': 'dashboard iscsi-gateway-add',
203 'name': 'testhost1'},
204 'http://user:password@[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:5000')
205
206 assert dashboard_expected_call in self.mgr.check_mon_command.mock_calls
207
208 # Case 3: IPV6 Address . Secure protocol
209 self.mgr.check_mon_command.reset_mock()
210
211 self.iscsi_spec.api_secure = True
212
213 self.iscsi_service.config_dashboard(daemon_list)
214
215 dashboard_expected_call = call({'prefix': 'dashboard iscsi-gateway-add',
216 'name': 'testhost1'},
217 'https://user:password@[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:5000')
218
219 assert dashboard_expected_call in self.mgr.check_mon_command.mock_calls