VNFD_BUILD_PKGS := $(addprefix $(VNFD_BUILD_DIR)_pkgs/, $(VNFD_PKGS))
IMS_GITHUB="https://github.com/Metaswitch/clearwater-juju.git"
+CHARM_REPO="https://osm.etsi.org/gerrit/osm/juju-charms.git"
all: $(VNFD_BUILD_PKGS) ${NSD_BUILD_PKGS}
echo $@
src/gen_vnfd_pkg.sh $< $@
-$(BUILD_DIR)/clearwater-juju: $(VNFD_BUILD_DIR)/ims_allin1_2p_vnf
+$(BUILD_DIR)/clearwater-juju:
+ mkdir -p $(BUILD_DIR)
-cd $(BUILD_DIR) && (test -e clearwater-juju || git clone $(IMS_GITHUB))
+$(BUILD_DIR)/juju-charms:
+ mkdir -p $(BUILD_DIR)
+ -cd $(BUILD_DIR) && (test -e juju-charms || git clone $(CHARM_REPO))
+
$(NSD_BUILD_DIR)/%: $(NSD_SRC_DIR)/%
mkdir -p $(NSD_BUILD_DIR)
cp -rf $< $(NSD_BUILD_DIR)
$(BUILD_DIR)/nsd_pkgs/%.tar.gz: $(NSD_BUILD_DIR)/%
src/generate_descriptor_pkg.sh $(BUILD_DIR)/nsd_pkgs $<
-$(VNFD_BUILD_DIR)/ims_allin1_2p_vnf/charms/clearwater-aio-proxy: $(BUILD_DIR)/clearwater-juju
- # Copy the IMS Charm into the IMS vnf package directory before
+$(VNFD_BUILD_DIR)/ims_allin1_2p_vnf/charms/clearwater-aio-proxy: $(VNFD_BUILD_DIR)/ims_allin1_2p_vnf $(BUILD_DIR)/clearwater-juju
+ # Copy the IMS Charm into the IMS vnf package directory before packaging
cp -rf $(BUILD_DIR)/clearwater-juju/charms/trusty/clearwater-aio-proxy $(VNFD_BUILD_DIR)/ims_allin1_2p_vnf/charms
-$(BUILD_DIR)/vnfd_pkgs/%.tar.gz: $(VNFD_BUILD_DIR)/% $(VNFD_BUILD_DIR)/ims_allin1_2p_vnf/charms/clearwater-aio-proxy
+$(VNFD_BUILD_DIR)/6wind_vnf/charms/vpe-router: $(VNFD_BUILD_DIR)/6wind_vnf $(BUILD_DIR)/juju-charms
+ # Copy the IMS Charm into the IMS vnf package directory before packaging
+ cp -rf $(BUILD_DIR)/juju-charms/vpe-router $(VNFD_BUILD_DIR)/6wind_vnf/charms
+
+$(BUILD_DIR)/vnfd_pkgs/%.tar.gz: $(VNFD_BUILD_DIR)/% $(VNFD_BUILD_DIR)/ims_allin1_2p_vnf/charms/clearwater-aio-proxy $(VNFD_BUILD_DIR)/6wind_vnf/charms/vpe-router
src/generate_descriptor_pkg.sh $(BUILD_DIR)/vnfd_pkgs $<
+++ /dev/null
-{
- "layers": [
- "layer:basic",
- "vpe-router",
- "build"
- ],
- "signatures": {
- "hooks/stop": [
- "layer:basic",
- "static",
- "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
- ],
- "wheelhouse/ecdsa-0.13.tar.gz": [
- "vpe-router",
- "dynamic",
- "64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa"
- ],
- "wheelhouse/charms.reactive-0.3.8.tar.gz": [
- "layer:basic",
- "dynamic",
- "3f8722d85f7d489f8414d11fc2a3e8793c68000f7a1bc7b1ad71120e037aebee"
- ],
- "hooks/hook.template": [
- "layer:basic",
- "static",
- "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
- ],
- "wheelhouse/pycrypto-2.6.1.tar.gz": [
- "vpe-router",
- "dynamic",
- "f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c"
- ],
- "hooks/start": [
- "layer:basic",
- "static",
- "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
- ],
- "wheelhouse/pip-7.1.2.tar.gz": [
- "layer:basic",
- "dynamic",
- "ca047986f0528cfa975a14fb9f7f106271d4e0c3fe1ddced6c1db2e7ae57a477"
- ],
- "wheelhouse/PyYAML-3.11.tar.gz": [
- "layer:basic",
- "dynamic",
- "c36c938a872e5ff494938b33b14aaa156cb439ec67548fcab3535bb78b0846e8"
- ],
- "Makefile": [
- "layer:basic",
- "static",
- "f91213a68bc5edce9ebe0615b70cc908ea45466c2e205fb6cfe9c35d9c3fde4b"
- ],
- "reactive/__init__.py": [
- "layer:basic",
- "static",
- "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
- ],
- "wheelhouse/Jinja2-2.8.tar.gz": [
- "layer:basic",
- "dynamic",
- "bc1ff2ff88dbfacefde4ddde471d1417d3b304e8df103a7a9437d47269201bf4"
- ],
- "hooks/upgrade-charm": [
- "layer:basic",
- "static",
- "b78e405476402d34624c70822d9a60be2f4f85255765f619c0ecfe18f5f934ea"
- ],
- "actions/add-corporation": [
- "vpe-router",
- "static",
- "951055318724d05aa82fa9757143561ecf3617a3bd2eaebb08533ed1ae897ade"
- ],
- ".build.manifest": [
- "build",
- "dynamic",
- "unchecked"
- ],
- "wheelhouse/charmhelpers-0.6.1.tar.gz": [
- "layer:basic",
- "dynamic",
- "c41a4cb3dcf6aa35e115addf9fb83a94585a4ff3bddc63148983431af45905f8"
- ],
- "actions/delete-corporation": [
- "vpe-router",
- "static",
- "1e380d728790fa946e2429eaed31ff11aa4186cc287b818d8a91da7da291a6b3"
- ],
- "hooks/update-status": [
- "layer:basic",
- "static",
- "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
- ],
- "hooks/leader-settings-changed": [
- "layer:basic",
- "static",
- "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
- ],
- "wheelhouse/Tempita-0.5.2.tar.gz": [
- "layer:basic",
- "dynamic",
- "cacecf0baa674d356641f1d406b8bff1d756d739c46b869a54de515d08e6fc9c"
- ],
- "actions.yaml": [
- "vpe-router",
- "static",
- "619cedd685181c02ae36d04014bc4763c1e4e1b0a1b8a743d1a239c442f2883b"
- ],
- "README.md": [
- "layer:basic",
- "static",
- "5d5101eb0f2eb90eb0959438416ceb5e9b82c7746a385eb64ccb8a8ffe01e92b"
- ],
- "reactive/vpe_router.py": [
- "vpe-router",
- "static",
- "479874bbe5db71ddc0b3e4e0adab051540dbc8d30021800c42a1b058bf9dcd94"
- ],
- "tox.ini": [
- "layer:basic",
- "static",
- "5efb9280763f1f4cb861485e80863caafc9cd5ab1176543e911c27519436de7a"
- ],
- "metadata.yaml": [
- "vpe-router",
- "dynamic",
- "a7bf974efb4a29810de06626025fbc3b158053c70b0d67eb4b142a2ac087c5c0"
- ],
- "wheelhouse/pyaml-15.8.2.tar.gz": [
- "layer:basic",
- "dynamic",
- "9c54fb5f17b58572c4cef50affea60bb73f445ab153580dac07a12383712b5b8"
- ],
- "copyright": [
- "layer:basic",
- "static",
- "1e2afbd75c71affa132ae7ee3327cb29b5e4b9d9705f27dfd03857c326f50c5c"
- ],
- "requirements.txt": [
- "layer:basic",
- "static",
- "0f1c70d27e26005a96d66ad54482877ae20f7737693c833e29dd72bd6ac24892"
- ],
- "wheelhouse/netaddr-0.7.18.tar.gz": [
- "layer:basic",
- "dynamic",
- "a1f5c9fcf75ac2579b9995c843dade33009543c04f218ff7c007b3c81695bd19"
- ],
- "wheelhouse/paramiko-1.16.0.tar.gz": [
- "vpe-router",
- "dynamic",
- "3297ebd3cd072f573772f7c7426939a443c62c458d54bb632ff30fd6ecf96892"
- ],
- "actions/connect-domains": [
- "vpe-router",
- "static",
- "cdc11dd947a97b1e6ecb92b95e5e2b2676a5b1a366638a80b5fcf052b6fe240d"
- ],
- ".gitignore": [
- "layer:basic",
- "static",
- "0da5c4dcda27cd6406e5bb81cbf68ddccaf728ac764ec15053a165c1449d87d9"
- ],
- "lib/charms/router.py": [
- "vpe-router",
- "static",
- "b29712ab37799310107c99bb79ce90a991c5ebf95d513bad127b3fabd02df4a7"
- ],
- "hooks/install": [
- "layer:basic",
- "static",
- "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
- ],
- "wheelhouse/MarkupSafe-0.23.tar.gz": [
- "layer:basic",
- "dynamic",
- "a4ec1aff59b95a14b45eb2e23761a0179e98319da5a7eb76b56ea8cdc7b871c3"
- ],
- "layer.yaml": [
- "vpe-router",
- "dynamic",
- "b6f7fe3a054fa4c8a17d4fa922ee2b0624f75cb39fdcc59c511cb55455425f8b"
- ],
- "config.yaml": [
- "vpe-router",
- "dynamic",
- "989e451c1dc464082f3e1122bd784362502af58680ad8e77b88ce00db0ec2246"
- ],
- "hooks/leader-elected": [
- "layer:basic",
- "static",
- "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
- ],
- "lib/charms/bootstrap.py": [
- "layer:basic",
- "static",
- "bec7997003dbe44e9bbe85f0df598746c868fe72d1971a99d357bf3512453c70"
- ],
- "lib/charms/layer.py": [
- "layer:basic",
- "static",
- "3accb93272464875583f9b661dc024b4adc67617354bc21d8a7f74284ae4deb4"
- ],
- "actions/delete-domain-connection": [
- "vpe-router",
- "static",
- "0b59e146b4b0223f5593cd4bad9a829822713b10b2ccab46d07a531eb9e20216"
- ],
- "wheelhouse/six-1.10.0.tar.gz": [
- "layer:basic",
- "dynamic",
- "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a"
- ],
- "hooks/config-changed": [
- "layer:basic",
- "static",
- "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
- ]
- }
-}
\ No newline at end of file
+++ /dev/null
-*.pyc
-*~
-.ropeproject
-.settings
-.tox
+++ /dev/null
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "{}"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright {yyyy} {name of copyright owner}
-
- 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.
+++ /dev/null
-#!/usr/bin/make
-PYTHON := /usr/bin/env python
-
-all: lint test build
-
-
-build: unit_test
- juju-compose -o ~/charms .
-
-lint:
- @flake8 --exclude hooks/charmhelpers hooks unit_tests tests
- @charm proof
-
-unit_test:
- @echo Starting tests...
- tox
-
-test:
- @echo Starting Amulet tests...
- # coreycb note: The -v should only be temporary until Amulet sends
- # raise_status() messages to stderr:
- # https://bugs.launchpad.net/amulet/+bug/1320357
- @juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
+++ /dev/null
-# Overview
-
-This is the base layer for all charms [built using layers][building]. It
-provides all of the standard Juju hooks and runs the
-[charms.reactive.main][charms.reactive] loop for them. It also bootstraps the
-[charm-helpers][] and [charms.reactive][] libraries and all of their
-dependencies for use by the charm.
-
-# Usage
-
-To create a charm layer using this base layer, you need only include it in
-a `layer.yaml` file:
-
-```yaml
-includes: ['layer:basic']
-```
-
-This will fetch this layer from [interfaces.juju.solutions][] and incorporate
-it into your charm layer. You can then add handlers under the `reactive/`
-directory. Note that **any** file under `reactive/` will be expected to
-contain handlers, whether as Python decorated functions or [executables][non-python]
-using the [external handler protocol][].
-
-You can also define Python libraries under `lib/charms/X` where `X` is a
-package under the `charms.` namespace for your charm. See [PyPI][pypi charms.X]
-for what packages already exist under the `charms.` namespace.
-
-# Hooks
-
-This layer provides hooks that other layers can react to using the decorators
-of the [charms.reactive][] library:
-
- * `config-changed`
- * `install`
- * `leader-elected`
- * `leader-settings-changed`
- * `start`
- * `stop`
- * `upgrade-charm`
- * `update-status`
-
-Other hooks are not implemented at this time. A new layer can implement storage
-or relation hooks in their own layer by putting them in the `hooks` directory.
-
-**Note:** Because `update-status` is invoked every 5 minutes, you should take
-care to ensure that your reactive handlers only invoke expensive operations
-when absolutely necessary. It is recommended that you use helpers like
-[`@only_once`][], [`@when_file_changed`][], and [`data_changed`][] to ensure
-that handlers run only when necessary.
-
-# Layer Configuration
-
-This layer does not currently support any configuration.
-
-
-# Reactive States
-
-This layer currently does not set any reactive states.
-
-
-# Actions
-
-This layer currently does not define any actions.
-
-
-[building]: https://jujucharms.com/docs/devel/authors-charm-building
-[charm-helpers]: https://pythonhosted.org/charmhelpers/
-[charms.reactive]: https://pythonhosted.org/charms.reactive/
-[interfaces.juju.solutions]: http://interfaces.juju.solutions/
-[non-python]: https://pythonhosted.org/charms.reactive/#non-python-reactive-handlers
-[external handler protocol]: https://pythonhosted.org/charms.reactive/charms.reactive.bus.html#charms.reactive.bus.ExternalHandler
-[pypi charms.X]: https://pypi.python.org/pypi?%3Aaction=search&term=charms.&submit=search
-[`@only_once`]: https://pythonhosted.org/charms.reactive/charms.reactive.decorators.html#charms.reactive.decorators.only_once
-[`@when_file_changed`]: https://pythonhosted.org/charms.reactive/charms.reactive.decorators.html#charms.reactive.decorators.when_file_changed
-[`data_changed`]: https://pythonhosted.org/charms.reactive/charms.reactive.helpers.html#charms.reactive.helpers.data_changed
+++ /dev/null
-configure-interface:
- description: Configure an ethernet interface.
- params:
- iface-name:
- type: string
- description: Device name, e.g. eth1
- cidr:
- type: string
- description: Network range to assign to the interface
- required: [iface-name]
-add-corporation:
- description: Add a new corporation to the router
- params:
- domain-name:
- type: string
- description: Name of the vlan corporation
- iface-name:
- type: string
- description: Device name. eg eth1
- vlan-id:
- type: integer
- description: The name of the vlan?
- cidr:
- type: string
- description: Network range to assign to the tagged vlan-id
- area:
- type: string
- description: Link State Advertisements (LSA) type
- subnet-cidr:
- type: string
- description: Network range
- subnet-area:
- type: string
- description: Link State Advertisements (LSA) type
- required: [domain-name, iface-name, vlan-id, cidr, area, subnet-cidr, subnet-area]
-delete-corporation:
- description: Remove the corporation from the router completely
- params:
- domain-name:
- type: string
- description: The domain of the corporation to remove
- cidr:
- type: string
- description: Network range to assign to the tagged vlan-id
- area:
- type: string
- description: Link State Advertisements (LSA) type
- subnet-cidr:
- type: string
- description: Network range
- subnet-area:
- type: string
- description: Link State Advertisements (LSA) type
- required: [domain-name, cidr, area, subnet-cidr, subnet-area]
-connect-domains:
- description: Connect the router to another router, where the same domain is present
- params:
- domain-name:
- type: string
- description: The domain of the coproration to connect
- iface-name:
- type: string
- description: Device name. eg eth1
- tunnel-name:
- type: string
- description: Name of the tunnel ?
- local-ip:
- type: string
- description: local ip ?
- remote-ip:
- type: string
- description: remote ip ?
- tunnel-key:
- type: string
- description: tunnel key?
- internal-local-ip:
- type: string
- description: internal local ip?
- internal-remote-ip:
- type: string
- description: internal remote ip?
- tunnel-type:
- type: string
- default: gre
- description: The type of tunnel to establish.
- required: [domain-name, iface-name, tunnel-name, local-ip, remote-ip, tunnel-key, internal-local-ip, internal-remote-ip]
-delete-domain-connection:
- description: Remove the tunnel to another router where the domain is present.
- params:
- domain-name:
- type: string
- description: The domain of the corporation to unlink
- tunnel-name:
- type: string
- description: The name of the tunnel to unlink that the domain-name is attached to
- required: [domain-name, tunnel-name]
+++ /dev/null
-#!/usr/bin/env python3
-import sys
-sys.path.append('lib')
-
-from charms.reactive import main
-from charms.reactive import set_state
-from charmhelpers.core.hookenv import action_fail
-
-"""
-`set_state` only works here because it's flushed to disk inside the `main()`
-loop. remove_state will need to be called inside the action method.
-"""
-set_state('vpe.add-corporation')
-
-try:
- main()
-except Exception as e:
- action_fail(repr(e))
+++ /dev/null
-#!/usr/bin/env python3
-import sys
-sys.path.append('lib')
-
-from charms.reactive import main
-from charms.reactive import set_state
-from charmhelpers.core.hookenv import action_fail
-
-"""
-`set_state` only works here because it's flushed to disk inside the `main()`
-loop. remove_state will need to be called inside the action method.
-"""
-set_state('vpe.configure-interface')
-
-try:
- main()
-except Exception as e:
- action_fail(repr(e))
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.reactive import main
-from charms.reactive import set_state
-from charmhelpers.core.hookenv import action_fail
-
-"""
-`set_state` only works here because it's flushed to disk inside the `main()`
-loop. remove_state will need to be called inside the action method.
-"""
-set_state('vpe.connect-domains')
-
-try:
- main()
-except Exception as e:
- action_fail(repr(e))
+++ /dev/null
-#!/usr/bin/env python3
-import sys
-sys.path.append('lib')
-
-from charms.reactive import main
-from charms.reactive import set_state
-from charmhelpers.core.hookenv import action_fail
-
-
-"""
-`set_state` only works here because it's flushed to disk inside the `main()`
-loop. remove_state will need to be called inside the action method.
-"""
-set_state('vpe.delete-corporation')
-
-try:
- main()
-except Exception as e:
- action_fail(repr(e))
+++ /dev/null
-#!/usr/bin/env python3
-import sys
-sys.path.append('lib')
-
-from charms.reactive import main
-from charms.reactive import set_state
-from charmhelpers.core.hookenv import action_fail
-
-
-"""
-`set_state` only works here because it's flushed to disk inside the `main()`
-loop. remove_state will need to be called inside the action method.
-"""
-set_state('vpe.delete-domain-connection')
-
-try:
- main()
-except Exception as e:
- action_fail(repr(e))
+++ /dev/null
-options:
- vpe-router:
- default:
- type: string
- description: Hostname or IP of the vpe router to connect to
- user:
- type: string
- default: root
- description: Username for VPE Router
- pass:
- type: string
- default:
- description: Password for VPE Router
- hostname:
- type: string
- default:
- description: The hostname to set the vpe router to.
+++ /dev/null
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
-
-Files: *
-Copyright: 2015, Canonical Ltd.
-License: GPL-3
-
-License: GPL-3
- On Debian GNU/Linux system you can find the complete text of the
- GPL-3 license in '/usr/share/common-licenses/GPL-3'
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import sys
-sys.path.append('lib')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-#!/usr/bin/env python3
-
-# Load modules from $CHARM_DIR/lib
-import os
-import sys
-sys.path.append('lib')
-
-# This is an upgrade-charm context, make sure we install latest deps
-if not os.path.exists('wheelhouse/.upgrade'):
- open('wheelhouse/.upgrade', 'w').close()
- if os.path.exists('wheelhouse/.bootstrapped'):
- os.unlink('wheelhouse/.bootstrapped')
-else:
- os.unlink('wheelhouse/.upgrade')
-
-from charms.bootstrap import bootstrap_charm_deps
-bootstrap_charm_deps()
-
-
-# This will load and run the appropriate @hook and other decorated
-# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
-# and $CHARM_DIR/hooks/relations.
-#
-# See https://jujucharms.com/docs/stable/authors-charm-building
-# for more information on this pattern.
-from charms.reactive import main
-main()
+++ /dev/null
-includes:
-- layer:basic
-is: vpe-router
+++ /dev/null
-import os
-import sys
-import shutil
-from glob import glob
-from subprocess import check_call
-
-
-def bootstrap_charm_deps():
- """
- Set up the base charm dependencies so that the reactive system can run.
- """
- venv = os.path.abspath('../.venv')
- vbin = os.path.join(venv, 'bin')
- vpip = os.path.join(vbin, 'pip')
- vpy = os.path.join(vbin, 'python')
- if os.path.exists('wheelhouse/.bootstrapped'):
- from charms import layer
- cfg = layer.options('basic')
- if cfg.get('use_venv') and '.venv' not in sys.executable:
- # activate the venv
- os.environ['PATH'] = ':'.join([vbin, os.environ['PATH']])
- reload_interpreter(vpy)
- return
- # bootstrap wheelhouse
- if os.path.exists('wheelhouse'):
- apt_install(['python3-pip', 'python3-yaml'])
- from charms import layer
- cfg = layer.options('basic')
- # include packages defined in layer.yaml
- apt_install(cfg.get('packages', []))
- # if we're using a venv, set it up
- if cfg.get('use_venv'):
- apt_install(['python-virtualenv'])
- cmd = ['virtualenv', '--python=python3', venv]
- if cfg.get('include_system_packages'):
- cmd.append('--system-site-packages')
- check_call(cmd)
- os.environ['PATH'] = ':'.join([vbin, os.environ['PATH']])
- pip = vpip
- else:
- pip = 'pip3'
- # save a copy of system pip to prevent `pip3 install -U pip` from changing it
- if os.path.exists('/usr/bin/pip'):
- shutil.copy2('/usr/bin/pip', '/usr/bin/pip.save')
- # need newer pip, to fix spurious Double Requirement error https://github.com/pypa/pip/issues/56
- check_call([pip, 'install', '-U', '--no-index', '-f', 'wheelhouse', 'pip'])
- # install the rest of the wheelhouse deps
- check_call([pip, 'install', '-U', '--no-index', '-f', 'wheelhouse'] + glob('wheelhouse/*'))
- if not cfg.get('use_venv'):
- # restore system pip to prevent `pip3 install -U pip` from changing it
- if os.path.exists('/usr/bin/pip.save'):
- shutil.copy2('/usr/bin/pip.save', '/usr/bin/pip')
- os.remove('/usr/bin/pip.save')
- # flag us as having already bootstrapped so we don't do it again
- open('wheelhouse/.bootstrapped', 'w').close()
- # Ensure that the newly bootstrapped libs are available.
- # Note: this only seems to be an issue with namespace packages.
- # Non-namespace-package libs (e.g., charmhelpers) are available
- # without having to reload the interpreter. :/
- reload_interpreter(vpy if cfg.get('use_venv') else sys.argv[0])
-
-
-def reload_interpreter(python):
- """
- Reload the python interpreter to ensure that all deps are available.
-
- Newly installed modules in namespace packages sometimes seemt to
- not be picked up by Python 3.
- """
- os.execle(python, python, sys.argv[0], os.environ)
-
-
-def apt_install(packages):
- """
- Install apt packages.
-
- This ensures a consistent set of options that are often missed but
- should really be set.
- """
- if isinstance(packages, (str, bytes)):
- packages = [packages]
-
- env = os.environ.copy()
-
- if 'DEBIAN_FRONTEND' not in env:
- env['DEBIAN_FRONTEND'] = 'noninteractive'
-
- cmd = ['apt-get',
- '--option=Dpkg::Options::=--force-confold',
- '--assume-yes',
- 'install']
- check_call(cmd + packages, env=env)
+++ /dev/null
-
-import os
-import yaml
-
-
-class LayerOptions(dict):
- def __init__(self, layer_file, section=None):
- with open(layer_file) as f:
- layer = yaml.safe_load(f.read())
- opts = layer.get('options', {})
- if section and section in opts:
- super(LayerOptions, self).__init__(opts.get(section))
- else:
- super(LayerOptions, self).__init__(opts)
-
-
-def options(section=None, layer_file=None):
- if not layer_file:
- base_dir = os.environ.get('CHARM_DIR', os.getcwd())
- layer_file = os.path.join(base_dir, 'layer.yaml')
-
- return LayerOptions(layer_file, section)
+++ /dev/null
-
-import paramiko
-import subprocess
-
-from charmhelpers.core.hookenv import config
-
-
-class NetNS(object):
- def __init__(self, name):
- pass
-
- @classmethod
- def create(cls, name):
- # @TODO: Need to check if namespace exists already
- try:
- ip('netns', 'add', name)
- except Exception as e:
- raise Exception('could not create net namespace: %s' % e)
-
- return cls(name)
-
- def up(self, iface, cidr):
- self.do('ip', 'link', 'set', 'dev', iface, 'up')
- self.do('ip', 'address', 'add', cidr, 'dev', iface)
-
- def add_iface(self, iface):
- ip('link', 'set', 'dev', iface, 'netns', self.name)
-
- def do(self, *cmd):
- ip(*['netns', 'exec', self.name] + cmd)
-
-
-def ip(*args):
- return _run(['ip'] + list(args))
-
-
-def _run(cmd, env=None):
- if isinstance(cmd, str):
- cmd = cmd.split() if ' ' in cmd else [cmd]
-
- cfg = config()
- if all(k in cfg for k in ['pass', 'vpe-router', 'user']):
- router = cfg['vpe-router']
- user = cfg['user']
- passwd = cfg['pass']
-
- if router and user and passwd:
- return ssh(cmd, router, user, passwd)
-
- p = subprocess.Popen(cmd,
- env=env,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- stdout, stderr = p.communicate()
- retcode = p.poll()
- if retcode > 0:
- raise subprocess.CalledProcessError(returncode=retcode,
- cmd=cmd,
- output=stderr.decode("utf-8").strip())
- return (''.join(stdout), ''.join(stderr))
-
-
-def ssh(cmd, host, user, password=None):
- ''' Suddenly this project needs to SSH to something. So we replicate what
- _run was doing with subprocess using the Paramiko library. This is
- temporary until this charm /is/ the VPE Router '''
-
- cmds = ' '.join(cmd)
- client = paramiko.SSHClient()
- client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- client.connect(host, port=22, username=user, password=password)
-
- stdin, stdout, stderr = client.exec_command(cmds)
- retcode = stdout.channel.recv_exit_status()
- client.close() # @TODO re-use connections
- if retcode > 0:
- output = stderr.read().strip()
- raise subprocess.CalledProcessError(returncode=retcode, cmd=cmd,
- output=output)
- return (''.join(stdout), ''.join(stderr))
+++ /dev/null
-name: vpe-router
-summary: setup a virtualized PE Router with GRE tunnels
-description: |
- this charm, when deployed and configured, will provide a secure virtualized
- provider edge router.
-peers:
- loadbalance:
- interface: vpe-router
-maintainers:
-- Marco Ceppi <marco.ceppi@canonical.com>
-- Adam Israel <adam.israel@canonical.com>
+++ /dev/null
-
-from charmhelpers.core.hookenv import (
- config,
- status_set,
- action_get,
- action_fail,
- log,
-)
-
-from charms.reactive import (
- hook,
- when,
- when_not,
- helpers,
- set_state,
- remove_state,
-)
-
-from charms import router
-import subprocess
-
-cfg = config()
-
-
-@hook('config-changed')
-def validate_config():
- try:
- """
- If the ssh credentials are available, we'll act as a proxy charm.
- Otherwise, we execute against the unit we're deployed on to.
- """
- if all(k in cfg for k in ['pass', 'vpe-router', 'user']):
- routerip = cfg['vpe-router']
- user = cfg['user']
- passwd = cfg['pass']
-
- if routerip and user and passwd:
- # Assumption: this will be a root user
- out, err = router.ssh(['whoami'], routerip,
- user, passwd)
- if out.strip() != user:
- raise Exception('invalid credentials')
-
- # Set the router's hostname
- try:
- if user == 'root' and 'hostname' in cfg:
- hostname = cfg['hostname']
- out, err = router.ssh(['hostname', hostname],
- routerip,
- user, passwd)
- out, err = router.ssh(['sed',
- '-i',
- '"s/hostname.*$/hostname %s/"'
- % hostname,
- '/usr/admin/global/hostname.sh'
- ],
- routerip,
- user, passwd)
-
- except subprocess.CalledProcessError as e:
- log('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- raise
-
- set_state('vpe.configured')
- status_set('active', 'ready!')
-
- except Exception as e:
- log(repr(e))
- remove_state('vpe.configured')
- status_set('blocked', 'validation failed: %s' % e)
-
-
-@when_not('vpe.configured')
-def not_ready_add():
- actions = [
- 'vpe.add-corporation',
- 'vpe.connect-domains',
- 'vpe.delete-domain-connections',
- 'vpe.remove-corporation',
- 'vpe.configure-interface',
- 'vpe.configure-ospf',
- ]
-
- if helpers.any_states(*actions):
- action_fail('VPE is not configured')
-
- status_set('blocked', 'vpe is not configured')
-
-
-def start_ospfd():
- # We may want to make this configurable via config setting
- ospfd = '/usr/local/bin/ospfd'
-
- try:
- (stdout, stderr) = router._run(['touch',
- '/usr/admin/global/ospfd.conf'])
- (stdout, stderr) = router._run([ospfd, '-d', '-f',
- '/usr/admin/global/ospfd.conf'])
- except subprocess.CalledProcessError as e:
- log('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
-
-
-def configure_ospf(domain, cidr, area, subnet_cidr, subnet_area, enable=True):
- """Configure the OSPF service"""
-
- # Check to see if the OSPF daemon is running, and start it if not
- try:
- (stdout, stderr) = router._run(['pgrep', 'ospfd'])
- except subprocess.CalledProcessError as e:
- # If pgrep fails, the process wasn't found.
- start_ospfd()
- log('Command failed (ospfd not running): %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
-
- upordown = ''
- if not enable:
- upordown = 'no'
- try:
- vrfctl = '/usr/local/bin/vrfctl'
- vtysh = '/usr/local/bin/vtysh'
-
- (stdout, stderr) = router._run([vrfctl, 'list'])
-
- domain_id = 0
- for line in stdout.split('\n'):
- if domain in line:
- domain_id = int(line[3:5])
-
- if domain_id > 0:
- router._run([vtysh,
- '-c',
- '"configure terminal"',
- '-c',
- '"router ospf %d vr %d"' % (domain_id, domain_id),
- '-c',
- '"%s network %s area %s"' % (upordown, cidr, area),
- '-c',
- '"%s network %s area %s"' % (upordown,
- subnet_cidr,
- subnet_area),
- ])
-
- else:
- log("Invalid domain id")
- except subprocess.CalledProcessError as e:
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- finally:
- remove_state('vpe.configure-interface')
- status_set('active', 'ready!')
-
-
-@when('vpe.configured')
-@when('vpe.configure-interface')
-def configure_interface():
- """
- Configure an ethernet interface
- """
- iface_name = action_get('iface-name')
- cidr = action_get('cidr')
-
- # cidr is optional
- if cidr:
- try:
- # Add may fail, but change seems to add or update
- router.ip('address', 'change', cidr, 'dev', iface_name)
- except subprocess.CalledProcessError as e:
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- return
- finally:
- remove_state('vpe.configure-interface')
- status_set('active', 'ready!')
-
- try:
- router.ip('link', 'set', 'dev', iface_name, 'up')
- except subprocess.CalledProcessError as e:
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- finally:
- remove_state('vpe.configure-interface')
- status_set('active', 'ready!')
-
-
-@when('vpe.configured')
-@when('vpe.add-corporation')
-def add_corporation():
- '''
- Create and Activate the network corporation
- '''
- domain_name = action_get('domain-name')
- iface_name = action_get('iface-name')
- # HACK: python's list, used deeper, throws an exception on ints in a tuple
- vlan_id = str(action_get('vlan-id'))
- cidr = action_get('cidr')
- area = action_get('area')
- subnet_cidr = action_get('subnet-cidr')
- subnet_area = action_get('subnet-area')
-
- iface_vlanid = '%s.%s' % (iface_name, vlan_id)
-
- status_set('maintenance', 'adding corporation {}'.format(domain_name))
-
- """
- Attempt to run all commands to add the network corporation. If any step
- fails, abort and call `delete_corporation()` to undo.
- """
- try:
- """
- $ ip link add link eth3 name eth3.103 type vlan id 103
- """
- router.ip('link',
- 'add',
- 'link',
- iface_name,
- 'name',
- iface_vlanid,
- 'type',
- 'vlan',
- 'id',
- vlan_id)
-
- """
- $ ip netns add domain
- """
- router.ip('netns',
- 'add',
- domain_name)
-
- """
- $ ip link set dev eth3.103 netns corpB
- """
- router.ip('link',
- 'set',
- 'dev',
- iface_vlanid,
- 'netns',
- domain_name)
-
- """
- $ ifconfig eth3 up
- """
- router._run(['ifconfig', iface_name, 'up'])
-
- """
- $ ip netns exec corpB ip link set dev eth3.103 up
- """
- router.ip('netns',
- 'exec',
- domain_name,
- 'ip',
- 'link',
- 'set',
- 'dev',
- iface_vlanid,
- 'up')
-
- """
- $ ip netns exec corpB ip address add 10.0.1.1/24 dev eth3.103
- """
- mask = cidr.split("/")[1]
- ip = '%s/%s' % (area, mask)
- router.ip('netns',
- 'exec',
- domain_name,
- 'ip',
- 'address',
- 'add',
- ip,
- 'dev',
- iface_vlanid)
-
- configure_ospf(domain_name, cidr, area, subnet_cidr, subnet_area, True)
-
- except subprocess.CalledProcessError as e:
- delete_corporation()
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- finally:
- remove_state('vpe.add-corporation')
- status_set('active', 'ready!')
-
-
-@when('vpe.configured')
-@when('vpe.delete-corporation')
-def delete_corporation():
-
- domain_name = action_get('domain-name')
- cidr = action_get('cidr')
- area = action_get('area')
- subnet_cidr = action_get('subnet-cidr')
- subnet_area = action_get('subnet-area')
-
- status_set('maintenance', 'deleting corporation {}'.format(domain_name))
-
- try:
- """
- Remove all tunnels defined for this domain
-
- $ ip netns exec domain_name ip tun show
- | grep gre
- | grep -v "remote any"
- | cut -d":" -f1
- """
- p = router.ip(
- 'netns',
- 'exec',
- domain_name,
- 'ip',
- 'tun',
- 'show',
- '|',
- 'grep',
- 'gre',
- '|',
- 'grep',
- '-v',
- '"remote any"',
- '|',
- 'cut -d":" -f1'
- )
-
- # `p` should be a tuple of (stdout, stderr)
- tunnels = p[0].split('\n')
-
- for tunnel in tunnels:
- try:
- """
- $ ip netns exec domain_name ip link set $tunnel_name down
- """
- router.ip(
- 'netns',
- 'exec',
- domain_name,
- 'ip',
- 'link',
- 'set',
- tunnel,
- 'down'
- )
- except subprocess.CalledProcessError as e:
- log('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- pass
-
- try:
- """
- $ ip netns exec domain_name ip tunnel del $tunnel_name
- """
- router.ip(
- 'netns',
- 'exec',
- domain_name,
- 'ip',
- 'tunnel',
- 'del',
- tunnel
- )
- except subprocess.CalledProcessError as e:
- log('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- pass
-
- """
- Remove all interfaces associated to the domain
-
- $ ip netns exec domain_name ifconfig | grep mtu | cut -d":" -f1
- """
- p = router.ip(
- 'netns',
- 'exec',
- domain_name,
- 'ifconfig',
- '|',
- 'grep mtu',
- '|',
- 'cut -d":" -f1'
- )
-
- ifaces = p[0].split('\n')
- for iface in ifaces:
-
- try:
- """
- $ ip netns exec domain_name ip link set $iface down
- """
- router.ip(
- 'netns',
- 'exec',
- domain_name,
- 'ip',
- 'link',
- 'set',
- iface,
- 'down'
- )
- except subprocess.CalledProcessError as e:
- log('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
-
- try:
- """
- $ ifconfig eth3 down
- """
- router._run(['ifconfig', iface, 'down'])
- except subprocess.CalledProcessError as e:
- log('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- pass
-
- try:
- """
- $ ip link del dev $iface
- """
- router.ip(
- 'link',
- 'del',
- 'dev',
- iface
- )
- except subprocess.CalledProcessError as e:
- log('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- pass
-
- try:
- """
- Remove the domain
-
- $ ip netns del domain_name
- """
- router.ip(
- 'netns',
- 'del',
- domain_name
- )
- except subprocess.CalledProcessError as e:
- log('Command failed: %s (%s)' % (' '.join(e.cmd), str(e.output)))
- pass
-
- try:
- configure_ospf(domain_name,
- cidr,
- area,
- subnet_cidr,
- subnet_area,
- False)
- except subprocess.CalledProcessError as e:
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
-
- except:
- # Do nothing
- log('delete-corporation failed.')
- pass
-
- finally:
- remove_state('vpe.delete-corporation')
- status_set('active', 'ready!')
-
-
-@when('vpe.configured')
-@when('vpe.connect-domains')
-def connect_domains():
-
- params = [
- 'domain-name',
- 'iface-name',
- 'tunnel-name',
- 'local-ip',
- 'remote-ip',
- 'tunnel-key',
- 'internal-local-ip',
- 'internal-remote-ip',
- 'tunnel-type',
- ]
-
- config = {}
- for p in params:
- config[p] = action_get(p)
-
- status_set('maintenance', 'connecting domains')
-
- try:
- """
- $ ip tunnel add tunnel_name mode gre local local_ip remote remote_ip
- dev iface_name key tunnel_key csum
- """
- router.ip(
- 'tunnel',
- 'add',
- config['tunnel-name'],
- 'mode',
- config['tunnel-type'],
- 'local',
- config['local-ip'],
- 'remote',
- config['remote-ip'],
- 'dev',
- config['iface-name'],
- 'key',
- config['tunnel-key'],
- 'csum'
- )
-
- except subprocess.CalledProcessError as e:
- log('Command failed (retrying with ip tunnel change): %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- try:
- """
- If the tunnel already exists (like gre0) and can't be deleted,
- modify it instead of trying to add it.
- """
- router.ip(
- 'tunnel',
- 'change',
- config['tunnel-name'],
- 'mode',
- config['tunnel-type'],
- 'local',
- config['local-ip'],
- 'remote',
- config['remote-ip'],
- 'dev',
- config['iface-name'],
- 'key',
- config['tunnel-key'],
- 'csum'
- )
- except subprocess.CalledProcessError as e:
- delete_domain_connection()
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- finally:
- remove_state('vpe.connect-domains')
- status_set('active', 'ready!')
-
- try:
- """
- $ ip link set dev tunnel_name netns domain_name
- """
- router.ip(
- 'link',
- 'set',
- 'dev',
- config['tunnel-name'],
- 'netns',
- config['domain-name']
- )
-
- """
- $ ip netns exec domain_name ip link set dev tunnel_name up
- """
- router.ip(
- 'netns',
- 'exec',
- config['domain-name'],
- 'ip',
- 'link',
- 'set',
- 'dev',
- config['tunnel-name'],
- 'up'
- )
-
- """
- $ ip netns exec domain_name ip address add internal_local_ip peer
- internal_remote_ip dev tunnel_name
- """
- router.ip(
- 'netns',
- 'exec',
- config['domain-name'],
- 'ip',
- 'address',
- 'add',
- config['internal-local-ip'],
- 'peer',
- config['internal-remote-ip'],
- 'dev',
- config['tunnel-name']
- )
- except subprocess.CalledProcessError as e:
- delete_domain_connection()
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- finally:
- remove_state('vpe.connect-domains')
- status_set('active', 'ready!')
-
-
-@when('vpe.configured')
-@when('vpe.delete-domain-connection')
-def delete_domain_connection():
- ''' Remove the tunnel to another router where the domain is present '''
- domain = action_get('domain-name')
- tunnel_name = action_get('tunnel-name')
-
- status_set('maintenance', 'deleting domain connection: {}'.format(domain))
-
- try:
-
- try:
- """
- $ ip netns exec domain_name ip link set tunnel_name down
- """
- router.ip('netns',
- 'exec',
- domain,
- 'ip',
- 'link',
- 'set',
- tunnel_name,
- 'down')
- except subprocess.CalledProcessError as e:
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
-
- try:
- """
- $ ip netns exec domain_name ip tunnel del tunnel_name
- """
- router.ip('netns',
- 'exec',
- domain,
- 'ip',
- 'tunnel',
- 'del',
- tunnel_name)
- except subprocess.CalledProcessError as e:
- action_fail('Command failed: %s (%s)' %
- (' '.join(e.cmd), str(e.output)))
- except:
- pass
- finally:
- remove_state('vpe.delete-domain-connection')
- status_set('active', 'ready!')
+++ /dev/null
-flake8
-pytest
+++ /dev/null
-[tox]
-skipsdist=True
-envlist = py34
-
-[testenv]
-commands = py.test -v
-deps =
- -r{toxinidir}/requirements.txt