library support

This commit is contained in:
Chris MacNaughton 2016-05-12 08:47:37 -04:00
parent f961745319
commit 3e633ce608
3 changed files with 230 additions and 98 deletions

View File

@ -17,6 +17,7 @@ import subprocess
import time import time
import os import os
import re import re
import socket
import sys import sys
import shutil import shutil
from charmhelpers.cli.host import mounts from charmhelpers.cli.host import mounts
@ -27,16 +28,24 @@ from charmhelpers.core.host import (
lsb_release, lsb_release,
service_stop, service_stop,
service_restart) service_restart)
from charms.reactive import is_state
from charmhelpers.core.hookenv import ( from charmhelpers.core.hookenv import (
log, log,
ERROR, ERROR,
WARNING, WARNING,
DEBUG, DEBUG,
cached, cached,
config,
unit_get,
status_set, status_set,
relation_ids,
related_units,
relation_get,
) )
from charmhelpers.fetch import ( from charmhelpers.fetch import (
apt_cache apt_cache,
# apt_install,
# filter_installed_packages
) )
from charmhelpers.contrib.storage.linux.utils import ( from charmhelpers.contrib.storage.linux.utils import (
zap_disk, zap_disk,
@ -47,27 +56,10 @@ from charmhelpers.contrib.storage.linux.utils import (
# get_unit_hostname, # get_unit_hostname,
# ) # )
# Imports from utils.py
import socket
import re
from charmhelpers.core.hookenv import (
unit_get,
cached,
config,
status_set,
)
from charmhelpers.fetch import (
apt_install,
filter_installed_packages
)
from charmhelpers.core.host import (
lsb_release
)
from charmhelpers.contrib.network.ip import ( from charmhelpers.contrib.network.ip import (
get_address_in_network, get_address_in_network,
get_ipv6_addr get_ipv6_addr,
format_ipv6_addr
) )
# try: # try:
@ -77,7 +69,24 @@ from charmhelpers.contrib.network.ip import (
# fatal=True) # fatal=True)
# import dns.resolver # import dns.resolver
import dns.resolver import dns.resolver
### This is migrated from hooks/utils.py
def get_mon_hosts():
hosts = []
if is_state('ceph_mon.installed'):
addr = get_public_addr()
hosts.append('{}:6789'.format(format_ipv6_addr(addr) or addr))
for relid in relation_ids('mon'):
for unit in related_units(relid):
addr = relation_get('ceph-public-address', unit, relid)
if addr is not None:
hosts.append('{}:6789'.format(
format_ipv6_addr(addr) or addr))
hosts.sort()
return hosts
def enable_pocket(pocket): def enable_pocket(pocket):
apt_sources = "/etc/apt/sources.list" apt_sources = "/etc/apt/sources.list"
@ -164,8 +173,6 @@ def assert_charm_supports_ipv6():
"versions less than Trusty 14.04") "versions less than Trusty 14.04")
### This is migrated from hooks/ceph.py
LEADER = 'leader' LEADER = 'leader'
PEON = 'peon' PEON = 'peon'
QUORUM = [LEADER, PEON] QUORUM = [LEADER, PEON]
@ -609,7 +616,7 @@ def generate_monitor_secret():
'--name=mon.', '--name=mon.',
'--gen-key' '--gen-key'
] ]
res = subprocess.check_output(cmd) res = subprocess.getoutput(cmd)
return "{}==".format(res.split('=')[1].strip()) return "{}==".format(res.split('=')[1].strip())
@ -684,6 +691,7 @@ _upgrade_caps = {
'mon': ['allow rwx'] 'mon': ['allow rwx']
} }
def get_radosgw_key(): def get_radosgw_key():
return get_named_key('radosgw.gateway', _radosgw_caps) return get_named_key('radosgw.gateway', _radosgw_caps)
@ -706,6 +714,8 @@ osd_upgrade_caps = {
'allow command "config-key exists"', 'allow command "config-key exists"',
] ]
} }
def get_upgrade_key(): def get_upgrade_key():
return get_named_key('upgrade-osd', _upgrade_caps) return get_named_key('upgrade-osd', _upgrade_caps)
@ -936,63 +946,3 @@ def get_running_osds():
return result.split() return result.split()
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
return [] return []
def emit_cephconf(mon_hosts):
networks = get_networks('ceph-public-network')
public_network = ', '.join(networks)
networks = get_networks('ceph-cluster-network')
cluster_network = ', '.join(networks)
cephcontext = {
'auth_supported': config('auth-supported'),
'mon_hosts': ' '.join(mon_hosts),
'fsid': leader_get('fsid'),
'old_auth': cmp_pkgrevno('ceph', "0.51") < 0,
'osd_journal_size': config('osd-journal-size'),
'use_syslog': str(config('use-syslog')).lower(),
'ceph_public_network': public_network,
'ceph_cluster_network': cluster_network,
'loglevel': config('loglevel'),
'dio': str(config('use-direct-io')).lower(),
}
if config('prefer-ipv6'):
dynamic_ipv6_address = get_ipv6_addr()[0]
if not public_network:
cephcontext['public_addr'] = dynamic_ipv6_address
if not cluster_network:
cephcontext['cluster_addr'] = dynamic_ipv6_address
if az_info():
cephcontext['crush_location'] = "root=default rack={} host={}" \
.format(az_info(), socket.gethostname())
# Install ceph.conf as an alternative to support
# co-existence with other charms that write this file
charm_ceph_conf = "/var/lib/charm/{}/ceph.conf".format(service_name())
mkdir(os.path.dirname(charm_ceph_conf), owner=ceph.ceph_user(),
group=ceph.ceph_user())
render('ceph.conf', charm_ceph_conf, cephcontext, perms=0o644)
install_alternative('ceph.conf', '/etc/ceph/ceph.conf',
charm_ceph_conf, 100)
def get_fsid():
return get_conf('fsid')
def get_auth():
return get_conf('auth')
def get_conf(name):
for relid in relation_ids('mon'):
for unit in related_units(relid):
conf = relation_get(name,
unit, relid)
if conf:
return conf
return None

