From d7a613df25163bb6d47aba802ffbb74b9ac967b7 Mon Sep 17 00:00:00 2001 From: James Page Date: Sun, 31 Mar 2013 12:21:09 +0100 Subject: [PATCH] Add missing files --- .project | 17 +++ .pydevproject | 8 ++ hooks/lib/utils.py | 332 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 357 insertions(+) create mode 100644 .project create mode 100644 .pydevproject create mode 100644 hooks/lib/utils.py diff --git a/.project b/.project new file mode 100644 index 0000000..9e30b38 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + ceilometer + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000..e5dca87 --- /dev/null +++ b/.pydevproject @@ -0,0 +1,8 @@ + + + +/ceilometer + +python 2.7 +Default + diff --git a/hooks/lib/utils.py b/hooks/lib/utils.py new file mode 100644 index 0000000..1033a58 --- /dev/null +++ b/hooks/lib/utils.py @@ -0,0 +1,332 @@ +# +# Copyright 2012 Canonical Ltd. +# +# This file is sourced from lp:openstack-charm-helpers +# +# Authors: +# James Page +# Paul Collins +# Adam Gandelman +# + +import json +import os +import subprocess +import socket +import sys + + +def do_hooks(hooks): + hook = os.path.basename(sys.argv[0]) + + try: + hook_func = hooks[hook] + except KeyError: + juju_log('INFO', + "This charm doesn't know how to handle '{}'.".format(hook)) + else: + hook_func() + + +def install(*pkgs): + cmd = [ + 'apt-get', + '-y', + 'install' + ] + for pkg in pkgs: + cmd.append(pkg) + subprocess.check_call(cmd) + +TEMPLATES_DIR = 'templates' + +try: + import jinja2 +except ImportError: + install('python-jinja2') + import jinja2 + +try: + import dns.resolver +except ImportError: + install('python-dnspython') + import dns.resolver + + +def render_template(template_name, context, template_dir=TEMPLATES_DIR): + templates = jinja2.Environment( + loader=jinja2.FileSystemLoader(template_dir) + ) + template = templates.get_template(template_name) + return template.render(context) + +CLOUD_ARCHIVE = \ +""" # Ubuntu Cloud Archive +deb http://ubuntu-cloud.archive.canonical.com/ubuntu {} main +""" + +CLOUD_ARCHIVE_POCKETS = { + 'folsom': 'precise-updates/folsom', + 'folsom/updates': 'precise-updates/folsom', + 'folsom/proposed': 'precise-proposed/folsom', + 'grizzly': 'precise-updates/grizzly', + 'grizzly/updates': 'precise-updates/grizzly', + 'grizzly/proposed': 'precise-proposed/grizzly' + } + + +def configure_source(): + source = str(config_get('openstack-origin')) + if not source: + return + if source.startswith('ppa:'): + cmd = [ + 'add-apt-repository', + source + ] + subprocess.check_call(cmd) + if source.startswith('cloud:'): + # CA values should be formatted as cloud:ubuntu-openstack/pocket, eg: + # cloud:precise-folsom/updates or cloud:precise-folsom/proposed + install('ubuntu-cloud-keyring') + pocket = source.split(':')[1] + pocket = pocket.split('-')[1] + with open('/etc/apt/sources.list.d/cloud-archive.list', 'w') as apt: + apt.write(CLOUD_ARCHIVE.format(CLOUD_ARCHIVE_POCKETS[pocket])) + if source.startswith('deb'): + l = len(source.split('|')) + if l == 2: + (apt_line, key) = source.split('|') + cmd = [ + 'apt-key', + 'adv', '--keyserver keyserver.ubuntu.com', + '--recv-keys', key + ] + subprocess.check_call(cmd) + elif l == 1: + apt_line = source + + with open('/etc/apt/sources.list.d/quantum.list', 'w') as apt: + apt.write(apt_line + "\n") + cmd = [ + 'apt-get', + 'update' + ] + subprocess.check_call(cmd) + +# Protocols +TCP = 'TCP' +UDP = 'UDP' + + +def expose(port, protocol='TCP'): + cmd = [ + 'open-port', + '{}/{}'.format(port, protocol) + ] + subprocess.check_call(cmd) + + +def juju_log(severity, message): + cmd = [ + 'juju-log', + '--log-level', severity, + message + ] + subprocess.check_call(cmd) + + +cache = {} + + +def cached(func): + def wrapper(*args, **kwargs): + global cache + key = str((func, args, kwargs)) + try: + return cache[key] + except KeyError: + res = func(*args, **kwargs) + cache[key] = res + return res + return wrapper + + +@cached +def relation_ids(relation): + cmd = [ + 'relation-ids', + relation + ] + result = str(subprocess.check_output(cmd)).split() + if result == "": + return None + else: + return result + + +@cached +def relation_list(rid): + cmd = [ + 'relation-list', + '-r', rid, + ] + result = str(subprocess.check_output(cmd)).split() + if result == "": + return None + else: + return result + + +@cached +def relation_get(attribute, unit=None, rid=None): + cmd = [ + 'relation-get', + ] + if rid: + cmd.append('-r') + cmd.append(rid) + cmd.append(attribute) + if unit: + cmd.append(unit) + value = subprocess.check_output(cmd).strip() # IGNORE:E1103 + if value == "": + return None + else: + return value + + +@cached +def relation_get_dict(relation_id=None, remote_unit=None): + """Obtain all relation data as dict by way of JSON""" + cmd = [ + 'relation-get', '--format=json' + ] + if relation_id: + cmd.append('-r') + cmd.append(relation_id) + if remote_unit: + remote_unit_orig = os.getenv('JUJU_REMOTE_UNIT', None) + os.environ['JUJU_REMOTE_UNIT'] = remote_unit + j = subprocess.check_output(cmd) + if remote_unit and remote_unit_orig: + os.environ['JUJU_REMOTE_UNIT'] = remote_unit_orig + d = json.loads(j) + settings = {} + # convert unicode to strings + for k, v in d.iteritems(): + settings[str(k)] = str(v) + return settings + + +def relation_set(**kwargs): + cmd = [ + 'relation-set' + ] + args = [] + for k, v in kwargs.items(): + if k == 'rid': + if v: + cmd.append('-r') + cmd.append(v) + else: + args.append('{}={}'.format(k, v)) + cmd += args + subprocess.check_call(cmd) + + +@cached +def unit_get(attribute): + cmd = [ + 'unit-get', + attribute + ] + value = subprocess.check_output(cmd).strip() # IGNORE:E1103 + if value == "": + return None + else: + return value + + +@cached +def config_get(attribute): + cmd = [ + 'config-get', + '--format', + 'json', + ] + out = subprocess.check_output(cmd).strip() # IGNORE:E1103 + cfg = json.loads(out) + + try: + return cfg[attribute] + except KeyError: + return None + + +@cached +def get_unit_hostname(): + return socket.gethostname() + + +@cached +def get_host_ip(hostname=unit_get('private-address')): + try: + # Test to see if already an IPv4 address + socket.inet_aton(hostname) + return hostname + except socket.error: + answers = dns.resolver.query(hostname, 'A') + if answers: + return answers[0].address + return None + + +def _svc_control(service, action): + subprocess.check_call(['service', service, action]) + + +def restart(*services): + for service in services: + _svc_control(service, 'restart') + + +def stop(*services): + for service in services: + _svc_control(service, 'stop') + + +def start(*services): + for service in services: + _svc_control(service, 'start') + + +def reload(*services): + for service in services: + try: + _svc_control(service, 'reload') + except subprocess.CalledProcessError: + # Reload failed - either service does not support reload + # or it was not running - restart will fixup most things + _svc_control(service, 'restart') + + +def running(service): + try: + output = subprocess.check_output(['service', service, 'status']) + except subprocess.CalledProcessError: + return False + else: + if ("start/running" in output or + "is running" in output): + return True + else: + return False + + +def is_relation_made(relation, key='private-address'): + for r_id in (relation_ids(relation) or []): + for unit in (relation_list(r_id) or []): + if relation_get(key, rid=r_id, unit=unit): + return True + return False