Initial Makefile for descriptor packages
authorAustin Cormier <Austin.Cormier@riftio.com>
Mon, 23 May 2016 23:12:00 +0000 (19:12 -0400)
committerAustin Cormier <Austin.Cormier@riftio.com>
Mon, 23 May 2016 23:12:00 +0000 (19:12 -0400)
89 files changed:
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/gen_nsd_pkg.sh [new file with mode: 0755]
src/gen_vnfd_pkg.sh [new file with mode: 0755]
src/generate_descriptor_pkg.sh [new file with mode: 0755]
src/nsd/gw_corpa_ns/README [new file with mode: 0644]
src/nsd/gw_corpa_ns/gwcorpA__nsd.yaml [new file with mode: 0644]
src/nsd/gw_corpa_ns/icons/osm_2x.png [new file with mode: 0644]
src/nsd/ims_allin1_corpa/IMS-corpA__nsd.yaml [new file with mode: 0644]
src/nsd/ims_allin1_corpa/icons/osm_2x.png [new file with mode: 0644]
src/nsd/ims_allin1_corpa/vnf_config/IMS-ALLIN1_2p__1.yaml [new file with mode: 0644]
src/nsd/mwc16_gen_ns/icons/osm_2x.png [new file with mode: 0644]
src/nsd/mwc16_gen_ns/mwc16-gen__nsd.yaml [new file with mode: 0644]
src/nsd/mwc16_pe_ns/icons/osm_2x.png [new file with mode: 0644]
src/nsd/mwc16_pe_ns/mwc16-pe__nsd.yaml [new file with mode: 0644]
src/nsd/mwc16_pe_ns/ns_config/mwc16-pe.yaml [new file with mode: 0644]
src/nsd/mwc16_pe_ns/scripts/add_corporation.py [new file with mode: 0755]
src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__1.yaml [new file with mode: 0644]
src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__2.yaml [new file with mode: 0644]
src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__3.yaml [new file with mode: 0644]
src/vnfd/6wind_vnf/6WindTR1.1.2__vnfd.yaml [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/.build.manifest [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/.gitignore [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/LICENSE [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/Makefile [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/README.md [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions.yaml [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/add-corporation [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/configure-interface [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/connect-domains [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/delete-corporation [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/delete-domain-connection [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/config.yaml [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/copyright [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/config-changed [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/hook.template [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/install [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/leader-elected [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/leader-settings-changed [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/start [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/stop [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/update-status [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/upgrade-charm [new file with mode: 0755]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/layer.yaml [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/bootstrap.py [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/layer.py [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/router.py [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/metadata.yaml [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/reactive/__init__.py [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/reactive/vpe_router.py [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/requirements.txt [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/tox.ini [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/Jinja2-2.8.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/MarkupSafe-0.23.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/PyYAML-3.11.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/Tempita-0.5.2.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charmhelpers-0.6.1.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charmhelpers-0.6.2.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charms.reactive-0.3.8.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/ecdsa-0.13.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/netaddr-0.7.18.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/paramiko-1.16.0.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pip-7.1.2.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pyaml-15.8.2.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pycrypto-2.6.1.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/six-1.10.0.tar.gz [new file with mode: 0644]
src/vnfd/6wind_vnf/icons/6wind_2x.png [new file with mode: 0644]
src/vnfd/gw_corpa_pe1_vnf/gw-corpa-pe1__vnfd.yaml [new file with mode: 0644]
src/vnfd/gw_corpa_pe2_vnf/gw-corpa-pe2__vnfd.yaml [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/IMS-ALLIN1__vnfd.yaml [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/README.md [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions.yaml [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/create-update-user [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/create-user [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/delete-user [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/config.yaml [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/copyright [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/config-changed [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/install [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/start [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/stop [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/upgrade-charm [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/icon.svg [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/lib/reconfigure-aio [new file with mode: 0755]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/metadata.yaml [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/revision [new file with mode: 0644]
src/vnfd/ims_allin1_2p_vnf/icons/metaswitch_2x.png [new file with mode: 0644]
src/vnfd/tidgen_mwc16_vnf/icons/tef.png [new file with mode: 0644]
src/vnfd/tidgen_mwc16_vnf/mwc16gen1__vnfd.yaml [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..1b2211d
--- /dev/null
@@ -0,0 +1 @@
+build*
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..0a01862
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,44 @@
+BUILD_DIR = build
+
+NSDS := gw_corpa_ns ims_allin1_corpa mwc16_gen_ns mwc16_pe_ns
+NSD_SRC_DIR := src/nsd
+NSD_BUILD_DIR := $(BUILD_DIR)/nsd
+
+NSD_SRC_DIRS := $(addprefix $(NSD_SRC_DIR)/, $(NSDS))
+NSD_BUILD_DIRS := $(addprefix $(NSD_BUILD_DIR)/, $(NSDS))
+NSD_PKGS := $(addsuffix .tar.gz, $(NSDS))
+NSD_BUILD_PKGS := $(addprefix $(NSD_BUILD_DIR)_pkgs/, $(NSD_PKGS))
+
+VNFDS := 6wind_vnf gw_corpa_pe1_vnf gw_corpa_pe2_vnf ims_allin1_2p_vnf tidgen_mwc16_vnf
+VNFD_SRC_DIR := src/vnfd
+VNFD_BUILD_DIR := $(BUILD_DIR)/vnfd
+
+VNFD_SRC_DIRS := $(addprefix $(VNFD_SRC_DIR)/, $(VNFDS))
+VNFD_BUILD_DIRS := $(addprefix $(VNFD_BUILD_DIR)/, $(VNFDS))
+VNFD_PKGS := $(addsuffix .tar.gz, $(VNFDS))
+VNFD_BUILD_PKGS := $(addprefix $(VNFD_BUILD_DIR)_pkgs/, $(VNFD_PKGS))
+
+all: $(VNFD_BUILD_PKGS) ${NSD_BUILD_PKGS}
+       echo $@
+
+clean:
+       -@ $(RM) -rf $(BUILD_DIR)
+
+$(VNFD_BUILD_DIR)/%: $(VNFD_SRC_DIR)/%
+       mkdir -p $(VNFD_BUILD_DIR)
+       cp -rf $< $(VNFD_BUILD_DIR)
+
+       src/gen_vnfd_pkg.sh $< $@
+       src/generate_descriptor_pkg.sh $(BUILD_DIR)/vnfd_pkgs $@
+
+$(NSD_BUILD_DIR)/%: $(NSD_SRC_DIR)/%
+       mkdir -p $(NSD_BUILD_DIR)
+       cp -rf $< $(NSD_BUILD_DIR)
+
+       src/gen_nsd_pkg.sh $< $@
+
+$(BUILD_DIR)/nsd_pkgs/%.tar.gz: $(NSD_BUILD_DIR)/%
+       src/generate_descriptor_pkg.sh $(BUILD_DIR)/nsd_pkgs $<
+
+$(BUILD_DIR)/vnfd_pkgs/%.tar.gz: $(VNFD_BUILD_DIR)/%
+       src/generate_descriptor_pkg.sh $(BUILD_DIR)/vnfd_pkgs $<
diff --git a/src/gen_nsd_pkg.sh b/src/gen_nsd_pkg.sh
new file mode 100755 (executable)
index 0000000..ea5e6a7
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Generates a NSD descriptor package from a source directory
+# Usage:
+# gen_nsd_pkg.sh <pkg_src_dir> <pkg_dest_dir>
+
+set -o nounset
+
+if [ $# -ne 2 ]; then
+       echo "Error: Must provide 2 parameters" >@2
+       exit 1
+fi
+
+pkg_src_dir="$1"
+pkg_dest_dir="$2"
+
+if [ ! -e ${pkg_src_dir} ]; then
+    echo "Error: ${pkg_src_dir} does not exist"
+    exit 1
+fi
+
+if [ ! -e ${pkg_dest_dir} ]; then
+    echo "Error: ${pkg_src_dir} does not exist"
+    exit 1
+fi
+
+echo "Generating package in directory: ${pkg_dest_dir}"
+
+# Create any missing directories/files so each package has
+# a complete hierachy
+nsd_dirs=( ns_config vnf_config icons scripts )
+nsd_files=( README )
+
+nsd_dir="${pkg_src_dir}"
+echo $(pwd)
+
+mkdir -p "${pkg_dest_dir}"
+cp -rf ${nsd_dir}/* "${pkg_dest_dir}"
+for sub_dir in ${nsd_dirs[@]}; do
+    dir_path=${pkg_dest_dir}/${sub_dir}
+    mkdir -p ${dir_path}
+done
+
+for file in ${nsd_files[@]}; do
+    file_path=${pkg_dest_dir}/${file}
+    touch ${file_path}
+done
diff --git a/src/gen_vnfd_pkg.sh b/src/gen_vnfd_pkg.sh
new file mode 100755 (executable)
index 0000000..478d5c5
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Generates a NSD descriptor package from a source directory
+# Usage:
+# gen_vnfd_pkg.sh <pkg_src_dir> <pkg_dest_dir>
+
+set -o nounset
+
+if [ $# -ne 2 ]; then
+       echo "Error: Must provide 2 parameters" >@2
+       exit 1
+fi
+
+pkg_src_dir="$1"
+pkg_dest_dir="$2"
+
+if [ ! -e ${pkg_src_dir} ]; then
+    echo "Error: ${pkg_src_dir} does not exist"
+    exit 1
+fi
+
+if [ ! -e ${pkg_dest_dir} ]; then
+    echo "Error: ${pkg_src_dir} does not exist"
+    exit 1
+fi
+
+echo "Generating package in directory: ${pkg_dest_dir}"
+
+# Create any missing directories/files so each package has
+# a complete hierachy
+vnfd_dirs=( charms icons scripts images )
+vnfd_files=( README )
+
+vnfd_dir="${pkg_src_dir}"
+echo $(pwd)
+
+mkdir -p "${pkg_dest_dir}"
+cp -rf ${vnfd_dir}/* "${pkg_dest_dir}"
+for sub_dir in ${vnfd_dirs[@]}; do
+    dir_path=${pkg_dest_dir}/${sub_dir}
+    mkdir -p ${dir_path}
+done
+
+for file in ${vnfd_files[@]}; do
+    file_path=${pkg_dest_dir}/${file}
+    touch ${file_path}
+done
diff --git a/src/generate_descriptor_pkg.sh b/src/generate_descriptor_pkg.sh
new file mode 100755 (executable)
index 0000000..82ecda1
--- /dev/null
@@ -0,0 +1,27 @@
+#! /usr/bin/bash
+# STANDARD_RIFT_IO_COPYRIGHT
+# Author(s): Anil Gunturu
+# Creation Date: 2015/10/09
+#
+# This shell script is used to create a descriptor package
+# The main functions of this script include:
+# - Generate checksums.txt file
+# - Generate a tar.gz file
+
+# Usage: generate_descriptor_pkg.sh <package-directory> <dest_package_dir>
+
+mkdir -p $1
+mkdir -p $2
+
+dest_dir=$(cd $1 && pwd)
+pkg_dir=$(cd $2 && pwd)
+
+echo $(pwd)
+cd ${pkg_dir}
+rm -rf checksums.txt
+find * -type f |
+    while read file; do
+        md5sum $file >> checksums.txt
+    done
+cd ..
+tar -zcvf ${dest_dir}/$(basename $pkg_dir).tar.gz $(basename $pkg_dir)
diff --git a/src/nsd/gw_corpa_ns/README b/src/nsd/gw_corpa_ns/README
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/nsd/gw_corpa_ns/gwcorpA__nsd.yaml b/src/nsd/gw_corpa_ns/gwcorpA__nsd.yaml
new file mode 100644 (file)
index 0000000..34caf2d
--- /dev/null
@@ -0,0 +1,75 @@
+nsd:nsd-catalog:
+    nsd:
+    -   id: gw_corpA
+        name: gw_corpA
+        short-name: gw_corpA
+        description: Gateways to access as corpA to PE1 and PE2
+        logo: osm_2x.png
+        constituent-vnfd:
+        -   member-vnf-index: '1'
+            vnfd-id-ref: gw_corpA_PE1
+        -   member-vnf-index: '2'
+            vnfd-id-ref: gw_corpA_PE2
+        vld:
+        -   id: connection_0
+            name: connection_0
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mgmt
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: eth1
+                vnfd-id-ref: gw_corpA_PE1
+        -   id: connection_1
+            name: connection_1
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mgmt
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: eth1
+                vnfd-id-ref: gw_corpA_PE2
+        -   id: connection_2
+            name: connection_2
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc1
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: eth0
+                vnfd-id-ref: gw_corpA_PE1
+        -   id: connection_3
+            name: connection_3
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc2
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: eth0
+                vnfd-id-ref: gw_corpA_PE2
+        -   id: connection_4
+            name: connection_4
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc16data1
+                segmentation_id: '101'
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: gw_corpA_PE1
+        -   id: connection_5
+            name: connection_5
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc16data2
+                segmentation_id: '102'
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: gw_corpA_PE2
diff --git a/src/nsd/gw_corpa_ns/icons/osm_2x.png b/src/nsd/gw_corpa_ns/icons/osm_2x.png
new file mode 100644 (file)
index 0000000..62012d2
Binary files /dev/null and b/src/nsd/gw_corpa_ns/icons/osm_2x.png differ
diff --git a/src/nsd/ims_allin1_corpa/IMS-corpA__nsd.yaml b/src/nsd/ims_allin1_corpa/IMS-corpA__nsd.yaml
new file mode 100644 (file)
index 0000000..27a1197
--- /dev/null
@@ -0,0 +1,57 @@
+nsd:nsd-catalog:
+    nsd:
+    -   id: IMS-corpA
+        name: IMS-corpA
+        short-name: IMS-corpA
+        description: All in one Clearwater IMS for corporation A in MWC16
+        logo: osm_2x.png
+        constituent-vnfd:
+        -   member-vnf-index: '1'
+            vnfd-id-ref: IMS-ALLIN1_2p
+        vld:
+        -   id: data
+            name: data
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: net-corp
+                segmentation_id: '108'
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: eth0
+                vnfd-id-ref: IMS-ALLIN1_2p
+        -   id: management
+            name: management
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: net-mgmtOS
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: eth1
+                vnfd-id-ref: IMS-ALLIN1_2p
+        config-primitive:
+        -   name: Update Domain
+            vnf-primitive-group:
+            -   member-vnf-index-ref: '1'
+                vnfd-id-ref: IMS-ALLIN1_2p
+                vnfd-name: cwims_vnfd
+                primitive:
+                -   index: '1'
+                    name: config
+        -   name: Add User
+            vnf-primitive-group:
+            -   member-vnf-index-ref: '1'
+                vnfd-id-ref: IMS-ALLIN1_2p
+                vnfd-name: cwims_vnfd
+                primitive:
+                -   index: '1'
+                    name: create-update-user
+        -   name: Delete User
+            vnf-primitive-group:
+            -   member-vnf-index-ref: '1'
+                vnfd-id-ref: IMS-ALLIN1_2p
+                vnfd-name: cwims_vnfd
+                primitive:
+                -   index: '1'
+                    name: delete-user
diff --git a/src/nsd/ims_allin1_corpa/icons/osm_2x.png b/src/nsd/ims_allin1_corpa/icons/osm_2x.png
new file mode 100644 (file)
index 0000000..62012d2
Binary files /dev/null and b/src/nsd/ims_allin1_corpa/icons/osm_2x.png differ
diff --git a/src/nsd/ims_allin1_corpa/vnf_config/IMS-ALLIN1_2p__1.yaml b/src/nsd/ims_allin1_corpa/vnf_config/IMS-ALLIN1_2p__1.yaml
new file mode 100644 (file)
index 0000000..33c5ef9
--- /dev/null
@@ -0,0 +1,4 @@
+initial_config_primitive:
+- name: config
+  parameter:
+    proxied_ip: <rw_mgmt_ip>
diff --git a/src/nsd/mwc16_gen_ns/icons/osm_2x.png b/src/nsd/mwc16_gen_ns/icons/osm_2x.png
new file mode 100644 (file)
index 0000000..62012d2
Binary files /dev/null and b/src/nsd/mwc16_gen_ns/icons/osm_2x.png differ
diff --git a/src/nsd/mwc16_gen_ns/mwc16-gen__nsd.yaml b/src/nsd/mwc16_gen_ns/mwc16-gen__nsd.yaml
new file mode 100644 (file)
index 0000000..534b52a
--- /dev/null
@@ -0,0 +1,53 @@
+nsd:nsd-catalog:
+    nsd:
+    -   id: mwc16_traffic_generator
+        name: mwc16_traffic_generator
+        short-name: mwc16_traffic_generator
+        description: Traffic generator connected to the demo environment
+        logo: osm_2x.png
+        constituent-vnfd:
+        -   member-vnf-index: '1'
+            vnfd-id-ref: mwc16gen
+        vld:
+        -   id: connection 0
+            name: connection 0
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: eth0
+                vnfd-id-ref: mwc16gen
+        -   id: connection 1
+            name: connection 1
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mgmt
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: eth1
+                vnfd-id-ref: mwc16gen
+        -   id: connection 2
+            name: connection 2
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc16data1
+                segmentation_id: '3000'
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: mwc16gen
+        -   id: connection 3
+            name: connection 3
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc16data2
+                segmentation_id: '3000'
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe2
+                vnfd-id-ref: mwc16gen
diff --git a/src/nsd/mwc16_pe_ns/icons/osm_2x.png b/src/nsd/mwc16_pe_ns/icons/osm_2x.png
new file mode 100644 (file)
index 0000000..62012d2
Binary files /dev/null and b/src/nsd/mwc16_pe_ns/icons/osm_2x.png differ
diff --git a/src/nsd/mwc16_pe_ns/mwc16-pe__nsd.yaml b/src/nsd/mwc16_pe_ns/mwc16-pe__nsd.yaml
new file mode 100644 (file)
index 0000000..7a2d38a
--- /dev/null
@@ -0,0 +1,247 @@
+nsd:nsd-catalog:
+    nsd:
+    -   id: mwc16-pe
+        name: mwc16-pe
+        short-name: mwc16-pe
+        description: mwc16-pe
+        logo: osm_2x.png
+        constituent-vnfd:
+        -   member-vnf-index: '1'
+            vnfd-id-ref: 6WindTR1.1.2
+        -   member-vnf-index: '2'
+            vnfd-id-ref: 6WindTR1.1.2
+        -   member-vnf-index: '3'
+            vnfd-id-ref: 6WindTR1.1.2
+        vld:
+        -   id: 6WindTR1.1.2__3 to OpenStack
+            name: 6WindTR1.1.2__3 to OpenStack
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: interDC
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '3'
+                vnfd-connection-point-ref: xe3
+                vnfd-id-ref: 6WindTR1.1.2
+        -   id: 6WindTR1.1.2__1 enty point
+            name: 6WindTR1.1.2__1 enty point
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc16data1
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe2
+                vnfd-id-ref: 6WindTR1.1.2
+        -   id: 6WindTR1.1.2__2 entry point
+            name: 6WindTR1.1.2__2 entry point
+            type: ELAN
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mwc16data2
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: xe2
+                vnfd-id-ref: 6WindTR1.1.2
+        -   id: management
+            name: management
+            provider-network:
+                overlay-type: VLAN
+                physical-network: mgmt
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: eth0
+                vnfd-id-ref: 6WindTR1.1.2
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: eth0
+                vnfd-id-ref: 6WindTR1.1.2
+            -   member-vnf-index-ref: '3'
+                vnfd-connection-point-ref: eth0
+                vnfd-id-ref: 6WindTR1.1.2
+        -   id: 6WindTR1.1.2__2-6WindTR1.1.2__3
+            name: 6WindTR1.1.2__2-6WindTR1.1.2__3
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: 6WindTR1.1.2
+            -   member-vnf-index-ref: '3'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: 6WindTR1.1.2
+        -   id: 6WindTR1.1.2__1-6WindTR1.1.2__3
+            name: 6WindTR1.1.2__1-6WindTR1.1.2__3
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: 6WindTR1.1.2
+            -   member-vnf-index-ref: '3'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: 6WindTR1.1.2
+        -   id: 6WindTR1.1.2__1-6WindTR1.1.2__2
+            name: 6WindTR1.1.2__1-6WindTR1.1.2__2
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: 6WindTR1.1.2
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: 6WindTR1.1.2
+        config-primitive:
+        -   name: Add SP Test Corporation
+            parameter:
+            -   name: Corporation Name
+                data-type: string
+                default-value: SP Test Corp
+                mandatory: 'true'
+            -   name: Tunnel Key
+                data-type: integer
+                default-value: '10'
+                hidden: 'true'
+                mandatory: 'true'
+            parameter-group:
+            -   mandatory: 'false'
+                name: PE1
+                parameter:
+                -   name: Vlan ID
+                    data-type: integer
+                    default-value: '3000'
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Interface Name
+                    data-type: string
+                    default-value: eth3
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Corp. Network
+                    data-type: string
+                    default-value: 10.0.1.0/24
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Corp. Gateway
+                    data-type: string
+                    default-value: 10.0.1.1
+                    hidden: 'true'
+                    mandatory: 'true'
+            -   mandatory: 'false'
+                name: PE2
+                parameter:
+                -   name: Vlan ID
+                    data-type: integer
+                    default-value: '3000'
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Interface Name
+                    data-type: string
+                    default-value: eth3
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Corp. Network
+                    data-type: string
+                    default-value: 10.0.2.0/24
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Corp. Gateway
+                    data-type: string
+                    default-value: 10.0.2.1
+                    hidden: 'true'
+                    mandatory: 'true'
+            -   mandatory: 'false'
+                name: PE3
+                parameter:
+                -   name: Vlan ID
+                    data-type: integer
+                    default-value: '3000'
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Interface Name
+                    data-type: string
+                    default-value: eth3
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Corp. Network
+                    data-type: string
+                    default-value: 10.0.3.0/24
+                    hidden: 'true'
+                    mandatory: 'true'
+                -   name: Corp. Gateway
+                    data-type: string
+                    default-value: 10.0.3.1
+                    hidden: 'true'
+                    mandatory: 'true'
+            user-defined-script: add_corporation.py
+        -   name: Add Corporation
+            parameter:
+            -   name: Corporation Name
+                data-type: string
+                default-value: CorpA
+                mandatory: 'true'
+            -   name: Tunnel Key
+                data-type: integer
+                default-value: '1'
+                hidden: 'true'
+                mandatory: 'true'
+            parameter-group:
+            -   mandatory: 'false'
+                name: PE1
+                parameter:
+                -   name: Vlan ID
+                    data-type: integer
+                    default-value: '101'
+                    mandatory: 'true'
+                    read-only: 'true'
+                -   name: Interface Name
+                    data-type: string
+                    default-value: eth3
+                    mandatory: 'true'
+                -   name: Corp. Network
+                    data-type: string
+                    default-value: 10.0.1.0/24
+                    mandatory: 'true'
+                -   name: Corp. Gateway
+                    data-type: string
+                    default-value: 10.0.1.1
+                    mandatory: 'true'
+            -   mandatory: 'false'
+                name: PE2
+                parameter:
+                -   name: Vlan ID
+                    data-type: integer
+                    default-value: '102'
+                    mandatory: 'true'
+                    read-only: 'true'
+                -   name: Interface Name
+                    data-type: string
+                    default-value: eth3
+                    mandatory: 'true'
+                -   name: Corp. Network
+                    data-type: string
+                    default-value: 10.0.2.0/24
+                    mandatory: 'true'
+                -   name: Corp. Gateway
+                    data-type: string
+                    default-value: 10.0.2.1
+                    mandatory: 'true'
+            -   mandatory: 'false'
+                name: PE3
+                parameter:
+                -   name: Vlan ID
+                    data-type: integer
+                    default-value: '108'
+                    mandatory: 'true'
+                    read-only: 'true'
+                -   name: Interface Name
+                    data-type: string
+                    default-value: eth4
+                    mandatory: 'true'
+                -   name: Corp. Network
+                    data-type: string
+                    default-value: 10.0.4.0/24
+                    mandatory: 'true'
+                -   name: Corp. Gateway
+                    data-type: string
+                    default-value: 10.0.4.1
+                    mandatory: 'true'
+            user-defined-script: add_corporation.py
diff --git a/src/nsd/mwc16_pe_ns/ns_config/mwc16-pe.yaml b/src/nsd/mwc16_pe_ns/ns_config/mwc16-pe.yaml
new file mode 100644 (file)
index 0000000..42276d2
--- /dev/null
@@ -0,0 +1,40 @@
+Add Corporation:
+  parameter:
+    Tunnel Key: '1'
+    Corporation Name: 'CorpA'
+  parameter_group:
+    PE1:
+      Corp. Gateway: 10.0.1.1
+      Corp. Network: 10.0.1.0/24
+      Interface Name: eth3
+      Vlan ID: '101'
+    PE2:
+      Corp. Gateway: 10.0.2.1
+      Corp. Network: 10.0.2.0/24
+      Interface Name: eth3
+      Vlan ID: '102'
+    PE3:
+      Corp. Gateway: 10.0.4.1
+      Corp. Network: 10.0.4.0/24
+      Interface Name: eth4
+      Vlan ID: '108'
+Add SP Test Corporation:
+  parameter:
+    Tunnel Key: '10'
+    Corporation Name: 'SP Test Corp'
+  parameter_group:
+    PE1:
+      Corp. Gateway: 10.0.1.1
+      Corp. Network: 10.0.1.0/24
+      Interface Name: eth3
+      Vlan ID: '3000'
+    PE2:
+      Corp. Gateway: 10.0.2.1
+      Corp. Network: 10.0.2.0/24
+      Interface Name: eth3
+      Vlan ID: '3000'
+    PE3:
+      Corp. Gateway: 10.0.3.1
+      Corp. Network: 10.0.3.0/24
+      Interface Name: eth3
+      Vlan ID: '3000'
diff --git a/src/nsd/mwc16_pe_ns/scripts/add_corporation.py b/src/nsd/mwc16_pe_ns/scripts/add_corporation.py
new file mode 100755 (executable)
index 0000000..4b2bb4c
--- /dev/null
@@ -0,0 +1,513 @@
+#!/usr/bin/env python3
+import argparse
+import hashlib
+import ipaddress
+import itertools
+import jujuclient
+import logging
+import sys
+import time
+import yaml
+
+
+logging.basicConfig(filename="/tmp/rift_ns_add_corp.log", level=logging.DEBUG)
+logger = logging.getLogger()
+
+ch = logging.StreamHandler()
+ch.setLevel(logging.INFO)
+
+# create formatter and add it to the handlers
+formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ch.setFormatter(formatter)
+logger.addHandler(ch)
+
+
+dry_run = False
+
+class JujuActionError(Exception):
+    pass
+
+
+class JujuClient(object):
+    """Class for executing Juju actions """
+    def __init__(self, ip, port, user, passwd):
+        self._ip = ip
+        self._port = port
+        self._user = user
+        self._passwd = passwd
+
+        endpoint = 'wss://%s:%d' % (ip, port)
+        logger.debug("Using endpoint=%s", endpoint)
+        if dry_run:
+            return
+        self.env = jujuclient.Environment(endpoint)
+        self.env.login(passwd, user)
+
+    def get_service(self, name):
+        return self.env.get_service(name)
+
+    def _get_units(self, name):
+        """
+        Get the units associated with service
+        """
+        units = self.env.status(name)['Services'][name]['Units']
+        units = list(units.keys())
+
+        # convert to a friendly format for juju-python-client
+        units[:] = [('unit-%s' % u).replace('/', '-') for u in units]
+        return units
+
+    def exec_action(self, name, action_name, params, block=False):
+        logger.debug("execute actiion %s using params %s", action_name, params)
+        if dry_run:
+            return
+
+        actions = jujuclient.Actions(self.env)
+        results = actions.enqueue_units(self._get_units(name),
+                                        action_name,
+                                        params)
+        if not block:
+            return results
+
+        if 'error' in results['results'][0].keys():
+            raise JujuActionError("Juju action error: %s" % results['results'][0])
+
+        action = results['results'][0]['action']
+        info = actions.info([action])
+        i = 0
+        logging.debug("Initial action results: %s", results['results'][0])
+        while info['results'][0]['status'] not in ['completed', 'failed']:
+            time.sleep(1)
+            info = actions.info([action])
+
+            # break out if the action doesn't complete in 10 secs
+            i += 1
+            if i == 10:
+                raise JujuActionError("Juju action timed out after 30 seconds")
+
+        if info['results'][0]['status'] != 'completed':
+            raise JujuActionError("Action %s failure: %s" % (action_name, info['results'][0]))
+
+        return info
+
+
+class CharmAction(object):
+    def __init__(self, deployed_name, action_name, action_params=None):
+        self._deployed_name = deployed_name
+        self._action_name = action_name
+        self._params = action_params if action_params is not None else []
+
+    def execute(self, juju_client):
+        logger.info("Executing charm (%s) action (%s) with params (%s)",
+                     self._deployed_name, self._action_name, self._params)
+        try:
+            info = juju_client.exec_action(
+                    name=self._deployed_name,
+                    action_name=self._action_name,
+                    params=self._params,
+                    block=True
+                    )
+
+        except JujuActionError as e:
+            logger.error("Juju charm (%s) action (%s) failed: %s",
+                         self._deployed_name, self._action_name, str(e))
+            raise
+
+        logger.debug("Juju charm (%s) action (%s) success.",
+                     self._deployed_name, self._action_name)
+
+
+class DeployedProxyCharm(object):
+    def __init__(self, juju_client, service_name, mgmt_ip=None, charm_name=None):
+        self._juju_client = juju_client
+        self.service_name = service_name
+        self.mgmt_ip = mgmt_ip
+        self.charm_name = charm_name
+
+    def do_action(self, action_name, action_params={}):
+        action = CharmAction(self.service_name, action_name, action_params)
+        action.execute(self._juju_client)
+
+
+class SixWindPEProxyCharm(DeployedProxyCharm):
+    USER = "root"
+    PASSWD = "6windos"
+
+    def configure_interface(self, iface_name, ipv4_interface_str=None):
+        action = "configure-interface"
+        params = {'iface-name', iface_name}
+
+        if ipv4_interface_str is None:
+            # Use ipaddress module to validate ipv4 interface string
+            ip_intf = ipaddress.IPv4Interface(ipv4_interface_str)
+            params["cidr"] = ip_intf.with_prefixlen
+
+            self.do_action(action, params)
+        else:
+            self.do_action(action, params)
+
+
+    def add_corporation(self, domain_name, user_iface_name, vlan_id, corp_gw,
+                        corp_net, local_net="10.255.255.0/24", local_net_area="0"):
+        logger.debug("Add corporation called with params: %s", locals())
+
+        action = "add-corporation"
+        params = {
+                "domain-name": domain_name,
+                "iface-name": user_iface_name,
+                "vlan-id": int(vlan_id),
+                "cidr": corp_net,
+                "area": corp_gw,
+                "subnet-cidr":local_net,
+                "subnet-area":local_net_area,
+                }
+
+        self.do_action(action, params)
+
+    def connect_domains(self, domain_name, core_iface_name, local_ip, remote_ip,
+                        internal_local_ip, internal_remote_ip, tunnel_name,
+                        tunnel_key, tunnel_type="gre"):
+
+        logger.debug("Connect domains called with params: %s", locals())
+
+        action = "connect-domains"
+        params = {
+                "domain-name": domain_name,
+                "iface-name": core_iface_name,
+                "tunnel-name": tunnel_name,
+                "local-ip": local_ip,
+                "remote-ip": remote_ip,
+                "tunnel-key": tunnel_key,
+                "internal-local-ip": internal_local_ip,
+                "internal-remote-ip": internal_remote_ip,
+                "tunnel-type":tunnel_type,
+                }
+
+        self.do_action(action, params)
+
+
+class PEGroupConfig(object):
+    def __init__(self, pe_group_cfg):
+        self._pe_group_cfg = pe_group_cfg
+
+    def _get_param_value(self, param_name):
+        for param in self._pe_group_cfg["parameter"]:
+            if param["name"] == param_name:
+                return param["value"]
+
+        raise ValueError("PE param not found: %s" % param_name)
+
+    @property
+    def vlan_id(self):
+        return self._get_param_value("Vlan ID")
+
+    @property
+    def interface_name(self):
+        return self._get_param_value("Interface Name")
+
+    @property
+    def corp_network(self):
+        return self._get_param_value("Corp. Network")
+
+    @property
+    def corp_gateway(self):
+        return self._get_param_value("Corp. Gateway")
+
+
+class AddCorporationRequest(object):
+    def __init__(self, add_corporation_rpc):
+        self._add_corporation_rpc = add_corporation_rpc
+
+    @property
+    def name(self):
+        return self._add_corporation_rpc["name"]
+
+    @property
+    def param_groups(self):
+        return self._add_corporation_rpc["parameter_group"]
+
+    @property
+    def params(self):
+        return self._add_corporation_rpc["parameter"]
+
+    @property
+    def corporation_name(self):
+        for param in self.params:
+            if param["name"] == "Corporation Name":
+                return param["value"]
+
+        raise ValueError("Could not find 'Corporation Name' field")
+
+    @property
+    def tunnel_key(self):
+        for param in self.params:
+            if param["name"] == "Tunnel Key":
+                return param["value"]
+
+        raise ValueError("Could not find 'Tunnel Key' field")
+
+    def get_pe_parameter_group_map(self):
+        group_name_map = {}
+        for group in self.param_groups:
+            group_name_map[group["name"]] = group
+
+        return group_name_map
+
+    def get_parameter_name_map(self):
+        name_param_map = {}
+        for param in self.params:
+            name_param_map[param["name"]] = param
+
+        return name_param_map
+
+    @classmethod
+    def from_yaml_cfg(cls, yaml_hdl):
+        config = yaml.load(yaml_hdl)
+        return cls(
+                config["rpc_ip"],
+                )
+
+
+class JujuVNFConfig(object):
+    def __init__(self, vnfr_index_map, vnf_name_map, vnf_init_config_map):
+        self._vnfr_index_map = vnfr_index_map
+        self._vnf_name_map = vnf_name_map
+        self._vnf_init_config_map = vnf_name_map
+
+    def get_service_name(self, vnf_index):
+        for vnfr_id, index in self._vnfr_index_map.items():
+            if index != vnf_index:
+                continue
+
+            return self._vnf_name_map[vnfr_id]
+
+        raise ValueError("VNF Index not found: %s" % vnf_index)
+
+    def get_vnfr_id(self, vnf_index):
+        for vnfr_id, index in self._vnfr_index_map.items():
+            if index != vnf_index:
+                continue
+
+            return vnfr_id
+
+        raise ValueError("VNF Index not found: %s" % vnf_index)
+
+    @classmethod
+    def from_yaml_cfg(cls, yaml_hdl):
+        config = yaml.load(yaml_hdl)
+        return cls(
+                config["vnfr_index_map"],
+                config["unit_names"],
+                config["init_config"],
+                )
+
+
+class JujuClientConfig(object):
+    def __init__(self, juju_ctrl_cfg):
+        self._juju_ctrl_cfg = juju_ctrl_cfg
+
+    @property
+    def name(self):
+        return self._juju_ctrl_cfg["name"]
+
+    @property
+    def host(self):
+        return self._juju_ctrl_cfg["host"]
+
+    @property
+    def port(self):
+        return self._juju_ctrl_cfg["port"]
+
+    @property
+    def user(self):
+        return self._juju_ctrl_cfg["user"]
+
+    @property
+    def secret(self):
+        return self._juju_ctrl_cfg["secret"]
+
+    @classmethod
+    def from_yaml_cfg(cls, yaml_hdl):
+        config = yaml.load(yaml_hdl)
+        return cls(
+                config["config_agent"],
+                )
+
+
+class OSM_MWC_Demo(object):
+    VNF_INDEX_NAME_MAP = {
+            "PE1": 1,
+            "PE2": 2,
+            "PE3": 3,
+        }
+
+    CORE_PE_CONN_MAP = {
+            "PE1": {
+                "PE2": {
+                    "ifacename": "eth1",
+                    "ip": "10.10.10.9",
+                    "mask": "30",
+                    "internal_local_ip": "10.255.255.1"
+                },
+                "PE3": {
+                    "ifacename": "eth2",
+                    "ip": "10.10.10.1",
+                    "mask": "30",
+                    "internal_local_ip": "10.255.255.1"
+                },
+            },
+            "PE2": {
+                "PE1": {
+                    "ifacename": "eth1",
+                    "ip": "10.10.10.10",
+                    "mask": "30",
+                    "internal_local_ip": "10.255.255.2"
+                },
+                "PE3": {
+                    "ifacename": "eth2",
+                    "ip": "10.10.10.6",
+                    "mask": "30",
+                    "internal_local_ip": "10.255.255.2"
+                }
+            },
+            "PE3": {
+                "PE1": {
+                    "ifacename": "eth1",
+                    "ip": "10.10.10.2",
+                    "mask": "30",
+                    "internal_local_ip": "10.255.255.3"
+                },
+                "PE2": {
+                    "ifacename": "eth2",
+                    "ip": "10.10.10.5",
+                    "mask": "30",
+                    "internal_local_ip": "10.255.255.3"
+                }
+            }
+        }
+
+    @staticmethod
+    def get_pe_vnf_index(pe_name):
+        if pe_name not in OSM_MWC_Demo.VNF_INDEX_NAME_MAP:
+            raise ValueError("Could not find PE name: %s", pe_name)
+
+        return OSM_MWC_Demo.VNF_INDEX_NAME_MAP[pe_name]
+
+    @staticmethod
+    def get_src_core_iface(src_pe_name, dest_pe_name):
+        return OSM_MWC_Demo.CORE_PE_CONN_MAP[src_pe_name][dest_pe_name]["ifacename"]
+
+    @staticmethod
+    def get_local_ip(src_pe_name, dest_pe_name):
+        return OSM_MWC_Demo.CORE_PE_CONN_MAP[src_pe_name][dest_pe_name]["ip"]
+
+    @staticmethod
+    def get_remote_ip(src_pe_name, dest_pe_name):
+        return OSM_MWC_Demo.CORE_PE_CONN_MAP[dest_pe_name][src_pe_name]["ip"]
+
+    @staticmethod
+    def get_internal_local_ip(src_pe_name, dest_pe_name):
+        return OSM_MWC_Demo.CORE_PE_CONN_MAP[src_pe_name][dest_pe_name]["internal_local_ip"]
+
+    @staticmethod
+    def get_internal_remote_ip(src_pe_name, dest_pe_name):
+        return OSM_MWC_Demo.CORE_PE_CONN_MAP[dest_pe_name][src_pe_name]["internal_local_ip"]
+
+
+def add_pe_corporation(src_pe_name, src_pe_charm, src_pe_group_cfg, corporation_name):
+    domain_name = corporation_name
+    vlan_id = src_pe_group_cfg.vlan_id
+    corp_gw = src_pe_group_cfg.corp_gateway
+    corp_net = src_pe_group_cfg.corp_network
+
+    user_iface = src_pe_group_cfg.interface_name
+
+    src_pe_charm.add_corporation(domain_name, user_iface, vlan_id, corp_gw, corp_net)
+
+
+def connect_pe_domains(src_pe_name, src_pe_charm, dest_pe_name, corporation_name, tunnel_key):
+    domain_name = corporation_name
+    core_iface_name = OSM_MWC_Demo.get_src_core_iface(src_pe_name, dest_pe_name)
+    local_ip = OSM_MWC_Demo.get_local_ip(src_pe_name, dest_pe_name)
+    remote_ip = OSM_MWC_Demo.get_remote_ip(src_pe_name, dest_pe_name)
+    internal_local_ip = OSM_MWC_Demo.get_internal_local_ip(src_pe_name, dest_pe_name)
+    internal_remote_ip = OSM_MWC_Demo.get_internal_remote_ip(src_pe_name, dest_pe_name)
+
+
+    src_pe_idx = OSM_MWC_Demo.get_pe_vnf_index(src_pe_name)
+    dest_pe_idx = OSM_MWC_Demo.get_pe_vnf_index(dest_pe_name)
+
+    # Create a 4 digit hash of the corporation name
+    hash_object = hashlib.md5(corporation_name.encode())
+    corp_hash = hash_object.hexdigest()[-4:]
+
+    # Tunnel name is the 4 digit corporation name hash followed by
+    # src index and dest index. When there are less than 10 PE's
+    # this creates a 8 character tunnel name which is the limit.
+    tunnel_name = "".join([corp_hash, "_", str(src_pe_idx), str(dest_pe_idx)])
+
+    src_pe_charm.connect_domains(domain_name, core_iface_name, local_ip, remote_ip,
+                                 internal_local_ip, internal_remote_ip, tunnel_name,
+                                 tunnel_key)
+
+
+def main(argv=sys.argv[1:]):
+    parser = argparse.ArgumentParser()
+    parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+    parser.add_argument("--dry-run", action="store_true")
+    parser.add_argument("--quiet", "-q", dest="verbose", action="store_false")
+    args = parser.parse_args()
+    if args.verbose:
+        ch.setLevel(logging.DEBUG)
+
+    global dry_run
+    dry_run = args.dry_run
+
+    yaml_str = args.yaml_cfg_file.read()
+
+    juju_cfg = JujuClientConfig.from_yaml_cfg(yaml_str)
+    juju_client = JujuClient(juju_cfg.host, juju_cfg.port, juju_cfg.user, juju_cfg.secret)
+
+    juju_vnf_config = JujuVNFConfig.from_yaml_cfg(yaml_str)
+
+    rpc_request = AddCorporationRequest.from_yaml_cfg(yaml_str)
+    pe_param_group_map = rpc_request.get_pe_parameter_group_map()
+
+    pe_name_charm_map = {}
+    for pe_name, pe_group_cfg in pe_param_group_map.items():
+        # The PE name (i.e. PE1) must be in the parameter group name so we can correlate
+        # to an actual VNF in the descriptor.
+        pe_vnf_index = OSM_MWC_Demo.get_pe_vnf_index(pe_name)
+
+        # Get the deployed VNFR charm service name
+        pe_charm_service_name = juju_vnf_config.get_service_name(pe_vnf_index)
+
+        pe_name_charm_map[pe_name] = SixWindPEProxyCharm(juju_client, pe_charm_service_name)
+
+    # At this point we have SixWindPEProxyCharm() instances for each PE and each
+    # PE param group configuration.
+    for src_pe_name in pe_param_group_map:
+        add_pe_corporation(
+                src_pe_name=src_pe_name,
+                src_pe_charm=pe_name_charm_map[src_pe_name],
+                src_pe_group_cfg=PEGroupConfig(pe_param_group_map[src_pe_name]),
+                corporation_name=rpc_request.corporation_name
+                )
+
+    # Create a permutation of all PE's involved in this topology and connect
+    # them together by creating tunnels with matching keys
+    for src_pe_name, dest_pe_name in itertools.permutations(pe_name_charm_map, 2):
+        connect_pe_domains(
+                src_pe_name=src_pe_name,
+                src_pe_charm=pe_name_charm_map[src_pe_name],
+                dest_pe_name=dest_pe_name,
+                corporation_name=rpc_request.corporation_name,
+                tunnel_key=rpc_request.tunnel_key,
+                )
+
+if __name__ == "__main__":
+    try:
+        main()
+    except Exception as e:
+        logger.exception("Caught exception when executing add_corporation ns")
+        raise
diff --git a/src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__1.yaml b/src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__1.yaml
new file mode 100644 (file)
index 0000000..5edbeef
--- /dev/null
@@ -0,0 +1,18 @@
+initial_config_primitive:
+- name: config
+  parameter:
+    hostname: pe1
+    pass: 6windos
+    user: root
+    vpe-router: <rw_mgmt_ip>
+- name: configure-interface
+  parameter:
+    cidr: 10.10.10.9/30
+    iface-name: eth1
+- name: configure-interface
+  parameter:
+    cidr: 10.10.10.1/30
+    iface-name: eth2
+- name: configure-interface
+  parameter:
+    iface-name: eth3
diff --git a/src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__2.yaml b/src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__2.yaml
new file mode 100644 (file)
index 0000000..b96a023
--- /dev/null
@@ -0,0 +1,18 @@
+initial_config_primitive:
+- name: config
+  parameter:
+    hostname: pe2
+    pass: 6windos
+    user: root
+    vpe-router: <rw_mgmt_ip>
+- name: configure-interface
+  parameter:
+    cidr: 10.10.10.10/30
+    iface-name: eth1
+- name: configure-interface
+  parameter:
+    cidr: 10.10.10.6/30
+    iface-name: eth2
+- name: configure-interface
+  parameter:
+    iface-name: eth3
diff --git a/src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__3.yaml b/src/nsd/mwc16_pe_ns/vnf_config/6WindTR1.1.2__3.yaml
new file mode 100644 (file)
index 0000000..c0b2c98
--- /dev/null
@@ -0,0 +1,21 @@
+initial_config_primitive:
+- name: config
+  parameter:
+    hostname: pe3
+    pass: 6windos
+    user: root
+    vpe-router: <rw_mgmt_ip>
+- name: configure-interface
+  parameter:
+    cidr: 10.10.10.2/30
+    iface-name: eth1
+- name: configure-interface
+  parameter:
+    cidr: 10.10.10.5/30
+    iface-name: eth2
+- name: configure-interface
+  parameter:
+    iface-name: eth3
+- name: configure-interface
+  parameter:
+    iface-name: eth4
diff --git a/src/vnfd/6wind_vnf/6WindTR1.1.2__vnfd.yaml b/src/vnfd/6wind_vnf/6WindTR1.1.2__vnfd.yaml
new file mode 100644 (file)
index 0000000..5b8bffc
--- /dev/null
@@ -0,0 +1,183 @@
+vnfd:vnfd-catalog:
+    vnfd:
+    -   id: 6WindTR1.1.2
+        name: 6WindTR1.1.2
+        short-name: 6WindTR1.1.2
+        logo: 6wind_2x.png
+        mgmt-interface:
+            vdu-id: VM
+            vnf-configuration:
+                config-attributes:
+                    config-delay: '0'
+                    config-priority: '0'
+                config-primitive:
+                -   name: configure-interface
+                    parameter:
+                    -   name: iface-name
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: cidr
+                        data-type: STRING
+                -   name: add-corporation
+                    parameter:
+                    -   name: domain-name
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: iface-name
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: vlan-id
+                        data-type: INTEGER
+                        mandatory: 'true'
+                    -   name: cidr
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: area
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: subnet-cidr
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: subnet-area
+                        data-type: STRING
+                        mandatory: 'true'
+                -   name: delete-corporation
+                    parameter:
+                    -   name: domain-name
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: cidr
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: area
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: subnet-cidr
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: subnet-area
+                        data-type: STRING
+                        mandatory: 'true'
+                -   name: connect-domains
+                    parameter:
+                    -   name: domain-name
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: iface-name
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: tunnel-name
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: local-ip
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: remote-ip
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: tunnel-key
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: internal-local-ip
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: internal-remote-ip
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: tunnel-type
+                        data-type: STRING
+                        mandatory: 'false'
+                        default-value: 'gre'
+                -   name: delete-domain-connection
+                    parameter:
+                    -   name: domain-name
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: tunnel-name
+                        data-type: STRING
+                        mandatory: 'true'
+                juju:
+                    charm: vpe-router
+        connection-point:
+        -   name: eth0
+            type: VPORT
+        -   name: xe0
+            type: VPORT
+        -   name: xe1
+            type: VPORT
+        -   name: xe2
+            type: VPORT
+        -   name: xe3
+            type: VPORT
+        vdu:
+        -   id: VM
+            name: VM
+            image: /mnt/powervault/virtualization/vnfs/6wind/6wind-turbo-router-1.1.2.img.qcow2
+            mgmt-vpci: 0000:00:0a.0
+            vm-flavor:
+                memory-mb: '8192'
+                vcpu-count: '12'
+            external-interface:
+            -   name: eth0
+                virtual-interface:
+                    bandwidth: '1000000000'
+                    type: OM-MGMT
+                    vpci: '0000:00:03.0'
+                vnfd-connection-point-ref: eth0
+            -   name: xe0
+                virtual-interface:
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:05.0'
+                vnfd-connection-point-ref: xe0
+            -   name: xe1
+                virtual-interface:
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:06.0'
+                vnfd-connection-point-ref: xe1
+            -   name: xe2
+                virtual-interface:
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:07.0'
+                vnfd-connection-point-ref: xe2
+            -   name: xe3
+                virtual-interface:
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:08.0'
+                vnfd-connection-point-ref: xe3
+            guest-epa:
+                cpu-pinning-policy: DEDICATED
+                cpu-thread-pinning-policy: PREFER
+                mempage-size: LARGE
+                numa-node-policy:
+                    mem-policy: STRICT
+                    node:
+                    -   id: '0'
+                        paired-threads:
+                            num-paired-threads: '6'
+                            paired-thread-ids:
+                            -   thread-a: '0'
+                                thread-b: '1'
+                            -   thread-a: '2'
+                                thread-b: '3'
+                            -   thread-a: '4'
+                                thread-b: '5'
+                            -   thread-a: '6'
+                                thread-b: '7'
+                            -   thread-a: '8'
+                                thread-b: '9'
+                            -   thread-a: '10'
+                                thread-b: '11'
+                    node-cnt: '1'
+            host-epa:
+                om-cpu-feature:
+                - 64b
+                - iommu
+                - lps
+                - tlbps
+                - hwsv
+                - dioc
+                - ht
+                om-cpu-model-string: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz
+            hypervisor-epa:
+                type: REQUIRE_KVM
+                version: 10002|12001|2.6.32-358.el6.x86_64
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/.build.manifest b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/.build.manifest
new file mode 100644 (file)
index 0000000..41d6999
--- /dev/null
@@ -0,0 +1,219 @@
+{
+  "layers": [
+    "layer:basic", 
+    "vpe-router", 
+    "build"
+  ], 
+  "signatures": {
+    "hooks/stop": [
+      "layer:basic", 
+      "static", 
+      "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
+    ], 
+    "wheelhouse/ecdsa-0.13.tar.gz": [
+      "vpe-router", 
+      "dynamic", 
+      "64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa"
+    ], 
+    "wheelhouse/charms.reactive-0.3.8.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "3f8722d85f7d489f8414d11fc2a3e8793c68000f7a1bc7b1ad71120e037aebee"
+    ], 
+    "hooks/hook.template": [
+      "layer:basic", 
+      "static", 
+      "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
+    ], 
+    "wheelhouse/pycrypto-2.6.1.tar.gz": [
+      "vpe-router", 
+      "dynamic", 
+      "f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c"
+    ], 
+    "hooks/start": [
+      "layer:basic", 
+      "static", 
+      "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
+    ], 
+    "wheelhouse/pip-7.1.2.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "ca047986f0528cfa975a14fb9f7f106271d4e0c3fe1ddced6c1db2e7ae57a477"
+    ], 
+    "wheelhouse/PyYAML-3.11.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "c36c938a872e5ff494938b33b14aaa156cb439ec67548fcab3535bb78b0846e8"
+    ], 
+    "Makefile": [
+      "layer:basic", 
+      "static", 
+      "f91213a68bc5edce9ebe0615b70cc908ea45466c2e205fb6cfe9c35d9c3fde4b"
+    ], 
+    "reactive/__init__.py": [
+      "layer:basic", 
+      "static", 
+      "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+    ], 
+    "wheelhouse/Jinja2-2.8.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "bc1ff2ff88dbfacefde4ddde471d1417d3b304e8df103a7a9437d47269201bf4"
+    ], 
+    "hooks/upgrade-charm": [
+      "layer:basic", 
+      "static", 
+      "b78e405476402d34624c70822d9a60be2f4f85255765f619c0ecfe18f5f934ea"
+    ], 
+    "actions/add-corporation": [
+      "vpe-router", 
+      "static", 
+      "951055318724d05aa82fa9757143561ecf3617a3bd2eaebb08533ed1ae897ade"
+    ], 
+    ".build.manifest": [
+      "build", 
+      "dynamic", 
+      "unchecked"
+    ], 
+    "wheelhouse/charmhelpers-0.6.1.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "c41a4cb3dcf6aa35e115addf9fb83a94585a4ff3bddc63148983431af45905f8"
+    ], 
+    "actions/delete-corporation": [
+      "vpe-router", 
+      "static", 
+      "1e380d728790fa946e2429eaed31ff11aa4186cc287b818d8a91da7da291a6b3"
+    ], 
+    "hooks/update-status": [
+      "layer:basic", 
+      "static", 
+      "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
+    ], 
+    "hooks/leader-settings-changed": [
+      "layer:basic", 
+      "static", 
+      "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
+    ], 
+    "wheelhouse/Tempita-0.5.2.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "cacecf0baa674d356641f1d406b8bff1d756d739c46b869a54de515d08e6fc9c"
+    ], 
+    "actions.yaml": [
+      "vpe-router", 
+      "static", 
+      "619cedd685181c02ae36d04014bc4763c1e4e1b0a1b8a743d1a239c442f2883b"
+    ], 
+    "README.md": [
+      "layer:basic", 
+      "static", 
+      "5d5101eb0f2eb90eb0959438416ceb5e9b82c7746a385eb64ccb8a8ffe01e92b"
+    ], 
+    "reactive/vpe_router.py": [
+      "vpe-router", 
+      "static", 
+      "479874bbe5db71ddc0b3e4e0adab051540dbc8d30021800c42a1b058bf9dcd94"
+    ], 
+    "tox.ini": [
+      "layer:basic", 
+      "static", 
+      "5efb9280763f1f4cb861485e80863caafc9cd5ab1176543e911c27519436de7a"
+    ], 
+    "metadata.yaml": [
+      "vpe-router", 
+      "dynamic", 
+      "a7bf974efb4a29810de06626025fbc3b158053c70b0d67eb4b142a2ac087c5c0"
+    ], 
+    "wheelhouse/pyaml-15.8.2.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "9c54fb5f17b58572c4cef50affea60bb73f445ab153580dac07a12383712b5b8"
+    ], 
+    "copyright": [
+      "layer:basic", 
+      "static", 
+      "1e2afbd75c71affa132ae7ee3327cb29b5e4b9d9705f27dfd03857c326f50c5c"
+    ], 
+    "requirements.txt": [
+      "layer:basic", 
+      "static", 
+      "0f1c70d27e26005a96d66ad54482877ae20f7737693c833e29dd72bd6ac24892"
+    ], 
+    "wheelhouse/netaddr-0.7.18.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "a1f5c9fcf75ac2579b9995c843dade33009543c04f218ff7c007b3c81695bd19"
+    ], 
+    "wheelhouse/paramiko-1.16.0.tar.gz": [
+      "vpe-router", 
+      "dynamic", 
+      "3297ebd3cd072f573772f7c7426939a443c62c458d54bb632ff30fd6ecf96892"
+    ], 
+    "actions/connect-domains": [
+      "vpe-router", 
+      "static", 
+      "cdc11dd947a97b1e6ecb92b95e5e2b2676a5b1a366638a80b5fcf052b6fe240d"
+    ], 
+    ".gitignore": [
+      "layer:basic", 
+      "static", 
+      "0da5c4dcda27cd6406e5bb81cbf68ddccaf728ac764ec15053a165c1449d87d9"
+    ], 
+    "lib/charms/router.py": [
+      "vpe-router", 
+      "static", 
+      "b29712ab37799310107c99bb79ce90a991c5ebf95d513bad127b3fabd02df4a7"
+    ], 
+    "hooks/install": [
+      "layer:basic", 
+      "static", 
+      "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
+    ], 
+    "wheelhouse/MarkupSafe-0.23.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "a4ec1aff59b95a14b45eb2e23761a0179e98319da5a7eb76b56ea8cdc7b871c3"
+    ], 
+    "layer.yaml": [
+      "vpe-router", 
+      "dynamic", 
+      "b6f7fe3a054fa4c8a17d4fa922ee2b0624f75cb39fdcc59c511cb55455425f8b"
+    ], 
+    "config.yaml": [
+      "vpe-router", 
+      "dynamic", 
+      "989e451c1dc464082f3e1122bd784362502af58680ad8e77b88ce00db0ec2246"
+    ], 
+    "hooks/leader-elected": [
+      "layer:basic", 
+      "static", 
+      "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
+    ], 
+    "lib/charms/bootstrap.py": [
+      "layer:basic", 
+      "static", 
+      "bec7997003dbe44e9bbe85f0df598746c868fe72d1971a99d357bf3512453c70"
+    ], 
+    "lib/charms/layer.py": [
+      "layer:basic", 
+      "static", 
+      "3accb93272464875583f9b661dc024b4adc67617354bc21d8a7f74284ae4deb4"
+    ], 
+    "actions/delete-domain-connection": [
+      "vpe-router", 
+      "static", 
+      "0b59e146b4b0223f5593cd4bad9a829822713b10b2ccab46d07a531eb9e20216"
+    ], 
+    "wheelhouse/six-1.10.0.tar.gz": [
+      "layer:basic", 
+      "dynamic", 
+      "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a"
+    ], 
+    "hooks/config-changed": [
+      "layer:basic", 
+      "static", 
+      "21759be2af2e65c9e29531b293fd77fc1c710468ece35bc1cb4360cdefd997b0"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/.gitignore b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/.gitignore
new file mode 100644 (file)
index 0000000..56e95aa
--- /dev/null
@@ -0,0 +1,5 @@
+*.pyc
+*~
+.ropeproject
+.settings
+.tox
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/LICENSE b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/LICENSE
new file mode 100644 (file)
index 0000000..8dada3e
--- /dev/null
@@ -0,0 +1,201 @@
+                                 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/src/vnfd/6wind_vnf/charms/trusty/vpe-router/Makefile b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/Makefile
new file mode 100644 (file)
index 0000000..241e63b
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/make
+PYTHON := /usr/bin/env python
+
+all: lint test build
+
+
+build: unit_test
+       juju-compose -o ~/charms .
+
+lint:
+       @flake8 --exclude hooks/charmhelpers hooks unit_tests tests
+       @charm proof
+
+unit_test:
+       @echo Starting tests...
+       tox
+
+test:
+       @echo Starting Amulet tests...
+       # coreycb note: The -v should only be temporary until Amulet sends
+       # raise_status() messages to stderr:
+       #   https://bugs.launchpad.net/amulet/+bug/1320357
+       @juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/README.md b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/README.md
new file mode 100644 (file)
index 0000000..0550cbf
--- /dev/null
@@ -0,0 +1,75 @@
+# Overview
+
+This is the base layer for all charms [built using layers][building].  It
+provides all of the standard Juju hooks and runs the
+[charms.reactive.main][charms.reactive] loop for them.  It also bootstraps the
+[charm-helpers][] and [charms.reactive][] libraries and all of their
+dependencies for use by the charm.
+
+# Usage
+
+To create a charm layer using this base layer, you need only include it in
+a `layer.yaml` file:
+
+```yaml
+includes: ['layer:basic']
+```
+
+This will fetch this layer from [interfaces.juju.solutions][] and incorporate
+it into your charm layer.  You can then add handlers under the `reactive/`
+directory.  Note that **any** file under `reactive/` will be expected to
+contain handlers, whether as Python decorated functions or [executables][non-python]
+using the [external handler protocol][].
+
+You can also define Python libraries under `lib/charms/X` where `X` is a
+package under the `charms.` namespace for your charm.  See [PyPI][pypi charms.X]
+for what packages already exist under the `charms.` namespace.
+
+# Hooks
+
+This layer provides hooks that other layers can react to using the decorators
+of the [charms.reactive][] library:
+
+  * `config-changed`
+  * `install`
+  * `leader-elected`
+  * `leader-settings-changed`
+  * `start`
+  * `stop`
+  * `upgrade-charm`
+  * `update-status`
+
+Other hooks are not implemented at this time. A new layer can implement storage
+or relation hooks in their own layer by putting them in the `hooks` directory.
+
+**Note:** Because `update-status` is invoked every 5 minutes, you should take
+care to ensure that your reactive handlers only invoke expensive operations
+when absolutely necessary.  It is recommended that you use helpers like
+[`@only_once`][], [`@when_file_changed`][], and [`data_changed`][] to ensure
+that handlers run only when necessary.
+
+# Layer Configuration
+
+This layer does not currently support any configuration.
+
+
+# Reactive States
+
+This layer currently does not set any reactive states.
+
+
+# Actions
+
+This layer currently does not define any actions.
+
+
+[building]: https://jujucharms.com/docs/devel/authors-charm-building
+[charm-helpers]: https://pythonhosted.org/charmhelpers/
+[charms.reactive]: https://pythonhosted.org/charms.reactive/
+[interfaces.juju.solutions]: http://interfaces.juju.solutions/
+[non-python]: https://pythonhosted.org/charms.reactive/#non-python-reactive-handlers
+[external handler protocol]: https://pythonhosted.org/charms.reactive/charms.reactive.bus.html#charms.reactive.bus.ExternalHandler
+[pypi charms.X]: https://pypi.python.org/pypi?%3Aaction=search&term=charms.&submit=search
+[`@only_once`]: https://pythonhosted.org/charms.reactive/charms.reactive.decorators.html#charms.reactive.decorators.only_once
+[`@when_file_changed`]: https://pythonhosted.org/charms.reactive/charms.reactive.decorators.html#charms.reactive.decorators.when_file_changed
+[`data_changed`]: https://pythonhosted.org/charms.reactive/charms.reactive.helpers.html#charms.reactive.helpers.data_changed
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions.yaml b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions.yaml
new file mode 100644 (file)
index 0000000..913cc64
--- /dev/null
@@ -0,0 +1,96 @@
+configure-interface:
+  description: Configure an ethernet interface.
+  params:
+    iface-name:
+      type: string
+      description: Device name, e.g. eth1
+    cidr:
+      type: string
+      description: Network range to assign to the interface
+  required: [iface-name]
+add-corporation:
+  description: Add a new corporation to the router
+  params:
+    domain-name:
+      type: string
+      description: Name of the vlan corporation
+    iface-name:
+      type: string
+      description: Device name. eg eth1
+    vlan-id:
+      type: integer
+      description: The name of the vlan?
+    cidr:
+      type: string
+      description: Network range to assign to the tagged vlan-id
+    area:
+      type: string
+      description: Link State Advertisements (LSA) type
+    subnet-cidr:
+      type: string
+      description: Network range
+    subnet-area:
+      type: string
+      description: Link State Advertisements (LSA) type
+  required: [domain-name, iface-name, vlan-id, cidr, area, subnet-cidr, subnet-area]
+delete-corporation:
+  description: Remove the corporation from the router completely
+  params:
+    domain-name:
+      type: string
+      description: The domain of the corporation to remove
+    cidr:
+      type: string
+      description: Network range to assign to the tagged vlan-id
+    area:
+      type: string
+      description: Link State Advertisements (LSA) type
+    subnet-cidr:
+      type: string
+      description: Network range
+    subnet-area:
+      type: string
+      description: Link State Advertisements (LSA) type
+  required: [domain-name, cidr, area, subnet-cidr, subnet-area]
+connect-domains:
+  description: Connect the router to another router, where the same domain is present
+  params:
+    domain-name:
+      type: string
+      description: The domain of the coproration to connect
+    iface-name:
+      type: string
+      description: Device name. eg eth1
+    tunnel-name:
+      type: string
+      description: Name of the tunnel ?
+    local-ip:
+      type: string
+      description: local ip ?
+    remote-ip:
+      type: string
+      description: remote ip ?
+    tunnel-key:
+      type: string
+      description: tunnel key?
+    internal-local-ip:
+      type: string
+      description: internal local ip?
+    internal-remote-ip:
+      type: string
+      description: internal remote ip?
+    tunnel-type:
+      type: string
+      default: gre
+      description: The type of tunnel to establish.
+  required: [domain-name, iface-name, tunnel-name, local-ip, remote-ip, tunnel-key, internal-local-ip, internal-remote-ip]
+delete-domain-connection:
+  description: Remove the tunnel to another router where the domain is present.
+  params:
+    domain-name:
+      type: string
+      description: The domain of the corporation to unlink
+    tunnel-name:
+      type: string
+      description: The name of the tunnel to unlink that the domain-name is attached to
+  required: [domain-name, tunnel-name]
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/add-corporation b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/add-corporation
new file mode 100755 (executable)
index 0000000..c8ab2f8
--- /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('vpe.add-corporation')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/configure-interface b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/configure-interface
new file mode 100755 (executable)
index 0000000..db9a099
--- /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('vpe.configure-interface')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/connect-domains b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/connect-domains
new file mode 100755 (executable)
index 0000000..48adfc7
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.reactive import main
+from charms.reactive import set_state
+from charmhelpers.core.hookenv import action_fail
+
+"""
+`set_state` only works here because it's flushed to disk inside the `main()`
+loop. remove_state will need to be called inside the action method.
+"""
+set_state('vpe.connect-domains')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/delete-corporation b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/delete-corporation
new file mode 100755 (executable)
index 0000000..0576c08
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('lib')
+
+from charms.reactive import main
+from charms.reactive import set_state
+from charmhelpers.core.hookenv import action_fail
+
+
+"""
+`set_state` only works here because it's flushed to disk inside the `main()`
+loop. remove_state will need to be called inside the action method.
+"""
+set_state('vpe.delete-corporation')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/delete-domain-connection b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/actions/delete-domain-connection
new file mode 100755 (executable)
index 0000000..5ba05f6
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('lib')
+
+from charms.reactive import main
+from charms.reactive import set_state
+from charmhelpers.core.hookenv import action_fail
+
+
+"""
+`set_state` only works here because it's flushed to disk inside the `main()`
+loop. remove_state will need to be called inside the action method.
+"""
+set_state('vpe.delete-domain-connection')
+
+try:
+    main()
+except Exception as e:
+    action_fail(repr(e))
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/config.yaml b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/config.yaml
new file mode 100644 (file)
index 0000000..562515f
--- /dev/null
@@ -0,0 +1,17 @@
+options:
+  vpe-router:
+    default:
+    type: string
+    description: Hostname or IP of the vpe router to connect to
+  user:
+    type: string
+    default: root
+    description: Username for VPE Router
+  pass:
+    type: string
+    default:
+    description: Password for VPE Router
+  hostname:
+    type: string
+    default:
+    description: The hostname to set the vpe router to.
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/copyright b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/copyright
new file mode 100644 (file)
index 0000000..afa853f
--- /dev/null
@@ -0,0 +1,9 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
+
+Files: *
+Copyright: 2015, Canonical Ltd.
+License: GPL-3
+
+License: GPL-3
+ On Debian GNU/Linux system you can find the complete text of the
+ GPL-3 license in '/usr/share/common-licenses/GPL-3'
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/config-changed b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/config-changed
new file mode 100755 (executable)
index 0000000..b74b146
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/hook.template b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/hook.template
new file mode 100644 (file)
index 0000000..b74b146
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/install b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/install
new file mode 100755 (executable)
index 0000000..b74b146
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/leader-elected b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/leader-elected
new file mode 100755 (executable)
index 0000000..b74b146
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/leader-settings-changed b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/leader-settings-changed
new file mode 100755 (executable)
index 0000000..b74b146
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/start b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/start
new file mode 100755 (executable)
index 0000000..b74b146
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/stop b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/stop
new file mode 100755 (executable)
index 0000000..b74b146
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/update-status b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/update-status
new file mode 100755 (executable)
index 0000000..b74b146
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import sys
+sys.path.append('lib')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/upgrade-charm b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/hooks/upgrade-charm
new file mode 100755 (executable)
index 0000000..41fc740
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+
+# Load modules from $CHARM_DIR/lib
+import os
+import sys
+sys.path.append('lib')
+
+# This is an upgrade-charm context, make sure we install latest deps
+if not os.path.exists('wheelhouse/.upgrade'):
+    open('wheelhouse/.upgrade', 'w').close()
+    if os.path.exists('wheelhouse/.bootstrapped'):
+        os.unlink('wheelhouse/.bootstrapped')
+else:
+    os.unlink('wheelhouse/.upgrade')
+
+from charms.bootstrap import bootstrap_charm_deps
+bootstrap_charm_deps()
+
+
+# This will load and run the appropriate @hook and other decorated
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
+# and $CHARM_DIR/hooks/relations.
+#
+# See https://jujucharms.com/docs/stable/authors-charm-building
+# for more information on this pattern.
+from charms.reactive import main
+main()
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/layer.yaml b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/layer.yaml
new file mode 100644 (file)
index 0000000..ac6b1df
--- /dev/null
@@ -0,0 +1,3 @@
+includes:
+- layer:basic
+is: vpe-router
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/bootstrap.py b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/bootstrap.py
new file mode 100644 (file)
index 0000000..bc07490
--- /dev/null
@@ -0,0 +1,92 @@
+import os
+import sys
+import shutil
+from glob import glob
+from subprocess import check_call
+
+
+def bootstrap_charm_deps():
+    """
+    Set up the base charm dependencies so that the reactive system can run.
+    """
+    venv = os.path.abspath('../.venv')
+    vbin = os.path.join(venv, 'bin')
+    vpip = os.path.join(vbin, 'pip')
+    vpy = os.path.join(vbin, 'python')
+    if os.path.exists('wheelhouse/.bootstrapped'):
+        from charms import layer
+        cfg = layer.options('basic')
+        if cfg.get('use_venv') and '.venv' not in sys.executable:
+            # activate the venv
+            os.environ['PATH'] = ':'.join([vbin, os.environ['PATH']])
+            reload_interpreter(vpy)
+        return
+    # bootstrap wheelhouse
+    if os.path.exists('wheelhouse'):
+        apt_install(['python3-pip', 'python3-yaml'])
+        from charms import layer
+        cfg = layer.options('basic')
+        # include packages defined in layer.yaml
+        apt_install(cfg.get('packages', []))
+        # if we're using a venv, set it up
+        if cfg.get('use_venv'):
+            apt_install(['python-virtualenv'])
+            cmd = ['virtualenv', '--python=python3', venv]
+            if cfg.get('include_system_packages'):
+                cmd.append('--system-site-packages')
+            check_call(cmd)
+            os.environ['PATH'] = ':'.join([vbin, os.environ['PATH']])
+            pip = vpip
+        else:
+            pip = 'pip3'
+            # save a copy of system pip to prevent `pip3 install -U pip` from changing it
+            if os.path.exists('/usr/bin/pip'):
+                shutil.copy2('/usr/bin/pip', '/usr/bin/pip.save')
+        # need newer pip, to fix spurious Double Requirement error https://github.com/pypa/pip/issues/56
+        check_call([pip, 'install', '-U', '--no-index', '-f', 'wheelhouse', 'pip'])
+        # install the rest of the wheelhouse deps
+        check_call([pip, 'install', '-U', '--no-index', '-f', 'wheelhouse'] + glob('wheelhouse/*'))
+        if not cfg.get('use_venv'):
+            # restore system pip to prevent `pip3 install -U pip` from changing it
+            if os.path.exists('/usr/bin/pip.save'):
+                shutil.copy2('/usr/bin/pip.save', '/usr/bin/pip')
+                os.remove('/usr/bin/pip.save')
+        # flag us as having already bootstrapped so we don't do it again
+        open('wheelhouse/.bootstrapped', 'w').close()
+        # Ensure that the newly bootstrapped libs are available.
+        # Note: this only seems to be an issue with namespace packages.
+        # Non-namespace-package libs (e.g., charmhelpers) are available
+        # without having to reload the interpreter. :/
+        reload_interpreter(vpy if cfg.get('use_venv') else sys.argv[0])
+
+
+def reload_interpreter(python):
+    """
+    Reload the python interpreter to ensure that all deps are available.
+
+    Newly installed modules in namespace packages sometimes seemt to
+    not be picked up by Python 3.
+    """
+    os.execle(python, python, sys.argv[0], os.environ)
+
+
+def apt_install(packages):
+    """
+    Install apt packages.
+
+    This ensures a consistent set of options that are often missed but
+    should really be set.
+    """
+    if isinstance(packages, (str, bytes)):
+        packages = [packages]
+
+    env = os.environ.copy()
+
+    if 'DEBIAN_FRONTEND' not in env:
+        env['DEBIAN_FRONTEND'] = 'noninteractive'
+
+    cmd = ['apt-get',
+           '--option=Dpkg::Options::=--force-confold',
+           '--assume-yes',
+           'install']
+    check_call(cmd + packages, env=env)
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/layer.py b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/layer.py
new file mode 100644 (file)
index 0000000..45552fd
--- /dev/null
@@ -0,0 +1,22 @@
+
+import os
+import yaml
+
+
+class LayerOptions(dict):
+    def __init__(self, layer_file, section=None):
+        with open(layer_file) as f:
+            layer = yaml.safe_load(f.read())
+        opts = layer.get('options', {})
+        if section and section in opts:
+            super(LayerOptions, self).__init__(opts.get(section))
+        else:
+            super(LayerOptions, self).__init__(opts)
+
+
+def options(section=None, layer_file=None):
+    if not layer_file:
+        base_dir = os.environ.get('CHARM_DIR', os.getcwd())
+        layer_file = os.path.join(base_dir, 'layer.yaml')
+
+    return LayerOptions(layer_file, section)
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/router.py b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/lib/charms/router.py
new file mode 100644 (file)
index 0000000..54ff7fb
--- /dev/null
@@ -0,0 +1,80 @@
+
+import paramiko
+import subprocess
+
+from charmhelpers.core.hookenv import config
+
+
+class NetNS(object):
+    def __init__(self, name):
+        pass
+
+    @classmethod
+    def create(cls, name):
+        # @TODO: Need to check if namespace exists already
+        try:
+            ip('netns', 'add', name)
+        except Exception as e:
+            raise Exception('could not create net namespace: %s' % e)
+
+        return cls(name)
+
+    def up(self, iface, cidr):
+        self.do('ip', 'link', 'set', 'dev', iface, 'up')
+        self.do('ip', 'address', 'add', cidr, 'dev', iface)
+
+    def add_iface(self, iface):
+        ip('link', 'set', 'dev', iface, 'netns', self.name)
+
+    def do(self, *cmd):
+        ip(*['netns', 'exec', self.name] + cmd)
+
+
+def ip(*args):
+    return _run(['ip'] + list(args))
+
+
+def _run(cmd, env=None):
+    if isinstance(cmd, str):
+        cmd = cmd.split() if ' ' in cmd else [cmd]
+
+    cfg = config()
+    if all(k in cfg for k in ['pass', 'vpe-router', 'user']):
+        router = cfg['vpe-router']
+        user = cfg['user']
+        passwd = cfg['pass']
+
+        if router and user and passwd:
+            return ssh(cmd, router, user, passwd)
+
+    p = subprocess.Popen(cmd,
+                         env=env,
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.PIPE)
+    stdout, stderr = p.communicate()
+    retcode = p.poll()
+    if retcode > 0:
+        raise subprocess.CalledProcessError(returncode=retcode,
+                                            cmd=cmd,
+                                            output=stderr.decode("utf-8").strip())
+    return (''.join(stdout), ''.join(stderr))
+
+
+def ssh(cmd, host, user, password=None):
+    ''' Suddenly this project needs to SSH to something. So we replicate what
+        _run was doing with subprocess using the Paramiko library. This is
+        temporary until this charm /is/ the VPE Router '''
+
+    cmds = ' '.join(cmd)
+    client = paramiko.SSHClient()
+    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+    client.connect(host, port=22, username=user, password=password)
+
+    stdin, stdout, stderr = client.exec_command(cmds)
+    retcode = stdout.channel.recv_exit_status()
+    client.close()  # @TODO re-use connections
+    if retcode > 0:
+        output = stderr.read().strip()
+        raise subprocess.CalledProcessError(returncode=retcode, cmd=cmd,
+                                            output=output)
+    return (''.join(stdout), ''.join(stderr))
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/metadata.yaml b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/metadata.yaml
new file mode 100644 (file)
index 0000000..82789ad
--- /dev/null
@@ -0,0 +1,11 @@
+name: vpe-router
+summary: setup a virtualized PE Router with GRE tunnels
+description: |
+  this charm, when deployed and configured, will provide a secure virtualized
+  provider edge router.
+peers:
+  loadbalance:
+    interface: vpe-router
+maintainers:
+- Marco Ceppi <marco.ceppi@canonical.com>
+- Adam Israel <adam.israel@canonical.com>
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/reactive/__init__.py b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/reactive/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/reactive/vpe_router.py b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/reactive/vpe_router.py
new file mode 100644 (file)
index 0000000..c62983d
--- /dev/null
@@ -0,0 +1,639 @@
+
+from charmhelpers.core.hookenv import (
+    config,
+    status_set,
+    action_get,
+    action_fail,
+    log,
+)
+
+from charms.reactive import (
+    hook,
+    when,
+    when_not,
+    helpers,
+    set_state,
+    remove_state,
+)
+
+from charms import router
+import subprocess
+
+cfg = config()
+
+
+@hook('config-changed')
+def validate_config():
+    try:
+        """
+        If the ssh credentials are available, we'll act as a proxy charm.
+        Otherwise, we execute against the unit we're deployed on to.
+        """
+        if all(k in cfg for k in ['pass', 'vpe-router', 'user']):
+            routerip = cfg['vpe-router']
+            user = cfg['user']
+            passwd = cfg['pass']
+
+            if routerip and user and passwd:
+                # Assumption: this will be a root user
+                out, err = router.ssh(['whoami'], routerip,
+                                      user, passwd)
+                if out.strip() != user:
+                    raise Exception('invalid credentials')
+
+                # Set the router's hostname
+                try:
+                    if user == 'root' and 'hostname' in cfg:
+                        hostname = cfg['hostname']
+                        out, err = router.ssh(['hostname', hostname],
+                                              routerip,
+                                              user, passwd)
+                        out, err = router.ssh(['sed',
+                                              '-i',
+                                               '"s/hostname.*$/hostname %s/"'
+                                               % hostname,
+                                               '/usr/admin/global/hostname.sh'
+                                               ],
+                                              routerip,
+                                              user, passwd)
+
+                except subprocess.CalledProcessError as e:
+                    log('Command failed: %s (%s)' %
+                        (' '.join(e.cmd), str(e.output)))
+                    raise
+
+        set_state('vpe.configured')
+        status_set('active', 'ready!')
+
+    except Exception as e:
+        log(repr(e))
+        remove_state('vpe.configured')
+        status_set('blocked', 'validation failed: %s' % e)
+
+
+@when_not('vpe.configured')
+def not_ready_add():
+    actions = [
+        'vpe.add-corporation',
+        'vpe.connect-domains',
+        'vpe.delete-domain-connections',
+        'vpe.remove-corporation',
+        'vpe.configure-interface',
+        'vpe.configure-ospf',
+    ]
+
+    if helpers.any_states(*actions):
+        action_fail('VPE is not configured')
+
+    status_set('blocked', 'vpe is not configured')
+
+
+def start_ospfd():
+    # We may want to make this configurable via config setting
+    ospfd = '/usr/local/bin/ospfd'
+
+    try:
+        (stdout, stderr) = router._run(['touch',
+                                        '/usr/admin/global/ospfd.conf'])
+        (stdout, stderr) = router._run([ospfd, '-d', '-f',
+                                        '/usr/admin/global/ospfd.conf'])
+    except subprocess.CalledProcessError as e:
+        log('Command failed: %s (%s)' %
+            (' '.join(e.cmd), str(e.output)))
+
+
+def configure_ospf(domain, cidr, area, subnet_cidr, subnet_area, enable=True):
+    """Configure the OSPF service"""
+
+    # Check to see if the OSPF daemon is running, and start it if not
+    try:
+        (stdout, stderr) = router._run(['pgrep', 'ospfd'])
+    except subprocess.CalledProcessError as e:
+        # If pgrep fails, the process wasn't found.
+        start_ospfd()
+        log('Command failed (ospfd not running): %s (%s)' %
+            (' '.join(e.cmd), str(e.output)))
+
+    upordown = ''
+    if not enable:
+        upordown = 'no'
+    try:
+        vrfctl = '/usr/local/bin/vrfctl'
+        vtysh = '/usr/local/bin/vtysh'
+
+        (stdout, stderr) = router._run([vrfctl, 'list'])
+
+        domain_id = 0
+        for line in stdout.split('\n'):
+            if domain in line:
+                domain_id = int(line[3:5])
+
+        if domain_id > 0:
+            router._run([vtysh,
+                         '-c',
+                         '"configure terminal"',
+                         '-c',
+                         '"router ospf %d vr %d"' % (domain_id, domain_id),
+                         '-c',
+                         '"%s network %s area %s"' % (upordown, cidr, area),
+                         '-c',
+                         '"%s network %s area %s"' % (upordown,
+                                                      subnet_cidr,
+                                                      subnet_area),
+                         ])
+
+        else:
+            log("Invalid domain id")
+    except subprocess.CalledProcessError as e:
+        action_fail('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+    finally:
+        remove_state('vpe.configure-interface')
+        status_set('active', 'ready!')
+
+
+@when('vpe.configured')
+@when('vpe.configure-interface')
+def configure_interface():
+    """
+    Configure an ethernet interface
+    """
+    iface_name = action_get('iface-name')
+    cidr = action_get('cidr')
+
+    # cidr is optional
+    if cidr:
+        try:
+            # Add may fail, but change seems to add or update
+            router.ip('address', 'change', cidr, 'dev', iface_name)
+        except subprocess.CalledProcessError as e:
+            action_fail('Command failed: %s (%s)' %
+                        (' '.join(e.cmd), str(e.output)))
+            return
+        finally:
+            remove_state('vpe.configure-interface')
+            status_set('active', 'ready!')
+
+    try:
+        router.ip('link', 'set', 'dev', iface_name, 'up')
+    except subprocess.CalledProcessError as e:
+        action_fail('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+    finally:
+        remove_state('vpe.configure-interface')
+        status_set('active', 'ready!')
+
+
+@when('vpe.configured')
+@when('vpe.add-corporation')
+def add_corporation():
+    '''
+    Create and Activate the network corporation
+    '''
+    domain_name = action_get('domain-name')
+    iface_name = action_get('iface-name')
+    # HACK: python's list, used deeper, throws an exception on ints in a tuple
+    vlan_id = str(action_get('vlan-id'))
+    cidr = action_get('cidr')
+    area = action_get('area')
+    subnet_cidr = action_get('subnet-cidr')
+    subnet_area = action_get('subnet-area')
+
+    iface_vlanid = '%s.%s' % (iface_name, vlan_id)
+
+    status_set('maintenance', 'adding corporation {}'.format(domain_name))
+
+    """
+    Attempt to run all commands to add the network corporation. If any step
+    fails, abort and call `delete_corporation()` to undo.
+    """
+    try:
+        """
+        $ ip link add link eth3 name eth3.103 type vlan id 103
+        """
+        router.ip('link',
+                  'add',
+                  'link',
+                  iface_name,
+                  'name',
+                  iface_vlanid,
+                  'type',
+                  'vlan',
+                  'id',
+                  vlan_id)
+
+        """
+        $ ip netns add domain
+        """
+        router.ip('netns',
+                  'add',
+                  domain_name)
+
+        """
+        $ ip link set dev eth3.103 netns corpB
+        """
+        router.ip('link',
+                  'set',
+                  'dev',
+                  iface_vlanid,
+                  'netns',
+                  domain_name)
+
+        """
+        $ ifconfig eth3 up
+        """
+        router._run(['ifconfig', iface_name, 'up'])
+
+        """
+        $ ip netns exec corpB ip link set dev eth3.103 up
+        """
+        router.ip('netns',
+                  'exec',
+                  domain_name,
+                  'ip',
+                  'link',
+                  'set',
+                  'dev',
+                  iface_vlanid,
+                  'up')
+
+        """
+        $ ip netns exec corpB ip address add 10.0.1.1/24 dev eth3.103
+        """
+        mask = cidr.split("/")[1]
+        ip = '%s/%s' % (area, mask)
+        router.ip('netns',
+                  'exec',
+                  domain_name,
+                  'ip',
+                  'address',
+                  'add',
+                  ip,
+                  'dev',
+                  iface_vlanid)
+
+        configure_ospf(domain_name, cidr, area, subnet_cidr, subnet_area, True)
+
+    except subprocess.CalledProcessError as e:
+        delete_corporation()
+        action_fail('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+    finally:
+        remove_state('vpe.add-corporation')
+        status_set('active', 'ready!')
+
+
+@when('vpe.configured')
+@when('vpe.delete-corporation')
+def delete_corporation():
+
+    domain_name = action_get('domain-name')
+    cidr = action_get('cidr')
+    area = action_get('area')
+    subnet_cidr = action_get('subnet-cidr')
+    subnet_area = action_get('subnet-area')
+
+    status_set('maintenance', 'deleting corporation {}'.format(domain_name))
+
+    try:
+        """
+        Remove all tunnels defined for this domain
+
+        $ ip netns exec domain_name ip tun show
+            | grep gre
+            | grep -v "remote any"
+            | cut -d":" -f1
+        """
+        p = router.ip(
+            'netns',
+            'exec',
+            domain_name,
+            'ip',
+            'tun',
+            'show',
+            '|',
+            'grep',
+            'gre',
+            '|',
+            'grep',
+            '-v',
+            '"remote any"',
+            '|',
+            'cut -d":" -f1'
+        )
+
+        # `p` should be a tuple of (stdout, stderr)
+        tunnels = p[0].split('\n')
+
+        for tunnel in tunnels:
+            try:
+                """
+                $ ip netns exec domain_name ip link set $tunnel_name down
+                """
+                router.ip(
+                    'netns',
+                    'exec',
+                    domain_name,
+                    'ip',
+                    'link',
+                    'set',
+                    tunnel,
+                    'down'
+                )
+            except subprocess.CalledProcessError as e:
+                log('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+                pass
+
+            try:
+                """
+                $ ip netns exec domain_name ip tunnel del $tunnel_name
+                """
+                router.ip(
+                    'netns',
+                    'exec',
+                    domain_name,
+                    'ip',
+                    'tunnel',
+                    'del',
+                    tunnel
+                )
+            except subprocess.CalledProcessError as e:
+                log('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+                pass
+
+        """
+        Remove all interfaces associated to the domain
+
+        $ ip netns exec domain_name ifconfig | grep mtu | cut -d":" -f1
+        """
+        p = router.ip(
+            'netns',
+            'exec',
+            domain_name,
+            'ifconfig',
+            '|',
+            'grep mtu',
+            '|',
+            'cut -d":" -f1'
+        )
+
+        ifaces = p[0].split('\n')
+        for iface in ifaces:
+
+            try:
+                """
+                $ ip netns exec domain_name ip link set $iface down
+                """
+                router.ip(
+                    'netns',
+                    'exec',
+                    domain_name,
+                    'ip',
+                    'link',
+                    'set',
+                    iface,
+                    'down'
+                )
+            except subprocess.CalledProcessError as e:
+                log('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+
+            try:
+                """
+                $ ifconfig eth3 down
+                """
+                router._run(['ifconfig', iface, 'down'])
+            except subprocess.CalledProcessError as e:
+                log('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+                pass
+
+            try:
+                """
+                $ ip link del dev $iface
+                """
+                router.ip(
+                    'link',
+                    'del',
+                    'dev',
+                    iface
+                )
+            except subprocess.CalledProcessError as e:
+                log('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+                pass
+
+        try:
+            """
+            Remove the domain
+
+            $ ip netns del domain_name
+            """
+            router.ip(
+                'netns',
+                'del',
+                domain_name
+            )
+        except subprocess.CalledProcessError as e:
+            log('Command failed: %s (%s)' % (' '.join(e.cmd), str(e.output)))
+            pass
+
+        try:
+            configure_ospf(domain_name,
+                           cidr,
+                           area,
+                           subnet_cidr,
+                           subnet_area,
+                           False)
+        except subprocess.CalledProcessError as e:
+            action_fail('Command failed: %s (%s)' %
+                        (' '.join(e.cmd), str(e.output)))
+
+    except:
+        # Do nothing
+        log('delete-corporation failed.')
+        pass
+
+    finally:
+        remove_state('vpe.delete-corporation')
+        status_set('active', 'ready!')
+
+
+@when('vpe.configured')
+@when('vpe.connect-domains')
+def connect_domains():
+
+    params = [
+        'domain-name',
+        'iface-name',
+        'tunnel-name',
+        'local-ip',
+        'remote-ip',
+        'tunnel-key',
+        'internal-local-ip',
+        'internal-remote-ip',
+        'tunnel-type',
+    ]
+
+    config = {}
+    for p in params:
+        config[p] = action_get(p)
+
+    status_set('maintenance', 'connecting domains')
+
+    try:
+        """
+        $ ip tunnel add tunnel_name mode gre local local_ip remote remote_ip
+            dev iface_name key tunnel_key csum
+        """
+        router.ip(
+            'tunnel',
+            'add',
+            config['tunnel-name'],
+            'mode',
+            config['tunnel-type'],
+            'local',
+            config['local-ip'],
+            'remote',
+            config['remote-ip'],
+            'dev',
+            config['iface-name'],
+            'key',
+            config['tunnel-key'],
+            'csum'
+        )
+
+    except subprocess.CalledProcessError as e:
+        log('Command failed (retrying with ip tunnel change): %s (%s)' %
+            (' '.join(e.cmd), str(e.output)))
+        try:
+            """
+            If the tunnel already exists (like gre0) and can't be deleted,
+            modify it instead of trying to add it.
+            """
+            router.ip(
+                'tunnel',
+                'change',
+                config['tunnel-name'],
+                'mode',
+                config['tunnel-type'],
+                'local',
+                config['local-ip'],
+                'remote',
+                config['remote-ip'],
+                'dev',
+                config['iface-name'],
+                'key',
+                config['tunnel-key'],
+                'csum'
+            )
+        except subprocess.CalledProcessError as e:
+            delete_domain_connection()
+            action_fail('Command failed: %s (%s)' %
+                        (' '.join(e.cmd), str(e.output)))
+        finally:
+            remove_state('vpe.connect-domains')
+            status_set('active', 'ready!')
+
+    try:
+        """
+        $ ip link set dev tunnel_name netns domain_name
+        """
+        router.ip(
+            'link',
+            'set',
+            'dev',
+            config['tunnel-name'],
+            'netns',
+            config['domain-name']
+        )
+
+        """
+        $ ip netns exec domain_name ip link set dev tunnel_name up
+        """
+        router.ip(
+            'netns',
+            'exec',
+            config['domain-name'],
+            'ip',
+            'link',
+            'set',
+            'dev',
+            config['tunnel-name'],
+            'up'
+        )
+
+        """
+        $ ip netns exec domain_name ip address add internal_local_ip peer
+            internal_remote_ip dev tunnel_name
+        """
+        router.ip(
+            'netns',
+            'exec',
+            config['domain-name'],
+            'ip',
+            'address',
+            'add',
+            config['internal-local-ip'],
+            'peer',
+            config['internal-remote-ip'],
+            'dev',
+            config['tunnel-name']
+        )
+    except subprocess.CalledProcessError as e:
+        delete_domain_connection()
+        action_fail('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+    finally:
+        remove_state('vpe.connect-domains')
+        status_set('active', 'ready!')
+
+
+@when('vpe.configured')
+@when('vpe.delete-domain-connection')
+def delete_domain_connection():
+    ''' Remove the tunnel to another router where the domain is present '''
+    domain = action_get('domain-name')
+    tunnel_name = action_get('tunnel-name')
+
+    status_set('maintenance', 'deleting domain connection: {}'.format(domain))
+
+    try:
+
+        try:
+            """
+            $ ip netns exec domain_name ip link set tunnel_name down
+            """
+            router.ip('netns',
+                      'exec',
+                      domain,
+                      'ip',
+                      'link',
+                      'set',
+                      tunnel_name,
+                      'down')
+        except subprocess.CalledProcessError as e:
+            action_fail('Command failed: %s (%s)' %
+                        (' '.join(e.cmd), str(e.output)))
+
+        try:
+            """
+            $ ip netns exec domain_name ip tunnel del tunnel_name
+            """
+            router.ip('netns',
+                      'exec',
+                      domain,
+                      'ip',
+                      'tunnel',
+                      'del',
+                      tunnel_name)
+        except subprocess.CalledProcessError as e:
+            action_fail('Command failed: %s (%s)' %
+                        (' '.join(e.cmd), str(e.output)))
+    except:
+        pass
+    finally:
+        remove_state('vpe.delete-domain-connection')
+        status_set('active', 'ready!')
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/requirements.txt b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/requirements.txt
new file mode 100644 (file)
index 0000000..28ecaca
--- /dev/null
@@ -0,0 +1,2 @@
+flake8
+pytest
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/tox.ini b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/tox.ini
new file mode 100644 (file)
index 0000000..cc7cf78
--- /dev/null
@@ -0,0 +1,8 @@
+[tox]
+skipsdist=True
+envlist = py34
+
+[testenv]
+commands = py.test -v
+deps =
+    -r{toxinidir}/requirements.txt
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/Jinja2-2.8.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/Jinja2-2.8.tar.gz
new file mode 100644 (file)
index 0000000..9c38426
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/Jinja2-2.8.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/MarkupSafe-0.23.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/MarkupSafe-0.23.tar.gz
new file mode 100644 (file)
index 0000000..6b19006
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/MarkupSafe-0.23.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/PyYAML-3.11.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/PyYAML-3.11.tar.gz
new file mode 100644 (file)
index 0000000..2a5d431
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/PyYAML-3.11.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/Tempita-0.5.2.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/Tempita-0.5.2.tar.gz
new file mode 100644 (file)
index 0000000..755befc
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/Tempita-0.5.2.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charmhelpers-0.6.1.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charmhelpers-0.6.1.tar.gz
new file mode 100644 (file)
index 0000000..5255319
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charmhelpers-0.6.1.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charmhelpers-0.6.2.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charmhelpers-0.6.2.tar.gz
new file mode 100644 (file)
index 0000000..9192919
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charmhelpers-0.6.2.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charms.reactive-0.3.8.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charms.reactive-0.3.8.tar.gz
new file mode 100644 (file)
index 0000000..c7ed6ed
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/charms.reactive-0.3.8.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/ecdsa-0.13.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/ecdsa-0.13.tar.gz
new file mode 100644 (file)
index 0000000..3709762
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/ecdsa-0.13.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/netaddr-0.7.18.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/netaddr-0.7.18.tar.gz
new file mode 100644 (file)
index 0000000..0df6b47
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/netaddr-0.7.18.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/paramiko-1.16.0.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/paramiko-1.16.0.tar.gz
new file mode 100644 (file)
index 0000000..88850e6
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/paramiko-1.16.0.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pip-7.1.2.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pip-7.1.2.tar.gz
new file mode 100644 (file)
index 0000000..56ead41
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pip-7.1.2.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pyaml-15.8.2.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pyaml-15.8.2.tar.gz
new file mode 100644 (file)
index 0000000..3c49aaf
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pyaml-15.8.2.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pycrypto-2.6.1.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pycrypto-2.6.1.tar.gz
new file mode 100644 (file)
index 0000000..e6bf62c
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/pycrypto-2.6.1.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/six-1.10.0.tar.gz b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/six-1.10.0.tar.gz
new file mode 100644 (file)
index 0000000..ac8eec5
Binary files /dev/null and b/src/vnfd/6wind_vnf/charms/trusty/vpe-router/wheelhouse/six-1.10.0.tar.gz differ
diff --git a/src/vnfd/6wind_vnf/icons/6wind_2x.png b/src/vnfd/6wind_vnf/icons/6wind_2x.png
new file mode 100644 (file)
index 0000000..64e5054
Binary files /dev/null and b/src/vnfd/6wind_vnf/icons/6wind_2x.png differ
diff --git a/src/vnfd/gw_corpa_pe1_vnf/gw-corpa-pe1__vnfd.yaml b/src/vnfd/gw_corpa_pe1_vnf/gw-corpa-pe1__vnfd.yaml
new file mode 100644 (file)
index 0000000..416bcc4
--- /dev/null
@@ -0,0 +1,55 @@
+vnfd:vnfd-catalog:
+    vnfd:
+    -   id: gw_corpA_PE1
+        name: gw_corpA_PE1
+        short-name: gw_corpA_PE1
+        description: gw_corpA_PE1
+        connection-point:
+        -   name: eth0
+            type: VPORT
+        -   name: eth1
+            type: VPORT
+        -   name: xe0
+            type: VPORT
+        mgmt-interface:
+            vdu-id: gw_corpA_PE1-VM
+        vdu:
+        -   id: gw_corpA_PE1-VM
+            name: gw_corpA_PE1-VM
+            description: gw_corpA_PE1-VM
+            image: /mnt/powervault/virtualization/vnfs/demos/mwc2016/gw_corpA_PE1.qcow2
+            mgmt-vpci: 0000:00:0a.0
+            vm-flavor:
+                vcpu-count: '2'
+                memory-mb: '4096'
+                storage-gb: '10'
+            external-interface:
+            -   name: eth0
+                virtual-interface:
+                    bandwidth: '0'
+                    type: VIRTIO
+                    vpci: 0000:00:0a.0
+                vnfd-connection-point-ref: eth0
+            -   name: eth1
+                virtual-interface:
+                    bandwidth: '0'
+                    type: OM-MGMT
+                    vpci: 0000:00:0b.0
+                vnfd-connection-point-ref: eth1
+            -   name: xe0
+                virtual-interface:
+                    bandwidth: '10000000000'
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:10.0'
+                vnfd-connection-point-ref: xe0
+            guest-epa:
+                cpu-pinning-policy: DEDICATED
+                cpu-thread-pinning-policy: PREFER
+                mempage-size: LARGE
+                numa-node-policy:
+                    mem-policy: STRICT
+                    node:
+                    -   id: '0'
+                        paired-threads:
+                            num-paired-threads: '1'
+                    node-cnt: '1'
diff --git a/src/vnfd/gw_corpa_pe2_vnf/gw-corpa-pe2__vnfd.yaml b/src/vnfd/gw_corpa_pe2_vnf/gw-corpa-pe2__vnfd.yaml
new file mode 100644 (file)
index 0000000..cf43bf2
--- /dev/null
@@ -0,0 +1,55 @@
+vnfd:vnfd-catalog:
+    vnfd:
+    -   id: gw_corpA_PE2
+        name: gw_corpA_PE2
+        short-name: gw_corpA_PE2
+        description: gw_corpA_PE2
+        mgmt-interface:
+            vdu-id: gw_corpA_PE2-VM
+        connection-point:
+        -   name: eth0
+            type: VPORT
+        -   name: eth1
+            type: VPORT
+        -   name: xe0
+            type: VPORT
+        vdu:
+        -   id: gw_corpA_PE2-VM
+            name: gw_corpA_PE2-VM
+            description: gw_corpA_PE2-VM
+            image: /mnt/powervault/virtualization/vnfs/demos/mwc2016/gw_corpA_PE2.qcow2
+            mgmt-vpci: 0000:00:0a.0
+            vm-flavor:
+                memory-mb: '4096'
+                storage-gb: '10'
+                vcpu-count: '2'
+            external-interface:
+            -   name: eth0
+                virtual-interface:
+                    bandwidth: '0'
+                    type: VIRTIO
+                    vpci: 0000:00:0a.0
+                vnfd-connection-point-ref: eth0
+            -   name: eth1
+                virtual-interface:
+                    bandwidth: '0'
+                    type: OM-MGMT
+                    vpci: 0000:00:0b.0
+                vnfd-connection-point-ref: eth1
+            -   name: xe0
+                virtual-interface:
+                    bandwidth: '10000000000'
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:10.0'
+                vnfd-connection-point-ref: xe0
+            guest-epa:
+                cpu-pinning-policy: DEDICATED
+                cpu-thread-pinning-policy: PREFER
+                mempage-size: LARGE
+                numa-node-policy:
+                    mem-policy: STRICT
+                    node:
+                    -   id: '0'
+                        paired-threads:
+                            num-paired-threads: '1'
+                    node-cnt: '1'
diff --git a/src/vnfd/ims_allin1_2p_vnf/IMS-ALLIN1__vnfd.yaml b/src/vnfd/ims_allin1_2p_vnf/IMS-ALLIN1__vnfd.yaml
new file mode 100644 (file)
index 0000000..b36941a
--- /dev/null
@@ -0,0 +1,85 @@
+vnfd:vnfd-catalog:
+    vnfd:
+    -   id: IMS-ALLIN1_2p
+        name: IMS-ALLIN1_2p
+        short-name: IMS-ALLIN1_2p
+        description: IMS-ALLIN1_2p
+        logo: metaswitch_2x.png
+        mgmt-interface:
+            vdu-id: IMS-ALLIN1_2p-VM
+            vnf-configuration:
+                config-attributes:
+                    config-delay: '0'
+                    config-priority: '1'
+                config-primitive:
+                -   name: config
+                    parameter:
+                    -   name: home_domain
+                        data-type: STRING
+                        mandatory: 'true'
+                        default-value: ims.com
+                    -   name: password
+                        data-type: string
+                        mandatory: 'true'
+                        name: password
+                        default-value: cw-aio
+                -   name: create-update-user
+                    parameter:
+                    -   name: number
+                        data-type: STRING
+                        mandatory: 'true'
+                    -   name: password
+                        data-type: STRING
+                        mandatory: 'true'
+                -   name: delete-user
+                    parameter:
+                    -   name: number
+                        data-type: STRING
+                        mandatory: 'true'
+                initial-config-primitive:
+                -   name: config
+                    parameter:
+                    -   name: proxied_ip
+                        value: <rw_mgmt_ip>
+                    seq: '1'
+                juju:
+                    charm: clearwater-aio-proxy
+        connection-point:
+        -   name: eth0
+            type: VPORT
+        -   name: eth1
+            type: VPORT
+        vdu:
+        -   id: IMS-ALLIN1_2p-VM
+            name: IMS-ALLIN1_2p-VM
+            description: IMS-ALLIN1_2p-VM
+            image: /mnt/powervault/virtualization/vnfs/demos/mwc2016/allin1.qcow2
+            vm-flavor:
+                memory-mb: '4096'
+                storage-gb: '10'
+                vcpu-count: '2'
+            mgmt-vpci: 0000:00:0a.0
+            external-interface:
+            -   name: eth0
+                virtual-interface:
+                    bandwidth: '0'
+                    type: VIRTIO
+                    vpci: 0000:00:0a.0
+                vnfd-connection-point-ref: eth0
+            -   name: eth1
+                virtual-interface:
+                    bandwidth: '0'
+                    type: OM-MGMT
+                    vpci: 0000:00:0b.0
+                vnfd-connection-point-ref: eth1
+            guest-epa:
+                cpu-pinning-policy: DEDICATED
+                cpu-thread-pinning-policy: PREFER
+                mempage-size: LARGE
+                numa-node-policy:
+                    mem-policy: STRICT
+                    node:
+                    -   id: '0'
+                        paired-threads:
+                            num-paired-threads: '1'
+                    node-cnt: '1'
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/README.md b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/README.md
new file mode 100644 (file)
index 0000000..c67a763
--- /dev/null
@@ -0,0 +1,53 @@
+# Overview
+
+This is a [Juju charm](https://jujucharms.com/about), which allows configuration of the [Project Clearwater](http://projectclearwater.org) IMS core's [all-in-one](http://clearwater.readthedocs.org/en/stable/All_in_one_Images/index.html) node.
+
+This is a proxy charm, meaning that you must spin up the all-in-one VM first, and then point this charm at it to manage it.
+
+Since the all-in-one node does not support scaling up, neither does this charm.
+
+# Deployment
+
+## Initial deployment
+
+The all-in-one VM image should be downloaded from [http://repo.cw-ngv.com/juju-clearwater-2/cw-aio.ova](http://repo.cw-ngv.com/juju-clearwater-2/cw-aio.ova) and deployed onto your virtualization platform.  (You could alternatively try the latest all-in-one VM image from [http://vm-images.cw-ngv.com/](http://vm-images.cw-ngv.com/), but this may not have been tested with this charm - the juju-clearwater-2 version above is known to work.)
+
+The proxy charm should then be deployed, pointing at the all-in-one VM.
+
+# Using the All-in-One Node
+
+Once installed, the all-in-one node will listen for SIP traffic on port 5060 (both TCP and UDP).  You can use a standard SIP client (e.g. Blink, Boghe or X-Lite) to register against the all-in-one VM's public IP and make calls.
+
+Our ["Making your first call" documentation](http://clearwater.readthedocs.org/en/latest/Making_your_first_call/index.html) has more information on this process.
+
+# Configuration
+
+-  `proxied_ip`: The IP address of the All-in-One node to manage
+-  `password`: The login password of the All-in-One node to manage (default is
+ very likely correct)
+-  `home_domain`: The home domain for this service
+-  `base_number`: The first number to be allocated in the number range
+-  `number_count`: The count of numbers to allocate
+
+# Actions
+
+This proxy charm exposes two actions.
+
+-  `create-update-user`: Creates a user, or updates if they already exist
+    -  `number`: The number to provision
+    -  `password`: The number's password
+
+-  `delete-user`: Deletes a user
+    -  `number`: The number to delete
+
+For example, `juju action do clearwater-aio-proxy/0 create-update-user number=\"1234567890\" password=secret` creates a user.  (Note that the escaped double-quotes are required to avoid juju parsing the number as an integer rather than a string.)
+
+Note that the numbers specified in `create-update-user` and `delete-user` actions need not be in the number range specified in the configuration above.
+
+# Contact and Upstream Project Information
+
+Project Clearwater is an open-source IMS core, developed by [Metaswitch Networks](http://www.metaswitch.com) and released under the [GNU GPLv3](http://www.projectclearwater.org/download/license/). You can find more information about it on [our website](http://www.projectclearwater.org/) or [our documentation site](https://clearwater.readthedocs.org).
+
+Clearwater source code and issue list can be found at https://github.com/Metaswitch/.
+
+If you have problems when using Project Clearwater, read [our troubleshooting documentation](http://clearwater.readthedocs.org/en/latest/Troubleshooting_and_Recovery/index.html) for help, or see [our support page](http://clearwater.readthedocs.org/en/latest/Support/index.html) to find out how to ask mailing list questions or raise issues.
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions.yaml b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions.yaml
new file mode 100644 (file)
index 0000000..424ae89
--- /dev/null
@@ -0,0 +1,19 @@
+create-update-user:
+  description: Create a user, or update a user if they already exist.
+  params:
+    number:
+      description: The number to provision
+      type: string
+    password:
+      description: The number's password
+      type: string
+  required: [number, password]
+  additionalProperties: false
+delete-user:
+  description: Delete a user.  If the user does not exist, this is still considered success.
+  params:
+    number:
+      description: The number to provision
+      type: string
+  required: [number]
+  additionalProperties: false
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/create-update-user b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/create-update-user
new file mode 100755 (executable)
index 0000000..1f388fe
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/bash
+set -e
+
+# Get the configuration and action parameters.
+proxied_ip=$(config-get proxied_ip)
+login_password=$(config-get password)
+home_domain=$(config-get home_domain)
+number=$(action-get number)
+password=$(action-get password)
+
+if [ -z "$proxied_ip" ] || [ -z "$login_password" ] || [ -z "$home_domain" ] ; then
+  echo Proxy not yet configured!
+  exit 1
+fi
+
+# If the user doesn't exist, try to create them.  Otherwise, try to update them.
+if ! sshpass -p$login_password ssh -o StrictHostKeyChecking=no ubuntu@$proxied_ip "echo $login_password | sudo -S /usr/share/clearwater/bin/display_user $number $home_domain" ; then
+  echo "Subscriber doesn't exist - creating"
+  sshpass -p$login_password ssh -o StrictHostKeyChecking=no ubuntu@$proxied_ip "echo $login_password | sudo -S /usr/share/clearwater/bin/create_user $number $home_domain $password"
+else
+  echo "Subscriber exists - updating"
+  sshpass -p$login_password ssh -o StrictHostKeyChecking=no ubuntu@$proxied_ip "echo $login_password | sudo -S /usr/share/clearwater/bin/update_user $number $home_domain --password $password"
+fi
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/create-user b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/create-user
new file mode 100755 (executable)
index 0000000..feeb646
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+
+# Get the configuration and action parameters.
+proxied_ip=$(config-get proxied_ip)
+login_password=$(config-get password)
+home_domain=$(config-get home_domain)
+number=$(action-get number)
+password=$(action-get password)
+
+if [ -z "$proxied_ip" ] || [ -z "$login_password" ] || [ -z "$home_domain" ] ; then
+  echo Proxy not yet configured!
+  exit 1
+fi
+
+# Create the user.
+sshpass -p$login_password ssh -o StrictHostKeyChecking=no ubuntu@$proxied_ip "echo $login_password | sudo -S /usr/share/clearwater/bin/create_user $number $home_domain $password"
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/delete-user b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/actions/delete-user
new file mode 100755 (executable)
index 0000000..7ecf519
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+set -e
+
+# Get the configuration and action parameters.
+proxied_ip=$(config-get proxied_ip)
+login_password=$(config-get password)
+home_domain=$(config-get home_domain)
+number=$(action-get number)
+
+if [ -z "$proxied_ip" ] || [ -z "$login_password" ] || [ -z "$home_domain" ] ; then
+  echo Proxy not yet configured!
+  exit 1
+fi
+
+# Delete the user.
+sshpass -p$login_password ssh -o StrictHostKeyChecking=no ubuntu@$proxied_ip "echo $login_password | sudo -S /usr/share/clearwater/bin/delete_user -y $number $home_domain"
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/config.yaml b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/config.yaml
new file mode 100644 (file)
index 0000000..3be783f
--- /dev/null
@@ -0,0 +1,20 @@
+options:
+  proxied_ip:
+    description: The IP address of the All-in-One node to manage
+    type: string
+  password:
+    default: cw-aio
+    description: The login password of the All-in-One node to manage (default is very likely correct)
+    type: string
+  home_domain:
+    default: example.com
+    description: The home domain for this service
+    type: string
+  base_number:
+    default: "1230000000"
+    description: The first number to be allocated in the number range
+    type: string
+  number_count:
+    default: 1000
+    description: The count of numbers to allocate
+    type: int
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/copyright b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/copyright
new file mode 100644 (file)
index 0000000..39f1ec8
--- /dev/null
@@ -0,0 +1,31 @@
+Project Clearwater - IMS in the Cloud
+Copyright (C) 2016  Metaswitch Networks Ltd
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version, along with the "Special Exception" for use of
+the program along with SSL, set forth below. This program is distributed
+in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.  See the GNU General Public License for more
+details. You should have received a copy of the GNU General Public
+License along with this program.  If not, see
+<http://www.gnu.org/licenses/>.
+
+The author can be reached by email at clearwater@metaswitch.com or by
+post at Metaswitch Networks Ltd, 100 Church St, Enfield EN2 6BQ, UK
+
+Special Exception
+Metaswitch Networks Ltd  grants you permission to copy, modify,
+propagate, and distribute a work formed by combining OpenSSL with The
+Software, or a work derivative of such a combination, even if such
+copying, modification, propagation, or distribution would otherwise
+violate the terms of the GPL. You must comply with the GPL in all
+respects for all of the code used other than OpenSSL.
+"OpenSSL" means OpenSSL toolkit software distributed by the OpenSSL
+Project and licensed under the OpenSSL Licenses, or a work based on such
+software and licensed under the OpenSSL Licenses.
+"OpenSSL Licenses" means the OpenSSL License and Original SSLeay License
+under which the OpenSSL Project distributes the OpenSSL toolkit software,
+as those licenses appear in the file LICENSE-OPENSSL.
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/config-changed b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/config-changed
new file mode 100755 (executable)
index 0000000..4382edd
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/bash
+set -e
+
+# Get the configuration.
+proxied_ip=$(config-get proxied_ip)
+login_password=$(config-get password)
+home_domain=$(config-get home_domain)
+base_number=$(config-get base_number)
+number_count=$(config-get number_count)
+
+# If the node is configured, provision it and its numbers.
+if [ -n "$proxied_ip" ] && [ -n "$home_domain" ]  && [ -n "$login_password" ] ; then
+  # Copy the reconfigure-aio script on, and run it.
+  status-set maintenance "configuring"
+  sshpass -p$login_password scp -o StrictHostKeyChecking=no $CHARM_DIR/lib/reconfigure-aio ubuntu@$proxied_ip:/tmp/reconfigure-aio.$$
+  sshpass -p$login_password ssh -o StrictHostKeyChecking=no ubuntu@$proxied_ip "echo $login_password | sudo -S bash -c 'bash /tmp/reconfigure-aio.$$ $home_domain $base_number $number_count ; rm -f /tmp/reconfigure-aio.$$'"
+  status-set active "configured"
+else
+  status-set blocked "waiting for configuration"
+fi
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/install b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/install
new file mode 100755 (executable)
index 0000000..4378d03
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+set -e
+
+status-set maintenance "installing"
+
+# Install sshpass as we'll need it shortly
+apt-get update
+apt-get -q -y --force-yes install sshpass
+
+status-set maintenance "installed"
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/start b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/start
new file mode 100755 (executable)
index 0000000..8824f74
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Here put anything that is needed to start the service.
+# Note that currently this is run directly after install
+# i.e. 'service apache2 start'
+set -e
+
+# Nothing to do
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/stop b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/stop
new file mode 100755 (executable)
index 0000000..f6ecbe3
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+# This will be run when the service is being torn down, allowing you to disable
+# it in various ways..
+# For example, if your web app uses a text file to signal to the load balancer
+# that it is live... you could remove it and sleep for a bit to allow the load
+# balancer to stop sending traffic.
+# rm /srv/webroot/server-live.txt && sleep 30
+set -e
+
+# Nothing to do
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/upgrade-charm b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/hooks/upgrade-charm
new file mode 100755 (executable)
index 0000000..fdb1f86
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+# This hook is executed each time a charm is upgraded after the new charm
+# contents have been unpacked
+# Best practice suggests you execute the hooks/install to ensure all updates are processed -
+# hooks/config_change is triggered automatically
+set -e
+
+$CHARM_DIR/hooks/install
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/icon.svg b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/icon.svg
new file mode 100644 (file)
index 0000000..f9ac92c
--- /dev/null
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg6517"
+   version="1.1"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="icon.svg">
+  <defs
+     id="defs6519">
+    <linearGradient
+       id="Background">
+      <stop
+         id="stop4178"
+         offset="0"
+         style="stop-color:#b8b8b8;stop-opacity:1" />
+      <stop
+         id="stop4180"
+         offset="1"
+         style="stop-color:#c9c9c9;stop-opacity:1" />
+    </linearGradient>
+    <filter
+       style="color-interpolation-filters:sRGB;"
+       inkscape:label="Inner Shadow"
+       id="filter1121">
+      <feFlood
+         flood-opacity="0.59999999999999998"
+         flood-color="rgb(0,0,0)"
+         result="flood"
+         id="feFlood1123" />
+      <feComposite
+         in="flood"
+         in2="SourceGraphic"
+         operator="out"
+         result="composite1"
+         id="feComposite1125" />
+      <feGaussianBlur
+         in="composite1"
+         stdDeviation="1"
+         result="blur"
+         id="feGaussianBlur1127" />
+      <feOffset
+         dx="0"
+         dy="2"
+         result="offset"
+         id="feOffset1129" />
+      <feComposite
+         in="offset"
+         in2="SourceGraphic"
+         operator="atop"
+         result="composite2"
+         id="feComposite1131" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB;"
+       inkscape:label="Drop Shadow"
+       id="filter950">
+      <feFlood
+         flood-opacity="0.25"
+         flood-color="rgb(0,0,0)"
+         result="flood"
+         id="feFlood952" />
+      <feComposite
+         in="flood"
+         in2="SourceGraphic"
+         operator="in"
+         result="composite1"
+         id="feComposite954" />
+      <feGaussianBlur
+         in="composite1"
+         stdDeviation="1"
+         result="blur"
+         id="feGaussianBlur956" />
+      <feOffset
+         dx="0"
+         dy="1"
+         result="offset"
+         id="feOffset958" />
+      <feComposite
+         in="SourceGraphic"
+         in2="offset"
+         operator="over"
+         result="composite2"
+         id="feComposite960" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath873">
+      <g
+         transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"
+         id="g875"
+         inkscape:label="Layer 1"
+         style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">
+        <path
+           style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"
+           d="m 46.702703,898.22775 50.594594,0 C 138.16216,898.22775 144,904.06497 144,944.92583 l 0,50.73846 c 0,40.86071 -5.83784,46.69791 -46.702703,46.69791 l -50.594594,0 C 5.8378378,1042.3622 0,1036.525 0,995.66429 L 0,944.92583 C 0,904.06497 5.8378378,898.22775 46.702703,898.22775 Z"
+           id="path877"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="sssssssss" />
+      </g>
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter891"
+       inkscape:label="Badge Shadow">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.71999962"
+         id="feGaussianBlur893" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.3995495"
+     inkscape:cx="18.514671"
+     inkscape:cy="49.018169"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1331"
+     inkscape:window-height="674"
+     inkscape:window-x="19"
+     inkscape:window-y="1"
+     inkscape:window-maximized="0"
+     showborder="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:showpageshadow="false">
+    <inkscape:grid
+       type="xygrid"
+       id="grid821" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="16,48"
+       id="guide823" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="64,80"
+       id="guide825" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="80,40"
+       id="guide827" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="64,16"
+       id="guide829" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata6522">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="BACKGROUND"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(268,-635.29076)"
+     style="display:inline">
+    <path
+       style="fill:#e6e6e6;fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"
+       d="m -268,700.15563 0,-33.72973 c 0,-27.24324 3.88785,-31.13513 31.10302,-31.13513 l 33.79408,0 c 27.21507,0 31.1029,3.89189 31.1029,31.13513 l 0,33.72973 c 0,27.24325 -3.88783,31.13514 -31.1029,31.13514 l -33.79408,0 C -264.11215,731.29077 -268,727.39888 -268,700.15563 Z"
+       id="path6455"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="sssssssss" />
+    <image
+       y="633.29077"
+       x="-270"
+       id="image3169"
+       xlink:href="data:image/png;base64,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
+AABJRU5ErkJggg==
+"
+       height="96"
+       width="96"
+       style="stroke:#000000;stroke-opacity:0.18666669" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="PLACE YOUR PICTOGRAM HERE"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="BADGE"
+     style="display:none"
+     sodipodi:insensitive="true">
+    <g
+       style="display:inline"
+       transform="translate(-340.00001,-581)"
+       id="g4394"
+       clip-path="none">
+      <g
+         id="g855">
+        <g
+           inkscape:groupmode="maskhelper"
+           id="g870"
+           clip-path="url(#clipPath873)"
+           style="opacity:0.6;filter:url(#filter891)">
+          <path
+             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"
+             d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 6.62742,0 12,5.37259 12,12 z"
+             sodipodi:ry="12"
+             sodipodi:rx="12"
+             sodipodi:cy="552.36218"
+             sodipodi:cx="252"
+             id="path844"
+             style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           id="g862">
+          <path
+             sodipodi:type="arc"
+             style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+             id="path4398"
+             sodipodi:cx="252"
+             sodipodi:cy="552.36218"
+             sodipodi:rx="12"
+             sodipodi:ry="12"
+             d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 6.62742,0 12,5.37259 12,12 z"
+             transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />
+          <path
+             transform="matrix(1.25,0,0,1.25,33,-100.45273)"
+             d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 6.62742,0 12,5.37259 12,12 z"
+             sodipodi:ry="12"
+             sodipodi:rx="12"
+             sodipodi:cy="552.36218"
+             sodipodi:cx="252"
+             id="path4400"
+             style="color:#000000;fill:#dd4814;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+             sodipodi:type="arc" />
+          <path
+             sodipodi:type="star"
+             style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+             id="path4459"
+             sodipodi:sides="5"
+             sodipodi:cx="666.19574"
+             sodipodi:cy="589.50385"
+             sodipodi:r1="7.2431178"
+             sodipodi:r2="4.3458705"
+             sodipodi:arg1="1.0471976"
+             sodipodi:arg2="1.6755161"
+             inkscape:flatsided="false"
+             inkscape:rounded="0.1"
+             inkscape:randomized="0"
+             d="m 669.8173,595.77657 c -0.39132,0.22593 -3.62645,-1.90343 -4.07583,-1.95066 -0.44938,-0.0472 -4.05653,1.36297 -4.39232,1.06062 -0.3358,-0.30235 0.68963,-4.03715 0.59569,-4.47913 -0.0939,-0.44198 -2.5498,-3.43681 -2.36602,-3.8496 0.18379,-0.41279 4.05267,-0.59166 4.44398,-0.81759 0.39132,-0.22593 2.48067,-3.48704 2.93005,-3.4398 0.44938,0.0472 1.81505,3.67147 2.15084,3.97382 0.3358,0.30236 4.08294,1.2817 4.17689,1.72369 0.0939,0.44198 -2.9309,2.86076 -3.11469,3.27355 -0.18379,0.41279 0.0427,4.27917 -0.34859,4.5051 z"
+             transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />
+        </g>
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/lib/reconfigure-aio b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/lib/reconfigure-aio
new file mode 100755 (executable)
index 0000000..a7cad90
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Reconfigures an all-in-one image to use a new home domain and number range.
+# Usage: reconfigure-aio <home-domain> [<base-number> <number-count>]
+
+# Get command-line arguments.
+home_domain=$1
+base_number=$2
+number_count=$3
+
+if [ -z "$home_domain" ] ; then
+  echo "Usage: reconfigure-aio <home-domain> [<base-number> <number-count>]"
+fi
+
+# Remove all old numbers from the database, unless they're currently assigned.
+# We do this even if the home domain hasn't changed, because the number range might have done (and
+# it's hard to tell if that's happened, and cheap/low-impact to just do the reprovisioning).
+old_home_domain=$(. /etc/clearwater/config ; echo $home_domain)
+echo "DELETE FROM ellis.numbers WHERE number LIKE '%@$old_home_domain' AND owner_id IS NULL ;" | mysql
+
+# Update /etc/clearwater/shared_config, if the home domain has changed.
+if [ "$home_domain" != "$old_home_domain" ] ; then
+  function escape { echo $1 | sed -e 's/\//\\\//g' ; }
+  sed -e 's/^home_domain=.*$/home_domain='$(escape $home_domain)'/g' \
+      </etc/clearwater/shared_config >/tmp/shared_config.$$
+  mv /tmp/shared_config.$$ /etc/clearwater/shared_config
+  
+  # Restart clearwater-infrastructure to propagate changes to other configuration files.
+  service clearwater-infrastructure restart
+fi
+
+# Create new numbers in the new domain, if we've been asked to.
+if [ -n "$base_number" ] && [ -n "$number_count" ] ; then
+  /usr/share/clearwater/ellis/env/bin/python /usr/share/clearwater/ellis/src/metaswitch/ellis/tools/create_numbers.py --start $base_number --count $number_count
+fi
+
+# Restart all the components, if the home domain has changed.
+if [ "$home_domain" != "$old_home_domain" ] ; then
+  # Work around https://github.com/Metaswitch/sprout/issues/1296.
+  service bono stop
+
+  # Restart all the processes.
+  for X in /usr/share/clearwater/infrastructure/scripts/restart/* ; do $X ; done
+
+  # Kick monit to wake up and sleep for 10 seconds to make sure it has an accurate view of the system.
+  monit
+  sleep 10
+
+  # Now wait until all the processes are back up and running (or at least "Uptime failed", which
+  # means the process is running, just hasn't been running for very long).
+  while monit summary | grep _process | egrep -v "(Running|Uptime failed)" ; do
+    echo Some processes still not running - waiting...
+    sleep 2
+  done
+  echo All processes running - configuration complete!
+fi
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/metadata.yaml b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/metadata.yaml
new file mode 100644 (file)
index 0000000..4f1ad13
--- /dev/null
@@ -0,0 +1,10 @@
+name: clearwater-aio-proxy
+summary: All-in-One proxy charm for Project Clearwater
+maintainer: Project Clearwater Maintainers <maintainers@projectclearwater.org>
+description: All-in-One proxy charm for Project Clearwater
+tags:
+  - misc
+subordinate: false
+provides:
+  ue:
+    interface: 3GPP-Gm
diff --git a/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/revision b/src/vnfd/ims_allin1_2p_vnf/charms/clearwater-aio-proxy/revision
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/src/vnfd/ims_allin1_2p_vnf/icons/metaswitch_2x.png b/src/vnfd/ims_allin1_2p_vnf/icons/metaswitch_2x.png
new file mode 100644 (file)
index 0000000..a899bc8
Binary files /dev/null and b/src/vnfd/ims_allin1_2p_vnf/icons/metaswitch_2x.png differ
diff --git a/src/vnfd/tidgen_mwc16_vnf/icons/tef.png b/src/vnfd/tidgen_mwc16_vnf/icons/tef.png
new file mode 100644 (file)
index 0000000..fcaaf88
Binary files /dev/null and b/src/vnfd/tidgen_mwc16_vnf/icons/tef.png differ
diff --git a/src/vnfd/tidgen_mwc16_vnf/mwc16gen1__vnfd.yaml b/src/vnfd/tidgen_mwc16_vnf/mwc16gen1__vnfd.yaml
new file mode 100644 (file)
index 0000000..204c8c9
--- /dev/null
@@ -0,0 +1,87 @@
+vnfd:vnfd-catalog:
+    vnfd:
+    -   id: mwc16gen
+        name: mwc16gen
+        short-name: mwc16gen
+        description: tidgen 4x10Gbps 28GB 11cores
+        logo: tef.png
+        mgmt-interface:
+            vdu-id: mwc16gen1-VM
+        connection-point:
+        -   name: eth0
+            type: VPORT
+        -   name: eth1
+            type: VPORT
+        -   name: xe0
+            type: VPORT
+        -   name: xe1
+            type: VPORT
+        -   name: xe2
+            type: VPORT
+        -   name: xe3
+            type: VPORT
+        vdu:
+        -   id: mwc16gen1-VM
+            name: mwc16gen1-VM
+            description: tidgen with 4x10Gbps 28GB
+            image: /mnt/powervault/virtualization/vnfs/demos/mwc2016/tidgen_mwc16.qcow2
+            vm-flavor:
+                memory-mb: '28672'
+            mgmt-vpci: 0000:00:0a.0
+            external-interface:
+            -   name: xe0
+                virtual-interface:
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:10.0'
+                vnfd-connection-point-ref: xe0
+            -   name: xe1
+                virtual-interface:
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:11.0'
+                vnfd-connection-point-ref: xe1
+            -   name: xe2
+                virtual-interface:
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:12.0'
+                vnfd-connection-point-ref: xe2
+            -   name: xe3
+                virtual-interface:
+                    type: PCI-PASSTHROUGH
+                    vpci: '0000:00:13.0'
+                vnfd-connection-point-ref: xe3
+            -   name: eth0
+                virtual-interface:
+                    bandwidth: '1000000'
+                    type: VIRTIO
+                    vpci: 0000:00:0a.0
+                vnfd-connection-point-ref: eth0
+            -   name: eth1
+                virtual-interface:
+                    bandwidth: '1000000'
+                    type: OM-MGMT
+                    vpci: 0000:00:0b.0
+                vnfd-connection-point-ref: eth1
+            guest-epa:
+                cpu-pinning-policy: DEDICATED
+                cpu-thread-pinning-policy: PREFER
+                mempage-size: LARGE
+                numa-node-policy:
+                    mem-policy: STRICT
+                    node:
+                    -   id: '0'
+                        paired-threads:
+                            num-paired-threads: '11'
+                    node-cnt: '1'
+            host-epa:
+                om-cpu-feature:
+                - 64b
+                - iommu
+                - lps
+                - tlbps
+                - hwsv
+                - dioc
+                - ht
+                om-cpu-model-string: Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz
+            hypervisor-epa:
+                type: REQUIRE_KVM
+                version: 10002|12001|2.6.32-358.el6.x86_64