]>
git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/cephadm/services/nfs.py
4 from typing
import Dict
, Optional
, Tuple
, Any
, List
, cast
6 from ceph
.deployment
.service_spec
import NFSServiceSpec
9 from orchestrator
import OrchestratorError
14 from .cephadmservice
import CephadmService
15 logger
= logging
.getLogger(__name__
)
18 class NFSService(CephadmService
):
19 def _generate_nfs_config(self
, daemon_type
, daemon_id
, host
):
20 # type: (str, str, str) -> Tuple[Dict[str, Any], List[str]]
21 deps
= [] # type: List[str]
23 # find the matching NFSServiceSpec
24 # TODO: find the spec and pass via _create_daemon instead ??
25 dd
= orchestrator
.DaemonDescription()
26 dd
.daemon_type
= daemon_type
27 dd
.daemon_id
= daemon_id
30 service_name
= dd
.service_name()
31 specs
= self
.mgr
.spec_store
.find(service_name
)
34 raise OrchestratorError('Cannot find service spec %s' % (service_name
))
36 raise OrchestratorError('Found multiple service specs for %s' % (service_name
))
38 # cast to keep mypy happy
39 spec
= cast(NFSServiceSpec
, specs
[0])
41 nfs
= NFSGanesha(self
.mgr
, daemon_id
, spec
)
44 entity
= nfs
.get_keyring_entity()
45 keyring
= nfs
.get_or_create_keyring(entity
=entity
)
47 # update the caps after get-or-create, the keyring might already exist!
48 nfs
.update_keyring_caps(entity
=entity
)
50 # create the rados config object
51 nfs
.create_rados_config_obj()
53 # generate the cephadm config
54 cephadm_config
= nfs
.get_cephadm_config()
55 cephadm_config
.update(
56 self
.mgr
._get
_config
_and
_keyring
(
57 daemon_type
, daemon_id
,
60 return cephadm_config
, deps
62 def config(self
, spec
):
63 self
.mgr
._check
_pool
_exists
(spec
.pool
, spec
.service_name())
64 logger
.info('Saving service %s spec with placement %s' % (
65 spec
.service_name(), spec
.placement
.pretty_str()))
66 self
.mgr
.spec_store
.save(spec
)
68 def create(self
, daemon_id
, host
, spec
):
69 logger
.info('Create daemon %s on host %s with spec %s' % (
70 daemon_id
, host
, spec
))
71 return self
.mgr
._create
_daemon
('nfs', daemon_id
, host
)
74 class NFSGanesha(object):
79 # type: (cephadm.CephadmOrchestrator, str, NFSServiceSpec) -> None
80 assert spec
.service_id
and daemon_id
.startswith(spec
.service_id
)
82 self
.daemon_id
= daemon_id
85 def get_daemon_name(self
):
87 return '%s.%s' % (self
.spec
.service_type
, self
.daemon_id
)
89 def get_rados_user(self
):
91 return '%s.%s' % (self
.spec
.service_type
, self
.daemon_id
)
93 def get_keyring_entity(self
):
95 return utils
.name_to_config_section(self
.get_rados_user())
97 def get_or_create_keyring(self
, entity
=None):
98 # type: (Optional[str]) -> str
100 entity
= self
.get_keyring_entity()
102 logger
.info('Create keyring: %s' % entity
)
103 ret
, keyring
, err
= self
.mgr
.mon_command({
104 'prefix': 'auth get-or-create',
109 raise OrchestratorError(
110 'Unable to create keyring %s: %s %s' \
111 % (entity
, ret
, err
))
114 def update_keyring_caps(self
, entity
=None):
115 # type: (Optional[str]) -> None
117 entity
= self
.get_keyring_entity()
119 osd_caps
='allow rw pool=%s' % (self
.spec
.pool
)
120 if self
.spec
.namespace
:
121 osd_caps
='%s namespace=%s' % (osd_caps
, self
.spec
.namespace
)
123 logger
.info('Updating keyring caps: %s' % entity
)
124 ret
, out
, err
= self
.mgr
.mon_command({
125 'prefix': 'auth caps',
127 'caps': ['mon', 'allow r',
132 raise OrchestratorError(
133 'Unable to update keyring caps %s: %s %s' \
134 % (entity
, ret
, err
))
136 def create_rados_config_obj(self
, clobber
=False):
137 # type: (Optional[bool]) -> None
138 obj
= self
.spec
.rados_config_name()
140 with self
.mgr
.rados
.open_ioctx(self
.spec
.pool
) as ioctx
:
141 if self
.spec
.namespace
:
142 ioctx
.set_namespace(self
.spec
.namespace
)
147 except rados
.ObjectNotFound
as e
:
150 if exists
and not clobber
:
151 # Assume an existing config
152 logger
.info('Rados config object exists: %s' % obj
)
154 # Create an empty config object
155 logger
.info('Creating rados config object: %s' % obj
)
156 ioctx
.write_full(obj
, ''.encode('utf-8'))
158 def get_ganesha_conf(self
):
160 context
= dict(user
=self
.get_rados_user(),
161 nodeid
=self
.get_daemon_name(),
163 namespace
=self
.spec
.namespace
if self
.spec
.namespace
else '',
164 url
=self
.spec
.rados_config_location())
165 return self
.mgr
.template
.render('services/nfs/ganesha.conf.j2', context
)
167 def get_cephadm_config(self
):
169 config
= {'pool' : self
.spec
.pool
} # type: Dict
170 if self
.spec
.namespace
:
171 config
['namespace'] = self
.spec
.namespace
172 config
['userid'] = self
.get_rados_user()
173 config
['extra_args'] = ['-N', 'NIV_EVENT']
175 'ganesha.conf' : self
.get_ganesha_conf(),
177 logger
.debug('Generated cephadm config-json: %s' % config
)