]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/pybind/mgr/cephadm/services/nfs.py
import 15.2.5
[ceph.git] / ceph / src / pybind / mgr / cephadm / services / nfs.py
index 4c7f79133491a6b08fec8cf36fba9a651d40e51b..6824053ff20bb61afbb62256431c54f30fc39b04 100644 (file)
@@ -1,28 +1,35 @@
 import logging
+from typing import TYPE_CHECKING, Dict, Optional, Tuple, Any, List, Set, cast
 
+from ceph.deployment.service_spec import NFSServiceSpec
 import rados
-from typing import Dict, Optional, Tuple, Any, List, cast
 
-from ceph.deployment.service_spec import NFSServiceSpec
+from orchestrator import OrchestratorError, DaemonDescription
 
-import orchestrator
-from orchestrator import OrchestratorError
+from cephadm import utils
+from cephadm.services.cephadmservice import CephadmService, CephadmDaemonSpec
 
-import cephadm
-from .. import utils
+if TYPE_CHECKING:
+    from cephadm.module import CephadmOrchestrator
 
-from .cephadmservice import CephadmService
 logger = logging.getLogger(__name__)
 
 
 class NFSService(CephadmService):
-    def _generate_nfs_config(self, daemon_type, daemon_id, host):
-        # type: (str, str, str) -> Tuple[Dict[str, Any], List[str]]
-        deps = []  # type: List[str]
+    TYPE = 'nfs'
+
+    def generate_config(self, daemon_spec: CephadmDaemonSpec) -> Tuple[Dict[str, Any], List[str]]:
+        assert self.TYPE == daemon_spec.daemon_type
+
+        daemon_type = daemon_spec.daemon_type
+        daemon_id = daemon_spec.daemon_id
+        host = daemon_spec.host
+
+        deps: List[str] = []
 
         # find the matching NFSServiceSpec
         # TODO: find the spec and pass via _create_daemon instead ??
-        dd = orchestrator.DaemonDescription()
+        dd = DaemonDescription()
         dd.daemon_type = daemon_type
         dd.daemon_id = daemon_id
         dd.hostname = host
@@ -53,49 +60,84 @@ class NFSService(CephadmService):
         # generate the cephadm config
         cephadm_config = nfs.get_cephadm_config()
         cephadm_config.update(
-                self.mgr._get_config_and_keyring(
-                    daemon_type, daemon_id,
-                    keyring=keyring))
+            self.mgr._get_config_and_keyring(
+                daemon_type, daemon_id,
+                keyring=keyring,
+                host=host
+            )
+        )
 
         return cephadm_config, deps
 
-    def config(self, spec):
+    def config(self, spec: NFSServiceSpec) -> None:
+        assert self.TYPE == spec.service_type
         self.mgr._check_pool_exists(spec.pool, spec.service_name())
+
         logger.info('Saving service %s spec with placement %s' % (
             spec.service_name(), spec.placement.pretty_str()))
         self.mgr.spec_store.save(spec)
 
-    def create(self, daemon_id, host, spec):
+    def create(self, daemon_spec: CephadmDaemonSpec[NFSServiceSpec]) -> str:
+        assert self.TYPE == daemon_spec.daemon_type
+        assert daemon_spec.spec
+
+        daemon_id = daemon_spec.daemon_id
+        host = daemon_spec.host
+        spec = daemon_spec.spec
+
         logger.info('Create daemon %s on host %s with spec %s' % (
             daemon_id, host, spec))
-        return self.mgr._create_daemon('nfs', daemon_id, host)
+        return self.mgr._create_daemon(daemon_spec)
+
+    def config_dashboard(self, daemon_descrs: List[DaemonDescription]):
+
+        def get_set_cmd_dicts(out: str) -> List[dict]:
+            locations: Set[str] = set()
+            for dd in daemon_descrs:
+                spec = cast(NFSServiceSpec,
+                            self.mgr.spec_store.specs.get(dd.service_name(), None))
+                if not spec or not spec.service_id:
+                    logger.warning('No ServiceSpec or service_id found for %s', dd)
+                    continue
+                location = '{}:{}'.format(spec.service_id, spec.pool)
+                if spec.namespace:
+                    location = '{}/{}'.format(location, spec.namespace)
+                locations.add(location)
+            new_value = ','.join(locations)
+            if new_value and new_value != out:
+                return [{'prefix': 'dashboard set-ganesha-clusters-rados-pool-namespace',
+                         'value': new_value}]
+            return []
+
+        self._check_and_set_dashboard(
+            service_name='Ganesha',
+            get_cmd='dashboard get-ganesha-clusters-rados-pool-namespace',
+            get_set_cmd_dicts=get_set_cmd_dicts
+        )
 
 
 class NFSGanesha(object):
     def __init__(self,
-                 mgr,
-                 daemon_id,
-                 spec):
-        # type: (cephadm.CephadmOrchestrator, str, NFSServiceSpec) -> None
+                 mgr: "CephadmOrchestrator",
+                 daemon_id: str,
+                 spec: NFSServiceSpec) -> None:
         assert spec.service_id and daemon_id.startswith(spec.service_id)
