]>
git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/cephadm/services/nfs.py
e5773bfb1942304b7b8661d1daa17035450efb27
3 from typing
import Dict
, Tuple
, Any
, List
, cast
, Optional
5 from mgr_module
import HandleCommandResult
7 from ceph
.deployment
.service_spec
import NFSServiceSpec
10 from orchestrator
import DaemonDescription
12 from cephadm
.services
.cephadmservice
import AuthEntity
, CephadmDaemonDeploySpec
, CephService
14 logger
= logging
.getLogger(__name__
)
17 class NFSService(CephService
):
20 def config(self
, spec
: NFSServiceSpec
, daemon_id
: str) -> None: # type: ignore
21 assert self
.TYPE
== spec
.service_type
23 self
.mgr
._check
_pool
_exists
(spec
.pool
, spec
.service_name())
25 def prepare_create(self
, daemon_spec
: CephadmDaemonDeploySpec
) -> CephadmDaemonDeploySpec
:
26 assert self
.TYPE
== daemon_spec
.daemon_type
27 daemon_spec
.final_config
, daemon_spec
.deps
= self
.generate_config(daemon_spec
)
30 def generate_config(self
, daemon_spec
: CephadmDaemonDeploySpec
) -> Tuple
[Dict
[str, Any
], List
[str]]:
31 assert self
.TYPE
== daemon_spec
.daemon_type
33 daemon_type
= daemon_spec
.daemon_type
34 daemon_id
= daemon_spec
.daemon_id
35 host
= daemon_spec
.host
36 spec
= cast(NFSServiceSpec
, self
.mgr
.spec_store
[daemon_spec
.service_name
].spec
)
40 # create the RADOS recovery pool keyring
41 rados_user
= f
'{daemon_type}.{daemon_id}'
42 rados_keyring
= self
.create_keyring(daemon_spec
)
44 # create the rados config object
45 self
.create_rados_config_obj(spec
)
47 # create the RGW keyring
48 rgw_user
= f
'{rados_user}-rgw'
49 rgw_keyring
= self
.create_rgw_keyring(daemon_spec
)
51 # generate the ganesha config
52 def get_ganesha_conf() -> str:
53 context
= dict(user
=rados_user
,
54 nodeid
=daemon_spec
.name(),
56 namespace
=spec
.namespace
if spec
.namespace
else '',
58 url
=spec
.rados_config_location())
59 return self
.mgr
.template
.render('services/nfs/ganesha.conf.j2', context
)
61 # generate the cephadm config json
62 def get_cephadm_config() -> Dict
[str, Any
]:
63 config
: Dict
[str, Any
] = {}
64 config
['pool'] = spec
.pool
66 config
['namespace'] = spec
.namespace
67 config
['userid'] = rados_user
68 config
['extra_args'] = ['-N', 'NIV_EVENT']
70 'ganesha.conf': get_ganesha_conf(),
73 self
.get_config_and_keyring(
74 daemon_type
, daemon_id
,
75 keyring
=rados_keyring
,
82 'keyring': rgw_keyring
,
84 logger
.debug('Generated cephadm config-json: %s' % config
)
87 return get_cephadm_config(), deps
89 def create_rados_config_obj(self
,
91 clobber
: bool = False) -> None:
92 with self
.mgr
.rados
.open_ioctx(spec
.pool
) as ioctx
:
94 ioctx
.set_namespace(spec
.namespace
)
96 obj
= spec
.rados_config_name()
100 except rados
.ObjectNotFound
:
103 if exists
and not clobber
:
104 # Assume an existing config
105 logger
.info('Rados config object exists: %s' % obj
)
107 # Create an empty config object
108 logger
.info('Creating rados config object: %s' % obj
)
109 ioctx
.write_full(obj
, ''.encode('utf-8'))
111 def create_keyring(self
, daemon_spec
: CephadmDaemonDeploySpec
) -> str:
112 daemon_id
= daemon_spec
.daemon_id
113 spec
= cast(NFSServiceSpec
, self
.mgr
.spec_store
[daemon_spec
.service_name
].spec
)
114 entity
: AuthEntity
= self
.get_auth_entity(daemon_id
)
116 osd_caps
= 'allow rw pool=%s' % (spec
.pool
)
118 osd_caps
= '%s namespace=%s' % (osd_caps
, spec
.namespace
)
120 logger
.info('Creating key for %s' % entity
)
121 keyring
= self
.get_keyring_with_caps(entity
,
127 def create_rgw_keyring(self
, daemon_spec
: CephadmDaemonDeploySpec
) -> str:
128 daemon_id
= daemon_spec
.daemon_id
129 entity
: AuthEntity
= self
.get_auth_entity(f
'{daemon_id}-rgw')
131 logger
.info('Creating key for %s' % entity
)
132 keyring
= self
.get_keyring_with_caps(entity
,
134 'osd', 'allow rwx tag rgw *=*'])
138 def remove_rgw_keyring(self
, daemon
: DaemonDescription
) -> None:
139 assert daemon
.daemon_id
is not None
140 daemon_id
: str = daemon
.daemon_id
141 entity
: AuthEntity
= self
.get_auth_entity(f
'{daemon_id}-rgw')
143 logger
.info(f
'Removing key for {entity}')
144 ret
, out
, err
= self
.mgr
.check_mon_command({
149 def post_remove(self
, daemon
: DaemonDescription
) -> None:
150 super().post_remove(daemon
)
151 self
.remove_rgw_keyring(daemon
)
154 daemon_ids
: List
[str],
156 known
: Optional
[List
[str]] = None) -> HandleCommandResult
:
157 # if only 1 nfs, alert user (this is not passable with --force)
158 warn
, warn_message
= self
._enough
_daemons
_to
_stop
(self
.TYPE
, daemon_ids
, 'NFS', 1, True)
160 return HandleCommandResult(-errno
.EBUSY
, '', warn_message
)
162 # if reached here, there is > 1 nfs daemon.
164 return HandleCommandResult(0, warn_message
, '')
166 # if reached here, > 1 nfs daemon and no force flag.
168 warn_message
= "WARNING: Removing NFS daemons can cause clients to lose connectivity. "
169 return HandleCommandResult(-errno
.EBUSY
, '', warn_message
)