Rebase on trunk helpers

This commit is contained in:
James Page 2014-07-24 11:33:09 +01:00
parent 62dd6aa7dd
commit 32e85a148f
7 changed files with 92 additions and 40 deletions

View File

@ -1,4 +1,4 @@
branch: lp:~james-page/charm-helpers/network-splits branch: lp:charm-helpers
destination: hooks/charmhelpers destination: hooks/charmhelpers
include: include:
- core - core

View File

@ -146,12 +146,12 @@ def get_hacluster_config():
Obtains all relevant configuration from charm configuration required Obtains all relevant configuration from charm configuration required
for initiating a relation to hacluster: for initiating a relation to hacluster:
ha-bindiface, ha-mcastport, vip, vip_iface, vip_cidr ha-bindiface, ha-mcastport, vip
returns: dict: A dict containing settings keyed by setting name. returns: dict: A dict containing settings keyed by setting name.
raises: HAIncompleteConfig if settings are missing. raises: HAIncompleteConfig if settings are missing.
''' '''
settings = ['ha-bindiface', 'ha-mcastport', 'vip', 'vip_iface', 'vip_cidr'] settings = ['ha-bindiface', 'ha-mcastport', 'vip']
conf = {} conf = {}
for setting in settings: for setting in settings:
conf[setting] = config_get(setting) conf[setting] = config_get(setting)
@ -163,7 +163,7 @@ def get_hacluster_config():
return conf return conf
def canonical_url(configs, vip_setting='vip', address=None): def canonical_url(configs, vip_setting='vip'):
''' '''
Returns the correct HTTP URL to this host given the state of HTTPS Returns the correct HTTP URL to this host given the state of HTTPS
configuration and hacluster. configuration and hacluster.
@ -180,5 +180,5 @@ def canonical_url(configs, vip_setting='vip', address=None):
if is_clustered(): if is_clustered():
addr = config_get(vip_setting) addr = config_get(vip_setting)
else: else:
addr = address or unit_get('private-address') addr = unit_get('private-address')
return '%s://%s' % (scheme, addr) return '%s://%s' % (scheme, addr)

View File