View File

@ -1,25 +1,47 @@
from charms.reactive import when, when_not, set_state from charms import reactive
from charms.reactive import when, when_not, set_state, is_state
import charms.apt import charms.apt
from charms.ceph_base import ( from charms.ceph_base import (
get_networks, # get_networks,
get_public_addr, # get_public_addr,
get_mon_hosts,
is_bootstrapped,
is_quorum,
get_running_osds,
assert_charm_supports_ipv6 assert_charm_supports_ipv6
) )
from charmhelpers.contrib.hardening.harden import harden # from charmhelpers.core.host import (
# umount,
# )
from charmhelpers.core import hookenv
from charmhelpers.core.hookenv import (
# log,
config,
relation_ids,
related_units,
relation_get,
status_set,
local_unit
)
from charmhelpers.core.sysctl import create as create_sysctl
# from charmhelpers.contrib.hardening.harden import harden
@when_not('ceph.installed') @when_not('ceph.installed')
@harden() # @harden()
def install_ceph_base(): def install_ceph_base():
charms.apt.add_source(config('source'), key=config('key')) charms.apt.add_source(config('source'), key=config('key'))
charms.apt.queue_install(['ceph', 'gdisk', 'ntp', 'btrfs-tools', 'python3-ceph', 'xfsprogs']) charms.apt.queue_install(charms.ceph_base.PACKAGES)
charms.apt.install_queued()
set_state('ceph.installed') set_state('ceph.installed')
@when('config.changed') @when('config.changed', 'ceph.installed')
@harden() # @harden()
def config_changed(): def config_changed():
# # Check if an upgrade was requested # # Check if an upgrade was requested
# check_for_upgrade() # check_for_upgrade()
@ -30,9 +52,127 @@ def config_changed():
sysctl_dict = config('sysctl') sysctl_dict = config('sysctl')
if sysctl_dict: if sysctl_dict:
create_sysctl(sysctl_dict, '/etc/sysctl.d/50-ceph-osd-charm.conf') create_sysctl(sysctl_dict, '/etc/sysctl.d/50-ceph-charm.conf')
# if relations_of_type('nrpe-external-master'):
# update_nrpe_config()
e_mountpoint = config('ephemeral-unmount') # sysctl_dict = config('sysctl')
if e_mountpoint and ceph.filesystem_mounted(e_mountpoint): # if sysctl_dict:
umount(e_mountpoint) # create_sysctl(sysctl_dict, '/etc/sysctl.d/50-ceph-osd-charm.conf')
prepare_disks_and_activate()
# e_mountpoint = config('ephemeral-unmount')
# if e_mountpoint and ceph.filesystem_mounted(e_mountpoint):
# umount(e_mountpoint)
# prepare_disks_and_activate()
def assess_status():
'''Assess status of current unit'''
# is_state('ceph_mon.bootstrapped')
statuses = set([])
messages = set([])
if is_state('ceph_mon.installed'):
(status, message) = log_monitor()
statuses.add(status)
messages.add(message)
if is_state('ceph_osd.installed'):
(status, message) = log_osds()
statuses.add(status)
messages.add(message)
if 'blocked' in statuses:
status = 'blocked'
elif 'waiting' in statuses:
status = 'waiting'
else:
status = 'active'
message = '; '.join(messages)
status_set(status, message)
def get_conf(name):
for relid in relation_ids('mon'):
for unit in related_units(relid):
conf = relation_get(name,
unit, relid)
if conf:
return conf
return None
def log_monitor():
moncount = int(config('monitor-count'))
units = get_peer_units()
# not enough peers and mon_count > 1
if len(units.keys()) < moncount:
return ('blocked', 'Insufficient peer units to bootstrap'
' cluster (require {})'.format(moncount))
# mon_count > 1, peers, but no ceph-public-address
ready = sum(1 for unit_ready in units.values() if unit_ready)
if ready < moncount:
return ('waiting', 'Peer units detected, waiting for addresses')
# active - bootstrapped + quorum status check
if is_bootstrapped() and is_quorum():
return ('active', 'Unit is ready and clustered')
else:
# Unit should be running and clustered, but no quorum
# TODO: should this be blocked or waiting?
return ('blocked', 'Unit not clustered (no quorum)')
# If there's a pending lock for this unit,
# can i get the lock?
# reboot the ceph-mon process
def get_peer_units():
"""
Returns a dictionary of unit names from the mon peer relation with
a flag indicating whether the unit has presented its address
"""
units = {}
units[local_unit()] = True
for relid in relation_ids('mon'):
for unit in related_units(relid):
addr = relation_get('ceph-public-address', unit, relid)
units[unit] = addr is not None
return units
def log_osds():
if not is_state('ceph_mon.installed'):
# Check for mon relation
if len(relation_ids('mon')) < 1:
status_set('blocked', 'Missing relation: monitor')
return
# Check for monitors with presented addresses
# Check for bootstrap key presentation
monitors = get_mon_hosts()
if len(monitors) < 1 or not get_conf('osd_bootstrap_key'):
status_set('waiting', 'Incomplete relation: monitor')
return
# Check for OSD device creation parity i.e. at least some devices
# must have been presented and used for this charm to be operational
running_osds = get_running_osds()
if not running_osds:
return ('blocked',
'No block devices detected using current configuration')
else:
return ('active',
'Unit is ready ({} OSD)'.format(len(running_osds)))
# Per https://github.com/juju-solutions/charms.reactive/issues/33,
# this module may be imported multiple times so ensure the
# initialization hook is only registered once. I have to piggy back
# onto the namespace of a module imported before reactive discovery
# to do this.
if not hasattr(reactive, '_ceph_log_registered'):
# We need to register this to run every hook, not just during install
# and config-changed, to protect against race conditions. If we don't
# do this, then the config in the hook environment may show updates
# to running hooks well before the config-changed hook has been invoked
# and the intialization provided an opertunity to be run.
hookenv.atexit(assess_status)
reactive._ceph_log_registered = True

