[trivia] Add missing helper
This commit is contained in:
parent
95520a436e
commit
f5ed6b80af
|
@ -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]qKaUr/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 KKK!K%K*K/K3KLKSKUKVKYK[K\K]K^K`KaKfKiKjKmKnKoKpKqKtKuKzK{K|K‰K‹KŒKŽK<C5BD>K‘K“K”K•K–K<E28093>KŸK¡K£K¤K¦K©K«KK¯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<>M‚MƒM„M…M†M‡MˆM‰MŠM‹MŒM<>MŽM<>M<>M‘M’M“M–M—M˜M™MšM›MœM<>MžMŸM M£M¤M¥M¦M§M¨M«M°M±M²MÃMÄMÅMÊMåMôMõMöM÷MøMùMúMû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€K‚KƒK„K†K‡KˆKŠK‹KŒK<C592>KŽK<C5BD>K<EFBFBD>K‘K’K“K”K•K–K˜K™KšKœK<C593>KžKŸK¡K¢K£K¥K¦K§K«KK°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¦M§M¨M©M«MM®M²M³MµM¶M·M¹M¼M½M¾M¿MÄMÅMÆMÇMÈMÊMÌMÎMÏMÐMÒMÔM×MØMÙMÚMÛMÜMßMáMâMãMäMåMæMçMê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ˆM‹M<>MŽM<>M‘M”M—M˜MšMžMŸM M¡M¢M£M¤M§M¨M©MªM«M¬MM®M¯M°M±M²M³M´MµM¶M¹MºM»M¼M½M¾M¿MÃMÄMÅMÆMÇMÈMÉMËMÌMÍMÎMÏMÐMÑMÔM×eUf/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/openstack/utils.pyq]q(KKKKK KKKKKKKKK!K%K&K'K(K)K*K+K,K0K1K2K3K4K5K6K7K;K<K=K>K?K@KAKBKCKDKEKFKGKHKKKNKSKnKsK|K†K³KÆKÉKÙKâM,M>MRMsMŠM–MªMµeUi/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(KKKKK
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
|
||||||
|
KKK
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(KKKKKKKKK&K+K/K1K4K5K8K?KJKoKpKrKvKwKzK€K<E282AC>K‚KƒK…KµK¶K¸K¹K»KÒKëKìKîMM
MMMMMM]M^M`M†M‡M‰M«M¬M®MÂMÑMÒMÖM×MÙMÝMîMMM M
MMMMM%M4MCMWMgM‚M‹M<>M–MÀMÂMÉMÊMËMÍMôMöMÿMeUg/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/contrib/hahelpers/apache.pyq ]q!(KK
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?KUKVKXK–K¨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
|
||||||
|
KKK
KKKKKKKKK&K/K2K=KFKGKIKNK\K`KdKhKmK{K€K…KŠK<C5A0>K”K™KžKÂKÃKÅKÌKÜKåKîKüKýMM
M M/M0M:M;MDMEMPMQM\M]MhMwM‡MˆM›M¢M©M³M¸M¹MºM½MÑMÓMÔMÕM×MÙMÛMãMåMæMçMéMêMëMìMíMî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(KKKKKKKK*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(KKKKKKKKKKKKKKKKK K!K#K$K%K&K'K(K)K+K,K-K.K/K0K1K3K4K5K6K7K8K9K;K<K=K>K?K@KAKBKIKLKMKNKQKRKUKVKYKZK]K_KaKfKkKnKuK‹Kœ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:(KKKKKKK)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
|
||||||
|
KKKKKKRK]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
|
||||||
|
KKKKKK)K9KAKJKWKpK<70>K<EFBFBD>K¦eUY/home/jamespage/src/charms/landing/nova-cloud-controller/hooks/charmhelpers/core/fstab.pyqE]qF(KKK KKKKKK!K)K+K2K9KCKJKRKhKiKpKqeuu.
|
|
@ -8,3 +8,4 @@ include:
|
||||||
- contrib.hahelpers:
|
- contrib.hahelpers:
|
||||||
- apache
|
- apache
|
||||||
- payload.execd
|
- payload.execd
|
||||||
|
- contrib.network.ip
|
||||||
|
|
|
@ -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')
|
Loading…
Reference in New Issue