.. 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 `__ 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 `__ or `Full Client `__ 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 "); executor.outFields["hasChanged"] = true; } else { logger.trace("-- link <" + ifEdgeName + "> status not changed "); 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 "); 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 "); 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 "); 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 "); 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