Imported repo juju-charms
authorAdmin <Admin@etsi.org>
Fri, 23 Jun 2017 08:34:07 +0000 (10:34 +0200)
committerAdmin <Admin@etsi.org>
Fri, 23 Jun 2017 08:34:07 +0000 (10:34 +0200)
101 files changed:
.gitignore [deleted file]
Makefile [deleted file]
README.md [deleted file]
juju-charms/Makefile [new file with mode: 0644]
juju-charms/README.md [new file with mode: 0644]
juju-charms/juju-env.sh [new file with mode: 0644]
juju-charms/layers/netutils/LICENSE [new file with mode: 0644]
juju-charms/layers/netutils/README.md [new file with mode: 0644]
juju-charms/layers/netutils/actions.yaml [new file with mode: 0644]
juju-charms/layers/netutils/actions/dig [new file with mode: 0755]
juju-charms/layers/netutils/actions/iperf [new file with mode: 0755]
juju-charms/layers/netutils/actions/nmap [new file with mode: 0755]
juju-charms/layers/netutils/actions/ping [new file with mode: 0755]
juju-charms/layers/netutils/actions/traceroute [new file with mode: 0755]
juju-charms/layers/netutils/config.yaml [new file with mode: 0644]
juju-charms/layers/netutils/icon.svg [new file with mode: 0644]
juju-charms/layers/netutils/layer.yaml [new file with mode: 0644]
juju-charms/layers/netutils/metadata.yaml [new file with mode: 0644]
juju-charms/layers/netutils/reactive/layer_netutils.py [new file with mode: 0644]
juju-charms/layers/netutils/tests/00-setup [new file with mode: 0755]
juju-charms/layers/netutils/tests/10-deploy [new file with mode: 0755]
juju-charms/layers/pingpong/README.md [new file with mode: 0644]
juju-charms/layers/pingpong/actions.yaml [new file with mode: 0644]
juju-charms/layers/pingpong/actions/get-rate [new file with mode: 0755]
juju-charms/layers/pingpong/actions/get-server [new file with mode: 0755]
juju-charms/layers/pingpong/actions/get-state [new file with mode: 0755]
juju-charms/layers/pingpong/actions/get-stats [new file with mode: 0755]
juju-charms/layers/pingpong/actions/set-rate [new file with mode: 0755]
juju-charms/layers/pingpong/actions/set-server [new file with mode: 0755]
juju-charms/layers/pingpong/actions/start-traffic [new file with mode: 0755]
juju-charms/layers/pingpong/actions/stop-traffic [new file with mode: 0755]
juju-charms/layers/pingpong/config.yaml [new file with mode: 0644]
juju-charms/layers/pingpong/icon.svg [new file with mode: 0644]
juju-charms/layers/pingpong/layer.yaml [new file with mode: 0644]
juju-charms/layers/pingpong/metadata.yaml [new file with mode: 0644]
juju-charms/layers/pingpong/reactive/pingpong.py [new file with mode: 0644]
juju-charms/layers/pingpong/tests/00-setup [new file with mode: 0755]
juju-charms/layers/pingpong/tests/10-deploy [new file with mode: 0755]
juju-charms/layers/vyos-proxy/Makefile [new file with mode: 0644]
juju-charms/layers/vyos-proxy/README.md [new file with mode: 0644]
juju-charms/layers/vyos-proxy/actions.yaml [new file with mode: 0644]
juju-charms/layers/vyos-proxy/actions/ping [new file with mode: 0755]
juju-charms/layers/vyos-proxy/config.yaml [new file with mode: 0644]
juju-charms/layers/vyos-proxy/copyright [new file with mode: 0644]
juju-charms/layers/vyos-proxy/icon.svg [new file with mode: 0644]
juju-charms/layers/vyos-proxy/layer.yaml [new file with mode: 0644]
juju-charms/layers/vyos-proxy/metadata.yaml [new file with mode: 0644]
juju-charms/layers/vyos-proxy/reactive/__init__.py [new file with mode: 0644]
juju-charms/layers/vyos-proxy/reactive/vyos_proxy.py [new file with mode: 0644]
juju-charms/layers/vyos-proxy/requirements.txt [new file with mode: 0644]
juju-charms/layers/vyos-proxy/revision [new file with mode: 0644]
juju-charms/layers/vyos-proxy/tox.ini [new file with mode: 0644]
juju-charms/layers/vyos-proxy/wheelhouse.txt [new file with mode: 0644]
juju-env.sh [deleted file]
layers/netutils/LICENSE [deleted file]
layers/netutils/README.md [deleted file]
layers/netutils/actions.yaml [deleted file]
layers/netutils/actions/dig [deleted file]
layers/netutils/actions/iperf [deleted file]
layers/netutils/actions/nmap [deleted file]
layers/netutils/actions/ping [deleted file]
layers/netutils/actions/traceroute [deleted file]
layers/netutils/config.yaml [deleted file]
layers/netutils/icon.svg [deleted file]
layers/netutils/layer.yaml [deleted file]
layers/netutils/metadata.yaml [deleted file]
layers/netutils/reactive/layer_netutils.py [deleted file]
layers/netutils/tests/00-setup [deleted file]
layers/netutils/tests/10-deploy [deleted file]
layers/pingpong/README.md [deleted file]
layers/pingpong/actions.yaml [deleted file]
layers/pingpong/actions/get-rate [deleted file]
layers/pingpong/actions/get-server [deleted file]
layers/pingpong/actions/get-state [deleted file]
layers/pingpong/actions/get-stats [deleted file]
layers/pingpong/actions/set-rate [deleted file]
layers/pingpong/actions/set-server [deleted file]
layers/pingpong/actions/start-traffic [deleted file]
layers/pingpong/actions/stop-traffic [deleted file]
layers/pingpong/config.yaml [deleted file]
layers/pingpong/icon.svg [deleted file]
layers/pingpong/layer.yaml [deleted file]
layers/pingpong/metadata.yaml [deleted file]
layers/pingpong/reactive/pingpong.py [deleted file]
layers/pingpong/tests/00-setup [deleted file]
layers/pingpong/tests/10-deploy [deleted file]
layers/vyos-proxy/Makefile [deleted file]
layers/vyos-proxy/README.md [deleted file]
layers/vyos-proxy/actions.yaml [deleted file]
layers/vyos-proxy/actions/ping [deleted file]
layers/vyos-proxy/config.yaml [deleted file]
layers/vyos-proxy/copyright [deleted file]
layers/vyos-proxy/icon.svg [deleted file]
layers/vyos-proxy/layer.yaml [deleted file]
layers/vyos-proxy/metadata.yaml [deleted file]
layers/vyos-proxy/reactive/__init__.py [deleted file]
layers/vyos-proxy/reactive/vyos_proxy.py [deleted file]
layers/vyos-proxy/requirements.txt [deleted file]
layers/vyos-proxy/revision [deleted file]
layers/vyos-proxy/tox.ini [deleted file]
layers/vyos-proxy/wheelhouse.txt [deleted file]

