[james-page,r=dosaboy] Add configuration options for ceph public and cluster networks.

This commit is contained in:
james.page@ubuntu.com 2014-07-29 12:03:49 +01:00
commit eb1d0968d3
7 changed files with 190 additions and 21 deletions

View File

@ -6,3 +6,4 @@ include:
- contrib.storage.linux:
- utils
- contrib.openstack.alternatives
- contrib.network.ip

View File

@ -83,3 +83,13 @@ options:
default: False
description: |
If set to True, supporting services will log to syslog.
ceph-public-network:
type: string
description: |
The IP address and netmask of the public (front-side) network (e.g.,
192.168.0.0/24)
ceph-cluster-network:
type: string
description: |
The IP address and netmask of the cluster (back-side) network (e.g.,
192.168.0.0/24)

View File

@ -337,6 +337,8 @@ def osdize_dev(dev, osd_format, osd_journal, reformat_osd=False):
if osd_format:
cmd.append('--fs-type')
cmd.append(osd_format)
if reformat_osd:
cmd.append('--zap-disk')
cmd.append(dev)
if osd_journal and os.path.exists(osd_journal):
cmd.append(osd_journal)
@ -344,9 +346,8 @@ def osdize_dev(dev, osd_format, osd_journal, reformat_osd=False):
# Just provide the device - no other options
# for older versions of ceph
cmd.append(dev)
if reformat_osd:
zap_disk(dev)
if reformat_osd:
zap_disk(dev)
subprocess.check_call(cmd)

View File

@ -0,0 +1,156 @@
import sys
from functools import partial
from charmhelpers.fetch import apt_install
from charmhelpers.core.hookenv import (
ERROR, log,
)
try:
import netifaces
except ImportError:
apt_install('python-netifaces')
import netifaces
try:
import netaddr
except ImportError:
apt_install('python-netaddr')
import netaddr
def _validate_cidr(network):
try:
netaddr.IPNetwork(network)
except (netaddr.core.AddrFormatError, ValueError):
raise ValueError("Network (%s) is not in CIDR presentation format" %
network)
def get_address_in_network(network, fallback=None, fatal=False):
"""
Get an IPv4 or IPv6 address within the network from the host.
:param network (str): CIDR presentation format. For example,
'192.168.1.0/24'.
:param fallback (str): If no address is found, return fallback.
:param fatal (boolean): If no address is found, fallback is not
set and fatal is True then exit(1).
"""
def not_found_error_out():
log("No IP address found in network: %s" % network,
level=ERROR)
sys.exit(1)
if network is None:
if fallback is not None:
return fallback
else:
if fatal:
not_found_error_out()
_validate_cidr(network)
network = netaddr.IPNetwork(network)
for iface in netifaces.interfaces():
addresses = netifaces.ifaddresses(iface)
if network.version == 4 and netifaces.AF_INET in addresses:
addr = addresses[netifaces.AF_INET][0]['addr']
netmask = addresses[netifaces.AF_INET][0]['netmask']
cidr = netaddr.IPNetwork("%s/%s" % (addr, netmask))
if cidr in network:
return str(cidr.ip)
if network.version == 6 and netifaces.AF_INET6 in addresses:
for addr in addresses[netifaces.AF_INET6]:
if not addr['addr'].startswith('fe80'):
cidr = netaddr.IPNetwork("%s/%s" % (addr['addr'],
addr['netmask']))
if cidr in network:
return str(cidr.ip)
if fallback is not None:
return fallback
if fatal:
not_found_error_out()
return None
def is_ipv6(address):
'''Determine whether provided address is IPv6 or not'''
try:
address = netaddr.IPAddress(address)
except netaddr.AddrFormatError:
# probably a hostname - so not an address at all!
return False
else:
return address.version == 6
def is_address_in_network(network, address):
"""
Determine whether the provided address is within a network range.
:param network (str): CIDR presentation format. For example,
'192.168.1.0/24'.
:param address: An individual IPv4 or IPv6 address without a net
mask or subnet prefix. For example, '192.168.1.1'.
:returns boolean: Flag indicating whether address is in network.
"""
try:
network = netaddr.IPNetwork(network)
except (netaddr.core.AddrFormatError, ValueError):
raise ValueError("Network (%s) is not in CIDR presentation format" %
network)
try:
address = netaddr.IPAddress(address)
except (netaddr.core.AddrFormatError, ValueError):
raise ValueError("Address (%s) is not in correct presentation format" %
address)
if address in network:
return True
else:
return False
def _get_for_address(address, key):
"""Retrieve an attribute of or the physical interface that
the IP address provided could be bound to.
:param address (str): An individual IPv4 or IPv6 address without a net
mask or subnet prefix. For example, '192.168.1.1'.
:param key: 'iface' for the physical interface name or an attribute
of the configured interface, for example 'netmask'.
:returns str: Requested attribute or None if address is not bindable.
"""
address = netaddr.IPAddress(address)
for iface in netifaces.interfaces():
addresses = netifaces.ifaddresses(iface)
if address.version == 4 and netifaces.AF_INET in addresses:
addr = addresses[netifaces.AF_INET][0]['addr']
netmask = addresses[netifaces.AF_INET][0]['netmask']
cidr = netaddr.IPNetwork("%s/%s" % (addr, netmask))
if address in cidr:
if key == 'iface':
return iface
else:
return addresses[netifaces.AF_INET][0][key]
if address.version == 6 and netifaces.AF_INET6 in addresses:
for addr in addresses[netifaces.AF_INET6]:
if not addr['addr'].startswith('fe80'):
cidr = netaddr.IPNetwork("%s/%s" % (addr['addr'],
addr['netmask']))
if address in cidr:
if key == 'iface':
return iface
else:
return addr[key]
return None
get_iface_for_address = partial(_get_for_address, key='iface')
get_netmask_for_address = partial(_get_for_address, key='netmask')

