diff options
Diffstat (limited to 'docs/apex/APEX-PCVS-Example.rst')
-rw-r--r-- | docs/apex/APEX-PCVS-Example.rst | 2954 |
1 files changed, 2954 insertions, 0 deletions
diff --git a/docs/apex/APEX-PCVS-Example.rst b/docs/apex/APEX-PCVS-Example.rst new file mode 100644 index 00000000..fc420303 --- /dev/null +++ b/docs/apex/APEX-PCVS-Example.rst @@ -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 + + |