2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Licensed under the Apache License, Version 2.0 (the "License");
 
   6  * you may not use this file except in compliance with the License.
 
   7  * You may obtain a copy of the License at
 
   9  *      http://www.apache.org/licenses/LICENSE-2.0
 
  11  * Unless required by applicable law or agreed to in writing, software
 
  12  * distributed under the License is distributed on an "AS IS" BASIS,
 
  13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  14  * See the License for the specific language governing permissions and
 
  15  * limitations under the License.
 
  16  * ============LICENSE_END=========================================================
 
  18 package org.onap.ccsdk.sli.core.slipluginutils;
 
  20 import com.google.common.collect.ImmutableSet;
 
  21 import com.google.gson.JsonArray;
 
  22 import com.google.gson.JsonElement;
 
  23 import com.google.gson.JsonObject;
 
  24 import com.google.gson.JsonParser;
 
  25 import org.apache.commons.lang3.StringUtils;
 
  26 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
 
  27 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 
  28 import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
 
  29 import org.onap.ccsdk.sli.core.slipluginutils.slitopologyutils.JsonParserHelper;
 
  30 import org.onap.ccsdk.sli.core.slipluginutils.slitopologyutils.graph.DijkstraGraphSearch;
 
  31 import org.onap.ccsdk.sli.core.slipluginutils.slitopologyutils.graph.Graph;
 
  32 import org.onap.ccsdk.sli.core.slipluginutils.slitopologyutils.graph.Path;
 
  33 import org.onap.ccsdk.sli.core.slipluginutils.slitopologyutils.topology.*;
 
  34 import org.onap.ccsdk.sli.core.slipluginutils.slitopologyutils.topology.LogicalLink;
 
  35 import org.slf4j.Logger;
 
  36 import org.slf4j.LoggerFactory;
 
  38 import java.util.ArrayList;
 
  39 import java.util.List;
 
  42 public class SliTopologyUtils implements SvcLogicJavaPlugin {
 
  43     private static final Logger LOG = LoggerFactory.getLogger(SliTopologyUtils.class);
 
  44     public static final String SUCCESS_CONSTANT = "success";
 
  45     public static final String FAILURE_CONSTANT = "failure";
 
  46     public static final String NOT_FOUND_CONSTANT = "not-found";
 
  49     public SliTopologyUtils(){};
 
  51      * Provides simple path computation functionality to Directed Graphs.
 
  53      * @param parameters HashMap<String,String> of parameters passed by the DG to this function
 
  55      *  <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
 
  57      *          <tr><td>pnfs-pfx</td><td>Mandatory</td><td>Prefix in context memory to get the pnf attributes from.</td></tr>
 
  58      *          <tr><td>links-pfx</td><td>Mandatory</td><td>Prefix in context memory to get the link attributes from.</td></tr>
 
  59      *          <tr><td>src-node</td><td>Mandatory</td><td>Source pnf name.</td></tr>
 
  60      *          <tr><td>dst-node</td><td>Mandatory</td><td>Destination pnf name.</td></tr>
 
  61      *          <tr><td>response-pfx</td><td>Mandatory</td><td>Prefix in context memory to populate the resulting attributes in.</td></tr>
 
  62      *          <tr><td>output-end-to-end-path</td><td>Optional</td><td>true or false to output end to end full path. If not included, only output cross domain path</td></tr>
 
  65      * @param ctx Reference to context memory
 
  66      * @throws SvcLogicException
 
  68     public static String computePath(Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
 
  70             LOG.debug( "ENTERING Execute Node \"computePath\"" );
 
  72             // Validate, Log, & read parameters
 
  73             checkParameters(parameters, new String[]{ "pnfs-pfx", "links-pfx",
 
  74                     "src-node", "dst-node", "response-pfx"}, LOG);
 
  76             boolean outputFullPath = false;
 
  77             String outputEndToEnd = parameters.get("output-end-to-end-path");
 
  79             if (outputEndToEnd != null && outputEndToEnd.equals("true")){
 
  80                 outputFullPath = true;
 
  81                 LOG.debug( "OutputEndToEndPath enabled");
 
  84             String pnfsStr = ctx.toJsonString(parameters.get("pnfs-pfx"));
 
  85             String lkStr = ctx.toJsonString(parameters.get("links-pfx"));
 
  87             if (pnfsStr.isEmpty()){
 
  88                 LOG.warn("Pnf Array attributes are empty");
 
  89                 throw new Exception( "Pnf Array attributes are empty");
 
  93                 LOG.warn("Logical-links Array attributes are empty");
 
  94                 throw new Exception( "Logical-links Array attributes are empty");
 
  97             LOG.debug("Pnf Json String is: {}", pnfsStr);
 
  99             String srcNodeStr = parameters.get("src-node");
 
 100             String dstNodeStr = parameters.get("dst-node");
 
 102             if( srcNodeStr.isEmpty() || dstNodeStr.isEmpty()){
 
 103                 LOG.warn("Src or Dst node is empty");
 
 104                 throw new Exception("Src or Dst node is empty");
 
 107             JsonParser jp = new JsonParser();
 
 109             JsonArray pnfArr = ((JsonObject) jp.parse(pnfsStr)).getAsJsonArray("pnf");
 
 110             JsonArray lkArr = ((JsonObject) jp.parse(lkStr)).getAsJsonArray("logical-link");
 
 111             LOG.debug("Creating graph with {} pnf(s) and {} link(s)", pnfArr.size(), lkArr.size());
 
 112             Graph<Pnf, LogicalLink> graph = buildGraph(pnfArr, lkArr);
 
 114             Pnf src = new Pnf(srcNodeStr);
 
 115             Pnf dst = new Pnf(dstNodeStr);
 
 117             if (!graph.getVertexes().contains(src) || !graph.getVertexes().contains(dst)){
 
 118                 LOG.warn("Src or Dst node doesn't exist");
 
 119                 throw new Exception("Src or Dst node doesn't exist");
 
 122             DijkstraGraphSearch.Result result =
 
 123                         new DijkstraGraphSearch<Pnf, LogicalLink>().search(graph, src, dst,null, -1);
 
 124             LOG.debug("Path Computing results: {}", result.paths().toString());
 
 126             if (result.paths().size() > 0){
 
 127                 JsonObject root = new JsonObject();
 
 128                 JsonArray solnList = new JsonArray();
 
 130                 Path<Pnf, LogicalLink> path = (Path<Pnf, LogicalLink>) result.paths().iterator().next();
 
 131                 for (LogicalLink logicalLink : path.edges()) {
 
 132                     if ( ((OtnLink) logicalLink.underlayLink()).isInnerDomain() && !outputFullPath ){
 
 133                         //Ignore inner domain links
 
 135                         JsonObject curLink = new JsonObject();
 
 136                         String srcNode = logicalLink.src().toString();
 
 137                         String dstNode = logicalLink.dst().toString();
 
 138                         String srcPInterface = ((OtnLink) logicalLink.underlayLink()).src().pInterfaceName().getName();
 
 139                         String dstPInterface = ((OtnLink) logicalLink.underlayLink()).dst().pInterfaceName().getName();
 
 140                         String linkName = ((OtnLink) logicalLink.underlayLink()).linkName();
 
 141                         curLink.addProperty("src_node", srcNode);
 
 142                         curLink.addProperty("dst_node", dstNode);
 
 143                         curLink.addProperty("src_pinterface", srcPInterface);
 
 144                         curLink.addProperty("dst_pinterface", dstPInterface);
 
 145                         curLink.addProperty("original_link", linkName);
 
 147                         solnList.add(curLink);
 
 150                 root.add("solutions", solnList);
 
 151                 //Write result back to context memory;
 
 152                 String pp = parameters.get("response-pfx").isEmpty() ? "" : parameters.get("response-pfx") + ".";
 
 153                 Map<String, String> mm = null;
 
 154                 mm = JsonParserHelper.convertToProperties(root.toString());
 
 156                     for (Map.Entry<String, String> entry : mm.entrySet()) {
 
 157                         ctx.setAttribute(pp + entry.getKey(), entry.getValue());
 
 160                 LOG.debug("SliTopologyUtils: path computation succeeds in finding the shortest path;" +
 
 161                         " result has been written back into context memory.");
 
 162                 return SUCCESS_CONSTANT;
 
 164                 LOG.debug("SliTopologyUtils: no valid path found.");
 
 165                 return NOT_FOUND_CONSTANT;
 
 168         } catch( Exception e ) {
 
 169             throw new SvcLogicException( "An error occurred in the computePath Execute node", e );
 
 171             LOG.debug( "EXITING Execute Node \"computePath\"" );
 
 175     private static Graph<Pnf, LogicalLink> buildGraph(JsonArray pnfs, JsonArray llks) {
 
 176         ImmutableSet.Builder pnfSetBlder = ImmutableSet.builder();
 
 177         ImmutableSet.Builder lkSetBlder = ImmutableSet.builder();
 
 179         //Create Immutable set of Pnf;
 
 180         for (int i = 0,e = pnfs.size(); i < e; i++){
 
 181             JsonElement pnfName = ((JsonObject) pnfs.get(i)).get("pnf-name");
 
 183             if (pnfName != null){
 
 184                 String pnfNameStr = pnfName.getAsString();
 
 186                 if (pnfNameStr != null && !pnfNameStr.isEmpty()){
 
 187                     pnfSetBlder.add(new Pnf(pnfNameStr));
 
 191                 LOG.debug("SliTopologyUtils: invalid pnf: {}", ((JsonObject) pnfs.get(i)).toString());
 
 195         //Create Immutable set of Logical-Link
 
 196         for (int i = 0,e = llks.size(); i < e; i++){
 
 197             JsonObject lkRoot = ((JsonObject) llks.get(i));
 
 198             JsonElement relationList = lkRoot.get("relationship-list");
 
 200             if (relationList != null) {
 
 201                 JsonElement relationListArray = ((JsonObject) relationList).get("relationship");
 
 203                 if (relationListArray != null){
 
 204                     List<String> pnfNameStrList = new ArrayList<>();
 
 205                     List<String> pInterfaceStrList= new ArrayList<>();
 
 207                     for (int j = 0,k = ((JsonArray) relationListArray).size(); j < k; j++){
 
 208                         JsonObject relation = ((JsonArray) relationListArray).get(j).getAsJsonObject();
 
 209                         JsonElement relatedTo = relation.getAsJsonPrimitive("related-to");
 
 211                         if (relatedTo != null && relatedTo.getAsString().equals("p-interface")){
 
 212                             JsonArray data = relation.getAsJsonArray("relationship-data");
 
 213                             for (int m = 0, n = data.size(); m < n; m++){
 
 214                                 JsonObject dataKeyValue = data.get(m).getAsJsonObject();
 
 216                                 if (dataKeyValue.get("relationship-key").getAsString().equals("pnf.pnf-name")){
 
 217                                     pnfNameStrList.add(dataKeyValue.get("relationship-value").getAsString());
 
 218                                 } else if (dataKeyValue.get("relationship-key").getAsString()
 
 219                                         .equals("p-interface.interface-name")){
 
 220                                     pInterfaceStrList.add(dataKeyValue.get("relationship-value").getAsString());
 
 226                     if (pnfNameStrList.size() == 2 && pnfNameStrList.size() == 2){
 
 227                         String pnf1NameStr = pnfNameStrList.get(0);
 
 228                         String pnf2NameStr = pnfNameStrList.get(1);
 
 229                         String pI1NameStr = pInterfaceStrList.get(0);
 
 230                         String pI2NameStr = pInterfaceStrList.get(1);
 
 231                         Pnf pnf1 = new Pnf(pnf1NameStr);
 
 232                         Pnf pnf2 = new Pnf(pnf2NameStr);
 
 233                         PInterfaceName pI1Name = PInterfaceName.of(pI1NameStr);
 
 234                         PInterfaceName pI2Name = PInterfaceName.of(pI2NameStr);
 
 235                         PInterface pI1 = new PInterface(pnf1NameStr, pI1Name);
 
 236                         PInterface pI2 = new PInterface(pnf1NameStr, pI2Name);
 
 237                         String linkName_f = pI1Name.getNetworkId() + "-linkId-"
 
 238                                                 + pI1Name.getPnfId() + "-"
 
 239                                                 + pI1Name.getLtpId();
 
 240                         String linkName_b = pI2Name.getNetworkId()
 
 241                                 + "-linkId-" + pI2Name.getPnfId()
 
 242                                 + "-" + pI2Name.getLtpId();
 
 243                         OtnLink link_f = new OtnLink(linkName_f, pI1, pI2);
 
 244                         OtnLink link_b = new OtnLink(linkName_b, pI2, pI1);
 
 245                         lkSetBlder.add(new LogicalLink(pnf1, pnf2, link_f));
 
 246                         lkSetBlder.add(new LogicalLink(pnf2, pnf1, link_b));
 
 251         return new Graph<Pnf, LogicalLink>(pnfSetBlder.build(), lkSetBlder.build());
 
 255      * Throws an exception and writes an error to the log file if a required
 
 256      * parameters is not found in the parametersMap.
 
 258      * Use at the beginning of functions that can be called by Directed Graphs
 
 259      * and can take parameters to verify that all parameters have been provided
 
 260      * by the Directed Graph.
 
 261      * @param parametersMap parameters Map passed to this node
 
 262      * @param requiredParams Array of parameters required by the calling function
 
 263      * @param log Reference to Logger to log to
 
 264      * @throws SvcLogicException if a String in the requiredParams array is
 
 265      * not a key in parametersMap.
 
 268     public static final void checkParameters(Map<String, String> parametersMap, String[] requiredParams, Logger log) throws SvcLogicException {
 
 269         if( requiredParams == null || requiredParams.length < 1){
 
 270             log.debug("required parameters was empty, exiting early.");
 
 273         if (parametersMap == null || parametersMap.keySet().isEmpty()){
 
 274             String errorMessage = "This method requires the parameters [" +   StringUtils.join(requiredParams,",") + "], but no parameters were passed in.";
 
 275             log.error(errorMessage);
 
 276             throw new SvcLogicException(errorMessage);
 
 279         for (String param : requiredParams) {
 
 280             if (!parametersMap.containsKey(param)) {
 
 281                 String errorMessage = "Required parameter \"" + param + "\" was not found in parameter list.";
 
 282                 log.error(errorMessage);
 
 283                 log.error("Total list of required parameters is [" + StringUtils.join(requiredParams, ",") + "].");
 
 284                 throw new SvcLogicException(errorMessage);