synced charm-helpers

This commit is contained in:
Edward Hope-Morley 2014-09-26 13:41:08 +01:00
parent 81d88b4c22
commit 1c71af51d8
8 changed files with 90 additions and 35 deletions

View File

@ -1 +1,2 @@
}q(U collectorqUcoverage v3.7.1qUlinesq}u.
}q(U collectorqUcoverage v3.7.1qUlinesq}q(UT/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/plugins/manager.pyq]q(KXKYK]K^K_K`KcKiKjKkKoKrKvKxKyK{K|K}K€K†K‰KŠKKŒK<C592>KŽK<C5BD>K<EFBFBD>K•K¦K§K¨K±K²K¸KùKúKûKüKýKþeUJ/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/suite.pyq]q (K4KCKNKOKPK]K^K_K`KaKfKgKhKjKpKqK“K”K•KK˜K™KšKKœK<C593>K¬K°KÈKËKÌKÏKÐK×KØKÙKßKáKâKãM M MMMMMMMMMM M!M"M#M$M(M)M,M-M.M/M3M4M5M7M8M9M:MBMCMHMIMJMPMQMRMSMTMUMXMYMZM[M\M]M^McMdMeMgMhMiMkMlMmMnMoMsMtMuM‰MM<>MMM“M”M•MM¸MMMMM M!M"M#M&M'M)eUT/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/plugins/capture.pyq
]q (K:K;KEKJKKKLKPK`KaKbKeKfKoKpeUK/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/loader.pyq ]q (KOKQKRKSKTKUKVKYKZK[K\K]K^K_KaKcMjMlMoMpMsMtM<>M<>M<>eUI/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/util.pyq]q(KKŒK<C592>KŽK¢K£KÝKßKàKáKâKãKåM1M2M3M4M5M6M7M8M9M:M;M<M=M>M?M@MAMBMPMQMRMSMUMXM¿eUI/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/core.pyq]q(K"K$K%K)K*K+K,K2K3K7K8K;K<K=K>KAKBK»K¼KÁKÇKÈKÉKÊKËKÌKÍKÏeUM/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/importer.pyq]q(KK K<>K<EFBFBD>KK“K”K•K—K˜K™KšKKœK<C593>KžK¡eUL/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/failure.pyq]q(KKKKKKKKK%K&K'eUR/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/plugins/cover.pyq]q(K¤K¥eUM/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/selector.pyq]q(K#K%K(K)K*K+K,K-KÞKàKáKâKãKäKåKæKçKèKïKðKñKôeUK/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/result.pyq]q(K&K'K(K)K+K,K;K<K=KAKEKKKLKMKQKRKXKYKZKaKbKgKhKiKjKmKnKžKŸK¶K·KºK»eUW/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/plugins/errorclass.pyq]q(KŒK<C592>K<EFBFBD>K<EFBFBD>K”KK—K˜K™KšeUJ/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/proxy.pyq]q(KK+K-K.K/K9K:K;K<K>K@KNKPKQKRKSKYK`KfKgKhKnKoKpKtKuKvKzK{K|K}K€K<E282AC>KKƒK„K…K¨K©KªK°K±K²eUN/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/pyversion.pyq ]q!K­aUI/home/user1/Desktop/reviews/venv/lib/python2.7/site-packages/nose/case.pyq"]q#(KK!K"K$K%K&K'K(K)K*K-K0K1K3K;K<K@KEKFKJKcKdKeKfKgKhK€K<E282AC>KKƒK„K…KŒK“K”K•K—KšKKŸK K¡K¢K£K¦K§K¨K¬K­K²K³K¹euu.

View File