42
templates/ceph.conf Normal file
View File

@ -0,0 +1,42 @@
[global]
{% if old_auth %}
auth supported = {{ auth_supported }}
{% else %}
auth cluster required = {{ auth_supported }}
auth service required = {{ auth_supported }}
auth client required = {{ auth_supported }}
{% endif %}
keyring = /etc/ceph/$cluster.$name.keyring
mon host = {{ mon_hosts }}
fsid = {{ fsid }}
log to syslog = {{ use_syslog }}
err to syslog = {{ use_syslog }}
clog to syslog = {{ use_syslog }}
mon cluster log to syslog = {{ use_syslog }}
{%- if ceph_public_network is string %}
public network = {{ ceph_public_network }}
{%- endif %}
{%- if ceph_cluster_network is string %}
cluster network = {{ ceph_cluster_network }}
{%- endif %}
{% if public_addr %}
public addr = {{ public_addr }}
{% endif %}
{% if cluster_addr %}
cluster addr = {{ cluster_addr }}
{%- endif %}
[mon]
keyring = /var/lib/ceph/mon/$cluster-$id/keyring
[mds]
keyring = /var/lib/ceph/mds/$cluster-$id/keyring
[osd]
keyring = /var/lib/ceph/osd/$cluster-$id/keyring
osd journal size = {{ osd_journal_size }}
filestore xattr use omap = true