@ -1,5 +1,7 @@
import sys import sys
from functools import partial
from charmhelpers.fetch import apt_install from charmhelpers.fetch import apt_install
from charmhelpers.core.hookenv import ( from charmhelpers.core.hookenv import (
ERROR, log, ERROR, log,
@ -28,7 +30,7 @@ def _validate_cidr(network):
def get_address_in_network(network, fallback=None, fatal=False): def get_address_in_network(network, fallback=None, fatal=False):
""" """
Get an IPv4 address within the network from the host. Get an IPv4 or IPv6 address within the network from the host.
:param network (str): CIDR presentation format. For example, :param network (str): CIDR presentation format. For example,
'192.168.1.0/24'. '192.168.1.0/24'.
@ -51,14 +53,22 @@ def get_address_in_network(network, fallback=None, fatal=False):
not_found_error_out() not_found_error_out()
_validate_cidr(network) _validate_cidr(network)
network = netaddr.IPNetwork(network)
for iface in netifaces.interfaces(): for iface in netifaces.interfaces():
addresses = netifaces.ifaddresses(iface) addresses = netifaces.ifaddresses(iface)
if netifaces.AF_INET in addresses: if network.version == 4 and netifaces.AF_INET in addresses:
addr = addresses[netifaces.AF_INET][0]['addr'] addr = addresses[netifaces.AF_INET][0]['addr']
netmask = addresses[netifaces.AF_INET][0]['netmask'] netmask = addresses[netifaces.AF_INET][0]['netmask']
cidr = netaddr.IPNetwork("%s/%s" % (addr, netmask)) cidr = netaddr.IPNetwork("%s/%s" % (addr, netmask))
if cidr in netaddr.IPNetwork(network): if cidr in network:
return str(cidr.ip) 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: if fallback is not None:
return fallback return fallback
@ -69,6 +79,17 @@ def get_address_in_network(network, fallback=None, fatal=False):
return None 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): def is_address_in_network(network, address):
""" """
Determine whether the provided address is within a network range. Determine whether the provided address is within a network range.
@ -93,3 +114,43 @@ def is_address_in_network(network, address):
return True return True
else: else:
return False 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

@ -21,12 +21,16 @@ def del_bridge(name):
subprocess.check_call(["ovs-vsctl", "--", "--if-exists", "del-br", name]) subprocess.check_call(["ovs-vsctl", "--", "--if-exists", "del-br", name])
def add_bridge_port(name, port): def add_bridge_port(name, port, promisc=False):
''' Add a port to the named openvswitch bridge ''' ''' Add a port to the named openvswitch bridge '''
log('Adding port {} to bridge {}'.format(port, name)) log('Adding port {} to bridge {}'.format(port, name))
subprocess.check_call(["ovs-vsctl", "--", "--may-exist", "add-port", subprocess.check_call(["ovs-vsctl", "--", "--may-exist", "add-port",
name, port]) name, port])
subprocess.check_call(["ip", "link", "set", port, "up"]) subprocess.check_call(["ip", "link", "set", port, "up"])
if promisc:
subprocess.check_call(["ip", "link", "set", port, "promisc", "on"])
else:
subprocess.check_call(["ip", "link", "set", port, "promisc", "off"])
def del_bridge_port(name, port): def del_bridge_port(name, port):
@ -35,6 +39,7 @@ def del_bridge_port(name, port):
subprocess.check_call(["ovs-vsctl", "--", "--if-exists", "del-port", subprocess.check_call(["ovs-vsctl", "--", "--if-exists", "del-port",
name, port]) name, port])
subprocess.check_call(["ip", "link", "set", port, "down"]) subprocess.check_call(["ip", "link", "set", port, "down"])
subprocess.check_call(["ip", "link", "set", port, "promisc", "off"])
def set_manager(manager): def set_manager(manager):

View File

@ -25,6 +25,7 @@ from charmhelpers.core.hookenv import (
unit_get, unit_get,
unit_private_ip, unit_private_ip,
ERROR, ERROR,
INFO
) )
from charmhelpers.contrib.hahelpers.cluster import ( from charmhelpers.contrib.hahelpers.cluster import (
@ -400,7 +401,9 @@ class HAProxyContext(OSContextGenerator):
cluster_hosts = {} cluster_hosts = {}
l_unit = local_unit().replace('/', '-') l_unit = local_unit().replace('/', '-')
cluster_hosts[l_unit] = unit_get('private-address') cluster_hosts[l_unit] = \
get_address_in_network(config('os-internal-network'),
unit_get('private-address'))
for rid in relation_ids('cluster'): for rid in relation_ids('cluster'):
for unit in related_units(rid): for unit in related_units(rid):
@ -712,7 +715,7 @@ class SubordinateConfigContext(OSContextGenerator):
self.interface = interface self.interface = interface
def __call__(self): def __call__(self):
ctxt = {} ctxt = {'sections': {}}
for rid in relation_ids(self.interface): for rid in relation_ids(self.interface):
for unit in related_units(rid): for unit in related_units(rid):
sub_config = relation_get('subordinate_configuration', sub_config = relation_get('subordinate_configuration',
@ -738,10 +741,14 @@ class SubordinateConfigContext(OSContextGenerator):
sub_config = sub_config[self.config_file] sub_config = sub_config[self.config_file]
for k, v in sub_config.iteritems(): for k, v in sub_config.iteritems():
ctxt[k] = v if k == 'sections':
for section, config_dict in v.iteritems():
log("adding section '%s'" % (section))
ctxt[k][section] = config_dict
else:
ctxt[k] = v
if not ctxt: log("%d section(s) found" % (len(ctxt['sections'])), level=INFO)
ctxt['sections'] = {}
return ctxt return ctxt

View File

@ -1,25 +0,0 @@
from netaddr import IPAddress, IPNetwork
class VIPConfiguration():
def __init__(self, configuration):
self.vip = []
for vip in configuration.split():
self.vips.append(IPAddress(vip))
def getVIP(self, network):
''' Determine the VIP for the provided network
:network str: CIDR presented network, e.g. 192.168.1.1/24
:returns str: IP address of VIP in provided network or None
'''
network = IPNetwork(network)
for vip in self.vips:
if vip in network:
return str(vip)
return None
def getNIC(self, network):
''' Determine the physical network interface in use
for the specified network'''

View File

@ -322,6 +322,10 @@ def cmp_pkgrevno(package, revno, pkgcache=None):
import apt_pkg import apt_pkg
if not pkgcache: if not pkgcache:
apt_pkg.init() apt_pkg.init()
# Force Apt to build its cache in memory. That way we avoid race
# conditions with other applications building the cache in the same
# place.
apt_pkg.config.set("Dir::Cache::pkgcache", "")
pkgcache = apt_pkg.Cache() pkgcache = apt_pkg.Cache()
pkg = pkgcache[package] pkg = pkgcache[package]
return apt_pkg.version_compare(pkg.current_ver.ver_str, revno) return apt_pkg.version_compare(pkg.current_ver.ver_str, revno)