diff --git a/PendingReleaseNotes b/PendingReleaseNotes index cc7b5b69ac7..b9c6150e19f 100644 --- a/PendingReleaseNotes +++ b/PendingReleaseNotes @@ -231,6 +231,15 @@ on the intended OSDs). You can reenable the old warning by setting ``mon_warn_on_misplaced`` to ``true``. +* The ``ceph-create-keys`` tool is now obsolete. The monitors + automatically create these keys on their own. For now the script + prints a warning message and exits, but it will be removed in the + next release. Note that ``ceph-create-keys`` would also write the + admin and bootstrap keys to /etc/ceph and /var/lib/ceph, but this + script no longer does that. Any deployment tools that relied on + this behavior should instead make use of the ``ceph auth export + `` command for whichever key(s) they need. + Upgrading from Luminous ----------------------- diff --git a/src/ceph-create-keys b/src/ceph-create-keys index 41d76e1578d..a960a08be82 100755 --- a/src/ceph-create-keys +++ b/src/ceph-create-keys @@ -1,315 +1,5 @@ -#!/usr/bin/env python -import argparse -import errno -import json -import logging -import os -import subprocess -import sys -import time -import pwd -import grp +#!/bin/sh - -LOG = logging.getLogger(os.path.basename(sys.argv[0])) - -QUORUM_STATES = ['leader', 'peon'] - -def get_ceph_uid(): - try: - uid = pwd.getpwnam('ceph').pw_uid - except: - uid = -1 - return uid - -def get_ceph_gid(): - try: - gid = grp.getgrnam('ceph').gr_gid - except: - gid = -1 - return gid - -def wait_for_quorum(cluster, mon_id, wait_count=600): - # wait 10 minutes by default - while wait_count > 0: - p = subprocess.Popen( - args=[ - 'ceph', - '--cluster={cluster}'.format(cluster=cluster), - '--admin-daemon=/var/run/ceph/{cluster}-mon.{mon_id}.asok'.format( - cluster=cluster, - mon_id=mon_id, - ), - 'mon_status', - ], - stdout=subprocess.PIPE, - ) - out = p.stdout.read() - returncode = p.wait() - if returncode != 0: - LOG.info('ceph-mon admin socket not ready yet.') - time.sleep(1) - wait_count -= 1 - continue - - if out == '': - LOG.info('ceph-mon admin socket returned no data') - time.sleep(1) - wait_count -= 1 - continue - - try: - data = json.loads(out) - except: - LOG.info('failed to parse json %s', out) - sys.exit(errno.EINVAL) - - state = data['state'] - if state not in QUORUM_STATES: - LOG.info('ceph-mon is not in quorum: %r', state) - time.sleep(1) - wait_count -= 1 - continue - - break - - if wait_count == 0: - raise SystemExit("ceph-mon was not able to join quorum within %d seconds" % wait_count) - - -def get_key(cluster, mon_id, wait_count=600): - path = '/etc/ceph/{cluster}.client.admin.keyring'.format( - cluster=cluster, - ) - if os.path.exists(path): - LOG.info('Key exists already: %s', path) - return - tmp = '{path}.{pid}.tmp'.format( - path=path, - pid=os.getpid(), - ) - pathdir = os.path.dirname(path) - if not os.path.exists(pathdir): - os.makedirs(pathdir) - os.chmod(pathdir, 0o770) - os.chown(pathdir, get_ceph_uid(), get_ceph_gid()) - while wait_count > 0: - try: - with open(tmp, 'w') as f: - os.fchmod(f.fileno(), 0o600) - os.fchown(f.fileno(), get_ceph_uid(), get_ceph_gid()) - LOG.info('Talking to monitor...') - - args_prefix = [ - "ceph", - '--connect-timeout=20', - '--cluster={cluster}'.format(cluster=cluster), - '--name=mon.', - '--keyring=/var/lib/ceph/mon/{cluster}-{mon_id}/keyring'.format( - cluster=cluster, - mon_id=mon_id, - ), - ] - - # First try getting the key if it already exists, to handle - # the case where it exists but doesn't match the caps - # we would pass into get-or-create. - returncode = subprocess.call( - args=args_prefix + [ - 'auth', - 'get', - 'client.admin', - ], - stdout=f, - ) - if returncode == errno.ENOENT: - returncode = subprocess.call( - args=args_prefix + [ - 'auth', - 'get-or-create', - 'client.admin', - 'mon', 'allow *', - 'osd', 'allow *', - 'mds', 'allow *', - 'mgr', 'allow *', - ], - stdout=f, - ) - else: - returncode = subprocess.call( - args=args_prefix + [ - 'auth', - 'caps', - 'client.admin', - 'mon', 'allow *', - 'osd', 'allow *', - 'mds', 'allow *', - 'mgr', 'allow *', - ], - stdout=f, - ) - - if returncode != 0: - if returncode == errno.EPERM or returncode == errno.EACCES: - LOG.info('Cannot get or create admin key, permission denied') - sys.exit(returncode) - else: - LOG.info('Cannot get or create admin key') - time.sleep(1) - wait_count -= 1 - continue - - os.rename(tmp, path) - break - finally: - try: - os.unlink(tmp) - except OSError as e: - if e.errno == errno.ENOENT: - pass - else: - raise - - if wait_count == 0: - raise SystemExit("Could not get or create the admin key after %d seconds" % wait_count) - - -def bootstrap_key(cluster, type_, wait_count=600): - path = '/var/lib/ceph/bootstrap-{type}/{cluster}.keyring'.format( - type=type_, - cluster=cluster, - ) - if os.path.exists(path): - LOG.info('Key exists already: %s', path) - return - tmp = '{path}.{pid}.tmp'.format( - path=path, - pid=os.getpid(), - ) - - args = [ - 'ceph', - '--connect-timeout=20', - '--cluster={cluster}'.format(cluster=cluster), - 'auth', - 'get-or-create', - 'client.bootstrap-{type}'.format(type=type_), - 'mon', - 'allow profile bootstrap-{type}'.format(type=type_), - ] - - pathdir = os.path.dirname(path) - if not os.path.exists(pathdir): - os.makedirs(pathdir) - os.chmod(pathdir, 0o770) - os.chown(pathdir, get_ceph_uid(), get_ceph_gid()) - - while wait_count > 0: - try: - with open(tmp, 'w') as f: - os.fchmod(f.fileno(), 0o600) - os.fchown(f.fileno(), get_ceph_uid(), get_ceph_gid()) - LOG.info('Talking to monitor...') - returncode = subprocess.call( - args=args, - stdout=f, - ) - if returncode != 0: - if returncode == errno.EPERM or returncode == errno.EACCES: - LOG.info('Cannot get or create bootstrap key for %s, permission denied', type_) - break - else: - LOG.info('Cannot get or create bootstrap key for %s', type_) - time.sleep(1) - wait_count -= 1 - continue - - os.rename(tmp, path) - break - finally: - try: - os.unlink(tmp) - except OSError as e: - if e.errno == errno.ENOENT: - pass - else: - raise - if wait_count == 0: - raise SystemExit("Could not get or create %s bootstrap key after %d seconds" % (type_, wait_count)) - - -def parse_args(): - parser = argparse.ArgumentParser( - description='Create Ceph client.admin key when ceph-mon is ready', - ) - parser.add_argument( - '-v', '--verbose', - action='store_true', default=None, - help='be more verbose', - ) - parser.add_argument( - '--cluster', - metavar='NAME', - help='name of the cluster', - ) - parser.add_argument( - '--id', '-i', - metavar='ID', - help='id of a ceph-mon that is coming up', - required=True, - ) - parser.add_argument( - '--timeout', '-t', - metavar='TIMEOUT', - type=int, - help='timeout in seconds to wait', - ) - parser.set_defaults( - cluster='ceph', - timeout=600, - ) - parser.set_defaults( - # we want to hold on to this, for later - prog=parser.prog, - ) - args = parser.parse_args() - return args - - -def main(): - args = parse_args() - - loglevel = logging.INFO - if args.verbose: - loglevel = logging.DEBUG - - logging.basicConfig( - level=loglevel, - ) - - wait_for_quorum(cluster=args.cluster, mon_id=args.id, wait_count=args.timeout) - get_key(cluster=args.cluster, mon_id=args.id, wait_count=args.timeout) - - bootstrap_key( - cluster=args.cluster, - type_='osd', - wait_count=args.timeout, - ) - bootstrap_key( - cluster=args.cluster, - type_='rgw', - wait_count=args.timeout, - ) - bootstrap_key( - cluster=args.cluster, - type_='mds', - wait_count=args.timeout, - ) - bootstrap_key( - cluster=args.cluster, - type_='rbd', - wait_count=args.timeout, - ) - -if __name__ == '__main__': - main() +echo "$0: This tool is obsolete; mons now create these keys on their own, and" +echo "$0: this tool does nothing except print this message." +echo "$0: It will be removed in the next release. Please fix your script/tool."