mirror of
https://github.com/ceph/ceph
synced 2024-12-28 14:34:13 +00:00
Merge PR #21305 into master
* refs/pull/21305/head: ceph-create-keys: depreceate, print warning Reviewed-by: Sébastien Han <seb@redhat.com> Reviewed-by: Nathan Cutler <ncutler@suse.com>
This commit is contained in:
commit
c219402ed9
@ -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
|
||||
<entity-name>`` command for whichever key(s) they need.
|
||||
|
||||
Upgrading from Luminous
|
||||
-----------------------
|
||||
|
||||
|
@ -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."
|
||||
|
Loading…
Reference in New Issue
Block a user