@ -20,20 +20,27 @@ from charmhelpers.core.hookenv import (
)
def get_cert():
def get_cert(cn=None):
# TODO: deal with multiple https endpoints via charm config
cert = config_get('ssl_cert')
key = config_get('ssl_key')
if not (cert and key):
log("Inspecting identity-service relations for SSL certificate.",
level=INFO)
cert = key = None
if cn:
ssl_cert_attr = 'ssl_cert_{}'.format(cn)
ssl_key_attr = 'ssl_key_{}'.format(cn)
else:
ssl_cert_attr = 'ssl_cert'
ssl_key_attr = 'ssl_key'
for r_id in relation_ids('identity-service'):
for unit in relation_list(r_id):
if not cert:
cert = relation_get('ssl_cert',
cert = relation_get(ssl_cert_attr,
rid=r_id, unit=unit)
if not key:
key = relation_get('ssl_key',
key = relation_get(ssl_key_attr,
rid=r_id, unit=unit)
return (cert, key)

View File

@ -139,10 +139,9 @@ def https():
return True
for r_id in relation_ids('identity-service'):
for unit in relation_list(r_id):
# TODO - needs fixing for new helper as ssl_cert/key suffixes with CN
rel_state = [
relation_get('https_keystone', rid=r_id, unit=unit),
relation_get('ssl_cert', rid=r_id, unit=unit),
relation_get('ssl_key', rid=r_id, unit=unit),
relation_get('ca_cert', rid=r_id, unit=unit),
]
# NOTE: works around (LP: #1203241)

View File

@ -1,4 +1,6 @@
import glob
import re
import subprocess
import sys
from functools import partial
@ -172,7 +174,8 @@ def format_ipv6_addr(address):
return address
def get_iface_addr(iface='eth0', inet_type='AF_INET', inc_aliases=False, fatal=True, exc_list=None):
def get_iface_addr(iface='eth0', inet_type='AF_INET', inc_aliases=False,
fatal=True, exc_list=None):
"""
Return the assigned IP address for a given interface, if any, or [].
"""
@ -212,26 +215,67 @@ def get_iface_addr(iface='eth0', inet_type='AF_INET', inc_aliases=False, fatal=T
if 'addr' in entry and entry['addr'] not in exc_list:
addresses.append(entry['addr'])
if fatal and not addresses:
raise Exception("Interface '%s' doesn't have any %s addresses." % (iface, inet_type))
raise Exception("Interface '%s' doesn't have any %s addresses." %
(iface, inet_type))
return addresses
get_ipv4_addr = partial(get_iface_addr, inet_type='AF_INET')
def get_ipv6_addr(iface='eth0', inc_aliases=False, fatal=True, exc_list=None):
"""
Return the assigned IPv6 address for a given interface, if any, or [].
def get_ipv6_addr(iface='eth0', inc_aliases=False, fatal=True, exc_list=None,
dynamic_only=True):
"""Get assigned IPv6 address for a given interface.
Returns list of addresses found. If no address found, returns empty list.
We currently only support scope global IPv6 addresses i.e. non-temporary
addresses. If no global IPv6 address is found, return the first one found
in the ipv6 address list.
"""
addresses = get_iface_addr(iface=iface, inet_type='AF_INET6',
inc_aliases=inc_aliases, fatal=fatal,
exc_list=exc_list)
remotly_addressable = []
for address in addresses:
if not address.startswith('fe80'):
remotly_addressable.append(address)
if fatal and not remotly_addressable:
raise Exception("Interface '%s' doesn't have global ipv6 address." % iface)
return remotly_addressable
if addresses:
global_addrs = []
for addr in addresses:
key_scope_link_local = re.compile("^fe80::..(.+)%(.+)")
m = re.match(key_scope_link_local, addr)
if m:
eui_64_mac = m.group(1)
iface = m.group(2)
else:
global_addrs.append(addr)
if global_addrs:
# Make sure any found global addresses are not temporary
cmd = ['ip', 'addr', 'show', iface]
out = subprocess.check_output(cmd)
if dynamic_only:
key = re.compile("inet6 (.+)/[0-9]+ scope global dynamic.*")
else:
key = re.compile("inet6 (.+)/[0-9]+ scope global.*")
addrs = []
for line in out.split('\n'):
line = line.strip()
m = re.match(key, line)
if m and 'temporary' not in line:
# Return the first valid address we find
for addr in global_addrs:
if m.group(1) == addr:
if not dynamic_only or \
m.group(1).endswith(eui_64_mac):
addrs.append(addr)
if addrs:
return addrs
if fatal:
raise Exception("Interface '%s' doesn't have a scope global "
"non-temporary ipv6 address." % iface)
return []
def get_bridges(vnic_dir='/sys/devices/virtual/net'):

View File

@ -486,9 +486,10 @@ class Hooks(object):
hooks.execute(sys.argv)
"""
def __init__(self):
def __init__(self, config_save=True):
super(Hooks, self).__init__()
self._hooks = {}
self._config_save = config_save
def register(self, name, function):
"""Register a hook"""
@ -499,9 +500,10 @@ class Hooks(object):
hook_name = os.path.basename(args[0])
if hook_name in self._hooks:
self._hooks[hook_name]()
cfg = config()
if cfg.implicit_save:
cfg.save()
if self._config_save:
cfg = config()
if cfg.implicit_save:
cfg.save()
else:
raise UnregisteredHookError(hook_name)

View File

@ -68,8 +68,8 @@ def service_available(service_name):
"""Determine whether a system service is available"""
try:
subprocess.check_output(['service', service_name, 'status'], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
return False
except subprocess.CalledProcessError as e:
return 'unrecognized service' not in e.output
else:
return True
@ -229,12 +229,12 @@ def check_hash(path, checksum, hash_type='md5'):
"""
Validate a file using a cryptographic checksum.
:param str checksum: Value of the checksum used to validate the file.
:param str hash_type: Hash algorithm used to generate :param:`checksum`.
Can be any hash alrgorithm supported by :mod:`hashlib`,
such as md5, sha1, sha256, sha512, etc.
:param str hash_type: Hash algorithm used to generate `checksum`.
Can be any hash alrgorithm supported by :mod:`hashlib`,
such as md5, sha1, sha256, sha512, etc.
:raises ChecksumError: If the file fails the checksum
"""
actual_checksum = file_hash(path, hash_type)
if checksum != actual_checksum:

View File

@ -208,7 +208,8 @@ def add_source(source, key=None):
"""Add a package source to this system.
@param source: a URL or sources.list entry, as supported by
add-apt-repository(1). Examples:
add-apt-repository(1). Examples::
ppa:charmers/example
deb https://stub:key@private.example.com/ubuntu trusty main

View File

@ -74,18 +74,19 @@ class ArchiveUrlFetchHandler(BaseFetchHandler):
"""
Download and install an archive file, with optional checksum validation.
The checksum can also be given on the :param:`source` URL's fragment.
The checksum can also be given on the `source` URL's fragment.
For example::
handler.install('http://example.com/file.tgz#sha1=deadbeef')
:param str source: URL pointing to an archive file.
:param str dest: Local destination path to install to. If not given,
installs to `$CHARM_DIR/archives/archive_file_name`.
:param str dest: Local destination path to install to. If not given,
installs to `$CHARM_DIR/archives/archive_file_name`.
:param str checksum: If given, validate the archive file after download.
:param str hash_type: Algorithm used to generate :param:`checksum`.
Can be any hash alrgorithm supported by :mod:`hashlib`,
such as md5, sha1, sha256, sha512, etc.
:param str hash_type: Algorithm used to generate `checksum`.
Can be any hash alrgorithm supported by :mod:`hashlib`,
such as md5, sha1, sha256, sha512, etc.
"""
url_parts = self.parse_url(source)
dest_dir = os.path.join(os.environ.get('CHARM_DIR'), 'fetched')