[trivia] Add missing helper

This commit is contained in:
James Page 2014-07-28 13:05:42 +01:00
parent 95520a436e
commit f5ed6b80af
4 changed files with 165 additions and 0 deletions

8
.coverage Normal file
View File

@ -0,0 +1,8 @@
}q(U collectorqUcoverage v3.7.1qUlinesq}q(Um/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/alternatives.pyq]Uh/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/storage/linux/lvm.pyq]q(KK KK(K3KEKOeUg/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/storage/__init__.pyq ]q
KaU\/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/core/__init__.pyq ]q KaUr/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/amulet/deployment.pyq ]UO/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/nova_cc_hooks.pyq]q(KKKKKK K KK!K%K*K/K3KLKSKUKVKYK[K\K]K^K`KaKfKiKjKmKnKoKpKqKtKuKzK{K|K‰KKŒKŽK<C5BD>KK“K”K•KK<E28093>KŸK¡K£K¤K¦K©K«K­K¯K°K²KµK¶K¸K¹KºK»K½K¾K¿KÀKÁKÄKÅKÇKÈKÉKÊKÌKÍKÎKÏKÐKÓKÔKÜKÝKæKçKîKïMMMM M%M2M3M4M5M6M8M9M;M<M?MAMBMCMDMEMGMHMIMJMMMNMOMQMRMSMTMUMVMWMXM[M\M]M_M`MaMdMhMkMlMoMpMqMrMtMuMvMyMzM{M|M}M~MM€M<>MM„M…M†M‡MˆM‰MM<>M<>M<>MMM“MM—M˜M™MM<>M MMMMMMMMMMMMM!M$M%M*M5M6M7M8M9M:M;M<M=M>M?M@MCMDMFMGMHMIMJMMMNMPMQMRMSMTMUMVMYM`eUm/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/storage/linux/__init__.pyq]qKaUi/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/storage/linux/ceph.pyq]UO/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/nova_cc_utils.pyq]q(KKKKKKK K
K KKKK)K.K0K2K6K7K8K9K:K;K?K@KAKBKCKFKGKHKIKJKKKLKOKPKQKSKTKUKVKWKXKYKZK[K\K^K_K`KaKbKcKdKeKfKgKhKiKjKkKlKmKnKpKqKrKtKuKvKwKxKyKzK{K|K}K~KK€KKƒK„K†K‡KˆKŠKKŒK<C592>KŽK<C5BD>K<EFBFBD>KKK“K”K•KK˜K™KšKœK<C593>KžKŸK¡K¢K£K¥K¦K§K«K­K°KµK·KºK»K½K¿KÀKÂKÄKÅKÆKÇKÈKÊKËKÎKÏKÐKÑKÒKÓKÖK×KØKÙKÚKÛKÝKÞKßKàKáKâKãKæKçKêKëKîKïKðKñKòKóKôKõK÷KúMMMMM MMMMMMMMMM!M#M$M%M&M'M(M)M*M-M.M/M0M1M2M3M4M5M7M8M9M;M=M@MEMHMJMMMNMOMPMQMRMSMUMdMgMmMqMrMuMwMxM{M“M­M¿M×MM M
M MMMMMMMMMMMMMM M#M$M%M&M+M,M-M.M1M3M4M5M:M;M<M=M>M@MBMCMDMGMHMIMLMQMlMvM€M<>M…M†MˆMM<>M<>MM”M—M˜M M­M´M¿M×eUf/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/utils.pyq]q(KKKKK K KKKKKKKK!K%K&K'K(K)K*K+K,K0K1K2K3K4K5K6K7K;K<K=K>K?K@KAKBKCKDKEKFKGKHKKKNKSKnKsK|K†K³KÆKÉKÙKâM,M>MRMsMeUi/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/hahelpers/__init__.pyq]qKaUk/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/templating.pyq]q(KKKK K KKKKKFKJKKKUKaKkK³K´KÅKÎKÓKÙKòMMMeUm/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/amulet/utils.pyq]UX/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/core/host.pyq]q(KKK K
K K K KKKKKKK K%K.K4KAKWKbKmKyK‰K”KšK K±K¿KÈKÓKâKãKäKåKçKèKéKìKíKîKñKòKôKõKøMMMM%M0M:eUh/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/context.pyq]q(KKKKKK KKK&K+K/K1K4K5K8K?KJKoKpKrKvKwKzK€K<E282AC>KKƒK…KµK¶K¸K¹K»KÒKëKìKîM M MMMMMM]M^M`M†M‡M‰M×MMM M MMMMM%M4MCMWMgMMM<>MMÿMeUg/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/hahelpers/apache.pyq ]q!(K K KK)K6eUm/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/storage/linux/loopback.pyq"]q#(KKKKK K-eUQ/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/nova_cc_context.pyq$]q%(KKKK KKKKK K"K)K*K<K=K?KUKVKXKK¨K©K«K°K´KºK¿KÐKÒKãKäKçKèKêKëKìeUe/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/hahelpers/ceph.pyq&]Uc/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/ip.pyq']Up/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/amulet/__init__.pyq(]U[/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/fetch/bzrurl.pyq)]U[/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/core/hookenv.pyq*]q+(KKKK K
K K K KKKKKKKKK&K/K2K=KFKGKIKNK\K`KdKhKmK{K€K…KŠK<C5A0>K”K™KžKÂKÃKÅKÌKÜKåKîKüKýM M M M/M0M:M;MDMEMPMQM\M]MhMwM‡MˆMM¸M×eUW/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/__init__.pyq,]q-KaU_/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/fetch/archiveurl.pyq.]Us/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/templates/__init__.pyq/]Uh/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/neutron.pyq0]q1(KKK KKKKK*KOKRKžK´eUg/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/network/__init__.pyq2]q3KaUJ/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/__init__.pyq4]U]/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/fetch/__init__.pyq5]q6(KKKKKK K KKKKKKKKKK K!K#K$K%K&K'K(K)K+K,K-K.K/K0K1K3K4K5K6K7K8K9K;K<K=K>K?K@KAKBKIKLKMKNKQKRKUKVKYKZK]K_KaKfKkKnKuKKœK«K±K¼KËKêKëKìMM*M0MCeUi/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/__init__.pyq7]q8KaUj/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/storage/linux/utils.pyq9]q:(KKKKK KK)eU\/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/payload/execd.pyq;]q<(KKKKK K KK$K0eU_/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/payload/__init__.pyq=]q>KaUa/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/network/ip.pyq?]q@(KKKKK
K KKKKKRK]KwKšKœeU_/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/__init__.pyqA]qBKaUh/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/hahelpers/cluster.pyqC]qD(K K
K KKKKK)K9KAKJKWKpK<70>K<EFBFBD>K¦eUY/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/core/fstab.pyqE]qF(KKK K KKKKK!K)K+K2K9KCKJKRKhKiKpKqeuu.

View File

@ -8,3 +8,4 @@ include:
- contrib.hahelpers:
- apache
- payload.execd
- contrib.network.ip

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')