[james-page,r=dosaboy] Add configuration options for ceph public and cluster networks.
This commit is contained in:
commit
eb1d0968d3
|
@ -6,3 +6,4 @@ include:
|
|||
- contrib.storage.linux:
|
||||
- utils
|
||||
- contrib.openstack.alternatives
|
||||
- contrib.network.ip
|
||||
|
|
10
config.yaml
10
config.yaml
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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')
|
|
@ -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__':
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue