14 LOG = logging.getLogger(os.path.basename(sys.argv[0]))
16 QUORUM_STATES = ['leader', 'peon']
20 uid = pwd.getpwnam('ceph').pw_uid
27 gid = grp.getgrnam('ceph').gr_gid
32 def wait_for_quorum(cluster, mon_id, wait_count=600):
33 # wait 10 minutes by default
38 '--cluster={cluster}'.format(cluster=cluster),
39 '--admin-daemon=/var/run/ceph/{cluster}-mon.{mon_id}.asok'.format(
45 stdout=subprocess.PIPE,
50 LOG.info('ceph-mon admin socket not ready yet.')
56 LOG.info('ceph-mon admin socket returned no data')
62 data = json.loads(out)
64 LOG.info('failed to parse json %s', out)
65 sys.exit(errno.EINVAL)
68 if state not in QUORUM_STATES:
69 LOG.info('ceph-mon is not in quorum: %r', state)
77 raise SystemExit("ceph-mon was not able to join quorum within %d seconds" % wait_count)
80 def get_key(cluster, mon_id, wait_count=600):
81 path = '/etc/ceph/{cluster}.client.admin.keyring'.format(
84 if os.path.exists(path):
85 LOG.info('Key exists already: %s', path)
87 tmp = '{path}.{pid}.tmp'.format(
91 pathdir = os.path.dirname(path)
92 if not os.path.exists(pathdir):
94 os.chmod(pathdir, 0770)
95 os.chown(pathdir, get_ceph_uid(), get_ceph_gid())
98 with file(tmp, 'w') as f:
99 os.fchmod(f.fileno(), 0600)
100 os.fchown(f.fileno(), get_ceph_uid(), get_ceph_gid())
101 LOG.info('Talking to monitor...')
105 '--connect-timeout=20',
106 '--cluster={cluster}'.format(cluster=cluster),
108 '--keyring=/var/lib/ceph/mon/{cluster}-{mon_id}/keyring'.format(
114 # First try getting the key if it already exists, to handle
115 # the case where it exists but doesn't match the caps
116 # we would pass into get-or-create.
117 returncode = subprocess.call(
125 if returncode == errno.ENOENT:
126 returncode = subprocess.call(
139 returncode = subprocess.call(
153 if returncode == errno.EPERM or returncode == errno.EACCES:
154 LOG.info('Cannot get or create admin key, permission denied')
157 LOG.info('Cannot get or create admin key')
168 if e.errno == errno.ENOENT:
174 raise SystemExit("Could not get or create the admin key after %d seconds" % wait_count)
177 def bootstrap_key(cluster, type_, wait_count=600):
178 path = '/var/lib/ceph/bootstrap-{type}/{cluster}.keyring'.format(
182 if os.path.exists(path):
183 LOG.info('Key exists already: %s', path)
185 tmp = '{path}.{pid}.tmp'.format(
192 '--connect-timeout=20',
193 '--cluster={cluster}'.format(cluster=cluster),
196 'client.bootstrap-{type}'.format(type=type_),
198 'allow profile bootstrap-{type}'.format(type=type_),
201 pathdir = os.path.dirname(path)
202 if not os.path.exists(pathdir):
204 os.chmod(pathdir, 0770)
205 os.chown(pathdir, get_ceph_uid(), get_ceph_gid())
207 while wait_count > 0:
209 with file(tmp, 'w') as f:
210 os.fchmod(f.fileno(), 0600)
211 os.fchown(f.fileno(), get_ceph_uid(), get_ceph_gid())
212 LOG.info('Talking to monitor...')
213 returncode = subprocess.call(
218 if returncode == errno.EPERM or returncode == errno.EACCES:
219 LOG.info('Cannot get or create bootstrap key for %s, permission denied', type_)
222 LOG.info('Cannot get or create bootstrap key for %s', type_)
233 if e.errno == errno.ENOENT:
238 raise SystemExit("Could not get or create %s bootstrap key after %d seconds" % (type_, wait_count))
242 parser = argparse.ArgumentParser(
243 description='Create Ceph client.admin key when ceph-mon is ready',
247 action='store_true', default=None,
248 help='be more verbose',
253 help='name of the cluster',
258 help='id of a ceph-mon that is coming up',
265 help='timeout in seconds to wait',
272 # we want to hold on to this, for later
275 args = parser.parse_args()
282 loglevel = logging.INFO
284 loglevel = logging.DEBUG
290 wait_for_quorum(cluster=args.cluster, mon_id=args.id, wait_count=args.timeout)
291 get_key(cluster=args.cluster, mon_id=args.id, wait_count=args.timeout)
294 cluster=args.cluster,
296 wait_count=args.timeout,
299 cluster=args.cluster,
301 wait_count=args.timeout,
304 cluster=args.cluster,
306 wait_count=args.timeout,
309 cluster=args.cluster,
311 wait_count=args.timeout,
314 if __name__ == '__main__':