From: Michael Fritch Date: Sun, 2 Feb 2020 02:30:33 +0000 (-0700) Subject: cephadm: add ganasha.conf X-Git-Tag: v15.1.1~21^2~14 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=563990173c62aaae66f042308e1e9ffe9f90ac92;p=ceph.git cephadm: add ganasha.conf also allows for any arbitrary nfs conf to be deployed by adding items to the `files` dict of the config-json Signed-off-by: Michael Fritch --- diff --git a/src/cephadm/cephadm b/src/cephadm/cephadm index 15216f4d343a..38b82cb1233b 100755 --- a/src/cephadm/cephadm +++ b/src/cephadm/cephadm @@ -166,6 +166,34 @@ class NFSGanesha(object): entrypoint = '/usr/bin/ganesha.nfsd' daemon_args = ['-F', '-L', 'STDERR'] + required_files = ['ganesha.conf'] + + def __init__(self, + fsid, + daemon_id, + config_json): + # type: (str, Union[int, str], Dict) -> None + self.fsid = fsid + self.daemon_id = daemon_id + + def json_get(key, default=None, require=False): + if require and not key in config_json.keys(): + raise Error('{} missing from config-json'.format(key)) + return config_json.get(key, default) + + # config-json options + self.pool = json_get('pool', require=True) + self.namespace = json_get('namespace') + self.files = json_get('files', {}) + + # validate the supplied args + self.validate() + + @classmethod + def init(cls, fsid, daemon_id): + # type: (str, Union[int, str]) -> NFSGanesha + return cls(fsid, daemon_id, get_parm(args.config_json)) + @staticmethod def get_container_mounts(data_dir): # type: (str) -> Dict[str, str] @@ -173,8 +201,65 @@ class NFSGanesha(object): mounts[os.path.join(data_dir, 'config')] = '/etc/ceph/ceph.conf:z' # TODO: `ceph auth get-or-create` instead of admin keyring? mounts[os.path.join(data_dir, 'keyring')] = '/etc/ceph/keyring:z' + mounts[os.path.join(data_dir, 'etc/ganesha')] = '/etc/ganesha' return mounts + def validate(self): + # type () -> None + if not is_fsid(self.fsid): + raise Error('not an fsid: %s' % self.fsid) + if not self.daemon_id: + raise Error('invalid daemon_id: %s' % self.daemon_id) + if not self.image: + raise Error('invalid image: %s' % self.image) + + # check for the required files + if self.required_files: + for fname in self.required_files: + if fname not in self.files: + raise Error('required file missing from config-json: %s' % fname) + + def get_daemon_name(self): + # type: () -> str + return '%s.%s' % (self.daemon_type, self.daemon_id) + + def get_container_name(self, desc=None): + # type: (Optional[str]) -> str + cname = 'ceph-%s-%s' % (self.fsid, self.get_daemon_name()) + if desc: + cname = '%s-%s' % (cname, desc) + return cname + + def get_file_content(self, fname): + # type: (str) -> str + """Normalize the json file content into a string""" + content = self.files.get(fname) + if isinstance(content, list): + content = '\n'.join(content) + return content + + def create_daemon_dirs(self, data_dir, uid, gid): + # type: (str, int, int) -> None + """Create files under the container data dir""" + if not os.path.isdir(data_dir): + raise OSError('data_dir is not a directory: %s' % (data_dir)) + + logger.info('Creating ganesha config...') + + # create the ganesha conf dir + config_dir = os.path.join(data_dir, 'etc/ganesha') + makedirs(config_dir, uid, gid, 0o755) + + # populate files from the config-json + for fname in self.files: + config_file = os.path.join(config_dir, fname) + config_content = self.get_file_content(fname) + logger.info('Write file: %s' % (config_file)) + with open(config_file, 'w') as f: + os.fchown(f.fileno(), uid, gid) + os.fchmod(f.fileno(), 0o600) + f.write(config_content) + ################################## def get_supported_daemons(): @@ -1074,12 +1159,14 @@ def create_daemon_dirs(fsid, daemon_type, daemon_id, uid, gid, make_log_dir(fsid, uid=uid, gid=gid) if config: - with open(data_dir + '/config', 'w') as f: + config_path = os.path.join(data_dir, 'config') + with open(config_path, 'w') as f: os.fchown(f.fileno(), uid, gid) os.fchmod(f.fileno(), 0o600) f.write(config) if keyring: - with open(data_dir + '/keyring', 'w') as f: + keyring_path = os.path.join(data_dir, 'keyring') + with open(keyring_path, 'w') as f: os.fchmod(f.fileno(), 0o600) os.fchown(f.fileno(), uid, gid) f.write(keyring) @@ -1123,6 +1210,10 @@ def create_daemon_dirs(fsid, daemon_type, daemon_id, uid, gid, os.fchmod(f.fileno(), 0o600) f.write(content) + if daemon_type == NFSGanesha.daemon_type: + nfs_ganesha = NFSGanesha.init(fsid, daemon_id) + nfs_ganesha.create_daemon_dirs(data_dir, uid, gid) + def get_parm(option): # type: (str) -> Dict[str, str] diff --git a/src/cephadm/samples/nfs.json b/src/cephadm/samples/nfs.json new file mode 100644 index 000000000000..1b01489d8567 --- /dev/null +++ b/src/cephadm/samples/nfs.json @@ -0,0 +1,46 @@ +{ + "pool" : "nfs-ganesha", + "namespace" : "nfs-ns", + "files": { + "ganesha.conf": [ + "NFS_CORE_PARAM {", + " Enable_NLM = false;", + " Enable_RQUOTA = false;", + " Protocols = 4;", + "}", + "", + "CACHEINODE {", + " Dir_Chunk = 0;", + " NParts = 1;", + " Cache_Size = 1;", + "}", + "", + "EXPORT_DEFAULTS {", + " Attr_Expiration_Time = 0;", + "}", + "", + "NFSv4 {", + " Delegations = false;", + " RecoveryBackend = 'rados_cluster';", + " Minor_Versions = 1, 2;", + "}", + "", + "RADOS_KV {", + " ceph_conf = '/etc/ceph/ceph.conf';", + " userid = admin;", + " nodeid = nfs.a;", + " pool = 'nfs-ganesha';", + " namespace = 'nfs-ns';", + "}", + "", + "RADOS_URLS {", + " ceph_conf = '/etc/ceph/ceph.conf';", + " userid = admin;", + " watch_url = 'rados://nfs-ganesha/nfs-ns/conf-nfs.a';", + "}", + "", + "%url rados://nfs-ganesha/nfs-ns/conf-nfs.a", + "" + ] + } +}