2 from typing
import TYPE_CHECKING
, List
4 from mgr_module
import MonCommandFailed
6 from ceph
.deployment
.service_spec
import ServiceSpec
, RGWSpec
7 from orchestrator
import OrchestratorError
, DaemonDescription
8 from cephadm
import utils
11 from cephadm
.module
import CephadmOrchestrator
13 logger
= logging
.getLogger(__name__
)
18 Base class for service types. Often providing a create() and config() fn.
20 def __init__(self
, mgr
: "CephadmOrchestrator"):
21 self
.mgr
: "CephadmOrchestrator" = mgr
23 def daemon_check_post(self
, daemon_descrs
: List
[DaemonDescription
]):
24 """The post actions needed to be done after daemons are checked"""
25 raise NotImplementedError()
27 def get_active_daemon(self
, daemon_descrs
: List
[DaemonDescription
]) -> DaemonDescription
:
28 raise NotImplementedError()
30 def _inventory_get_addr(self
, hostname
: str):
31 """Get a host's address with its hostname."""
32 return self
.mgr
.inventory
.get_addr(hostname
)
34 def _set_service_url_on_dashboard(self
,
39 """A helper to get and set service_url via Dashboard's MON command."""
41 _
, out
, _
= self
.mgr
.check_mon_command({
44 except MonCommandFailed
as e
:
45 logger
.warning('Failed to get service URL for %s: %s', service_name
, e
)
47 if out
.strip() != service_url
:
50 'Setting service URL %s for %s in the Dashboard', service_url
, service_name
)
51 _
, out
, _
= self
.mgr
.check_mon_command({
52 'prefix': set_mon_cmd
,
55 except MonCommandFailed
as e
:
56 logger
.warning('Failed to set service URL %s for %s in the Dashboard: %s',
57 service_url
, service_name
, e
)
60 class MonService(CephadmService
):
61 def create(self
, name
, host
, network
):
63 Create a new monitor on the given host.
66 ret
, keyring
, err
= self
.mgr
.check_mon_command({
71 extra_config
= '[mon.%s]\n' % name
73 # infer whether this is a CIDR network, addrvec, or plain IP
75 extra_config
+= 'public network = %s\n' % network
76 elif network
.startswith('[v') and network
.endswith(']'):
77 extra_config
+= 'public addrv = %s\n' % network
78 elif ':' not in network
:
79 extra_config
+= 'public addr = %s\n' % network
81 raise OrchestratorError('Must specify a CIDR network, ceph addrvec, or plain IP: \'%s\'' % network
)
83 # try to get the public_network from the config
84 ret
, network
, err
= self
.mgr
.check_mon_command({
85 'prefix': 'config get',
87 'key': 'public_network',
89 network
= network
.strip() # type: ignore
91 raise OrchestratorError('Must set public_network config option or specify a CIDR network, ceph addrvec, or plain IP')
92 if '/' not in network
:
93 raise OrchestratorError('public_network is set but does not look like a CIDR network: \'%s\'' % network
)
94 extra_config
+= 'public network = %s\n' % network
96 return self
.mgr
._create
_daemon
('mon', name
, host
,
98 extra_config
={'config': extra_config
})
101 class MgrService(CephadmService
):
102 def create(self
, mgr_id
, host
):
104 Create a new manager instance on a host.
107 ret
, keyring
, err
= self
.mgr
.check_mon_command({
108 'prefix': 'auth get-or-create',
109 'entity': 'mgr.%s' % mgr_id
,
110 'caps': ['mon', 'profile mgr',
115 return self
.mgr
._create
_daemon
('mgr', mgr_id
, host
, keyring
=keyring
)
118 class MdsService(CephadmService
):
119 def config(self
, spec
: ServiceSpec
):
120 # ensure mds_join_fs is set for these daemons
121 assert spec
.service_id
122 ret
, out
, err
= self
.mgr
.check_mon_command({
123 'prefix': 'config set',
124 'who': 'mds.' + spec
.service_id
,
125 'name': 'mds_join_fs',
126 'value': spec
.service_id
,
129 def create(self
, mds_id
, host
) -> str:
131 ret
, keyring
, err
= self
.mgr
.check_mon_command({
132 'prefix': 'auth get-or-create',
133 'entity': 'mds.' + mds_id
,
134 'caps': ['mon', 'profile mds',
138 return self
.mgr
._create
_daemon
('mds', mds_id
, host
, keyring
=keyring
)
141 class RgwService(CephadmService
):
142 def config(self
, spec
: RGWSpec
):
143 # ensure rgw_realm and rgw_zone is set for these daemons
144 ret
, out
, err
= self
.mgr
.check_mon_command({
145 'prefix': 'config set',
146 'who': f
"{utils.name_to_config_section('rgw')}.{spec.service_id}",
148 'value': spec
.rgw_zone
,
150 ret
, out
, err
= self
.mgr
.check_mon_command({
151 'prefix': 'config set',
152 'who': f
"{utils.name_to_config_section('rgw')}.{spec.rgw_realm}",
154 'value': spec
.rgw_realm
,
156 ret
, out
, err
= self
.mgr
.check_mon_command({
157 'prefix': 'config set',
158 'who': f
"{utils.name_to_config_section('rgw')}.{spec.service_id}",
159 'name': 'rgw_frontends',
160 'value': spec
.rgw_frontends_config_value(),
163 if spec
.rgw_frontend_ssl_certificate
:
164 if isinstance(spec
.rgw_frontend_ssl_certificate
, list):
165 cert_data
= '\n'.join(spec
.rgw_frontend_ssl_certificate
)
166 elif isinstance(spec
.rgw_frontend_ssl_certificate
, str):
167 cert_data
= spec
.rgw_frontend_ssl_certificate
169 raise OrchestratorError(
170 'Invalid rgw_frontend_ssl_certificate: %s'
171 % spec
.rgw_frontend_ssl_certificate
)
172 ret
, out
, err
= self
.mgr
.check_mon_command({
173 'prefix': 'config-key set',
174 'key': f
'rgw/cert/{spec.rgw_realm}/{spec.rgw_zone}.crt',
178 if spec
.rgw_frontend_ssl_key
:
179 if isinstance(spec
.rgw_frontend_ssl_key
, list):
180 key_data
= '\n'.join(spec
.rgw_frontend_ssl_key
)
181 elif isinstance(spec
.rgw_frontend_ssl_certificate
, str):
182 key_data
= spec
.rgw_frontend_ssl_key
184 raise OrchestratorError(
185 'Invalid rgw_frontend_ssl_key: %s'
186 % spec
.rgw_frontend_ssl_key
)
187 ret
, out
, err
= self
.mgr
.check_mon_command({
188 'prefix': 'config-key set',
189 'key': f
'rgw/cert/{spec.rgw_realm}/{spec.rgw_zone}.key',
193 logger
.info('Saving service %s spec with placement %s' % (
194 spec
.service_name(), spec
.placement
.pretty_str()))
195 self
.mgr
.spec_store
.save(spec
)
197 def create(self
, rgw_id
, host
) -> str:
198 ret
, keyring
, err
= self
.mgr
.check_mon_command({
199 'prefix': 'auth get-or-create',
200 'entity': f
"{utils.name_to_config_section('rgw')}.{rgw_id}",
201 'caps': ['mon', 'allow *',
205 return self
.mgr
._create
_daemon
('rgw', rgw_id
, host
, keyring
=keyring
)
208 class RbdMirrorService(CephadmService
):
209 def create(self
, daemon_id
, host
) -> str:
210 ret
, keyring
, err
= self
.mgr
.check_mon_command({
211 'prefix': 'auth get-or-create',
212 'entity': 'client.rbd-mirror.' + daemon_id
,
213 'caps': ['mon', 'profile rbd-mirror',
214 'osd', 'profile rbd'],
216 return self
.mgr
._create
_daemon
('rbd-mirror', daemon_id
, host
,
220 class CrashService(CephadmService
):
221 def create(self
, daemon_id
, host
) -> str:
222 ret
, keyring
, err
= self
.mgr
.check_mon_command({
223 'prefix': 'auth get-or-create',
224 'entity': 'client.crash.' + host
,
225 'caps': ['mon', 'profile crash',
226 'mgr', 'profile crash'],
228 return self
.mgr
._create
_daemon
('crash', daemon_id
, host
, keyring
=keyring
)