diff --git a/.gitignore b/.gitignore
deleted file mode 100644 (file)
index 9421a45..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-builds/
-deps/
diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index a579390..0000000
--- a/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-#   Copyright 2016 RIFT.io Inc
-#
-#   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.
-#
-#
-
-BUILD_DIR = .
-
-CHARMS:= vpe-router vyos-proxy pingpong flownac sandvine-pts-proxy
-CHARM_SRC_DIR := layers
-CHARM_BUILD_DIR := $(BUILD_DIR)/builds
-
-CHARM_SRC_DIRS := $(addprefix $(CHARM_SRC_DIR)/, $(CHARMS))
-CHARM_BUILD_DIRS := $(addprefix $(CHARM_BUILD_DIR)/, $(CHARMS))
-
-all: $(CHARM_BUILD_DIRS)
-
-clean:
-       -@ $(RM) -rf $(CHARM_BUILD_DIR)
-
-$(CHARM_BUILD_DIR)/%: $(CHARM_SRC_DIR)/%
-       charm-build -o $(BUILD_DIR) $<
diff --git a/README.md b/README.md
deleted file mode 100644 (file)
index 6eaf43f..0000000
--- a/README.md
+++ /dev/null
@@ -1,79 +0,0 @@
-# Juju Charm usage and development
-
-This document is intended to provide a brief overview of the components included
-in this repository as well as recommendations for how to develop, build, and
-publish charms.
-
-Please read the [develper geting started guide](https://jujucharms.com/docs/2.0/developer-getting-started) before proceeding.
-
-## Directory structure
-
-```
-.
-├── builds
-│   â””── vpe-router
-├── interfaces
-├── layers
-│   â””── vpe-router
-└── module-blueprints
-```
-
-The source code of a charm is referred to as a "layer". This layer is compiled
-into a charm and placed in the `builds/` directory. Interfaces, currently
-unused in this context, extend relationships between applications.
-
-## Development workflow
-### Prepare your build environment
-```
-# Source the environment variables JUJU_REPOSITORY, INTERFACE_PATH, and
-# LAYER_PATH, which are needed to build a charm. You could also place these
-# in your $HOME/.bashrc
-$ source juju-env.sh
-```
-#### Install the `charm` command, either via apt:
-
-```
-$ sudo apt install charm
-```
-
-or with [snap](http://snapcraft.io/)
-
-```
-$ snap install charm --edge
-```
-
-To build a charm, simply run `charm build` inside of a layer.
-```
-$ cd $LAYER_PATH/vpe-router
-$ charm build
-$ charm deploy $JUJU_REPOSITORY/builds/vpe-router
-```
-
-## Publishing to jujucharms.com
-
-Publishing to the Juju Charm store requires a launchpad login. With that, login
-to [jujucharms.com](http://www.jujucharms.com/).
-
-Next, you'll use the charm command to publish your compiled charm. This will
-put the charm into the store where it can be used by anyone with access.
-
-For example, if I wanted to publish the latest version of the vpe-router charm:
-
-# Step 1: Upload the charm to the "unpublished" channel
-```
-$ cd $JUJU_REPOSITORY/builds
-$ charm push vpe-router/ cs:~aisrael/vpe-router
-url: cs:~aisrael/vpe-router-0
-channel: unpublished
-```
-
-# There are four channels to release a charm: edge, beta, candidate, and stable
-```
-$ charm release cs:~aisrael/vpe-router-0 --channel=edge
-url: cs:~aisrael/vpe-router-0
-channel: edge
-```
-The charm can then be deployed directly from the charm store:
-```
-$ juju deploy cs:~aisrael/vpe-router --channel=edge
-```
diff --git a/juju-charms/Makefile b/juju-charms/Makefile
new file mode 100644 (file)
index 0000000..a579390
--- /dev/null
@@ -0,0 +1,33 @@
+#
+#   Copyright 2016 RIFT.io Inc
+#
+#   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.
+#
+#
+
+BUILD_DIR = .
+
+CHARMS:= vpe-router vyos-proxy pingpong flownac sandvine-pts-proxy
+CHARM_SRC_DIR := layers
+CHARM_BUILD_DIR := $(BUILD_DIR)/builds
+
+CHARM_SRC_DIRS := $(addprefix $(CHARM_SRC_DIR)/, $(CHARMS))
+CHARM_BUILD_DIRS := $(addprefix $(CHARM_BUILD_DIR)/, $(CHARMS))
+
+all: $(CHARM_BUILD_DIRS)
+
+clean:
+       -@ $(RM) -rf $(CHARM_BUILD_DIR)
+
+$(CHARM_BUILD_DIR)/%: $(CHARM_SRC_DIR)/%
+       charm-build -o $(BUILD_DIR) $<
diff --git a/juju-charms/README.md b/juju-charms/README.md
new file mode 100644 (file)
index 0000000..6eaf43f
--- /dev/null
@@ -0,0 +1,79 @@
+# Juju Charm usage and development
+
+This document is intended to provide a brief overview of the components included
+in this repository as well as recommendations for how to develop, build, and
+publish charms.
+
+Please read the [develper geting started guide](https://jujucharms.com/docs/2.0/developer-getting-started) before proceeding.
+
+## Directory structure
+
+```
+.
+├── builds
+│   â””── vpe-router
+├── interfaces
+├── layers
+│   â””── vpe-router
+└── module-blueprints
+```
+
+The source code of a charm is referred to as a "layer". This layer is compiled
+into a charm and placed in the `builds/` directory. Interfaces, currently
+unused in this context, extend relationships between applications.
+
+## Development workflow
+### Prepare your build environment
+```
+# Source the environment variables JUJU_REPOSITORY, INTERFACE_PATH, and
+# LAYER_PATH, which are needed to build a charm. You could also place these
+# in your $HOME/.bashrc
+$ source juju-env.sh
+```
+#### Install the `charm` command, either via apt:
+
+```
+$ sudo apt install charm
+```
+
+or with [snap](http://snapcraft.io/)
+
+```
+$ snap install charm --edge
+```
+
+To build a charm, simply run `charm build` inside of a layer.
+```
+$ cd $LAYER_PATH/vpe-router
+$ charm build
+$ charm deploy $JUJU_REPOSITORY/builds/vpe-router
+```
+
+## Publishing to jujucharms.com
+
+Publishing to the Juju Charm store requires a launchpad login. With that, login
+to [jujucharms.com](http://www.jujucharms.com/).
+
+Next, you'll use the charm command to publish your compiled charm. This will
+put the charm into the store where it can be used by anyone with access.
+
+For example, if I wanted to publish the latest version of the vpe-router charm:
+
+# Step 1: Upload the charm to the "unpublished" channel
+```
+$ cd $JUJU_REPOSITORY/builds
+$ charm push vpe-router/ cs:~aisrael/vpe-router
+url: cs:~aisrael/vpe-router-0
+channel: unpublished
+```
+
+# There are four channels to release a charm: edge, beta, candidate, and stable
+```
+$ charm release cs:~aisrael/vpe-router-0 --channel=edge
+url: cs:~aisrael/vpe-router-0
+channel: edge
+```
+The charm can then be deployed directly from the charm store:
+```
+$ juju deploy cs:~aisrael/vpe-router --channel=edge
+```
diff --git a/juju-charms/juju-env.sh b/juju-charms/juju-env.sh
new file mode 100644 (file)
index 0000000..59fa9e7
--- /dev/null
@@ -0,0 +1,4 @@
+# Set the Juju env variables for building a layer
+export JUJU_REPOSITORY=`pwd`
+export INTERFACE_PATH=$JUJU_REPOSITORY/interfaces
+export LAYER_PATH=$JUJU_REPOSITORY/layers
diff --git a/juju-charms/layers/netutils/LICENSE b/juju-charms/layers/netutils/LICENSE
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 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.
diff --git a/juju-charms/layers/netutils/README.md b/juju-charms/layers/netutils/README.md
new file mode 100644 (file)
index 0000000..e8258c0
--- /dev/null
@@ -0,0 +1,64 @@
+# Overview
+
+This charm provides basic network utilities that can be run from a Juju-deployed
+machine.
+
+# Usage
+
+To deploy the charm:
+```bash
+$ juju deploy cs:~nfv/netutils
+```
+
+To run an action:
+```bash
+$ juju run-action netutils/0 ping destination=google.com
+$ juju run-action netutils/0 traceroute destination=google.com
+```
+
+To fetch the output of an action:
+```bash
+$ juju show-action-output 026b3d4c-0bb2-4818-8d24-9855936cdcdf
+results:
+  output: |
+    traceroute to google.com (216.58.198.78), 30 hops max, 60 byte packets
+     1  ec2-79-125-0-86.eu-west-1.compute.amazonaws.com (79.125.0.86)  1.431 ms  1.410 ms  1.380 ms
+     2  100.64.2.73 (100.64.2.73)  1.647 ms 100.64.2.103 (100.64.2.103)  1.247 ms 100.64.2.121 (100.64.2.121)  1.224 ms
+     3  100.64.0.232 (100.64.0.232)  1.296 ms 100.64.0.184 (100.64.0.184)  1.515 ms 100.64.0.234 (100.64.0.234)  1.079 ms
+     4  100.64.16.37 (100.64.16.37)  0.377 ms 100.64.16.49 (100.64.16.49)  0.347 ms 100.64.16.1 (100.64.16.1)  0.340 ms
+     5  176.32.107.12 (176.32.107.12)  0.739 ms 176.32.107.4 (176.32.107.4)  0.875 ms  0.748 ms
+     6  178.236.0.111 (178.236.0.111)  0.650 ms  0.641 ms  0.645 ms
+     7  72.14.215.85 (72.14.215.85)  0.544 ms  1.508 ms  1.498 ms
+     8  209.85.252.198 (209.85.252.198)  0.680 ms  0.659 ms  0.618 ms
+     9  64.233.174.27 (64.233.174.27)  0.690 ms  0.682 ms  0.634 ms
+    10  dub08s02-in-f14.1e100.net (216.58.198.78)  0.568 ms  0.560 ms  0.595 ms
+status: completed
+timing:
+  completed: 2016-06-29 14:50:04 +0000 UTC
+  enqueued: 2016-06-29 14:50:03 +0000 UTC
+  started: 2016-06-29 14:50:03 +0000 UTC
+```
+## iperf3
+
+Because iperf3 has a client and server component, the netutils charm can operate
+as both. Setting the iperf3 configuration value to True will start iperf3 in
+server mode, running as a daemon.
+```
+$ juju deploy cs:~nfv/netutils client
+$ juju deploy cs:~nfv/netutils server iperf3=True
+$ juju run-action client/0 iperf host=<ip of server> [...]
+```
+
+## Scale out Usage
+
+With great scalability comes great power, but please don't use this to DDoS anyone without their permission.
+
+## Known Limitations and Issues
+
+# Contact Information
+
+## Contributing to the charm
+
+  - The compiled charm can be found [here](https://www.jujucharms.com/u/nfv/netutils).
+  - [layer/netutils](https://osm.etsi.org/gitweb/?p=osm/juju-charms.git;a=summary/) contains the source of the layer.
+  - Please add any bugs or feature requests to the [bugzilla](https://osm.etsi.org/bugzilla/buglist.cgi?component=Juju-charms&list_id=426&product=OSM&resolution=---).
diff --git a/juju-charms/layers/netutils/actions.yaml b/juju-charms/layers/netutils/actions.yaml
new file mode 100644 (file)
index 0000000..f4f7884
--- /dev/null
@@ -0,0 +1,133 @@
+nmap:
+  description: "nmap a thing!"
+  params:
+    destination:
+      description: "destination to scan"
+      type: string
+  required:
+    - destination
+ping:
+  description: 'ping a thing!'
+  params:
+    count:
+      description: "Stop after sending count ECHO_REQUEST packets"
+      type: integer
+      default: 30
+    destination:
+      description: "destination of ping request"
+      type: string
+  required:
+    - destination
+traceroute:
+  description: 'trace a thing!'
+  params:
+    hops:
+      description: "Stop tracing after count hops"
+      type: integer
+      default: 30
+    destination:
+      description: "destination of traceroute request"
+      type: string
+  required:
+    - destination
+dig:
+  description: "DNS lookup"
+  params:
+    nsserver:
+      description: "The nameserver to lookup against."
+      type: string
+    host:
+      description: "The host to lookup"
+      type: string
+    type:
+      description: "The DNS record type to lookup"
+      type: string
+  required:
+    - host
+iperf:
+    description: ""
+    params:
+      host:
+        description: ""
+        type: string
+      port:
+        description: ""
+        type: integer
+        default: 5201
+      format:
+        description: ""
+        type: string
+      interval:
+        description: ""
+        type: string
+      affinity:
+        description: ""
+        type: string
+      udp:
+        description: "Use UDP rather than TCP"
+        type: boolean
+        default: False
+      bandwidth:
+        description: "Set the target bandwidth to n bits/sec (default 1Mbit/sec for UDP, unlimited for TCP)"
+        type: integer
+        default: 1
+      time:
+        description: "Time, in seconds, to transmit for."
+        type: integer
+        default: 10
+      blockcount:
+        description: "The number of blocks to transmit"
+        type: integer
+      length:
+        description: "The length of buffer to read or write (default 128KB for TCP, 8KB for UDP)"
+        type: integer
+      parallel:
+        description: "The number of parallel client streams to run"
+        type: integer
+      reverse:
+        description: "Run in reverse mode (server sends, client receives)."
+        type: boolean
+        default: false
+      window:
+        description: "Window size/socket buffer size."
+        type: integer
+      bind:
+        description: "Bind to a specific interface or multicast address"
+        type: string
+      mss:
+        description: "Set the TCP maximum segment size (MTU - 40 bytes)"
+        type: integer
+      no-delay:
+        description: "Set the TCP no delay, disabling Nagle's algorithm."
+        type: boolean
+        default: false
+      ipv4:
+        description: "Only use IPv4"
+        type: boolean
+        default: false
+      ipv6:
+        description: "Only use IPv6"
+        type: boolean
+        default: false
+      tos:
+        description: "Set the IP 'type of service'"
+        type: integer
+      flowlabel:
+        description: "Set the IPv6 flow label (linux-only)"
+        type: string
+      zerocopy:
+        description: "Use a 'zero copy' method of sending data, such as sendfile(s), instead of the usual write(2)."
+        type: boolean
+        default: false
+      omit:
+        description: "Omit the first n seconds of the test, to skip past the TCP slow-start period."
+        type: integer
+      title:
+        description: "Prefix every output line with this string."
+        type: string
+      congestion:
+        description: "Set the linux congestion control algorithm."
+        type: string
+
+    required:
+      - host
diff --git a/juju-charms/layers/netutils/actions/dig b/juju-charms/layers/netutils/actions/dig
new file mode 100755 (executable)
index 0000000..736a406
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.dig')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/netutils/actions/iperf b/juju-charms/layers/netutils/actions/iperf
new file mode 100755 (executable)
index 0000000..750028e
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.iperf3')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/netutils/actions/nmap b/juju-charms/layers/netutils/actions/nmap
new file mode 100755 (executable)
index 0000000..ede4f5b
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.nmap')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/netutils/actions/ping b/juju-charms/layers/netutils/actions/ping
new file mode 100755 (executable)
index 0000000..9850fe7
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.ping')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/netutils/actions/traceroute b/juju-charms/layers/netutils/actions/traceroute
new file mode 100755 (executable)
index 0000000..229ed32
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.traceroute')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/netutils/config.yaml b/juju-charms/layers/netutils/config.yaml
new file mode 100644 (file)
index 0000000..6101063
--- /dev/null
@@ -0,0 +1,5 @@
+options:
+    iperf3:
+        type: boolean
+        default: false
+        description: "Enabling this option will start iperf3 in server mode."
diff --git a/juju-charms/layers/netutils/icon.svg b/juju-charms/layers/netutils/icon.svg
new file mode 100644 (file)
index 0000000..e092eef
--- /dev/null
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
+\r
+<svg\r
+   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+   xmlns:cc="http://creativecommons.org/ns#"\r
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+   xmlns:svg="http://www.w3.org/2000/svg"\r
+   xmlns="http://www.w3.org/2000/svg"\r
+   xmlns:xlink="http://www.w3.org/1999/xlink"\r
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
+   width="96"\r
+   height="96"\r
+   id="svg6517"\r
+   version="1.1"\r
+   inkscape:version="0.48+devel r12274"\r
+   sodipodi:docname="Juju_charm_icon_template.svg">\r
+  <defs\r
+     id="defs6519">\r
+    <linearGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#Background"\r
+       id="linearGradient6461"\r
+       gradientUnits="userSpaceOnUse"\r
+       x1="0"\r
+       y1="970.29498"\r
+       x2="144"\r
+       y2="970.29498"\r
+       gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />\r
+    <linearGradient\r
+       id="Background">\r
+      <stop\r
+         id="stop4178"\r
+         offset="0"\r
+         style="stop-color:#b8b8b8;stop-opacity:1" />\r
+      <stop\r
+         id="stop4180"\r
+         offset="1"\r
+         style="stop-color:#c9c9c9;stop-opacity:1" />\r
+    </linearGradient>\r
+    <filter\r
+       style="color-interpolation-filters:sRGB;"\r
+       inkscape:label="Inner Shadow"\r
+       id="filter1121">\r
+      <feFlood\r
+         flood-opacity="0.59999999999999998"\r
+         flood-color="rgb(0,0,0)"\r
+         result="flood"\r
+         id="feFlood1123" />\r
+      <feComposite\r
+         in="flood"\r
+         in2="SourceGraphic"\r
+         operator="out"\r
+         result="composite1"\r
+         id="feComposite1125" />\r
+      <feGaussianBlur\r
+         in="composite1"\r
+         stdDeviation="1"\r
+         result="blur"\r
+         id="feGaussianBlur1127" />\r
+      <feOffset\r
+         dx="0"\r
+         dy="2"\r
+         result="offset"\r
+         id="feOffset1129" />\r
+      <feComposite\r
+         in="offset"\r
+         in2="SourceGraphic"\r
+         operator="atop"\r
+         result="composite2"\r
+         id="feComposite1131" />\r
+    </filter>\r
+    <filter\r
+       style="color-interpolation-filters:sRGB;"\r
+       inkscape:label="Drop Shadow"\r
+       id="filter950">\r
+      <feFlood\r
+         flood-opacity="0.25"\r
+         flood-color="rgb(0,0,0)"\r
+         result="flood"\r
+         id="feFlood952" />\r
+      <feComposite\r
+         in="flood"\r
+         in2="SourceGraphic"\r
+         operator="in"\r
+         result="composite1"\r
+         id="feComposite954" />\r
+      <feGaussianBlur\r
+         in="composite1"\r
+         stdDeviation="1"\r
+         result="blur"\r
+         id="feGaussianBlur956" />\r
+      <feOffset\r
+         dx="0"\r
+         dy="1"\r
+         result="offset"\r
+         id="feOffset958" />\r
+      <feComposite\r
+         in="SourceGraphic"\r
+         in2="offset"\r
+         operator="over"\r
+         result="composite2"\r
+         id="feComposite960" />\r
+    </filter>\r
+    <clipPath\r
+       clipPathUnits="userSpaceOnUse"\r
+       id="clipPath873">\r
+      <g\r
+         transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"\r
+         id="g875"\r
+         inkscape:label="Layer 1"\r
+         style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">\r
+        <path\r
+           style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"\r
+           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"\r
+           id="path877"\r
+           inkscape:connector-curvature="0"\r
+           sodipodi:nodetypes="sssssssss" />\r
+      </g>\r
+    </clipPath>\r
+    <filter\r
+       inkscape:collect="always"\r
+       id="filter891"\r
+       inkscape:label="Badge Shadow">\r
+      <feGaussianBlur\r
+         inkscape:collect="always"\r
+         stdDeviation="0.71999962"\r
+         id="feGaussianBlur893" />\r
+    </filter>\r
+  </defs>\r
+  <sodipodi:namedview\r
+     id="base"\r
+     pagecolor="#ffffff"\r
+     bordercolor="#666666"\r
+     borderopacity="1.0"\r
+     inkscape:pageopacity="0.0"\r
+     inkscape:pageshadow="2"\r
+     inkscape:zoom="4.0745362"\r
+     inkscape:cx="18.514671"\r
+     inkscape:cy="49.018169"\r
+     inkscape:document-units="px"\r
+     inkscape:current-layer="layer1"\r
+     showgrid="true"\r
+     fit-margin-top="0"\r
+     fit-margin-left="0"\r
+     fit-margin-right="0"\r
+     fit-margin-bottom="0"\r
+     inkscape:window-width="1920"\r
+     inkscape:window-height="1029"\r
+     inkscape:window-x="0"\r
+     inkscape:window-y="24"\r
+     inkscape:window-maximized="1"\r
+     showborder="true"\r
+     showguides="true"\r
+     inkscape:guide-bbox="true"\r
+     inkscape:showpageshadow="false">\r
+    <inkscape:grid\r
+       type="xygrid"\r
+       id="grid821" />\r
+    <sodipodi:guide\r
+       orientation="1,0"\r
+       position="16,48"\r
+       id="guide823" />\r
+    <sodipodi:guide\r
+       orientation="0,1"\r
+       position="64,80"\r
+       id="guide825" />\r
+    <sodipodi:guide\r
+       orientation="1,0"\r
+       position="80,40"\r
+       id="guide827" />\r
+    <sodipodi:guide\r
+       orientation="0,1"\r
+       position="64,16"\r
+       id="guide829" />\r
+  </sodipodi:namedview>\r
+  <metadata\r
+     id="metadata6522">\r
+    <rdf:RDF>\r
+      <cc:Work\r
+         rdf:about="">\r
+        <dc:format>image/svg+xml</dc:format>\r
+        <dc:type\r
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
+        <dc:title></dc:title>\r
+      </cc:Work>\r
+    </rdf:RDF>\r
+  </metadata>\r
+  <g\r
+     inkscape:label="BACKGROUND"\r
+     inkscape:groupmode="layer"\r
+     id="layer1"\r
+     transform="translate(268,-635.29076)"\r
+     style="display:inline">\r
+    <path\r
+       style="fill:url(#linearGradient6461);fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"\r
+       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"\r
+       id="path6455"\r
+       inkscape:connector-curvature="0"\r
+       sodipodi:nodetypes="sssssssss" />\r
+  </g>\r
+  <g\r
+     inkscape:groupmode="layer"\r
+     id="layer3"\r
+     inkscape:label="PLACE YOUR PICTOGRAM HERE"\r
+     style="display:inline" />\r
+  <g\r
+     inkscape:groupmode="layer"\r
+     id="layer2"\r
+     inkscape:label="BADGE"\r
+     style="display:none"\r
+     sodipodi:insensitive="true">\r
+    <g\r
+       style="display:inline"\r
+       transform="translate(-340.00001,-581)"\r
+       id="g4394"\r
+       clip-path="none">\r
+      <g\r
+         id="g855">\r
+        <g\r
+           inkscape:groupmode="maskhelper"\r
+           id="g870"\r
+           clip-path="url(#clipPath873)"\r
+           style="opacity:0.6;filter:url(#filter891)">\r
+          <path\r
+             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             sodipodi:ry="12"\r
+             sodipodi:rx="12"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:cx="252"\r
+             id="path844"\r
+             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"\r
+             sodipodi:type="arc" />\r
+        </g>\r
+        <g\r
+           id="g862">\r
+          <path\r
+             sodipodi:type="arc"\r
+             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"\r
+             id="path4398"\r
+             sodipodi:cx="252"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:rx="12"\r
+             sodipodi:ry="12"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />\r
+          <path\r
+             transform="matrix(1.25,0,0,1.25,33,-100.45273)"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             sodipodi:ry="12"\r
+             sodipodi:rx="12"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:cx="252"\r
+             id="path4400"\r
+             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"\r
+             sodipodi:type="arc" />\r
+          <path\r
+             sodipodi:type="star"\r
+             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"\r
+             id="path4459"\r
+             sodipodi:sides="5"\r
+             sodipodi:cx="666.19574"\r
+             sodipodi:cy="589.50385"\r
+             sodipodi:r1="7.2431178"\r
+             sodipodi:r2="4.3458705"\r
+             sodipodi:arg1="1.0471976"\r
+             sodipodi:arg2="1.6755161"\r
+             inkscape:flatsided="false"\r
+             inkscape:rounded="0.1"\r
+             inkscape:randomized="0"\r
+             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"\r
+             transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />\r
+        </g>\r
+      </g>\r
+    </g>\r
+  </g>\r
+</svg>\r
diff --git a/juju-charms/layers/netutils/layer.yaml b/juju-charms/layers/netutils/layer.yaml
new file mode 100644 (file)
index 0000000..e13c81a
--- /dev/null
@@ -0,0 +1,8 @@
+repo: git@github.com:AdamIsrael/layer-netutils.git
+includes: ['layer:basic', 'layer:sshproxy']
+options:
+  basic:
+    packages:
+      - traceroute
+      - nmap
+      - iperf3
diff --git a/juju-charms/layers/netutils/metadata.yaml b/juju-charms/layers/netutils/metadata.yaml
new file mode 100644 (file)
index 0000000..c42d963
--- /dev/null
@@ -0,0 +1,15 @@
+name: netutils
+summary: A suite of network-related utilities.
+maintainer: Adam Israel <adam.israel@canonical.com>
+description: |
+  A suite of network-related utilities, such as ping and traceroute, that
+  can be deployed into a data center in order to diagnose connectivity issues.
+tags:
+  # https://jujucharms.com/docs/stable/authors-charm-metadata
+  - ops
+  - network
+  - performance
+series:
+  - trusty
+  - xenial
+subordinate: false
diff --git a/juju-charms/layers/netutils/reactive/layer_netutils.py b/juju-charms/layers/netutils/reactive/layer_netutils.py
new file mode 100644 (file)
index 0000000..1fd4cb2
--- /dev/null
@@ -0,0 +1,137 @@
+from charmhelpers.core.hookenv import (
+    action_get,
+    action_fail,
+    action_set,
+    config,
+    log,
+    status_set,
+)
+
+from charms.reactive import (
+    remove_state as remove_flag,
+    set_state as set_flag,
+    when,
+    when_not,
+)
+import charms.sshproxy
+from subprocess import CalledProcessError
+
+
+@when_not('netutils.ready')
+def ready():
+    status_set('active', 'Ready!')
+    set_flag('netutils.ready')
+
+
+@when('actions.dig')
+def dig():
+    err = ''
+    try:
+        nsserver = action_get('nsserver')
+        host = action_get('host')
+        nstype = action_get('type')
+        cmd = "dig"
+
+        if nsserver:
+            cmd += " @{}".format(nsserver)
+        if host:
+            cmd += " {}".format(host)
+        else:
+            action_fail('Hostname required.')
+        if nstype:
+            cmd += " -t {}".format(nstype)
+
+        result, err = charms.sshproxy._run(cmd)
+    except:
+        action_fail('dig command failed:' + err)
+    else:
+        action_set({'outout': result})
+    finally:
+        remove_flag('actions.dig')
+
+
+@when('actions.nmap')
+def nmap():
+    err = ''
+    try:
+        result, err = charms.sshproxy._run(
+            'nmap {}'.format(action_get('destination'))
+        )
+    except:
+        action_fail('nmap command failed:' + err)
+    else:
+        action_set({'outout': result})
+    finally:
+        remove_flag('actions.nmap')
+
+
+@when('actions.ping')
+def ping():
+    err = ''
+    try:
+        result, err = charms.sshproxy._run('ping -qc {} {}'.format(
+            action_get('count'), action_get('destination'))
+        )
+
+    except:
+        action_fail('ping command failed:' + err)
+    else:
+        # Here you can send results back from ping, if you had time to parse it
+        action_set({'output': result})
+    finally:
+        remove_flag('actions.ping')
+
+
+@when('actions.traceroute')
+def traceroute():
+    try:
+        result, err = charms.sshproxy._run(
+            'traceroute -m {} {}'.format(
+                    action_get('hops'),
+                    action_get('destination')
+            )
+        )
+    except:
+        action_fail('traceroute command failed')
+    else:
+        # Here you can send results back from ping, if you had time to parse it
+        action_set({'output': result})
+    finally:
+        remove_flag('actions.traceroute')
+
+
+@when('actions.iperf3')
+def iperf3():
+    err = ''
+    try:
+        # TODO: read all the flags via action_get and build the
+        # proper command line to run iperf3
+        host = action_get('host')
+
+        cmd = 'iperf3 -c {} --json'.format(host)
+        result, err = charms.sshproxy._run(cmd)
+    except CalledProcessError as e:
+        action_fail('iperf3 command failed:' + e.output)
+    else:
+        action_set({'outout': result})
+    finally:
+        remove_flag('actions.iperf3')
+
+
+@when('config.changed')
+def config_changed():
+    """ Handle configuration changes """
+    cfg = config()
+    if cfg.changed('iperf3'):
+        if cfg['iperf3']:
+            # start iperf in server + daemon mode
+            cmd = "iperf3 -s -D"
+        else:
+            cmd = "killall iperf3"
+        try:
+            charms.sshproxy._run(cmd)
+            log("iperf3 stopped.")
+        except CalledProcessError:
+            log("iperf3 not running.")
+        else:
+            log("iperf3 started.")
diff --git a/juju-charms/layers/netutils/tests/00-setup b/juju-charms/layers/netutils/tests/00-setup
new file mode 100755 (executable)
index 0000000..f0616a5
--- /dev/null
@@ -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
diff --git a/juju-charms/layers/netutils/tests/10-deploy b/juju-charms/layers/netutils/tests/10-deploy
new file mode 100755 (executable)
index 0000000..ef269cd
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/python3
+
+import amulet
+import requests
+import unittest
+
+
+class TestCharm(unittest.TestCase):
+    def setUp(self):
+        self.d = amulet.Deployment()
+
+        self.d.add('layer-netutils')
+        self.d.expose('layer-netutils')
+
+        self.d.setup(timeout=900)
+        self.d.sentry.wait()
+
+        self.unit = self.d.sentry['layer-netutils'][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
diff --git a/juju-charms/layers/pingpong/README.md b/juju-charms/layers/pingpong/README.md
new file mode 100644 (file)
index 0000000..3bec243
--- /dev/null
@@ -0,0 +1,163 @@
+# Overview
+
+This repository contains the [Juju] layer that represents a working example of a proxy charm.
+
+# What is a proxy charm?
+
+A proxy charm is a limited type of charm that does not interact with software running on the same host, such as controlling and configuring a remote device (a static VM image, a router/switch, etc.). It cannot take advantage of some of Juju's key features, such as [scaling], [relations], and [leadership].
+
+Proxy charms are primarily a stop-gap, intended to prototype quickly, with the end goal being to develop it into a full-featured charm, which installs and executes code on the same machine as the charm is running.
+
+# Usage
+
+```bash
+# Clone this repository
+git clone https://osm.etsi.org/gerrit/osm/juju-charms
+cd juju-charms
+
+# Setup environment variables
+source juju-env.sh
+
+cd layers/pingpong
+charm build
+
+# Examine the built charm
+cd ../../builds/pingpong
+ls
+actions       config.yaml  icon.svg    metadata.yaml     tests
+actions.yaml  copyright    layer.yaml  reactive          tox.ini
+bin           deps         lib         README.md         wheelhouse
+builds        hooks        Makefile    requirements.txt
+
+```
+
+You can view a screencast of this: https://asciinema.org/a/96738
+
+The `charm build` process combines this pingpong layer with each layer that it
+has included in the `metadata.yaml` file, along with their various dependencies.
+
+This built charm is what will then be used by the SO to communicate with the
+VNF.
+
+# Configuration
+
+The pingpong charm has several configuration properties that can be set via
+the SO:
+
+- ssh-hostname
+- ssh-username
+- ssh-password
+- ssh-private-key
+- mode
+
+The ssh-* keys are included by the `sshproxy` layer, and enable the charm to
+connect to the VNF image.
+
+The mode key must be one of two values: `ping` or `pong`. This informs the
+charm as to which function it is serving.
+
+# Contact Information
+For support, please send an email to the [OSM Tech] list.
+
+
+[OSM Tech]: mailto:OSM_TECH@list.etsi.org
+[Juju]: https://jujucharms.com/about
+[configure]: https://jujucharms.com/docs/2.0/charms-config
+[scaling]: https://jujucharms.com/docs/2.0/charms-scaling
+[relations]: https://jujucharms.com/docs/2.0/charms-relations
+[leadership]: https://jujucharms.com/docs/2.0/developer-leadership
+[created your charm]: https://jujucharms.com/docs/2.0/developer-getting-started
+
+
+
+
+
+-----
+
+
+# Integration
+
+After you've [created your charm], open `interfaces.yaml` and add
+`layer:sshproxy` to the includes stanza, as shown below:
+```
+includes: ['layer:basic', 'layer:sshproxy']
+```
+
+## Reactive states
+
+This layer will set the following states:
+
+- `sshproxy.configured` This state is set when SSH credentials have been supplied to the charm.
+
+
+## Example
+In `reactive/mycharm.py`, you can add logic to execute commands over SSH. This
+example is run via a `start` action, and starts a service running on a remote
+host.
+```
+...
+import charms.sshproxy
+
+
+@when('sshproxy.configured')
+@when('actions.start')
+def start():
+    """ Execute's the command, via the start action` using the
+    configured SSH credentials
+    """
+    sshproxy.ssh("service myservice start")
+
+```
+
+## Actions
+This layer includes a built-in `run` action useful for debugging or running arbitrary commands:
+
+```
+$ juju run-action mycharm/0 run command=hostname
+Action queued with id: 014b72f3-bc02-4ecb-8d38-72bce03bbb63
+
+$ juju show-action-output 014b72f3-bc02-4ecb-8d38-72bce03bbb63
+results:
+  output: juju-66a5f3-11
+status: completed
+timing:
+  completed: 2016-10-27 19:53:49 +0000 UTC
+  enqueued: 2016-10-27 19:53:44 +0000 UTC
+  started: 2016-10-27 19:53:48 +0000 UTC
+
+```
+## Known Limitations and Issues
+
+### Security issues
+
+- Password and key-based authentications are supported, with the caveat that
+both (password and private key) are stored plaintext within the Juju controller.
+
+# Configuration and Usage
+
+This layer adds the following configuration options:
+- ssh-hostname
+- ssh-username
+- ssh-password
+- ssh-private-key
+
+Once  [configure] those values at any time. Once they are set, the `sshproxy.configured` state flag will be toggled:
+
+```
+juju deploy mycharm ssh-hostname=10.10.10.10 ssh-username=ubuntu ssh-password=yourpassword
+```
+or
+```
+juju deploy mycharm ssh-hostname=10.10.10.10 ssh-username=ubuntu ssh-private-key="cat `~/.ssh/id_rsa`"
+```
+
+
+# Contact Information
+Homepage: https://github.com/AdamIsrael/layer-sshproxy
+
+[Juju]: https://jujucharms.com/about
+[configure]: https://jujucharms.com/docs/2.0/charms-config
+[scaling]: https://jujucharms.com/docs/2.0/charms-scaling
+[relations]: https://jujucharms.com/docs/2.0/charms-relations
+[leadership]: https://jujucharms.com/docs/2.0/developer-leadership
+[created your charm]: https://jujucharms.com/docs/2.0/developer-getting-started
diff --git a/juju-charms/layers/pingpong/actions.yaml b/juju-charms/layers/pingpong/actions.yaml
new file mode 100644 (file)
index 0000000..a5928f1
--- /dev/null
@@ -0,0 +1,32 @@
+set-server:
+    description: "Set the target IP address and port"
+    params:
+        server-ip:
+            description: "IP on which the target service is listening."
+            type: string
+            default: ""
+        server-port:
+            description: "Port on which the target service is listening."
+            type: integer
+            default: 5555
+    required:
+        - server-ip
+set-rate:
+    description: "Set the rate of packet generation."
+    params:
+        rate:
+            description: "Packet rate."
+            type: integer
+            default: 5
+get-stats:
+    description: "Get the stats."
+get-state:
+    description: "Get the admin state of the target service."
+get-rate:
+    description: "Get the rate set on the target service."
+get-server:
+    description: "Get the target server and IP set"
+start-traffic:
+    description: "Start the traffic generator or echo."
+stop-traffic:
+    description: "Stop the traffic generator or echo."
diff --git a/juju-charms/layers/pingpong/actions/get-rate b/juju-charms/layers/pingpong/actions/get-rate
new file mode 100755 (executable)
index 0000000..959b3e9
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.get-rate')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/pingpong/actions/get-server b/juju-charms/layers/pingpong/actions/get-server
new file mode 100755 (executable)
index 0000000..52e0089
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.get-server')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/pingpong/actions/get-state b/juju-charms/layers/pingpong/actions/get-state
new file mode 100755 (executable)
index 0000000..446e8d7
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.get-state')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/pingpong/actions/get-stats b/juju-charms/layers/pingpong/actions/get-stats
new file mode 100755 (executable)
index 0000000..086afc2
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.get-stats')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/pingpong/actions/set-rate b/juju-charms/layers/pingpong/actions/set-rate
new file mode 100755 (executable)
index 0000000..8fb723e
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.set-rate')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/pingpong/actions/set-server b/juju-charms/layers/pingpong/actions/set-server
new file mode 100755 (executable)
index 0000000..d1e908f
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.set-server')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/pingpong/actions/start-traffic b/juju-charms/layers/pingpong/actions/start-traffic
new file mode 100755 (executable)
index 0000000..562ac4c
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.start-traffic')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/pingpong/actions/stop-traffic b/juju-charms/layers/pingpong/actions/stop-traffic
new file mode 100755 (executable)
index 0000000..9352b33
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.stop-traffic')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/pingpong/config.yaml b/juju-charms/layers/pingpong/config.yaml
new file mode 100644 (file)
index 0000000..437524e
--- /dev/null
@@ -0,0 +1,5 @@
+options:
+  mode:
+    type: string
+    default:
+    description: "The service type: [ping, pong]"
diff --git a/juju-charms/layers/pingpong/icon.svg b/juju-charms/layers/pingpong/icon.svg
new file mode 100644 (file)
index 0000000..e092eef
--- /dev/null
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
+\r
+<svg\r
+   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+   xmlns:cc="http://creativecommons.org/ns#"\r
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+   xmlns:svg="http://www.w3.org/2000/svg"\r
+   xmlns="http://www.w3.org/2000/svg"\r
+   xmlns:xlink="http://www.w3.org/1999/xlink"\r
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
+   width="96"\r
+   height="96"\r
+   id="svg6517"\r
+   version="1.1"\r
+   inkscape:version="0.48+devel r12274"\r
+   sodipodi:docname="Juju_charm_icon_template.svg">\r
+  <defs\r
+     id="defs6519">\r
+    <linearGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#Background"\r
+       id="linearGradient6461"\r
+       gradientUnits="userSpaceOnUse"\r
+       x1="0"\r
+       y1="970.29498"\r
+       x2="144"\r
+       y2="970.29498"\r
+       gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />\r
+    <linearGradient\r
+       id="Background">\r
+      <stop\r
+         id="stop4178"\r
+         offset="0"\r
+         style="stop-color:#b8b8b8;stop-opacity:1" />\r
+      <stop\r
+         id="stop4180"\r
+         offset="1"\r
+         style="stop-color:#c9c9c9;stop-opacity:1" />\r
+    </linearGradient>\r
+    <filter\r
+       style="color-interpolation-filters:sRGB;"\r
+       inkscape:label="Inner Shadow"\r
+       id="filter1121">\r
+      <feFlood\r
+         flood-opacity="0.59999999999999998"\r
+         flood-color="rgb(0,0,0)"\r
+         result="flood"\r
+         id="feFlood1123" />\r
+      <feComposite\r
+         in="flood"\r
+         in2="SourceGraphic"\r
+         operator="out"\r
+         result="composite1"\r
+         id="feComposite1125" />\r
+      <feGaussianBlur\r
+         in="composite1"\r
+         stdDeviation="1"\r
+         result="blur"\r
+         id="feGaussianBlur1127" />\r
+      <feOffset\r
+         dx="0"\r
+         dy="2"\r
+         result="offset"\r
+         id="feOffset1129" />\r
+      <feComposite\r
+         in="offset"\r
+         in2="SourceGraphic"\r
+         operator="atop"\r
+         result="composite2"\r
+         id="feComposite1131" />\r
+    </filter>\r
+    <filter\r
+       style="color-interpolation-filters:sRGB;"\r
+       inkscape:label="Drop Shadow"\r
+       id="filter950">\r
+      <feFlood\r
+         flood-opacity="0.25"\r
+         flood-color="rgb(0,0,0)"\r
+         result="flood"\r
+         id="feFlood952" />\r
+      <feComposite\r
+         in="flood"\r
+         in2="SourceGraphic"\r
+         operator="in"\r
+         result="composite1"\r
+         id="feComposite954" />\r
+      <feGaussianBlur\r
+         in="composite1"\r
+         stdDeviation="1"\r
+         result="blur"\r
+         id="feGaussianBlur956" />\r
+      <feOffset\r
+         dx="0"\r
+         dy="1"\r
+         result="offset"\r
+         id="feOffset958" />\r
+      <feComposite\r
+         in="SourceGraphic"\r
+         in2="offset"\r
+         operator="over"\r
+         result="composite2"\r
+         id="feComposite960" />\r
+    </filter>\r
+    <clipPath\r
+       clipPathUnits="userSpaceOnUse"\r
+       id="clipPath873">\r
+      <g\r
+         transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"\r
+         id="g875"\r
+         inkscape:label="Layer 1"\r
+         style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">\r
+        <path\r
+           style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"\r
+           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"\r
+           id="path877"\r
+           inkscape:connector-curvature="0"\r
+           sodipodi:nodetypes="sssssssss" />\r
+      </g>\r
+    </clipPath>\r
+    <filter\r
+       inkscape:collect="always"\r
+       id="filter891"\r
+       inkscape:label="Badge Shadow">\r
+      <feGaussianBlur\r
+         inkscape:collect="always"\r
+         stdDeviation="0.71999962"\r
+         id="feGaussianBlur893" />\r
+    </filter>\r
+  </defs>\r
+  <sodipodi:namedview\r
+     id="base"\r
+     pagecolor="#ffffff"\r
+     bordercolor="#666666"\r
+     borderopacity="1.0"\r
+     inkscape:pageopacity="0.0"\r
+     inkscape:pageshadow="2"\r
+     inkscape:zoom="4.0745362"\r
+     inkscape:cx="18.514671"\r
+     inkscape:cy="49.018169"\r
+     inkscape:document-units="px"\r
+     inkscape:current-layer="layer1"\r
+     showgrid="true"\r
+     fit-margin-top="0"\r
+     fit-margin-left="0"\r
+     fit-margin-right="0"\r
+     fit-margin-bottom="0"\r
+     inkscape:window-width="1920"\r
+     inkscape:window-height="1029"\r
+     inkscape:window-x="0"\r
+     inkscape:window-y="24"\r
+     inkscape:window-maximized="1"\r
+     showborder="true"\r
+     showguides="true"\r
+     inkscape:guide-bbox="true"\r
+     inkscape:showpageshadow="false">\r
+    <inkscape:grid\r
+       type="xygrid"\r
+       id="grid821" />\r
+    <sodipodi:guide\r
+       orientation="1,0"\r
+       position="16,48"\r
+       id="guide823" />\r
+    <sodipodi:guide\r
+       orientation="0,1"\r
+       position="64,80"\r
+       id="guide825" />\r
+    <sodipodi:guide\r
+       orientation="1,0"\r
+       position="80,40"\r
+       id="guide827" />\r
+    <sodipodi:guide\r
+       orientation="0,1"\r
+       position="64,16"\r
+       id="guide829" />\r
+  </sodipodi:namedview>\r
+  <metadata\r
+     id="metadata6522">\r
+    <rdf:RDF>\r
+      <cc:Work\r
+         rdf:about="">\r
+        <dc:format>image/svg+xml</dc:format>\r
+        <dc:type\r
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
+        <dc:title></dc:title>\r
+      </cc:Work>\r
+    </rdf:RDF>\r
+  </metadata>\r
+  <g\r
+     inkscape:label="BACKGROUND"\r
+     inkscape:groupmode="layer"\r
+     id="layer1"\r
+     transform="translate(268,-635.29076)"\r
+     style="display:inline">\r
+    <path\r
+       style="fill:url(#linearGradient6461);fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"\r
+       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"\r
+       id="path6455"\r
+       inkscape:connector-curvature="0"\r
+       sodipodi:nodetypes="sssssssss" />\r
+  </g>\r
+  <g\r
+     inkscape:groupmode="layer"\r
+     id="layer3"\r
+     inkscape:label="PLACE YOUR PICTOGRAM HERE"\r
+     style="display:inline" />\r
+  <g\r
+     inkscape:groupmode="layer"\r
+     id="layer2"\r
+     inkscape:label="BADGE"\r
+     style="display:none"\r
+     sodipodi:insensitive="true">\r
+    <g\r
+       style="display:inline"\r
+       transform="translate(-340.00001,-581)"\r
+       id="g4394"\r
+       clip-path="none">\r
+      <g\r
+         id="g855">\r
+        <g\r
+           inkscape:groupmode="maskhelper"\r
+           id="g870"\r
+           clip-path="url(#clipPath873)"\r
+           style="opacity:0.6;filter:url(#filter891)">\r
+          <path\r
+             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             sodipodi:ry="12"\r
+             sodipodi:rx="12"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:cx="252"\r
+             id="path844"\r
+             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"\r
+             sodipodi:type="arc" />\r
+        </g>\r
+        <g\r
+           id="g862">\r
+          <path\r
+             sodipodi:type="arc"\r
+             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"\r
+             id="path4398"\r
+             sodipodi:cx="252"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:rx="12"\r
+             sodipodi:ry="12"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />\r
+          <path\r
+             transform="matrix(1.25,0,0,1.25,33,-100.45273)"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             sodipodi:ry="12"\r
+             sodipodi:rx="12"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:cx="252"\r
+             id="path4400"\r
+             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"\r
+             sodipodi:type="arc" />\r
+          <path\r
+             sodipodi:type="star"\r
+             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"\r
+             id="path4459"\r
+             sodipodi:sides="5"\r
+             sodipodi:cx="666.19574"\r
+             sodipodi:cy="589.50385"\r
+             sodipodi:r1="7.2431178"\r
+             sodipodi:r2="4.3458705"\r
+             sodipodi:arg1="1.0471976"\r
+             sodipodi:arg2="1.6755161"\r
+             inkscape:flatsided="false"\r
+             inkscape:rounded="0.1"\r
+             inkscape:randomized="0"\r
+             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"\r
+             transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />\r
+        </g>\r
+      </g>\r
+    </g>\r
+  </g>\r
+</svg>\r
diff --git a/juju-charms/layers/pingpong/layer.yaml b/juju-charms/layers/pingpong/layer.yaml
new file mode 100644 (file)
index 0000000..833eea6
--- /dev/null
@@ -0,0 +1,4 @@
+includes:
+    - layer:basic
+    - layer:vnfproxy
+repo: https://osm.etsi.org/gerrit/osm/juju-charms
diff --git a/juju-charms/layers/pingpong/metadata.yaml b/juju-charms/layers/pingpong/metadata.yaml
new file mode 100644 (file)
index 0000000..1840743
--- /dev/null
@@ -0,0 +1,13 @@
+name: pingpong
+summary: <Fill in summary here>
+maintainer: Adam Israel <Adam.Israel@ronin>
+description: |
+  <Multi-line description here>
+tags:
+  # Replace "misc" with one or more whitelisted tags from this list:
+  # https://jujucharms.com/docs/stable/authors-charm-metadata
+  - misc
+subordinate: false
+series:
+    - trusty
+    - xenial
diff --git a/juju-charms/layers/pingpong/reactive/pingpong.py b/juju-charms/layers/pingpong/reactive/pingpong.py
new file mode 100644 (file)
index 0000000..b5a5db9
--- /dev/null
@@ -0,0 +1,272 @@
+from charmhelpers.core.hookenv import (
+    action_get,
+    action_fail,
+    action_set,
+    config,
+    status_set,
+)
+
+from charms.reactive import (
+    remove_state as remove_flag,
+    set_state as set_flag,
+    when,
+)
+import charms.sshproxy
+from subprocess import (
+    Popen,
+    CalledProcessError,
+    PIPE,
+)
+
+
+cfg = config()
+
+
+@when('config.changed')
+def config_changed():
+    if all(k in cfg for k in ['mode']):
+        if cfg['mode'] in ['ping', 'pong']:
+            set_flag('pingpong.configured')
+            status_set('active', 'ready!')
+            return
+    status_set('blocked', 'Waiting for configuration')
+
+
+def is_ping():
+    if cfg['mode'] == 'ping':
+        return True
+    return False
+
+
+def is_pong():
+    return not is_ping()
+
+
+def get_port():
+    port = 18888
+    if is_pong():
+        port = 18889
+    return port
+
+
+@when('pingpong.configured')
+@when('actions.start')
+def start():
+    try:
+        # Bring up the eth1 interface.
+        # The selinux label on the file needs to be set correctly
+        cmd = "sudo timeout 5 /sbin/restorecon -v /etc/sysconfig/network-scripts/ifcfg-eth1"
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        err = "{}".format(e)
+        action_fail('command failed: {}, errors: {}'.format(err, e.output))
+        remove_flag('actions.start')
+        return
+
+    try:
+        cmd =  "sudo timeout 30 /sbin/ifup eth1"
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+        remove_flag('actions.start')
+        return
+
+    try:
+        cmd =  "sudo timeout 30 /usr/bin/systemctl start {}". \
+              format(cfg['mode'])
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.start')
+
+
+@when('pingpong.configured')
+@when('actions.stop')
+def stop():
+    try:
+        # Enter the command to stop your service(s)
+        cmd = "sudo timeout 30 /usr/bin/systemctl stop {}".format(cfg['mode'])
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.stop')
+
+
+@when('pingpong.configured')
+@when('actions.restart')
+def restart():
+    try:
+        # Enter the command to restart your service(s)
+        cmd = "sudo timeout 30 /usr/bin/systemctl restart {}".format(cfg['mode'])
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.restart')
+
+
+@when('pingpong.configured')
+@when('actions.set-server')
+def set_server():
+    try:
+        # Get the target service info
+        target_ip = action_get('server-ip')
+        target_port = action_get('server-port')
+
+        data = '{{"ip" : "{}", "port" : {} }}'. \
+               format(target_ip, target_port)
+
+        cmd = format_curl(
+            'POST',
+            '/server',
+            data,
+        )
+
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.set-server')
+
+
+@when('pingpong.configured')
+@when('actions.set-rate')
+def set_rate():
+    try:
+        if is_ping():
+            rate = action_get('rate')
+            cmd = format_curl('POST', '/rate', '{{"rate" : {}}}'.format(rate))
+
+            result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        err = "{}".format(e)
+        action_fail('command failed: {}, errors: {}'.format(err, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.set-rate')
+
+
+@when('pingpong.configured')
+@when('actions.get-rate')
+def get_rate():
+    try:
+        if is_ping():
+            cmd = format_curl('GET', '/rate')
+
+            result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.get-rate')
+
+
+@when('pingpong.configured')
+@when('actions.get-state')
+def get_state():
+    try:
+        cmd = format_curl('GET', '/state')
+
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.get-state')
+
+
+@when('pingpong.configured')
+@when('actions.get-stats')
+def get_stats():
+    try:
+        cmd = format_curl('GET', '/stats')
+
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.get-stats')
+
+
+@when('pingpong.configured')
+@when('actions.start-traffic')
+def start_traffic():
+    try:
+        cmd = format_curl('POST', '/adminstatus/state', '{"enable" : true}')
+
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.start-traffic')
+
+
+@when('pingpong.configured')
+@when('actions.stop-traffic')
+def stop_traffic():
+    try:
+        cmd = format_curl('POST', '/adminstatus/state', '{"enable" : false}')
+
+        result, err = charms.sshproxy._run(cmd)
+    except Exception as e:
+        action_fail('command failed: {}, errors: {}'.format(e, e.output))
+    else:
+        action_set({'stdout': result,
+                    'errors': err})
+    finally:
+        remove_flag('actions.stop-traffic')
+
+
+def format_curl(method, path, data=None):
+    """ A utility function to build the curl command line. """
+
+    # method must be GET or POST
+    if method not in ['GET', 'POST']:
+        # Throw exception
+        return None
+
+    # Get our service info
+    host = '127.0.0.1'
+    port = get_port()
+    mode = cfg['mode']
+
+    cmd = ['curl',
+           # '-D', '/dev/stdout',
+           '-H', 'Accept: application/vnd.yang.data+xml',
+           '-H', 'Content-Type: application/vnd.yang.data+json',
+           '-X', method]
+
+    if method == "POST" and data:
+        cmd.append('-d')
+        cmd.append('{}'.format(data))
+
+    cmd.append(
+        'http://{}:{}/api/v1/{}{}'.format(host, port, mode, path)
+    )
+    return cmd
diff --git a/juju-charms/layers/pingpong/tests/00-setup b/juju-charms/layers/pingpong/tests/00-setup
new file mode 100755 (executable)
index 0000000..f0616a5
--- /dev/null
@@ -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
diff --git a/juju-charms/layers/pingpong/tests/10-deploy b/juju-charms/layers/pingpong/tests/10-deploy
new file mode 100755 (executable)
index 0000000..d1d4719
--- /dev/null
@@ -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('pingpong')
+        self.d.expose('pingpong')
+
+        self.d.setup(timeout=900)
+        self.d.sentry.wait()
+
+        self.unit = self.d.sentry['pingpong'][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()
diff --git a/juju-charms/layers/vyos-proxy/Makefile b/juju-charms/layers/vyos-proxy/Makefile
new file mode 100644 (file)
index 0000000..a1ad3a5
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/make
+
+all: lint unit_test
+
+
+.PHONY: clean
+clean:
+       @rm -rf .tox
+
+.PHONY: apt_prereqs
+apt_prereqs:
+       @# Need tox, but don't install the apt version unless we have to (don't want to conflict with pip)
+       @which tox >/dev/null || (sudo apt-get install -y python-pip && sudo pip install tox)
+
+.PHONY: lint
+lint: apt_prereqs
+       @tox --notest
+       @PATH=.tox/py34/bin:.tox/py35/bin flake8 $(wildcard hooks reactive lib unit_tests tests)
+       @charm proof
+
+.PHONY: unit_test
+unit_test: apt_prereqs
+       @echo Starting tests...
+       tox
diff --git a/juju-charms/layers/vyos-proxy/README.md b/juju-charms/layers/vyos-proxy/README.md
new file mode 100644 (file)
index 0000000..0337c83
--- /dev/null
@@ -0,0 +1,221 @@
+# 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][].
+
+### Charm Dependencies
+
+Each layer can include a `wheelhouse.txt` file with Python requirement lines.
+For example, this layer's `wheelhouse.txt` includes:
+
+```
+pip>=7.0.0,<8.0.0
+charmhelpers>=0.4.0,<1.0.0
+charms.reactive>=0.1.0,<2.0.0
+```
+
+All of these dependencies from each layer will be fetched (and updated) at build
+time and will be automatically installed by this base layer before any reactive
+handlers are run.
+
+Note that the `wheelhouse.txt` file is intended for **charm** dependencies only.
+That is, for libraries that the charm code itself needs to do its job of deploying
+and configuring the payload.  If the payload itself has Python dependencies, those
+should be handled separately, by the charm.
+
+See [PyPI][pypi charms.X] for packages under the `charms.` namespace which might
+be useful for your charm.
+
+### Layer Namespace
+
+Each layer has a reserved section in the `charms.layer.` Python package namespace,
+which it can populate by including a `lib/charms/layer/<layer-name>.py` file or
+by placing files under `lib/charms/layer/<layer-name>/`.  (If the layer name
+includes hyphens, replace them with underscores.)  These can be helpers that the
+layer uses internally, or it can expose classes or functions to be used by other
+layers to interact with that layer.
+
+For example, a layer named `foo` could include a `lib/charms/layer/foo.py` file
+with some helper functions that other layers could access using:
+
+```python
+from charms.layer.foo import my_helper
+```
+
+### Layer Options
+
+Any layer can define options in its `layer.yaml`.  Those options can then be set
+by other layers to change the behavior of your layer.  The options are defined
+using [jsonschema][], which is the same way that [action paramters][] are defined.
+
+For example, the `foo` layer could include the following option definitons:
+
+```yaml
+includes: ['layer:basic']
+defines:  # define some options for this layer (the layer "foo")
+  enable-bar:  # define an "enable-bar" option for this layer
+    description: If true, enable support for "bar".
+    type: boolean
+    default: false
+```
+
+A layer using `foo` could then set it:
+
+```yaml
+includes: ['layer:foo']
+options:
+  foo:  # setting options for the "foo" layer
+    enable-bar: true  # set the "enable-bar" option to true
+```
+
+The `foo` layer can then use the `charms.layer.options` helper to load the values
+for the options that it defined.  For example:
+
+```python
+from charms import layer
+
+@when('state')
+def do_thing():
+  layer_opts = layer.options('foo')  # load all of the options for the "foo" layer
+  if layer_opts['enable-bar']:  # check the value of the "enable-bar" option
+      hookenv.log("Bar is enabled")
+```
+
+You can also access layer options in other handlers, such as Bash, using
+the command-line interface:
+
+```bash
+. charms.reactive.sh
+
+@when 'state'
+function do_thing() {
+    if layer_option foo enable-bar; then
+        juju-log "Bar is enabled"
+        juju-log "bar-value is: $(layer_option foo bar-value)"
+    fi
+}
+
+reactive_handler_main
+```
+
+Note that options of type `boolean` will set the exit code, while other types
+will be printed out.
+
+# 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 supports the following options, which can be set in `layer.yaml`:
+
+  * **packages**  A list of system packages to be installed before the reactive
+    handlers are invoked.
+
+  * **use_venv**  If set to true, the charm dependencies from the various
+    layers' `wheelhouse.txt` files will be installed in a Python virtualenv
+    located at `$CHARM_DIR/../.venv`.  This keeps charm dependencies from
+    conflicting with payload dependencies, but you must take care to preserve
+    the environment and interpreter if using `execl` or `subprocess`.
+
+  * **include_system_packages**  If set to true and using a venv, include
+    the `--system-site-packages` options to make system Python libraries
+    visible within the venv.
+
+An example `layer.yaml` using these options might be:
+
+```yaml
+includes: ['layer:basic']
+options:
+  basic:
+    packages: ['git']
+    use_venv: true
+    include_system_packages: true
+```
+
+
+# Reactive States
+
+This layer will set the following states:
+
+  * **`config.changed`**  Any config option has changed from its previous value.
+    This state is cleared automatically at the end of each hook invocation.
+
+  * **`config.changed.<option>`** A specific config option has changed.
+    **`<option>`** will be replaced by the config option name from `config.yaml`.
+    This state is cleared automatically at the end of each hook invocation.
+
+  * **`config.set.<option>`** A specific config option has a True or non-empty
+    value set.  **`<option>`** will be replaced by the config option name from
+    `config.yaml`.  This state is cleared automatically at the end of each hook
+    invocation.
+
+  * **`config.default.<option>`** A specific config option is set to its
+    default value.  **`<option>`** will be replaced by the config option name
+    from `config.yaml`.  This state is cleared automatically at the end of
+    each hook invocation.
+
+An example using the config states would be:
+
+```python
+@when('config.changed.my-opt')
+def my_opt_changed():
+    update_config()
+    restart_service()
+```
+
+
+# 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
+[jsonschema]: http://json-schema.org/
+[action paramters]: https://jujucharms.com/docs/stable/authors-charm-actions
+[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
diff --git a/juju-charms/layers/vyos-proxy/actions.yaml b/juju-charms/layers/vyos-proxy/actions.yaml
new file mode 100644 (file)
index 0000000..2acc33d
--- /dev/null
@@ -0,0 +1,12 @@
+"ping":
+  "description": "ping a thing!"
+  "params":
+    "count":
+      "description": "Stop after sending count ECHO_REQUEST packets"
+      "type": "integer"
+      "default": !!int "30"
+    "destination":
+      "description": "destination of ping request"
+      "type": "string"
+  "required":
+  - "destination"
diff --git a/juju-charms/layers/vyos-proxy/actions/ping b/juju-charms/layers/vyos-proxy/actions/ping
new file mode 100755 (executable)
index 0000000..9850fe7
--- /dev/null
@@ -0,0 +1,18 @@
+#!/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('actions.ping')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/juju-charms/layers/vyos-proxy/config.yaml b/juju-charms/layers/vyos-proxy/config.yaml
new file mode 100644 (file)
index 0000000..0780d5f
--- /dev/null
@@ -0,0 +1,13 @@
+"options":
+  "hostname":
+    "default": !!null ""
+    "type": "string"
+    "description": "Hostname or IP of the VyOS"
+  "user":
+    "type": "string"
+    "default": "vyos"
+    "description": "Username for VyOS"
+  "pass":
+    "type": "string"
+    "default": !!null ""
+    "description": "Password for VyOS"
diff --git a/juju-charms/layers/vyos-proxy/copyright b/juju-charms/layers/vyos-proxy/copyright
new file mode 100644 (file)
index 0000000..720356a
--- /dev/null
@@ -0,0 +1,9 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
+
+Files: *
+Copyright: 2015, Canonical Ltd.
+License: Apache-2.0 
+
+License: Apache-2.0
+ On Debian GNU/Linux system you can find the complete text of the
+ Apache-2.0 license in '/usr/share/common-licenses/Apache-2.0'
diff --git a/juju-charms/layers/vyos-proxy/icon.svg b/juju-charms/layers/vyos-proxy/icon.svg
new file mode 100644 (file)
index 0000000..e092eef
--- /dev/null
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
+\r
+<svg\r
+   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+   xmlns:cc="http://creativecommons.org/ns#"\r
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+   xmlns:svg="http://www.w3.org/2000/svg"\r
+   xmlns="http://www.w3.org/2000/svg"\r
+   xmlns:xlink="http://www.w3.org/1999/xlink"\r
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
+   width="96"\r
+   height="96"\r
+   id="svg6517"\r
+   version="1.1"\r
+   inkscape:version="0.48+devel r12274"\r
+   sodipodi:docname="Juju_charm_icon_template.svg">\r
+  <defs\r
+     id="defs6519">\r
+    <linearGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#Background"\r
+       id="linearGradient6461"\r
+       gradientUnits="userSpaceOnUse"\r
+       x1="0"\r
+       y1="970.29498"\r
+       x2="144"\r
+       y2="970.29498"\r
+       gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />\r
+    <linearGradient\r
+       id="Background">\r
+      <stop\r
+         id="stop4178"\r
+         offset="0"\r
+         style="stop-color:#b8b8b8;stop-opacity:1" />\r
+      <stop\r
+         id="stop4180"\r
+         offset="1"\r
+         style="stop-color:#c9c9c9;stop-opacity:1" />\r
+    </linearGradient>\r
+    <filter\r
+       style="color-interpolation-filters:sRGB;"\r
+       inkscape:label="Inner Shadow"\r
+       id="filter1121">\r
+      <feFlood\r
+         flood-opacity="0.59999999999999998"\r
+         flood-color="rgb(0,0,0)"\r
+         result="flood"\r
+         id="feFlood1123" />\r
+      <feComposite\r
+         in="flood"\r
+         in2="SourceGraphic"\r
+         operator="out"\r
+         result="composite1"\r
+         id="feComposite1125" />\r
+      <feGaussianBlur\r
+         in="composite1"\r
+         stdDeviation="1"\r
+         result="blur"\r
+         id="feGaussianBlur1127" />\r
+      <feOffset\r
+         dx="0"\r
+         dy="2"\r
+         result="offset"\r
+         id="feOffset1129" />\r
+      <feComposite\r
+         in="offset"\r
+         in2="SourceGraphic"\r
+         operator="atop"\r
+         result="composite2"\r
+         id="feComposite1131" />\r
+    </filter>\r
+    <filter\r
+       style="color-interpolation-filters:sRGB;"\r
+       inkscape:label="Drop Shadow"\r
+       id="filter950">\r
+      <feFlood\r
+         flood-opacity="0.25"\r
+         flood-color="rgb(0,0,0)"\r
+         result="flood"\r
+         id="feFlood952" />\r
+      <feComposite\r
+         in="flood"\r
+         in2="SourceGraphic"\r
+         operator="in"\r
+         result="composite1"\r
+         id="feComposite954" />\r
+      <feGaussianBlur\r
+         in="composite1"\r
+         stdDeviation="1"\r
+         result="blur"\r
+         id="feGaussianBlur956" />\r
+      <feOffset\r
+         dx="0"\r
+         dy="1"\r
+         result="offset"\r
+         id="feOffset958" />\r
+      <feComposite\r
+         in="SourceGraphic"\r
+         in2="offset"\r
+         operator="over"\r
+         result="composite2"\r
+         id="feComposite960" />\r
+    </filter>\r
+    <clipPath\r
+       clipPathUnits="userSpaceOnUse"\r
+       id="clipPath873">\r
+      <g\r
+         transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"\r
+         id="g875"\r
+         inkscape:label="Layer 1"\r
+         style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">\r
+        <path\r
+           style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"\r
+           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"\r
+           id="path877"\r
+           inkscape:connector-curvature="0"\r
+           sodipodi:nodetypes="sssssssss" />\r
+      </g>\r
+    </clipPath>\r
+    <filter\r
+       inkscape:collect="always"\r
+       id="filter891"\r
+       inkscape:label="Badge Shadow">\r
+      <feGaussianBlur\r
+         inkscape:collect="always"\r
+         stdDeviation="0.71999962"\r
+         id="feGaussianBlur893" />\r
+    </filter>\r
+  </defs>\r
+  <sodipodi:namedview\r
+     id="base"\r
+     pagecolor="#ffffff"\r
+     bordercolor="#666666"\r
+     borderopacity="1.0"\r
+     inkscape:pageopacity="0.0"\r
+     inkscape:pageshadow="2"\r
+     inkscape:zoom="4.0745362"\r
+     inkscape:cx="18.514671"\r
+     inkscape:cy="49.018169"\r
+     inkscape:document-units="px"\r
+     inkscape:current-layer="layer1"\r
+     showgrid="true"\r
+     fit-margin-top="0"\r
+     fit-margin-left="0"\r
+     fit-margin-right="0"\r
+     fit-margin-bottom="0"\r
+     inkscape:window-width="1920"\r
+     inkscape:window-height="1029"\r
+     inkscape:window-x="0"\r
+     inkscape:window-y="24"\r
+     inkscape:window-maximized="1"\r
+     showborder="true"\r
+     showguides="true"\r
+     inkscape:guide-bbox="true"\r
+     inkscape:showpageshadow="false">\r
+    <inkscape:grid\r
+       type="xygrid"\r
+       id="grid821" />\r
+    <sodipodi:guide\r
+       orientation="1,0"\r
+       position="16,48"\r
+       id="guide823" />\r
+    <sodipodi:guide\r
+       orientation="0,1"\r
+       position="64,80"\r
+       id="guide825" />\r
+    <sodipodi:guide\r
+       orientation="1,0"\r
+       position="80,40"\r
+       id="guide827" />\r
+    <sodipodi:guide\r
+       orientation="0,1"\r
+       position="64,16"\r
+       id="guide829" />\r
+  </sodipodi:namedview>\r
+  <metadata\r
+     id="metadata6522">\r
+    <rdf:RDF>\r
+      <cc:Work\r
+         rdf:about="">\r
+        <dc:format>image/svg+xml</dc:format>\r
+        <dc:type\r
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
+        <dc:title></dc:title>\r
+      </cc:Work>\r
+    </rdf:RDF>\r
+  </metadata>\r
+  <g\r
+     inkscape:label="BACKGROUND"\r
+     inkscape:groupmode="layer"\r
+     id="layer1"\r
+     transform="translate(268,-635.29076)"\r
+     style="display:inline">\r
+    <path\r
+       style="fill:url(#linearGradient6461);fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"\r
+       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"\r
+       id="path6455"\r
+       inkscape:connector-curvature="0"\r
+       sodipodi:nodetypes="sssssssss" />\r
+  </g>\r
+  <g\r
+     inkscape:groupmode="layer"\r
+     id="layer3"\r
+     inkscape:label="PLACE YOUR PICTOGRAM HERE"\r
+     style="display:inline" />\r
+  <g\r
+     inkscape:groupmode="layer"\r
+     id="layer2"\r
+     inkscape:label="BADGE"\r
+     style="display:none"\r
+     sodipodi:insensitive="true">\r
+    <g\r
+       style="display:inline"\r
+       transform="translate(-340.00001,-581)"\r
+       id="g4394"\r
+       clip-path="none">\r
+      <g\r
+         id="g855">\r
+        <g\r
+           inkscape:groupmode="maskhelper"\r
+           id="g870"\r
+           clip-path="url(#clipPath873)"\r
+           style="opacity:0.6;filter:url(#filter891)">\r
+          <path\r
+             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             sodipodi:ry="12"\r
+             sodipodi:rx="12"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:cx="252"\r
+             id="path844"\r
+             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"\r
+             sodipodi:type="arc" />\r
+        </g>\r
+        <g\r
+           id="g862">\r
+          <path\r
+             sodipodi:type="arc"\r
+             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"\r
+             id="path4398"\r
+             sodipodi:cx="252"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:rx="12"\r
+             sodipodi:ry="12"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />\r
+          <path\r
+             transform="matrix(1.25,0,0,1.25,33,-100.45273)"\r
+             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
+             sodipodi:ry="12"\r
+             sodipodi:rx="12"\r
+             sodipodi:cy="552.36218"\r
+             sodipodi:cx="252"\r
+             id="path4400"\r
+             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"\r
+             sodipodi:type="arc" />\r
+          <path\r
+             sodipodi:type="star"\r
+             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"\r
+             id="path4459"\r
+             sodipodi:sides="5"\r
+             sodipodi:cx="666.19574"\r
+             sodipodi:cy="589.50385"\r
+             sodipodi:r1="7.2431178"\r
+             sodipodi:r2="4.3458705"\r
+             sodipodi:arg1="1.0471976"\r
+             sodipodi:arg2="1.6755161"\r
+             inkscape:flatsided="false"\r
+             inkscape:rounded="0.1"\r
+             inkscape:randomized="0"\r
+             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"\r
+             transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />\r
+        </g>\r
+      </g>\r
+    </g>\r
+  </g>\r
+</svg>\r
diff --git a/juju-charms/layers/vyos-proxy/layer.yaml b/juju-charms/layers/vyos-proxy/layer.yaml
new file mode 100644 (file)
index 0000000..dd254f3
--- /dev/null
@@ -0,0 +1,13 @@
+"options":
+  "basic":
+    "packages":
+    - "python-dev"
+    - "libffi-dev"
+    - "libssl-dev"
+    "use_venv": !!bool "false"
+    "include_system_packages": !!bool "false"
+  "vyos-proxy": {}
+"includes":
+- "layer:basic"
+"is": "vyos-proxy"
+"repo": "https://osm.etsi.org/gerrit/osm/juju-charms"
diff --git a/juju-charms/layers/vyos-proxy/metadata.yaml b/juju-charms/layers/vyos-proxy/metadata.yaml
new file mode 100644 (file)
index 0000000..1d29b37
--- /dev/null
@@ -0,0 +1,12 @@
+"name": "vyos-proxy"
+"summary": "VyOS Proxy charm for ping"
+"description": |
+  VyOS Proxy charm
+"tags":
+- "vnf"
+- "network"
+"maintainers":
+- "Marco Ceppi <marco.ceppi@canonical.com>"
+"series":
+- "xenial"
+- "trusty"
diff --git a/juju-charms/layers/vyos-proxy/reactive/__init__.py b/juju-charms/layers/vyos-proxy/reactive/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/juju-charms/layers/vyos-proxy/reactive/vyos_proxy.py b/juju-charms/layers/vyos-proxy/reactive/vyos_proxy.py
new file mode 100644 (file)
index 0000000..a8fd5e0
--- /dev/null
@@ -0,0 +1,99 @@
+
+import subprocess
+import paramiko
+
+from charmhelpers.core.hookenv import (
+    config,
+    status_set,
+    action_get,
+    action_set,
+    action_fail,
+)
+
+from charms.reactive import (
+    when,
+    when_not,
+    set_state as set_flag,
+    remove_state as remove_flag,
+)
+
+
+@when('config.changed')
+def test_connection():
+    status_set('maintenance', 'configuring ssh connection')
+    remove_flag('vyos-proxy.ready')
+    try:
+        who, _ = run('whoami')
+    except MgmtNotConfigured as e:
+        remove_flag('vyos-proxy.configured')
+        status_set('blocked', str(e))
+    except subprocess.CalledProcessError as e:
+        remove_flag('vyos-proxy.configured')
+        status_set('blocked', e.output)
+    else:
+        set_flag('vyos-proxy.configured')
+
+
+@when('vyos-proxy.configured')
+@when_not('vyos-proxy.ready')
+def vyos_proxy_ready():
+    status_set('active', 'ready')
+    set_flag('vyos-proxy.ready')
+
+
+@when('actions.ping')
+@when_not('vyos-proxy.configured')
+def pingme():
+    action_fail('proxy is not ready')
+
+
+@when('actions.ping')
+@when('vyos-proxy.configured')
+def pingme_forreal():
+    try:
+        result, err = run('ping -qc {} {}'.format(action_get('count'), action_get('destination')))
+    except:
+        action_fail('ping command failed')
+    finally:
+        remove_flag('actions.ping')
+
+    # Here you can send results back from ping, if you had time to parse it
+    action_set({'output': result})
+
+
+
+class MgmtNotConfigured(Exception):
+    pass
+
+
+def run(cmd):
+    ''' 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 '''
+
+    cfg = config()
+
+    hostname = cfg.get('hostname')
+    password = cfg.get('pass')
+    username = cfg.get('user')
+
+    if not (username and password and hostname):
+        raise MgmtNotConfigured('incomplete remote credentials')
+
+    client = paramiko.SSHClient()
+    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+
+    try:
+        client.connect(cfg.get('hostname'), port=22,
+                       username=cfg.get('user'), password=cfg.get('pass'))
+    except paramiko.ssh_exception.AuthenticationException:
+        raise MgmtNotConfigured('invalid credentials')
+
+    stdin, stdout, stderr = client.exec_command(cmd)
+    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))
diff --git a/juju-charms/layers/vyos-proxy/requirements.txt b/juju-charms/layers/vyos-proxy/requirements.txt
new file mode 100644 (file)
index 0000000..28ecaca
--- /dev/null
@@ -0,0 +1,2 @@
+flake8
+pytest
diff --git a/juju-charms/layers/vyos-proxy/revision b/juju-charms/layers/vyos-proxy/revision
new file mode 100644 (file)
index 0000000..c227083
--- /dev/null
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/juju-charms/layers/vyos-proxy/tox.ini b/juju-charms/layers/vyos-proxy/tox.ini
new file mode 100644 (file)
index 0000000..0b8b27a
--- /dev/null
@@ -0,0 +1,12 @@
+[tox]
+skipsdist=True
+envlist = py34, py35
+skip_missing_interpreters = True
+
+[testenv]
+commands = py.test -v
+deps =
+    -r{toxinidir}/requirements.txt
+
+[flake8]
+exclude=docs
diff --git a/juju-charms/layers/vyos-proxy/wheelhouse.txt b/juju-charms/layers/vyos-proxy/wheelhouse.txt
new file mode 100644 (file)
index 0000000..24d2c9c
--- /dev/null
@@ -0,0 +1 @@
+paramiko==2.0.1
diff --git a/juju-env.sh b/juju-env.sh
deleted file mode 100644 (file)
index 59fa9e7..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# Set the Juju env variables for building a layer
-export JUJU_REPOSITORY=`pwd`
-export INTERFACE_PATH=$JUJU_REPOSITORY/interfaces
-export LAYER_PATH=$JUJU_REPOSITORY/layers
diff --git a/layers/netutils/LICENSE b/layers/netutils/LICENSE
deleted file mode 100644 (file)
index d645695..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 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.
diff --git a/layers/netutils/README.md b/layers/netutils/README.md
deleted file mode 100644 (file)
index e8258c0..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-# Overview
-
-This charm provides basic network utilities that can be run from a Juju-deployed
-machine.
-
-# Usage
-
-To deploy the charm:
-```bash
-$ juju deploy cs:~nfv/netutils
-```
-
-To run an action:
-```bash
-$ juju run-action netutils/0 ping destination=google.com
-$ juju run-action netutils/0 traceroute destination=google.com
-```
-
-To fetch the output of an action:
-```bash
-$ juju show-action-output 026b3d4c-0bb2-4818-8d24-9855936cdcdf
-results:
-  output: |
-    traceroute to google.com (216.58.198.78), 30 hops max, 60 byte packets
-     1  ec2-79-125-0-86.eu-west-1.compute.amazonaws.com (79.125.0.86)  1.431 ms  1.410 ms  1.380 ms
-     2  100.64.2.73 (100.64.2.73)  1.647 ms 100.64.2.103 (100.64.2.103)  1.247 ms 100.64.2.121 (100.64.2.121)  1.224 ms
-     3  100.64.0.232 (100.64.0.232)  1.296 ms 100.64.0.184 (100.64.0.184)  1.515 ms 100.64.0.234 (100.64.0.234)  1.079 ms
-     4  100.64.16.37 (100.64.16.37)  0.377 ms 100.64.16.49 (100.64.16.49)  0.347 ms 100.64.16.1 (100.64.16.1)  0.340 ms
-     5  176.32.107.12 (176.32.107.12)  0.739 ms 176.32.107.4 (176.32.107.4)  0.875 ms  0.748 ms
-     6  178.236.0.111 (178.236.0.111)  0.650 ms  0.641 ms  0.645 ms
-     7  72.14.215.85 (72.14.215.85)  0.544 ms  1.508 ms  1.498 ms
-     8  209.85.252.198 (209.85.252.198)  0.680 ms  0.659 ms  0.618 ms
-     9  64.233.174.27 (64.233.174.27)  0.690 ms  0.682 ms  0.634 ms
-    10  dub08s02-in-f14.1e100.net (216.58.198.78)  0.568 ms  0.560 ms  0.595 ms
-status: completed
-timing:
-  completed: 2016-06-29 14:50:04 +0000 UTC
-  enqueued: 2016-06-29 14:50:03 +0000 UTC
-  started: 2016-06-29 14:50:03 +0000 UTC
-```
-## iperf3
-
-Because iperf3 has a client and server component, the netutils charm can operate
-as both. Setting the iperf3 configuration value to True will start iperf3 in
-server mode, running as a daemon.
-```
-$ juju deploy cs:~nfv/netutils client
-$ juju deploy cs:~nfv/netutils server iperf3=True
-$ juju run-action client/0 iperf host=<ip of server> [...]
-```
-
-## Scale out Usage
-
-With great scalability comes great power, but please don't use this to DDoS anyone without their permission.
-
-## Known Limitations and Issues
-
-# Contact Information
-
-## Contributing to the charm
-
-  - The compiled charm can be found [here](https://www.jujucharms.com/u/nfv/netutils).
-  - [layer/netutils](https://osm.etsi.org/gitweb/?p=osm/juju-charms.git;a=summary/) contains the source of the layer.
-  - Please add any bugs or feature requests to the [bugzilla](https://osm.etsi.org/bugzilla/buglist.cgi?component=Juju-charms&list_id=426&product=OSM&resolution=---).
diff --git a/layers/netutils/actions.yaml b/layers/netutils/actions.yaml
deleted file mode 100644 (file)
index f4f7884..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-nmap:
-  description: "nmap a thing!"
-  params:
-    destination:
-      description: "destination to scan"
-      type: string
-  required:
-    - destination
-ping:
-  description: 'ping a thing!'
-  params:
-    count:
-      description: "Stop after sending count ECHO_REQUEST packets"
-      type: integer
-      default: 30
-    destination:
-      description: "destination of ping request"
-      type: string
-  required:
-    - destination
-traceroute:
-  description: 'trace a thing!'
-  params:
-    hops:
-      description: "Stop tracing after count hops"
-      type: integer
-      default: 30
-    destination:
-      description: "destination of traceroute request"
-      type: string
-  required:
-    - destination
-dig:
-  description: "DNS lookup"
-  params:
-    nsserver:
-      description: "The nameserver to lookup against."
-      type: string
-    host:
-      description: "The host to lookup"
-      type: string
-    type:
-      description: "The DNS record type to lookup"
-      type: string
-  required:
-    - host
-iperf:
-    description: ""
-    params:
-      host:
-        description: ""
-        type: string
-      port:
-        description: ""
-        type: integer
-        default: 5201
-      format:
-        description: ""
-        type: string
-      interval:
-        description: ""
-        type: string
-      affinity:
-        description: ""
-        type: string
-      udp:
-        description: "Use UDP rather than TCP"
-        type: boolean
-        default: False
-      bandwidth:
-        description: "Set the target bandwidth to n bits/sec (default 1Mbit/sec for UDP, unlimited for TCP)"
-        type: integer
-        default: 1
-      time:
-        description: "Time, in seconds, to transmit for."
-        type: integer
-        default: 10
-      blockcount:
-        description: "The number of blocks to transmit"
-        type: integer
-      length:
-        description: "The length of buffer to read or write (default 128KB for TCP, 8KB for UDP)"
-        type: integer
-      parallel:
-        description: "The number of parallel client streams to run"
-        type: integer
-      reverse:
-        description: "Run in reverse mode (server sends, client receives)."
-        type: boolean
-        default: false
-      window:
-        description: "Window size/socket buffer size."
-        type: integer
-      bind:
-        description: "Bind to a specific interface or multicast address"
-        type: string
-      mss:
-        description: "Set the TCP maximum segment size (MTU - 40 bytes)"
-        type: integer
-      no-delay:
-        description: "Set the TCP no delay, disabling Nagle's algorithm."
-        type: boolean
-        default: false
-      ipv4:
-        description: "Only use IPv4"
-        type: boolean
-        default: false
-      ipv6:
-        description: "Only use IPv6"
-        type: boolean
-        default: false
-      tos:
-        description: "Set the IP 'type of service'"
-        type: integer
-      flowlabel:
-        description: "Set the IPv6 flow label (linux-only)"
-        type: string
-      zerocopy:
-        description: "Use a 'zero copy' method of sending data, such as sendfile(s), instead of the usual write(2)."
-        type: boolean
-        default: false
-      omit:
-        description: "Omit the first n seconds of the test, to skip past the TCP slow-start period."
-        type: integer
-      title:
-        description: "Prefix every output line with this string."
-        type: string
-      congestion:
-        description: "Set the linux congestion control algorithm."
-        type: string
-
-    required:
-      - host
diff --git a/layers/netutils/actions/dig b/layers/netutils/actions/dig
deleted file mode 100755 (executable)
index 736a406..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.dig')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/netutils/actions/iperf b/layers/netutils/actions/iperf
deleted file mode 100755 (executable)
index 750028e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.iperf3')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/netutils/actions/nmap b/layers/netutils/actions/nmap
deleted file mode 100755 (executable)
index ede4f5b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.nmap')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/netutils/actions/ping b/layers/netutils/actions/ping
deleted file mode 100755 (executable)
index 9850fe7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.ping')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/netutils/actions/traceroute b/layers/netutils/actions/traceroute
deleted file mode 100755 (executable)
index 229ed32..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.traceroute')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/netutils/config.yaml b/layers/netutils/config.yaml
deleted file mode 100644 (file)
index 6101063..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-options:
-    iperf3:
-        type: boolean
-        default: false
-        description: "Enabling this option will start iperf3 in server mode."
diff --git a/layers/netutils/icon.svg b/layers/netutils/icon.svg
deleted file mode 100644 (file)
index e092eef..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
-<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
-\r
-<svg\r
-   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
-   xmlns:cc="http://creativecommons.org/ns#"\r
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
-   xmlns:svg="http://www.w3.org/2000/svg"\r
-   xmlns="http://www.w3.org/2000/svg"\r
-   xmlns:xlink="http://www.w3.org/1999/xlink"\r
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
-   width="96"\r
-   height="96"\r
-   id="svg6517"\r
-   version="1.1"\r
-   inkscape:version="0.48+devel r12274"\r
-   sodipodi:docname="Juju_charm_icon_template.svg">\r
-  <defs\r
-     id="defs6519">\r
-    <linearGradient\r
-       inkscape:collect="always"\r
-       xlink:href="#Background"\r
-       id="linearGradient6461"\r
-       gradientUnits="userSpaceOnUse"\r
-       x1="0"\r
-       y1="970.29498"\r
-       x2="144"\r
-       y2="970.29498"\r
-       gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />\r
-    <linearGradient\r
-       id="Background">\r
-      <stop\r
-         id="stop4178"\r
-         offset="0"\r
-         style="stop-color:#b8b8b8;stop-opacity:1" />\r
-      <stop\r
-         id="stop4180"\r
-         offset="1"\r
-         style="stop-color:#c9c9c9;stop-opacity:1" />\r
-    </linearGradient>\r
-    <filter\r
-       style="color-interpolation-filters:sRGB;"\r
-       inkscape:label="Inner Shadow"\r
-       id="filter1121">\r
-      <feFlood\r
-         flood-opacity="0.59999999999999998"\r
-         flood-color="rgb(0,0,0)"\r
-         result="flood"\r
-         id="feFlood1123" />\r
-      <feComposite\r
-         in="flood"\r
-         in2="SourceGraphic"\r
-         operator="out"\r
-         result="composite1"\r
-         id="feComposite1125" />\r
-      <feGaussianBlur\r
-         in="composite1"\r
-         stdDeviation="1"\r
-         result="blur"\r
-         id="feGaussianBlur1127" />\r
-      <feOffset\r
-         dx="0"\r
-         dy="2"\r
-         result="offset"\r
-         id="feOffset1129" />\r
-      <feComposite\r
-         in="offset"\r
-         in2="SourceGraphic"\r
-         operator="atop"\r
-         result="composite2"\r
-         id="feComposite1131" />\r
-    </filter>\r
-    <filter\r
-       style="color-interpolation-filters:sRGB;"\r
-       inkscape:label="Drop Shadow"\r
-       id="filter950">\r
-      <feFlood\r
-         flood-opacity="0.25"\r
-         flood-color="rgb(0,0,0)"\r
-         result="flood"\r
-         id="feFlood952" />\r
-      <feComposite\r
-         in="flood"\r
-         in2="SourceGraphic"\r
-         operator="in"\r
-         result="composite1"\r
-         id="feComposite954" />\r
-      <feGaussianBlur\r
-         in="composite1"\r
-         stdDeviation="1"\r
-         result="blur"\r
-         id="feGaussianBlur956" />\r
-      <feOffset\r
-         dx="0"\r
-         dy="1"\r
-         result="offset"\r
-         id="feOffset958" />\r
-      <feComposite\r
-         in="SourceGraphic"\r
-         in2="offset"\r
-         operator="over"\r
-         result="composite2"\r
-         id="feComposite960" />\r
-    </filter>\r
-    <clipPath\r
-       clipPathUnits="userSpaceOnUse"\r
-       id="clipPath873">\r
-      <g\r
-         transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"\r
-         id="g875"\r
-         inkscape:label="Layer 1"\r
-         style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">\r
-        <path\r
-           style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"\r
-           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"\r
-           id="path877"\r
-           inkscape:connector-curvature="0"\r
-           sodipodi:nodetypes="sssssssss" />\r
-      </g>\r
-    </clipPath>\r
-    <filter\r
-       inkscape:collect="always"\r
-       id="filter891"\r
-       inkscape:label="Badge Shadow">\r
-      <feGaussianBlur\r
-         inkscape:collect="always"\r
-         stdDeviation="0.71999962"\r
-         id="feGaussianBlur893" />\r
-    </filter>\r
-  </defs>\r
-  <sodipodi:namedview\r
-     id="base"\r
-     pagecolor="#ffffff"\r
-     bordercolor="#666666"\r
-     borderopacity="1.0"\r
-     inkscape:pageopacity="0.0"\r
-     inkscape:pageshadow="2"\r
-     inkscape:zoom="4.0745362"\r
-     inkscape:cx="18.514671"\r
-     inkscape:cy="49.018169"\r
-     inkscape:document-units="px"\r
-     inkscape:current-layer="layer1"\r
-     showgrid="true"\r
-     fit-margin-top="0"\r
-     fit-margin-left="0"\r
-     fit-margin-right="0"\r
-     fit-margin-bottom="0"\r
-     inkscape:window-width="1920"\r
-     inkscape:window-height="1029"\r
-     inkscape:window-x="0"\r
-     inkscape:window-y="24"\r
-     inkscape:window-maximized="1"\r
-     showborder="true"\r
-     showguides="true"\r
-     inkscape:guide-bbox="true"\r
-     inkscape:showpageshadow="false">\r
-    <inkscape:grid\r
-       type="xygrid"\r
-       id="grid821" />\r
-    <sodipodi:guide\r
-       orientation="1,0"\r
-       position="16,48"\r
-       id="guide823" />\r
-    <sodipodi:guide\r
-       orientation="0,1"\r
-       position="64,80"\r
-       id="guide825" />\r
-    <sodipodi:guide\r
-       orientation="1,0"\r
-       position="80,40"\r
-       id="guide827" />\r
-    <sodipodi:guide\r
-       orientation="0,1"\r
-       position="64,16"\r
-       id="guide829" />\r
-  </sodipodi:namedview>\r
-  <metadata\r
-     id="metadata6522">\r
-    <rdf:RDF>\r
-      <cc:Work\r
-         rdf:about="">\r
-        <dc:format>image/svg+xml</dc:format>\r
-        <dc:type\r
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
-        <dc:title></dc:title>\r
-      </cc:Work>\r
-    </rdf:RDF>\r
-  </metadata>\r
-  <g\r
-     inkscape:label="BACKGROUND"\r
-     inkscape:groupmode="layer"\r
-     id="layer1"\r
-     transform="translate(268,-635.29076)"\r
-     style="display:inline">\r
-    <path\r
-       style="fill:url(#linearGradient6461);fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"\r
-       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"\r
-       id="path6455"\r
-       inkscape:connector-curvature="0"\r
-       sodipodi:nodetypes="sssssssss" />\r
-  </g>\r
-  <g\r
-     inkscape:groupmode="layer"\r
-     id="layer3"\r
-     inkscape:label="PLACE YOUR PICTOGRAM HERE"\r
-     style="display:inline" />\r
-  <g\r
-     inkscape:groupmode="layer"\r
-     id="layer2"\r
-     inkscape:label="BADGE"\r
-     style="display:none"\r
-     sodipodi:insensitive="true">\r
-    <g\r
-       style="display:inline"\r
-       transform="translate(-340.00001,-581)"\r
-       id="g4394"\r
-       clip-path="none">\r
-      <g\r
-         id="g855">\r
-        <g\r
-           inkscape:groupmode="maskhelper"\r
-           id="g870"\r
-           clip-path="url(#clipPath873)"\r
-           style="opacity:0.6;filter:url(#filter891)">\r
-          <path\r
-             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             sodipodi:ry="12"\r
-             sodipodi:rx="12"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:cx="252"\r
-             id="path844"\r
-             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"\r
-             sodipodi:type="arc" />\r
-        </g>\r
-        <g\r
-           id="g862">\r
-          <path\r
-             sodipodi:type="arc"\r
-             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"\r
-             id="path4398"\r
-             sodipodi:cx="252"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:rx="12"\r
-             sodipodi:ry="12"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />\r
-          <path\r
-             transform="matrix(1.25,0,0,1.25,33,-100.45273)"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             sodipodi:ry="12"\r
-             sodipodi:rx="12"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:cx="252"\r
-             id="path4400"\r
-             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"\r
-             sodipodi:type="arc" />\r
-          <path\r
-             sodipodi:type="star"\r
-             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"\r
-             id="path4459"\r
-             sodipodi:sides="5"\r
-             sodipodi:cx="666.19574"\r
-             sodipodi:cy="589.50385"\r
-             sodipodi:r1="7.2431178"\r
-             sodipodi:r2="4.3458705"\r
-             sodipodi:arg1="1.0471976"\r
-             sodipodi:arg2="1.6755161"\r
-             inkscape:flatsided="false"\r
-             inkscape:rounded="0.1"\r
-             inkscape:randomized="0"\r
-             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"\r
-             transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />\r
-        </g>\r
-      </g>\r
-    </g>\r
-  </g>\r
-</svg>\r
diff --git a/layers/netutils/layer.yaml b/layers/netutils/layer.yaml
deleted file mode 100644 (file)
index e13c81a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-repo: git@github.com:AdamIsrael/layer-netutils.git
-includes: ['layer:basic', 'layer:sshproxy']
-options:
-  basic:
-    packages:
-      - traceroute
-      - nmap
-      - iperf3
diff --git a/layers/netutils/metadata.yaml b/layers/netutils/metadata.yaml
deleted file mode 100644 (file)
index c42d963..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-name: netutils
-summary: A suite of network-related utilities.
-maintainer: Adam Israel <adam.israel@canonical.com>
-description: |
-  A suite of network-related utilities, such as ping and traceroute, that
-  can be deployed into a data center in order to diagnose connectivity issues.
-tags:
-  # https://jujucharms.com/docs/stable/authors-charm-metadata
-  - ops
-  - network
-  - performance
-series:
-  - trusty
-  - xenial
-subordinate: false
diff --git a/layers/netutils/reactive/layer_netutils.py b/layers/netutils/reactive/layer_netutils.py
deleted file mode 100644 (file)
index 1fd4cb2..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-from charmhelpers.core.hookenv import (
-    action_get,
-    action_fail,
-    action_set,
-    config,
-    log,
-    status_set,
-)
-
-from charms.reactive import (
-    remove_state as remove_flag,
-    set_state as set_flag,
-    when,
-    when_not,
-)
-import charms.sshproxy
-from subprocess import CalledProcessError
-
-
-@when_not('netutils.ready')
-def ready():
-    status_set('active', 'Ready!')
-    set_flag('netutils.ready')
-
-
-@when('actions.dig')
-def dig():
-    err = ''
-    try:
-        nsserver = action_get('nsserver')
-        host = action_get('host')
-        nstype = action_get('type')
-        cmd = "dig"
-
-        if nsserver:
-            cmd += " @{}".format(nsserver)
-        if host:
-            cmd += " {}".format(host)
-        else:
-            action_fail('Hostname required.')
-        if nstype:
-            cmd += " -t {}".format(nstype)
-
-        result, err = charms.sshproxy._run(cmd)
-    except:
-        action_fail('dig command failed:' + err)
-    else:
-        action_set({'outout': result})
-    finally:
-        remove_flag('actions.dig')
-
-
-@when('actions.nmap')
-def nmap():
-    err = ''
-    try:
-        result, err = charms.sshproxy._run(
-            'nmap {}'.format(action_get('destination'))
-        )
-    except:
-        action_fail('nmap command failed:' + err)
-    else:
-        action_set({'outout': result})
-    finally:
-        remove_flag('actions.nmap')
-
-
-@when('actions.ping')
-def ping():
-    err = ''
-    try:
-        result, err = charms.sshproxy._run('ping -qc {} {}'.format(
-            action_get('count'), action_get('destination'))
-        )
-
-    except:
-        action_fail('ping command failed:' + err)
-    else:
-        # Here you can send results back from ping, if you had time to parse it
-        action_set({'output': result})
-    finally:
-        remove_flag('actions.ping')
-
-
-@when('actions.traceroute')
-def traceroute():
-    try:
-        result, err = charms.sshproxy._run(
-            'traceroute -m {} {}'.format(
-                    action_get('hops'),
-                    action_get('destination')
-            )
-        )
-    except:
-        action_fail('traceroute command failed')
-    else:
-        # Here you can send results back from ping, if you had time to parse it
-        action_set({'output': result})
-    finally:
-        remove_flag('actions.traceroute')
-
-
-@when('actions.iperf3')
-def iperf3():
-    err = ''
-    try:
-        # TODO: read all the flags via action_get and build the
-        # proper command line to run iperf3
-        host = action_get('host')
-
-        cmd = 'iperf3 -c {} --json'.format(host)
-        result, err = charms.sshproxy._run(cmd)
-    except CalledProcessError as e:
-        action_fail('iperf3 command failed:' + e.output)
-    else:
-        action_set({'outout': result})
-    finally:
-        remove_flag('actions.iperf3')
-
-
-@when('config.changed')
-def config_changed():
-    """ Handle configuration changes """
-    cfg = config()
-    if cfg.changed('iperf3'):
-        if cfg['iperf3']:
-            # start iperf in server + daemon mode
-            cmd = "iperf3 -s -D"
-        else:
-            cmd = "killall iperf3"
-        try:
-            charms.sshproxy._run(cmd)
-            log("iperf3 stopped.")
-        except CalledProcessError:
-            log("iperf3 not running.")
-        else:
-            log("iperf3 started.")
diff --git a/layers/netutils/tests/00-setup b/layers/netutils/tests/00-setup
deleted file mode 100755 (executable)
index f0616a5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-sudo add-apt-repository ppa:juju/stable -y
-sudo apt-get update
-sudo apt-get install amulet python-requests -y
diff --git a/layers/netutils/tests/10-deploy b/layers/netutils/tests/10-deploy
deleted file mode 100755 (executable)
index ef269cd..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/python3
-
-import amulet
-import requests
-import unittest
-
-
-class TestCharm(unittest.TestCase):
-    def setUp(self):
-        self.d = amulet.Deployment()
-
-        self.d.add('layer-netutils')
-        self.d.expose('layer-netutils')
-
-        self.d.setup(timeout=900)
-        self.d.sentry.wait()
-
-        self.unit = self.d.sentry['layer-netutils'][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
diff --git a/layers/pingpong/README.md b/layers/pingpong/README.md
deleted file mode 100644 (file)
index 3bec243..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-# Overview
-
-This repository contains the [Juju] layer that represents a working example of a proxy charm.
-
-# What is a proxy charm?
-
-A proxy charm is a limited type of charm that does not interact with software running on the same host, such as controlling and configuring a remote device (a static VM image, a router/switch, etc.). It cannot take advantage of some of Juju's key features, such as [scaling], [relations], and [leadership].
-
-Proxy charms are primarily a stop-gap, intended to prototype quickly, with the end goal being to develop it into a full-featured charm, which installs and executes code on the same machine as the charm is running.
-
-# Usage
-
-```bash
-# Clone this repository
-git clone https://osm.etsi.org/gerrit/osm/juju-charms
-cd juju-charms
-
-# Setup environment variables
-source juju-env.sh
-
-cd layers/pingpong
-charm build
-
-# Examine the built charm
-cd ../../builds/pingpong
-ls
-actions       config.yaml  icon.svg    metadata.yaml     tests
-actions.yaml  copyright    layer.yaml  reactive          tox.ini
-bin           deps         lib         README.md         wheelhouse
-builds        hooks        Makefile    requirements.txt
-
-```
-
-You can view a screencast of this: https://asciinema.org/a/96738
-
-The `charm build` process combines this pingpong layer with each layer that it
-has included in the `metadata.yaml` file, along with their various dependencies.
-
-This built charm is what will then be used by the SO to communicate with the
-VNF.
-
-# Configuration
-
-The pingpong charm has several configuration properties that can be set via
-the SO:
-
-- ssh-hostname
-- ssh-username
-- ssh-password
-- ssh-private-key
-- mode
-
-The ssh-* keys are included by the `sshproxy` layer, and enable the charm to
-connect to the VNF image.
-
-The mode key must be one of two values: `ping` or `pong`. This informs the
-charm as to which function it is serving.
-
-# Contact Information
-For support, please send an email to the [OSM Tech] list.
-
-
-[OSM Tech]: mailto:OSM_TECH@list.etsi.org
-[Juju]: https://jujucharms.com/about
-[configure]: https://jujucharms.com/docs/2.0/charms-config
-[scaling]: https://jujucharms.com/docs/2.0/charms-scaling
-[relations]: https://jujucharms.com/docs/2.0/charms-relations
-[leadership]: https://jujucharms.com/docs/2.0/developer-leadership
-[created your charm]: https://jujucharms.com/docs/2.0/developer-getting-started
-
-
-
-
-
------
-
-
-# Integration
-
-After you've [created your charm], open `interfaces.yaml` and add
-`layer:sshproxy` to the includes stanza, as shown below:
-```
-includes: ['layer:basic', 'layer:sshproxy']
-```
-
-## Reactive states
-
-This layer will set the following states:
-
-- `sshproxy.configured` This state is set when SSH credentials have been supplied to the charm.
-
-
-## Example
-In `reactive/mycharm.py`, you can add logic to execute commands over SSH. This
-example is run via a `start` action, and starts a service running on a remote
-host.
-```
-...
-import charms.sshproxy
-
-
-@when('sshproxy.configured')
-@when('actions.start')
-def start():
-    """ Execute's the command, via the start action` using the
-    configured SSH credentials
-    """
-    sshproxy.ssh("service myservice start")
-
-```
-
-## Actions
-This layer includes a built-in `run` action useful for debugging or running arbitrary commands:
-
-```
-$ juju run-action mycharm/0 run command=hostname
-Action queued with id: 014b72f3-bc02-4ecb-8d38-72bce03bbb63
-
-$ juju show-action-output 014b72f3-bc02-4ecb-8d38-72bce03bbb63
-results:
-  output: juju-66a5f3-11
-status: completed
-timing:
-  completed: 2016-10-27 19:53:49 +0000 UTC
-  enqueued: 2016-10-27 19:53:44 +0000 UTC
-  started: 2016-10-27 19:53:48 +0000 UTC
-
-```
-## Known Limitations and Issues
-
-### Security issues
-
-- Password and key-based authentications are supported, with the caveat that
-both (password and private key) are stored plaintext within the Juju controller.
-
-# Configuration and Usage
-
-This layer adds the following configuration options:
-- ssh-hostname
-- ssh-username
-- ssh-password
-- ssh-private-key
-
-Once  [configure] those values at any time. Once they are set, the `sshproxy.configured` state flag will be toggled:
-
-```
-juju deploy mycharm ssh-hostname=10.10.10.10 ssh-username=ubuntu ssh-password=yourpassword
-```
-or
-```
-juju deploy mycharm ssh-hostname=10.10.10.10 ssh-username=ubuntu ssh-private-key="cat `~/.ssh/id_rsa`"
-```
-
-
-# Contact Information
-Homepage: https://github.com/AdamIsrael/layer-sshproxy
-
-[Juju]: https://jujucharms.com/about
-[configure]: https://jujucharms.com/docs/2.0/charms-config
-[scaling]: https://jujucharms.com/docs/2.0/charms-scaling
-[relations]: https://jujucharms.com/docs/2.0/charms-relations
-[leadership]: https://jujucharms.com/docs/2.0/developer-leadership
-[created your charm]: https://jujucharms.com/docs/2.0/developer-getting-started
diff --git a/layers/pingpong/actions.yaml b/layers/pingpong/actions.yaml
deleted file mode 100644 (file)
index a5928f1..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-set-server:
-    description: "Set the target IP address and port"
-    params:
-        server-ip:
-            description: "IP on which the target service is listening."
-            type: string
-            default: ""
-        server-port:
-            description: "Port on which the target service is listening."
-            type: integer
-            default: 5555
-    required:
-        - server-ip
-set-rate:
-    description: "Set the rate of packet generation."
-    params:
-        rate:
-            description: "Packet rate."
-            type: integer
-            default: 5
-get-stats:
-    description: "Get the stats."
-get-state:
-    description: "Get the admin state of the target service."
-get-rate:
-    description: "Get the rate set on the target service."
-get-server:
-    description: "Get the target server and IP set"
-start-traffic:
-    description: "Start the traffic generator or echo."
-stop-traffic:
-    description: "Stop the traffic generator or echo."
diff --git a/layers/pingpong/actions/get-rate b/layers/pingpong/actions/get-rate
deleted file mode 100755 (executable)
index 959b3e9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.get-rate')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/pingpong/actions/get-server b/layers/pingpong/actions/get-server
deleted file mode 100755 (executable)
index 52e0089..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.get-server')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/pingpong/actions/get-state b/layers/pingpong/actions/get-state
deleted file mode 100755 (executable)
index 446e8d7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.get-state')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/pingpong/actions/get-stats b/layers/pingpong/actions/get-stats
deleted file mode 100755 (executable)
index 086afc2..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.get-stats')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/pingpong/actions/set-rate b/layers/pingpong/actions/set-rate
deleted file mode 100755 (executable)
index 8fb723e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.set-rate')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/pingpong/actions/set-server b/layers/pingpong/actions/set-server
deleted file mode 100755 (executable)
index d1e908f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.set-server')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/pingpong/actions/start-traffic b/layers/pingpong/actions/start-traffic
deleted file mode 100755 (executable)
index 562ac4c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.start-traffic')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/pingpong/actions/stop-traffic b/layers/pingpong/actions/stop-traffic
deleted file mode 100755 (executable)
index 9352b33..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.stop-traffic')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/pingpong/config.yaml b/layers/pingpong/config.yaml
deleted file mode 100644 (file)
index 437524e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-options:
-  mode:
-    type: string
-    default:
-    description: "The service type: [ping, pong]"
diff --git a/layers/pingpong/icon.svg b/layers/pingpong/icon.svg
deleted file mode 100644 (file)
index e092eef..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
-<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
-\r
-<svg\r
-   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
-   xmlns:cc="http://creativecommons.org/ns#"\r
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
-   xmlns:svg="http://www.w3.org/2000/svg"\r
-   xmlns="http://www.w3.org/2000/svg"\r
-   xmlns:xlink="http://www.w3.org/1999/xlink"\r
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
-   width="96"\r
-   height="96"\r
-   id="svg6517"\r
-   version="1.1"\r
-   inkscape:version="0.48+devel r12274"\r
-   sodipodi:docname="Juju_charm_icon_template.svg">\r
-  <defs\r
-     id="defs6519">\r
-    <linearGradient\r
-       inkscape:collect="always"\r
-       xlink:href="#Background"\r
-       id="linearGradient6461"\r
-       gradientUnits="userSpaceOnUse"\r
-       x1="0"\r
-       y1="970.29498"\r
-       x2="144"\r
-       y2="970.29498"\r
-       gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />\r
-    <linearGradient\r
-       id="Background">\r
-      <stop\r
-         id="stop4178"\r
-         offset="0"\r
-         style="stop-color:#b8b8b8;stop-opacity:1" />\r
-      <stop\r
-         id="stop4180"\r
-         offset="1"\r
-         style="stop-color:#c9c9c9;stop-opacity:1" />\r
-    </linearGradient>\r
-    <filter\r
-       style="color-interpolation-filters:sRGB;"\r
-       inkscape:label="Inner Shadow"\r
-       id="filter1121">\r
-      <feFlood\r
-         flood-opacity="0.59999999999999998"\r
-         flood-color="rgb(0,0,0)"\r
-         result="flood"\r
-         id="feFlood1123" />\r
-      <feComposite\r
-         in="flood"\r
-         in2="SourceGraphic"\r
-         operator="out"\r
-         result="composite1"\r
-         id="feComposite1125" />\r
-      <feGaussianBlur\r
-         in="composite1"\r
-         stdDeviation="1"\r
-         result="blur"\r
-         id="feGaussianBlur1127" />\r
-      <feOffset\r
-         dx="0"\r
-         dy="2"\r
-         result="offset"\r
-         id="feOffset1129" />\r
-      <feComposite\r
-         in="offset"\r
-         in2="SourceGraphic"\r
-         operator="atop"\r
-         result="composite2"\r
-         id="feComposite1131" />\r
-    </filter>\r
-    <filter\r
-       style="color-interpolation-filters:sRGB;"\r
-       inkscape:label="Drop Shadow"\r
-       id="filter950">\r
-      <feFlood\r
-         flood-opacity="0.25"\r
-         flood-color="rgb(0,0,0)"\r
-         result="flood"\r
-         id="feFlood952" />\r
-      <feComposite\r
-         in="flood"\r
-         in2="SourceGraphic"\r
-         operator="in"\r
-         result="composite1"\r
-         id="feComposite954" />\r
-      <feGaussianBlur\r
-         in="composite1"\r
-         stdDeviation="1"\r
-         result="blur"\r
-         id="feGaussianBlur956" />\r
-      <feOffset\r
-         dx="0"\r
-         dy="1"\r
-         result="offset"\r
-         id="feOffset958" />\r
-      <feComposite\r
-         in="SourceGraphic"\r
-         in2="offset"\r
-         operator="over"\r
-         result="composite2"\r
-         id="feComposite960" />\r
-    </filter>\r
-    <clipPath\r
-       clipPathUnits="userSpaceOnUse"\r
-       id="clipPath873">\r
-      <g\r
-         transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"\r
-         id="g875"\r
-         inkscape:label="Layer 1"\r
-         style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">\r
-        <path\r
-           style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"\r
-           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"\r
-           id="path877"\r
-           inkscape:connector-curvature="0"\r
-           sodipodi:nodetypes="sssssssss" />\r
-      </g>\r
-    </clipPath>\r
-    <filter\r
-       inkscape:collect="always"\r
-       id="filter891"\r
-       inkscape:label="Badge Shadow">\r
-      <feGaussianBlur\r
-         inkscape:collect="always"\r
-         stdDeviation="0.71999962"\r
-         id="feGaussianBlur893" />\r
-    </filter>\r
-  </defs>\r
-  <sodipodi:namedview\r
-     id="base"\r
-     pagecolor="#ffffff"\r
-     bordercolor="#666666"\r
-     borderopacity="1.0"\r
-     inkscape:pageopacity="0.0"\r
-     inkscape:pageshadow="2"\r
-     inkscape:zoom="4.0745362"\r
-     inkscape:cx="18.514671"\r
-     inkscape:cy="49.018169"\r
-     inkscape:document-units="px"\r
-     inkscape:current-layer="layer1"\r
-     showgrid="true"\r
-     fit-margin-top="0"\r
-     fit-margin-left="0"\r
-     fit-margin-right="0"\r
-     fit-margin-bottom="0"\r
-     inkscape:window-width="1920"\r
-     inkscape:window-height="1029"\r
-     inkscape:window-x="0"\r
-     inkscape:window-y="24"\r
-     inkscape:window-maximized="1"\r
-     showborder="true"\r
-     showguides="true"\r
-     inkscape:guide-bbox="true"\r
-     inkscape:showpageshadow="false">\r
-    <inkscape:grid\r
-       type="xygrid"\r
-       id="grid821" />\r
-    <sodipodi:guide\r
-       orientation="1,0"\r
-       position="16,48"\r
-       id="guide823" />\r
-    <sodipodi:guide\r
-       orientation="0,1"\r
-       position="64,80"\r
-       id="guide825" />\r
-    <sodipodi:guide\r
-       orientation="1,0"\r
-       position="80,40"\r
-       id="guide827" />\r
-    <sodipodi:guide\r
-       orientation="0,1"\r
-       position="64,16"\r
-       id="guide829" />\r
-  </sodipodi:namedview>\r
-  <metadata\r
-     id="metadata6522">\r
-    <rdf:RDF>\r
-      <cc:Work\r
-         rdf:about="">\r
-        <dc:format>image/svg+xml</dc:format>\r
-        <dc:type\r
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
-        <dc:title></dc:title>\r
-      </cc:Work>\r
-    </rdf:RDF>\r
-  </metadata>\r
-  <g\r
-     inkscape:label="BACKGROUND"\r
-     inkscape:groupmode="layer"\r
-     id="layer1"\r
-     transform="translate(268,-635.29076)"\r
-     style="display:inline">\r
-    <path\r
-       style="fill:url(#linearGradient6461);fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"\r
-       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"\r
-       id="path6455"\r
-       inkscape:connector-curvature="0"\r
-       sodipodi:nodetypes="sssssssss" />\r
-  </g>\r
-  <g\r
-     inkscape:groupmode="layer"\r
-     id="layer3"\r
-     inkscape:label="PLACE YOUR PICTOGRAM HERE"\r
-     style="display:inline" />\r
-  <g\r
-     inkscape:groupmode="layer"\r
-     id="layer2"\r
-     inkscape:label="BADGE"\r
-     style="display:none"\r
-     sodipodi:insensitive="true">\r
-    <g\r
-       style="display:inline"\r
-       transform="translate(-340.00001,-581)"\r
-       id="g4394"\r
-       clip-path="none">\r
-      <g\r
-         id="g855">\r
-        <g\r
-           inkscape:groupmode="maskhelper"\r
-           id="g870"\r
-           clip-path="url(#clipPath873)"\r
-           style="opacity:0.6;filter:url(#filter891)">\r
-          <path\r
-             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             sodipodi:ry="12"\r
-             sodipodi:rx="12"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:cx="252"\r
-             id="path844"\r
-             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"\r
-             sodipodi:type="arc" />\r
-        </g>\r
-        <g\r
-           id="g862">\r
-          <path\r
-             sodipodi:type="arc"\r
-             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"\r
-             id="path4398"\r
-             sodipodi:cx="252"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:rx="12"\r
-             sodipodi:ry="12"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />\r
-          <path\r
-             transform="matrix(1.25,0,0,1.25,33,-100.45273)"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             sodipodi:ry="12"\r
-             sodipodi:rx="12"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:cx="252"\r
-             id="path4400"\r
-             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"\r
-             sodipodi:type="arc" />\r
-          <path\r
-             sodipodi:type="star"\r
-             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"\r
-             id="path4459"\r
-             sodipodi:sides="5"\r
-             sodipodi:cx="666.19574"\r
-             sodipodi:cy="589.50385"\r
-             sodipodi:r1="7.2431178"\r
-             sodipodi:r2="4.3458705"\r
-             sodipodi:arg1="1.0471976"\r
-             sodipodi:arg2="1.6755161"\r
-             inkscape:flatsided="false"\r
-             inkscape:rounded="0.1"\r
-             inkscape:randomized="0"\r
-             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"\r
-             transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />\r
-        </g>\r
-      </g>\r
-    </g>\r
-  </g>\r
-</svg>\r
diff --git a/layers/pingpong/layer.yaml b/layers/pingpong/layer.yaml
deleted file mode 100644 (file)
index 833eea6..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-includes:
-    - layer:basic
-    - layer:vnfproxy
-repo: https://osm.etsi.org/gerrit/osm/juju-charms
diff --git a/layers/pingpong/metadata.yaml b/layers/pingpong/metadata.yaml
deleted file mode 100644 (file)
index 1840743..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-name: pingpong
-summary: <Fill in summary here>
-maintainer: Adam Israel <Adam.Israel@ronin>
-description: |
-  <Multi-line description here>
-tags:
-  # Replace "misc" with one or more whitelisted tags from this list:
-  # https://jujucharms.com/docs/stable/authors-charm-metadata
-  - misc
-subordinate: false
-series:
-    - trusty
-    - xenial
diff --git a/layers/pingpong/reactive/pingpong.py b/layers/pingpong/reactive/pingpong.py
deleted file mode 100644 (file)
index b5a5db9..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-from charmhelpers.core.hookenv import (
-    action_get,
-    action_fail,
-    action_set,
-    config,
-    status_set,
-)
-
-from charms.reactive import (
-    remove_state as remove_flag,
-    set_state as set_flag,
-    when,
-)
-import charms.sshproxy
-from subprocess import (
-    Popen,
-    CalledProcessError,
-    PIPE,
-)
-
-
-cfg = config()
-
-
-@when('config.changed')
-def config_changed():
-    if all(k in cfg for k in ['mode']):
-        if cfg['mode'] in ['ping', 'pong']:
-            set_flag('pingpong.configured')
-            status_set('active', 'ready!')
-            return
-    status_set('blocked', 'Waiting for configuration')
-
-
-def is_ping():
-    if cfg['mode'] == 'ping':
-        return True
-    return False
-
-
-def is_pong():
-    return not is_ping()
-
-
-def get_port():
-    port = 18888
-    if is_pong():
-        port = 18889
-    return port
-
-
-@when('pingpong.configured')
-@when('actions.start')
-def start():
-    try:
-        # Bring up the eth1 interface.
-        # The selinux label on the file needs to be set correctly
-        cmd = "sudo timeout 5 /sbin/restorecon -v /etc/sysconfig/network-scripts/ifcfg-eth1"
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        err = "{}".format(e)
-        action_fail('command failed: {}, errors: {}'.format(err, e.output))
-        remove_flag('actions.start')
-        return
-
-    try:
-        cmd =  "sudo timeout 30 /sbin/ifup eth1"
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-        remove_flag('actions.start')
-        return
-
-    try:
-        cmd =  "sudo timeout 30 /usr/bin/systemctl start {}". \
-              format(cfg['mode'])
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.start')
-
-
-@when('pingpong.configured')
-@when('actions.stop')
-def stop():
-    try:
-        # Enter the command to stop your service(s)
-        cmd = "sudo timeout 30 /usr/bin/systemctl stop {}".format(cfg['mode'])
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.stop')
-
-
-@when('pingpong.configured')
-@when('actions.restart')
-def restart():
-    try:
-        # Enter the command to restart your service(s)
-        cmd = "sudo timeout 30 /usr/bin/systemctl restart {}".format(cfg['mode'])
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.restart')
-
-
-@when('pingpong.configured')
-@when('actions.set-server')
-def set_server():
-    try:
-        # Get the target service info
-        target_ip = action_get('server-ip')
-        target_port = action_get('server-port')
-
-        data = '{{"ip" : "{}", "port" : {} }}'. \
-               format(target_ip, target_port)
-
-        cmd = format_curl(
-            'POST',
-            '/server',
-            data,
-        )
-
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.set-server')
-
-
-@when('pingpong.configured')
-@when('actions.set-rate')
-def set_rate():
-    try:
-        if is_ping():
-            rate = action_get('rate')
-            cmd = format_curl('POST', '/rate', '{{"rate" : {}}}'.format(rate))
-
-            result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        err = "{}".format(e)
-        action_fail('command failed: {}, errors: {}'.format(err, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.set-rate')
-
-
-@when('pingpong.configured')
-@when('actions.get-rate')
-def get_rate():
-    try:
-        if is_ping():
-            cmd = format_curl('GET', '/rate')
-
-            result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.get-rate')
-
-
-@when('pingpong.configured')
-@when('actions.get-state')
-def get_state():
-    try:
-        cmd = format_curl('GET', '/state')
-
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.get-state')
-
-
-@when('pingpong.configured')
-@when('actions.get-stats')
-def get_stats():
-    try:
-        cmd = format_curl('GET', '/stats')
-
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.get-stats')
-
-
-@when('pingpong.configured')
-@when('actions.start-traffic')
-def start_traffic():
-    try:
-        cmd = format_curl('POST', '/adminstatus/state', '{"enable" : true}')
-
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.start-traffic')
-
-
-@when('pingpong.configured')
-@when('actions.stop-traffic')
-def stop_traffic():
-    try:
-        cmd = format_curl('POST', '/adminstatus/state', '{"enable" : false}')
-
-        result, err = charms.sshproxy._run(cmd)
-    except Exception as e:
-        action_fail('command failed: {}, errors: {}'.format(e, e.output))
-    else:
-        action_set({'stdout': result,
-                    'errors': err})
-    finally:
-        remove_flag('actions.stop-traffic')
-
-
-def format_curl(method, path, data=None):
-    """ A utility function to build the curl command line. """
-
-    # method must be GET or POST
-    if method not in ['GET', 'POST']:
-        # Throw exception
-        return None
-
-    # Get our service info
-    host = '127.0.0.1'
-    port = get_port()
-    mode = cfg['mode']
-
-    cmd = ['curl',
-           # '-D', '/dev/stdout',
-           '-H', 'Accept: application/vnd.yang.data+xml',
-           '-H', 'Content-Type: application/vnd.yang.data+json',
-           '-X', method]
-
-    if method == "POST" and data:
-        cmd.append('-d')
-        cmd.append('{}'.format(data))
-
-    cmd.append(
-        'http://{}:{}/api/v1/{}{}'.format(host, port, mode, path)
-    )
-    return cmd
diff --git a/layers/pingpong/tests/00-setup b/layers/pingpong/tests/00-setup
deleted file mode 100755 (executable)
index f0616a5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-sudo add-apt-repository ppa:juju/stable -y
-sudo apt-get update
-sudo apt-get install amulet python-requests -y
diff --git a/layers/pingpong/tests/10-deploy b/layers/pingpong/tests/10-deploy
deleted file mode 100755 (executable)
index d1d4719..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/python3
-
-import amulet
-import requests
-import unittest
-
-
-class TestCharm(unittest.TestCase):
-    def setUp(self):
-        self.d = amulet.Deployment()
-
-        self.d.add('pingpong')
-        self.d.expose('pingpong')
-
-        self.d.setup(timeout=900)
-        self.d.sentry.wait()
-
-        self.unit = self.d.sentry['pingpong'][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()
diff --git a/layers/vyos-proxy/Makefile b/layers/vyos-proxy/Makefile
deleted file mode 100644 (file)
index a1ad3a5..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/make
-
-all: lint unit_test
-
-
-.PHONY: clean
-clean:
-       @rm -rf .tox
-
-.PHONY: apt_prereqs
-apt_prereqs:
-       @# Need tox, but don't install the apt version unless we have to (don't want to conflict with pip)
-       @which tox >/dev/null || (sudo apt-get install -y python-pip && sudo pip install tox)
-
-.PHONY: lint
-lint: apt_prereqs
-       @tox --notest
-       @PATH=.tox/py34/bin:.tox/py35/bin flake8 $(wildcard hooks reactive lib unit_tests tests)
-       @charm proof
-
-.PHONY: unit_test
-unit_test: apt_prereqs
-       @echo Starting tests...
-       tox
diff --git a/layers/vyos-proxy/README.md b/layers/vyos-proxy/README.md
deleted file mode 100644 (file)
index 0337c83..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-# 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][].
-
-### Charm Dependencies
-
-Each layer can include a `wheelhouse.txt` file with Python requirement lines.
-For example, this layer's `wheelhouse.txt` includes:
-
-```
-pip>=7.0.0,<8.0.0
-charmhelpers>=0.4.0,<1.0.0
-charms.reactive>=0.1.0,<2.0.0
-```
-
-All of these dependencies from each layer will be fetched (and updated) at build
-time and will be automatically installed by this base layer before any reactive
-handlers are run.
-
-Note that the `wheelhouse.txt` file is intended for **charm** dependencies only.
-That is, for libraries that the charm code itself needs to do its job of deploying
-and configuring the payload.  If the payload itself has Python dependencies, those
-should be handled separately, by the charm.
-
-See [PyPI][pypi charms.X] for packages under the `charms.` namespace which might
-be useful for your charm.
-
-### Layer Namespace
-
-Each layer has a reserved section in the `charms.layer.` Python package namespace,
-which it can populate by including a `lib/charms/layer/<layer-name>.py` file or
-by placing files under `lib/charms/layer/<layer-name>/`.  (If the layer name
-includes hyphens, replace them with underscores.)  These can be helpers that the
-layer uses internally, or it can expose classes or functions to be used by other
-layers to interact with that layer.
-
-For example, a layer named `foo` could include a `lib/charms/layer/foo.py` file
-with some helper functions that other layers could access using:
-
-```python
-from charms.layer.foo import my_helper
-```
-
-### Layer Options
-
-Any layer can define options in its `layer.yaml`.  Those options can then be set
-by other layers to change the behavior of your layer.  The options are defined
-using [jsonschema][], which is the same way that [action paramters][] are defined.
-
-For example, the `foo` layer could include the following option definitons:
-
-```yaml
-includes: ['layer:basic']
-defines:  # define some options for this layer (the layer "foo")
-  enable-bar:  # define an "enable-bar" option for this layer
-    description: If true, enable support for "bar".
-    type: boolean
-    default: false
-```
-
-A layer using `foo` could then set it:
-
-```yaml
-includes: ['layer:foo']
-options:
-  foo:  # setting options for the "foo" layer
-    enable-bar: true  # set the "enable-bar" option to true
-```
-
-The `foo` layer can then use the `charms.layer.options` helper to load the values
-for the options that it defined.  For example:
-
-```python
-from charms import layer
-
-@when('state')
-def do_thing():
-  layer_opts = layer.options('foo')  # load all of the options for the "foo" layer
-  if layer_opts['enable-bar']:  # check the value of the "enable-bar" option
-      hookenv.log("Bar is enabled")
-```
-
-You can also access layer options in other handlers, such as Bash, using
-the command-line interface:
-
-```bash
-. charms.reactive.sh
-
-@when 'state'
-function do_thing() {
-    if layer_option foo enable-bar; then
-        juju-log "Bar is enabled"
-        juju-log "bar-value is: $(layer_option foo bar-value)"
-    fi
-}
-
-reactive_handler_main
-```
-
-Note that options of type `boolean` will set the exit code, while other types
-will be printed out.
-
-# 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 supports the following options, which can be set in `layer.yaml`:
-
-  * **packages**  A list of system packages to be installed before the reactive
-    handlers are invoked.
-
-  * **use_venv**  If set to true, the charm dependencies from the various
-    layers' `wheelhouse.txt` files will be installed in a Python virtualenv
-    located at `$CHARM_DIR/../.venv`.  This keeps charm dependencies from
-    conflicting with payload dependencies, but you must take care to preserve
-    the environment and interpreter if using `execl` or `subprocess`.
-
-  * **include_system_packages**  If set to true and using a venv, include
-    the `--system-site-packages` options to make system Python libraries
-    visible within the venv.
-
-An example `layer.yaml` using these options might be:
-
-```yaml
-includes: ['layer:basic']
-options:
-  basic:
-    packages: ['git']
-    use_venv: true
-    include_system_packages: true
-```
-
-
-# Reactive States
-
-This layer will set the following states:
-
-  * **`config.changed`**  Any config option has changed from its previous value.
-    This state is cleared automatically at the end of each hook invocation.
-
-  * **`config.changed.<option>`** A specific config option has changed.
-    **`<option>`** will be replaced by the config option name from `config.yaml`.
-    This state is cleared automatically at the end of each hook invocation.
-
-  * **`config.set.<option>`** A specific config option has a True or non-empty
-    value set.  **`<option>`** will be replaced by the config option name from
-    `config.yaml`.  This state is cleared automatically at the end of each hook
-    invocation.
-
-  * **`config.default.<option>`** A specific config option is set to its
-    default value.  **`<option>`** will be replaced by the config option name
-    from `config.yaml`.  This state is cleared automatically at the end of
-    each hook invocation.
-
-An example using the config states would be:
-
-```python
-@when('config.changed.my-opt')
-def my_opt_changed():
-    update_config()
-    restart_service()
-```
-
-
-# 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
-[jsonschema]: http://json-schema.org/
-[action paramters]: https://jujucharms.com/docs/stable/authors-charm-actions
-[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
diff --git a/layers/vyos-proxy/actions.yaml b/layers/vyos-proxy/actions.yaml
deleted file mode 100644 (file)
index 2acc33d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-"ping":
-  "description": "ping a thing!"
-  "params":
-    "count":
-      "description": "Stop after sending count ECHO_REQUEST packets"
-      "type": "integer"
-      "default": !!int "30"
-    "destination":
-      "description": "destination of ping request"
-      "type": "string"
-  "required":
-  - "destination"
diff --git a/layers/vyos-proxy/actions/ping b/layers/vyos-proxy/actions/ping
deleted file mode 100755 (executable)
index 9850fe7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/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('actions.ping')
-
-try:
-    main()
-except Exception as e:
-    action_fail(repr(e))
diff --git a/layers/vyos-proxy/config.yaml b/layers/vyos-proxy/config.yaml
deleted file mode 100644 (file)
index 0780d5f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-"options":
-  "hostname":
-    "default": !!null ""
-    "type": "string"
-    "description": "Hostname or IP of the VyOS"
-  "user":
-    "type": "string"
-    "default": "vyos"
-    "description": "Username for VyOS"
-  "pass":
-    "type": "string"
-    "default": !!null ""
-    "description": "Password for VyOS"
diff --git a/layers/vyos-proxy/copyright b/layers/vyos-proxy/copyright
deleted file mode 100644 (file)
index 720356a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
-
-Files: *
-Copyright: 2015, Canonical Ltd.
-License: Apache-2.0 
-
-License: Apache-2.0
- On Debian GNU/Linux system you can find the complete text of the
- Apache-2.0 license in '/usr/share/common-licenses/Apache-2.0'
diff --git a/layers/vyos-proxy/icon.svg b/layers/vyos-proxy/icon.svg
deleted file mode 100644 (file)
index e092eef..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
-<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
-\r
-<svg\r
-   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
-   xmlns:cc="http://creativecommons.org/ns#"\r
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
-   xmlns:svg="http://www.w3.org/2000/svg"\r
-   xmlns="http://www.w3.org/2000/svg"\r
-   xmlns:xlink="http://www.w3.org/1999/xlink"\r
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
-   width="96"\r
-   height="96"\r
-   id="svg6517"\r
-   version="1.1"\r
-   inkscape:version="0.48+devel r12274"\r
-   sodipodi:docname="Juju_charm_icon_template.svg">\r
-  <defs\r
-     id="defs6519">\r
-    <linearGradient\r
-       inkscape:collect="always"\r
-       xlink:href="#Background"\r
-       id="linearGradient6461"\r
-       gradientUnits="userSpaceOnUse"\r
-       x1="0"\r
-       y1="970.29498"\r
-       x2="144"\r
-       y2="970.29498"\r
-       gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />\r
-    <linearGradient\r
-       id="Background">\r
-      <stop\r
-         id="stop4178"\r
-         offset="0"\r
-         style="stop-color:#b8b8b8;stop-opacity:1" />\r
-      <stop\r
-         id="stop4180"\r
-         offset="1"\r
-         style="stop-color:#c9c9c9;stop-opacity:1" />\r
-    </linearGradient>\r
-    <filter\r
-       style="color-interpolation-filters:sRGB;"\r
-       inkscape:label="Inner Shadow"\r
-       id="filter1121">\r
-      <feFlood\r
-         flood-opacity="0.59999999999999998"\r
-         flood-color="rgb(0,0,0)"\r
-         result="flood"\r
-         id="feFlood1123" />\r
-      <feComposite\r
-         in="flood"\r
-         in2="SourceGraphic"\r
-         operator="out"\r
-         result="composite1"\r
-         id="feComposite1125" />\r
-      <feGaussianBlur\r
-         in="composite1"\r
-         stdDeviation="1"\r
-         result="blur"\r
-         id="feGaussianBlur1127" />\r
-      <feOffset\r
-         dx="0"\r
-         dy="2"\r
-         result="offset"\r
-         id="feOffset1129" />\r
-      <feComposite\r
-         in="offset"\r
-         in2="SourceGraphic"\r
-         operator="atop"\r
-         result="composite2"\r
-         id="feComposite1131" />\r
-    </filter>\r
-    <filter\r
-       style="color-interpolation-filters:sRGB;"\r
-       inkscape:label="Drop Shadow"\r
-       id="filter950">\r
-      <feFlood\r
-         flood-opacity="0.25"\r
-         flood-color="rgb(0,0,0)"\r
-         result="flood"\r
-         id="feFlood952" />\r
-      <feComposite\r
-         in="flood"\r
-         in2="SourceGraphic"\r
-         operator="in"\r
-         result="composite1"\r
-         id="feComposite954" />\r
-      <feGaussianBlur\r
-         in="composite1"\r
-         stdDeviation="1"\r
-         result="blur"\r
-         id="feGaussianBlur956" />\r
-      <feOffset\r
-         dx="0"\r
-         dy="1"\r
-         result="offset"\r
-         id="feOffset958" />\r
-      <feComposite\r
-         in="SourceGraphic"\r
-         in2="offset"\r
-         operator="over"\r
-         result="composite2"\r
-         id="feComposite960" />\r
-    </filter>\r
-    <clipPath\r
-       clipPathUnits="userSpaceOnUse"\r
-       id="clipPath873">\r
-      <g\r
-         transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"\r
-         id="g875"\r
-         inkscape:label="Layer 1"\r
-         style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">\r
-        <path\r
-           style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"\r
-           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"\r
-           id="path877"\r
-           inkscape:connector-curvature="0"\r
-           sodipodi:nodetypes="sssssssss" />\r
-      </g>\r
-    </clipPath>\r
-    <filter\r
-       inkscape:collect="always"\r
-       id="filter891"\r
-       inkscape:label="Badge Shadow">\r
-      <feGaussianBlur\r
-         inkscape:collect="always"\r
-         stdDeviation="0.71999962"\r
-         id="feGaussianBlur893" />\r
-    </filter>\r
-  </defs>\r
-  <sodipodi:namedview\r
-     id="base"\r
-     pagecolor="#ffffff"\r
-     bordercolor="#666666"\r
-     borderopacity="1.0"\r
-     inkscape:pageopacity="0.0"\r
-     inkscape:pageshadow="2"\r
-     inkscape:zoom="4.0745362"\r
-     inkscape:cx="18.514671"\r
-     inkscape:cy="49.018169"\r
-     inkscape:document-units="px"\r
-     inkscape:current-layer="layer1"\r
-     showgrid="true"\r
-     fit-margin-top="0"\r
-     fit-margin-left="0"\r
-     fit-margin-right="0"\r
-     fit-margin-bottom="0"\r
-     inkscape:window-width="1920"\r
-     inkscape:window-height="1029"\r
-     inkscape:window-x="0"\r
-     inkscape:window-y="24"\r
-     inkscape:window-maximized="1"\r
-     showborder="true"\r
-     showguides="true"\r
-     inkscape:guide-bbox="true"\r
-     inkscape:showpageshadow="false">\r
-    <inkscape:grid\r
-       type="xygrid"\r
-       id="grid821" />\r
-    <sodipodi:guide\r
-       orientation="1,0"\r
-       position="16,48"\r
-       id="guide823" />\r
-    <sodipodi:guide\r
-       orientation="0,1"\r
-       position="64,80"\r
-       id="guide825" />\r
-    <sodipodi:guide\r
-       orientation="1,0"\r
-       position="80,40"\r
-       id="guide827" />\r
-    <sodipodi:guide\r
-       orientation="0,1"\r
-       position="64,16"\r
-       id="guide829" />\r
-  </sodipodi:namedview>\r
-  <metadata\r
-     id="metadata6522">\r
-    <rdf:RDF>\r
-      <cc:Work\r
-         rdf:about="">\r
-        <dc:format>image/svg+xml</dc:format>\r
-        <dc:type\r
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
-        <dc:title></dc:title>\r
-      </cc:Work>\r
-    </rdf:RDF>\r
-  </metadata>\r
-  <g\r
-     inkscape:label="BACKGROUND"\r
-     inkscape:groupmode="layer"\r
-     id="layer1"\r
-     transform="translate(268,-635.29076)"\r
-     style="display:inline">\r
-    <path\r
-       style="fill:url(#linearGradient6461);fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"\r
-       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"\r
-       id="path6455"\r
-       inkscape:connector-curvature="0"\r
-       sodipodi:nodetypes="sssssssss" />\r
-  </g>\r
-  <g\r
-     inkscape:groupmode="layer"\r
-     id="layer3"\r
-     inkscape:label="PLACE YOUR PICTOGRAM HERE"\r
-     style="display:inline" />\r
-  <g\r
-     inkscape:groupmode="layer"\r
-     id="layer2"\r
-     inkscape:label="BADGE"\r
-     style="display:none"\r
-     sodipodi:insensitive="true">\r
-    <g\r
-       style="display:inline"\r
-       transform="translate(-340.00001,-581)"\r
-       id="g4394"\r
-       clip-path="none">\r
-      <g\r
-         id="g855">\r
-        <g\r
-           inkscape:groupmode="maskhelper"\r
-           id="g870"\r
-           clip-path="url(#clipPath873)"\r
-           style="opacity:0.6;filter:url(#filter891)">\r
-          <path\r
-             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             sodipodi:ry="12"\r
-             sodipodi:rx="12"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:cx="252"\r
-             id="path844"\r
-             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"\r
-             sodipodi:type="arc" />\r
-        </g>\r
-        <g\r
-           id="g862">\r
-          <path\r
-             sodipodi:type="arc"\r
-             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"\r
-             id="path4398"\r
-             sodipodi:cx="252"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:rx="12"\r
-             sodipodi:ry="12"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />\r
-          <path\r
-             transform="matrix(1.25,0,0,1.25,33,-100.45273)"\r
-             d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"\r
-             sodipodi:ry="12"\r
-             sodipodi:rx="12"\r
-             sodipodi:cy="552.36218"\r
-             sodipodi:cx="252"\r
-             id="path4400"\r
-             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"\r
-             sodipodi:type="arc" />\r
-          <path\r
-             sodipodi:type="star"\r
-             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"\r
-             id="path4459"\r
-             sodipodi:sides="5"\r
-             sodipodi:cx="666.19574"\r
-             sodipodi:cy="589.50385"\r
-             sodipodi:r1="7.2431178"\r
-             sodipodi:r2="4.3458705"\r
-             sodipodi:arg1="1.0471976"\r
-             sodipodi:arg2="1.6755161"\r
-             inkscape:flatsided="false"\r
-             inkscape:rounded="0.1"\r
-             inkscape:randomized="0"\r
-             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"\r
-             transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />\r
-        </g>\r
-      </g>\r
-    </g>\r
-  </g>\r
-</svg>\r
diff --git a/layers/vyos-proxy/layer.yaml b/layers/vyos-proxy/layer.yaml
deleted file mode 100644 (file)
index dd254f3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-"options":
-  "basic":
-    "packages":
-    - "python-dev"
-    - "libffi-dev"
-    - "libssl-dev"
-    "use_venv": !!bool "false"
-    "include_system_packages": !!bool "false"
-  "vyos-proxy": {}
-"includes":
-- "layer:basic"
-"is": "vyos-proxy"
-"repo": "https://osm.etsi.org/gerrit/osm/juju-charms"
diff --git a/layers/vyos-proxy/metadata.yaml b/layers/vyos-proxy/metadata.yaml
deleted file mode 100644 (file)
index 1d29b37..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-"name": "vyos-proxy"
-"summary": "VyOS Proxy charm for ping"
-"description": |
-  VyOS Proxy charm
-"tags":
-- "vnf"
-- "network"
-"maintainers":
-- "Marco Ceppi <marco.ceppi@canonical.com>"
-"series":
-- "xenial"
-- "trusty"
diff --git a/layers/vyos-proxy/reactive/__init__.py b/layers/vyos-proxy/reactive/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/layers/vyos-proxy/reactive/vyos_proxy.py b/layers/vyos-proxy/reactive/vyos_proxy.py
deleted file mode 100644 (file)
index a8fd5e0..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-
-import subprocess
-import paramiko
-
-from charmhelpers.core.hookenv import (
-    config,
-    status_set,
-    action_get,
-    action_set,
-    action_fail,
-)
-
-from charms.reactive import (
-    when,
-    when_not,
-    set_state as set_flag,
-    remove_state as remove_flag,
-)
-
-
-@when('config.changed')
-def test_connection():
-    status_set('maintenance', 'configuring ssh connection')
-    remove_flag('vyos-proxy.ready')
-    try:
-        who, _ = run('whoami')
-    except MgmtNotConfigured as e:
-        remove_flag('vyos-proxy.configured')
-        status_set('blocked', str(e))
-    except subprocess.CalledProcessError as e:
-        remove_flag('vyos-proxy.configured')
-        status_set('blocked', e.output)
-    else:
-        set_flag('vyos-proxy.configured')
-
-
-@when('vyos-proxy.configured')
-@when_not('vyos-proxy.ready')
-def vyos_proxy_ready():
-    status_set('active', 'ready')
-    set_flag('vyos-proxy.ready')
-
-
-@when('actions.ping')
-@when_not('vyos-proxy.configured')
-def pingme():
-    action_fail('proxy is not ready')
-
-
-@when('actions.ping')
-@when('vyos-proxy.configured')
-def pingme_forreal():
-    try:
-        result, err = run('ping -qc {} {}'.format(action_get('count'), action_get('destination')))
-    except:
-        action_fail('ping command failed')
-    finally:
-        remove_flag('actions.ping')
-
-    # Here you can send results back from ping, if you had time to parse it
-    action_set({'output': result})
-
-
-
-class MgmtNotConfigured(Exception):
-    pass
-
-
-def run(cmd):
-    ''' 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 '''
-
-    cfg = config()
-
-    hostname = cfg.get('hostname')
-    password = cfg.get('pass')
-    username = cfg.get('user')
-
-    if not (username and password and hostname):
-        raise MgmtNotConfigured('incomplete remote credentials')
-
-    client = paramiko.SSHClient()
-    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
-    try:
-        client.connect(cfg.get('hostname'), port=22,
-                       username=cfg.get('user'), password=cfg.get('pass'))
-    except paramiko.ssh_exception.AuthenticationException:
-        raise MgmtNotConfigured('invalid credentials')
-
-    stdin, stdout, stderr = client.exec_command(cmd)
-    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))
diff --git a/layers/vyos-proxy/requirements.txt b/layers/vyos-proxy/requirements.txt
deleted file mode 100644 (file)
index 28ecaca..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-flake8
-pytest
diff --git a/layers/vyos-proxy/revision b/layers/vyos-proxy/revision
deleted file mode 100644 (file)
index c227083..0000000
+++ /dev/null
@@ -1 +0,0 @@
-0
\ No newline at end of file
diff --git a/layers/vyos-proxy/tox.ini b/layers/vyos-proxy/tox.ini
deleted file mode 100644 (file)
index 0b8b27a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-[tox]
-skipsdist=True
-envlist = py34, py35
-skip_missing_interpreters = True
-
-[testenv]
-commands = py.test -v
-deps =
-    -r{toxinidir}/requirements.txt
-
-[flake8]
-exclude=docs
diff --git a/layers/vyos-proxy/wheelhouse.txt b/layers/vyos-proxy/wheelhouse.txt
deleted file mode 100644 (file)
index 24d2c9c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-paramiko==2.0.1