Updates for pep8 compliance, added peer hinting to mon hook, removed redundant mon-relation-changed hook, updated copyright, added start/stop hooks to keep charm proof quiet

This commit is contained in:
James Page 2012-10-04 09:28:49 +01:00
parent 2915bfc4fd
commit dbd2a656cb
7 changed files with 138 additions and 68 deletions

View File

@ -1,5 +1,15 @@
Copyright 2012 Canonical Ltd.
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
Comment: The licensing of this charm is aligned to upstream ceph
as the ceph upstart integration is distributed as part of the charm.
Authors:
Paul Collins <paul.collins@canonocal.com>
James Page <james.page@canonical.com>
Files: *
Copyright: 2012, Canonical Ltd.
License: LGPL-2.1
Files: files/upstart/*
Copyright: 2004-2010 by Sage Weil <sage@newdream.net>
License: LGPL-2.1
License: LGPL-2.1
On Debian GNU/Linux system you can find the complete text of the
LGPL-2.1 license in '/usr/share/common-licenses/LGPL-2.1'

View File

@ -13,13 +13,14 @@ import subprocess
import time
import utils
QUORUM = [ 'leader', 'peon' ]
QUORUM = ['leader', 'peon']
def is_quorum():
cmd = [
"ceph",
"--admin-daemon",
"/var/run/ceph/ceph-mon.%s.asok" % utils.get_unit_hostname(),
"/var/run/ceph/ceph-mon.{}.asok".format(utils.get_unit_hostname()),
"mon_status"
]
@ -33,6 +34,19 @@ def is_quorum():
else:
return False
def wait_for_quorum():
while not is_quorum():
time.sleep(3)
def add_bootstrap_hint(peer):
cmd = [
"ceph",
"--admin-daemon",
"/var/run/ceph/ceph-mon.{}.asok".format(utils.get_unit_hostname()),
"add_bootstrap_peer_hint",
peer
]
# Ignore any errors for this call
subprocess.call(cmd)

View File

@ -5,6 +5,7 @@
#
# Authors:
# Paul Collins <paul.collins@canonical.com>
# James Page <james.page@ubuntu.com>
#
import glob
@ -17,20 +18,20 @@ import sys
import ceph
import utils
def install_upstart_scripts():
for x in glob.glob('files/upstart/*.conf'):
shutil.copy(x, '/etc/init/')
shutil.copy(x, '/etc/init/')
def install():
utils.juju_log('INFO', 'Begin install hook.')
utils.configure_source()
utils.install('ceph')
utils.install('gdisk') # for ceph-disk-prepare
utils.install('ceph', 'gdisk')
install_upstart_scripts()
utils.juju_log('INFO', 'End install hook.')
def emit_cephconf():
cephcontext = {
'mon_hosts': ' '.join(get_mon_hosts()),
@ -40,19 +41,21 @@ def emit_cephconf():
with open('/etc/ceph/ceph.conf', 'w') as cephconf:
cephconf.write(utils.render_template('ceph.conf', cephcontext))
def config_changed():
utils.juju_log('INFO', 'Begin config-changed hook.')
utils.juju_log('INFO', 'Monitor hosts are ' + repr(get_mon_hosts()))
fsid = utils.config_get('fsid')
if fsid == "":
if fsid == '':
utils.juju_log('CRITICAL', 'No fsid supplied, cannot proceed.')
sys.exit(1)
monitor_secret = utils.config_get('monitor-secret')
if monitor_secret == "":
utils.juju_log('CRITICAL', 'No monitor-secret supplied, cannot proceed.')
if monitor_secret == '':
utils.juju_log('CRITICAL',
'No monitor-secret supplied, cannot proceed.')
sys.exit(1)
emit_cephconf()
@ -63,12 +66,13 @@ def config_changed():
utils.juju_log('INFO', 'End config-changed hook.')
def get_mon_hosts():
hosts = []
hosts.append(socket.gethostbyname(utils.unit_get('private-address'))
+ ':6789')
for relid in utils.relation_ids("mon"):
for relid in utils.relation_ids('mon'):
for unit in utils.relation_list(relid):
hosts.append(
socket.gethostbyname(utils.relation_get('private-address',
@ -78,19 +82,35 @@ def get_mon_hosts():
hosts.sort()
return hosts
def get_mon_addresses():
hosts = []
hosts.append(socket.gethostbyname(utils.unit_get('private-address')))
for relid in utils.relation_ids('mon'):
for unit in utils.relation_list(relid):
hosts.append(
socket.gethostbyname(utils.relation_get('private-address',
unit, relid)))
hosts.sort()
return hosts
def bootstrap_monitor_cluster():
hostname = utils.get_unit_hostname()
done = "/var/lib/ceph/mon/ceph-%s/done" % hostname
done = '/var/lib/ceph/mon/ceph-{}/done'.format(hostname)
secret = utils.config_get('monitor-secret')
keyring = "/var/lib/ceph/tmp/%s.mon.keyring" % hostname
keyring = '/var/lib/ceph/tmp/{}.mon.keyring'.format(hostname)
if os.path.exists(done):
utils.juju_log('INFO', 'bootstrap_monitor_cluster: mon already initialized, getting on with life.')
utils.juju_log('INFO',
'bootstrap_monitor_cluster: mon already initialized.')
else:
try:
subprocess.check_call(['ceph-authtool', keyring,
'--create-keyring', '--name=mon.',
"--add-key=%s" % secret,
'--add-key={}'.format(secret),
'--cap', 'mon', 'allow *'])
subprocess.check_call(['ceph-mon', '--mkfs',
@ -106,47 +126,53 @@ def bootstrap_monitor_cluster():
finally:
os.unlink(keyring)
def osdize_and_activate(dev):
# XXX hack for instances
subprocess.call(['umount', '/mnt'])
if subprocess.call(['grep', '-wqs', dev + '1', '/proc/mounts']) == 0:
utils.juju_log('INFO', "Looks like %s is in use, skipping." % dev)
return True
utils.juju_log('INFO',
'Looks like {} is in use, skipping.'.format(dev))
else:
if os.path.exists(dev):
subprocess.call(['ceph-disk-prepare', dev])
subprocess.call(['udevadm', 'trigger',
'--subsystem-match=block', '--action=add'])
if os.path.exists(dev):
subprocess.call(['ceph-disk-prepare', dev])
subprocess.call(['udevadm', 'trigger',
'--subsystem-match=block', '--action=add'])
def mon_relation():
utils.juju_log('INFO', 'Begin mon-relation hook.')
emit_cephconf()
moncount = int(utils.config_get('monitor-count'))
if len(get_mon_hosts()) == moncount:
if len(get_mon_hosts()) >= moncount:
bootstrap_monitor_cluster()
ceph.wait_for_quorum()
for dev in utils.config_get('osd-devices').split(' '):
osdize_and_activate(dev)
for peer in get_mon_addresses():
ceph.add_bootstrap_hint(peer)
else:
utils.juju_log('INFO',
"Not enough mons (%d), punting." % len(get_mon_hosts()))
'Not enough mons ({}), punting.'.format(
len(get_mon_hosts())))
utils.juju_log('INFO', 'End mon-relation hook.')
def upgrade_charm():
utils.juju_log('INFO', 'Begin upgrade-charm hook.')
emit_cephconf()
install_upstart_scripts()
utils.install('gdisk') # for ceph-disk-prepare
utils.juju_log('INFO', 'End upgrade-charm hook.')
hooks = {
'config-changed': config_changed,
'install': install,
'mon-relation-changed': mon_relation,
'mon-relation-departed': mon_relation,
'mon-relation-joined': mon_relation,
'upgrade-charm': upgrade_charm,
@ -157,6 +183,7 @@ hook = os.path.basename(sys.argv[0])
try:
hooks[hook]()
except KeyError:
utils.juju_log('INFO', "This charm doesn't know how to handle '%s'." % hook)
utils.juju_log('INFO',
'This charm doesn't know how to handle '{}'.'.format(hook))
sys.exit(0)

1
hooks/stop Symbolic link
View File

@ -0,0 +1 @@
hooks.py

View File

@ -13,17 +13,18 @@ import os
import sys
import socket
def install (*pkgs):
def install(*pkgs):
cmd = [
"apt-get",
"-y",
"install"
'apt-get',
'-y',
'install'
]
for pkg in pkgs:
cmd.append(pkg)
subprocess.check_call(cmd)
TEMPLATES_DIR="templates"
TEMPLATES_DIR = 'templates'
try:
import jinja2
@ -31,104 +32,118 @@ except ImportError:
install('python-jinja2')
import jinja2
def render_template (template_name, context, template_dir=TEMPLATES_DIR):
templates = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir))
def render_template(template_name, context, template_dir=TEMPLATES_DIR):
templates = jinja2.Environment(
loader=jinja2.FileSystemLoader(template_dir)
)
template = templates.get_template(template_name)
return template.render(context)
def configure_source():
source = config_get("source")
if (source.startswith("ppa:") or
source.startswith("cloud:") or
source.startswith("http:")):
source = config_get('source')
if (source.startswith('ppa:') or
source.startswith('cloud:') or
source.startswith('http:')):
cmd = [
"add-apt-repository",
'add-apt-repository',
source
]
subprocess.check_call(cmd)
if source.startswith("http:"):
key = config_get("key")
if source.startswith('http:'):
key = config_get('key')
cmd = [
"apt-key",
"import",
'apt-key',
'import',
key
]
subprocess.check_call(cmd)
cmd = [
"apt-get",
"update"
'apt-get',
'update'
]
subprocess.check_call(cmd)
# Protocols
TCP="TCP"
UDP="UDP"
TCP = 'TCP'
UDP = 'UDP'
def expose(port, protocol="TCP"):
def expose(port, protocol='TCP'):
cmd = [
"open-port",
"%d/%s" % (port,protocol)
'open-port',
'{}/{}'.format(port, protocol)
]
subprocess.check_call(cmd)
def juju_log(message,severity="INFO"):
def juju_log(message, severity='INFO'):
cmd = [
"juju-log",
"--log-level", severity,
'juju-log',
'--log-level', severity,
message
]
subprocess.check_call(cmd)
def relation_ids(relation):
cmd = [
"relation-ids",
'relation-ids',
relation
]
return subprocess.check_output(cmd).split()
def relation_list(rid):
cmd = [
"relation-list",
"-r", rid,
'relation-list',
'-r', rid,
]
return subprocess.check_output(cmd).split()
def relation_get(attribute,unit=None,rid=None):
def relation_get(attribute, unit=None, rid=None):
cmd = [
"relation-get",
'relation-get',
]
if rid:
cmd.append("-r")
cmd.append('-r')
cmd.append(rid)
cmd.append(attribute)
if unit:
cmd.append(unit)
return subprocess.check_output(cmd).strip()
def relation_set(**kwargs):
cmd = [
"relation-set"
'relation-set'
]
for k, v in kwargs.items():
cmd.append("%s=%s" % (k,v))
cmd.append('{}={}'.format(k, v))
subprocess.check_call(cmd)
def unit_get(attribute):
cmd = [
"unit-get",
'unit-get',
attribute
]
return subprocess.check_output(cmd).strip()
def config_get(attribute):
cmd = [
"config-get",
'config-get',
attribute
]
return subprocess.check_output(cmd).strip()
def juju_log(level, message):
subprocess.call(['juju-log', '-l', level, message])
def get_unit_hostname():
return socket.gethostname()

View File

@ -1,7 +1,10 @@
name: ceph-brolin
summary: distributed storage
summary: Highly scalable distributed storage
maintainer: James Page <james.page@ubuntu.com>,
Paul Collins <paul.collins@canonical.com>
description: |
This charm deploys Ceph.
Ceph is a distributed storage and network file system designed to provide
excellent performance, reliability, and scalability.
peers:
mon:
interface: ceph-brolin