initial commit
This commit is contained in:
commit
a55c2425f5
0
src/README.ex
Normal file
0
src/README.ex
Normal file
43
src/config.yaml
Normal file
43
src/config.yaml
Normal file
@ -0,0 +1,43 @@
|
||||
options:
|
||||
arista-version:
|
||||
default: '2017.2.2'
|
||||
type: string
|
||||
description: Arista Driver version
|
||||
pip-proxy:
|
||||
type: string
|
||||
default: None
|
||||
description: Proxy address to install python modules behind a proxy.
|
||||
eapi-host:
|
||||
default:
|
||||
type: string
|
||||
description: |
|
||||
Set a comma separated list of IP addresses for each CVX instance.
|
||||
If CVX has been deployed in a highly available (HA) cluster,
|
||||
specify each instance IP separated by a comma.
|
||||
eapi-username:
|
||||
default:
|
||||
type: string
|
||||
description: EOS command API username. This is required field.
|
||||
eapi-password:
|
||||
default:
|
||||
type: string
|
||||
description: EOS command API password. This is required field.
|
||||
api-type:
|
||||
default: EAPI
|
||||
type: string
|
||||
description: |
|
||||
Tells the plugin to use a sepcific API interfaces to communicate
|
||||
with CVX. Valid options are:
|
||||
.
|
||||
EAPI - Use EOS extensible API.
|
||||
JSON - Use EOS JSON/REST API.
|
||||
.
|
||||
region-name:
|
||||
default: RegionOne
|
||||
type: string
|
||||
description: |
|
||||
Name of the OpenStack region.
|
||||
service-plugins:
|
||||
default: router,firewall,metering,neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2
|
||||
type: string
|
||||
description: Override of Neutron-API service plugins setting.
|
279
src/icon.svg
Normal file
279
src/icon.svg
Normal file
@ -0,0 +1,279 @@
|
||||
<?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:xlink="http://www.w3.org/1999/xlink"
|
||||
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.48+devel r12274"
|
||||
sodipodi:docname="Juju_charm_icon_template.svg">
|
||||
<defs
|
||||
id="defs6519">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Background"
|
||||
id="linearGradient6461"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="0"
|
||||
y1="970.29498"
|
||||
x2="144"
|
||||
y2="970.29498"
|
||||
gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />
|
||||
<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="18.514671"
|
||||
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="1029"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
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:url(#linearGradient6461);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
|
||||
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 1 1 -24,0 A 12,12 0 1 1 264,552.36218 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 1 1 -24,0 A 12,12 0 1 1 264,552.36218 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 1 1 -24,0 A 12,12 0 1 1 264,552.36218 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 C 669.9821,591.68426 670.20862,595.55064 669.8173,595.77657 Z"
|
||||
transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.6 KiB |
3
src/layer.yaml
Normal file
3
src/layer.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
includes:
|
||||
- 'layer:openstack'
|
||||
- 'interface:neutron-plugin-api-subordinate'
|
77
src/lib/charm/openstack/neutron_arista.py
Normal file
77
src/lib/charm/openstack/neutron_arista.py
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
import subprocess
|
||||
|
||||
import charmhelpers.core.hookenv as hookenv
|
||||
from charmhelpers.core.hookenv import (
|
||||
config,
|
||||
log,
|
||||
status_set,
|
||||
is_leader,
|
||||
leader_get,
|
||||
leader_set,
|
||||
)
|
||||
import charms_openstack.charm
|
||||
|
||||
from charmhelpers.contrib.python.packages import pip_install
|
||||
|
||||
from charmhelpers.contrib.openstack import context
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
CompareOpenStackReleases,
|
||||
os_release,
|
||||
)
|
||||
|
||||
ML2_CONFIG_ARISTA = '/etc/neutron/plugins/ml2/ml2_conf_arista.ini'
|
||||
TEMPLATES = 'templates/'
|
||||
|
||||
|
||||
class NeutronAristaCharm(charms_openstack.charm.OpenStackCharm):
|
||||
|
||||
# Internal name of charm
|
||||
service_name = name = 'neutron-arista'
|
||||
|
||||
# First release supported
|
||||
release = 'queens'
|
||||
|
||||
# List of packages to install for this charm
|
||||
packages = ['']
|
||||
|
||||
def install(self):
|
||||
package_version = config('arista-version')
|
||||
package_name = 'networking-arista==%s' % package_version
|
||||
proxy = config('pip-proxy')
|
||||
if proxy:
|
||||
pip_install(package_name, fatal=True, proxy=proxy)
|
||||
else:
|
||||
pip_install(package_name, fatal=True)
|
||||
status_set('active', 'Unit is ready')
|
||||
|
||||
|
||||
class AristaMl2Context(context.OSContextGenerator):
|
||||
|
||||
def __call__(self):
|
||||
ctxt = {'eapi_host': config('eapi-host'),
|
||||
'eapi_username': config('eapi-username'),
|
||||
'eapi_password': config('eapi-password'),
|
||||
'region_name': config('region-name'),
|
||||
'api_type': config('api-type'),
|
||||
'arista_version': config('arista-version')}
|
||||
return ctxt
|
||||
|
||||
|
||||
def register_configs(release=None):
|
||||
resources = OrderedDict([
|
||||
(ML2_CONFIG, {
|
||||
'services': ['neutron-server'],
|
||||
'contexts': [AristaMl2Context(), ]
|
||||
}),
|
||||
(ML2_CONFIG_ARISTA, {
|
||||
'services': ['neutron-server'],
|
||||
'contexts': [AristaMl2Context(), ]
|
||||
}),
|
||||
])
|
||||
release = os_release('neutron-common')
|
||||
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
|
||||
openstack_release=release)
|
||||
for cfg, rscs in resources.iteritems():
|
||||
configs.register(cfg, rscs['contexts'])
|
||||
return configs
|
19
src/metadata.yaml
Normal file
19
src/metadata.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
name: neutron-arista
|
||||
summary: Arista ML2 plugin support for Neutron-API
|
||||
maintainer: Michael Skalka <Michael.Skalka@canonical.com>
|
||||
description: |
|
||||
|
||||
tags:
|
||||
- misc
|
||||
- networking
|
||||
subordinate: true
|
||||
series:
|
||||
- xenial
|
||||
provides:
|
||||
neutron-arista:
|
||||
interface: neutron-plugin-api-subordinate
|
||||
scope: container
|
||||
requires:
|
||||
container:
|
||||
interface: juju-info
|
||||
scope: container
|
56
src/reactive/neutron_arista_handlers.py
Normal file
56
src/reactive/neutron_arista_handlers.py
Normal file
@ -0,0 +1,56 @@
|
||||
# Copyright 2016 Canonical Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import charms.reactive as reactive
|
||||
|
||||
from charms_openstack.charm import (
|
||||
provide_charm_instance,
|
||||
use_defaults,
|
||||
)
|
||||
import charm.openstack.keystone_ico as ico # noqa
|
||||
|
||||
CONFIGS = register_configs()
|
||||
|
||||
use_defaults('update-status')
|
||||
|
||||
|
||||
@reactive.when_not('neutron-arista.installed')
|
||||
def install_neutron_arista():
|
||||
with provide_charm_instance() as charm_class:
|
||||
charm_class.install()
|
||||
reactive.set_state('neutron-arista.installed')
|
||||
|
||||
|
||||
@reactive.when('neutron-plugin-api-subordinate.connected')
|
||||
@reactive.when('neutron-arista.installed')
|
||||
def configure_principle(api_principle):
|
||||
with provide_charm_instance() as charm_class:
|
||||
charm_class.render_ml2_conf()
|
||||
injet_config = {
|
||||
'neutron-api': {
|
||||
'/etc/neutron/neutron.conf': {
|
||||
'sections': {
|
||||
'DEFAULT': [
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
api_principle.configure_plugin(
|
||||
neutron_plugin='arista',
|
||||
core_plugin='neutron.plugins.ml2.plugin.Ml2Plugin',
|
||||
neutron_plugin_config='/etc/neutron/plugins/ml2/ml2_conf_arista.ini',
|
||||
service_plugins=config('service-plugins'),
|
||||
subordinate_configuration=inject_config)
|
||||
api_principle.request_restart(service_type='neutron-server')
|
11
src/templates/ml2_conf_arista.ini
Normal file
11
src/templates/ml2_conf_arista.ini
Normal file
@ -0,0 +1,11 @@
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
|
||||
[ml2_arista]
|
||||
eapi_host = {{ eapi_host }}
|
||||
eapi_username = {{ eapi_username }}
|
||||
eapi_password = {{ eapi_password }}
|
||||
region_name = {{ region_name }}
|
||||
api_type = {{ api_type }}
|
5
src/tests/00-setup
Executable file
5
src/tests/00-setup
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
sudo add-apt-repository ppa:juju/stable -y
|
||||
sudo apt-get update
|
||||
sudo apt-get install amulet python-requests -y
|
35
src/tests/10-deploy
Executable file
35
src/tests/10-deploy
Executable file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import amulet
|
||||
import requests
|
||||
import unittest
|
||||
|
||||
|
||||
class TestCharm(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.d = amulet.Deployment()
|
||||
|
||||
self.d.add('charm-neutron-arista')
|
||||
self.d.expose('charm-neutron-arista')
|
||||
|
||||
self.d.setup(timeout=900)
|
||||
self.d.sentry.wait()
|
||||
|
||||
self.unit = self.d.sentry['charm-neutron-arista'][0]
|
||||
|
||||
def test_service(self):
|
||||
# test we can access over http
|
||||
page = requests.get('http://{}'.format(self.unit.info['public-address']))
|
||||
self.assertEqual(page.status_code, 200)
|
||||
# Now you can use self.d.sentry[SERVICE][UNIT] to address each of the units and perform
|
||||
# more in-depth steps. Each self.d.sentry[SERVICE][UNIT] has the following methods:
|
||||
# - .info - An array of the information of that unit from Juju
|
||||
# - .file(PATH) - Get the details of a file on that unit
|
||||
# - .file_contents(PATH) - Get plain text output of PATH file from that unit
|
||||
# - .directory(PATH) - Get details of directory
|
||||
# - .directory_contents(PATH) - List files and folders in PATH on that unit
|
||||
# - .relation(relation, service:rel) - Get relation data from return service
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user