+        mgr._check_pool_exists(spec.pool, spec.service_name())
+
         self.mgr = mgr
         self.daemon_id = daemon_id
         self.spec = spec
 
-    def get_daemon_name(self):
-        # type: () -> str
+    def get_daemon_name(self) -> str:
         return '%s.%s' % (self.spec.service_type, self.daemon_id)
 
-    def get_rados_user(self):
-        # type: () -> str
+    def get_rados_user(self) -> str:
         return '%s.%s' % (self.spec.service_type, self.daemon_id)
 
-    def get_keyring_entity(self):
-        # type: () -> str
+    def get_keyring_entity(self) -> str:
         return utils.name_to_config_section(self.get_rados_user())
 
-    def get_or_create_keyring(self, entity=None):
-        # type: (Optional[str]) -> str
+    def get_or_create_keyring(self, entity: Optional[str] = None) -> str:
         if not entity:
             entity = self.get_keyring_entity()
 
@@ -107,18 +149,17 @@ class NFSGanesha(object):
 
         if ret != 0:
             raise OrchestratorError(
-                    'Unable to create keyring %s: %s %s' \
-                            % (entity, ret, err))
+                'Unable to create keyring %s: %s %s'
+                % (entity, ret, err))
         return keyring
 
-    def update_keyring_caps(self, entity=None):
-        # type: (Optional[str]) -> None
+    def update_keyring_caps(self, entity: Optional[str] = None) -> None:
         if not entity:
             entity = self.get_keyring_entity()
 
-        osd_caps='allow rw pool=%s' % (self.spec.pool)
+        osd_caps = 'allow rw pool=%s' % (self.spec.pool)
         if self.spec.namespace:
-            osd_caps='%s namespace=%s' % (osd_caps, self.spec.namespace)
+            osd_caps = '%s namespace=%s' % (osd_caps, self.spec.namespace)
 
         logger.info('Updating keyring caps: %s' % entity)
         ret, out, err = self.mgr.mon_command({
@@ -130,17 +171,15 @@ class NFSGanesha(object):
 
         if ret != 0:
             raise OrchestratorError(
-                    'Unable to update keyring caps %s: %s %s' \
-                            % (entity, ret, err))
-
-    def create_rados_config_obj(self, clobber=False):
-        # type: (Optional[bool]) -> None
-        obj = self.spec.rados_config_name()
+                'Unable to update keyring caps %s: %s %s'
+                % (entity, ret, err))
 
+    def create_rados_config_obj(self, clobber: Optional[bool] = False) -> None:
         with self.mgr.rados.open_ioctx(self.spec.pool) as ioctx:
             if self.spec.namespace:
                 ioctx.set_namespace(self.spec.namespace)
 
+            obj = self.spec.rados_config_name()
             exists = True
             try:
                 ioctx.stat(obj)
@@ -155,8 +194,7 @@ class NFSGanesha(object):
                 logger.info('Creating rados config object: %s' % obj)
                 ioctx.write_full(obj, ''.encode('utf-8'))
 
-    def get_ganesha_conf(self):
-        # type: () -> str
+    def get_ganesha_conf(self) -> str:
         context = dict(user=self.get_rados_user(),
                        nodeid=self.get_daemon_name(),
                        pool=self.spec.pool,
@@ -164,15 +202,14 @@ class NFSGanesha(object):
                        url=self.spec.rados_config_location())
         return self.mgr.template.render('services/nfs/ganesha.conf.j2', context)
 
-    def get_cephadm_config(self):
-        # type: () -> Dict
-        config = {'pool' : self.spec.pool} # type: Dict
+    def get_cephadm_config(self) -> Dict[str, Any]:
+        config: Dict[str, Any] = {'pool': self.spec.pool}
         if self.spec.namespace:
             config['namespace'] = self.spec.namespace
         config['userid'] = self.get_rados_user()
         config['extra_args'] = ['-N', 'NIV_EVENT']
         config['files'] = {
-            'ganesha.conf' : self.get_ganesha_conf(),
+            'ganesha.conf': self.get_ganesha_conf(),
         }
         logger.debug('Generated cephadm config-json: %s' % config)
         return config