Apex-pdp documentation conversion from .adoc to .rst
[policy/parent.git] / docs / apex / APEX-PCVS-Example.rst
diff --git a/docs/apex/APEX-PCVS-Example.rst b/docs/apex/APEX-PCVS-Example.rst
new file mode 100644 (file)
index 0000000..fc42030
--- /dev/null
@@ -0,0 +1,2954 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+
+.. _apex-PCVSExample:
+
+Policy-controlled Video Streaming (pcvs) with APEX
+**************************************************
+
+.. contents::
+    :depth: 3
+
+Introduction
+^^^^^^^^^^^^
+
+      .. container:: sectionbody
+
+           .. container:: paragraph
+
+                  This module contains several demos for
+                  Policy-controlled Video Streaming (PCVS). Each demo
+                  defines a policy using AVRO and Javascript (or other
+                  scripting languages for the policy logic). To run the
+                  demo, a vanilla Ubuntu server with some extra software
+                  packages is required:
+
+               .. container:: ulist
+
+                  -  Mininet as network simulator
+
+                  -  Floodlight as SDN controller
+
+                  -  Kafka as messaging system
+
+                  -  Zookeeper for Kafka configuration
+
+                  -  APEX for policy control
+
+Install Ubuntu Server and SW
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+          .. container:: sect1
+
+            .. rubric:: Install Demo
+               :name: install_demo
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  Requirements:
+
+               .. container:: ulist
+
+                  -  Ubuntu server: 1.4 GB
+
+                  -  Ubuntu with Xubuntu Desktop, git, Firefox: 2.3 GB
+
+                  -  Ubuntu with all, system updated: 3 GB
+
+                  -  With ZK, Kafka, VLC, Mininet, Floodlight, Python:
+                     4.4 GB
+
+                  -  APEX Build (M2 and built): M2 ~ 2 GB, APEX ~3.5 GB
+
+                  -  APEX install (not build locally): ~ 300 MB
+
+               .. container:: paragraph
+
+                  On a Ubuntu OS (install a stable or LTS server first)
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     ::
+
+                        # pre for Ubuntu, tools and X
+                        sudo apt-get  -y install --no-install-recommends software-properties-common
+                        sudo apt-get  -y install --no-install-recommends build-essential
+                        sudo apt-get  -y install --no-install-recommends git
+                        sudo aptitude -y install --no-install-recommends xubuntu-desktop
+                        sudo apt-get  -y install --no-install-recommends firefox
+
+
+                        # install Java
+                        sudo add-apt-repository ppa:webupd8team/java
+                        sudo apt-get update
+                        sudo apt-get -y install --no-install-recommends oracle-java8-installer
+                        java -version
+
+
+                        # reboot system, run system update, then continue
+
+                        # if VBox additions are needed, install and reboot
+                        sudo (cd /usr/local/share; wget https://www.virtualbox.org/download/testcase/VBoxGuestAdditions_5.2.7-120528.iso)
+                        sudo mount /usr/local/share/VBoxGuestAdditions_5.2.7-120528.iso /media/cdrom
+                        sudo (cd /media/cdrom;VBoxLinuxAdditions.run)
+
+
+                        # update apt-get DB
+                        sudo apt-get update
+
+                        # if APEX is build from source, install maven and rpm
+                        sudo apt-get install maven rpm
+
+                        # install ZooKeeper
+                        sudo apt-get install zookeeperd
+
+                        # install Kafka
+                        (cd /tmp;wget http://ftp.heanet.ie/mirrors/www.apache.org/dist/kafka/1.0.0/kafka_2.12-1.0.0.tgz --show-progress)
+                        sudo mkdir /opt/Kafka
+                        sudo tar -xvf /tmp/kafka_2.12-1.0.0.tgz -C /opt/Kafka/
+
+                        # install mininet
+                        cd /usr/local/src
+                        sudo git clone https://github.com/mininet/mininet.git
+                        (cd mininet;util/install.sh -a)
+
+                        # install floodlight, requires ant
+                        sudo apt-get install ant
+                        cd /usr/local/src
+                        sudo wget --no-check-certificate https://github.com/floodlight/floodlight/archive/master.zip
+                        sudo unzip master.zip
+                        cd floodlight-master
+                        sudo ant
+                        sudo mkdir /var/lib/floodlight
+                        sudo chmod 777 /var/lib/floodlight
+
+                        # install python pip
+                        sudo apt-get install python-pip
+
+                        # install kafka-python (need newer version from github)
+                        cd /usr/local/src
+                        sudo git clone https://github.com/dpkp/kafka-python
+                        sudo pip install ./kafka-python
+
+                        # install vlc
+                        sudo apt-get install vlc
+
+               .. container:: paragraph
+
+                  Install APEX either from source or from a distribution
+                  package. See the APEX documentation for details. We
+                  assume that APEX is installed in
+                  ``/opt/ericsson/apex/apex``
+
+               .. container:: paragraph
+
+                  Copy the LinkMonitor file to Kafka-Python
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     ::
+
+                        sudo cp /opt/ericsson/apex/apex/examples/scripts/pcvs/vpnsla/LinkMonitor.py /usr/local/src/kafka-python
+
+               .. container:: paragraph
+
+                  Change the Logback configuration in APEX to logic
+                  logging
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     ::
+
+                        (cd /opt/ericsson/apex/apex/etc; sudo cp logback-logic.xml logback.xml)
+
+         .. container:: sect1
+
+            .. rubric:: Get the Demo Video
+               :name: get_the_demo_video
+
+            .. container:: sectionbody
+
+               .. container:: ulist
+
+                  -  For all download options of the movie please visit
+                     http://bbb3d.renderfarming.net/download.html
+
+                  -  For lower-res downloads and mirrors see
+                     https://peach.blender.org/download
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     ::
+
+                        sudo mkdir /usr/local/src/videos
+
+               .. container:: paragraph
+
+                  Standard 720p (recommended)
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     ::
+
+                        (cd /usr/local/src/videos; sudo curl -o big_buck_bunny_480p_surround.avi http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_480p_surround-fix.avi)
+
+               .. container:: paragraph
+
+                  Full HD video
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     ::
+
+                        (cd videos; sudo curl -o bbb_sunflower_1080p_60fps_normal.mp4 http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_60fps_normal.mp4)
+
+
+
+VPN SLA Demo
+^^^^^^^^^^^^^
+
+          .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  This demo uses a network with several central office
+                  and core switches, over which two VPNs are run. A
+                  customer ``A`` has two location ``A1`` and ``A2`` and
+                  a VPN between them. A customer ``B`` has two location
+                  ``B1`` and ``B2`` and a VPN between them.
+
+               .. container:: imageblock
+
+                  .. container:: content
+
+                     |VPN SLA Architecture|
+
+               .. container:: paragraph
+
+                  The architecture above shows the scenario. The
+                  components are realized in this demo as follows:
+
+               .. container:: ulist
+
+                  -  *CEP / Analytics* - a simple Python script taking
+                     events from Kafka and sending them to APEX
+
+                  -  *APEX / Policy* - the APEX engine running the VPA
+                     SLA policy
+
+                  -  *Controller* - A vanilla Floodlight controller
+                     taking events from the Link Monitor and configuring
+                     Mininet
+
+                  -  *Network* - A network created using Mininet
+
+               .. container:: paragraph
+
+                  The demo requires to start some software (detailed
+                  below). To show actual video streams, we use ``VLC``.
+                  If you do not want to show video streams, but only the
+                  policy, skip the ``VLC`` section.
+
+               .. container:: paragraph
+
+                  All shown scripts are available in a full APEX
+                  installation in
+                  ``$APEX_HOME/examples/scripts/pcvs/vpnsla``.
+
+               .. container:: sect2
+
+                  .. rubric:: Start all Software
+                     :name: start_all_software
+
+                  .. container:: paragraph
+
+                     Create environment variables in a file, say
+                     ``env.sh``. In each new Xterm
+
+                  .. container:: ulist
+
+                     -  Source these environment settings, e.g.
+                        ``. ./env.sh``
+
+                     -  Run the commands below as root (``sudo`` per
+                        command or ``sudo -i`` for interactive mode as
+                        shown below)
+
+                  .. container:: listingblock
+
+                     .. container:: content
+
+                        ::
+
+                           #!/usr/bin/env bash
+
+                           export src_dir=/usr/local/src
+                           export APEX_HOME=/opt/ericsson/apex/apex
+                           export APEX_USER=apexuser
+
+                  .. container:: paragraph
+
+                     In a new Xterm, start Floodlight
+
+                  .. container:: listingblock
+
+                     .. container:: content
+
+                        ::
+
+                           sudo -i
+                           . ./env.sh
+                           cd $src_dir/floodlight-master && java -jar target/floodlight.jar
+
+                  .. container:: paragraph
+
+                     In a new Xterm start Mininet
+
+                  .. container:: listingblock
+
+                     .. container:: content
+
+                        ::
+
+                           sudo -i
+                           . ./env.sh
+                           mn -c && python $APEX_HOME/examples/scripts/pcvs/vpnsla/MininetTopology.py
+
+                  .. container:: paragraph
+
+                     In a new Xterm, start Kafka
+
+                  .. container:: listingblock
+
+                     .. container:: content
+
+                        ::
+
+                           sudo -i
+                           . ./env.sh
+                           /opt/Kafka/kafka_2.12-1.0.0/bin/kafka-server-start.sh /opt/Kafka/kafka_2.12-1.0.0/config/server.properties
+
+                  .. container:: paragraph
+
+                     In a new Xerm start APEX with the Kafka
+                     configuration for this demo
+
+                  .. container:: listingblock
+
+                     .. container:: content
+
+                        ::
+
+                           cd $APEX_HOME
+                           ./bin/apexApps.sh engine -c examples/config/pcvs/vpnsla/kafka2kafka.json
+
+                  .. container:: paragraph
+
+                     In a new Xterm start the Link Monitor. The Link
+                     Monitor has a 30 second sleep to slow down the
+                     demonstration. So the first action of it comes 30
+                     seconds after start. Every new action in 30 second
+                     intervals.
+
+                  .. container:: listingblock
+
+                     .. container:: content
+
+                        ::
+
+                           sudo -i
+                           . ./env.sh
+                           cd $src_dir
+                           xterm -hold -e 'python3 $src_dir/kafka-python/LinkMonitor.py' &
+
+                  .. container:: paragraph
+
+                     Now all software should be started and the demo is
+                     running. The Link Monitor will send link up events,
+                     picked up by APEX which triggers the policy. Since
+                     there is no problem, the policy will do nothing.
+
+               .. container:: sect2
+
+                  .. rubric:: Create 2 Video Streams with VLC
+                     :name: create_2_video_streams_with_vlc
+
+                  .. container:: paragraph
+
+                     In the Mininet console, type ``xterm A1 A2`` and
+                     ``xterm B1 B2`` to open terminals on these nodes.
+
+                  .. container:: paragraph
+
+                     ``A2`` and ``B2`` are the receiving nodes. In these
+                     terminals, run ``vlc-wrapper``. In each opened VLC
+                     window do
+
+                  .. container:: ulist
+
+                     -  Click Media → Open Network Stream
+
+                     -  Give the URL as ``rtp://@:5004``
+
+                  .. container:: paragraph
+
+                     ``A1`` and ``B1`` are the sending nodes (sending
+                     the video stream) In these terminals, run
+                     ``vlc-wrapper``. In each opened VLC window do
+
+                  .. container:: ulist
+
+                     -  Click Media → Stream
+
+                     -  Add the video (from ``/usr/local/src/videos``)
+
+                     -  Click ``Stream``
+
+                     -  Click ``Next``
+
+                     -  Change the destination
+                        ``RTP / MPEG Transport Stream`` and click
+                        ``Add``
+
+                     -  Change the address and type to ``10.0.0.2`` in
+                        ``A1`` and to ``10.0.0.4`` in ``B1``
+
+                     -  Turn off ``Active Transcoding`` (this is
+                        important to minimize CPU load)
+
+                     -  Click ``Next``
+
+                     -  Click ``Stream``
+
+                  .. container:: paragraph
+
+                     The video should be streaming across the network
+                     from ``A1`` to ``A2`` and from ``B1`` to ``B2``. If
+                     the video streams a slow or interrupted the CPU
+                     load is too high. In these cases either try a
+                     better machine or use a different (lower quality)
+                     video stream.
+
+               .. container:: sect2
+
+                  .. rubric:: Take out L09 and let the Policy do it’s
+                     Magic
+                     :name: take_out_l09_and_let_the_policy_do_it_s_magic
+
+                  .. container:: paragraph
+
+                     Now it is time to take out the link ``L09``. This
+                     will be picked up by the Link Monitor, which sends
+                     a new event (L09 DOWN) to the policy. The policy
+                     then will calculate which customer should be
+                     impeded (throttled). This will continue, until SLAs
+                     are violated, then a priority calculation will kick
+                     in (Customer ``A`` is prioritized in the setup).
+
+                  .. container:: paragraph
+
+                     To initiate this, simply type ``link s5 s6 down``
+                     in the Mininet console followed by ``exit``.
+
+                  .. container:: paragraph
+
+                     If you have the video streams running, you will see
+                     one or the other struggeling, depending on the
+                     policy decision.
+
+               .. container:: sect2
+
+                  .. rubric:: Reset the Demo
+                     :name: reset_the_demo
+
+                  .. container:: paragraph
+
+                     If you want to reset the demo, simple stop (in this
+                     order) the following process
+
+                  .. container:: ulist
+
+                     -  Link Monitor
+
+                     -  APEX
+
+                     -  Mininet
+
+                     -  Floodlight
+
+                  .. container:: paragraph
+
+                     Then restart them in this order
+
+                  .. container:: ulist
+
+                     -  Floodlight
+
+                     -  Mininet
+
+                     -  APEX
+
+                     -  Link Monitor
+
+               .. container:: sect2
+
+                  .. rubric:: Monitor the Demo
+                     :name: monitor_the_demo
+
+                  .. container:: paragraph
+
+                     Floodlight and APEX provide REST interfaces for
+                     monitoring.
+
+                  .. container:: ulist
+
+                     -  Floodlight: see `Floodlight
+                        Docs <https://floodlight.atlassian.net/wiki/spaces/floodlightcontroller/pages/40403023/Web+GUI>`__
+                        for details on how to access the monitoring. In
+                        a standard installation as we use here, pointing
+                        browser to the URL
+                        ``http://localhost:8080/ui/pages/index.html``
+                        should work on the same host
+
+                     -  APEX please see the APEX documentation for
+                        `Monitoring
+                        Client <https://ericsson.github.io/apex-docs/user-manual/engine-apps/um-engapps-eng-monitoring.html>`__
+                        or `Full
+                        Client <https://ericsson.github.io/apex-docs/user-manual/engine-apps/um-engapps-full-client.html>`__
+                        for details on how to monitor APEX.
+
+
+VPN SLA Policy
+^^^^^^^^^^^^^^
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The VPN SLA policy is designed as a MEDA policy. The
+                  first state (M = Match) takes the trigger event (a
+                  link up or down) and checks if this is a change to the
+                  known topology. The second state (E = Establish) takes
+                  all available information (trigger event, local
+                  context) and defines what situation we have. The third
+                  state (D = Decide) takes the situation and selects
+                  which algorithm is best to process it. This state can
+                  select between ``none`` (nothing to do), ``solved`` (a
+                  problem is solved now), ``sla`` (compare the current
+                  customer SLA situation and select one to impede), and
+                  ``priority`` (impede non-priority customers). The
+                  fourth and final state (A = Act) selects the right
+                  action for the taken decision and creates the response
+                  event sent to the orchestrator.
+
+               .. container:: paragraph
+
+                  We have added three more policies to set the local
+                  context: one for adding nodes, one for adding edges
+                  (links), and one for adding customers. These policies
+                  do not realize any action, they are only here for
+                  updating the local context. This mechanism is the
+                  fasted way to update local context, and it is
+                  independent of any context plugin.
+
+               .. container:: paragraph
+
+                  The policy uses data defined in Avro, so we have a
+                  number of Avro schema definitions.
+
+Context Schemas
+---------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The context schemas are for the local context. We
+                  model edges and nodes for the topology, customers, and
+                  problems with all information on detected problems.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        {
+                            "type" : "record",
+                            "name" : "TopologyEdges",
+                            "fields" : [
+                                {"name": "name",   "type": "string",  "doc": "Name of the Edge, typically a link name"},
+                                {"name": "start",  "type": "string",  "doc": "Edge endpoint: start - a node name"},
+                                {"name": "end",    "type": "string",  "doc": "Edge endpoint: end - a node name"},
+                                {"name": "active", "type": "boolean", "doc": "Flag for active/inactive edges, inactive means a link is down"}
+                            ]
+                        }
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        {
+                            "type" : "record",
+                            "name" : "TopologyNodes",
+                            "fields" : [
+                                {"name" : "name",   "type" : "string", "doc": "The name of the node"},
+                                {"name" : "mnname", "type" : "string", "doc": "The name of the node in Mininet"}
+                            ]
+                        }
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        {
+                            "type" : "record",
+                            "name" : "Customer",
+                            "fields" : [
+                                {"name" : "customerName", "type" : "string"},
+                                {"name" : "dtSLA"       , "type" : "int"},
+                                {"name" : "dtYTD"       , "type" : "int"},
+                                {"name" : "priority"    , "type" : "boolean"},
+                                {"name" : "satisfaction", "type" : "int"},
+                                {
+                                    "name": "links",
+                                    "doc": "Links used by this customer",
+                                    "type": {"type"  : "array", "items" : "string"}
+                                }
+                            ]
+                        }
+
+
+Trigger Schemas
+---------------
+
+        .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The trigger event provides a status as ``UP`` or
+                  ``DOWN``. To avoid tests for these strings in the
+                  logic, we defined an Avro schema for an enumeration.
+                  This does not impact the trigger system (it can still
+                  send the strings), but makes the task logic simpler.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        {
+                            "type": "enum",
+                            "name": "Status",
+                            "symbols" : [
+                                "UP",
+                                "DOWN"
+                            ]
+                        }
+
+Context Logic Nodes
+--------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The node context logic simply takes the trigger event
+                  (for context) and creates a new node in the local
+                  context topology.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var ifNodeName = executor.inFields["nodeName"];
+                        var ifMininetName = executor.inFields["mininetName"];
+
+                        var albumTopoNodes = executor.getContextAlbum("albumTopoNodes");
+
+                        logger.trace("-- got infields, testing existing node");
+
+                        var ctxtNode = albumTopoNodes.get(ifNodeName);
+                        if (ctxtNode != null) {
+                            albumTopoNodes.remove(ifNodeName);
+                            logger.trace("-- removed node: <" + ifNodeName + ">");
+                        }
+
+                        logger.trace("-- creating node: <" + ifNodeName + ">");
+                        ctxtNode = "{name:" + ifNodeName + ", mnname:" + ifMininetName + "}";
+                        albumTopoNodes.put(ifNodeName, ctxtNode);
+
+                        if (logger.isTraceEnabled()) {
+                            logger.trace("   >> *** Nodes ***");
+                            if (albumTopoNodes != null) {
+                                for (var i = 0; i < albumTopoNodes.values().size(); i++) {
+                                    logger.trace("   >> >> " + albumTopoNodes.values().get(i).get("name") + " : "
+                                            + albumTopoNodes.values().get(i).get("mnname"));
+                                }
+                            } else {
+                                logger.trace("   >> >> node album is null");
+                            }
+                        }
+
+                        executor.outFields["report"] = "node ctxt :: added node " + ifNodeName;
+
+                        logger.info("vpnsla: ctxt added node " + ifNodeName);
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        var returnValue = new returnValueType(true);
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".");
+
+Context Logic Edges
+--------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The edge context logic simply takes the trigger event
+                  (for context) and creates a new edge in the local
+                  context topology.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var ifEdgeName = executor.inFields["edgeName"];
+                        var ifEdgeStatus = executor.inFields["status"];
+
+                        var albumTopoEdges = executor.getContextAlbum("albumTopoEdges");
+
+                        logger.trace("-- got infields, testing existing edge");
+
+                        var ctxtEdge = albumTopoEdges.get(ifEdgeName);
+                        if (ctxtEdge != null) {
+                            albumTopoEdges.remove(ifEdgeName);
+                            logger.trace("-- removed edge: <" + ifEdgeName + ">");
+                        }
+
+                        logger.trace("-- creating edge: <" + ifEdgeName + ">");
+                        ctxtEdge = "{name:" + ifEdgeName + ", start:" + executor.inFields["start"] + ", end:" + executor.inFields["end"]
+                                + ", active:" + ifEdgeStatus + "}";
+                        albumTopoEdges.put(ifEdgeName, ctxtEdge);
+
+                        if (logger.isTraceEnabled()) {
+                            logger.trace("   >> *** Edges ***");
+                            if (albumTopoEdges != null) {
+                                for (var i = 0; i < albumTopoEdges.values().size(); i++) {
+                                    logger.trace("   >> >> " + albumTopoEdges.values().get(i).get("name") + " \t "
+                                            + albumTopoEdges.values().get(i).get("start") + " --> " + albumTopoEdges.values().get(i).get("end")
+                                            + " \t " + albumTopoEdges.values().get(i).get("active"));
+                                }
+                            } else {
+                                logger.trace("   >> >> edge album is null");
+                            }
+                        }
+
+                        executor.outFields["report"] = "edge ctxt :: added edge " + ifEdgeName;
+
+                        logger.info("vpnsla: ctxt added edge " + ifEdgeName);
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        var returnValue = new returnValueType(true);
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".");
+
+Context Logic Customer
+----------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The customer context logic simply takes the trigger
+                  event (for context) and creates a new customer in the
+                  local context topology.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var ifCustomerName = executor.inFields["customerName"];
+                        var ifLinks = executor.inFields["links"];
+
+                        logger.trace("-- got infields, testing existing customer");
+                        var ctxtCustomer = executor.getContextAlbum("albumCustomerMap").get(ifCustomerName);
+                        if (ctxtCustomer != null) {
+                            executor.getContextAlbum("albumCustomerMap").remove(ifCustomerName);
+                            logger.trace("-- removed customer: <" + ifCustomerName + ">");
+                        }
+
+                        logger.trace("-- creating customer: <" + ifCustomerName + ">");
+                        var links = new Array();
+                        for (var i = 0; i < ifLinks.split(" ").length; i++) {
+                            var link = executor.getContextAlbum("albumTopoEdges").get(ifLinks.split(" ")[i]);
+                            if (link != null) {
+                                logger.trace("-- link: <" + ifLinks.split(" ")[i] + ">");
+                                links.push(ifLinks.split(" ")[i]);
+                            } else {
+                                logger.trace("-- unknown link: <" + ifLinks.split(" ")[i] + "> for customer <" + ifCustomerName + ">");
+                            }
+                        }
+                        logger.trace("-- links: <" + links + ">");
+                        ctxtCustomer = "{customerName:" + ifCustomerName + ", dtSLA:" + executor.inFields["dtSLA"] + ", dtYTD:"
+                                + executor.inFields["dtYTD"] + ", priority:" + executor.inFields["priority"] + ", satisfaction:"
+                                + executor.inFields["satisfaction"] + ", links:[" + links + "]}";
+
+                        executor.getContextAlbum("albumCustomerMap").put(ifCustomerName, ctxtCustomer);
+
+                        if (logger.isTraceEnabled()) {
+                            logger.trace("   >> *** Customers ***");
+                            if (executor.getContextAlbum("albumCustomerMap") != null) {
+                                for (var i = 0; i < executor.getContextAlbum("albumCustomerMap").values().size(); i++) {
+                                    logger.trace("   >> >> " + executor.getContextAlbum("albumCustomerMap").values().get(i).get("customerName")
+                                            + " : " + "dtSLA=" + executor.getContextAlbum("albumCustomerMap").values().get(i).get("dtSLA")
+                                            + " : " + "dtYTD=" + executor.getContextAlbum("albumCustomerMap").values().get(i).get("dtYTD")
+                                            + " : " + "links=" + executor.getContextAlbum("albumCustomerMap").values().get(i).get("links")
+                                            + " : " + "priority="
+                                            + executor.getContextAlbum("albumCustomerMap").values().get(i).get("priority") + " : "
+                                            + "satisfaction="
+                                            + executor.getContextAlbum("albumCustomerMap").values().get(i).get("satisfaction"));
+                                }
+                            } else {
+                                logger.trace("   >> >> customer album is null");
+                            }
+                        }
+
+                        executor.outFields["report"] = "customer ctxt :: added customer: " + ifCustomerName;
+
+                        logger.info("vpnsla: ctxt added customer " + ifCustomerName);
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        var returnValue = new returnValueType(true);
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".");
+
+Logic: Match
+------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  This is the logic for the match state. It is kept very
+                  simple. Beside taking the trigger event, it also
+                  creates a timestamp. This timestamp is later used for
+                  SLA and downtime calculations as well as for some
+                  performance information of the policy.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+
+                        var now = new Date().getTime();
+                        executor.outFields["matchStart"] = now;
+
+                        importClass(org.slf4j.LoggerFactory);
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
+
+                        var ifEdgeName = executor.inFields["edgeName"];
+                        var ifLinkStatus = executor.inFields["status"];
+
+                        var albumTopoEdges = executor.getContextAlbum("albumTopoEdges");
+
+                        logger.trace("-- got infields, checking albumTopoEdges changes");
+
+                        var active = false;
+                        switch (ifLinkStatus.toString()) {
+                        case "UP":
+                            active = true;
+                            break;
+                        case "DOWN":
+                            active = false;
+                            break;
+                        default:
+                            active = false;
+                            logger.error("-- trigger sent unknown link status <" + ifLinkStatus + "> for link <" + ifEdgeName + ">");
+                            rootLogger.error(executor.subject.id + " " + "-- trigger sent unknown link status <" + ifLinkStatus
+                                    + "> for link <" + ifEdgeName + ">");
+                        }
+
+                        var link = albumTopoEdges.get(ifEdgeName);
+                        if (link == null) {
+                            logger.trace("-- link <" + ifEdgeName + "> not in albumTopoEdges");
+                        } else {
+                            logger.trace("-- found link <" + link + "> in albumTopoEdges");
+                            logger.trace("-- active <" + active + "> : link.active <" + link.get("active") + ">");
+                            if (active != link.get("active")) {
+                                link.put("active", active);
+                                logger.trace("-- link <" + ifEdgeName + "> status changed to <active:" + link.get("active") + ">");
+                                executor.outFields["hasChanged"] = true;
+                            } else {
+                                logger.trace("-- link <" + ifEdgeName + "> status not changed <active:" + link.get("active") + ">");
+                                executor.outFields["hasChanged"] = false;
+                            }
+                        }
+
+                        executor.outFields["edgeName"] = ifEdgeName;
+                        executor.outFields["status"] = ifLinkStatus;
+
+                        logger.info("vpnsla: detected " + ifEdgeName + " as " + ifLinkStatus);
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        var returnValue = new returnValueType(true);
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".m");
+
+
+Logic: Policy Establish State
+-----------------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  This is the logic for the establish state. It is the
+                  most complicated logic, since establishing a situation
+                  for a decision is the most important part of any
+                  policy. First, the policy describes what we find (the
+                  switch block), in terms of 8 normal situations and 1
+                  extreme error case.
+
+               .. container:: paragraph
+
+                  If required, it creates local context information for
+                  the problem (if it is new) or updates it (if the
+                  problem still exists). It also calculates customer SLA
+                  downtime and checks for any SLA violations. Finally,
+                  it creates a situation object.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+                        importClass(org.slf4j.LoggerFactory);
+
+                        importClass(java.util.ArrayList);
+
+                        importClass(org.apache.avro.generic.GenericData.Array);
+                        importClass(org.apache.avro.generic.GenericRecord);
+                        importClass(org.apache.avro.Schema);
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
+
+                        var ifEdgeName = executor.inFields["edgeName"];
+                        var ifEdgeStatus = executor.inFields["status"].toString();
+                        var ifhasChanged = executor.inFields["hasChanged"];
+                        var ifMatchStart = executor.inFields["matchStart"];
+
+                        var albumCustomerMap = executor.getContextAlbum("albumCustomerMap");
+                        var albumProblemMap = executor.getContextAlbum("albumProblemMap");
+
+                        var linkProblem = albumProblemMap.get(ifEdgeName);
+
+                        // create outfiled for situation
+                        var situation = executor.subject.getOutFieldSchemaHelper("situation").createNewInstance();
+                        situation.put("violatedSLAs", new ArrayList());
+
+                        // create a string as states+hasChanged+linkProblem and switch over it
+                        var switchTest = ifEdgeStatus + ":" + ifhasChanged + ":" + (linkProblem == null ? "no" : "yes");
+                        switch (switchTest) {
+                        case "UP:false:no":
+                            logger.trace("-- edge <" + ifEdgeName + "> UP:false:no => everything ok");
+                            logger.info("vpnsla: everything ok");
+                            situation.put("problemID", "NONE");
+                            break;
+                        case "UP:false:yes":
+                            logger.trace("-- edge <" + ifEdgeName + "> UP:false:yes ==> did we miss earlier up?, removing problem");
+                            albumProblemMap.remove(ifEdgeName);
+                            linkProblem = null;
+                            situation.put("problemID", "NONE");
+                            break;
+                        case "UP:true:no":
+                            logger.trace("-- edge <" + ifEdgeName + "> UP:true:no ==> did we miss the earlier down?, creating new problem");
+                            situation.put("problemID", ifEdgeName);
+                            break;
+                        case "UP:true:yes":
+                            logger.trace("-- edge <" + ifEdgeName + "> UP:true:yes ==> detected solution, link up again");
+                            logger.info("vpnsla: problem solved");
+                            linkProblem.put("endTime", ifMatchStart);
+                            linkProblem.put("status", "SOLVED");
+                            situation.put("problemID", "NONE");
+                            break;
+                        case "DOWN:false:no":
+                            logger.trace("-- edge <" + ifEdgeName + "> DOWN:false:no ==> did we miss an earlier down?, creating new problem");
+                            situation.put("problemID", ifEdgeName);
+                            break;
+                        case "DOWN:false:yes":
+                            logger.trace("-- edge <" + ifEdgeName + "> DOWN:false:yes ==> problem STILL exists");
+                            logger.info("vpnsla: problem still exists");
+                            linkProblem.put("status", "STILL");
+                            situation.put("problemID", ifEdgeName);
+                            break;
+                        case "DOWN:true:no":
+                            logger.trace("-- edge <" + ifEdgeName + "> DOWN:true:no ==> found NEW problem");
+                            logger.info("vpnsla: this is a new problem");
+                            situation.put("problemID", ifEdgeName);
+                            break;
+                        case "DOWN:true:yes":
+                            logger.trace("-- edge <" + ifEdgeName
+                                    + "> DOWN:true:yes ==> did we miss to remove an earlier problem?, remove and create new problem");
+                            linkProblem = null;
+                            situation.put("problemID", ifEdgeName);
+                            break;
+
+                        default:
+                            logger.error("-- input wrong for edge" + ifEdgeName + ": edge status <" + ifEdgeStatus
+                                    + "> unknown or null on hasChanged <" + ifhasChanged + ">");
+                            rootLogger.error("-- input wrong for edge" + ifEdgeName + ": edge status <" + ifEdgeStatus
+                                    + "> unknown or null on hasChanged <" + ifhasChanged + ">");
+                        }
+
+                        // create new problem if situation requires it
+                        if (situation.get("problemID").equals(ifEdgeName) && linkProblem == null) {
+                            logger.trace("-- edge <" + ifEdgeName + "> creating new problem");
+                            linkProblem = albumProblemMap.getSchemaHelper().createNewInstance();
+                            linkProblem.put("edge", ifEdgeName);
+                            linkProblem.put("startTime", ifMatchStart);
+                            linkProblem.put("lastUpdate", ifMatchStart);
+                            linkProblem.put("endTime", 0);
+                            linkProblem.put("status", "NEW");
+                            linkProblem.put("edgeUsedBy", new ArrayList());
+                            linkProblem.put("impededLast", new ArrayList());
+
+                            for (var i = 0; i < albumCustomerMap.values().size(); i++) {
+                                var customer = albumCustomerMap.values().get(i);
+                                var customerLinks = albumCustomerMap.values().get(i).get("links");
+                                for (var k = 0; k < customerLinks.size(); k++) {
+                                    if (customerLinks.get(k) == ifEdgeName) {
+                                        linkProblem.get("edgeUsedBy").add(customer.get("customerName"));
+                                    }
+                                }
+                            }
+                            albumProblemMap.put(ifEdgeName, linkProblem);
+                            logger.trace("-- edge <" + ifEdgeName + "> problem created as <" + linkProblem + ">");
+                        }
+
+                        // set dtYTD if situation requires it
+                        if (linkProblem != null && (linkProblem.get("status") == "STILL" || linkProblem.get("status") == "SOLVED")) {
+                            var linkDownTimeinSecs = (ifMatchStart - linkProblem.get("lastUpdate")) / 1000;
+                            logger.trace("-- edge <" + ifEdgeName + "> down time: " + linkDownTimeinSecs + " s");
+                            for (var k = 0; k < linkProblem.get("impededLast").size(); k++) {
+                                for (var i = 0; i < albumCustomerMap.values().size(); i++) {
+                                    var customer = albumCustomerMap.values().get(i);
+                                    if (customer.get("customerName").equals(linkProblem.get("impededLast").get(k))) {
+                                        logger.info("-- vpnsla: customer " + customer.get("customerName") + " YDT downtime increased from "
+                                                + customer.get("dtYTD") + " to " + (customer.get("dtYTD") + linkDownTimeinSecs));
+                                        customer.put("dtYTD", (customer.get("dtYTD") + linkDownTimeinSecs))
+                                    }
+                                }
+                            }
+                            // set lastUpdate to this policy execution for next execution calculation
+                            linkProblem.put("lastUpdate", ifMatchStart);
+                        }
+
+                        // check SLA violations if situation requires it
+                        if (linkProblem != null && linkProblem.get("status") != "SOLVED") {
+                            logger.info(">e> customer\tDT SLA\tDT YTD\tviolation");
+                            for (var i = 0; i < albumCustomerMap.values().size(); i++) {
+                                var customer = albumCustomerMap.values().get(i);
+                                if (customer.get("dtYTD") > customer.get("dtSLA")) {
+                                    situation.get("violatedSLAs").add(customer.get("customerName"));
+                                    logger.info(">e> " + customer.get("customerName") + "\t\t" + customer.get("dtSLA") + "s\t"
+                                            + customer.get("dtYTD") + "s\t" + "!!");
+                                } else {
+                                    logger.info(">e> " + customer.get("customerName") + "\t\t" + customer.get("dtSLA") + "s\t"
+                                            + customer.get("dtYTD") + "s");
+                                }
+                            }
+                        }
+
+                        executor.outFields["situation"] = situation;
+
+                        logger.trace("-- out fields <" + executor.outFields + ">");
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        var returnValue = new returnValueType(true);
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".e");
+
+Logic: Policy Decide State
+--------------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The decide state can select between different
+                  algorithms depending on the situation. So it needs a
+                  Task Selection Logic (TSL). This TSL select a task in
+                  the current policy execution (i.e. potentially a
+                  different one per execution).
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+                        importClass(org.slf4j.LoggerFactory);
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id + " - TSL");
+
+                        var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
+
+                        var ifSituation = executor.inFields["situation"];
+
+                        var albumProblemMap = executor.getContextAlbum("albumProblemMap");
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        if (ifSituation.get("problemID") == "NONE") {
+                            logger.trace("-- situation has no problem, selecting <VpnSlaPolicyDecideNoneTask>");
+                            executor.subject.getTaskKey("VpnSlaPolicyDecideNoneTask").copyTo(executor.selectedTask);
+                            var returnValue = new returnValueType(true);
+                        } else if (albumProblemMap.get(ifSituation.get("problemID")).get("status") == "SOLVED") {
+                            logger.trace("-- situation is solved, selecting <VpnSlaPolicyDecideSolvedTask>");
+                            executor.subject.getTaskKey("VpnSlaPolicyDecideSolvedTask").copyTo(executor.selectedTask);
+                            var returnValue = new returnValueType(true);
+                        } else if (ifSituation.get("violatedSLAs") != null && ifSituation.get("violatedSLAs").size() > 0) {
+                            logger.trace("-- situation is problem with violations, selecting <VpnSlaPolicyDecidePriorityTask>");
+                            executor.subject.getTaskKey("VpnSlaPolicyDecidePriorityTask").copyTo(executor.selectedTask);
+                            var returnValue = new returnValueType(true);
+                        } else if (ifSituation.get("violatedSLAs") != null && ifSituation.get("violatedSLAs").size() == 0) {
+                            logger.trace("-- situation is problem without violations, selecting <VpnSlaPolicyDecideSlaTask>");
+                            executor.subject.getTaskKey("VpnSlaPolicyDecideSlaTask").copyTo(executor.selectedTask);
+                            var returnValue = new returnValueType(true);
+                        } else {
+                            logger.error("-- detected unknown decision for situation <" + ifSituation.get("problemID") + ">");
+                            rootLogger.error(executor.subject.id + " " + "-- detected unknown decision for situation <"
+                                    + ifSituation.get("problemID") + ">");
+                            var returnValue = new returnValueType(false);
+                        }
+
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".d-tsl");
+
+               .. container:: paragraph
+
+                  The actual task logic are then ``none``, ``solved``,
+                  ``sla``, and ``priority``.
+
+Logic: Decide None
+-------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+                        importClass(org.slf4j.LoggerFactory);
+
+                        importClass(java.util.ArrayList);
+
+                        importClass(org.apache.avro.generic.GenericData.Array);
+                        importClass(org.apache.avro.generic.GenericRecord);
+                        importClass(org.apache.avro.Schema);
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
+
+                        var ifSituation = executor.inFields["situation"];
+
+                        // create outfiled for decision
+                        var decision = executor.subject.getOutFieldSchemaHelper("decision").createNewInstance();
+                        decision.put("description", "None, everything is ok");
+                        decision.put("decision", "NONE");
+                        decision.put("customers", new ArrayList());
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        if (ifSituation.get("problemID") == "NONE") {
+                            logger.trace("-- no problem, everything ok");
+                            var returnValue = new returnValueType(true);
+                        } else {
+                            logger.trace("-- wrong problemID <" + problemID + "> for NONE task, we should not be here");
+                            rootLogger.error(executor.subject.id + " " + "-- wrong problemID <" + problemID
+                                    + "> for NONE task, we should not be here");
+                            var returnValue = new returnValueType(false);
+                        }
+
+                        executor.outFields["decision"] = decision;
+
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".d-non");
+
+Logic: Decide Solved
+---------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+                        importClass(org.slf4j.LoggerFactory);
+
+                        importClass(java.util.ArrayList);
+
+                        importClass(org.apache.avro.generic.GenericData.Array);
+                        importClass(org.apache.avro.generic.GenericRecord);
+                        importClass(org.apache.avro.Schema);
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
+
+                        var ifSituation = executor.inFields["situation"];
+
+                        var albumProblemMap = executor.getContextAlbum("albumProblemMap");
+
+                        // create outfiled for decision
+                        var decision = executor.subject.getOutFieldSchemaHelper("decision").createNewInstance();
+                        decision.put("description", "None, everything is ok");
+                        decision.put("decision", "REBUILD");
+                        decision.put("customers", new ArrayList());
+                        decision.put("problemID", ifSituation.get("problemID"));
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        if (albumProblemMap.get(ifSituation.get("problemID")).get("status") == "SOLVED") {
+                            logger.trace("-- problem solved");
+                            var returnValue = new returnValueType(true);
+                        } else {
+                            logger.trace("-- wrong problemID <" + problemID + "> for SOLVED task, we should not be here");
+                            rootLogger.error(executor.subject.id + " " + "-- wrong problemID <" + problemID
+                                    + "> for SOLVED task, we should not be here");
+                            var returnValue = new returnValueType(false);
+                        }
+
+                        executor.outFields["decision"] = decision;
+
+                        logger.info("vpnsla: sla solved, problem solved");
+
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".d-non");
+
+Logic: Decide SLA
+------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+                        importClass(org.slf4j.LoggerFactory);
+
+                        importClass(java.util.ArrayList);
+
+                        importClass(org.apache.avro.generic.GenericData.Array);
+                        importClass(org.apache.avro.generic.GenericRecord);
+                        importClass(org.apache.avro.Schema);
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
+
+                        var ifSituation = executor.inFields["situation"];
+
+                        var albumCustomerMap = executor.getContextAlbum("albumCustomerMap");
+                        var albumProblemMap = executor.getContextAlbum("albumProblemMap");
+
+                        // create outfiled for decision
+                        var decision = executor.subject.getOutFieldSchemaHelper("decision").createNewInstance();
+                        decision.put("description", "Impede given customers selected based on maximum SLA delta");
+                        decision.put("decision", "IMPEDE");
+                        decision.put("problemID", ifSituation.get("problemID"));
+                        decision.put("customers", new ArrayList());
+
+                        var problem = albumProblemMap.get(ifSituation.get("problemID"));
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        if (problem != null && ifSituation.get("violatedSLAs").size() == 0) {
+                            logger.trace("-- impede by maximum SLA");
+                            var customer = "";
+                            var customerSla = 0;
+                            for (var i = 0; i < problem.get("edgeUsedBy").size(); i++) {
+                                customerCtxt = albumCustomerMap.get(problem.get("edgeUsedBy").get(i).toString());
+                                if (customerSla == 0) {
+                                    customerSla = customerCtxt.get("dtSLA") - customerCtxt.get("dtYTD");
+                                }
+                                if ((customerCtxt.get("dtSLA") - customerCtxt.get("dtYTD")) >= customerSla) {
+                                    customer = customerCtxt.get("customerName");
+                                    customerSla = (customerCtxt.get("dtSLA") - customerCtxt.get("dtYTD"));
+                                }
+                            }
+                            decision.get("customers").add(customer);
+                            var returnValue = new returnValueType(true);
+                        } else {
+                            logger.trace("-- wrong problemID <" + ifSituation.get("problemID") + "> for SLA task, we should not be here");
+                            rootLogger.error(executor.subject.id + " " + "-- wrong problemID <" + ifSituation.get("problemID")
+                                    + "> for SLA task, we should not be here");
+                            var returnValue = new returnValueType(false);
+                        }
+
+                        // set impededLast to decision[customers]
+                        problem.get("impededLast").clear();
+                        problem.get("impededLast").addAll(decision.get("customers"));
+
+                        executor.outFields["decision"] = decision;
+                        logger.trace("-- decision: " + decision);
+
+                        logger.info("vpnsla: sla balance, impeding customers " + decision.get("customers"));
+
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".d-sla");
+
+Logic: Decide Priority
+----------------------
+
+         .. container:: sect2
+
+            .. container:: listingblock
+
+               .. container:: content
+
+                  .. code:: CodeRay
+
+                     /*
+                      * ============LICENSE_START=======================================================
+                      *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                      * ================================================================================
+                      * 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.
+                      *
+                      * SPDX-License-Identifier: Apache-2.0
+                      * ============LICENSE_END=========================================================
+                      */
+
+                     load("nashorn:mozilla_compat.js");
+                     importClass(org.slf4j.LoggerFactory);
+
+                     importClass(java.util.ArrayList);
+
+                     importClass(org.apache.avro.generic.GenericData.Array);
+                     importClass(org.apache.avro.generic.GenericRecord);
+                     importClass(org.apache.avro.Schema);
+
+                     var logger = executor.logger;
+                     logger.trace("start: " + executor.subject.id);
+                     logger.trace("-- infields: " + executor.inFields);
+
+                     var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
+
+                     var ifSituation = executor.inFields["situation"];
+
+                     var albumCustomerMap = executor.getContextAlbum("albumCustomerMap");
+                     var albumProblemMap = executor.getContextAlbum("albumProblemMap");
+
+                     // create outfiled for decision
+                     var decision = executor.subject.getOutFieldSchemaHelper("decision").createNewInstance();
+                     decision.put("description", "None, everything is ok");
+                     decision.put("decision", "IMPEDE");
+                     decision.put("problemID", ifSituation.get("problemID"));
+                     decision.put("customers", new ArrayList());
+
+                     var problem = albumProblemMap.get(ifSituation.get("problemID"));
+                     var returnValueType = Java.type("java.lang.Boolean");
+                     if (problem != null && ifSituation.get("violatedSLAs").size() > 0) {
+                         logger.trace("-- impede by priority");
+                         for (var i = 0; i < problem.get("edgeUsedBy").size(); i++) {
+                             customerCtxt = albumCustomerMap.get(problem.get("edgeUsedBy").get(i).toString());
+                             if (customerCtxt.get("priority") == false) {
+                                 decision.get("customers").add(customerCtxt.get("customerName"));
+                             }
+                         }
+                         var returnValue = new returnValueType(true);
+                     } else {
+                         logger.trace("-- wrong problemID <" + ifSituation.get("problemID") + "> for PRIORITY task, we should not be here");
+                         rootLogger.error(executor.subject.id + " " + "-- wrong problemID <" + ifSituation.get("problemID")
+                                 + "> for PRIORITY task, we should not be here");
+                         var returnValue = new returnValueType(false);
+                     }
+
+                     // set impededLast to decision[customers]
+                     problem.get("impededLast").clear();
+                     problem.get("impededLast").addAll(decision.get("customers"));
+
+                     executor.outFields["decision"] = decision;
+                     logger.trace("-- decision: " + decision);
+
+                     logger.info("vpnsla: priority, impeding customers " + decision.get("customers"));
+
+                     logger.trace("finished: " + executor.subject.id);
+                     logger.debug(".d-pri");
+
+Logic: Policy Act State
+------------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  This is the logic for the act state. It is simply
+                  selecting an action, and creating the repsonse event
+                  for the orchestrator (the output of the policy).
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        /*
+                         * ============LICENSE_START=======================================================
+                         *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                         * ================================================================================
+                         * 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.
+                         *
+                         * SPDX-License-Identifier: Apache-2.0
+                         * ============LICENSE_END=========================================================
+                         */
+
+                        load("nashorn:mozilla_compat.js");
+
+                        var logger = executor.logger;
+                        logger.trace("start: " + executor.subject.id);
+                        logger.trace("-- infields: " + executor.inFields);
+
+                        var ifDecision = executor.inFields["decision"];
+                        var ifMatchStart = executor.inFields["matchStart"];
+
+                        var albumCustomerMap = executor.getContextAlbum("albumCustomerMap");
+                        var albumProblemMap = executor.getContextAlbum("albumProblemMap");
+
+                        switch (ifDecision.get("decision").toString()) {
+                        case "NONE":
+                            executor.outFields["edgeName"] = "";
+                            executor.outFields["action"] = "";
+                            break;
+                        case "IMPEDE":
+                            for (var i = 0; i < ifDecision.get("customers").size(); i++) {
+                                customer = albumCustomerMap.get(ifDecision.get("customers").get(i).toString());
+                                executor.outFields["edgeName"] = customer.get("links").get(0);
+                                executor.outFields["action"] = "firewall";
+                            }
+                            break;
+                        case "REBUILD":
+                            // finally solved, remove problem
+                            albumProblemMap.remove(ifDecision.get("problemID"));
+                            executor.outFields["edgeName"] = "L10"; // this is ###static###
+                            executor.outFields["action"] = "rebuild"; // this is ###static###
+                            break;
+                        default:
+
+                        }
+
+                        var returnValueType = Java.type("java.lang.Boolean");
+                        var returnValue = new returnValueType(true);
+
+                        if (executor.outFields["action"] != "") {
+                            logger.info("vpnsla: action is to " + executor.outFields["action"] + " " + executor.outFields["edgeName"]);
+                        } else {
+                            logger.info("vpnsla: no action required");
+                        }
+
+                        logger.trace("-- outfields: " + executor.outFields);
+                        logger.trace("finished: " + executor.subject.id);
+                        logger.debug(".a");
+
+                        var now = new Date().getTime();
+                        logger.info("VPN SLA finished in " + (now - ifMatchStart) + " ms");
+
+CLI Spec
+--------
+
+         .. container:: sect1
+
+            .. rubric:: Complete Policy Definition
+               :name: complete_policy_definition
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The complete policy definition is realized using the
+                  APEX CLI Editor. The script below shows the actual
+                  policy specification. All logic and schemas are
+                  included (as macro file).
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        #-------------------------------------------------------------------------------
+                        # ============LICENSE_START=======================================================
+                        #  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                        # ================================================================================
+                        # 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.
+                        #
+                        # SPDX-License-Identifier: Apache-2.0
+                        # ============LICENSE_END=========================================================
+                        #-------------------------------------------------------------------------------
+
+                        # ============LICENSE_START=======================================================
+                        #  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                        # ================================================================================
+                        # 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.
+                        #
+                        # SPDX-License-Identifier: Apache-2.0
+                        # ============LICENSE_END=========================================================
+
+                        model create name=PCVS-VpnSla version=1.0.0 description="Policies-Controlled Video Streaming, VPN SLA Policy Model"
+
+
+
+                        schema create name=reportDecl version=1.0.0 description="Report of activities of a policy/task" flavour=Java schema=java.lang.String
+                        event create name=ReportOut version=1.0.0 description="Report of a policy (issued by a task)" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="APEX" target="CtxtManagement"
+                        event parameter create name=ReportOut version=1.0.0 parName=report schemaName=reportDecl schemaVersion=1.0.0
+
+                        schema create name=timestampDecl version=1.0.0 description="Timestamp" flavour=Java schema=java.lang.Long
+
+
+
+                        schema create name=ctxtEdgeNameDecl version=1.0.0 description="Topology Edges: edge (link) name" flavour=Java schema=java.lang.String
+                        schema create name=ctxtEdgeStartDecl version=1.0.0 description="Topology Edges: edge endpoint (start)" flavour=Java schema=java.lang.String
+                        schema create name=ctxtEdgeEndDecl version=1.0.0 description="Topology Edges: edge endpoint (end)" flavour=Java schema=java.lang.String
+                        schema create name=ctxtEdgeStatusDecl version=1.0.0 description="Topology Edges: edge status as up (true) or down (false)" flavour=Java schema=java.lang.Boolean
+
+                        schema create name=ctxtTopologyEdgesDecl version=1.0.0 description="Topology Edges Context Map" flavour=Avro schema=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/avro/topology-edges.avsc"
+                        LE
+                        album create name=albumTopoEdges scope=global writable=true schemaName=ctxtTopologyEdgesDecl
+
+
+                        task create name=EdgeContextTask version=1.0.0 description="This task adds event context to edge context"
+                        task inputfield create name=EdgeContextTask version=1.0.0 fieldName=edgeName schemaName=ctxtEdgeNameDecl schemaVersion=1.0.0
+                        task inputfield create name=EdgeContextTask version=1.0.0 fieldName=start schemaName=ctxtEdgeStartDecl schemaVersion=1.0.0
+                        task inputfield create name=EdgeContextTask version=1.0.0 fieldName=end schemaName=ctxtEdgeEndDecl schemaVersion=1.0.0
+                        task inputfield create name=EdgeContextTask version=1.0.0 fieldName=status schemaName=ctxtEdgeStatusDecl schemaVersion=1.0.0
+                        task outputfield create name=EdgeContextTask version=1.0.0 fieldName=report schemaName=reportDecl schemaVersion=1.0.0
+                        task contextref create name=EdgeContextTask albumName=albumTopoEdges
+                        task logic create name=EdgeContextTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/ctxt-edges.js"
+                        LE
+
+                        event create name=EdgeContextEventIn version=1.0.0 description="Event to add an Edge to engine Context" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="CtxtManagement" target="APEX"
+                        event parameter create name=EdgeContextEventIn version=1.0.0 parName=edgeName schemaName=ctxtEdgeNameDecl schemaVersion=1.0.0
+                        event parameter create name=EdgeContextEventIn version=1.0.0 parName=start schemaName=ctxtEdgeStartDecl schemaVersion=1.0.0
+                        event parameter create name=EdgeContextEventIn version=1.0.0 parName=end schemaName=ctxtEdgeEndDecl schemaVersion=1.0.0
+                        event parameter create name=EdgeContextEventIn version=1.0.0 parName=status schemaName=ctxtEdgeStatusDecl schemaVersion=1.0.0
+
+                        policy create name=EdgeContextPolicy version=1.0.0 description="Policy that adds an edge to context" template=FREEFORM firstState=EdgeContextState
+                        policy state create name=EdgeContextPolicy version=1.0.0 stateName=EdgeContextState triggerName=EdgeContextEventIn triggerVersion=1.0.0 defaultTaskName=EdgeContextTask defaultTaskVersion=1.0.0
+                        policy state output create name=EdgeContextPolicy version=1.0.0 stateName=EdgeContextState outputName=EdgeContextState_Output_Direct eventName=ReportOut eventVersion=1.0.0 nextState=NULL
+                        policy state taskref create name=EdgeContextPolicy version=1.0.0 stateName=EdgeContextState taskLocalName=doContext taskName=EdgeContextTask taskVersion=1.0.0 outputType=DIRECT outputName=EdgeContextState_Output_Direct
+
+
+
+                        schema create name=ctxtNodeNameDecl version=1.0.0 description="Topology Nodes: node name" flavour=Java schema=java.lang.String
+                        schema create name=ctxtNodeMininetNameDecl version=1.0.0 description="Topology Nodes: node name in Mininet" flavour=Java schema=java.lang.String
+
+                        schema create name=ctxtTopologyNodesDecl version=1.0.0 description="Topology Nodes Context Map" flavour=Avro schema=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/avro/topology-nodes.avsc"
+                        LE
+                        album create name=albumTopoNodes scope=global writable=true schemaName=ctxtTopologyNodesDecl
+
+                        task create name=NodeContextTask version=1.0.0 description="This task adds event context to node context"
+                        task inputfield create name=NodeContextTask version=1.0.0 fieldName=nodeName schemaName=ctxtNodeNameDecl schemaVersion=1.0.0
+                        task inputfield create name=NodeContextTask version=1.0.0 fieldName=mininetName schemaName=ctxtNodeMininetNameDecl schemaVersion=1.0.0
+                        task outputfield create name=NodeContextTask version=1.0.0 fieldName=report schemaName=reportDecl schemaVersion=1.0.0
+                        task contextref create name=NodeContextTask albumName=albumTopoNodes
+                        task logic create name=NodeContextTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/ctxt-nodes.js"
+                        LE
+
+                        event create name=NodeContextEventIn version=1.0.0 description="Event to add Node to engine Context" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="CtxtManagement" target="APEX"
+                        event parameter create name=NodeContextEventIn version=1.0.0 parName=nodeName schemaName=ctxtNodeNameDecl schemaVersion=1.0.0
+                        event parameter create name=NodeContextEventIn version=1.0.0 parName=mininetName schemaName=ctxtNodeMininetNameDecl schemaVersion=1.0.0
+
+                        policy create name=NodeContextPolicy version=1.0.0 description="Policy that adds an node to context" template=FREEFORM firstState=NodeContextState
+                        policy state create name=NodeContextPolicy version=1.0.0 stateName=NodeContextState triggerName=NodeContextEventIn triggerVersion=1.0.0 defaultTaskName=NodeContextTask defaultTaskVersion=1.0.0
+                        policy state output create name=NodeContextPolicy version=1.0.0 stateName=NodeContextState outputName=NodeContextState_Output_Direct eventName=ReportOut eventVersion=1.0.0 nextState=NULL
+                        policy state taskref create name=NodeContextPolicy version=1.0.0 stateName=NodeContextState taskLocalName=doContext taskName=NodeContextTask taskVersion=1.0.0 outputType=DIRECT outputName=NodeContextState_Output_Direct
+
+
+
+
+                        schema create name=ctxtCustomerNameDecl version=1.0.0 description="Customer Context: customer name" flavour=Java schema=java.lang.String
+                        schema create name=ctxtCustomerPriorityDecl version=1.0.0 description="Customer Context: priority flag" flavour=Java schema=java.lang.Boolean
+                        schema create name=ctxtCustomerSatisfactionDecl version=1.0.0 description="Customer Context: satisfaction in percent" flavour=Java schema=java.lang.Integer
+                        schema create name=ctxtCustomerDowntimeSLADecl version=1.0.0 description="Customer Context: contracted downtime as per SLA" flavour=Java schema=java.lang.Integer
+                        schema create name=ctxtCustomerDowntimeYTDDecl version=1.0.0 description="Customer Context: year-to-date downtime experienced" flavour=Java schema=java.lang.Integer
+                        schema create name=ctxtCustomerLinksDecl version=1.0.0 description="Customer Context: links a customer uses (for events/task)" flavour=Java schema=java.lang.String
+
+                        schema create name=ctxtCustomerMapDecl version=1.0.0 description="Map of customers with all known information" flavour=Avro schema=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/avro/customers.avsc"
+                        LE
+                        album create name=albumCustomerMap scope=global writable=true schemaName=ctxtCustomerMapDecl
+
+                        task create name=CustomerContextTask version=1.0.0 description="This task adds event context to customer context"
+                        task inputfield create name=CustomerContextTask version=1.0.0 fieldName=customerName schemaName=ctxtCustomerNameDecl schemaVersion=1.0.0
+                        task inputfield create name=CustomerContextTask version=1.0.0 fieldName=priority schemaName=ctxtCustomerPriorityDecl schemaVersion=1.0.0
+                        task inputfield create name=CustomerContextTask version=1.0.0 fieldName=satisfaction schemaName=ctxtCustomerSatisfactionDecl schemaVersion=1.0.0
+                        task inputfield create name=CustomerContextTask version=1.0.0 fieldName=dtSLA schemaName=ctxtCustomerDowntimeSLADecl schemaVersion=1.0.0
+                        task inputfield create name=CustomerContextTask version=1.0.0 fieldName=dtYTD schemaName=ctxtCustomerDowntimeYTDDecl schemaVersion=1.0.0
+                        task inputfield create name=CustomerContextTask version=1.0.0 fieldName=links schemaName=ctxtCustomerLinksDecl schemaVersion=1.0.0
+                        task outputfield create name=CustomerContextTask version=1.0.0 fieldName=report schemaName=reportDecl schemaVersion=1.0.0
+                        task contextref create name=CustomerContextTask albumName=albumCustomerMap
+                        task contextref create name=CustomerContextTask albumName=albumTopoEdges
+                        task logic create name=CustomerContextTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/ctxt-customer.js"
+                        LE
+
+                        event create name=CustomerContextEventIn version=1.0.0 description="Event to add Customers to engine Context" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="CtxtManagement" target="APEX"
+                        event parameter create name=CustomerContextEventIn version=1.0.0 parName=customerName schemaName=ctxtCustomerNameDecl schemaVersion=1.0.0
+                        event parameter create name=CustomerContextEventIn version=1.0.0 parName=priority schemaName=ctxtCustomerPriorityDecl schemaVersion=1.0.0
+                        event parameter create name=CustomerContextEventIn version=1.0.0 parName=satisfaction schemaName=ctxtCustomerSatisfactionDecl schemaVersion=1.0.0
+                        event parameter create name=CustomerContextEventIn version=1.0.0 parName=dtSLA schemaName=ctxtCustomerDowntimeSLADecl schemaVersion=1.0.0
+                        event parameter create name=CustomerContextEventIn version=1.0.0 parName=dtYTD schemaName=ctxtCustomerDowntimeYTDDecl schemaVersion=1.0.0
+                        event parameter create name=CustomerContextEventIn version=1.0.0 parName=links schemaName=ctxtCustomerLinksDecl schemaVersion=1.0.0
+
+                        policy create name=CustomerContextPolicy version=1.0.0 description="Policy that adds Customer information to engine context" template=FREEFORM firstState=CustomerContextState
+                        policy state create name=CustomerContextPolicy version=1.0.0 stateName=CustomerContextState triggerName=CustomerContextEventIn triggerVersion=1.0.0 defaultTaskName=CustomerContextTask defaultTaskVersion=1.0.0
+                        policy state output create name=CustomerContextPolicy version=1.0.0 stateName=CustomerContextState outputName=CustomerContextState_Output_Direct eventName=ReportOut eventVersion=1.0.0 nextState=NULL
+                        policy state taskref create name=CustomerContextPolicy version=1.0.0 stateName=CustomerContextState taskLocalName=doContext taskName=CustomerContextTask taskVersion=1.0.0 outputType=DIRECT outputName=CustomerContextState_Output_Direct
+
+
+
+
+                        schema create name=edgeNameDecl version=1.0.0 description="Edge name" flavour=Java schema=java.lang.String
+                        schema create name=edgeStatusDecl version=1.0.0 description="Statuf of the edge (UP, DOWN)" flavour=Avro schema=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/avro/link-status.avsc"
+                        LE
+                        schema create name=edgeChangedDecl version=1.0.0 description="Status Change (true:change, false:no change)" flavour=Java schema=java.lang.Boolean
+
+                        task create name=VpnSlaPolicyMatchTask version=1.0.0 description="Pre-process an edge event"
+                        task inputfield create name=VpnSlaPolicyMatchTask version=1.0.0 fieldName=edgeName schemaName=edgeNameDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyMatchTask version=1.0.0 fieldName=status schemaName=edgeStatusDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyMatchTask version=1.0.0 fieldName=edgeName schemaName=edgeNameDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyMatchTask version=1.0.0 fieldName=status schemaName=edgeStatusDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyMatchTask version=1.0.0 fieldName=hasChanged schemaName=edgeChangedDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyMatchTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task contextref create name=VpnSlaPolicyMatchTask albumName=albumTopoEdges
+                        task logic create name=VpnSlaPolicyMatchTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/task-match.js"
+                        LE
+
+
+
+
+                        schema create name=problemMapDecl version=1.0.0 description="Map of problems with all known Information" flavour=Avro schema=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/avro/problems.avsc"
+                        LE
+                        album create name=albumProblemMap scope=global writable=true schemaName=problemMapDecl
+
+                        schema create name=establishSituationDecl version=1.0.0 description="Establish: the situation that was established" flavour=Avro schema=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/avro/situation.avsc"
+                        LE
+
+                        task create name=VpnSlaPolicyEstablishTask version=1.0.0 description="Task taking a match event and establishing a situation"
+                        task inputfield create name=VpnSlaPolicyEstablishTask version=1.0.0 fieldName=edgeName schemaName=edgeNameDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyEstablishTask version=1.0.0 fieldName=status schemaName=edgeStatusDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyEstablishTask version=1.0.0 fieldName=hasChanged schemaName=edgeChangedDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyEstablishTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyEstablishTask version=1.0.0 fieldName=situation schemaName=establishSituationDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyEstablishTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task contextref create name=VpnSlaPolicyEstablishTask albumName=albumProblemMap
+                        task contextref create name=VpnSlaPolicyEstablishTask albumName=albumCustomerMap
+                        task logic create name=VpnSlaPolicyEstablishTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/task-establish.js"
+                        LE
+
+
+
+
+                        schema create name=decideDecisionDecl version=1.0.0 description="Decide: the taken decision" flavour=Avro schema=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/avro/decision.avsc"
+                        LE
+
+                        task create name=VpnSlaPolicyDecideNoneTask version=1.0.0 description="Decide task for a 'none' problem"
+                        task inputfield create name=VpnSlaPolicyDecideNoneTask version=1.0.0 fieldName=situation schemaName=establishSituationDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyDecideNoneTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyDecideNoneTask version=1.0.0 fieldName=decision schemaName=decideDecisionDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyDecideNoneTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task logic create name=VpnSlaPolicyDecideNoneTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/task-decide-none.js"
+                        LE
+
+
+                        task create name=VpnSlaPolicyDecideSlaTask version=1.0.0 description="Decide task solving the problem by balancing SLAs"
+                        task inputfield create name=VpnSlaPolicyDecideSlaTask version=1.0.0 fieldName=situation schemaName=establishSituationDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyDecideSlaTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyDecideSlaTask version=1.0.0 fieldName=decision schemaName=decideDecisionDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyDecideSlaTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task contextref create name=VpnSlaPolicyDecideSlaTask albumName=albumCustomerMap
+                        task contextref create name=VpnSlaPolicyDecideSlaTask albumName=albumProblemMap
+                        task logic create name=VpnSlaPolicyDecideSlaTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/task-decide-sla.js"
+                        LE
+
+
+                        task create name=VpnSlaPolicyDecidePriorityTask version=1.0.0 description="Decide task solving the problem by using customer priorities"
+                        task inputfield create name=VpnSlaPolicyDecidePriorityTask version=1.0.0 fieldName=situation schemaName=establishSituationDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyDecidePriorityTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyDecidePriorityTask version=1.0.0 fieldName=decision schemaName=decideDecisionDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyDecidePriorityTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task contextref create name=VpnSlaPolicyDecidePriorityTask albumName=albumCustomerMap
+                        task contextref create name=VpnSlaPolicyDecidePriorityTask albumName=albumProblemMap
+                        task logic create name=VpnSlaPolicyDecidePriorityTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/task-decide-priority.js"
+                        LE
+
+
+                        task create name=VpnSlaPolicyDecideSolvedTask version=1.0.0 description="Decide task solving the problem by using customer priorities"
+                        task inputfield create name=VpnSlaPolicyDecideSolvedTask version=1.0.0 fieldName=situation schemaName=establishSituationDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyDecideSolvedTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyDecideSolvedTask version=1.0.0 fieldName=decision schemaName=decideDecisionDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyDecideSolvedTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task contextref create name=VpnSlaPolicyDecideSolvedTask albumName=albumProblemMap
+                        task logic create name=VpnSlaPolicyDecideSolvedTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/task-decide-solved.js"
+                        LE
+
+
+
+
+                        schema create name=actionDecl version=1.0.0 description="An action for the actioning system" flavour=Java schema=java.lang.String
+
+                        task create name=VpnSlaPolicyActTask version=1.0.0 description="Task issueing an action for taken decision"
+                        task inputfield create name=VpnSlaPolicyActTask version=1.0.0 fieldName=decision schemaName=decideDecisionDecl schemaVersion=1.0.0
+                        task inputfield create name=VpnSlaPolicyActTask version=1.0.0 fieldName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyActTask version=1.0.0 fieldName=edgeName schemaName=edgeNameDecl schemaVersion=1.0.0
+                        task outputfield create name=VpnSlaPolicyActTask version=1.0.0 fieldName=action schemaName=actionDecl schemaVersion=1.0.0
+                        task contextref create name=VpnSlaPolicyActTask albumName=albumCustomerMap
+                        task contextref create name=VpnSlaPolicyActTask albumName=albumProblemMap
+                        task logic create name=VpnSlaPolicyActTask logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/task-act.js"
+                        LE
+
+
+
+
+
+
+
+                        event create name=VpnSlaTrigger version=1.0.0 description="Event triggering the VPN SLA policy" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="TriggerSys" target="VpnSlaMatch"
+                        event parameter create name=VpnSlaTrigger version=1.0.0 parName=edgeName schemaName=edgeNameDecl schemaVersion=1.0.0
+                        event parameter create name=VpnSlaTrigger version=1.0.0 parName=status schemaName=edgeStatusDecl schemaVersion=1.0.0
+
+                        event create name=VpnSlaMatchOut version=1.0.0 description="Event with matched trigger for the VPN SLA policy" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="VpnSlaMatch" target="VpnSlaEstablish"
+                        event parameter create name=VpnSlaMatchOut version=1.0.0 parName=edgeName schemaName=edgeNameDecl schemaVersion=1.0.0
+                        event parameter create name=VpnSlaMatchOut version=1.0.0 parName=status schemaName=edgeStatusDecl schemaVersion=1.0.0
+                        event parameter create name=VpnSlaMatchOut version=1.0.0 parName=hasChanged schemaName=edgeChangedDecl schemaVersion=1.0.0
+                        event parameter create name=VpnSlaMatchOut version=1.0.0 parName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+
+                        event create name=VpnSlaEstablishOut version=1.0.0 description="Event with situation for the SLA policy" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="SlaEstablish" target="SlaDecide"
+                        event parameter create name=VpnSlaEstablishOut version=1.0.0 parName=situation schemaName=establishSituationDecl schemaVersion=1.0.0
+                        event parameter create name=VpnSlaEstablishOut version=1.0.0 parName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+
+                        event create name=VpnSlaDecideOut version=1.0.0 description="Event with a decision for the SLA policy" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="SlaDecide" target="SlaAct"
+                        event parameter create name=VpnSlaDecideOut version=1.0.0 parName=decision schemaName=decideDecisionDecl schemaVersion=1.0.0
+                        event parameter create name=VpnSlaDecideOut version=1.0.0 parName=matchStart schemaName=timestampDecl schemaVersion=1.0.0
+
+                        event create name=VpnSlaActOut version=1.0.0 description="Event action" nameSpace=org.onap.policy.apex.examples.pcvs.vpnsla source="SlaAct" target="ActioningSystem"
+                        event parameter create name=VpnSlaActOut version=1.0.0 parName=edgeName schemaName=edgeNameDecl schemaVersion=1.0.0
+                        event parameter create name=VpnSlaActOut version=1.0.0 parName=action schemaName=actionDecl schemaVersion=1.0.0
+
+
+                        policy create name=VpnSlaPolicy version=1.0.0 description="Policy deciding customer treatment based on SLAs as MEDA policy" template=FREEFORM firstState=VpnSlaPolicyMatchState
+
+                        policy state create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyActState triggerName=VpnSlaDecideOut triggerVersion=1.0.0 defaultTaskName=VpnSlaPolicyActTask defaultTaskVersion=1.0.0
+                        policy state output create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyActState outputName=SlaPolicyAct_Output_Direct eventName=VpnSlaActOut eventVersion=1.0.0 nextState=NULL
+                        policy state taskref create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyActState taskLocalName=act taskName=VpnSlaPolicyActTask taskVersion=1.0.0 outputType=DIRECT outputName=SlaPolicyAct_Output_Direct
+
+                        policy state create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyDecideState triggerName=VpnSlaEstablishOut triggerVersion=1.0.0 defaultTaskName=VpnSlaPolicyDecideSlaTask defaultTaskVersion=1.0.0
+                        policy state contextref create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyDecideState albumName=albumProblemMap
+                        policy state selecttasklogic create name=VpnSlaPolicy stateName=VpnSlaPolicyDecideState logicFlavour=JAVASCRIPT logic=LS
+                        #MACROFILE:"src/main/resources/org/onap/policy/apex/examples/pcvs/vpnsla/logic/tsl-decide.js"
+                        LE
+                        policy state output create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyDecideState outputName=VpnSlaPolicyDecide_Output_Direct eventName=VpnSlaDecideOut eventVersion=1.0.0 nextState=VpnSlaPolicyActState
+                        policy state taskref create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyDecideState taskLocalName=decideNone taskName=VpnSlaPolicyDecideNoneTask taskVersion=1.0.0 outputType=DIRECT outputName=VpnSlaPolicyDecide_Output_Direct
+                        policy state taskref create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyDecideState taskLocalName=decideNone taskName=VpnSlaPolicyDecideSolvedTask taskVersion=1.0.0 outputType=DIRECT outputName=VpnSlaPolicyDecide_Output_Direct
+                        policy state taskref create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyDecideState taskLocalName=decideSla taskName=VpnSlaPolicyDecideSlaTask taskVersion=1.0.0 outputType=DIRECT outputName=VpnSlaPolicyDecide_Output_Direct
+                        policy state taskref create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyDecideState taskLocalName=decidePriority taskName=VpnSlaPolicyDecidePriorityTask taskVersion=1.0.0 outputType=DIRECT outputName=VpnSlaPolicyDecide_Output_Direct
+
+                        policy state create name=VpnSlaPolicy version=1.0.0 stateName=VpmSlaPolicyEstablishState triggerName=VpnSlaMatchOut triggerVersion=1.0.0 defaultTaskName=VpnSlaPolicyEstablishTask defaultTaskVersion=1.0.0
+                        policy state output create name=VpnSlaPolicy version=1.0.0 stateName=VpmSlaPolicyEstablishState outputName=VpnSlaPolicyEstablish_Output_Direct eventName=VpnSlaEstablishOut eventVersion=1.0.0 nextState=VpnSlaPolicyDecideState
+                        policy state taskref create name=VpnSlaPolicy version=1.0.0 stateName=VpmSlaPolicyEstablishState taskLocalName=establish taskName=VpnSlaPolicyEstablishTask taskVersion=1.0.0 outputType=DIRECT outputName=VpnSlaPolicyEstablish_Output_Direct
+
+                        policy state create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyMatchState triggerName=VpnSlaTrigger triggerVersion=1.0.0 defaultTaskName=VpnSlaPolicyMatchTask defaultTaskVersion=1.0.0
+                        policy state output create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyMatchState outputName=VpnSlaPolicyMatch_Output_Direct eventName=VpnSlaMatchOut eventVersion=1.0.0 nextState=VpmSlaPolicyEstablishState
+                        policy state taskref create name=VpnSlaPolicy version=1.0.0 stateName=VpnSlaPolicyMatchState taskLocalName=match taskName=VpnSlaPolicyMatchTask taskVersion=1.0.0 outputType=DIRECT outputName=VpnSlaPolicyMatch_Output_Direct
+
+
+
+                        validate
+                        quit
+
+Context Events Nodes
+--------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The following events create all nodes of the topology.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "A1",
+                            "mininetName": "nn"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "A2",
+                            "mininetName": "nn"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "B1",
+                            "mininetName": "nn"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "B2",
+                            "mininetName": "nn"
+                        }
+
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "A1CO",
+                            "mininetName": "s1"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "A2CO",
+                            "mininetName": "s2"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "B1CO",
+                            "mininetName": "s3"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "B2CO",
+                            "mininetName": "s4"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "BBL",
+                            "mininetName": "s5"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "NodeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_NodeContext",
+                            "nodeName": "BBR",
+                            "mininetName": "s6"
+                        }
+
+Context Events Edges
+--------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The following events create all edges of the topology.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L01",
+                            "start": "A1",
+                            "end": "A1CO",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L02",
+                            "start": "B1",
+                            "end": "B1CO",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L03",
+                            "start": "A2",
+                            "end": "A2CO",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L04",
+                            "start": "B2",
+                            "end": "B2CO",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L05",
+                            "start": "A1CO",
+                            "end": "BBL",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L06",
+                            "start": "B1CO",
+                            "end": "BBL",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L07",
+                            "start": "A2CO",
+                            "end": "BBR",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L08",
+                            "start": "B2CO",
+                            "end": "BBR",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L09",
+                            "start": "BBL",
+                            "end": "BBR",
+                            "status": true
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "EdgeContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_EdgeContext",
+                            "edgeName": "L10",
+                            "start": "BBR",
+                            "end": "BBL",
+                            "status": true
+                        }
+
+Context Events Customers
+------------------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The following events create all customers of the
+                  topology.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "CustomerContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_CustomerContext",
+                            "customerName": "A",
+                            "links": "L01 L05 L09 L10",
+                            "dtSLA": 180,
+                            "dtYTD": 10,
+                            "priority": false,
+                            "satisfaction": 80
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "CustomerContextEventIn",
+                            "version": "1.0.0",
+                            "source": "CtxtManagement",
+                            "target" : "VpnSlaPolicy_CustomerContext",
+                            "customerName": "B",
+                            "links": "L02 L07 L09 L10",
+                            "dtSLA": 180,
+                            "dtYTD": 120,
+                            "priority": true,
+                            "satisfaction": 99
+                        }
+
+Trigger Examples
+----------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The following events are examples for trigger events
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "VpnSlaTrigger",
+                            "version": "1.0.0",
+                            "source": "ExampleEvents",
+                            "target" : "VpnSlaPolicy",
+                            "edgeName": "L09",
+                            "status": "UP"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "VpnSlaTrigger",
+                            "version": "1.0.0",
+                            "source": "ExampleEvents",
+                            "target" : "VpnSlaPolicy",
+                            "edgeName": "L09",
+                            "status": "UP"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "VpnSlaTrigger",
+                            "version": "1.0.0",
+                            "source": "ExampleEvents",
+                            "target" : "VpnSlaPolicy",
+                            "edgeName": "L09",
+                            "status": "DOWN"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "VpnSlaTrigger",
+                            "version": "1.0.0",
+                            "source": "ExampleEvents",
+                            "target" : "VpnSlaPolicy",
+                            "edgeName": "L09",
+                            "status": "DOWN"
+                        }
+
+                        {
+                            "nameSpace": "org.onap.policy.apex.examples.pcvs.vpnsla",
+                            "name": "VpnSlaTrigger",
+                            "version": "1.0.0",
+                            "source": "ExampleEvents",
+                            "target" : "VpnSlaPolicy",
+                            "edgeName": "L09",
+                            "status": "UP"
+                        }
+
+Link Monitor
+------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The Link Monitor is a Python script. At startup, it
+                  sends the context events to APEX to initialize the
+                  topology and the customers. Then it takes events from
+                  Kafka and sends them to APEX.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        # ============LICENSE_START=======================================================
+                        #  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                        # ================================================================================
+                        # 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.
+                        #
+                        # SPDX-License-Identifier: Apache-2.0
+                        # ============LICENSE_END=========================================================
+
+                        import http.client
+                        import json
+                        import time
+                        from kafka import KafkaConsumer, KafkaProducer
+
+                        class StaticFlowPusher(object):
+
+                            def __init__(self, server):
+                                self.server = server
+
+                            def get(self, data):
+                                ret = self.rest_call({}, 'GET')
+                                return json.loads(ret[2])
+
+                            def set(self, data):
+                                ret = self.rest_call(data, 'POST')
+                                return ret[0] == 200
+
+                            def remove(self, objtype, data):
+                                ret = self.rest_call(data, 'DELETE')
+                                return ret[0] == 200
+
+                            def getControllerSummary(self, data):
+                                ret = self.rest_call_controller_summary({}, 'GET')
+                                return json.loads(ret[2])
+
+                            def getLinks(self, data):
+                                ret = self.rest_call_links({}, 'GET')
+                                return json.loads(ret[2].decode())
+
+                            def rest_call(self, data, action):
+                                path = '/wm/staticflowpusher/json'
+                                headers = {
+                                    'Content-type': 'application/json',
+                                    'Accept': 'application/json',
+                                    }
+                                body = json.dumps(data)
+                                conn = http.client.HTTPConnection(self.server, 8080)
+                                conn.request(action, path, body, headers)
+                                response = conn.getresponse()
+                                ret = (response.status, response.reason, response.read())
+                                print(ret)
+                                conn.close()
+                                return ret
+
+                            def rest_call_controller_summary(self, data, action):
+                                path = '/wm/core/controller/summary/json'
+                                headers = {
+                                    'Content-type': 'application/json',
+                                    'Accept': 'application/json',
+                                    }
+                                body = json.dumps(data)
+                                conn = http.client.HTTPConnection(self.server, 8080)
+                                conn.request(action, path, body, headers)
+                                response = conn.getresponse()
+                                ret = (response.status, response.reason, response.read())
+                                print(ret)
+                                conn.close()
+                                return ret
+
+                            def rest_call_links(self, data, action):
+                                path = '/wm/topology/links/json'
+                                headers = {
+                                    'Content-type': 'application/json',
+                                    'Accept': 'application/json',
+                                    }
+                                body = json.dumps(data)
+                                conn = http.client.HTTPConnection(self.server, 8080)
+                                conn.request(action, path, body, headers)
+                                response = conn.getresponse()
+                                ret = (response.status, response.reason, response.read())
+                                conn.close()
+                                return ret
+
+                        pusher = StaticFlowPusher('127.0.1.1')
+
+
+                        def parseLinks(links):
+                                #print("\n\n\n",links)
+                                result = []
+                                for link in links:
+                                        list = []
+                                        #print("\n\n\n",link)
+                                        #print("\nsrc-switch : s", link['src-switch'][len(link['src-switch'])-1])
+                                        #print("\ndst-switch : s", link['dst-switch'][len(link['dst-switch'])-1])
+                                        list.append("s")
+                                        list.append(link['src-switch'][len(link['src-switch'])-1])
+                                        list.append("-s")
+                                        list.append(link['dst-switch'][len(link['dst-switch'])-1])
+                                        result.append(''.join(list))
+                                #print(result, "\n")
+                                return result
+
+
+
+                        counter =0
+                        healthyList = []
+                        testableList = []
+                        healthyLinks = ""
+                        testableLinks = ""
+                        producer = KafkaProducer(bootstrap_servers='localhost:9092')
+                        while(True):
+                                time.sleep(30)
+                                switchLinks = pusher.getLinks({})
+                                if counter == 0:
+                                        healthyList = parseLinks(switchLinks)
+                                        #Build All Links
+                                        print("READING LINKS FROM MININET\n")
+                                        for l in healthyList:
+                                                link = ""
+                                                #print(l, "\n")
+                                                #Links between switches [s6-s7 is ignored so it matches VPN SCENARIO]
+                                                if(l == "s1-s5"):
+                                                        link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L05', 'start': 'A1CO','end': 'BBL'}"
+                                                        producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                if(l == "s5-s6"):
+                                                        link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L09', 'start': 'BBL','end': 'BBR'}"
+                                                        producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                if(l == "s2-s6"):
+                                                        link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L07', 'start': 'A2CO','end': 'BBR'}"
+                                                        producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                if(l == "s5-s7"):
+                                                        link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L10', 'start': 'BBR','end': 'BBL'}"
+                                                        producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                if(l == "s3-s5"):
+                                                        link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L06', 'start': 'B1CO','end': 'BBL'}"
+                                                        producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                if(l == "s4-s6"):
+                                                        link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L08', 'start': 'B2CO','end': 'BBR'}"
+                                                        producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                        #Links between switches and hosts [NoT SENT IN FROM FLOODLIGHT]
+                                        producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L01', 'start': 'A1','end': 'A1CO'}")
+                                        producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L02', 'start': 'B1','end': 'B1CO'}")
+                                        producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L03', 'start': 'A2','end': 'A2CO'}")
+                                        producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'EdgeContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_EdgeContext','status': true,'edgeName': 'L04', 'start': 'B2','end': 'B2CO'}")
+                                        print("LINKS HAVE BEEN SENT TO APEX\n")
+
+                                        #Build Customers
+                                        print("BUILDING CUSTOMERS\n")
+                                        producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'CustomerContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_CustomerContext','dtYTD': 10,'dtSLA': 180,'links': 'L01 L05 L09 L10','customerName': 'A', 'priority': true,'satisfaction': 80}")
+                                        producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'CustomerContextEventIn','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy_CustomerContext','dtYTD': 120,'dtSLA': 180,'links': 'L02 L07 L09 L10','customerName': 'B', 'priority': false,'satisfaction': 99}")
+                                        print("CUSTOMERS HAVE BEEN SENT TO APEX\n")
+                                        healthyLinks = switchLinks
+                                        myfile = open('LinkInfo.json', 'a')
+                                        myfile.write(str(healthyLinks))
+                                        myfile.write('\n')
+                                        myfile.close()
+                                        print("We start off with", len(healthyLinks), "healthy Links!\n")
+                                else:
+                                        testableList = parseLinks(switchLinks)
+                                        issueLink = "";
+                                        for h in healthyList:
+                                                issueLink = h
+                                                for t in testableList:
+                                                        if t == h:
+                                                                issueLink = ""
+                                                if issueLink != "":
+                                                        print("There is an issue with the links! ", issueLink, " \n")
+                                                        if(issueLink == "s1-s5"):
+                                                                link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'DOWN','edgeName': 'L05'}"
+                                                                producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                        if(issueLink == "s5-s6"):
+                                                                link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'DOWN','edgeName': 'L09'}"
+                                                                producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                        if(issueLink == "s2-s6"):
+                                                                link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'DOWN','edgeName': 'L07'}"
+                                                                producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                        if(issueLink == "s5-s7"):
+                                                                link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'DOWN','edgeName': 'L10'}"
+                                                                producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                        if(issueLink == "s3-s5"):
+                                                                link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'DOWN','edgeName': 'L06'}"
+                                                                producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                        if(issueLink == "s4-s6"):
+                                                                link = "{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'DOWN','edgeName': 'L08'}"
+                                                                producer.send("apex-in-0", bytes(link, encoding="ascii"))
+                                                        break
+                                        if issueLink == "":
+                                                print("All Links are working\n")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L01'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L02'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L03'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L04'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L05'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L06'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L07'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L08'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L09'}")
+                                                producer.send("apex-in-0", b"{'nameSpace': 'org.onap.policy.apex.examples.pcvs.vpnsla','name': 'VpnSlaTrigger','version': '1.0.0','source': 'LinkMonitor.py','target': 'VpnSlaPolicy','status': 'UP','edgeName': 'L10'}")
+
+                                        testableLinks = switchLinks
+                                        myfile = open('LinkInfo.json', 'a')
+                                        myfile.write(str(testableLinks))
+                                        myfile.write('\n')
+                                        myfile.close()
+                                counter += 1
+
+Mininet Topology
+----------------
+
+         .. container:: sect1
+
+            .. container:: sectionbody
+
+               .. container:: paragraph
+
+                  The topology is realized using Mininet. The following
+                  script is use to estalish the topology and to realize
+                  network configurations.
+
+               .. container:: listingblock
+
+                  .. container:: content
+
+                     .. code:: CodeRay
+
+                        # ============LICENSE_START=======================================================
+                        #  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+                        # ================================================================================
+                        # 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.
+                        #
+                        # SPDX-License-Identifier: Apache-2.0
+                        # ============LICENSE_END=========================================================
+
+                        #Add Mininet to PATH
+                        import sys
+                        sys.path.insert(0, "/~/mininet")
+
+                        #Kafka
+                        import httplib
+                        import json
+                        import time
+                        from kafka import KafkaConsumer, KafkaProducer
+
+                        #Mininet
+                        from mininet.clean import *
+                        from mininet.cli import *
+                        from mininet.link import *
+                        from mininet.log import *
+                        from mininet.net import *
+                        from mininet.node import *
+                        from mininet.nodelib import *
+                        from mininet.topo import *
+                        from mininet.topolib import *
+
+                        class StaticFlowPusher(object):
+                            def __init__(self, server):
+                                self.server = server
+
+                            def enableFirewall(self, data):
+                                path = "/wm/firewall/module/enable/json"
+                                headers = {'Content-Type': 'application/json','Accept': 'application/json',}
+                                body = json.dumps(data)
+                                conn = httplib.HTTPConnection(self.server, 8080)
+                                conn.request("PUT", path, "")
+                                response = conn.getresponse()
+                                ret = (response.status, response.reason, response.read())
+                                conn.close()
+                                return ret
+
+                            def addRule(self, data):
+                                path = '/wm/firewall/rules/json'
+                                headers = {'Content-Type': 'application/json','Accept': 'application/json',}
+                                body = json.dumps(data)
+                                conn = httplib.HTTPConnection(self.server, 8080)
+                                conn.request('POST', path, body, headers)
+                                response = conn.getresponse()
+                                ret = (response.status, response.reason, response.read())
+                                conn.close()
+                                return ret
+
+                            def deleteRule(self, data):
+                                path = '/wm/firewall/rules/json'
+                                headers = {'Content-Type': 'application/json','Accept': 'application/json',}
+                                body = json.dumps(data)
+                                conn = httplib.HTTPConnection(self.server, 8080)
+                                conn.request('DELETE', path, body, headers)
+                                response = conn.getresponse()
+                                ret = (response.status, response.reason, response.read())
+                                conn.close()
+                                return ret
+
+                        #Build Pusher(REST/IN)
+                        pusher = StaticFlowPusher('127.0.0.1')
+
+                        net = Mininet(link=TCLink)
+
+                        #Create Customers
+                        customerA1 = net.addHost( 'A1' )
+                        customerA2 = net.addHost( 'A2' )
+                        customerB1 = net.addHost( 'B1' )
+                        customerB2 = net.addHost( 'B2' )
+
+                        #Create Switches
+                        switchA1CO = net.addSwitch( 's1' )
+                        switchA2CO = net.addSwitch( 's2' )
+                        switchB1CO = net.addSwitch( 's3' )
+                        switchB2CO = net.addSwitch( 's4' )
+                        switchBBL = net.addSwitch( 's5' )
+                        switchBBR = net.addSwitch( 's6' )
+                        # we need an extra switch here because Mininet does not allow two links between two switches
+                        switchEx = net.addSwitch( 's7' )
+
+                        #Create Links
+                        net.addLink( customerA1, switchA1CO )
+                        net.addLink( customerA2, switchA2CO )
+                        net.addLink( customerB1, switchB1CO )
+                        net.addLink( customerB2, switchB2CO )
+                        net.addLink( switchA1CO, switchBBL )
+                        net.addLink( switchB1CO, switchBBL )
+                        net.addLink( switchA2CO, switchBBR )
+                        net.addLink( switchB2CO, switchBBR )
+                        net.addLink( switchBBL, switchBBR)
+                        net.addLink( switchBBR, switchEx, bw=1.2 )
+                        net.addLink( switchEx, switchBBL )
+
+                        #Create Controller
+                        floodlightController = net.addController(name='c0' , controller=RemoteController , ip='127.0.0.1', port=6653)
+
+                        net.start()
+
+                        if pusher.enableFirewall({})[0] == 200:
+                            print("Firewall enabled!")
+
+                        #print(pusher.addRule({"switchid": "00:00:00:00:00:00:00:01"})[2])
+                        s1id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:01"})[2])['rule-id']
+                        s2id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:02"})[2])['rule-id']
+                        s3id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:03"})[2])['rule-id']
+                        s4id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:04"})[2])['rule-id']
+                        s5id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:05"})[2])['rule-id']
+                        s6id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:06"})[2])['rule-id']
+                        s7id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:07"})[2])['rule-id']
+
+
+                        result = 100
+                        while result!=0:
+                            result = net.pingAll(None)
+                        print("Network Simulation Complete")
+
+                        #Assume control and when finished "exit"
+                        cli = CLI( net )
+
+                        consumer = KafkaConsumer(bootstrap_servers='localhost:9092',auto_offset_reset='latest')
+                        consumer.subscribe(['apex-out'])
+                        print("Starting Message Loop")
+                        for message in consumer:
+                            myOutput = json.loads(message.value.decode())
+                            action = ""
+                            try:
+                                print("Checking Message")
+                                #print("SWITCHES= ",net.switches)
+                                #print("LINKS= ",net.links)
+                                #print("VALUES= ",net.values)
+                                if myOutput['edgeName'] != '':
+                                    print("Message Received: ",myOutput['edgeName'])
+                                    pusher.deleteRule({"ruleid": s1id})
+                                    pusher.deleteRule({"ruleid": s2id})
+                                    pusher.deleteRule({"ruleid": s3id})
+                                    pusher.deleteRule({"ruleid": s4id})
+                                    pusher.deleteRule({"ruleid": s5id})
+                                    pusher.deleteRule({"ruleid": s6id})
+                                    pusher.deleteRule({"ruleid": s7id})
+                                    s1id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:01"})[2])['rule-id']
+                                    s2id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:02"})[2])['rule-id']
+                                    s3id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:03"})[2])['rule-id']
+                                    s4id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:04"})[2])['rule-id']
+                                    s5id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:05"})[2])['rule-id']
+                                    s6id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:06"})[2])['rule-id']
+                                    s7id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:07"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L01":
+                                        action = "link s1 s5 down"
+                                        #net.configLinkStatus('s1', 's5', "down")
+                                        pusher.deleteRule({"ruleid": s1id})
+                                        s1id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:01", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L02":
+                                        action = "link s3 s5 down"
+                                        #net.configLinkStatus('s3', 's5', "down")
+                                        pusher.deleteRule({"ruleid": s3id})
+                                        s3id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:03", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L03":
+                                        action = "link s2 s6 down"
+                                        #net.configLinkStatus('s2', 's6', "down")
+                                        pusher.deleteRule({"ruleid": s1id})
+                                        s1id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:01", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L04":
+                                        action = "link s4 s6 down"
+                                        #net.configLinkStatus('s4', 's6', "down")
+                                        pusher.deleteRule({"ruleid": s3id})
+                                        s3id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:03", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L05":
+                                        action = "link s1 s5 down"
+                                        #net.configLinkStatus('s1', 's5', "down")
+                                        pusher.deleteRule({"ruleid": s1id})
+                                        s1id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:01", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L06":
+                                        action = "link s3 s5 down"
+                                        #net.configLinkStatus('s3', 's5', "down")
+                                        pusher.deleteRule({"ruleid": s3id})
+                                        s3id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:03", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L07":
+                                        action = "link s2 s6 down"
+                                        #net.configLinkStatus('s2', 's6', "down")
+                                        pusher.deleteRule({"ruleid": s2id})
+                                        s2id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:02", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L08":
+                                        action = "link s4 s6 down"
+                                        #net.configLinkStatus('s4', 's6', "down")
+                                        pusher.deleteRule({"ruleid": s4id})
+                                        s4id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:04", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L09":
+                                        action = "link s5 s6 down"
+                                        #net.configLinkStatus('s5', 's6', "down")
+                                        pusher.deleteRule({"ruleid": s7id})
+                                        s7id = json.loads(pusher.addRule({"switchid": "00:00:00:00:00:00:00:07", "action": "DENY"})[2])['rule-id']
+                                    if myOutput['edgeName'] == "L10":
+                                        print("L10")
+                                    #print(action)
+                                #print("3")
+                            except KeyError:
+                                print(myOutput)
+                        print("HA")
+                        net.stop()
+
+   .. container::
+      :name: footer-text
+
+      2.3.0-SNAPSHOT
+      Last updated 2020-04-03 16:04:24 IST
+
+
+.. |ONAP| image:: ../../../images/logos.png
+   :class: builtBy
+   :target: http://www.onap.org/
+
+.. |VPN SLA Architecture| image:: images/pcvs/vpnsla-arch.png
+
+