5760bdfd4c5f969a8491aec2dc4d1b238ace4802
[ccsdk/sli.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : CCSDK
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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=========================================================
17  */
18 package org.onap.ccsdk.sli.core.slipluginutils;
19
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;
37
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Map;
41
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";
47
48
49     public SliTopologyUtils(){};
50     /**
51      * Provides simple path computation functionality to Directed Graphs.
52      * <p>
53      * @param parameters HashMap<String,String> of parameters passed by the DG to this function
54      * <table border="1">
55      *  <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
56      *  <tbody>
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>
63      *  </tbody>
64      * </table>
65      * @param ctx Reference to context memory
66      * @throws SvcLogicException
67      */
68     public static String computePath(Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
69         try{
70             LOG.debug( "ENTERING Execute Node \"computePath\"" );
71
72             // Validate, Log, & read parameters
73             checkParameters(parameters, new String[]{ "pnfs-pfx", "links-pfx",
74                     "src-node", "dst-node", "response-pfx"}, LOG);
75
76             boolean outputFullPath = false;
77             String outputEndToEnd = parameters.get("output-end-to-end-path");
78
79             if (outputEndToEnd != null && outputEndToEnd.equals("true")){
80                 outputFullPath = true;
81                 LOG.debug( "OutputEndToEndPath enabled");
82             }
83
84             String pnfsStr = ctx.toJsonString(parameters.get("pnfs-pfx"));
85             String lkStr = ctx.toJsonString(parameters.get("links-pfx"));
86
87             if (pnfsStr.isEmpty()){
88                 LOG.warn("Pnf Array attributes are empty");
89                 throw new Exception( "Pnf Array attributes are empty");
90             }
91
92             if (lkStr.isEmpty()){
93                 LOG.warn("Logical-links Array attributes are empty");
94                 throw new Exception( "Logical-links Array attributes are empty");
95             }
96
97             LOG.debug("Pnf Json String is: {}", pnfsStr);
98
99             String srcNodeStr = parameters.get("src-node");
100             String dstNodeStr = parameters.get("dst-node");
101
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");
105             }
106
107             JsonParser jp = new JsonParser();
108
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);
113
114             Pnf src = new Pnf(srcNodeStr);
115             Pnf dst = new Pnf(dstNodeStr);
116
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");
120             }
121
122             DijkstraGraphSearch.Result result =
123                         new DijkstraGraphSearch<Pnf, LogicalLink>().search(graph, src, dst,null, -1);
124             LOG.debug("Path Computing results: {}", result.paths().toString());
125
126             if (result.paths().size() > 0){
127                 JsonObject root = new JsonObject();
128                 JsonArray solnList = new JsonArray();
129
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
134                     } else {
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);
146
147                         solnList.add(curLink);
148                     }
149                 }
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());
155                 if (mm != null) {
156                     for (Map.Entry<String, String> entry : mm.entrySet()) {
157                         ctx.setAttribute(pp + entry.getKey(), entry.getValue());
158                     }
159                 }
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;
163             } else {
164                 LOG.debug("SliTopologyUtils: no valid path found.");
165                 return NOT_FOUND_CONSTANT;
166             }
167
168         } catch( Exception e ) {
169             throw new SvcLogicException( "An error occurred in the computePath Execute node", e );
170         } finally {
171             LOG.debug( "EXITING Execute Node \"computePath\"" );
172         }
173     }
174
175     private static Graph<Pnf, LogicalLink> buildGraph(JsonArray pnfs, JsonArray llks) {
176         ImmutableSet.Builder pnfSetBlder = ImmutableSet.builder();
177         ImmutableSet.Builder lkSetBlder = ImmutableSet.builder();
178
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");
182
183             if (pnfName != null){
184                 String pnfNameStr = pnfName.getAsString();
185
186                 if (pnfNameStr != null && !pnfNameStr.isEmpty()){
187                     pnfSetBlder.add(new Pnf(pnfNameStr));
188                 }
189
190             } else {
191                 LOG.debug("SliTopologyUtils: invalid pnf: {}", ((JsonObject) pnfs.get(i)).toString());
192             }
193         }
194
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");
199
200             if (relationList != null) {
201                 JsonElement relationListArray = ((JsonObject) relationList).get("relationship");
202
203                 if (relationListArray != null){
204                     List<String> pnfNameStrList = new ArrayList<>();
205                     List<String> pInterfaceStrList= new ArrayList<>();
206
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");
210
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();
215
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());
221                                 }
222                             }
223                         }
224                     }
225
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));
247                     }
248                 }
249             }
250         }
251         return new Graph<Pnf, LogicalLink>(pnfSetBlder.build(), lkSetBlder.build());
252     }
253
254     /**
255      * Throws an exception and writes an error to the log file if a required
256      * parameters is not found in the parametersMap.
257      * <p>
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.
266      * @since 1.0
267      */
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.");
271             return;
272         }
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);
277         }
278
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);
285             }
286         }
287     }
288 }