aboutsummaryrefslogtreecommitdiffstats
path: root/charms/trusty/neutron-contrail
diff options
context:
space:
mode:
authorStuart Mackie <wsmackie@juniper.net>2017-03-23 06:19:54 -0700
committerStuart Mackie <wsmackie@juniper.net>2017-03-23 06:19:54 -0700
commit88df88a19674ccc0017836941b8ee32eaadf19fb (patch)
treef930c90f75846ec8d8e33cf27325ff8fafc85d5c /charms/trusty/neutron-contrail
parent9f50a40437477432a21b326b15c343ca6b8fe516 (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')
-rw-r--r--charms/trusty/neutron-contrail/.bzrignore1
-rw-r--r--charms/trusty/neutron-contrail/Makefile10
-rw-r--r--charms/trusty/neutron-contrail/README.md131
-rw-r--r--charms/trusty/neutron-contrail/charm-helpers-sync.yaml5
-rw-r--r--charms/trusty/neutron-contrail/config.yaml74
-rw-r--r--charms/trusty/neutron-contrail/copyright17
-rw-r--r--charms/trusty/neutron-contrail/files/60-vrouter-vgw.conf3
-rw-r--r--charms/trusty/neutron-contrail/files/contrail-nodemgr-vrouter.ini6
-rw-r--r--charms/trusty/neutron-contrail/files/contrail-vrouter-nodemgr6
-rw-r--r--charms/trusty/neutron-contrail/files/contrail-vrouter.rules3
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/__init__.py38
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/__init__.py15
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/decorators.py57
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/files.py45
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/fstab.py134
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/hookenv.py898
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/host.py586
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/hugepage.py69
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/kernel.py68
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/__init__.py18
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/base.py353
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/services/helpers.py283
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/strutils.py72
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/sysctl.py56
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/templating.py68
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/core/unitdata.py521
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/__init__.py468
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/archiveurl.py167
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/bzrurl.py78
-rw-r--r--charms/trusty/neutron-contrail/hooks/charmhelpers/fetch/giturl.py73
l---------charms/trusty/neutron-contrail/hooks/config-changed1
l---------charms/trusty/neutron-contrail/hooks/contrail-api-relation-broken1
l---------charms/trusty/neutron-contrail/hooks/contrail-api-relation-changed1
l---------charms/trusty/neutron-contrail/hooks/contrail-api-relation-departed1
l---------charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-broken1
l---------charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-changed1
l---------charms/trusty/neutron-contrail/hooks/contrail-discovery-relation-departed1
l---------charms/trusty/neutron-contrail/hooks/control-node-relation-broken1
l---------charms/trusty/neutron-contrail/hooks/control-node-relation-departed1
l---------charms/trusty/neutron-contrail/hooks/control-node-relation-joined1
l---------charms/trusty/neutron-contrail/hooks/identity-admin-relation-broken1
l---------charms/trusty/neutron-contrail/hooks/identity-admin-relation-changed1
l---------charms/trusty/neutron-contrail/hooks/identity-admin-relation-departed1
l---------charms/trusty/neutron-contrail/hooks/install1
l---------charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-broken1
l---------charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-changed1
l---------charms/trusty/neutron-contrail/hooks/neutron-metadata-relation-departed1
l---------charms/trusty/neutron-contrail/hooks/neutron-plugin-relation-joined1
-rwxr-xr-xcharms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py353
-rw-r--r--charms/trusty/neutron-contrail/hooks/neutron_contrail_utils.py478
l---------charms/trusty/neutron-contrail/hooks/start1
l---------charms/trusty/neutron-contrail/hooks/stop1
l---------charms/trusty/neutron-contrail/hooks/upgrade-charm1
-rw-r--r--charms/trusty/neutron-contrail/icon.svg309
-rw-r--r--charms/trusty/neutron-contrail/metadata.yaml39
-rwxr-xr-xcharms/trusty/neutron-contrail/scripts/create-vrouter.sh133
-rw-r--r--charms/trusty/neutron-contrail/scripts/interfaces7
-rw-r--r--charms/trusty/neutron-contrail/scripts/juju-header5
-rwxr-xr-xcharms/trusty/neutron-contrail/scripts/remove-juju-bridge.sh17
-rwxr-xr-xcharms/trusty/neutron-contrail/scripts/vhost-phys.sh6
-rw-r--r--charms/trusty/neutron-contrail/scripts/vrouter-interfaces.awk38
-rw-r--r--charms/trusty/neutron-contrail/templates/contrail-barbican-auth.conf13
-rw-r--r--charms/trusty/neutron-contrail/templates/contrail-vrouter-agent.conf44
-rw-r--r--charms/trusty/neutron-contrail/templates/contrail-vrouter-nodemgr.conf9
-rw-r--r--charms/trusty/neutron-contrail/templates/vnc_api_lib.ini16
-rw-r--r--charms/trusty/neutron-contrail/templates/vrouter-vgw.cfg21
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 %}
-