diff options
author | Stuart Mackie <wsmackie@juniper.net> | 2017-03-23 06:19:54 -0700 |
---|---|---|
committer | Stuart Mackie <wsmackie@juniper.net> | 2017-03-23 06:19:54 -0700 |
commit | 88df88a19674ccc0017836941b8ee32eaadf19fb (patch) | |
tree | f930c90f75846ec8d8e33cf27325ff8fafc85d5c /charms/trusty/neutron-contrail | |
parent | 9f50a40437477432a21b326b15c343ca6b8fe516 (diff) |
Deleted charms with wrong license. Will source them differently in future.
Change-Id: I0fc99ea03c6b6ca4701e63793cb2be60e56c7588
Signed-off-by: Stuart Mackie <wsmackie@juniper.net>
Diffstat (limited to 'charms/trusty/neutron-contrail')
66 files changed, 0 insertions, 5832 deletions
diff --git a/charms/trusty/neutron-contrail/.bzrignore b/charms/trusty/neutron-contrail/.bzrignore deleted file mode 100644 index ba077a4..0000000 --- a/charms/trusty/neutron-contrail/.bzrignore +++ /dev/null @@ -1 +0,0 @@ -bin diff --git a/charms/trusty/neutron-contrail/Makefile b/charms/trusty/neutron-contrail/Makefile deleted file mode 100644 index 378713f..0000000 --- a/charms/trusty/neutron-contrail/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/make -PYTHON := /usr/bin/env python - -bin/charm_helpers_sync.py: - @mkdir -p bin - @bzr cat lp:charm-helpers/tools/charm_helpers_sync/charm_helpers_sync.py \ - > bin/charm_helpers_sync.py - -sync: bin/charm_helpers_sync.py - @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-sync.yaml diff --git a/charms/trusty/neutron-contrail/README.md b/charms/trusty/neutron-contrail/README.md deleted file mode 100644 index 6257304..0000000 --- a/charms/trusty/neutron-contrail/README.md +++ /dev/null @@ -1,131 +0,0 @@ -Overview --------- - -OpenContrail (www.opencontrail.org) is a fully featured Software Defined -Networking (SDN) solution for private clouds. It supports high performance -isolated tenant networks without requiring external hardware support. It -provides a Neutron plugin to integrate with OpenStack. - -This charm is designed to be used in conjunction with the rest of the OpenStack -related charms in the charm store to virtualize the network that Nova Compute -instances plug into. - -This subordinate charm provides the Nova Compute vRouter component which -contains the contrail-vrouter-agent service. -Only OpenStack Icehouse or newer is supported. -Juju 1.23.2+ required. - -Usage ------ - -Nova Compute, Contrail Configuration and Keystone are prerequisite services to -deploy. - -Nova Compute should be deployed with legacy plugin management set to false: - - nova-compute: - manage-neutron-plugin-legacy-mode: false - -Once ready, deploy and relate as follows: - - juju deploy neutron-contrail - juju add-relation nova-compute neutron-contrail - juju add-relation neutron-contrail:contrail-discovery contrail-configuration:contrail-discovery - juju add-relation neutron-contrail:contrail-api contrail-configuration:contrail-api - juju add-relation neutron-contrail keystone - -Install Sources ---------------- - -The version of OpenContrail installed when deploying can be changed using the -'install-sources' option. This is a multilined value that may refer to PPAs or -Deb repositories. - -Control Node Relation ---------------------- - -This charm is typically related to contrail-configuration:contrail-discovery. -This instructs the Contrail vRouter agent to use the discovery service for -locating control nodes. This is the recommended approach. - -Should the user wish to use vRouter configuration that specifies the location -of control nodes explicitly, not using the discovery service, they can relate -to a contrail-control charm: - - juju add-relation neutron-contrail contrail-control - -Nova Metadata -------------- - -To use Nova Metadata with Nova Compute instances, a metadata service must first -be registered. Registration allows OpenContrail to create the appropriate -network config to proxy requests from instances to a nova-api service on the -network. - -Option 'local-metadata-server' controls if a local nova-api-metadata service is -started (per Compute Node) and registered to serve metadata requests. It is -the recommended approach for serving metadata to instances and is enabled by -default. - -Alternatively, relating to a charm implementing neutron-metadata interface will -use this external metadata service: - - juju add-relation neutron-contrail neutron-metadata-charm - -contrail-configuration charm also needs to be related to the same charm to -register the metadata service: - - juju add-relation contrail-configuration neutron-metadata-charm - -Virtual Gateways ----------------- - -For launched instances to be able to access external networks e.g. the Internet -a gateway is required that allows virtual network traffic to traverse an IP -network. - -For production setups, this is typically a hardware gateway. For testing -purposes OpenContrail provides a software gateway (Simple Gateway) that runs on -Compute Node(s) and provides this function. - -Option 'virtual-gateways' allows specifying of one or more software gateways. -The value is a YAML encoded string using a list of maps, where each map -consists of the following attributes: - - project - project name - network - network name - interface - interface to use (will be created) - subnets - list of virtual subnets to route - routes - list of routes gateway will make available to virtual subnets, - 0.0.0.0/0 selects all routes - -For example to create a gateway for virtual subnet 10.0.10.0/24 on -'admin:public' network using local interface vgw for routing: - - juju set neutron-contrail \ - "virtual-gateways=[ { project: admin, network: public, interface: vgw, subnets: [ 10.0.10.0/24 ], routes: [ 0.0.0.0/0 ] } ]" - -Previously specified gateways will be removed. - -The routing of external IP networks needs to be updated if virtual network -traffic will traverse it. Traffic flow from the IP network should be directed to -one of the Compute Nodes. - -For example a static route could be added to the router of the Compute Node -network: - - // assuming it's a linux box - sudo ip route add 10.0.10.0/24 via <compute ip> - -The virtual-gateways option can be used with 'floating-ip-pools' option of the -contrail-configuration charm to create a typical Neutron setup of launched -instances attached to a private network, each with an assigned public/external -floating IP. - -Using the running example above, you would use Neutron to create an external -network with subnet 10.0.10.0/24 and a private network of 10.0.5.0/24. You would -set the virtual-gateways option (as above) and the floating-ip-pools option. -You would attach launched instances to the private network and then assign them -floating IPs from the external network. vRouter will automatically perform 1:1 -NAT of an external address to a private one. (Note: security groups may still -need to be updated to allow traffic flow). diff --git a/charms/trusty/neutron-contrail/charm-helpers-sync.yaml b/charms/trusty/neutron-contrail/charm-helpers-sync.yaml deleted file mode 100644 index 0af5672..0000000 --- a/charms/trusty/neutron-contrail/charm-helpers-sync.yaml +++ /dev/null @@ -1,5 +0,0 @@ -branch: lp:charm-helpers -destination: hooks/charmhelpers -include: - - core - - fetch diff --git a/charms/trusty/neutron-contrail/config.yaml b/charms/trusty/neutron-contrail/config.yaml deleted file mode 100644 index 8430326..0000000 --- a/charms/trusty/neutron-contrail/config.yaml +++ /dev/null @@ -1,74 +0,0 @@ -options: - install-sources: - type: string - default: | - - "ppa:opencontrail/ppa" - - "ppa:opencontrail/r2.20" - description: Package sources for install - install-keys: - type: string - description: Apt keys for package install sources - vhost-interface: - type: string - description: | - Specify the interface to install vhost0 on. If left empty, vhost0 will - be installed on the default gateway interface. - vhost-gateway: - type: string - default: auto - description: | - Specify the gateway for vhost0, either an IPv4 address or keyword 'auto'. - 'auto' will set gateway automatically based on host's existing routes. - control-interface: - type: string - default: vhost0 - description: | - Specify the interface to use for the control channel. - Default is to use vRouter interface that will be created. - local-metadata-server: - type: boolean - default: true - description: | - Run a local instance of nova-api-metadata for serving metadata to VMs. - An external metadata server (neutron-metadata relation) is not required - when enabled. - remove-juju-bridge: - type: boolean - default: false - description: | - Juju on MAAS creates a juju-br0 bridge for deploying LXC and KVM - workloads. Enable this to remove this bridge if you want to install - vhost0 directly on the underlying interface. - - WARNING: This will break current and future juju-deployed LXC or KVM - workloads on all machines where this is set to true. - virtual-gateways: - type: string - description: | - Virtual gateways to create (software based). - - Using a YAML encoded string specify one or more gateways using a list - of maps, where each map consists of the following attributes: - - project - project name - network - network name - interface - interface to use (will be created) - subnets - list of virtual subnets to route - routes - list of routes gateway will make available to virtual subnets, - 0.0.0.0/0 selects all routes - - For example: - - // make any network available to virtual subnet 10.0.10.0/24 on - // admin:public network using local interface vgw to route - [ { project: admin, network: public, interface: vgw, subnets: [ 10.0.10.0/24 ], routes: [ 0.0.0.0/0 ] } ] - # development options - contrail-api-ip: - type: string - description: Specify contrail-api ip manually - contrail-api-port: - type: int - description: Specify contrail-api port manually - discovery-server-ip: - type: string - description: Specify discovery server ip manually diff --git a/charms/trusty/neutron-contrail/copyright b/charms/trusty/neutron-contrail/copyright deleted file mode 100644 index 4081144..0000000 --- a/charms/trusty/neutron-contrail/copyright +++ /dev/null @@ -1,17 +0,0 @@ -Format: http://dep.debian.net/deps/dep5/ - -Files: * -Copyright: Copyright 2014, Canonical Ltd., All Rights Reserved. -License: GPL-3 - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - . - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. diff --git a/charms/trusty/neutron-contrail/files/60-vrouter-vgw.conf b/charms/trusty/neutron-contrail/files/60-vrouter-vgw.conf deleted file mode 100644 index 3e7fe4c..0000000 --- a/charms/trusty/neutron-contrail/files/60-vrouter-vgw.conf +++ /dev/null @@ -1,3 +0,0 @@ -# sysctl values for vrouter gateway - -net.ipv4.ip_forward=1 diff --git a/charms/trusty/neutron-contrail/files/contrail-nodemgr-vrouter.ini b/charms/trusty/neutron-contrail/files/contrail-nodemgr-vrouter.ini deleted file mode 100644 index 860812d..0000000 --- a/charms/trusty/neutron-contrail/files/contrail-nodemgr-vrouter.ini +++ /dev/null @@ -1,6 +0,0 @@ -[eventlistener:contrail-vrouter-nodemgr] -command=/bin/bash -c "exec python /usr/bin/contrail-nodemgr --nodetype=contrail-vrouter" -events=PROCESS_COMMUNICATION,PROCESS_STATE,TICK_60 -buffer_size=10000 -stdout_logfile=/var/log/contrail/contrail-vrouter-nodemgr-stdout.log -stderr_logfile=/var/log/contrail/contrail-vrouter-nodemgr-stderr.log diff --git a/charms/trusty/neutron-contrail/files/contrail-vrouter-nodemgr b/charms/trusty/neutron-contrail/files/contrail-vrouter-nodemgr deleted file mode 100644 index 1c6a55b..0000000 --- a/charms/trusty/neutron-contrail/files/contrail-vrouter-nodemgr +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -# chkconfig: 2345 99 01 -# description: Juniper Network vRouter Node Manager - -supervisorctl -s unix:///tmp/supervisord_vrouter.sock ${1} `basename ${0}` diff --git a/charms/trusty/neutron-contrail/files/contrail-vrouter.rules b/charms/trusty/neutron-contrail/files/contrail-vrouter.rules deleted file mode 100644 index 54cba11..0000000 --- a/charms/trusty/neutron-contrail/files/contrail-vrouter.rules +++ /dev/null @@ -1,3 +0,0 @@ -{ "Rules": [ - ] -} diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/__init__.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/__init__.py deleted file mode 100644 index f72e7f8..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -# Bootstrap charm-helpers, installing its dependencies if necessary using -# only standard libraries. -import subprocess -import sys - -try: - import six # flake8: noqa -except ImportError: - if sys.version_info.major == 2: - subprocess.check_call(['apt-get', 'install', '-y', 'python-six']) - else: - subprocess.check_call(['apt-get', 'install', '-y', 'python3-six']) - import six # flake8: noqa - -try: - import yaml # flake8: noqa -except ImportError: - if sys.version_info.major == 2: - subprocess.check_call(['apt-get', 'install', '-y', 'python-yaml']) - else: - subprocess.check_call(['apt-get', 'install', '-y', 'python3-yaml']) - import yaml # flake8: noqa diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/__init__.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/__init__.py deleted file mode 100644 index d1400a0..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/decorators.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/decorators.py deleted file mode 100644 index bb05620..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/decorators.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -# -# Copyright 2014 Canonical Ltd. -# -# Authors: -# Edward Hope-Morley <opentastic@gmail.com> -# - -import time - -from charmhelpers.core.hookenv import ( - log, - INFO, -) - - -def retry_on_exception(num_retries, base_delay=0, exc_type=Exception): - """If the decorated function raises exception exc_type, allow num_retries - retry attempts before raise the exception. - """ - def _retry_on_exception_inner_1(f): - def _retry_on_exception_inner_2(*args, **kwargs): - retries = num_retries - multiplier = 1 - while True: - try: - return f(*args, **kwargs) - except exc_type: - if not retries: - raise - - delay = base_delay * multiplier - multiplier += 1 - log("Retrying '%s' %d more times (delay=%s)" % - (f.__name__, retries, delay), level=INFO) - retries -= 1 - if delay: - time.sleep(delay) - - return _retry_on_exception_inner_2 - - return _retry_on_exception_inner_1 diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/files.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/files.py deleted file mode 100644 index 0f12d32..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/files.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -__author__ = 'Jorge Niedbalski <niedbalski@ubuntu.com>' - -import os -import subprocess - - -def sed(filename, before, after, flags='g'): - """ - Search and replaces the given pattern on filename. - - :param filename: relative or absolute file path. - :param before: expression to be replaced (see 'man sed') - :param after: expression to replace with (see 'man sed') - :param flags: sed-compatible regex flags in example, to make - the search and replace case insensitive, specify ``flags="i"``. - The ``g`` flag is always specified regardless, so you do not - need to remember to include it when overriding this parameter. - :returns: If the sed command exit code was zero then return, - otherwise raise CalledProcessError. - """ - expression = r's/{0}/{1}/{2}'.format(before, - after, flags) - - return subprocess.check_call(["sed", "-i", "-r", "-e", - expression, - os.path.expanduser(filename)]) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/fstab.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/fstab.py deleted file mode 100644 index 3056fba..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/fstab.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import io -import os - -__author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>' - - -class Fstab(io.FileIO): - """This class extends file in order to implement a file reader/writer - for file `/etc/fstab` - """ - - class Entry(object): - """Entry class represents a non-comment line on the `/etc/fstab` file - """ - def __init__(self, device, mountpoint, filesystem, - options, d=0, p=0): - self.device = device - self.mountpoint = mountpoint - self.filesystem = filesystem - - if not options: - options = "defaults" - - self.options = options - self.d = int(d) - self.p = int(p) - - def __eq__(self, o): - return str(self) == str(o) - - def __str__(self): - return "{} {} {} {} {} {}".format(self.device, - self.mountpoint, - self.filesystem, - self.options, - self.d, - self.p) - - DEFAULT_PATH = os.path.join(os.path.sep, 'etc', 'fstab') - - def __init__(self, path=None): - if path: - self._path = path - else: - self._path = self.DEFAULT_PATH - super(Fstab, self).__init__(self._path, 'rb+') - - def _hydrate_entry(self, line): - # NOTE: use split with no arguments to split on any - # whitespace including tabs - return Fstab.Entry(*filter( - lambda x: x not in ('', None), - line.strip("\n").split())) - - @property - def entries(self): - self.seek(0) - for line in self.readlines(): - line = line.decode('us-ascii') - try: - if line.strip() and not line.strip().startswith("#"): - yield self._hydrate_entry(line) - except ValueError: - pass - - def get_entry_by_attr(self, attr, value): - for entry in self.entries: - e_attr = getattr(entry, attr) - if e_attr == value: - return entry - return None - - def add_entry(self, entry): - if self.get_entry_by_attr('device', entry.device): - return False - - self.write((str(entry) + '\n').encode('us-ascii')) - self.truncate() - return entry - - def remove_entry(self, entry): - self.seek(0) - - lines = [l.decode('us-ascii') for l in self.readlines()] - - found = False - for index, line in enumerate(lines): - if line.strip() and not line.strip().startswith("#"): - if self._hydrate_entry(line) == entry: - found = True - break - - if not found: - return False - - lines.remove(line) - - self.seek(0) - self.write(''.join(lines).encode('us-ascii')) - self.truncate() - return True - - @classmethod - def remove_by_mountpoint(cls, mountpoint, path=None): - fstab = cls(path=path) - entry = fstab.get_entry_by_attr('mountpoint', mountpoint) - if entry: - return fstab.remove_entry(entry) - return False - - @classmethod - def add(cls, device, mountpoint, filesystem, options=None, path=None): - return cls(path=path).add_entry(Fstab.Entry(device, - mountpoint, filesystem, - options=options)) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/hookenv.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/hookenv.py deleted file mode 100644 index ab53a78..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/hookenv.py +++ /dev/null @@ -1,898 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -"Interactions with the Juju environment" -# Copyright 2013 Canonical Ltd. -# -# Authors: -# Charm Helpers Developers <juju@lists.ubuntu.com> - -from __future__ import print_function -import copy -from distutils.version import LooseVersion -from functools import wraps -import glob -import os -import json -import yaml -import subprocess -import sys -import errno -import tempfile -from subprocess import CalledProcessError - -import six -if not six.PY3: - from UserDict import UserDict -else: - from collections import UserDict - -CRITICAL = "CRITICAL" -ERROR = "ERROR" -WARNING = "WARNING" -INFO = "INFO" -DEBUG = "DEBUG" -MARKER = object() - -cache = {} - - -def cached(func): - """Cache return values for multiple executions of func + args - - For example:: - - @cached - def unit_get(attribute): - pass - - unit_get('test') - - will cache the result of unit_get + 'test' for future calls. - """ - @wraps(func) - def wrapper(*args, **kwargs): - global cache - key = str((func, args, kwargs)) - try: - return cache[key] - except KeyError: - pass # Drop out of the exception handler scope. - res = func(*args, **kwargs) - cache[key] = res - return res - wrapper._wrapped = func - return wrapper - - -def flush(key): - """Flushes any entries from function cache where the - key is found in the function+args """ - flush_list = [] - for item in cache: - if key in item: - flush_list.append(item) - for item in flush_list: - del cache[item] - - -def log(message, level=None): - """Write a message to the juju log""" - command = ['juju-log'] - if level: - command += ['-l', level] - if not isinstance(message, six.string_types): - message = repr(message) - command += [message] - # Missing juju-log should not cause failures in unit tests - # Send log output to stderr - try: - subprocess.call(command) - except OSError as e: - if e.errno == errno.ENOENT: - if level: - message = "{}: {}".format(level, message) - message = "juju-log: {}".format(message) - print(message, file=sys.stderr) - else: - raise - - -class Serializable(UserDict): - """Wrapper, an object that can be serialized to yaml or json""" - - def __init__(self, obj): - # wrap the object - UserDict.__init__(self) - self.data = obj - - def __getattr__(self, attr): - # See if this object has attribute. - if attr in ("json", "yaml", "data"): - return self.__dict__[attr] - # Check for attribute in wrapped object. - got = getattr(self.data, attr, MARKER) - if got is not MARKER: - return got - # Proxy to the wrapped object via dict interface. - try: - return self.data[attr] - except KeyError: - raise AttributeError(attr) - - def __getstate__(self): - # Pickle as a standard dictionary. - return self.data - - def __setstate__(self, state): - # Unpickle into our wrapper. - self.data = state - - def json(self): - """Serialize the object to json""" - return json.dumps(self.data) - - def yaml(self): - """Serialize the object to yaml""" - return yaml.dump(self.data) - - -def execution_environment(): - """A convenient bundling of the current execution context""" - context = {} - context['conf'] = config() - if relation_id(): - context['reltype'] = relation_type() - context['relid'] = relation_id() - context['rel'] = relation_get() - context['unit'] = local_unit() - context['rels'] = relations() - context['env'] = os.environ - return context - - -def in_relation_hook(): - """Determine whether we're running in a relation hook""" - return 'JUJU_RELATION' in os.environ - - -def relation_type(): - """The scope for the current relation hook""" - return os.environ.get('JUJU_RELATION', None) - - -@cached -def relation_id(relation_name=None, service_or_unit=None): - """The relation ID for the current or a specified relation""" - if not relation_name and not service_or_unit: - return os.environ.get('JUJU_RELATION_ID', None) - elif relation_name and service_or_unit: - service_name = service_or_unit.split('/')[0] - for relid in relation_ids(relation_name): - remote_service = remote_service_name(relid) - if remote_service == service_name: - return relid - else: - raise ValueError('Must specify neither or both of relation_name and service_or_unit') - - -def local_unit(): - """Local unit ID""" - return os.environ['JUJU_UNIT_NAME'] - - -def remote_unit(): - """The remote unit for the current relation hook""" - return os.environ.get('JUJU_REMOTE_UNIT', None) - - -def service_name(): - """The name service group this unit belongs to""" - return local_unit().split('/')[0] - - -@cached -def remote_service_name(relid=None): - """The remote service name for a given relation-id (or the current relation)""" - if relid is None: - unit = remote_unit() - else: - units = related_units(relid) - unit = units[0] if units else None - return unit.split('/')[0] if unit else None - - -def hook_name(): - """The name of the currently executing hook""" - return os.environ.get('JUJU_HOOK_NAME', os.path.basename(sys.argv[0])) - - -class Config(dict): - """A dictionary representation of the charm's config.yaml, with some - extra features: - - - See which values in the dictionary have changed since the previous hook. - - For values that have changed, see what the previous value was. - - Store arbitrary data for use in a later hook. - - NOTE: Do not instantiate this object directly - instead call - ``hookenv.config()``, which will return an instance of :class:`Config`. - - Example usage:: - - >>> # inside a hook - >>> from charmhelpers.core import hookenv - >>> config = hookenv.config() - >>> config['foo'] - 'bar' - >>> # store a new key/value for later use - >>> config['mykey'] = 'myval' - - - >>> # user runs `juju set mycharm foo=baz` - >>> # now we're inside subsequent config-changed hook - >>> config = hookenv.config() - >>> config['foo'] - 'baz' - >>> # test to see if this val has changed since last hook - >>> config.changed('foo') - True - >>> # what was the previous value? - >>> config.previous('foo') - 'bar' - >>> # keys/values that we add are preserved across hooks - >>> config['mykey'] - 'myval' - - """ - CONFIG_FILE_NAME = '.juju-persistent-config' - - def __init__(self, *args, **kw): - super(Config, self).__init__(*args, **kw) - self.implicit_save = True - self._prev_dict = None - self.path = os.path.join(charm_dir(), Config.CONFIG_FILE_NAME) - if os.path.exists(self.path): - self.load_previous() - atexit(self._implicit_save) - - def load_previous(self, path=None): - """Load previous copy of config from disk. - - In normal usage you don't need to call this method directly - it - is called automatically at object initialization. - - :param path: - - File path from which to load the previous config. If `None`, - config is loaded from the default location. If `path` is - specified, subsequent `save()` calls will write to the same - path. - - """ - self.path = path or self.path - with open(self.path) as f: - self._prev_dict = json.load(f) - for k, v in copy.deepcopy(self._prev_dict).items(): - if k not in self: - self[k] = v - - def changed(self, key): - """Return True if the current value for this key is different from - the previous value. - - """ - if self._prev_dict is None: - return True - return self.previous(key) != self.get(key) - - def previous(self, key): - """Return previous value for this key, or None if there - is no previous value. - - """ - if self._prev_dict: - return self._prev_dict.get(key) - return None - - def save(self): - """Save this config to disk. - - If the charm is using the :mod:`Services Framework <services.base>` - or :meth:'@hook <Hooks.hook>' decorator, this - is called automatically at the end of successful hook execution. - Otherwise, it should be called directly by user code. - - To disable automatic saves, set ``implicit_save=False`` on this - instance. - - """ - with open(self.path, 'w') as f: - json.dump(self, f) - - def _implicit_save(self): - if self.implicit_save: - self.save() - - -@cached -def config(scope=None): - """Juju charm configuration""" - config_cmd_line = ['config-get'] - if scope is not None: - config_cmd_line.append(scope) - config_cmd_line.append('--format=json') - try: - config_data = json.loads( - subprocess.check_output(config_cmd_line).decode('UTF-8')) - if scope is not None: - return config_data - return Config(config_data) - except ValueError: - return None - - -@cached -def relation_get(attribute=None, unit=None, rid=None): - """Get relation information""" - _args = ['relation-get', '--format=json'] - if rid: - _args.append('-r') - _args.append(rid) - _args.append(attribute or '-') - if unit: - _args.append(unit) - try: - return json.loads(subprocess.check_output(_args).decode('UTF-8')) - except ValueError: - return None - except CalledProcessError as e: - if e.returncode == 2: - return None - raise - - -def relation_set(relation_id=None, relation_settings=None, **kwargs): - """Set relation information for the current unit""" - relation_settings = relation_settings if relation_settings else {} - relation_cmd_line = ['relation-set'] - accepts_file = "--file" in subprocess.check_output( - relation_cmd_line + ["--help"], universal_newlines=True) - if relation_id is not None: - relation_cmd_line.extend(('-r', relation_id)) - settings = relation_settings.copy() - settings.update(kwargs) - for key, value in settings.items(): - # Force value to be a string: it always should, but some call - # sites pass in things like dicts or numbers. - if value is not None: - settings[key] = "{}".format(value) - if accepts_file: - # --file was introduced in Juju 1.23.2. Use it by default if - # available, since otherwise we'll break if the relation data is - # too big. Ideally we should tell relation-set to read the data from - # stdin, but that feature is broken in 1.23.2: Bug #1454678. - with tempfile.NamedTemporaryFile(delete=False) as settings_file: - settings_file.write(yaml.safe_dump(settings).encode("utf-8")) - subprocess.check_call( - relation_cmd_line + ["--file", settings_file.name]) - os.remove(settings_file.name) - else: - for key, value in settings.items(): - if value is None: - relation_cmd_line.append('{}='.format(key)) - else: - relation_cmd_line.append('{}={}'.format(key, value)) - subprocess.check_call(relation_cmd_line) - # Flush cache of any relation-gets for local unit - flush(local_unit()) - - -def relation_clear(r_id=None): - ''' Clears any relation data already set on relation r_id ''' - settings = relation_get(rid=r_id, - unit=local_unit()) - for setting in settings: - if setting not in ['public-address', 'private-address']: - settings[setting] = None - relation_set(relation_id=r_id, - **settings) - - -@cached -def relation_ids(reltype=None): - """A list of relation_ids""" - reltype = reltype or relation_type() - relid_cmd_line = ['relation-ids', '--format=json'] - if reltype is not None: - relid_cmd_line.append(reltype) - return json.loads( - subprocess.check_output(relid_cmd_line).decode('UTF-8')) or [] - return [] - - -@cached -def related_units(relid=None): - """A list of related units""" - relid = relid or relation_id() - units_cmd_line = ['relation-list', '--format=json'] - if relid is not None: - units_cmd_line.extend(('-r', relid)) - return json.loads( - subprocess.check_output(units_cmd_line).decode('UTF-8')) or [] - - -@cached -def relation_for_unit(unit=None, rid=None): - """Get the json represenation of a unit's relation""" - unit = unit or remote_unit() - relation = relation_get(unit=unit, rid=rid) - for key in relation: - if key.endswith('-list'): - relation[key] = relation[key].split() - relation['__unit__'] = unit - return relation - - -@cached -def relations_for_id(relid=None): - """Get relations of a specific relation ID""" - relation_data = [] - relid = relid or relation_ids() - for unit in related_units(relid): - unit_data = relation_for_unit(unit, relid) - unit_data['__relid__'] = relid - relation_data.append(unit_data) - return relation_data - - -@cached -def relations_of_type(reltype=None): - """Get relations of a specific type""" - relation_data = [] - reltype = reltype or relation_type() - for relid in relation_ids(reltype): - for relation in relations_for_id(relid): - relation['__relid__'] = relid - relation_data.append(relation) - return relation_data - - -@cached -def metadata(): - """Get the current charm metadata.yaml contents as a python object""" - with open(os.path.join(charm_dir(), 'metadata.yaml')) as md: - return yaml.safe_load(md) - - -@cached -def relation_types(): - """Get a list of relation types supported by this charm""" - rel_types = [] - md = metadata() - for key in ('provides', 'requires', 'peers'): - section = md.get(key) - if section: - rel_types.extend(section.keys()) - return rel_types - - -@cached -def relation_to_interface(relation_name): - """ - Given the name of a relation, return the interface that relation uses. - - :returns: The interface name, or ``None``. - """ - return relation_to_role_and_interface(relation_name)[1] - - -@cached -def relation_to_role_and_interface(relation_name): - """ - Given the name of a relation, return the role and the name of the interface - that relation uses (where role is one of ``provides``, ``requires``, or ``peer``). - - :returns: A tuple containing ``(role, interface)``, or ``(None, None)``. - """ - _metadata = metadata() - for role in ('provides', 'requires', 'peer'): - interface = _metadata.get(role, {}).get(relation_name, {}).get('interface') - if interface: - return role, interface - return None, None - - -@cached -def role_and_interface_to_relations(role, interface_name): - """ - Given a role and interface name, return a list of relation names for the - current charm that use that interface under that role (where role is one - of ``provides``, ``requires``, or ``peer``). - - :returns: A list of relation names. - """ - _metadata = metadata() - results = [] - for relation_name, relation in _metadata.get(role, {}).items(): - if relation['interface'] == interface_name: - results.append(relation_name) - return results - - -@cached -def interface_to_relations(interface_name): - """ - Given an interface, return a list of relation names for the current - charm that use that interface. - - :returns: A list of relation names. - """ - results = [] - for role in ('provides', 'requires', 'peer'): - results.extend(role_and_interface_to_relations(role, interface_name)) - return results - - -@cached -def charm_name(): - """Get the name of the current charm as is specified on metadata.yaml""" - return metadata().get('name') - - -@cached -def relations(): - """Get a nested dictionary of relation data for all related units""" - rels = {} - for reltype in relation_types(): - relids = {} - for relid in relation_ids(reltype): - units = {local_unit(): relation_get(unit=local_unit(), rid=relid)} - for unit in related_units(relid): - reldata = relation_get(unit=unit, rid=relid) - units[unit] = reldata - relids[relid] = units - rels[reltype] = relids - return rels - - -@cached -def is_relation_made(relation, keys='private-address'): - ''' - Determine whether a relation is established by checking for - presence of key(s). If a list of keys is provided, they - must all be present for the relation to be identified as made - ''' - if isinstance(keys, str): - keys = [keys] - for r_id in relation_ids(relation): - for unit in related_units(r_id): - context = {} - for k in keys: - context[k] = relation_get(k, rid=r_id, - unit=unit) - if None not in context.values(): - return True - return False - - -def open_port(port, protocol="TCP"): - """Open a service network port""" - _args = ['open-port'] - _args.append('{}/{}'.format(port, protocol)) - subprocess.check_call(_args) - - -def close_port(port, protocol="TCP"): - """Close a service network port""" - _args = ['close-port'] - _args.append('{}/{}'.format(port, protocol)) - subprocess.check_call(_args) - - -@cached -def unit_get(attribute): - """Get the unit ID for the remote unit""" - _args = ['unit-get', '--format=json', attribute] - try: - return json.loads(subprocess.check_output(_args).decode('UTF-8')) - except ValueError: - return None - - -def unit_public_ip(): - """Get this unit's public IP address""" - return unit_get('public-address') - - -def unit_private_ip(): - """Get this unit's private IP address""" - return unit_get('private-address') - - -class UnregisteredHookError(Exception): - """Raised when an undefined hook is called""" - pass - - -class Hooks(object): - """A convenient handler for hook functions. - - Example:: - - hooks = Hooks() - - # register a hook, taking its name from the function name - @hooks.hook() - def install(): - pass # your code here - - # register a hook, providing a custom hook name - @hooks.hook("config-changed") - def config_changed(): - pass # your code here - - if __name__ == "__main__": - # execute a hook based on the name the program is called by - hooks.execute(sys.argv) - """ - - def __init__(self, config_save=None): - super(Hooks, self).__init__() - self._hooks = {} - - # For unknown reasons, we allow the Hooks constructor to override - # config().implicit_save. - if config_save is not None: - config().implicit_save = config_save - - def register(self, name, function): - """Register a hook""" - self._hooks[name] = function - - def execute(self, args): - """Execute a registered hook based on args[0]""" - _run_atstart() - hook_name = os.path.basename(args[0]) - if hook_name in self._hooks: - try: - self._hooks[hook_name]() - except SystemExit as x: - if x.code is None or x.code == 0: - _run_atexit() - raise - _run_atexit() - else: - raise UnregisteredHookError(hook_name) - - def hook(self, *hook_names): - """Decorator, registering them as hooks""" - def wrapper(decorated): - for hook_name in hook_names: - self.register(hook_name, decorated) - else: - self.register(decorated.__name__, decorated) - if '_' in decorated.__name__: - self.register( - decorated.__name__.replace('_', '-'), decorated) - return decorated - return wrapper - - -def charm_dir(): - """Return the root directory of the current charm""" - return os.environ.get('CHARM_DIR') - - -@cached -def action_get(key=None): - """Gets the value of an action parameter, or all key/value param pairs""" - cmd = ['action-get'] - if key is not None: - cmd.append(key) - cmd.append('--format=json') - action_data = json.loads(subprocess.check_output(cmd).decode('UTF-8')) - return action_data - - -def action_set(values): - """Sets the values to be returned after the action finishes""" - cmd = ['action-set'] - for k, v in list(values.items()): - cmd.append('{}={}'.format(k, v)) - subprocess.check_call(cmd) - - -def action_fail(message): - """Sets the action status to failed and sets the error message. - - The results set by action_set are preserved.""" - subprocess.check_call(['action-fail', message]) - - -def action_name(): - """Get the name of the currently executing action.""" - return os.environ.get('JUJU_ACTION_NAME') - - -def action_uuid(): - """Get the UUID of the currently executing action.""" - return os.environ.get('JUJU_ACTION_UUID') - - -def action_tag(): - """Get the tag for the currently executing action.""" - return os.environ.get('JUJU_ACTION_TAG') - - -def status_set(workload_state, message): - """Set the workload state with a message - - Use status-set to set the workload state with a message which is visible - to the user via juju status. If the status-set command is not found then - assume this is juju < 1.23 and juju-log the message unstead. - - workload_state -- valid juju workload state. - message -- status update message - """ - valid_states = ['maintenance', 'blocked', 'waiting', 'active'] - if workload_state not in valid_states: - raise ValueError( - '{!r} is not a valid workload state'.format(workload_state) - ) - cmd = ['status-set', workload_state, message] - try: - ret = subprocess.call(cmd) - if ret == 0: - return - except OSError as e: - if e.errno != errno.ENOENT: - raise - log_message = 'status-set failed: {} {}'.format(workload_state, - message) - log(log_message, level='INFO') - - -def status_get(): - """Retrieve the previously set juju workload state and message - - If the status-get command is not found then assume this is juju < 1.23 and - return 'unknown', "" - - """ - cmd = ['status-get', "--format=json", "--include-data"] - try: - raw_status = subprocess.check_output(cmd) - except OSError as e: - if e.errno == errno.ENOENT: - return ('unknown', "") - else: - raise - else: - status = json.loads(raw_status.decode("UTF-8")) - return (status["status"], status["message"]) - - -def translate_exc(from_exc, to_exc): - def inner_translate_exc1(f): - def inner_translate_exc2(*args, **kwargs): - try: - return f(*args, **kwargs) - except from_exc: - raise to_exc - - return inner_translate_exc2 - - return inner_translate_exc1 - - -@translate_exc(from_exc=OSError, to_exc=NotImplementedError) -def is_leader(): - """Does the current unit hold the juju leadership - - Uses juju to determine whether the current unit is the leader of its peers - """ - cmd = ['is-leader', '--format=json'] - return json.loads(subprocess.check_output(cmd).decode('UTF-8')) - - -@translate_exc(from_exc=OSError, to_exc=NotImplementedError) -def leader_get(attribute=None): - """Juju leader get value(s)""" - cmd = ['leader-get', '--format=json'] + [attribute or '-'] - return json.loads(subprocess.check_output(cmd).decode('UTF-8')) - - -@translate_exc(from_exc=OSError, to_exc=NotImplementedError) -def leader_set(settings=None, **kwargs): - """Juju leader set value(s)""" - # Don't log secrets. - # log("Juju leader-set '%s'" % (settings), level=DEBUG) - cmd = ['leader-set'] - settings = settings or {} - settings.update(kwargs) - for k, v in settings.items(): - if v is None: - cmd.append('{}='.format(k)) - else: - cmd.append('{}={}'.format(k, v)) - subprocess.check_call(cmd) - - -@cached -def juju_version(): - """Full version string (eg. '1.23.3.1-trusty-amd64')""" - # Per https://bugs.launchpad.net/juju-core/+bug/1455368/comments/1 - jujud = glob.glob('/var/lib/juju/tools/machine-*/jujud')[0] - return subprocess.check_output([jujud, 'version'], - universal_newlines=True).strip() - - -@cached -def has_juju_version(minimum_version): - """Return True if the Juju version is at least the provided version""" - return LooseVersion(juju_version()) >= LooseVersion(minimum_version) - - -_atexit = [] -_atstart = [] - - -def atstart(callback, *args, **kwargs): - '''Schedule a callback to run before the main hook. - - Callbacks are run in the order they were added. - - This is useful for modules and classes to perform initialization - and inject behavior. In particular: - - - Run common code before all of your hooks, such as logging - the hook name or interesting relation data. - - Defer object or module initialization that requires a hook - context until we know there actually is a hook context, - making testing easier. - - Rather than requiring charm authors to include boilerplate to - invoke your helper's behavior, have it run automatically if - your object is instantiated or module imported. - - This is not at all useful after your hook framework as been launched. - ''' - global _atstart - _atstart.append((callback, args, kwargs)) - - -def atexit(callback, *args, **kwargs): - '''Schedule a callback to run on successful hook completion. - - Callbacks are run in the reverse order that they were added.''' - _atexit.append((callback, args, kwargs)) - - -def _run_atstart(): - '''Hook frameworks must invoke this before running the main hook body.''' - global _atstart - for callback, args, kwargs in _atstart: - callback(*args, **kwargs) - del _atstart[:] - - -def _run_atexit(): - '''Hook frameworks must invoke this after the main hook body has - successfully completed. Do not invoke it if the hook fails.''' - global _atexit - for callback, args, kwargs in reversed(_atexit): - callback(*args, **kwargs) - del _atexit[:] diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/host.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/host.py deleted file mode 100644 index cb3c527..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/host.py +++ /dev/null @@ -1,586 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -"""Tools for working with the host system""" -# Copyright 2012 Canonical Ltd. -# -# Authors: -# Nick Moffitt <nick.moffitt@canonical.com> -# Matthew Wedgwood <matthew.wedgwood@canonical.com> - -import os -import re -import pwd -import glob -import grp -import random -import string -import subprocess -import hashlib -from contextlib import contextmanager -from collections import OrderedDict - -import six - -from .hookenv import log -from .fstab import Fstab - - -def service_start(service_name): - """Start a system service""" - return service('start', service_name) - - -def service_stop(service_name): - """Stop a system service""" - return service('stop', service_name) - - -def service_restart(service_name): - """Restart a system service""" - return service('restart', service_name) - - -def service_reload(service_name, restart_on_failure=False): - """Reload a system service, optionally falling back to restart if - reload fails""" - service_result = service('reload', service_name) - if not service_result and restart_on_failure: - service_result = service('restart', service_name) - return service_result - - -def service_pause(service_name, init_dir="/etc/init", initd_dir="/etc/init.d"): - """Pause a system service. - - Stop it, and prevent it from starting again at boot.""" - stopped = service_stop(service_name) - upstart_file = os.path.join(init_dir, "{}.conf".format(service_name)) - sysv_file = os.path.join(initd_dir, service_name) - if os.path.exists(upstart_file): - override_path = os.path.join( - init_dir, '{}.override'.format(service_name)) - with open(override_path, 'w') as fh: - fh.write("manual\n") - elif os.path.exists(sysv_file): - subprocess.check_call(["update-rc.d", service_name, "disable"]) - else: - # XXX: Support SystemD too - raise ValueError( - "Unable to detect {0} as either Upstart {1} or SysV {2}".format( - service_name, upstart_file, sysv_file)) - return stopped - - -def service_resume(service_name, init_dir="/etc/init", - initd_dir="/etc/init.d"): - """Resume a system service. - - Reenable starting again at boot. Start the service""" - upstart_file = os.path.join(init_dir, "{}.conf".format(service_name)) - sysv_file = os.path.join(initd_dir, service_name) - if os.path.exists(upstart_file): - override_path = os.path.join( - init_dir, '{}.override'.format(service_name)) - if os.path.exists(override_path): - os.unlink(override_path) - elif os.path.exists(sysv_file): - subprocess.check_call(["update-rc.d", service_name, "enable"]) - else: - # XXX: Support SystemD too - raise ValueError( - "Unable to detect {0} as either Upstart {1} or SysV {2}".format( - service_name, upstart_file, sysv_file)) - - started = service_start(service_name) - return started - - -def service(action, service_name): - """Control a system service""" - cmd = ['service', service_name, action] - return subprocess.call(cmd) == 0 - - -def service_running(service): - """Determine whether a system service is running""" - try: - output = subprocess.check_output( - ['service', service, 'status'], - stderr=subprocess.STDOUT).decode('UTF-8') - except subprocess.CalledProcessError: - return False - else: - if ("start/running" in output or "is running" in output): - return True - else: - return False - - -def service_available(service_name): - """Determine whether a system service is available""" - try: - subprocess.check_output( - ['service', service_name, 'status'], - stderr=subprocess.STDOUT).decode('UTF-8') - except subprocess.CalledProcessError as e: - return b'unrecognized service' not in e.output - else: - return True - - -def adduser(username, password=None, shell='/bin/bash', system_user=False): - """Add a user to the system""" - try: - user_info = pwd.getpwnam(username) - log('user {0} already exists!'.format(username)) - except KeyError: - log('creating user {0}'.format(username)) - cmd = ['useradd'] - if system_user or password is None: - cmd.append('--system') - else: - cmd.extend([ - '--create-home', - '--shell', shell, - '--password', password, - ]) - cmd.append(username) - subprocess.check_call(cmd) - user_info = pwd.getpwnam(username) - return user_info - - -def user_exists(username): - """Check if a user exists""" - try: - pwd.getpwnam(username) - user_exists = True - except KeyError: - user_exists = False - return user_exists - - -def add_group(group_name, system_group=False): - """Add a group to the system""" - try: - group_info = grp.getgrnam(group_name) - log('group {0} already exists!'.format(group_name)) - except KeyError: - log('creating group {0}'.format(group_name)) - cmd = ['addgroup'] - if system_group: - cmd.append('--system') - else: - cmd.extend([ - '--group', - ]) - cmd.append(group_name) - subprocess.check_call(cmd) - group_info = grp.getgrnam(group_name) - return group_info - - -def add_user_to_group(username, group): - """Add a user to a group""" - cmd = ['gpasswd', '-a', username, group] - log("Adding user {} to group {}".format(username, group)) - subprocess.check_call(cmd) - - -def rsync(from_path, to_path, flags='-r', options=None): - """Replicate the contents of a path""" - options = options or ['--delete', '--executability'] - cmd = ['/usr/bin/rsync', flags] - cmd.extend(options) - cmd.append(from_path) - cmd.append(to_path) - log(" ".join(cmd)) - return subprocess.check_output(cmd).decode('UTF-8').strip() - - -def symlink(source, destination): - """Create a symbolic link""" - log("Symlinking {} as {}".format(source, destination)) - cmd = [ - 'ln', - '-sf', - source, - destination, - ] - subprocess.check_call(cmd) - - -def mkdir(path, owner='root', group='root', perms=0o555, force=False): - """Create a directory""" - log("Making dir {} {}:{} {:o}".format(path, owner, group, - perms)) - uid = pwd.getpwnam(owner).pw_uid - gid = grp.getgrnam(group).gr_gid - realpath = os.path.abspath(path) - path_exists = os.path.exists(realpath) - if path_exists and force: - if not os.path.isdir(realpath): - log("Removing non-directory file {} prior to mkdir()".format(path)) - os.unlink(realpath) - os.makedirs(realpath, perms) - elif not path_exists: - os.makedirs(realpath, perms) - os.chown(realpath, uid, gid) - os.chmod(realpath, perms) - - -def write_file(path, content, owner='root', group='root', perms=0o444): - """Create or overwrite a file with the contents of a byte string.""" - log("Writing file {} {}:{} {:o}".format(path, owner, group, perms)) - uid = pwd.getpwnam(owner).pw_uid - gid = grp.getgrnam(group).gr_gid - with open(path, 'wb') as target: - os.fchown(target.fileno(), uid, gid) - os.fchmod(target.fileno(), perms) - target.write(content) - - -def fstab_remove(mp): - """Remove the given mountpoint entry from /etc/fstab - """ - return Fstab.remove_by_mountpoint(mp) - - -def fstab_add(dev, mp, fs, options=None): - """Adds the given device entry to the /etc/fstab file - """ - return Fstab.add(dev, mp, fs, options=options) - - -def mount(device, mountpoint, options=None, persist=False, filesystem="ext3"): - """Mount a filesystem at a particular mountpoint""" - cmd_args = ['mount'] - if options is not None: - cmd_args.extend(['-o', options]) - cmd_args.extend([device, mountpoint]) - try: - subprocess.check_output(cmd_args) - except subprocess.CalledProcessError as e: - log('Error mounting {} at {}\n{}'.format(device, mountpoint, e.output)) - return False - - if persist: - return fstab_add(device, mountpoint, filesystem, options=options) - return True - - -def umount(mountpoint, persist=False): - """Unmount a filesystem""" - cmd_args = ['umount', mountpoint] - try: - subprocess.check_output(cmd_args) - except subprocess.CalledProcessError as e: - log('Error unmounting {}\n{}'.format(mountpoint, e.output)) - return False - - if persist: - return fstab_remove(mountpoint) - return True - - -def mounts(): - """Get a list of all mounted volumes as [[mountpoint,device],[...]]""" - with open('/proc/mounts') as f: - # [['/mount/point','/dev/path'],[...]] - system_mounts = [m[1::-1] for m in [l.strip().split() - for l in f.readlines()]] - return system_mounts - - -def fstab_mount(mountpoint): - """Mount filesystem using fstab""" - cmd_args = ['mount', mountpoint] - try: - subprocess.check_output(cmd_args) - except subprocess.CalledProcessError as e: - log('Error unmounting {}\n{}'.format(mountpoint, e.output)) - return False - return True - - -def file_hash(path, hash_type='md5'): - """ - Generate a hash checksum of the contents of 'path' or None if not found. - - :param str hash_type: Any hash alrgorithm supported by :mod:`hashlib`, - such as md5, sha1, sha256, sha512, etc. - """ - if os.path.exists(path): - h = getattr(hashlib, hash_type)() - with open(path, 'rb') as source: - h.update(source.read()) - return h.hexdigest() - else: - return None - - -def path_hash(path): - """ - Generate a hash checksum of all files matching 'path'. Standard wildcards - like '*' and '?' are supported, see documentation for the 'glob' module for - more information. - - :return: dict: A { filename: hash } dictionary for all matched files. - Empty if none found. - """ - return { - filename: file_hash(filename) - for filename in glob.iglob(path) - } - - -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 `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: - raise ChecksumError("'%s' != '%s'" % (checksum, actual_checksum)) - - -class ChecksumError(ValueError): - pass - - -def restart_on_change(restart_map, stopstart=False): - """Restart services based on configuration files changing - - This function is used a decorator, for example:: - - @restart_on_change({ - '/etc/ceph/ceph.conf': [ 'cinder-api', 'cinder-volume' ] - '/etc/apache/sites-enabled/*': [ 'apache2' ] - }) - def config_changed(): - pass # your code here - - In this example, the cinder-api and cinder-volume services - would be restarted if /etc/ceph/ceph.conf is changed by the - ceph_client_changed function. The apache2 service would be - restarted if any file matching the pattern got changed, created - or removed. Standard wildcards are supported, see documentation - for the 'glob' module for more information. - """ - def wrap(f): - def wrapped_f(*args, **kwargs): - checksums = {path: path_hash(path) for path in restart_map} - f(*args, **kwargs) - restarts = [] - for path in restart_map: - if path_hash(path) != checksums[path]: - restarts += restart_map[path] - services_list = list(OrderedDict.fromkeys(restarts)) - if not stopstart: - for service_name in services_list: - service('restart', service_name) - else: - for action in ['stop', 'start']: - for service_name in services_list: - service(action, service_name) - return wrapped_f - return wrap - - -def lsb_release(): - """Return /etc/lsb-release in a dict""" - d = {} - with open('/etc/lsb-release', 'r') as lsb: - for l in lsb: - k, v = l.split('=') - d[k.strip()] = v.strip() - return d - - -def pwgen(length=None): - """Generate a random pasword.""" - if length is None: - # A random length is ok to use a weak PRNG - length = random.choice(range(35, 45)) - alphanumeric_chars = [ - l for l in (string.ascii_letters + string.digits) - if l not in 'l0QD1vAEIOUaeiou'] - # Use a crypto-friendly PRNG (e.g. /dev/urandom) for making the - # actual password - random_generator = random.SystemRandom() - random_chars = [ - random_generator.choice(alphanumeric_chars) for _ in range(length)] - return(''.join(random_chars)) - - -def is_phy_iface(interface): - """Returns True if interface is not virtual, otherwise False.""" - if interface: - sys_net = '/sys/class/net' - if os.path.isdir(sys_net): - for iface in glob.glob(os.path.join(sys_net, '*')): - if '/virtual/' in os.path.realpath(iface): - continue - - if interface == os.path.basename(iface): - return True - - return False - - -def get_bond_master(interface): - """Returns bond master if interface is bond slave otherwise None. - - NOTE: the provided interface is expected to be physical - """ - if interface: - iface_path = '/sys/class/net/%s' % (interface) - if os.path.exists(iface_path): - if '/virtual/' in os.path.realpath(iface_path): - return None - - master = os.path.join(iface_path, 'master') - if os.path.exists(master): - master = os.path.realpath(master) - # make sure it is a bond master - if os.path.exists(os.path.join(master, 'bonding')): - return os.path.basename(master) - - return None - - -def list_nics(nic_type=None): - '''Return a list of nics of given type(s)''' - if isinstance(nic_type, six.string_types): - int_types = [nic_type] - else: - int_types = nic_type - - interfaces = [] - if nic_type: - for int_type in int_types: - cmd = ['ip', 'addr', 'show', 'label', int_type + '*'] - ip_output = subprocess.check_output(cmd).decode('UTF-8') - ip_output = ip_output.split('\n') - ip_output = (line for line in ip_output if line) - for line in ip_output: - if line.split()[1].startswith(int_type): - matched = re.search('.*: (' + int_type + - r'[0-9]+\.[0-9]+)@.*', line) - if matched: - iface = matched.groups()[0] - else: - iface = line.split()[1].replace(":", "") - - if iface not in interfaces: - interfaces.append(iface) - else: - cmd = ['ip', 'a'] - ip_output = subprocess.check_output(cmd).decode('UTF-8').split('\n') - ip_output = (line.strip() for line in ip_output if line) - - key = re.compile('^[0-9]+:\s+(.+):') - for line in ip_output: - matched = re.search(key, line) - if matched: - iface = matched.group(1) - iface = iface.partition("@")[0] - if iface not in interfaces: - interfaces.append(iface) - - return interfaces - - -def set_nic_mtu(nic, mtu): - '''Set MTU on a network interface''' - cmd = ['ip', 'link', 'set', nic, 'mtu', mtu] - subprocess.check_call(cmd) - - -def get_nic_mtu(nic): - cmd = ['ip', 'addr', 'show', nic] - ip_output = subprocess.check_output(cmd).decode('UTF-8').split('\n') - mtu = "" - for line in ip_output: - words = line.split() - if 'mtu' in words: - mtu = words[words.index("mtu") + 1] - return mtu - - -def get_nic_hwaddr(nic): - cmd = ['ip', '-o', '-0', 'addr', 'show', nic] - ip_output = subprocess.check_output(cmd).decode('UTF-8') - hwaddr = "" - words = ip_output.split() - if 'link/ether' in words: - hwaddr = words[words.index('link/ether') + 1] - return hwaddr - - -def cmp_pkgrevno(package, revno, pkgcache=None): - '''Compare supplied revno with the revno of the installed package - - * 1 => Installed revno is greater than supplied arg - * 0 => Installed revno is the same as supplied arg - * -1 => Installed revno is less than supplied arg - - This function imports apt_cache function from charmhelpers.fetch if - the pkgcache argument is None. Be sure to add charmhelpers.fetch if - you call this function, or pass an apt_pkg.Cache() instance. - ''' - import apt_pkg - if not pkgcache: - from charmhelpers.fetch import apt_cache - pkgcache = apt_cache() - pkg = pkgcache[package] - return apt_pkg.version_compare(pkg.current_ver.ver_str, revno) - - -@contextmanager -def chdir(d): - cur = os.getcwd() - try: - yield os.chdir(d) - finally: - os.chdir(cur) - - -def chownr(path, owner, group, follow_links=True): - uid = pwd.getpwnam(owner).pw_uid - gid = grp.getgrnam(group).gr_gid - if follow_links: - chown = os.chown - else: - chown = os.lchown - - for root, dirs, files in os.walk(path): - for name in dirs + files: - full = os.path.join(root, name) - broken_symlink = os.path.lexists(full) and not os.path.exists(full) - if not broken_symlink: - chown(full, uid, gid) - - -def lchownr(path, owner, group): - chownr(path, owner, group, follow_links=False) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/hugepage.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/hugepage.py deleted file mode 100644 index 4aaca3f..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/hugepage.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import yaml -from charmhelpers.core import fstab -from charmhelpers.core import sysctl -from charmhelpers.core.host import ( - add_group, - add_user_to_group, - fstab_mount, - mkdir, -) -from charmhelpers.core.strutils import bytes_from_string -from subprocess import check_output - - -def hugepage_support(user, group='hugetlb', nr_hugepages=256, - max_map_count=65536, mnt_point='/run/hugepages/kvm', - pagesize='2MB', mount=True, set_shmmax=False): - """Enable hugepages on system. - - Args: - user (str) -- Username to allow access to hugepages to - group (str) -- Group name to own hugepages - nr_hugepages (int) -- Number of pages to reserve - max_map_count (int) -- Number of Virtual Memory Areas a process can own - mnt_point (str) -- Directory to mount hugepages on - pagesize (str) -- Size of hugepages - mount (bool) -- Whether to Mount hugepages - """ - group_info = add_group(group) - gid = group_info.gr_gid - add_user_to_group(user, group) - sysctl_settings = { - 'vm.nr_hugepages': nr_hugepages, - 'vm.max_map_count': max_map_count, - 'vm.hugetlb_shm_group': gid, - } - if set_shmmax: - shmmax_current = int(check_output(['sysctl', '-n', 'kernel.shmmax'])) - shmmax_minsize = bytes_from_string(pagesize) * nr_hugepages - if shmmax_minsize > shmmax_current: - sysctl_settings['kernel.shmmax'] = shmmax_minsize - sysctl.create(yaml.dump(sysctl_settings), '/etc/sysctl.d/10-hugepage.conf') - mkdir(mnt_point, owner='root', group='root', perms=0o755, force=False) - lfstab = fstab.Fstab() - fstab_entry = lfstab.get_entry_by_attr('mountpoint', mnt_point) - if fstab_entry: - lfstab.remove_entry(fstab_entry) - entry = lfstab.Entry('nodev', mnt_point, 'hugetlbfs', - 'mode=1770,gid={},pagesize={}'.format(gid, pagesize), 0, 0) - lfstab.add_entry(entry) - if mount: - fstab_mount(mnt_point) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/kernel.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/kernel.py deleted file mode 100644 index 5dc6495..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/kernel.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -__author__ = "Jorge Niedbalski <jorge.niedbalski@canonical.com>" - -from charmhelpers.core.hookenv import ( - log, - INFO -) - -from subprocess import check_call, check_output -import re - - -def modprobe(module, persist=True): - """Load a kernel module and configure for auto-load on reboot.""" - cmd = ['modprobe', module] - - log('Loading kernel module %s' % module, level=INFO) - - check_call(cmd) - if persist: - with open('/etc/modules', 'r+') as modules: - if module not in modules.read(): - modules.write(module) - - -def rmmod(module, force=False): - """Remove a module from the linux kernel""" - cmd = ['rmmod'] - if force: - cmd.append('-f') - cmd.append(module) - log('Removing kernel module %s' % module, level=INFO) - return check_call(cmd) - - -def lsmod(): - """Shows what kernel modules are currently loaded""" - return check_output(['lsmod'], - universal_newlines=True) - - -def is_module_loaded(module): - """Checks if a kernel module is already loaded""" - matches = re.findall('^%s[ ]+' % module, lsmod(), re.M) - return len(matches) > 0 - - -def update_initramfs(version='all'): - """Updates an initramfs image""" - return check_call(["update-initramfs", "-k", version, "-u"]) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/__init__.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/__init__.py deleted file mode 100644 index 0928158..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -from .base import * # NOQA -from .helpers import * # NOQA diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/base.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/base.py deleted file mode 100644 index a42660c..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/base.py +++ /dev/null @@ -1,353 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import os -import json -from inspect import getargspec -from collections import Iterable, OrderedDict - -from charmhelpers.core import host -from charmhelpers.core import hookenv - - -__all__ = ['ServiceManager', 'ManagerCallback', - 'PortManagerCallback', 'open_ports', 'close_ports', 'manage_ports', - 'service_restart', 'service_stop'] - - -class ServiceManager(object): - def __init__(self, services=None): - """ - Register a list of services, given their definitions. - - Service definitions are dicts in the following formats (all keys except - 'service' are optional):: - - { - "service": <service name>, - "required_data": <list of required data contexts>, - "provided_data": <list of provided data contexts>, - "data_ready": <one or more callbacks>, - "data_lost": <one or more callbacks>, - "start": <one or more callbacks>, - "stop": <one or more callbacks>, - "ports": <list of ports to manage>, - } - - The 'required_data' list should contain dicts of required data (or - dependency managers that act like dicts and know how to collect the data). - Only when all items in the 'required_data' list are populated are the list - of 'data_ready' and 'start' callbacks executed. See `is_ready()` for more - information. - - The 'provided_data' list should contain relation data providers, most likely - a subclass of :class:`charmhelpers.core.services.helpers.RelationContext`, - that will indicate a set of data to set on a given relation. - - The 'data_ready' value should be either a single callback, or a list of - callbacks, to be called when all items in 'required_data' pass `is_ready()`. - Each callback will be called with the service name as the only parameter. - After all of the 'data_ready' callbacks are called, the 'start' callbacks - are fired. - - The 'data_lost' value should be either a single callback, or a list of - callbacks, to be called when a 'required_data' item no longer passes - `is_ready()`. Each callback will be called with the service name as the - only parameter. After all of the 'data_lost' callbacks are called, - the 'stop' callbacks are fired. - - The 'start' value should be either a single callback, or a list of - callbacks, to be called when starting the service, after the 'data_ready' - callbacks are complete. Each callback will be called with the service - name as the only parameter. This defaults to - `[host.service_start, services.open_ports]`. - - The 'stop' value should be either a single callback, or a list of - callbacks, to be called when stopping the service. If the service is - being stopped because it no longer has all of its 'required_data', this - will be called after all of the 'data_lost' callbacks are complete. - Each callback will be called with the service name as the only parameter. - This defaults to `[services.close_ports, host.service_stop]`. - - The 'ports' value should be a list of ports to manage. The default - 'start' handler will open the ports after the service is started, - and the default 'stop' handler will close the ports prior to stopping - the service. - - - Examples: - - The following registers an Upstart service called bingod that depends on - a mongodb relation and which runs a custom `db_migrate` function prior to - restarting the service, and a Runit service called spadesd:: - - manager = services.ServiceManager([ - { - 'service': 'bingod', - 'ports': [80, 443], - 'required_data': [MongoRelation(), config(), {'my': 'data'}], - 'data_ready': [ - services.template(source='bingod.conf'), - services.template(source='bingod.ini', - target='/etc/bingod.ini', - owner='bingo', perms=0400), - ], - }, - { - 'service': 'spadesd', - 'data_ready': services.template(source='spadesd_run.j2', - target='/etc/sv/spadesd/run', - perms=0555), - 'start': runit_start, - 'stop': runit_stop, - }, - ]) - manager.manage() - """ - self._ready_file = os.path.join(hookenv.charm_dir(), 'READY-SERVICES.json') - self._ready = None - self.services = OrderedDict() - for service in services or []: - service_name = service['service'] - self.services[service_name] = service - - def manage(self): - """ - Handle the current hook by doing The Right Thing with the registered services. - """ - hookenv._run_atstart() - try: - hook_name = hookenv.hook_name() - if hook_name == 'stop': - self.stop_services() - else: - self.reconfigure_services() - self.provide_data() - except SystemExit as x: - if x.code is None or x.code == 0: - hookenv._run_atexit() - hookenv._run_atexit() - - def provide_data(self): - """ - Set the relation data for each provider in the ``provided_data`` list. - - A provider must have a `name` attribute, which indicates which relation - to set data on, and a `provide_data()` method, which returns a dict of - data to set. - - The `provide_data()` method can optionally accept two parameters: - - * ``remote_service`` The name of the remote service that the data will - be provided to. The `provide_data()` method will be called once - for each connected service (not unit). This allows the method to - tailor its data to the given service. - * ``service_ready`` Whether or not the service definition had all of - its requirements met, and thus the ``data_ready`` callbacks run. - - Note that the ``provided_data`` methods are now called **after** the - ``data_ready`` callbacks are run. This gives the ``data_ready`` callbacks - a chance to generate any data necessary for the providing to the remote - services. - """ - for service_name, service in self.services.items(): - service_ready = self.is_ready(service_name) - for provider in service.get('provided_data', []): - for relid in hookenv.relation_ids(provider.name): - units = hookenv.related_units(relid) - if not units: - continue - remote_service = units[0].split('/')[0] - argspec = getargspec(provider.provide_data) - if len(argspec.args) > 1: - data = provider.provide_data(remote_service, service_ready) - else: - data = provider.provide_data() - if data: - hookenv.relation_set(relid, data) - - def reconfigure_services(self, *service_names): - """ - Update all files for one or more registered services, and, - if ready, optionally restart them. - - If no service names are given, reconfigures all registered services. - """ - for service_name in service_names or self.services.keys(): - if self.is_ready(service_name): - self.fire_event('data_ready', service_name) - self.fire_event('start', service_name, default=[ - service_restart, - manage_ports]) - self.save_ready(service_name) - else: - if self.was_ready(service_name): - self.fire_event('data_lost', service_name) - self.fire_event('stop', service_name, default=[ - manage_ports, - service_stop]) - self.save_lost(service_name) - - def stop_services(self, *service_names): - """ - Stop one or more registered services, by name. - - If no service names are given, stops all registered services. - """ - for service_name in service_names or self.services.keys(): - self.fire_event('stop', service_name, default=[ - manage_ports, - service_stop]) - - def get_service(self, service_name): - """ - Given the name of a registered service, return its service definition. - """ - service = self.services.get(service_name) - if not service: - raise KeyError('Service not registered: %s' % service_name) - return service - - def fire_event(self, event_name, service_name, default=None): - """ - Fire a data_ready, data_lost, start, or stop event on a given service. - """ - service = self.get_service(service_name) - callbacks = service.get(event_name, default) - if not callbacks: - return - if not isinstance(callbacks, Iterable): - callbacks = [callbacks] - for callback in callbacks: - if isinstance(callback, ManagerCallback): - callback(self, service_name, event_name) - else: - callback(service_name) - - def is_ready(self, service_name): - """ - Determine if a registered service is ready, by checking its 'required_data'. - - A 'required_data' item can be any mapping type, and is considered ready - if `bool(item)` evaluates as True. - """ - service = self.get_service(service_name) - reqs = service.get('required_data', []) - return all(bool(req) for req in reqs) - - def _load_ready_file(self): - if self._ready is not None: - return - if os.path.exists(self._ready_file): - with open(self._ready_file) as fp: - self._ready = set(json.load(fp)) - else: - self._ready = set() - - def _save_ready_file(self): - if self._ready is None: - return - with open(self._ready_file, 'w') as fp: - json.dump(list(self._ready), fp) - - def save_ready(self, service_name): - """ - Save an indicator that the given service is now data_ready. - """ - self._load_ready_file() - self._ready.add(service_name) - self._save_ready_file() - - def save_lost(self, service_name): - """ - Save an indicator that the given service is no longer data_ready. - """ - self._load_ready_file() - self._ready.discard(service_name) - self._save_ready_file() - - def was_ready(self, service_name): - """ - Determine if the given service was previously data_ready. - """ - self._load_ready_file() - return service_name in self._ready - - -class ManagerCallback(object): - """ - Special case of a callback that takes the `ServiceManager` instance - in addition to the service name. - - Subclasses should implement `__call__` which should accept three parameters: - - * `manager` The `ServiceManager` instance - * `service_name` The name of the service it's being triggered for - * `event_name` The name of the event that this callback is handling - """ - def __call__(self, manager, service_name, event_name): - raise NotImplementedError() - - -class PortManagerCallback(ManagerCallback): - """ - Callback class that will open or close ports, for use as either - a start or stop action. - """ - def __call__(self, manager, service_name, event_name): - service = manager.get_service(service_name) - new_ports = service.get('ports', []) - port_file = os.path.join(hookenv.charm_dir(), '.{}.ports'.format(service_name)) - if os.path.exists(port_file): - with open(port_file) as fp: - old_ports = fp.read().split(',') - for old_port in old_ports: - if bool(old_port): - old_port = int(old_port) - if old_port not in new_ports: - hookenv.close_port(old_port) - with open(port_file, 'w') as fp: - fp.write(','.join(str(port) for port in new_ports)) - for port in new_ports: - if event_name == 'start': - hookenv.open_port(port) - elif event_name == 'stop': - hookenv.close_port(port) - - -def service_stop(service_name): - """ - Wrapper around host.service_stop to prevent spurious "unknown service" - messages in the logs. - """ - if host.service_running(service_name): - host.service_stop(service_name) - - -def service_restart(service_name): - """ - Wrapper around host.service_restart to prevent spurious "unknown service" - messages in the logs. - """ - if host.service_available(service_name): - if host.service_running(service_name): - host.service_restart(service_name) - else: - host.service_start(service_name) - - -# Convenience aliases -open_ports = close_ports = manage_ports = PortManagerCallback() diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/helpers.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/helpers.py deleted file mode 100644 index 3f67783..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/helpers.py +++ /dev/null @@ -1,283 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import os -import yaml - -from charmhelpers.core import hookenv -from charmhelpers.core import host -from charmhelpers.core import templating - -from charmhelpers.core.services.base import ManagerCallback - - -__all__ = ['RelationContext', 'TemplateCallback', - 'render_template', 'template'] - - -class RelationContext(dict): - """ - Base class for a context generator that gets relation data from juju. - - Subclasses must provide the attributes `name`, which is the name of the - interface of interest, `interface`, which is the type of the interface of - interest, and `required_keys`, which is the set of keys required for the - relation to be considered complete. The data for all interfaces matching - the `name` attribute that are complete will used to populate the dictionary - values (see `get_data`, below). - - The generated context will be namespaced under the relation :attr:`name`, - to prevent potential naming conflicts. - - :param str name: Override the relation :attr:`name`, since it can vary from charm to charm - :param list additional_required_keys: Extend the list of :attr:`required_keys` - """ - name = None - interface = None - - def __init__(self, name=None, additional_required_keys=None): - if not hasattr(self, 'required_keys'): - self.required_keys = [] - - if name is not None: - self.name = name - if additional_required_keys: - self.required_keys.extend(additional_required_keys) - self.get_data() - - def __bool__(self): - """ - Returns True if all of the required_keys are available. - """ - return self.is_ready() - - __nonzero__ = __bool__ - - def __repr__(self): - return super(RelationContext, self).__repr__() - - def is_ready(self): - """ - Returns True if all of the `required_keys` are available from any units. - """ - ready = len(self.get(self.name, [])) > 0 - if not ready: - hookenv.log('Incomplete relation: {}'.format(self.__class__.__name__), hookenv.DEBUG) - return ready - - def _is_ready(self, unit_data): - """ - Helper method that tests a set of relation data and returns True if - all of the `required_keys` are present. - """ - return set(unit_data.keys()).issuperset(set(self.required_keys)) - - def get_data(self): - """ - Retrieve the relation data for each unit involved in a relation and, - if complete, store it in a list under `self[self.name]`. This - is automatically called when the RelationContext is instantiated. - - The units are sorted lexographically first by the service ID, then by - the unit ID. Thus, if an interface has two other services, 'db:1' - and 'db:2', with 'db:1' having two units, 'wordpress/0' and 'wordpress/1', - and 'db:2' having one unit, 'mediawiki/0', all of which have a complete - set of data, the relation data for the units will be stored in the - order: 'wordpress/0', 'wordpress/1', 'mediawiki/0'. - - If you only care about a single unit on the relation, you can just - access it as `{{ interface[0]['key'] }}`. However, if you can at all - support multiple units on a relation, you should iterate over the list, - like:: - - {% for unit in interface -%} - {{ unit['key'] }}{% if not loop.last %},{% endif %} - {%- endfor %} - - Note that since all sets of relation data from all related services and - units are in a single list, if you need to know which service or unit a - set of data came from, you'll need to extend this class to preserve - that information. - """ - if not hookenv.relation_ids(self.name): - return - - ns = self.setdefault(self.name, []) - for rid in sorted(hookenv.relation_ids(self.name)): - for unit in sorted(hookenv.related_units(rid)): - reldata = hookenv.relation_get(rid=rid, unit=unit) - if self._is_ready(reldata): - ns.append(reldata) - - def provide_data(self): - """ - Return data to be relation_set for this interface. - """ - return {} - - -class MysqlRelation(RelationContext): - """ - Relation context for the `mysql` interface. - - :param str name: Override the relation :attr:`name`, since it can vary from charm to charm - :param list additional_required_keys: Extend the list of :attr:`required_keys` - """ - name = 'db' - interface = 'mysql' - - def __init__(self, *args, **kwargs): - self.required_keys = ['host', 'user', 'password', 'database'] - RelationContext.__init__(self, *args, **kwargs) - - -class HttpRelation(RelationContext): - """ - Relation context for the `http` interface. - - :param str name: Override the relation :attr:`name`, since it can vary from charm to charm - :param list additional_required_keys: Extend the list of :attr:`required_keys` - """ - name = 'website' - interface = 'http' - - def __init__(self, *args, **kwargs): - self.required_keys = ['host', 'port'] - RelationContext.__init__(self, *args, **kwargs) - - def provide_data(self): - return { - 'host': hookenv.unit_get('private-address'), - 'port': 80, - } - - -class RequiredConfig(dict): - """ - Data context that loads config options with one or more mandatory options. - - Once the required options have been changed from their default values, all - config options will be available, namespaced under `config` to prevent - potential naming conflicts (for example, between a config option and a - relation property). - - :param list *args: List of options that must be changed from their default values. - """ - - def __init__(self, *args): - self.required_options = args - self['config'] = hookenv.config() - with open(os.path.join(hookenv.charm_dir(), 'config.yaml')) as fp: - self.config = yaml.load(fp).get('options', {}) - - def __bool__(self): - for option in self.required_options: - if option not in self['config']: - return False - current_value = self['config'][option] - default_value = self.config[option].get('default') - if current_value == default_value: - return False - if current_value in (None, '') and default_value in (None, ''): - return False - return True - - def __nonzero__(self): - return self.__bool__() - - -class StoredContext(dict): - """ - A data context that always returns the data that it was first created with. - - This is useful to do a one-time generation of things like passwords, that - will thereafter use the same value that was originally generated, instead - of generating a new value each time it is run. - """ - def __init__(self, file_name, config_data): - """ - If the file exists, populate `self` with the data from the file. - Otherwise, populate with the given data and persist it to the file. - """ - if os.path.exists(file_name): - self.update(self.read_context(file_name)) - else: - self.store_context(file_name, config_data) - self.update(config_data) - - def store_context(self, file_name, config_data): - if not os.path.isabs(file_name): - file_name = os.path.join(hookenv.charm_dir(), file_name) - with open(file_name, 'w') as file_stream: - os.fchmod(file_stream.fileno(), 0o600) - yaml.dump(config_data, file_stream) - - def read_context(self, file_name): - if not os.path.isabs(file_name): - file_name = os.path.join(hookenv.charm_dir(), file_name) - with open(file_name, 'r') as file_stream: - data = yaml.load(file_stream) - if not data: - raise OSError("%s is empty" % file_name) - return data - - -class TemplateCallback(ManagerCallback): - """ - Callback class that will render a Jinja2 template, for use as a ready - action. - - :param str source: The template source file, relative to - `$CHARM_DIR/templates` - - :param str target: The target to write the rendered template to - :param str owner: The owner of the rendered file - :param str group: The group of the rendered file - :param int perms: The permissions of the rendered file - :param partial on_change_action: functools partial to be executed when - rendered file changes - """ - def __init__(self, source, target, - owner='root', group='root', perms=0o444, - on_change_action=None): - self.source = source - self.target = target - self.owner = owner - self.group = group - self.perms = perms - self.on_change_action = on_change_action - - def __call__(self, manager, service_name, event_name): - pre_checksum = '' - if self.on_change_action and os.path.isfile(self.target): - pre_checksum = host.file_hash(self.target) - service = manager.get_service(service_name) - context = {} - for ctx in service.get('required_data', []): - context.update(ctx) - templating.render(self.source, self.target, context, - self.owner, self.group, self.perms) - if self.on_change_action: - if pre_checksum == host.file_hash(self.target): - hookenv.log( - 'No change detected: {}'.format(self.target), - hookenv.DEBUG) - else: - self.on_change_action() - - -# Convenience aliases for templates -render_template = template = TemplateCallback diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/strutils.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/strutils.py deleted file mode 100644 index 7e3f969..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/strutils.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import six -import re - - -def bool_from_string(value): - """Interpret string value as boolean. - - Returns True if value translates to True otherwise False. - """ - if isinstance(value, six.string_types): - value = six.text_type(value) - else: - msg = "Unable to interpret non-string value '%s' as boolean" % (value) - raise ValueError(msg) - - value = value.strip().lower() - - if value in ['y', 'yes', 'true', 't', 'on']: - return True - elif value in ['n', 'no', 'false', 'f', 'off']: - return False - - msg = "Unable to interpret string value '%s' as boolean" % (value) - raise ValueError(msg) - - -def bytes_from_string(value): - """Interpret human readable string value as bytes. - - Returns int - """ - BYTE_POWER = { - 'K': 1, - 'KB': 1, - 'M': 2, - 'MB': 2, - 'G': 3, - 'GB': 3, - 'T': 4, - 'TB': 4, - 'P': 5, - 'PB': 5, - } - if isinstance(value, six.string_types): - value = six.text_type(value) - else: - msg = "Unable to interpret non-string value '%s' as boolean" % (value) - raise ValueError(msg) - matches = re.match("([0-9]+)([a-zA-Z]+)", value) - if not matches: - msg = "Unable to interpret string value '%s' as bytes" % (value) - raise ValueError(msg) - return int(matches.group(1)) * (1024 ** BYTE_POWER[matches.group(2)]) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/sysctl.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/sysctl.py deleted file mode 100644 index 21cc8ab..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/sysctl.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import yaml - -from subprocess import check_call - -from charmhelpers.core.hookenv import ( - log, - DEBUG, - ERROR, -) - -__author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>' - - -def create(sysctl_dict, sysctl_file): - """Creates a sysctl.conf file from a YAML associative array - - :param sysctl_dict: a YAML-formatted string of sysctl options eg "{ 'kernel.max_pid': 1337 }" - :type sysctl_dict: str - :param sysctl_file: path to the sysctl file to be saved - :type sysctl_file: str or unicode - :returns: None - """ - try: - sysctl_dict_parsed = yaml.safe_load(sysctl_dict) - except yaml.YAMLError: - log("Error parsing YAML sysctl_dict: {}".format(sysctl_dict), - level=ERROR) - return - - with open(sysctl_file, "w") as fd: - for key, value in sysctl_dict_parsed.items(): - fd.write("{}={}\n".format(key, value)) - - log("Updating sysctl_file: %s values: %s" % (sysctl_file, sysctl_dict_parsed), - level=DEBUG) - - check_call(["sysctl", "-p", sysctl_file]) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/templating.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/templating.py deleted file mode 100644 index 4531999..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/templating.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import os - -from charmhelpers.core import host -from charmhelpers.core import hookenv - - -def render(source, target, context, owner='root', group='root', - perms=0o444, templates_dir=None, encoding='UTF-8'): - """ - Render a template. - - The `source` path, if not absolute, is relative to the `templates_dir`. - - The `target` path should be absolute. - - The context should be a dict containing the values to be replaced in the - template. - - The `owner`, `group`, and `perms` options will be passed to `write_file`. - - If omitted, `templates_dir` defaults to the `templates` folder in the charm. - - Note: Using this requires python-jinja2; if it is not installed, calling - this will attempt to use charmhelpers.fetch.apt_install to install it. - """ - try: - from jinja2 import FileSystemLoader, Environment, exceptions - except ImportError: - try: - from charmhelpers.fetch import apt_install - except ImportError: - hookenv.log('Could not import jinja2, and could not import ' - 'charmhelpers.fetch to install it', - level=hookenv.ERROR) - raise - apt_install('python-jinja2', fatal=True) - from jinja2 import FileSystemLoader, Environment, exceptions - - if templates_dir is None: - templates_dir = os.path.join(hookenv.charm_dir(), 'templates') - loader = Environment(loader=FileSystemLoader(templates_dir)) - try: - source = source - template = loader.get_template(source) - except exceptions.TemplateNotFound as e: - hookenv.log('Could not load template %s from %s.' % - (source, templates_dir), - level=hookenv.ERROR) - raise e - content = template.render(context) - host.mkdir(os.path.dirname(target), owner, group, perms=0o755) - host.write_file(target, content.encode(encoding), owner, group, perms) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/unitdata.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/core/unitdata.py deleted file mode 100644 index 338104e..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/core/unitdata.py +++ /dev/null @@ -1,521 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. -# -# -# Authors: -# Kapil Thangavelu <kapil.foss@gmail.com> -# -""" -Intro ------ - -A simple way to store state in units. This provides a key value -storage with support for versioned, transactional operation, -and can calculate deltas from previous values to simplify unit logic -when processing changes. - - -Hook Integration ----------------- - -There are several extant frameworks for hook execution, including - - - charmhelpers.core.hookenv.Hooks - - charmhelpers.core.services.ServiceManager - -The storage classes are framework agnostic, one simple integration is -via the HookData contextmanager. It will record the current hook -execution environment (including relation data, config data, etc.), -setup a transaction and allow easy access to the changes from -previously seen values. One consequence of the integration is the -reservation of particular keys ('rels', 'unit', 'env', 'config', -'charm_revisions') for their respective values. - -Here's a fully worked integration example using hookenv.Hooks:: - - from charmhelper.core import hookenv, unitdata - - hook_data = unitdata.HookData() - db = unitdata.kv() - hooks = hookenv.Hooks() - - @hooks.hook - def config_changed(): - # Print all changes to configuration from previously seen - # values. - for changed, (prev, cur) in hook_data.conf.items(): - print('config changed', changed, - 'previous value', prev, - 'current value', cur) - - # Get some unit specific bookeeping - if not db.get('pkg_key'): - key = urllib.urlopen('https://example.com/pkg_key').read() - db.set('pkg_key', key) - - # Directly access all charm config as a mapping. - conf = db.getrange('config', True) - - # Directly access all relation data as a mapping - rels = db.getrange('rels', True) - - if __name__ == '__main__': - with hook_data(): - hook.execute() - - -A more basic integration is via the hook_scope context manager which simply -manages transaction scope (and records hook name, and timestamp):: - - >>> from unitdata import kv - >>> db = kv() - >>> with db.hook_scope('install'): - ... # do work, in transactional scope. - ... db.set('x', 1) - >>> db.get('x') - 1 - - -Usage ------ - -Values are automatically json de/serialized to preserve basic typing -and complex data struct capabilities (dicts, lists, ints, booleans, etc). - -Individual values can be manipulated via get/set:: - - >>> kv.set('y', True) - >>> kv.get('y') - True - - # We can set complex values (dicts, lists) as a single key. - >>> kv.set('config', {'a': 1, 'b': True'}) - - # Also supports returning dictionaries as a record which - # provides attribute access. - >>> config = kv.get('config', record=True) - >>> config.b - True - - -Groups of keys can be manipulated with update/getrange:: - - >>> kv.update({'z': 1, 'y': 2}, prefix="gui.") - >>> kv.getrange('gui.', strip=True) - {'z': 1, 'y': 2} - -When updating values, its very helpful to understand which values -have actually changed and how have they changed. The storage -provides a delta method to provide for this:: - - >>> data = {'debug': True, 'option': 2} - >>> delta = kv.delta(data, 'config.') - >>> delta.debug.previous - None - >>> delta.debug.current - True - >>> delta - {'debug': (None, True), 'option': (None, 2)} - -Note the delta method does not persist the actual change, it needs to -be explicitly saved via 'update' method:: - - >>> kv.update(data, 'config.') - -Values modified in the context of a hook scope retain historical values -associated to the hookname. - - >>> with db.hook_scope('config-changed'): - ... db.set('x', 42) - >>> db.gethistory('x') - [(1, u'x', 1, u'install', u'2015-01-21T16:49:30.038372'), - (2, u'x', 42, u'config-changed', u'2015-01-21T16:49:30.038786')] - -""" - -import collections -import contextlib -import datetime -import itertools -import json -import os -import pprint -import sqlite3 -import sys - -__author__ = 'Kapil Thangavelu <kapil.foss@gmail.com>' - - -class Storage(object): - """Simple key value database for local unit state within charms. - - Modifications are not persisted unless :meth:`flush` is called. - - To support dicts, lists, integer, floats, and booleans values - are automatically json encoded/decoded. - """ - def __init__(self, path=None): - self.db_path = path - if path is None: - if 'UNIT_STATE_DB' in os.environ: - self.db_path = os.environ['UNIT_STATE_DB'] - else: - self.db_path = os.path.join( - os.environ.get('CHARM_DIR', ''), '.unit-state.db') - self.conn = sqlite3.connect('%s' % self.db_path) - self.cursor = self.conn.cursor() - self.revision = None - self._closed = False - self._init() - - def close(self): - if self._closed: - return - self.flush(False) - self.cursor.close() - self.conn.close() - self._closed = True - - def get(self, key, default=None, record=False): - self.cursor.execute('select data from kv where key=?', [key]) - result = self.cursor.fetchone() - if not result: - return default - if record: - return Record(json.loads(result[0])) - return json.loads(result[0]) - - def getrange(self, key_prefix, strip=False): - """ - Get a range of keys starting with a common prefix as a mapping of - keys to values. - - :param str key_prefix: Common prefix among all keys - :param bool strip: Optionally strip the common prefix from the key - names in the returned dict - :return dict: A (possibly empty) dict of key-value mappings - """ - self.cursor.execute("select key, data from kv where key like ?", - ['%s%%' % key_prefix]) - result = self.cursor.fetchall() - - if not result: - return {} - if not strip: - key_prefix = '' - return dict([ - (k[len(key_prefix):], json.loads(v)) for k, v in result]) - - def update(self, mapping, prefix=""): - """ - Set the values of multiple keys at once. - - :param dict mapping: Mapping of keys to values - :param str prefix: Optional prefix to apply to all keys in `mapping` - before setting - """ - for k, v in mapping.items(): - self.set("%s%s" % (prefix, k), v) - - def unset(self, key): - """ - Remove a key from the database entirely. - """ - self.cursor.execute('delete from kv where key=?', [key]) - if self.revision and self.cursor.rowcount: - self.cursor.execute( - 'insert into kv_revisions values (?, ?, ?)', - [key, self.revision, json.dumps('DELETED')]) - - def unsetrange(self, keys=None, prefix=""): - """ - Remove a range of keys starting with a common prefix, from the database - entirely. - - :param list keys: List of keys to remove. - :param str prefix: Optional prefix to apply to all keys in ``keys`` - before removing. - """ - if keys is not None: - keys = ['%s%s' % (prefix, key) for key in keys] - self.cursor.execute('delete from kv where key in (%s)' % ','.join(['?'] * len(keys)), keys) - if self.revision and self.cursor.rowcount: - self.cursor.execute( - 'insert into kv_revisions values %s' % ','.join(['(?, ?, ?)'] * len(keys)), - list(itertools.chain.from_iterable((key, self.revision, json.dumps('DELETED')) for key in keys))) - else: - self.cursor.execute('delete from kv where key like ?', - ['%s%%' % prefix]) - if self.revision and self.cursor.rowcount: - self.cursor.execute( - 'insert into kv_revisions values (?, ?, ?)', - ['%s%%' % prefix, self.revision, json.dumps('DELETED')]) - - def set(self, key, value): - """ - Set a value in the database. - - :param str key: Key to set the value for - :param value: Any JSON-serializable value to be set - """ - serialized = json.dumps(value) - - self.cursor.execute('select data from kv where key=?', [key]) - exists = self.cursor.fetchone() - - # Skip mutations to the same value - if exists: - if exists[0] == serialized: - return value - - if not exists: - self.cursor.execute( - 'insert into kv (key, data) values (?, ?)', - (key, serialized)) - else: - self.cursor.execute(''' - update kv - set data = ? - where key = ?''', [serialized, key]) - - # Save - if not self.revision: - return value - - self.cursor.execute( - 'select 1 from kv_revisions where key=? and revision=?', - [key, self.revision]) - exists = self.cursor.fetchone() - - if not exists: - self.cursor.execute( - '''insert into kv_revisions ( - revision, key, data) values (?, ?, ?)''', - (self.revision, key, serialized)) - else: - self.cursor.execute( - ''' - update kv_revisions - set data = ? - where key = ? - and revision = ?''', - [serialized, key, self.revision]) - - return value - - def delta(self, mapping, prefix): - """ - return a delta containing values that have changed. - """ - previous = self.getrange(prefix, strip=True) - if not previous: - pk = set() - else: - pk = set(previous.keys()) - ck = set(mapping.keys()) - delta = DeltaSet() - - # added - for k in ck.difference(pk): - delta[k] = Delta(None, mapping[k]) - - # removed - for k in pk.difference(ck): - delta[k] = Delta(previous[k], None) - - # changed - for k in pk.intersection(ck): - c = mapping[k] - p = previous[k] - if c != p: - delta[k] = Delta(p, c) - - return delta - - @contextlib.contextmanager - def hook_scope(self, name=""): - """Scope all future interactions to the current hook execution - revision.""" - assert not self.revision - self.cursor.execute( - 'insert into hooks (hook, date) values (?, ?)', - (name or sys.argv[0], - datetime.datetime.utcnow().isoformat())) - self.revision = self.cursor.lastrowid - try: - yield self.revision - self.revision = None - except: - self.flush(False) - self.revision = None - raise - else: - self.flush() - - def flush(self, save=True): - if save: - self.conn.commit() - elif self._closed: - return - else: - self.conn.rollback() - - def _init(self): - self.cursor.execute(''' - create table if not exists kv ( - key text, - data text, - primary key (key) - )''') - self.cursor.execute(''' - create table if not exists kv_revisions ( - key text, - revision integer, - data text, - primary key (key, revision) - )''') - self.cursor.execute(''' - create table if not exists hooks ( - version integer primary key autoincrement, - hook text, - date text - )''') - self.conn.commit() - - def gethistory(self, key, deserialize=False): - self.cursor.execute( - ''' - select kv.revision, kv.key, kv.data, h.hook, h.date - from kv_revisions kv, - hooks h - where kv.key=? - and kv.revision = h.version - ''', [key]) - if deserialize is False: - return self.cursor.fetchall() - return map(_parse_history, self.cursor.fetchall()) - - def debug(self, fh=sys.stderr): - self.cursor.execute('select * from kv') - pprint.pprint(self.cursor.fetchall(), stream=fh) - self.cursor.execute('select * from kv_revisions') - pprint.pprint(self.cursor.fetchall(), stream=fh) - - -def _parse_history(d): - return (d[0], d[1], json.loads(d[2]), d[3], - datetime.datetime.strptime(d[-1], "%Y-%m-%dT%H:%M:%S.%f")) - - -class HookData(object): - """Simple integration for existing hook exec frameworks. - - Records all unit information, and stores deltas for processing - by the hook. - - Sample:: - - from charmhelper.core import hookenv, unitdata - - changes = unitdata.HookData() - db = unitdata.kv() - hooks = hookenv.Hooks() - - @hooks.hook - def config_changed(): - # View all changes to configuration - for changed, (prev, cur) in changes.conf.items(): - print('config changed', changed, - 'previous value', prev, - 'current value', cur) - - # Get some unit specific bookeeping - if not db.get('pkg_key'): - key = urllib.urlopen('https://example.com/pkg_key').read() - db.set('pkg_key', key) - - if __name__ == '__main__': - with changes(): - hook.execute() - - """ - def __init__(self): - self.kv = kv() - self.conf = None - self.rels = None - - @contextlib.contextmanager - def __call__(self): - from charmhelpers.core import hookenv - hook_name = hookenv.hook_name() - - with self.kv.hook_scope(hook_name): - self._record_charm_version(hookenv.charm_dir()) - delta_config, delta_relation = self._record_hook(hookenv) - yield self.kv, delta_config, delta_relation - - def _record_charm_version(self, charm_dir): - # Record revisions.. charm revisions are meaningless - # to charm authors as they don't control the revision. - # so logic dependnent on revision is not particularly - # useful, however it is useful for debugging analysis. - charm_rev = open( - os.path.join(charm_dir, 'revision')).read().strip() - charm_rev = charm_rev or '0' - revs = self.kv.get('charm_revisions', []) - if charm_rev not in revs: - revs.append(charm_rev.strip() or '0') - self.kv.set('charm_revisions', revs) - - def _record_hook(self, hookenv): - data = hookenv.execution_environment() - self.conf = conf_delta = self.kv.delta(data['conf'], 'config') - self.rels = rels_delta = self.kv.delta(data['rels'], 'rels') - self.kv.set('env', dict(data['env'])) - self.kv.set('unit', data['unit']) - self.kv.set('relid', data.get('relid')) - return conf_delta, rels_delta - - -class Record(dict): - - __slots__ = () - - def __getattr__(self, k): - if k in self: - return self[k] - raise AttributeError(k) - - -class DeltaSet(Record): - - __slots__ = () - - -Delta = collections.namedtuple('Delta', ['previous', 'current']) - - -_KV = None - - -def kv(): - global _KV - if _KV is None: - _KV = Storage() - return _KV diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/__init__.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/__init__.py deleted file mode 100644 index 1cfb99f..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/__init__.py +++ /dev/null @@ -1,468 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import importlib -from tempfile import NamedTemporaryFile -import time -from yaml import safe_load -from charmhelpers.core.host import ( - lsb_release -) -import subprocess -from charmhelpers.core.hookenv import ( - config, - log, -) -import os - -import six -if six.PY3: - from urllib.parse import urlparse, urlunparse -else: - from urlparse import urlparse, urlunparse - - -CLOUD_ARCHIVE = """# Ubuntu Cloud Archive -deb http://ubuntu-cloud.archive.canonical.com/ubuntu {} main -""" -PROPOSED_POCKET = """# Proposed -deb http://archive.ubuntu.com/ubuntu {}-proposed main universe multiverse restricted -""" -CLOUD_ARCHIVE_POCKETS = { - # Folsom - 'folsom': 'precise-updates/folsom', - 'precise-folsom': 'precise-updates/folsom', - 'precise-folsom/updates': 'precise-updates/folsom', - 'precise-updates/folsom': 'precise-updates/folsom', - 'folsom/proposed': 'precise-proposed/folsom', - 'precise-folsom/proposed': 'precise-proposed/folsom', - 'precise-proposed/folsom': 'precise-proposed/folsom', - # Grizzly - 'grizzly': 'precise-updates/grizzly', - 'precise-grizzly': 'precise-updates/grizzly', - 'precise-grizzly/updates': 'precise-updates/grizzly', - 'precise-updates/grizzly': 'precise-updates/grizzly', - 'grizzly/proposed': 'precise-proposed/grizzly', - 'precise-grizzly/proposed': 'precise-proposed/grizzly', - 'precise-proposed/grizzly': 'precise-proposed/grizzly', - # Havana - 'havana': 'precise-updates/havana', - 'precise-havana': 'precise-updates/havana', - 'precise-havana/updates': 'precise-updates/havana', - 'precise-updates/havana': 'precise-updates/havana', - 'havana/proposed': 'precise-proposed/havana', - 'precise-havana/proposed': 'precise-proposed/havana', - 'precise-proposed/havana': 'precise-proposed/havana', - # Icehouse - 'icehouse': 'precise-updates/icehouse', - 'precise-icehouse': 'precise-updates/icehouse', - 'precise-icehouse/updates': 'precise-updates/icehouse', - 'precise-updates/icehouse': 'precise-updates/icehouse', - 'icehouse/proposed': 'precise-proposed/icehouse', - 'precise-icehouse/proposed': 'precise-proposed/icehouse', - 'precise-proposed/icehouse': 'precise-proposed/icehouse', - # Juno - 'juno': 'trusty-updates/juno', - 'trusty-juno': 'trusty-updates/juno', - 'trusty-juno/updates': 'trusty-updates/juno', - 'trusty-updates/juno': 'trusty-updates/juno', - 'juno/proposed': 'trusty-proposed/juno', - 'trusty-juno/proposed': 'trusty-proposed/juno', - 'trusty-proposed/juno': 'trusty-proposed/juno', - # Kilo - 'kilo': 'trusty-updates/kilo', - 'trusty-kilo': 'trusty-updates/kilo', - 'trusty-kilo/updates': 'trusty-updates/kilo', - 'trusty-updates/kilo': 'trusty-updates/kilo', - 'kilo/proposed': 'trusty-proposed/kilo', - 'trusty-kilo/proposed': 'trusty-proposed/kilo', - 'trusty-proposed/kilo': 'trusty-proposed/kilo', - # Liberty - 'liberty': 'trusty-updates/liberty', - 'trusty-liberty': 'trusty-updates/liberty', - 'trusty-liberty/updates': 'trusty-updates/liberty', - 'trusty-updates/liberty': 'trusty-updates/liberty', - 'liberty/proposed': 'trusty-proposed/liberty', - 'trusty-liberty/proposed': 'trusty-proposed/liberty', - 'trusty-proposed/liberty': 'trusty-proposed/liberty', - # Mitaka - 'mitaka': 'trusty-updates/mitaka', - 'trusty-mitaka': 'trusty-updates/mitaka', - 'trusty-mitaka/updates': 'trusty-updates/mitaka', - 'trusty-updates/mitaka': 'trusty-updates/mitaka', - 'mitaka/proposed': 'trusty-proposed/mitaka', - 'trusty-mitaka/proposed': 'trusty-proposed/mitaka', - 'trusty-proposed/mitaka': 'trusty-proposed/mitaka', -} - -# The order of this list is very important. Handlers should be listed in from -# least- to most-specific URL matching. -FETCH_HANDLERS = ( - 'charmhelpers.fetch.archiveurl.ArchiveUrlFetchHandler', - 'charmhelpers.fetch.bzrurl.BzrUrlFetchHandler', - 'charmhelpers.fetch.giturl.GitUrlFetchHandler', -) - -APT_NO_LOCK = 100 # The return code for "couldn't acquire lock" in APT. -APT_NO_LOCK_RETRY_DELAY = 10 # Wait 10 seconds between apt lock checks. -APT_NO_LOCK_RETRY_COUNT = 30 # Retry to acquire the lock X times. - - -class SourceConfigError(Exception): - pass - - -class UnhandledSource(Exception): - pass - - -class AptLockError(Exception): - pass - - -class BaseFetchHandler(object): - - """Base class for FetchHandler implementations in fetch plugins""" - - def can_handle(self, source): - """Returns True if the source can be handled. Otherwise returns - a string explaining why it cannot""" - return "Wrong source type" - - def install(self, source): - """Try to download and unpack the source. Return the path to the - unpacked files or raise UnhandledSource.""" - raise UnhandledSource("Wrong source type {}".format(source)) - - def parse_url(self, url): - return urlparse(url) - - def base_url(self, url): - """Return url without querystring or fragment""" - parts = list(self.parse_url(url)) - parts[4:] = ['' for i in parts[4:]] - return urlunparse(parts) - - -def filter_installed_packages(packages): - """Returns a list of packages that require installation""" - cache = apt_cache() - _pkgs = [] - for package in packages: - try: - p = cache[package] - p.current_ver or _pkgs.append(package) - except KeyError: - log('Package {} has no installation candidate.'.format(package), - level='WARNING') - _pkgs.append(package) - return _pkgs - - -def apt_cache(in_memory=True): - """Build and return an apt cache""" - from apt import apt_pkg - apt_pkg.init() - if in_memory: - apt_pkg.config.set("Dir::Cache::pkgcache", "") - apt_pkg.config.set("Dir::Cache::srcpkgcache", "") - return apt_pkg.Cache() - - -def apt_install(packages, options=None, fatal=False): - """Install one or more packages""" - if options is None: - options = ['--option=Dpkg::Options::=--force-confold'] - - cmd = ['apt-get', '--assume-yes'] - cmd.extend(options) - cmd.append('install') - if isinstance(packages, six.string_types): - cmd.append(packages) - else: - cmd.extend(packages) - log("Installing {} with options: {}".format(packages, - options)) - _run_apt_command(cmd, fatal) - - -def apt_upgrade(options=None, fatal=False, dist=False): - """Upgrade all packages""" - if options is None: - options = ['--option=Dpkg::Options::=--force-confold'] - - cmd = ['apt-get', '--assume-yes'] - cmd.extend(options) - if dist: - cmd.append('dist-upgrade') - else: - cmd.append('upgrade') - log("Upgrading with options: {}".format(options)) - _run_apt_command(cmd, fatal) - - -def apt_update(fatal=False): - """Update local apt cache""" - cmd = ['apt-get', 'update'] - _run_apt_command(cmd, fatal) - - -def apt_purge(packages, fatal=False): - """Purge one or more packages""" - cmd = ['apt-get', '--assume-yes', 'purge'] - if isinstance(packages, six.string_types): - cmd.append(packages) - else: - cmd.extend(packages) - log("Purging {}".format(packages)) - _run_apt_command(cmd, fatal) - - -def apt_mark(packages, mark, fatal=False): - """Flag one or more packages using apt-mark""" - cmd = ['apt-mark', mark] - if isinstance(packages, six.string_types): - cmd.append(packages) - else: - cmd.extend(packages) - log("Holding {}".format(packages)) - - if fatal: - subprocess.check_call(cmd, universal_newlines=True) - else: - subprocess.call(cmd, universal_newlines=True) - - -def apt_hold(packages, fatal=False): - return apt_mark(packages, 'hold', fatal=fatal) - - -def apt_unhold(packages, fatal=False): - return apt_mark(packages, 'unhold', fatal=fatal) - - -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:: - - ppa:charmers/example - deb https://stub:key@private.example.com/ubuntu trusty main - - In addition: - 'proposed:' may be used to enable the standard 'proposed' - pocket for the release. - 'cloud:' may be used to activate official cloud archive pockets, - such as 'cloud:icehouse' - 'distro' may be used as a noop - - @param key: A key to be added to the system's APT keyring and used - to verify the signatures on packages. Ideally, this should be an - ASCII format GPG public key including the block headers. A GPG key - id may also be used, but be aware that only insecure protocols are - available to retrieve the actual public key from a public keyserver - placing your Juju environment at risk. ppa and cloud archive keys - are securely added automtically, so sould not be provided. - """ - if source is None: - log('Source is not present. Skipping') - return - - if (source.startswith('ppa:') or - source.startswith('http') or - source.startswith('deb ') or - source.startswith('cloud-archive:')): - subprocess.check_call(['add-apt-repository', '--yes', source]) - elif source.startswith('cloud:'): - apt_install(filter_installed_packages(['ubuntu-cloud-keyring']), - fatal=True) - pocket = source.split(':')[-1] - if pocket not in CLOUD_ARCHIVE_POCKETS: - raise SourceConfigError( - 'Unsupported cloud: source option %s' % - pocket) - actual_pocket = CLOUD_ARCHIVE_POCKETS[pocket] - with open('/etc/apt/sources.list.d/cloud-archive.list', 'w') as apt: - apt.write(CLOUD_ARCHIVE.format(actual_pocket)) - elif source == 'proposed': - release = lsb_release()['DISTRIB_CODENAME'] - with open('/etc/apt/sources.list.d/proposed.list', 'w') as apt: - apt.write(PROPOSED_POCKET.format(release)) - elif source == 'distro': - pass - else: - log("Unknown source: {!r}".format(source)) - - if key: - if '-----BEGIN PGP PUBLIC KEY BLOCK-----' in key: - with NamedTemporaryFile('w+') as key_file: - key_file.write(key) - key_file.flush() - key_file.seek(0) - subprocess.check_call(['apt-key', 'add', '-'], stdin=key_file) - elif 'http://' in key: - with NamedTemporaryFile('w+') as key_file: - subprocess.check_call(['wget', key, '-O-'], stdout=key_file) - subprocess.check_call(['apt-key', 'add', key_file.name]) - else: - # Note that hkp: is in no way a secure protocol. Using a - # GPG key id is pointless from a security POV unless you - # absolutely trust your network and DNS. - subprocess.check_call(['apt-key', 'adv', '--keyserver', - 'hkp://keyserver.ubuntu.com:80', '--recv', - key]) - - -def configure_sources(update=False, - sources_var='install_sources', - keys_var='install_keys'): - """ - Configure multiple sources from charm configuration. - - The lists are encoded as yaml fragments in the configuration. - The frament needs to be included as a string. Sources and their - corresponding keys are of the types supported by add_source(). - - Example config: - install_sources: | - - "ppa:foo" - - "http://example.com/repo precise main" - install_keys: | - - null - - "a1b2c3d4" - - Note that 'null' (a.k.a. None) should not be quoted. - """ - sources = safe_load((config(sources_var) or '').strip()) or [] - keys = safe_load((config(keys_var) or '').strip()) or None - - if isinstance(sources, six.string_types): - sources = [sources] - - if keys is None: - for source in sources: - add_source(source, None) - else: - if isinstance(keys, six.string_types): - keys = [keys] - - if len(sources) != len(keys): - raise SourceConfigError( - 'Install sources and keys lists are different lengths') - for source, key in zip(sources, keys): - add_source(source, key) - if update: - apt_update(fatal=True) - - -def install_remote(source, *args, **kwargs): - """ - Install a file tree from a remote source - - The specified source should be a url of the form: - scheme://[host]/path[#[option=value][&...]] - - Schemes supported are based on this modules submodules. - Options supported are submodule-specific. - Additional arguments are passed through to the submodule. - - For example:: - - dest = install_remote('http://example.com/archive.tgz', - checksum='deadbeef', - hash_type='sha1') - - This will download `archive.tgz`, validate it using SHA1 and, if - the file is ok, extract it and return the directory in which it - was extracted. If the checksum fails, it will raise - :class:`charmhelpers.core.host.ChecksumError`. - """ - # We ONLY check for True here because can_handle may return a string - # explaining why it can't handle a given source. - handlers = [h for h in plugins() if h.can_handle(source) is True] - installed_to = None - for handler in handlers: - try: - installed_to = handler.install(source, *args, **kwargs) - except UnhandledSource as e: - log('Install source attempt unsuccessful: {}'.format(e), - level='WARNING') - if not installed_to: - raise UnhandledSource("No handler found for source {}".format(source)) - return installed_to - - -def install_from_config(config_var_name): - charm_config = config() - source = charm_config[config_var_name] - return install_remote(source) - - -def plugins(fetch_handlers=None): - if not fetch_handlers: - fetch_handlers = FETCH_HANDLERS - plugin_list = [] - for handler_name in fetch_handlers: - package, classname = handler_name.rsplit('.', 1) - try: - handler_class = getattr( - importlib.import_module(package), - classname) - plugin_list.append(handler_class()) - except (ImportError, AttributeError): - # Skip missing plugins so that they can be ommitted from - # installation if desired - log("FetchHandler {} not found, skipping plugin".format( - handler_name)) - return plugin_list - - -def _run_apt_command(cmd, fatal=False): - """ - Run an APT command, checking output and retrying if the fatal flag is set - to True. - - :param: cmd: str: The apt command to run. - :param: fatal: bool: Whether the command's output should be checked and - retried. - """ - env = os.environ.copy() - - if 'DEBIAN_FRONTEND' not in env: - env['DEBIAN_FRONTEND'] = 'noninteractive' - - if fatal: - retry_count = 0 - result = None - - # If the command is considered "fatal", we need to retry if the apt - # lock was not acquired. - - while result is None or result == APT_NO_LOCK: - try: - result = subprocess.check_call(cmd, env=env) - except subprocess.CalledProcessError as e: - retry_count = retry_count + 1 - if retry_count > APT_NO_LOCK_RETRY_COUNT: - raise - result = e.returncode - log("Couldn't acquire DPKG lock. Will retry in {} seconds." - "".format(APT_NO_LOCK_RETRY_DELAY)) - time.sleep(APT_NO_LOCK_RETRY_DELAY) - - else: - subprocess.call(cmd, env=env) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/archiveurl.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/archiveurl.py deleted file mode 100644 index efd7f9f..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/archiveurl.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import os -import hashlib -import re - -from charmhelpers.fetch import ( - BaseFetchHandler, - UnhandledSource -) -from charmhelpers.payload.archive import ( - get_archive_handler, - extract, -) -from charmhelpers.core.host import mkdir, check_hash - -import six -if six.PY3: - from urllib.request import ( - build_opener, install_opener, urlopen, urlretrieve, - HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, - ) - from urllib.parse import urlparse, urlunparse, parse_qs - from urllib.error import URLError -else: - from urllib import urlretrieve - from urllib2 import ( - build_opener, install_opener, urlopen, - HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, - URLError - ) - from urlparse import urlparse, urlunparse, parse_qs - - -def splituser(host): - '''urllib.splituser(), but six's support of this seems broken''' - _userprog = re.compile('^(.*)@(.*)$') - match = _userprog.match(host) - if match: - return match.group(1, 2) - return None, host - - -def splitpasswd(user): - '''urllib.splitpasswd(), but six's support of this is missing''' - _passwdprog = re.compile('^([^:]*):(.*)$', re.S) - match = _passwdprog.match(user) - if match: - return match.group(1, 2) - return user, None - - -class ArchiveUrlFetchHandler(BaseFetchHandler): - """ - Handler to download archive files from arbitrary URLs. - - Can fetch from http, https, ftp, and file URLs. - - Can install either tarballs (.tar, .tgz, .tbz2, etc) or zip files. - - Installs the contents of the archive in $CHARM_DIR/fetched/. - """ - def can_handle(self, source): - url_parts = self.parse_url(source) - if url_parts.scheme not in ('http', 'https', 'ftp', 'file'): - # XXX: Why is this returning a boolean and a string? It's - # doomed to fail since "bool(can_handle('foo://'))" will be True. - return "Wrong source type" - if get_archive_handler(self.base_url(source)): - return True - return False - - def download(self, source, dest): - """ - Download an archive file. - - :param str source: URL pointing to an archive file. - :param str dest: Local path location to download archive file to. - """ - # propogate all exceptions - # URLError, OSError, etc - proto, netloc, path, params, query, fragment = urlparse(source) - if proto in ('http', 'https'): - auth, barehost = splituser(netloc) - if auth is not None: - source = urlunparse((proto, barehost, path, params, query, fragment)) - username, password = splitpasswd(auth) - passman = HTTPPasswordMgrWithDefaultRealm() - # Realm is set to None in add_password to force the username and password - # to be used whatever the realm - passman.add_password(None, source, username, password) - authhandler = HTTPBasicAuthHandler(passman) - opener = build_opener(authhandler) - install_opener(opener) - response = urlopen(source) - try: - with open(dest, 'w') as dest_file: - dest_file.write(response.read()) - except Exception as e: - if os.path.isfile(dest): - os.unlink(dest) - raise e - - # Mandatory file validation via Sha1 or MD5 hashing. - def download_and_validate(self, url, hashsum, validate="sha1"): - tempfile, headers = urlretrieve(url) - check_hash(tempfile, hashsum, validate) - return tempfile - - def install(self, source, dest=None, checksum=None, hash_type='sha1'): - """ - Download and install an archive file, with optional checksum validation. - - 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 checksum: If given, validate the archive file after download. - :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') - if not os.path.exists(dest_dir): - mkdir(dest_dir, perms=0o755) - dld_file = os.path.join(dest_dir, os.path.basename(url_parts.path)) - try: - self.download(source, dld_file) - except URLError as e: - raise UnhandledSource(e.reason) - except OSError as e: - raise UnhandledSource(e.strerror) - options = parse_qs(url_parts.fragment) - for key, value in options.items(): - if not six.PY3: - algorithms = hashlib.algorithms - else: - algorithms = hashlib.algorithms_available - if key in algorithms: - if len(value) != 1: - raise TypeError( - "Expected 1 hash value, not %d" % len(value)) - expected = value[0] - check_hash(dld_file, expected, key) - if checksum: - check_hash(dld_file, checksum, hash_type) - return extract(dld_file, dest) diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/bzrurl.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/bzrurl.py deleted file mode 100644 index 3531315..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/bzrurl.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import os -from charmhelpers.fetch import ( - BaseFetchHandler, - UnhandledSource -) -from charmhelpers.core.host import mkdir - -import six -if six.PY3: - raise ImportError('bzrlib does not support Python3') - -try: - from bzrlib.branch import Branch - from bzrlib import bzrdir, workingtree, errors -except ImportError: - from charmhelpers.fetch import apt_install - apt_install("python-bzrlib") - from bzrlib.branch import Branch - from bzrlib import bzrdir, workingtree, errors - - -class BzrUrlFetchHandler(BaseFetchHandler): - """Handler for bazaar branches via generic and lp URLs""" - def can_handle(self, source): - url_parts = self.parse_url(source) - if url_parts.scheme not in ('bzr+ssh', 'lp'): - return False - else: - return True - - def branch(self, source, dest): - url_parts = self.parse_url(source) - # If we use lp:branchname scheme we need to load plugins - if not self.can_handle(source): - raise UnhandledSource("Cannot handle {}".format(source)) - if url_parts.scheme == "lp": - from bzrlib.plugin import load_plugins - load_plugins() - try: - local_branch = bzrdir.BzrDir.create_branch_convenience(dest) - except errors.AlreadyControlDirError: - local_branch = Branch.open(dest) - try: - remote_branch = Branch.open(source) - remote_branch.push(local_branch) - tree = workingtree.WorkingTree.open(dest) - tree.update() - except Exception as e: - raise e - - def install(self, source): - url_parts = self.parse_url(source) - branch_name = url_parts.path.strip("/").split("/")[-1] - dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", - branch_name) - if not os.path.exists(dest_dir): - mkdir(dest_dir, perms=0o755) - try: - self.branch(source, dest_dir) - except OSError as e: - raise UnhandledSource(e.strerror) - return dest_dir diff --git a/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/giturl.py b/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/giturl.py deleted file mode 100644 index f023b26..0000000 --- a/charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/giturl.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2014-2015 Canonical Limited. -# -# This file is part of charm-helpers. -# -# charm-helpers is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 as -# published by the Free Software Foundation. -# -# charm-helpers is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>. - -import os -from charmhelpers.fetch import ( - BaseFetchHandler, - UnhandledSource -) -from charmhelpers.core.host import mkdir - -import six -if six.PY3: - raise ImportError('GitPython does not support Python 3') - -try: - from git import Repo -except ImportError: - from charmhelpers.fetch import apt_install - apt_install("python-git") - from git import Repo - -from git.exc import GitCommandError # noqa E402 - - -class GitUrlFetchHandler(BaseFetchHandler): - """Handler for git branches via generic and github URLs""" - def can_handle(self, source): - url_parts = self.parse_url(source) - # TODO (mattyw) no support for ssh git@ yet - if url_parts.scheme not in ('http', 'https', 'git'): - return False - else: - return True - - def clone(self, source, dest, branch, depth=None): - if not self.can_handle(source): - raise UnhandledSource("Cannot handle {}".format(source)) - - if depth: - Repo.clone_from(source, dest, branch=branch, depth=depth) - else: - Repo.clone_from(source, dest, branch=branch) - - def install(self, source, branch="master", dest=None, depth=None): - url_parts = self.parse_url(source) - branch_name = url_parts.path.strip("/").split("/")[-1] - if dest: - dest_dir = os.path.join(dest, branch_name) - else: - dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", - branch_name) - if not os.path.exists(dest_dir): - mkdir(dest_dir, perms=0o755) - try: - self.clone(source, dest_dir, branch, depth) - except GitCommandError as e: - raise UnhandledSource(e) - except OSError as e: - raise UnhandledSource(e.strerror) - return dest_dir diff --git a/charms/trusty/neutron-contrail/hooks/config-changed b/charms/trusty/neutron-contrail/hooks/config-changed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/config-changed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/contrail-api-relation-broken b/charms/trusty/neutron-contrail/hooks/contrail-api-relation-broken deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/contrail-api-relation-broken +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/contrail-api-relation-changed b/charms/trusty/neutron-contrail/hooks/contrail-api-relation-changed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/contrail-api-relation-changed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/contrail-api-relation-departed b/charms/trusty/neutron-contrail/hooks/contrail-api-relation-departed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/contrail-api-relation-departed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-broken b/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-broken deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-broken +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-changed b/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-changed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-changed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-departed b/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-departed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-departed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/control-node-relation-broken b/charms/trusty/neutron-contrail/hooks/control-node-relation-broken deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/control-node-relation-broken +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/control-node-relation-departed b/charms/trusty/neutron-contrail/hooks/control-node-relation-departed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/control-node-relation-departed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/control-node-relation-joined b/charms/trusty/neutron-contrail/hooks/control-node-relation-joined deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/control-node-relation-joined +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/identity-admin-relation-broken b/charms/trusty/neutron-contrail/hooks/identity-admin-relation-broken deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/identity-admin-relation-broken +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/identity-admin-relation-changed b/charms/trusty/neutron-contrail/hooks/identity-admin-relation-changed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/identity-admin-relation-changed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/identity-admin-relation-departed b/charms/trusty/neutron-contrail/hooks/identity-admin-relation-departed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/identity-admin-relation-departed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/install b/charms/trusty/neutron-contrail/hooks/install deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/install +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-broken b/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-broken deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-broken +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-changed b/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-changed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-changed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-departed b/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-departed deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-departed +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/neutron-plugin-relation-joined b/charms/trusty/neutron-contrail/hooks/neutron-plugin-relation-joined deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/neutron-plugin-relation-joined +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py b/charms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py deleted file mode 100755 index a0b013c..0000000 --- a/charms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py +++ /dev/null @@ -1,353 +0,0 @@ -#!/usr/bin/env python - -from subprocess import CalledProcessError -import sys - -from apt_pkg import version_compare -import json -import uuid -import yaml - -from charmhelpers.core.hookenv import ( - Hooks, - UnregisteredHookError, - config, - is_leader, - leader_get, - leader_set, - log, - relation_get, - relation_ids, - relation_set -) - -from charmhelpers.core.host import ( - restart_on_change, - service_restart -) - -from charmhelpers.fetch import ( - apt_install, - apt_upgrade, - configure_sources -) - -from neutron_contrail_utils import ( - CONTRAIL_VERSION, - OPENSTACK_VERSION, - configure_vrouter, - disable_vrouter_vgw, - dpkg_version, - drop_caches, - enable_vrouter_vgw, - fix_nodemgr, - fix_permissions, - fix_vrouter_scripts, - ifdown, - ifup, - modprobe, - provision_local_metadata, - provision_vrouter, - remove_juju_bridge, - units, - unprovision_local_metadata, - unprovision_vrouter, - write_barbican_auth_config, - write_nodemgr_config, - write_vnc_api_config, - write_vrouter_config, - write_vrouter_vgw_interfaces -) - -PACKAGES = [ "contrail-vrouter-dkms", "contrail-vrouter-agent", - "contrail-nova-driver", "contrail-utils", "python-jinja2", - "python-netifaces", "python-netaddr", "contrail-nodemgr" ] - -PACKAGES_LBAAS = [ "python-barbicanclient", "haproxy" ] - -hooks = Hooks() -config = config() - -def check_local_metadata(): - if not is_leader(): - return - - if not config.get("vrouter-provisioned"): - if leader_get("local-metadata-provisioned"): - # impossible to know if current hook is firing because - # relation or leader is being removed lp #1469731 - if not relation_ids("cluster"): - unprovision_local_metadata() - leader_set({"local-metadata-provisioned": ""}) - return - - if config["local-metadata-server"]: - if not leader_get("local-metadata-provisioned"): - provision_local_metadata() - leader_set({"local-metadata-provisioned": True}) - elif leader_get("local-metadata-provisioned"): - unprovision_local_metadata() - leader_set({"local-metadata-provisioned": ""}) - -def check_vrouter(): - # check relation dependencies - if config_get("contrail-api-ready") \ - and config_get("control-node-ready") \ - and config_get("identity-admin-ready"): - if not config_get("vrouter-provisioned"): - provision_vrouter() - config["vrouter-provisioned"] = True - elif config_get("vrouter-provisioned"): - unprovision_vrouter() - config["vrouter-provisioned"] = False - -@hooks.hook("config-changed") -def config_changed(): - configure_local_metadata() - configure_virtual_gateways() - write_config() - if not units("contrail-discovery") and not units("control-node"): - config["control-node-ready"] = True if config.get("discovery-server-ip") \ - else False - if not units("contrail-api"): - config["contrail-api-ready"] = True if config.get("contrail-api-ip") \ - else False - check_vrouter() - check_local_metadata() - -def config_get(key): - try: - return config[key] - except KeyError: - return None - -def configure_local_metadata(): - if config["local-metadata-server"]: - if "local-metadata-secret" not in config: - # generate secret - secret = str(uuid.uuid4()) - config["local-metadata-secret"] = secret - settings = { "metadata-shared-secret": secret } - # inform relations - for rid in relation_ids("neutron-plugin"): - relation_set(relation_id=rid, relation_settings=settings) - else: - if "local-metadata-secret" in config: - # remove secret - del config["local-metadata-secret"] - settings = { "metadata-shared-secret": None } - # inform relations - for rid in relation_ids("neutron-plugin"): - relation_set(relation_id=rid, relation_settings=settings) - -def configure_virtual_gateways(): - gateways = config.get("virtual-gateways") - previous_gateways = config_get("virtual-gateways-prev") - if gateways != previous_gateways: - # create/destroy virtual gateway interfaces according to new value - interfaces = { gateway["interface"]: set(gateway["subnets"]) - for gateway in yaml.safe_load(gateways) } \ - if gateways else {} - previous_interfaces = { gateway["interface"]: set(gateway["subnets"]) - for gateway in yaml.safe_load(previous_gateways) } \ - if previous_gateways else {} - ifaces = [ interface for interface, subnets in previous_interfaces.iteritems() - if interface not in interfaces - or subnets != interfaces[interface] ] - if ifaces: - ifdown(ifaces) - - write_vrouter_vgw_interfaces() - - ifaces = [ interface for interface, subnets in interfaces.iteritems() - if interface not in previous_interfaces - or subnets != previous_interfaces[interface] ] - if ifaces: - ifup(ifaces) - - if interfaces: - enable_vrouter_vgw() - else: - disable_vrouter_vgw() - - config["virtual-gateways-prev"] = gateways - -@hooks.hook("contrail-api-relation-departed") -@hooks.hook("contrail-api-relation-broken") -def contrail_api_departed(): - if not units("contrail-api") and not config.get("contrail-api-ip"): - config["contrail-api-ready"] = False - check_vrouter() - check_local_metadata() - write_vnc_api_config() - -@hooks.hook("contrail-api-relation-changed") -def contrail_api_changed(): - if not relation_get("port"): - log("Relation not ready") - return - write_vnc_api_config() - config["contrail-api-ready"] = True - check_vrouter() - check_local_metadata() - -@hooks.hook("contrail-discovery-relation-changed") -def contrail_discovery_changed(): - if not relation_get("port"): - log("Relation not ready") - return - contrail_discovery_relation() - config["control-node-ready"] = True - check_vrouter() - check_local_metadata() - -@hooks.hook("contrail-discovery-relation-departed") -@hooks.hook("contrail-discovery-relation-broken") -def contrail_discovery_departed(): - if not units("contrail-discovery") \ - and not units("control-node") \ - and not config.get("discovery-server-ip"): - config["control-node-ready"] = False - check_vrouter() - check_local_metadata() - contrail_discovery_relation() - -@restart_on_change({"/etc/contrail/contrail-vrouter-agent.conf": ["contrail-vrouter-agent"], - "/etc/contrail/contrail-vrouter-nodemgr.conf": ["contrail-vrouter-nodemgr"]}) -def contrail_discovery_relation(): - write_vrouter_config() - write_nodemgr_config() - -@hooks.hook("control-node-relation-departed") -@hooks.hook("control-node-relation-broken") -def control_node_departed(): - if not units("control-node") \ - and not units("contrail-discovery") \ - and not config.get("discovery-server-ip"): - config["control-node-ready"] = False - check_vrouter() - check_local_metadata() - control_node_relation() - -@hooks.hook("control-node-relation-joined") -def control_node_joined(): - control_node_relation() - config["control-node-ready"] = True - check_vrouter() - check_local_metadata() - -@restart_on_change({"/etc/contrail/contrail-vrouter-agent.conf": ["contrail-vrouter-agent"]}) -def control_node_relation(): - write_vrouter_config() - -@hooks.hook("identity-admin-relation-changed") -def identity_admin_changed(): - if not relation_get("service_hostname"): - log("Relation not ready") - return - write_vnc_api_config() - if version_compare(CONTRAIL_VERSION, "3.0.2.0-34") >= 0: - write_barbican_auth_config() - config["identity-admin-ready"] = True - check_vrouter() - check_local_metadata() - -@hooks.hook("identity-admin-relation-departed") -@hooks.hook("identity-admin-relation-broken") -def identity_admin_departed(): - if not units("identity-admin"): - config["identity-admin-ready"] = False - check_vrouter() - check_local_metadata() - write_vnc_api_config() - if version_compare(CONTRAIL_VERSION, "3.0.2.0-34") >= 0: - write_barbican_auth_config() - -@hooks.hook() -def install(): - configure_sources(True, "install-sources", "install-keys") - apt_upgrade(fatal=True, dist=True) - fix_vrouter_scripts() # bug in 2.0+20141015.1 packages - apt_install(PACKAGES, fatal=True) - - contrail_version = dpkg_version("contrail-vrouter-agent") - openstack_version = dpkg_version("nova-compute") - if version_compare(contrail_version, "3.0.2.0-34") >= 0 \ - and version_compare(openstack_version, "2:12.0.0") >= 0: - # install lbaas packages - apt_install(PACKAGES_LBAAS, fatal=True) - - fix_permissions() - fix_nodemgr() - if config.get("remove-juju-bridge"): - remove_juju_bridge() - try: - modprobe("vrouter") - except CalledProcessError: - log("vrouter kernel module failed to load, clearing pagecache and retrying") - drop_caches() - modprobe("vrouter") - modprobe("vrouter", True, True) - configure_vrouter() - service_restart("nova-compute") - -@hooks.hook("neutron-metadata-relation-changed") -def neutron_metadata_changed(): - if not relation_get("shared-secret"): - log("Relation not ready") - return - neutron_metadata_relation() - -@hooks.hook("neutron-metadata-relation-departed") -@hooks.hook("neutron-metadata-relation-broken") -@restart_on_change({"/etc/contrail/contrail-vrouter-agent.conf": ["contrail-vrouter-agent"]}) -def neutron_metadata_relation(): - write_vrouter_config() - -@hooks.hook("neutron-plugin-relation-joined") -def neutron_plugin_joined(): - # create plugin config - section = [] - if version_compare(OPENSTACK_VERSION, "1:2015.1~") < 0: - if version_compare(OPENSTACK_VERSION, "1:2014.2") >= 0: - section.append(("network_api_class", "nova_contrail_vif.contrailvif.ContrailNetworkAPI")) - else: - section.append(("libvirt_vif_driver", "nova_contrail_vif.contrailvif.VRouterVIFDriver")) - section.append(("firewall_driver", "nova.virt.firewall.NoopFirewallDriver")) - conf = { - "nova-compute": { - "/etc/nova/nova.conf": { - "sections": { - "DEFAULT": section - } - } - } - } - relation_set(subordinate_configuration=json.dumps(conf)) - - if config["local-metadata-server"]: - settings = { "metadata-shared-secret": config["local-metadata-secret"] } - relation_set(relation_settings=settings) - -def main(): - try: - hooks.execute(sys.argv) - except UnregisteredHookError as e: - log("Unknown hook {} - skipping.".format(e)) - -@hooks.hook("upgrade-charm") -def upgrade_charm(): - write_vrouter_config() - write_vnc_api_config() - write_nodemgr_config() - service_restart("supervisor-vrouter") - -@restart_on_change({"/etc/contrail/contrail-vrouter-agent.conf": ["contrail-vrouter-agent"], - "/etc/contrail/contrail-vrouter-nodemgr.conf": ["contrail-vrouter-nodemgr"]}) -def write_config(): - write_vrouter_config() - write_vnc_api_config() - write_nodemgr_config() - -if __name__ == "__main__": - main() diff --git a/charms/trusty/neutron-contrail/hooks/neutron_contrail_utils.py b/charms/trusty/neutron-contrail/hooks/neutron_contrail_utils.py deleted file mode 100644 index 4bb8002..0000000 --- a/charms/trusty/neutron-contrail/hooks/neutron_contrail_utils.py +++ /dev/null @@ -1,478 +0,0 @@ -import functools -import os -import pwd -import shutil -from socket import gethostbyname, gethostname -from subprocess import ( - CalledProcessError, - check_call, - check_output -) -from time import sleep, time - -import apt_pkg -import yaml - -import netaddr -import netifaces - -from charmhelpers.core.hookenv import ( - config, - log, - related_units, - relation_get, - relation_ids, - relation_type, - remote_unit -) - -from charmhelpers.core.host import service_restart, service_start - -from charmhelpers.core.templating import render - -apt_pkg.init() - -def dpkg_version(pkg): - try: - return check_output(["dpkg-query", "-f", "${Version}\\n", "-W", pkg]).rstrip() - except CalledProcessError: - return None - -CONTRAIL_VERSION = dpkg_version("contrail-vrouter-agent") -OPENSTACK_VERSION = dpkg_version("nova-compute") - -config = config() - -def retry(f=None, timeout=10, delay=2): - """Retry decorator. - - Provides a decorator that can be used to retry a function if it raises - an exception. - - :param timeout: timeout in seconds (default 10) - :param delay: retry delay in seconds (default 2) - - Examples:: - - # retry fetch_url function - @retry - def fetch_url(): - # fetch url - - # retry fetch_url function for 60 secs - @retry(timeout=60) - def fetch_url(): - # fetch url - """ - if not f: - return functools.partial(retry, timeout=timeout, delay=delay) - @functools.wraps(f) - def func(*args, **kwargs): - start = time() - error = None - while True: - try: - return f(*args, **kwargs) - except Exception as e: - error = e - elapsed = time() - start - if elapsed >= timeout: - raise error - remaining = timeout - elapsed - if delay <= remaining: - sleep(delay) - else: - sleep(remaining) - raise error - return func - -def configure_vrouter(): - # run external script to configure vrouter - args = ["./create-vrouter.sh"] - iface = config.get("vhost-interface") - if iface: - args.append(iface) - check_call(args, cwd="scripts") - -def contrail_api_ctx(): - ip = config.get("contrail-api-ip") - if ip: - port = config.get("contrail-api-port") - return { "api_server": ip, - "api_port": port if port is not None else 8082 } - - ctxs = [ { "api_server": gethostbyname(relation_get("private-address", unit, rid)), - "api_port": port } - for rid in relation_ids("contrail-api") - for unit, port in - ((unit, relation_get("port", unit, rid)) for unit in related_units(rid)) - if port ] - return ctxs[0] if ctxs else {} - -def contrail_discovery_ctx(): - ip = config.get("discovery-server-ip") - if ip: - return { "discovery_server": ip, - "discovery_port": 5998 } - - ctxs = [ { "discovery_server": vip if vip \ - else gethostbyname(relation_get("private-address", unit, rid)), - "discovery_port": port } - for rid in relation_ids("contrail-discovery") - for unit, port, vip in - ((unit, relation_get("port", unit, rid), relation_get("vip", unit, rid)) - for unit in related_units(rid)) - if port ] - return ctxs[0] if ctxs else {} - -@retry(timeout=300) -def contrail_provision_linklocal(api_ip, api_port, service_name, service_ip, - service_port, fabric_ip, fabric_port, op, - user, password): - check_call(["contrail-provision-linklocal", - "--api_server_ip", api_ip, - "--api_server_port", str(api_port), - "--linklocal_service_name", service_name, - "--linklocal_service_ip", service_ip, - "--linklocal_service_port", str(service_port), - "--ipfabric_service_ip", fabric_ip, - "--ipfabric_service_port", str(fabric_port), - "--oper", op, - "--admin_user", user, - "--admin_password", password]) - -@retry(timeout=300) -def contrail_provision_vrouter(hostname, ip, api_ip, api_port, op, - user, password, tenant): - check_call(["contrail-provision-vrouter", - "--host_name", hostname, - "--host_ip", ip, - "--api_server_ip", api_ip, - "--api_server_port", str(api_port), - "--oper", op, - "--admin_user", user, - "--admin_password", password, - "--admin_tenant_name", tenant]) - -def control_node_ctx(): - return { "control_nodes": [ gethostbyname(relation_get("private-address", unit, rid)) - for rid in relation_ids("control-node") - for unit in related_units(rid) ] } - -def disable_vrouter_vgw(): - if os.path.exists("/etc/sysctl.d/60-vrouter-vgw.conf"): - # unset sysctl options - os.remove("/etc/sysctl.d/60-vrouter-vgw.conf") - check_call(["sysctl", "-qw", "net.ipv4.ip_forward=0"]) - -def drop_caches(): - """Clears OS pagecache""" - log("Clearing pagecache") - check_call(["sync"]) - with open("/proc/sys/vm/drop_caches", "w") as f: - f.write("3\n") - -def enable_vrouter_vgw(): - if not os.path.exists("/etc/sysctl.d/60-vrouter-vgw.conf"): - # set sysctl options - shutil.copy("files/60-vrouter-vgw.conf", "/etc/sysctl.d") - service_start("procps") - -def fix_nodemgr(): - # add files missing from contrail-nodemgr package - shutil.copy("files/contrail-nodemgr-vrouter.ini", - "/etc/contrail/supervisord_vrouter_files") - pw = pwd.getpwnam("contrail") - os.chown("/etc/contrail/supervisord_vrouter_files/contrail-nodemgr-vrouter.ini", - pw.pw_uid, pw.pw_gid) - shutil.copy("files/contrail-vrouter.rules", - "/etc/contrail/supervisord_vrouter_files") - os.chown("/etc/contrail/supervisord_vrouter_files/contrail-vrouter.rules", - pw.pw_uid, pw.pw_gid) - shutil.copy("files/contrail-vrouter-nodemgr", "/etc/init.d") - os.chmod("/etc/init.d/contrail-vrouter-nodemgr", 0755) - service_restart("supervisor-vrouter") - -def fix_permissions(): - os.chmod("/etc/contrail", 0755) - os.chown("/etc/contrail", 0, 0) - -def fix_vrouter_scripts(): - # certain files need to be present for packages - if not os.path.exists("/opt/contrail/bin"): - os.makedirs("/opt/contrail/bin") - os.symlink("/bin/true", "/opt/contrail/bin/vrouter-pre-start.sh") - os.symlink("/bin/true", "/opt/contrail/bin/vrouter-post-start.sh") - os.symlink("/bin/true", "/opt/contrail/bin/vrouter-pre-stop.sh") - -def identity_admin_ctx(): - ctxs = [ { "auth_host": gethostbyname(hostname), - "auth_port": relation_get("service_port", unit, rid), - "admin_user": relation_get("service_username", unit, rid), - "admin_password": relation_get("service_password", unit, rid), - "admin_tenant_name": relation_get("service_tenant_name", unit, rid), - "auth_region": relation_get("service_region", unit, rid) } - for rid in relation_ids("identity-admin") - for unit, hostname in - ((unit, relation_get("service_hostname", unit, rid)) for unit in related_units(rid)) - if hostname ] - return ctxs[0] if ctxs else {} - -def ifdown(interfaces=None): - """ifdown an interface or all interfaces""" - log("Taking down {}".format(interfaces if interfaces else "interfaces")) - check_call(["ifdown"] + interfaces if interfaces else ["-a"]) - -def ifup(interfaces=None): - """ifup an interface or all interfaces""" - log("Bringing up {}".format(interfaces if interfaces else "interfaces")) - check_call(["ifup"] + interfaces if interfaces else ["-a"]) - -def lsmod(module): - """Check if a kernel module is loaded""" - with open("/proc/modules", "r") as modules: - for line in modules: - if line.split()[0] == module: - return True - return False - -def modprobe(module, auto_load=False, dkms_autoinstall=False): - """Load a kernel module. - - Allows loading of a kernel module. - - 'dkms_autoinstall' is useful for DKMS kernel modules. Juju often upgrades - units to newer kernels before charm install, which won't be used until the - machine is rebooted. In these cases, some modules may not be compiled for - the newer kernel. Setting this argument to True will ensure these modules - are compiled for newer kernels. - - :param module: module to load - :param auto_load: load module on boot (default False) - :param dkms_autoinstall: invoke DKMS autoinstall for other kernels - (default False) - """ - if not lsmod(module): - log("Loading kernel module {}".format(module)) - check_call(["modprobe", module]) - if auto_load: - with open("/etc/modules", "a") as modules: - modules.write(module) - modules.write("\n") - if dkms_autoinstall: - current = check_output(["uname", "-r"]).rstrip() - for kernel in os.listdir("/lib/modules"): - if kernel == current: - continue - log("DKMS auto installing for kernel {}".format(kernel)) - check_call(["dkms", "autoinstall", "-k", kernel]) - -def network_ctx(): - iface = config.get("control-interface") - return { "control_network_ip": netifaces.ifaddresses(iface)[netifaces.AF_INET][0]["addr"] } - -def neutron_metadata_ctx(): - if "local-metadata-secret" in config: - return { "metadata_secret": config["local-metadata-secret"] } - - ctxs = [ { "metadata_secret": relation_get("shared-secret", unit, rid) } - for rid in relation_ids("neutron-metadata") - for unit in related_units(rid) ] - return ctxs[0] if ctxs else {} - -def provision_local_metadata(): - api_port = None - api_ip = config.get("contrail-api-ip") - if api_ip: - api_port = config.get("contrail-api-port") - if api_port is None: - api_port = 8082 - else: - api_ip, api_port = [ (gethostbyname(relation_get("private-address", unit, rid)), - port) - for rid in relation_ids("contrail-api") - for unit, port in - ((unit, relation_get("port", unit, rid)) for unit in related_units(rid)) - if port ][0] - user, password = [ (relation_get("service_username", unit, rid), - relation_get("service_password", unit, rid)) - for rid in relation_ids("identity-admin") - for unit in related_units(rid) - if relation_get("service_hostname", unit, rid) ][0] - log("Provisioning local metadata service 127.0.0.1:8775") - contrail_provision_linklocal(api_ip, api_port, "metadata", - "169.254.169.254", 80, "127.0.0.1", 8775, - "add", user, password) - -def provision_vrouter(): - hostname = gethostname() - ip = netifaces.ifaddresses("vhost0")[netifaces.AF_INET][0]["addr"] - api_port = None - api_ip = config.get("contrail-api-ip") - if api_ip: - api_port = config.get("contrail-api-port") - if api_port is None: - api_port = 8082 - else: - api_ip, api_port = [ (gethostbyname(relation_get("private-address", unit, rid)), - port) - for rid in relation_ids("contrail-api") - for unit, port in - ((unit, relation_get("port", unit, rid)) for unit in related_units(rid)) - if port ][0] - user, password, tenant = [ (relation_get("service_username", unit, rid), - relation_get("service_password", unit, rid), - relation_get("service_tenant_name", unit, rid)) - for rid in relation_ids("identity-admin") - for unit in related_units(rid) - if relation_get("service_hostname", unit, rid) ][0] - log("Provisioning vrouter {}".format(ip)) - contrail_provision_vrouter(hostname, ip, api_ip, api_port, "add", - user, password, tenant) - -def remove_juju_bridge(): - # run external script to remove bridge - check_call(["./remove-juju-bridge.sh"], cwd="scripts") - -def units(relation): - """Return a list of units for the specified relation""" - return [ unit for rid in relation_ids(relation) - for unit in related_units(rid) ] - -def unprovision_local_metadata(): - relation = relation_type() - if relation and not remote_unit(): - return - api_ip = config.previous("contrail-api-ip") - api_port = None - if api_ip: - api_port = config.previous("contrail-api-port") - if api_port is None: - api_port = 8082 - elif relation == "contrail-api": - api_ip = gethostbyname(relation_get("private-address")) - api_port = relation_get("port") - else: - api_ip, api_port = [ (gethostbyname(relation_get("private-address", unit, rid)), - relation_get("port", unit, rid)) - for rid in relation_ids("contrail-api") - for unit in related_units(rid) ][0] - user = None - password = None - if relation == "identity-admin": - user = relation_get("service_username") - password = relation_get("service_password") - else: - user, password = [ (relation_get("service_username", unit, rid), - relation_get("service_password", unit, rid)) - for rid in relation_ids("identity-admin") - for unit in related_units(rid) ][0] - log("Unprovisioning local metadata service 127.0.0.1:8775") - contrail_provision_linklocal(api_ip, api_port, "metadata", - "169.254.169.254", 80, "127.0.0.1", 8775, - "del", user, password) - -def unprovision_vrouter(): - relation = relation_type() - if relation and not remote_unit(): - return - hostname = gethostname() - ip = netifaces.ifaddresses("vhost0")[netifaces.AF_INET][0]["addr"] - api_ip = config.previous("contrail-api-ip") - api_port = None - if api_ip: - api_port = config.previous("contrail-api-port") - if api_port is None: - api_port = 8082 - elif relation == "contrail-api": - api_ip = gethostbyname(relation_get("private-address")) - api_port = relation_get("port") - else: - api_ip, api_port = [ (gethostbyname(relation_get("private-address", unit, rid)), - relation_get("port", unit, rid)) - for rid in relation_ids("contrail-api") - for unit in related_units(rid) ][0] - user = None - password = None - tenant = None - if relation == "identity-admin": - user = relation_get("service_username") - password = relation_get("service_password") - tenant = relation_get("service_tenant_name") - else: - user, password, tenant = [ (relation_get("service_username", unit, rid), - relation_get("service_password", unit, rid), - relation_get("service_tenant_name", unit, rid)) - for rid in relation_ids("identity-admin") - for unit in related_units(rid) ][0] - log("Unprovisioning vrouter {}".format(ip)) - contrail_provision_vrouter(hostname, ip, api_ip, api_port, "del", - user, password, tenant) - -def vhost_gateway(): - # determine vhost gateway - gateway = config.get("vhost-gateway") - if gateway == "auto": - for line in check_output(["route", "-n"]).splitlines()[2:]: - l = line.split() - if "G" in l[3] and l[7] == "vhost0": - return l[1] - gateway = None - return gateway - -def vhost_ip(iface): - # return a vhost formatted address and mask - x.x.x.x/xx - addr = netifaces.ifaddresses(iface)[netifaces.AF_INET][0] - ip = addr["addr"] - cidr = netaddr.IPNetwork(ip + "/" + addr["netmask"]).prefixlen - return ip + "/" + str(cidr) - -def vhost_phys(): - # run external script to determine physical interface of vhost0 - return check_output(["scripts/vhost-phys.sh"]).rstrip() - -def vrouter_ctx(): - return { "vhost_ip": vhost_ip("vhost0"), - "vhost_gateway": vhost_gateway(), - "vhost_physical": vhost_phys() } - -def vrouter_vgw_ctx(): - ctx = {} - vgws = config.get("virtual-gateways") - if vgws: - vgws = yaml.safe_load(vgws) - map(lambda item: item.update(domain="default-domain"), vgws) - ctx["vgws"] = vgws - return ctx - -def write_barbican_auth_config(): - ctx = identity_admin_ctx() - render("contrail-barbican-auth.conf", - "/etc/contrail/contrail-barbican-auth.conf", ctx, "root", "contrail", - 0440) - -def write_nodemgr_config(): - ctx = contrail_discovery_ctx() - render("contrail-vrouter-nodemgr.conf", - "/etc/contrail/contrail-vrouter-nodemgr.conf", ctx) - -def write_vnc_api_config(): - ctx = {} - ctx.update(contrail_api_ctx()) - ctx.update(identity_admin_ctx()) - render("vnc_api_lib.ini", "/etc/contrail/vnc_api_lib.ini", ctx) - -def write_vrouter_config(): - ctx = {} - ctx.update(control_node_ctx()) - ctx.update(contrail_discovery_ctx()) - ctx.update(neutron_metadata_ctx()) - ctx.update(network_ctx()) - ctx.update(vrouter_ctx()) - ctx.update(vrouter_vgw_ctx()) - render("contrail-vrouter-agent.conf", - "/etc/contrail/contrail-vrouter-agent.conf", ctx, perms=0440) - -def write_vrouter_vgw_interfaces(): - ctx = vrouter_vgw_ctx() - render("vrouter-vgw.cfg", "/etc/network/interfaces.d/vrouter-vgw.cfg", ctx) diff --git a/charms/trusty/neutron-contrail/hooks/start b/charms/trusty/neutron-contrail/hooks/start deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/start +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/stop b/charms/trusty/neutron-contrail/hooks/stop deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/stop +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/hooks/upgrade-charm b/charms/trusty/neutron-contrail/hooks/upgrade-charm deleted file mode 120000 index 930b3fb..0000000 --- a/charms/trusty/neutron-contrail/hooks/upgrade-charm +++ /dev/null @@ -1 +0,0 @@ -neutron_contrail_hooks.py
\ No newline at end of file diff --git a/charms/trusty/neutron-contrail/icon.svg b/charms/trusty/neutron-contrail/icon.svg deleted file mode 100644 index 6f77c1a..0000000 --- a/charms/trusty/neutron-contrail/icon.svg +++ /dev/null @@ -1,309 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="96" - height="96" - id="svg6517" - version="1.1" - inkscape:version="0.91 r13725" - sodipodi:docname="icon.svg"> - <defs - id="defs6519"> - <linearGradient - id="Background"> - <stop - id="stop4178" - offset="0" - style="stop-color:#b8b8b8;stop-opacity:1" /> - <stop - id="stop4180" - offset="1" - style="stop-color:#c9c9c9;stop-opacity:1" /> - </linearGradient> - <filter - style="color-interpolation-filters:sRGB;" - inkscape:label="Inner Shadow" - id="filter1121"> - <feFlood - flood-opacity="0.59999999999999998" - flood-color="rgb(0,0,0)" - result="flood" - id="feFlood1123" /> - <feComposite - in="flood" - in2="SourceGraphic" - operator="out" - result="composite1" - id="feComposite1125" /> - <feGaussianBlur - in="composite1" - stdDeviation="1" - result="blur" - id="feGaussianBlur1127" /> - <feOffset - dx="0" - dy="2" - result="offset" - id="feOffset1129" /> - <feComposite - in="offset" - in2="SourceGraphic" - operator="atop" - result="composite2" - id="feComposite1131" /> - </filter> - <filter - style="color-interpolation-filters:sRGB;" - inkscape:label="Drop Shadow" - id="filter950"> - <feFlood - flood-opacity="0.25" - flood-color="rgb(0,0,0)" - result="flood" - id="feFlood952" /> - <feComposite - in="flood" - in2="SourceGraphic" - operator="in" - result="composite1" - id="feComposite954" /> - <feGaussianBlur - in="composite1" - stdDeviation="1" - result="blur" - id="feGaussianBlur956" /> - <feOffset - dx="0" - dy="1" - result="offset" - id="feOffset958" /> - <feComposite - in="SourceGraphic" - in2="offset" - operator="over" - result="composite2" - id="feComposite960" /> - </filter> - <clipPath - clipPathUnits="userSpaceOnUse" - id="clipPath873"> - <g - transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)" - id="g875" - inkscape:label="Layer 1" - style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"> - <path - style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline" - d="m 46.702703,898.22775 50.594594,0 C 138.16216,898.22775 144,904.06497 144,944.92583 l 0,50.73846 c 0,40.86071 -5.83784,46.69791 -46.702703,46.69791 l -50.594594,0 C 5.8378378,1042.3622 0,1036.525 0,995.66429 L 0,944.92583 C 0,904.06497 5.8378378,898.22775 46.702703,898.22775 Z" - id="path877" - inkscape:connector-curvature="0" - sodipodi:nodetypes="sssssssss" /> - </g> - </clipPath> - <filter - inkscape:collect="always" - id="filter891" - inkscape:label="Badge Shadow"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="0.71999962" - id="feGaussianBlur893" /> - </filter> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="4.0745362" - inkscape:cx="48.413329" - inkscape:cy="49.018169" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="true" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" - inkscape:window-width="1920" - inkscape:window-height="1025" - inkscape:window-x="0" - inkscape:window-y="27" - inkscape:window-maximized="1" - showborder="true" - showguides="true" - inkscape:guide-bbox="true" - inkscape:showpageshadow="false"> - <inkscape:grid - type="xygrid" - id="grid821" /> - <sodipodi:guide - orientation="1,0" - position="16,48" - id="guide823" /> - <sodipodi:guide - orientation="0,1" - position="64,80" - id="guide825" /> - <sodipodi:guide - orientation="1,0" - position="80,40" - id="guide827" /> - <sodipodi:guide - orientation="0,1" - position="64,16" - id="guide829" /> - </sodipodi:namedview> - <metadata - id="metadata6522"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="BACKGROUND" - inkscape:groupmode="layer" - id="layer1" - transform="translate(268,-635.29076)" - style="display:inline"> - <path - style="fill:#ebebeb;fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)" - d="m -268,700.15563 0,-33.72973 c 0,-27.24324 3.88785,-31.13513 31.10302,-31.13513 l 33.79408,0 c 27.21507,0 31.1029,3.89189 31.1029,31.13513 l 0,33.72973 c 0,27.24325 -3.88783,31.13514 -31.1029,31.13514 l -33.79408,0 C -264.11215,731.29077 -268,727.39888 -268,700.15563 Z" - id="path6455" - inkscape:connector-curvature="0" - sodipodi:nodetypes="sssssssss" /> - </g> - <g - inkscape:groupmode="layer" - id="layer3" - inkscape:label="PLACE YOUR PICTOGRAM HERE" - style="display:inline"> - <g - style="display:inline" - transform="matrix(0.30759127,0,0,0.30759127,8.28218,8.97257)" - id="g3732"> - <path - style="fill:#a3cfe8" - d="M 95,165.62616 C 84.317392,162.68522 76.316695,156.3432 71.320441,146.85577 68.731857,141.94027 68.5,140.61329 68.5,130.71353 c 0,-11.83269 0.397793,-12.66977 6.034392,-12.69822 C 78.926707,117.99315 81,121.97863 81,130.44413 c 0,9.5666 3.34886,15.50194 11.662711,20.67036 3.651393,2.26995 4.798754,2.40131 23.683989,2.71173 l 19.8467,0.32623 -0.71218,2.17377 c -0.91082,2.78009 -0.90418,5.58369 0.0199,8.42378 l 0.73211,2.25 -18.36663,-0.0675 C 106.56201,166.89096 97.76974,166.38867 95,165.62616 Z m 46.00868,-0.11571 c -1.77687,-2.14099 -1.82625,-7.82041 -0.0862,-9.917 1.07681,-1.29747 3.57513,-1.59374 13.45,-1.595 9.54779,-0.001 12.86912,-0.37349 15.61365,-1.75 9.3963,-4.71272 7.35301,-19.21115 -2.93942,-20.85698 -2.07398,-0.33164 -4.19534,-0.89289 -4.71413,-1.24723 -0.51879,-0.35433 -1.44954,-3.43526 -2.06833,-6.84652 -1.37797,-7.59639 -3.48916,-12.20669 -7.30276,-15.94738 -3.66382,-3.59378 -3.6595,-4.21104 0.0385,-5.50018 2.54055,-0.88564 3,-1.56686 3,-4.447985 0,-4.258462 1.35388,-4.297632 5.25974,-0.152175 4.55275,4.83203 8.57589,11.55276 10.42257,17.41111 1.15326,3.65858 2.26012,5.35908 3.72889,5.72883 3.21482,0.8093 9.54053,7.29049 11.64977,11.9361 2.26213,4.98232 2.53846,14.30356 0.56413,19.02881 -1.97355,4.72336 -7.28419,10.42159 -12.03042,12.90844 -3.50369,1.8358 -6.19345,2.20312 -18.636,2.54499 -12.76506,0.35072 -14.7134,0.19219 -15.95,-1.29783 z M 36.760565,161.75 c -3.478655,-4.56459 -7.187084,-12.21027 -9.336932,-19.25 -2.778434,-9.09804 -2.583706,-24.94034 0.417306,-33.95043 3.497444,-10.500559 9.898641,-21.56636 12.457102,-21.534693 0.661077,0.0082 2.925911,1.473635 5.032964,3.256562 l 3.831004,3.241685 -2.568452,5.113673 C 42.599304,106.57918 40.65102,115.46967 40.594928,126 c -0.0579,10.86969 1.439444,17.99787 5.535634,26.35262 1.578191,3.21895 2.85983,6.14395 2.848087,6.5 C 48.949775,159.72808 41.428955,165 40.208913,165 c -0.534344,0 -2.086101,-1.4625 -3.448348,-3.25 z m 175.995035,-0.0376 -3.7444,-3.21245 1.79249,-3 c 8.93434,-14.95294 9.53034,-38.50427 1.41338,-55.849827 l -3.07866,-6.578941 4.1278,-3.035616 C 215.5365,88.366027 217.71535,87 218.10811,87 c 1.50502,0 6.33619,6.757331 8.97827,12.55785 7.79191,17.10669 7.87368,37.40315 0.21328,52.94215 -2.91602,5.91511 -7.82715,12.49548 -9.29966,12.46052 -0.825,-0.0196 -3.18498,-1.48122 -5.2444,-3.24807 z M 81.482645,115.96644 c -1.483807,-2.86937 -1.949857,-3.10137 -5.058516,-2.51818 -4.663007,0.87478 -4.493442,-0.95188 0.628511,-6.77072 5.256509,-5.97171 14.327595,-10.460488 22.924736,-11.34418 4.557714,-0.468483 7.786604,-1.496091 10.894994,-3.467375 10.33444,-6.553906 24.98246,-8.287165 35.62763,-4.215718 4.82222,1.84435 5,2.051462 5,5.824988 0,3.32368 -0.46902,4.186565 -3.11582,5.732379 -2.93452,1.713856 -3.47765,1.727036 -9.3345,0.226582 -5.19732,-1.331492 -7.06708,-1.394156 -11.38418,-0.381538 -6.35168,1.489842 -8.08332,2.337822 -13.18203,6.455152 -3.63495,2.93531 -4.49954,3.19704 -9.10062,2.75494 -6.189167,-0.59471 -12.218344,1.78693 -18.196739,7.18806 l -4.06908,3.67616 -1.634386,-3.16055 z" - id="path3746" - inkscape:connector-curvature="0" /> - <path - style="fill:#9a9a9c" - d="m 93.286039,164.54925 c -16.494387,-5.15489 -26.958648,-21.00658 -24.875196,-37.68196 0.843223,-6.74892 1.329136,-7.48226 5.337762,-8.05574 4.602358,-0.65842 6.634722,2.66079 6.356138,10.38072 -0.355642,9.8553 5.007342,19.02839 13.395257,22.91187 3.449975,1.59728 6.65053,1.85496 23.27568,1.8739 l 19.27568,0.022 -1.5223,2.9438 c -1.13702,2.19876 -1.27006,3.60722 -0.52568,5.5651 0.54814,1.44171 0.99662,2.817 0.99662,3.0562 0,1.13237 -37.784447,0.21221 -41.713961,-1.01585 z M 140.3757,163.25 c -0.75749,-2.06167 -0.6343,-3.56348 0.49217,-6 l 1.50255,-3.25 12.9105,0 c 14.6294,0 17.5288,-0.97189 20.29597,-6.80328 3.45454,-7.27989 -1.32251,-15.43619 -9.78395,-16.70506 l -4.53221,-0.67965 -0.51854,-5.71858 c -0.55357,-6.10485 -4.15117,-14.35103 -7.6341,-17.49842 -2.70447,-2.44391 -2.6528,-3.02579 0.39191,-4.41306 1.58875,-0.72388 2.50558,-1.96702 2.51531,-3.410511 0.008,-1.249292 0.39216,-2.865775 0.85274,-3.592185 C 158.67512,92.329247 172,111.55317 172,117.01025 c 0,0.94756 2.19487,3.0552 4.99312,4.79469 16.07824,9.99478 15.53196,32.74917 -0.99499,41.44506 -5.0138,2.63808 -5.82451,2.75 -19.91928,2.75 l -14.69277,0 -1.01038,-2.75 z M 35.40716,159.29417 c -2.083023,-3.13821 -5.109308,-9.54119 -6.725077,-14.22886 -2.485242,-7.21018 -2.938617,-10.06664 -2.943307,-18.54417 -0.0036,-6.59373 0.591734,-12.07325 1.74079,-16.02114 2.125307,-7.30206 7.833992,-18.506493 10.893586,-21.380833 l 2.245692,-2.109718 4.114129,3.025565 4.114129,3.025564 -2.940589,6.48533 c -7.687874,16.955242 -7.684823,36.645922 0.0082,53.085582 l 2.95122,6.30662 -3.826883,3.03094 C 42.934289,163.63607 40.758205,165 40.203333,165 c -0.554872,0 -2.71315,-2.56762 -4.796173,-5.70583 z m 178.33231,2.91881 c -4.12643,-2.97696 -4.12127,-2.77305 -0.30142,-11.89827 C 216.73845,142.43037 218,135.70645 218,126 c 0,-9.70412 -1.26117,-16.4284 -4.56034,-24.31471 -1.42316,-3.401907 -2.66678,-6.795138 -2.76361,-7.540509 -0.0968,-0.74537 1.55376,-2.77037 3.66797,-4.5 L 218.18803,86.5 l 2.46357,3 c 10.21069,12.43401 14.79345,33.98475 10.72523,50.43611 -2.37412,9.60065 -10.56942,25.165 -13.17772,25.02687 -0.38451,-0.0204 -2.39135,-1.25787 -4.45964,-2.75 z M 81.841186,115.55079 c -0.878315,-1.9277 -1.99166,-2.51327 -5.228562,-2.75 L 72.5,112.5 77.225927,107.42203 C 83.456988,100.72681 89.946931,97.312559 99.091117,95.919125 103.166,95.298175 107.175,94.376154 108,93.87019 c 0.825,-0.505965 4.40457,-2.344245 7.95461,-4.085068 8.22915,-4.035307 19.81365,-4.987772 28.27907,-2.325071 7.55962,2.37779 7.79351,2.597566 7.12811,6.697941 C 150.57502,99.006294 146.1878,101.20891 141,99.36016 132.99683,96.508113 122.06502,98.684599 115.29736,104.47747 111.53712,107.6961 110.64067,108 104.90676,108 97.846719,108 92.517648,110.09663 87.188282,114.97101 85.366837,116.63695 83.669689,118 83.416843,118 c -0.252846,0 -0.961892,-1.10215 -1.575657,-2.44921 z" - id="path3744" - inkscape:connector-curvature="0" /> - <path - style="fill:#50a1d2" - d="m 93.286039,164.54925 c -16.494387,-5.15489 -26.958648,-21.00658 -24.875196,-37.68196 0.843223,-6.74892 1.329136,-7.48226 5.337762,-8.05574 4.602358,-0.65842 6.634722,2.66079 6.356138,10.38072 -0.355642,9.8553 5.007342,19.02839 13.395257,22.91187 3.449975,1.59728 6.65053,1.85496 23.27568,1.8739 l 19.27568,0.022 -1.5223,2.9438 c -1.13702,2.19876 -1.27006,3.60722 -0.52568,5.5651 0.54814,1.44171 0.99662,2.817 0.99662,3.0562 0,1.13237 -37.784447,0.21221 -41.713961,-1.01585 z M 140.3757,163.25 c -0.75749,-2.06167 -0.6343,-3.56348 0.49217,-6 l 1.50255,-3.25 12.9105,0 c 14.6294,0 17.5288,-0.97189 20.29597,-6.80328 3.45454,-7.27989 -1.32251,-15.43619 -9.78395,-16.70506 l -4.53221,-0.67965 -0.51854,-5.71858 c -0.55357,-6.10485 -4.15117,-14.35103 -7.6341,-17.49842 -2.70447,-2.44391 -2.6528,-3.02579 0.39191,-4.41306 1.58875,-0.72388 2.50558,-1.96702 2.51531,-3.410511 0.008,-1.249292 0.39216,-2.865775 0.85274,-3.592185 C 158.67512,92.329247 172,111.55317 172,117.01025 c 0,0.94756 2.19487,3.0552 4.99312,4.79469 16.07824,9.99478 15.53196,32.74917 -0.99499,41.44506 -5.0138,2.63808 -5.82451,2.75 -19.91928,2.75 l -14.69277,0 -1.01038,-2.75 z M 36.924699,160.79198 C 33.485946,156.10457 30.687068,150.24942 28.180767,142.5 c -2.22154,-6.86895 -2.214797,-26.11727 0.01161,-33.13024 2.21057,-6.96308 6.348289,-15.18965 9.611074,-19.108624 L 40.5,87.022271 l 3.875471,3.282759 3.875472,3.282758 -2.18708,4.287031 c -7.653476,15.002051 -8.071995,38.329351 -0.968739,53.995241 3.168854,6.98876 3.078371,7.44609 -2.21963,11.2186 l -2.802135,1.99529 -3.14866,-4.29197 z m 177.289621,1.13424 -4.17969,-3.07377 1.95557,-3.83324 c 5.55817,-10.89491 7.78283,-24.62144 6.0729,-37.4708 -0.61859,-4.64838 -1.81396,-10.16088 -2.65638,-12.25 -1.54072,-3.82085 -4.3711,-10.259911 -5.02182,-11.424556 -0.6119,-1.095168 7.44846,-6.09488 8.63936,-5.35886 2.42142,1.496519 8.05598,11.676956 10.60291,19.157176 3.82818,11.24317 3.81121,25.44418 -0.044,36.82783 -2.07525,6.12777 -9.78971,20.5 -11.00362,20.5 -0.10204,0 -2.06639,-1.3832 -4.36522,-3.07378 z M 81.841186,115.55079 c -0.878315,-1.9277 -1.99166,-2.51327 -5.228562,-2.75 L 72.5,112.5 77.225927,107.42203 C 83.456988,100.72681 89.946931,97.312559 99.091117,95.919125 103.166,95.298175 107.175,94.376154 108,93.87019 c 0.825,-0.505965 4.40457,-2.344245 7.95461,-4.085068 8.22915,-4.035307 19.81365,-4.987772 28.27907,-2.325071 7.55962,2.37779 7.79351,2.597566 7.12811,6.697941 C 150.57502,99.006294 146.1878,101.20891 141,99.36016 132.99683,96.508113 122.06502,98.684599 115.29736,104.47747 111.53712,107.6961 110.64067,108 104.90676,108 97.846719,108 92.517648,110.09663 87.188282,114.97101 85.366837,116.63695 83.669689,118 83.416843,118 c -0.252846,0 -0.961892,-1.10215 -1.575657,-2.44921 z" - id="path3742" - inkscape:connector-curvature="0" /> - <path - style="fill:#258bc8" - d="m 140.94241,163.34852 c -0.60534,-1.59216 -0.6633,-3.68963 -0.14507,-5.25 0.8603,-2.5903 0.90545,-2.60011 14.28284,-3.09996 7.93908,-0.29664 14.30706,-1.00877 15.59227,-1.74367 10.44037,-5.96999 7.38458,-21.04866 -4.67245,-23.05598 l -4.5,-0.74919 -0.58702,-5.97486 c -0.62455,-6.35693 -3.09323,-12.09225 -7.29978,-16.95905 l -2.57934,-2.98419 2.20484,-0.81562 c 2.73303,-1.01102 3.71477,-2.49335 3.78569,-5.716 0.0511,-2.322172 0.38375,-2.144343 4.67651,2.5 4.32664,4.681 10.2991,15.64731 10.2991,18.91066 0,0.80001 0.94975,1.756 2.11054,2.12443 3.25146,1.03197 9.8171,7.40275 11.96188,11.60686 2.54215,4.98304 2.56222,14.86412 0.0414,20.41386 -2.26808,4.99343 -8.79666,10.73297 -13.97231,12.28363 C 170.01108,165.47775 162.34653,166 155.10923,166 l -13.15873,0 -1.00809,-2.65148 z M 36.924699,160.79198 C 33.485946,156.10457 30.687068,150.24942 28.180767,142.5 c -2.22154,-6.86895 -2.214797,-26.11727 0.01161,-33.13024 2.21057,-6.96308 6.348289,-15.18965 9.611074,-19.108624 L 40.5,87.022271 l 3.875471,3.282759 3.875472,3.282758 -2.18708,4.287031 c -7.653476,15.002051 -8.071995,38.329351 -0.968739,53.995241 3.168854,6.98876 3.078371,7.44609 -2.21963,11.2186 l -2.802135,1.99529 -3.14866,-4.29197 z m 177.289621,1.13424 -4.17969,-3.07377 1.95557,-3.83324 c 5.55817,-10.89491 7.78283,-24.62144 6.0729,-37.4708 -0.61859,-4.64838 -1.81396,-10.16088 -2.65638,-12.25 -1.54072,-3.82085 -4.3711,-10.259911 -5.02182,-11.424556 -0.6119,-1.095168 7.44846,-6.09488 8.63936,-5.35886 2.42142,1.496519 8.05598,11.676956 10.60291,19.157176 3.82818,11.24317 3.81121,25.44418 -0.044,36.82783 -2.07525,6.12777 -9.78971,20.5 -11.00362,20.5 -0.10204,0 -2.06639,-1.3832 -4.36522,-3.07378 z M 81.664567,115.0093 c -1.516672,-2.56752 -2.095101,-2.81369 -5.364599,-2.28313 l -3.66463,0.59469 2.22168,-3.12006 C 80.37626,102.44974 90.120126,97.000633 99.857357,96.219746 105.13094,95.796826 107.53051,95.01192 111.5,92.411404 c 10.08936,-6.609802 24.47284,-8.157994 35.30015,-3.799597 4.05392,1.631857 4.28296,1.935471 4,5.302479 -0.41543,4.943233 -3.85308,6.604794 -10.30411,4.980399 -9.07108,-2.284124 -18.26402,-0.195093 -26.41897,6.003525 -2.78485,2.11679 -4.55576,2.61322 -9.5,2.66311 -6.674981,0.0673 -12.069467,2.29808 -17.866999,7.38838 l -3.345536,2.93742 -1.699968,-2.87782 z" - id="path3740" - inkscape:connector-curvature="0" /> - <path - style="fill:#6c6d71" - d="M 36.924699,160.79198 C 33.485946,156.10457 30.687068,150.24942 28.180767,142.5 c -2.22154,-6.86895 -2.214797,-26.11727 0.01161,-33.13024 2.21057,-6.96308 6.348289,-15.18965 9.611074,-19.108624 L 40.5,87.022271 l 3.875471,3.282759 3.875472,3.282758 -2.18708,4.287031 c -7.653476,15.002051 -8.071995,38.329351 -0.968739,53.995241 3.168854,6.98876 3.078371,7.44609 -2.21963,11.2186 l -2.802135,1.99529 -3.14866,-4.29197 z m 177.289621,1.13424 -4.17969,-3.07377 1.95557,-3.83324 c 5.55817,-10.89491 7.78283,-24.62144 6.0729,-37.4708 -0.61859,-4.64838 -1.81396,-10.16088 -2.65638,-12.25 -1.54072,-3.82085 -4.3711,-10.259911 -5.02182,-11.424556 -0.6119,-1.095168 7.44846,-6.09488 8.63936,-5.35886 2.42142,1.496519 8.05598,11.676956 10.60291,19.157176 3.82818,11.24317 3.81121,25.44418 -0.044,36.82783 -2.07525,6.12777 -9.78971,20.5 -11.00362,20.5 -0.10204,0 -2.06639,-1.3832 -4.36522,-3.07378 z M 81.778822,114.41391 c -0.987352,-2.167 -1.713119,-2.52365 -4.478561,-2.2008 C 75.485117,112.42502 74,112.28006 74,111.89098 c 0,-0.38909 2.038348,-2.80473 4.529662,-5.36811 5.687016,-5.85151 13.385461,-9.421936 22.389748,-10.384041 4.19603,-0.448345 7.72119,-1.408591 8.81929,-2.402352 1.0061,-0.910509 4.51398,-2.848867 7.79529,-4.307463 11.5167,-5.119364 33.48865,-2.808232 33.4507,3.51853 -0.03,5.002939 -4.29101,7.838526 -9.20479,6.125573 -1.69309,-0.590214 -6.0487,-1.063234 -9.67912,-1.051155 -7.46196,0.02483 -12.78325,2.004318 -18.21979,6.777668 -3.02474,2.65576 -4.03125,2.9899 -7.5746,2.51464 -5.45614,-0.73182 -12.97717,1.85611 -18.074646,6.21936 -2.22732,1.9065 -4.325286,3.46637 -4.662147,3.46637 -0.336861,0 -1.14271,-1.16374 -1.790775,-2.58609 z" - id="path3738" - inkscape:connector-curvature="0" /> - <path - style="fill:#0076c2" - d="m 81.778822,114.41391 c -0.987352,-2.167 -1.713119,-2.52365 -4.478561,-2.2008 C 75.485117,112.42502 74,112.28006 74,111.89098 c 0,-0.38909 2.038348,-2.80473 4.529662,-5.36811 5.687016,-5.85151 13.385461,-9.421936 22.389748,-10.384041 4.19603,-0.448345 7.72119,-1.408591 8.81929,-2.402352 1.0061,-0.910509 4.51398,-2.848867 7.79529,-4.307463 11.5167,-5.119364 33.48865,-2.808232 33.4507,3.51853 -0.03,5.002939 -4.29101,7.838526 -9.20479,6.125573 -1.69309,-0.590214 -6.0487,-1.063234 -9.67912,-1.051155 -7.46196,0.02483 -12.78325,2.004318 -18.21979,6.777668 -3.02474,2.65576 -4.03125,2.9899 -7.5746,2.51464 -5.45614,-0.73182 -12.97717,1.85611 -18.074646,6.21936 -2.22732,1.9065 -4.325286,3.46637 -4.662147,3.46637 -0.336861,0 -1.14271,-1.16374 -1.790775,-2.58609 z" - id="path3736" - inkscape:connector-curvature="0" /> - <path - style="fill:#0275bc" - d="m 84,115.94098 c 0,-0.58246 -0.519529,-0.73793 -1.154508,-0.34549 -0.691266,0.42723 -0.883989,0.27582 -0.48031,-0.37735 0.370809,-0.59998 1.542397,-1.02548 2.603528,-0.94554 1.457446,0.10978 1.667267,0.4611 0.857865,1.43636 C 84.525185,117.27704 84,117.34375 84,115.94098 Z m 0.09671,-3.86005 c -1.011759,-0.64056 -0.689769,-0.84554 1.15404,-0.73469 1.406534,0.0846 2.348958,0.49126 2.094276,0.90376 -0.60193,0.97493 -1.516575,0.92732 -3.248316,-0.16907 z m 6.3078,-0.92642 c 0.398903,-0.64544 0.136326,-1.16792 -0.595491,-1.18492 -0.765174,-0.0178 -0.541923,-0.47628 0.537358,-1.10362 1.338377,-0.77794 2.163776,-0.75328 3,0.0896 0.874885,0.8819 0.691151,0.98669 -0.76042,0.43369 -1.280472,-0.48782 -1.688838,-0.3648 -1.233688,0.37165 0.374196,0.60547 0.153488,1.42647 -0.490464,1.82445 -0.731227,0.45192 -0.902922,0.29014 -0.457295,-0.4309 z M 78.5,109.91171 l -3,-0.7763 3.217276,0.16818 c 2.186877,0.11431 3.688589,-0.46785 4.688882,-1.81771 1.457369,-1.96667 1.489127,-1.96706 3.282724,-0.0406 1.583464,1.70072 1.591856,1.78019 0.06676,0.63224 -1.483392,-1.11656 -2.007002,-1.0195 -3.5,0.64877 -1.381497,1.54369 -2.394984,1.79632 -4.755647,1.18547 z M 78.5,107 c -0.60158,-0.97338 0.120084,-1.39478 1.85526,-1.08333 1.302991,0.23387 3.690445,-2.0337 3.117418,-2.96088 -0.277916,-0.44968 0.02157,-1.14322 0.665519,-1.5412 0.731227,-0.45192 0.902922,-0.29014 0.457295,0.4309 -1.008441,1.63169 1.517118,1.38391 3.845638,-0.37729 1.067621,-0.80751 2.867621,-1.42334 4,-1.36852 2.027174,0.0981 2.02808,0.11053 0.05887,0.80463 -4.600356,1.62151 -9.243399,4.08158 -10.452051,5.53791 C 80.556518,108.23929 79.380215,108.42422 78.5,107 Z m 12.25,-0.66228 c 0.6875,-0.27741 1.8125,-0.27741 2.5,0 0.6875,0.27741 0.125,0.50439 -1.25,0.50439 -1.375,0 -1.9375,-0.22698 -1.25,-0.50439 z m -1.953895,-1.90746 c 1.232615,-0.86336 3.020243,-1.36556 3.972506,-1.116 1.314258,0.34442 1.203531,0.48168 -0.459594,0.56974 -1.205041,0.0638 -2.469098,0.566 -2.809017,1.116 -0.339919,0.55 -1.141604,1 -1.781523,1 -0.639919,0 -0.154987,-0.70638 1.077628,-1.56974 z m 12.467645,-0.14784 c 1.52006,-0.22986 3.77006,-0.22371 5,0.0136 1.22994,0.23736 -0.0138,0.42542 -2.76375,0.41792 -2.75,-0.008 -3.756313,-0.20172 -2.23625,-0.43157 z m 13.52519,-3.66627 c 1.62643,-1.858573 1.61751,-1.921032 -0.18038,-1.262823 -1.58361,0.579759 -1.69145,0.451477 -0.6626,-0.788214 0.96581,-1.163733 1.50975,-1.222146 2.54116,-0.272892 0.80101,0.737212 0.96515,1.63324 0.42127,2.299789 -0.49007,0.6006 -0.69137,1.29168 -0.44733,1.53571 0.24403,0.24404 -0.41735,0.44371 -1.46974,0.44371 -1.81559,0 -1.82594,-0.1 -0.20238,-1.95528 z m -13.35766,0.48689 c 1.8068,-0.70764 6.56872,-0.33535 6.56872,0.51354 0,0.21088 -1.9125,0.35179 -4.25,0.31313 -3.00669,-0.0497 -3.68502,-0.29156 -2.31872,-0.82667 z M 120,98.984687 c -1.33333,-0.875277 -1.33333,-1.094097 0,-1.969374 0.825,-0.541578 2.175,-0.939378 3,-0.883999 0.99463,0.06677 0.88566,0.259531 -0.32343,0.572152 -1.07213,0.27721 -1.60009,1.05346 -1.28138,1.883999 0.63873,1.664515 0.5666,1.685055 -1.39519,0.397222 z m 23.8125,0.332199 c 0.72187,-0.288871 1.58437,-0.253344 1.91667,0.07895 0.33229,0.332292 -0.25834,0.568641 -1.3125,0.52522 -1.16495,-0.04798 -1.4019,-0.284941 -0.60417,-0.604167 z M 100,98.073324 c 0,-0.509672 -0.7875,-1.132471 -1.75,-1.383998 -1.31691,-0.344145 -1.19317,-0.486031 0.5,-0.573325 1.2375,-0.0638 2.25,0.305488 2.25,0.820641 0,0.515152 1.4625,1.118136 3.25,1.339962 3.19982,0.397095 3.1921,0.405793 -0.5,0.563359 -2.0625,0.08802 -3.75,-0.256967 -3.75,-0.766639 z m 29.75,-0.79672 c 1.7875,-0.221826 4.7125,-0.221826 6.5,0 1.7875,0.221827 0.325,0.403322 -3.25,0.403322 -3.575,0 -5.0375,-0.181495 -3.25,-0.403322 z M 142.5,97 c -1.75921,-0.755957 -1.6618,-0.867892 0.80902,-0.929715 1.63221,-0.04084 2.5501,0.348653 2.19098,0.929715 -0.33992,0.55 -0.70398,0.968372 -0.80902,0.929715 C 144.58594,97.891058 143.6,97.472686 142.5,97 Z m -32.85536,-1.199796 c 0.45361,-0.715112 0.83163,-1.600204 0.84005,-1.966871 0.008,-0.366666 0.42496,-1.041666 0.92564,-1.5 0.52889,-0.484163 0.60891,-0.309578 0.19098,0.416667 -0.93393,1.62288 0.27843,1.533702 3.39869,-0.25 2.99559,-1.712435 4,-1.837986 4,-0.5 0,0.55 -0.56916,1 -1.26481,1 -0.69564,0 -2.98616,0.922592 -5.09004,2.050204 -2.18676,1.172033 -3.47198,1.493283 -3.00051,0.75 z M 147,95.559017 C 147,94.701558 147.45,94 148,94 c 0.55,0 1,0.423442 1,0.940983 0,0.517541 -0.45,1.219098 -1,1.559017 -0.55,0.339919 -1,-0.08352 -1,-0.940983 z M 116.5,95 c 0.33992,-0.55 1.04148,-1 1.55902,-1 0.51754,0 0.94098,0.45 0.94098,1 0,0.55 -0.70156,1 -1.55902,1 -0.85746,0 -1.2809,-0.45 -0.94098,-1 z m 8.5,0.185596 c 0,-1.012848 13.57404,-0.944893 14.59198,0.07305 C 139.99972,95.666391 136.88333,96 132.66667,96 128.45,96 125,95.633518 125,95.185596 Z M 150.15789,94 c 0,-1.375 0.22698,-1.9375 0.50439,-1.25 0.27741,0.6875 0.27741,1.8125 0,2.5 -0.27741,0.6875 -0.50439,0.125 -0.50439,-1.25 z M 120.75,93.337719 c 0.6875,-0.277412 1.8125,-0.277412 2.5,0 0.6875,0.277413 0.125,0.504386 -1.25,0.504386 -1.375,0 -1.9375,-0.226973 -1.25,-0.504386 z m 21.51903,-0.03071 c 0.97297,-0.253543 2.32297,-0.236869 3,0.03705 0.67703,0.273923 -0.11903,0.481368 -1.76903,0.460988 -1.65,-0.02038 -2.20394,-0.244498 -1.23097,-0.498042 z M 126,91.822487 c 0,-1.159476 11.18403,-0.998163 13,0.187505 1.04165,0.680102 -0.71538,0.92675 -5.75,0.807174 C 129.2625,92.722461 126,92.274855 126,91.822487 Z M 147,92 c 0,-0.55 0.45,-1 1,-1 0.55,0 1,0.45 1,1 0,0.55 -0.45,1 -1,1 -0.55,0 -1,-0.45 -1,-1 z m -22.5,-2.531662 c 5.25889,-1.588265 12.55323,-1.437163 18.5,0.383229 3.35111,1.025823 3.2873,1.051779 -1.5,0.610174 -8.02324,-0.740105 -13.71413,-0.773698 -18,-0.106252 -3.61325,0.562697 -3.51656,0.476921 1,-0.887151 z m -1.6875,-2.151452 c 0.72187,-0.288871 1.58437,-0.253344 1.91667,0.07895 0.33229,0.332292 -0.25834,0.568641 -1.3125,0.52522 -1.16495,-0.04798 -1.4019,-0.284941 -0.60417,-0.604167 z m 8.45653,-1.009877 c 0.97297,-0.253543 2.32297,-0.236869 3,0.03705 0.67703,0.273923 -0.11903,0.481368 -1.76903,0.460988 -1.65,-0.02038 -2.20394,-0.244498 -1.23097,-0.498042 z" - id="path3734" - inkscape:connector-curvature="0" /> - </g> - </g> - <g - inkscape:groupmode="layer" - id="layer2" - inkscape:label="BADGE" - style="display:none" - sodipodi:insensitive="true"> - <g - style="display:inline" - transform="translate(-340.00001,-581)" - id="g4394" - clip-path="none"> - <g - id="g855"> - <g - inkscape:groupmode="maskhelper" - id="g870" - clip-path="url(#clipPath873)" - style="opacity:0.6;filter:url(#filter891)"> - <path - transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)" - d="m 264,552.36218 a 12,12 0 0 1 -12,12 12,12 0 0 1 -12,-12 12,12 0 0 1 12,-12 12,12 0 0 1 12,12 z" - sodipodi:ry="12" - sodipodi:rx="12" - sodipodi:cy="552.36218" - sodipodi:cx="252" - id="path844" - style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" /> - </g> - <g - id="g862"> - <path - sodipodi:type="arc" - style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path4398" - sodipodi:cx="252" - sodipodi:cy="552.36218" - sodipodi:rx="12" - sodipodi:ry="12" - d="m 264,552.36218 a 12,12 0 0 1 -12,12 12,12 0 0 1 -12,-12 12,12 0 0 1 12,-12 12,12 0 0 1 12,12 z" - transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" /> - <path - transform="matrix(1.25,0,0,1.25,33,-100.45273)" - d="m 264,552.36218 a 12,12 0 0 1 -12,12 12,12 0 0 1 -12,-12 12,12 0 0 1 12,-12 12,12 0 0 1 12,12 z" - sodipodi:ry="12" - sodipodi:rx="12" - sodipodi:cy="552.36218" - sodipodi:cx="252" - id="path4400" - style="color:#000000;fill:#dd4814;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - sodipodi:type="arc" /> - <path - sodipodi:type="star" - style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - id="path4459" - sodipodi:sides="5" - sodipodi:cx="666.19574" - sodipodi:cy="589.50385" - sodipodi:r1="7.2431178" - sodipodi:r2="4.3458705" - sodipodi:arg1="1.0471976" - sodipodi:arg2="1.6755161" - inkscape:flatsided="false" - inkscape:rounded="0.1" - inkscape:randomized="0" - d="m 669.8173,595.77657 c -0.39132,0.22593 -3.62645,-1.90343 -4.07583,-1.95066 -0.44938,-0.0472 -4.05653,1.36297 -4.39232,1.06062 -0.3358,-0.30235 0.68963,-4.03715 0.59569,-4.47913 -0.0939,-0.44198 -2.5498,-3.43681 -2.36602,-3.8496 0.18379,-0.41279 4.05267,-0.59166 4.44398,-0.81759 0.39132,-0.22593 2.48067,-3.48704 2.93005,-3.4398 0.44938,0.0472 1.81505,3.67147 2.15084,3.97382 0.3358,0.30236 4.08294,1.2817 4.17689,1.72369 0.0939,0.44198 -2.9309,2.86076 -3.11469,3.27355 -0.18379,0.41279 0.0427,4.27917 -0.34859,4.5051 z" - transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" /> - </g> - </g> - </g> - </g> -</svg> diff --git a/charms/trusty/neutron-contrail/metadata.yaml b/charms/trusty/neutron-contrail/metadata.yaml deleted file mode 100644 index fff4a7d..0000000 --- a/charms/trusty/neutron-contrail/metadata.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: neutron-contrail -summary: OpenStack Neutron OpenContrail Agent -maintainer: Robert Ayres <robert.ayres@ubuntu.com> -description: | - Neutron is a virtual network service for Openstack, and a part of - Netstack. Just like OpenStack Nova provides an API to dynamically - request and configure virtual servers, Neutron provides an API to - dynamically request and configure virtual networks. These networks - connect "interfaces" from other OpenStack services (e.g., virtual NICs - from Nova VMs). The Neutron API supports extensions to provide - advanced network capabilities (e.g., QoS, ACLs, network monitoring, - etc.) - . - This charm provides the OpenStack Neutron OpenContrail agent, managing - L2 connectivity on nova-compute services. -categories: - - openstack -subordinate: true -peers: - cluster: - interface: contrail-cluster -provides: - neutron-plugin: - interface: neutron-plugin - scope: container -requires: - container: - interface: juju-info - scope: container - contrail-api: - interface: contrail-api - contrail-discovery: - interface: contrail-discovery - control-node: - interface: contrail-control - identity-admin: - interface: keystone-admin - neutron-metadata: - interface: neutron-metadata diff --git a/charms/trusty/neutron-contrail/scripts/create-vrouter.sh b/charms/trusty/neutron-contrail/scripts/create-vrouter.sh deleted file mode 100755 index 686a7b7..0000000 --- a/charms/trusty/neutron-contrail/scripts/create-vrouter.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/sh -e -# -# Script used to configure vRouter interface - -configVRouter() -{ - cat juju-header - echo "auto $1" - if [ -e "$2" ]; then - cat "$2" - else - echo "iface $1 inet manual" - fi - printf "\n%s\n" "auto vhost0" - if [ -e "$3" ]; then - cat "$3" - else - echo "iface vhost0 inet dhcp" - fi - cat <<-EOF - pre-up ip link add address \$(cat /sys/class/net/$1/address) type vhost - pre-up vif --add $1 --mac \$(cat /sys/class/net/$1/address) --vrf 0 --vhost-phys --type physical - pre-up vif --add vhost0 --mac \$(cat /sys/class/net/$1/address) --vrf 0 --type vhost --xconnect $1 - post-down vif --list | awk '/^vif.*OS: vhost0/ {split(\$1, arr, "\\/"); print arr[2];}' | xargs vif --delete - post-down vif --list | awk '/^vif.*OS: $1/ {split(\$1, arr, "\\/"); print arr[2];}' | xargs vif --delete - post-down ip link delete vhost0 - EOF -} - -ifacedown() -{ - for iface; do - # ifdown interface - # if bridge, save list of interfaces - # if bond, save list of slaves - if [ ! -e /sys/class/net/$iface ]; then - continue - fi - [ -d /sys/class/net/$iface/bridge ] && saveIfaces $iface - [ -d /sys/class/net/$iface/bonding ] && saveSlaves $iface - ifdown --force $iface - done -} - -ifaceup() -{ - for iface; do - # ifup interface - # if bridge, restore list of interfaces - # restore list of slaves if exists (bond) - restoreSlaves $iface - ifup $iface - [ -d /sys/class/net/$iface/bridge ] && restoreIfaces $iface - done - return 0 -} - -restoreIfaces() -{ - if [ -e $TMP/$1.ifaces ]; then - cat $TMP/$1.ifaces | xargs -n 1 brctl addif $1 || true - fi -} - -restoreSlaves() -{ - if [ -e $TMP/$1.slaves ]; then - cat $TMP/$1.slaves | xargs ifup - fi -} - -saveIfaces() -{ - if [ -z "$(find /sys/class/net/$1/brif -maxdepth 0 -empty)" ]; then - find /sys/class/net/$1/brif | tail -n +2 | xargs -n 1 basename \ - > $TMP/$1.ifaces - fi -} - -saveSlaves() -{ - if [ -s /sys/class/net/$1/bonding/slaves ]; then - cat /sys/class/net/$1/bonding/slaves | tr " " "\n" \ - > $TMP/$1.slaves - fi -} - -TMP=$(mktemp -d /tmp/create-vrouter.XXX) - -if [ $# -ne 0 ]; then - interface=$1 -else - # use default gateway interface - interface=$(route -n | awk '$1 == "0.0.0.0" { print $8 }') -fi - -ifacedown $interface vhost0; sleep 5 -# add interfaces.d source line to /etc/network/interfaces -if ! grep -q '^[[:blank:]]*source /etc/network/interfaces\.d/\*\.cfg[[:blank:]]*$' \ - /etc/network/interfaces; then - printf "\n%s\n" "source /etc/network/interfaces.d/*.cfg" \ - >> /etc/network/interfaces - # it's possible for conflicting network config to exist in - # /etc/network/interfaces.d when we start sourcing it - # so disable any config as a precautionary measure - for cfg in /etc/network/interfaces.d/*.cfg; do - [ -e "$cfg" ] || continue - mv "$cfg" "$cfg.save" - done -fi -mkdir -p /etc/network/interfaces.d -for cfg in /etc/network/interfaces /etc/network/interfaces.d/*.cfg \ - /etc/network/*.config; do - # for each network interfaces config, extract the config for - # the chosen interface whilst commenting it out in the subsequent - # replacement config - [ -e "$cfg" ] || continue - awk -v interface=$interface -v interface_cfg=$TMP/interface.cfg \ - -v vrouter_cfg=$TMP/vrouter.cfg -f vrouter-interfaces.awk "$cfg" \ - > $TMP/interfaces.cfg - if ! diff $TMP/interfaces.cfg "$cfg" > /dev/null; then - # create backup - mv "$cfg" "$cfg.save" - # substitute replacement config for original config - cat juju-header $TMP/interfaces.cfg > "$cfg" - fi -done -# use extracted interface config to create new vrouter config -configVRouter $interface $TMP/interface.cfg $TMP/vrouter.cfg \ - > /etc/network/interfaces.d/vrouter.cfg -ifaceup $interface vhost0 - -rm -rf $TMP diff --git a/charms/trusty/neutron-contrail/scripts/interfaces b/charms/trusty/neutron-contrail/scripts/interfaces deleted file mode 100644 index 0356643..0000000 --- a/charms/trusty/neutron-contrail/scripts/interfaces +++ /dev/null @@ -1,7 +0,0 @@ -# This file describes the network interfaces available on your system -# and how to activate them. For more information see interfaces(5). - -# The loopback network interface -auto lo -iface lo inet loopback - diff --git a/charms/trusty/neutron-contrail/scripts/juju-header b/charms/trusty/neutron-contrail/scripts/juju-header deleted file mode 100644 index fccac13..0000000 --- a/charms/trusty/neutron-contrail/scripts/juju-header +++ /dev/null @@ -1,5 +0,0 @@ -############################################################################### -# [ WARNING ] -# Configuration file maintained by Juju. Local changes may be overwritten. -############################################################################### - diff --git a/charms/trusty/neutron-contrail/scripts/remove-juju-bridge.sh b/charms/trusty/neutron-contrail/scripts/remove-juju-bridge.sh deleted file mode 100755 index d9a9ec1..0000000 --- a/charms/trusty/neutron-contrail/scripts/remove-juju-bridge.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -e -# -# Script used to remove Juju LXC bridge on MAAS systems - -if [ ! -e /sys/class/net/juju-br0 ]; then - exit 0 -fi - -interface=$(find /sys/class/net/juju-br0/brif | sed -n -e '2p' | xargs basename) - -ifdown --force $interface juju-br0; sleep 5 -cp interfaces /etc/network -cat <<-EOF >> /etc/network/interfaces - auto $interface - iface $interface inet dhcp - EOF -ifup $interface diff --git a/charms/trusty/neutron-contrail/scripts/vhost-phys.sh b/charms/trusty/neutron-contrail/scripts/vhost-phys.sh deleted file mode 100755 index 6565d1c..0000000 --- a/charms/trusty/neutron-contrail/scripts/vhost-phys.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -e -# -# Script used to determine physical interface of vhost0 - -mac=$(cat /sys/class/net/vhost0/address) -vif --list | awk -v mac=$mac 'BEGIN { RS="\n\n" }; $3 != "vhost0" && $0 ~ "HWaddr:" mac { print $3; exit 0 }' diff --git a/charms/trusty/neutron-contrail/scripts/vrouter-interfaces.awk b/charms/trusty/neutron-contrail/scripts/vrouter-interfaces.awk deleted file mode 100644 index d8e5851..0000000 --- a/charms/trusty/neutron-contrail/scripts/vrouter-interfaces.awk +++ /dev/null @@ -1,38 +0,0 @@ -function strip(s) -{ - sub(/^[[:blank:]]+/, "", s) - sub(/[[:blank:]]+$/, "", s) - return s -} - -/^[[:blank:]]*(iface|mapping|auto|allow-[^ ]+|source) / { - s_iface = 0; iface = 0 -} - -$0 ~ "^[[:blank:]]*auto (" interface "|vhost0)[[:blank:]]*$" { print "#" $0; next } - -$0 ~ "^[[:blank:]]*iface (" interface "|vhost0) " { - s_iface = 1 - if ($2 == interface) { - iface = 1 - print "iface", interface, $3, "manual" > interface_cfg - print "iface vhost0", $3, $4 > vrouter_cfg - } - print "#" $0 - next -} - -s_iface == 1 { - if (iface == 1) { - if (match($1, "^address|netmask|broadcast|metric|gateway$")) { - cfg = vrouter_cfg - } else { - cfg = interface_cfg - } - print " " strip($0) > cfg - } - print "#" $0 - next -} - -{ print $0 } diff --git a/charms/trusty/neutron-contrail/templates/contrail-barbican-auth.conf b/charms/trusty/neutron-contrail/templates/contrail-barbican-auth.conf deleted file mode 100644 index 84ab4a0..0000000 --- a/charms/trusty/neutron-contrail/templates/contrail-barbican-auth.conf +++ /dev/null @@ -1,13 +0,0 @@ -############################################################################### -# [ WARNING ] -# Configuration file maintained by Juju. Local changes may be overwritten. -############################################################################### - -[DEFAULT] -auth_url = http://{{ auth_host }}:{{ auth_port }}/v2.0 -auth_version = 2 -admin_user = {{ admin_user }} -admin_password = {{ admin_password }} -admin_tenant_name = {{ admin_tenant_name }} -region = {{ auth_region }} - diff --git a/charms/trusty/neutron-contrail/templates/contrail-vrouter-agent.conf b/charms/trusty/neutron-contrail/templates/contrail-vrouter-agent.conf deleted file mode 100644 index 3543c2d..0000000 --- a/charms/trusty/neutron-contrail/templates/contrail-vrouter-agent.conf +++ /dev/null @@ -1,44 +0,0 @@ -############################################################################### -# [ WARNING ] -# Configuration file maintained by Juju. Local changes may be overwritten. -############################################################################### - -{%- if control_nodes %} - -[CONTROL-NODE] -server = {{ control_nodes|join(" ") }} - -{%- endif %} -{%- if discovery_server %} - -[DISCOVERY] -server = {{ discovery_server }} - -{%- endif %} - -[METADATA] -metadata_proxy_secret = {{ metadata_secret }} - -[NETWORKS] -control_network_ip = {{ control_network_ip }} - -[VIRTUAL-HOST-INTERFACE] -name = vhost0 -ip = {{ vhost_ip }} -gateway = {{ vhost_gateway }} -physical_interface = {{ vhost_physical }} - -{%- for vgw in vgws %} - -[GATEWAY-{{ loop.index0 }}] -routing_instance = {{ vgw["domain"] }}:{{ vgw["project"] }}:{{ vgw["network"] }}:{{ vgw["network"] }} -interface = {{ vgw["interface"] }} -ip_blocks = {{ vgw["subnets"]|join(" ") }} -routes = {{ vgw["routes"]|join(" ") }} - -{%- endfor %} - -[SERVICE-INSTANCE] -netns_command = /usr/bin/opencontrail-vrouter-netns -docker_command = /usr/bin/opencontrail-vrouter-docker - diff --git a/charms/trusty/neutron-contrail/templates/contrail-vrouter-nodemgr.conf b/charms/trusty/neutron-contrail/templates/contrail-vrouter-nodemgr.conf deleted file mode 100644 index ffea798..0000000 --- a/charms/trusty/neutron-contrail/templates/contrail-vrouter-nodemgr.conf +++ /dev/null @@ -1,9 +0,0 @@ -############################################################################### -# [ WARNING ] -# Configuration file maintained by Juju. Local changes may be overwritten. -############################################################################### - -[DISCOVERY] -server = {{ discovery_server }} -port = {{ discovery_port }} - diff --git a/charms/trusty/neutron-contrail/templates/vnc_api_lib.ini b/charms/trusty/neutron-contrail/templates/vnc_api_lib.ini deleted file mode 100644 index fd68487..0000000 --- a/charms/trusty/neutron-contrail/templates/vnc_api_lib.ini +++ /dev/null @@ -1,16 +0,0 @@ -############################################################################### -# [ WARNING ] -# Configuration file maintained by Juju. Local changes may be overwritten. -############################################################################### - -[global] -WEB_SERVER = {{ api_server }} -WEB_PORT = {{ api_port }} - -[auth] -AUTHN_TYPE = keystone -AUTHN_PROTOCOL = http -AUTHN_SERVER = {{ auth_host }} -AUTHN_PORT = {{ auth_port }} -AUTHN_URL = /v2.0/tokens - diff --git a/charms/trusty/neutron-contrail/templates/vrouter-vgw.cfg b/charms/trusty/neutron-contrail/templates/vrouter-vgw.cfg deleted file mode 100644 index f5afd46..0000000 --- a/charms/trusty/neutron-contrail/templates/vrouter-vgw.cfg +++ /dev/null @@ -1,21 +0,0 @@ -############################################################################### -# [ WARNING ] -# Configuration file maintained by Juju. Local changes may be overwritten. -############################################################################### - -{%- for vgw in vgws %} -{% set interface = vgw["interface"] %} -auto {{ interface }} -iface {{ interface }} inet manual - pre-up vif --create {{ interface }} --mac 00:00:5e:00:01:00 -{%- for subnet in vgw["subnets"] %} - post-up route add -net {{ subnet }} dev {{ interface }} -{%- endfor %} -{%- for subnet in vgw["subnets"] %} - pre-down route del -net {{ subnet }} dev {{ interface }} -{%- endfor %} - post-down id=$(vif --list | awk '/vif[0-9\/]+[\t ]+ OS: {{ interface }}/ { split($1, arr, "/"); print arr[2]; }'); \ - { [ -n "$id" ] && vif --delete $id; } || true - post-down ip link delete {{ interface }} -{%- endfor %} - |