1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
import errno
import logging
import json
from typing import List, cast, Optional
from mgr_module import HandleCommandResult
from ceph.deployment.service_spec import NvmeofServiceSpec
from orchestrator import DaemonDescription, DaemonDescriptionStatus
from .cephadmservice import CephadmDaemonDeploySpec, CephService
from .. import utils
logger = logging.getLogger(__name__)
class NvmeofService(CephService):
TYPE = 'nvmeof'
def config(self, spec: NvmeofServiceSpec) -> None: # type: ignore
assert self.TYPE == spec.service_type
assert spec.pool
self.mgr._check_pool_exists(spec.pool, spec.service_name())
def prepare_create(self, daemon_spec: CephadmDaemonDeploySpec) -> CephadmDaemonDeploySpec:
assert self.TYPE == daemon_spec.daemon_type
spec = cast(NvmeofServiceSpec, self.mgr.spec_store[daemon_spec.service_name].spec)
nvmeof_gw_id = daemon_spec.daemon_id
host_ip = self.mgr.inventory.get_addr(daemon_spec.host)
keyring = self.get_keyring_with_caps(self.get_auth_entity(nvmeof_gw_id),
['mon', 'profile rbd',
'osd', 'allow all tag rbd *=*'])
# TODO: check if we can force jinja2 to generate dicts with double quotes instead of using json.dumps
transport_tcp_options = json.dumps(spec.transport_tcp_options) if spec.transport_tcp_options else None
name = '{}.{}'.format(utils.name_to_config_section('nvmeof'), nvmeof_gw_id)
rados_id = name[len('client.'):] if name.startswith('client.') else name
context = {
'spec': spec,
'name': name,
'addr': host_ip,
'port': spec.port,
'log_level': 'WARN',
'rpc_socket': '/var/tmp/spdk.sock',
'transport_tcp_options': transport_tcp_options,
'rados_id': rados_id
}
gw_conf = self.mgr.template.render('services/nvmeof/ceph-nvmeof.conf.j2', context)
daemon_spec.keyring = keyring
daemon_spec.extra_files = {'ceph-nvmeof.conf': gw_conf}
daemon_spec.final_config, daemon_spec.deps = self.generate_config(daemon_spec)
daemon_spec.deps = []
return daemon_spec
def config_dashboard(self, daemon_descrs: List[DaemonDescription]) -> None:
# TODO: what integration do we need with the dashboard?
pass
def ok_to_stop(self,
daemon_ids: List[str],
force: bool = False,
known: Optional[List[str]] = None) -> HandleCommandResult:
# if only 1 nvmeof, alert user (this is not passable with --force)
warn, warn_message = self._enough_daemons_to_stop(self.TYPE, daemon_ids, 'Nvmeof', 1, True)
if warn:
return HandleCommandResult(-errno.EBUSY, '', warn_message)
# if reached here, there is > 1 nvmeof daemon. make sure none are down
warn_message = ('ALERT: 1 nvmeof daemon is already down. Please bring it back up before stopping this one')
nvmeof_daemons = self.mgr.cache.get_daemons_by_type(self.TYPE)
for i in nvmeof_daemons:
if i.status != DaemonDescriptionStatus.running:
return HandleCommandResult(-errno.EBUSY, '', warn_message)
names = [f'{self.TYPE}.{d_id}' for d_id in daemon_ids]
warn_message = f'It is presumed safe to stop {names}'
return HandleCommandResult(0, warn_message, '')
def post_remove(self, daemon: DaemonDescription, is_failed_deploy: bool) -> None:
"""
Called after the daemon is removed.
"""
logger.debug(f'Post remove daemon {self.TYPE}.{daemon.daemon_id}')
# TODO: remove config for dashboard nvmeof gateways if any
# and any certificates being used for mTLS
def purge(self, service_name: str) -> None:
"""Removes configuration
"""
# TODO: what should we purge in this case (if any)?
pass
|