View File

@ -42,6 +42,7 @@ from utils import (
)
from charmhelpers.contrib.openstack.alternatives import install_alternative
from charmhelpers.contrib.network.ip import is_ipv6
hooks = Hooks()
@ -55,12 +56,10 @@ def install_upstart_scripts():
@hooks.hook('install')
def install():
log('Begin install hook.')
add_source(config('source'), config('key'))
apt_update(fatal=True)
apt_install(packages=ceph.PACKAGES, fatal=True)
install_upstart_scripts()
log('End install hook.')
def emit_cephconf():
@ -73,7 +72,9 @@ def emit_cephconf():
'fsid': get_fsid(),
'old_auth': cmp_pkgrevno('ceph', "0.51") < 0,
'osd_journal_size': config('osd-journal-size'),
'use_syslog': str(config('use-syslog')).lower()
'use_syslog': str(config('use-syslog')).lower(),
'ceph_public_network': config('ceph-public-network'),
'ceph_cluster_network': config('ceph-cluster-network'),
}
# Install ceph.conf as an alternative to support
# co-existence with other charms that write this file
@ -89,8 +90,6 @@ JOURNAL_ZAPPED = '/var/lib/ceph/journal_zapped'
@hooks.hook('config-changed')
def config_changed():
log('Begin config-changed hook.')
# Pre-flight checks
if config('osd-format') not in ceph.DISK_FORMATS:
log('Invalid OSD disk format configuration specified', level=ERROR)
@ -115,18 +114,18 @@ def config_changed():
config('osd-journal'), config('osd-reformat'))
ceph.start_osds(get_devices())
log('End config-changed hook.')
def get_mon_hosts():
hosts = []
for relid in relation_ids('mon'):
for unit in related_units(relid):
hosts.append(
'{}:6789'.format(get_host_ip(relation_get('private-address',
unit, relid)))
)
addr = relation_get('ceph-public-address', unit, relid) or \
get_host_ip(relation_get('private-address', unit, relid))
if addr is not None:
if is_ipv6(addr):
hosts.append('[{}]:6789'.format(addr))
else:
hosts.append('{}:6789'.format(addr))
hosts.sort()
return hosts
@ -166,8 +165,6 @@ def get_devices():
@hooks.hook('mon-relation-changed',
'mon-relation-departed')
def mon_relation():
log('Begin mon-relation hook.')
bootstrap_key = relation_get('osd_bootstrap_key')
if get_fsid() and get_auth() and bootstrap_key:
log('mon has provided conf- scanning disks')
@ -180,18 +177,14 @@ def mon_relation():
else:
log('mon cluster has not yet provided conf')
log('End mon-relation hook.')
@hooks.hook('upgrade-charm')
def upgrade_charm():
log('Begin upgrade-charm hook.')
if get_fsid() and get_auth():
emit_cephconf()
install_upstart_scripts()
apt_install(packages=filter_installed_packages(ceph.PACKAGES),
fatal=True)
log('End upgrade-charm hook.')
if __name__ == '__main__':

View File

@ -9,10 +9,18 @@
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 }}
{%- if ceph_public_network is string %}
public network = {{ ceph_public_network }}
{%- endif %}
{%- if ceph_cluster_network is string %}
cluster network = {{ ceph_cluster_network }}
{%- endif %}
[mon]
keyring = /var/lib/ceph/mon/$cluster-$id/keyring