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