Skip to content

Commit

Permalink
Add etcd ansible python plugin (#1336)
Browse files Browse the repository at this point in the history
* Add etcd ansible python plugin
* Add example ansible playbook
* Fix indentation
* Update example playbook

Signed-off-by: miroslav.kovac <[email protected]>
  • Loading branch information
miroslavKovacPantheon authored and ondrej-fabry committed May 14, 2019
1 parent 7290ef8 commit 400e6c3
Show file tree
Hide file tree
Showing 31 changed files with 4,238 additions and 0 deletions.
7 changes: 7 additions & 0 deletions ansible/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
*.pyc
*.so
*.test
*.out
*.retry

.idea/*
55 changes: 55 additions & 0 deletions ansible/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Ansible Action Plugin for VPP ETCD

This is a plugin that contains generated python files out of
.proto files. Ansible plugin uses them to parse and validate
json that we want to submit to etcd database. These files need
to be regenerated in case of changes in .proto files

## Prerequisites

protoc

### Install protoc

Install prerequisits for protoc:

apt-get install autoconf automake libtool curl make g++ unzip

1. download the protobuf-all\[VERSION\].tar.gz.
https://github.com/protocolbuffers/protobuf/releases/tag/v3.6.1
2. Extract the contents and change in the directory
3. Run following commands (This might take several minutes)

./configure
make
make check
sudo make install
sudo ldconfig # refresh shared library cache.

Check your installation:

protoc --version

Expect similar output to this:

libprotoc 3.6.1


### Use protoc to regenerate the python modules

Run [update_proto_classes.sh](../scripts/update_proto_classes.sh) script
to update automatically created python files if needed. This script will
generate python objects used with ansible plugin to pout directory that
will replace [pout](action_plugins/pout).

In case we need to use new .proto files they need to be added to the
[update_proto_classes.sh](../scripts/update_proto_classes.sh) script.
and python validation module needs to be written in a similar way as
[interface.py](action_plugins/plugins/interface.py)

### Usage example

First we need the etcd database to be started and running. Once it is running
we can start the [exmaple](example.yaml) ansible playbook with following command:

ansible-playbook example.yaml
13 changes: 13 additions & 0 deletions ansible/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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.
13 changes: 13 additions & 0 deletions ansible/action_plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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.
13 changes: 13 additions & 0 deletions ansible/action_plugins/plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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.
100 changes: 100 additions & 0 deletions ansible/action_plugins/plugins/bridgeDomain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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 json

import etcd3
from google.protobuf.json_format import MessageToJson, Parse

from action_plugins.pout.models.vpp.l2.bridge_domain_pb2 import BridgeDomain


def plugin_init(name, values, agent_name, ip, port):
if name == 'bridge-domain':
return BridgeDomainValidation(values, agent_name)
elif name == 'add-bridge-domain-interface':
return AddBridgeDomainInterfaceValidation(values, agent_name, ip, port)
elif name == 'remove-bridge-domain-interface':
return RemoveBridgeDomainInterfaceValidation(values, agent_name, ip, port)
else:
return False


class BridgeDomainValidation:

def __init__(self, values, agent_name):
self.values = values
self.agent_name = agent_name

def validate(self):
bridgeDomain = BridgeDomain()
Parse(json.dumps(self.values), bridgeDomain)
return MessageToJson(bridgeDomain, indent=None)

def create_key(self):
return "/vnf-agent/{}/config/vpp/l2/v2/bridge-domain/{}".format(self.agent_name, self.values['name'])


class AddBridgeDomainInterfaceValidation:

def __init__(self, values, agent_name, ip, port):
self.values = values
self.agent_name = agent_name
host = ip
port = port
self.client = etcd3.client(host, port)

def validate(self):
etcd_values = self.client.get(self.create_key())
val = {}
if etcd_values[0] is None:
val['interfaces'] = []
else:
val = json.loads(etcd_values[0])

if val.get('interfaces') is None:
val['interfaces'] = []
val['interfaces'] += self.values['interfaces']

bridgeDomain = BridgeDomain()
Parse(json.dumps(val), bridgeDomain)
return MessageToJson(bridgeDomain, indent=None)

def create_key(self):
return "/vnf-agent/{}/config/vpp/l2/v2/bridge-domain/{}".format(self.agent_name, self.values['name'])


class RemoveBridgeDomainInterfaceValidation:

def __init__(self, values, agent_name, ip, port):
self.values = values
self.agent_name = agent_name
host = ip
port = int(port)
self.client = etcd3.client(host, port)

def validate(self):
etcd_values = self.client.get(self.create_key())
val = json.loads(etcd_values[0])
try:
val['interfaces'].remove(self.values['interfaces'][0])
except:
pass

bridgeDomain = BridgeDomain()
Parse(json.dumps(val), bridgeDomain)
return MessageToJson(bridgeDomain, indent=None)

def create_key(self):
return "/vnf-agent/{}/config/vpp/l2/v2/bridge-domain/{}".format(self.agent_name, self.values['name'])
41 changes: 41 additions & 0 deletions ansible/action_plugins/plugins/interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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 json

from google.protobuf.json_format import MessageToJson, Parse

from action_plugins.pout.models.vpp.interfaces.interface_pb2 import Interface


def plugin_init(name, values, agent_name, ip ,port):
if name == 'interface':
return InterfaceValidation(values, agent_name)
else:
return False


class InterfaceValidation:

def __init__(self, values, agent_name):
self.values = values
self.agent_name =agent_name

def validate(self):
interface = Interface()
Parse(json.dumps(self.values), interface)
return MessageToJson(interface, indent=None)

def create_key(self):
return "/vnf-agent/{}/config/vpp/v2/interfaces/{}".format(self.agent_name, self.values['name'])
41 changes: 41 additions & 0 deletions ansible/action_plugins/plugins/nat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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 json

from google.protobuf.json_format import MessageToJson, Parse

from action_plugins.pout.models.vpp.nat.nat_pb2 import Nat44Global


def plugin_init(name, values, agent_name, ip, port):
if name == 'nat':
return NatValidation(values, agent_name)
else:
return False


class NatValidation:

def __init__(self, values, agent_name):
self.values = values
self.agent_name =agent_name

def validate(self):
nat = Nat44Global()
Parse(json.dumps(self.values), nat)
return MessageToJson(nat, indent=None)

def create_key(self):
return "/vnf-agent/{}/config/vpp/nat/v2/nat44-global".format(self.agent_name)
45 changes: 45 additions & 0 deletions ansible/action_plugins/plugins/route.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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 json
from enum import Enum

from google.protobuf.json_format import MessageToJson, Parse

from action_plugins.pout.models.vpp.l3.route_pb2 import Route


def plugin_init(name, values, agent_name, ip, port):
if name == 'route':
return RouteValidation(values, agent_name)
else:
return False


class RouteValidation:

def __init__(self, values, agent_name):
self.values = values
self.agent_name = agent_name

def validate(self):
route = Route()
Parse(json.dumps(self.values), route)
return MessageToJson(route, indent=None)

def create_key(self):
return "/vnf-agent/{}/config/vpp/v2/route/vrf/{}/dst/{}/gw/{}".format(self.agent_name,
self.values.get('name', 0),
self.values['dst_network'],
self.values.get('next_hop_addr', ''))
13 changes: 13 additions & 0 deletions ansible/action_plugins/pout/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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.
13 changes: 13 additions & 0 deletions ansible/action_plugins/pout/github/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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.
13 changes: 13 additions & 0 deletions ansible/action_plugins/pout/github/com/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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.
13 changes: 13 additions & 0 deletions ansible/action_plugins/pout/github/com/gogo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2019 PANTHEON.tech
#
# 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.
Loading

0 comments on commit 400e6c3

Please sign in to comment.