Merge dev/fluorine work across to master
[unimgr.git] / impl / src / main / java / org / opendaylight / unimgr / mef / nrp / impl / decomposer / DecompositionAction.java
index dc140accf7eaa876aab1e6dfe3b14eaedaf60c58..d8621adba90bcbbd7c8ede61131f1cffe82fa5bb 100644 (file)
@@ -8,6 +8,20 @@
 
 package org.opendaylight.unimgr.mef.nrp.impl.decomposer;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 import org.jgrapht.Graph;
 import org.jgrapht.GraphPath;
 import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
@@ -21,20 +35,21 @@ import org.opendaylight.unimgr.mef.nrp.api.FailureResult;
 import org.opendaylight.unimgr.mef.nrp.api.Subrequrest;
 import org.opendaylight.unimgr.mef.nrp.api.TapiConstants;
 import org.opendaylight.unimgr.mef.nrp.common.NrpDao;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.common.rev171113.OperationalState;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.common.rev171113.PortDirection;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.common.rev171113.Uuid;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.topology.rev171113.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.onf.params.xml.ns.yang.tapi.topology.rev171113.topology.context.Topology;
+import org.opendaylight.unimgr.mef.nrp.common.TapiUtils;
+import org.opendaylight.yang.gen.v1.urn.odl.unimgr.yang.unimgr.ext.rev170531.NodeAdiAugmentation;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev180307.OperationalState;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev180307.PortDirection;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev180307.ServiceInterfacePointRef;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev180307.Uuid;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev180307.connectivity.service.end.point.ServiceInterfacePoint;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev180307.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev180307.topology.context.Topology;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.*;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
+ * Decompose request into sub-requests {@link Subrequrest} for drivers using graph path computation.
  * @author bartosz.michalik@amartus.com
  */
 class DecompositionAction {
@@ -53,17 +68,31 @@ class DecompositionAction {
         this.broker = broker;
     }
 
+    Function<ServiceInterfacePoint, Uuid> toUuid = s -> s == null ? null : s.getServiceInterfacePointId();
+
     List<Subrequrest> decompose() throws FailureResult {
         Graph<Vertex, DefaultEdge> graph = prepareData();
 
+
+
+        Set<String> missingSips = endpoints.stream()
+                .filter(e -> sipToNep.get(toUuid.apply(e.getEndpoint().getServiceInterfacePoint())) == null)
+                .map(e -> toUuid.apply(e.getEndpoint().getServiceInterfacePoint()).getValue())
+                .collect(Collectors.toSet());
+        if (!missingSips.isEmpty()) {
+            throw new FailureResult("Some service interface points not found in the system: "
+                    + missingSips.stream().collect(Collectors.joining(",", "[", "]")));
+        }
+
         List<Vertex> vertices = endpoints.stream().map(e -> {
-            Vertex v = sipToNep.get(e.getEndpoint().getServiceInterfacePoint());
-            if((v.dir == PortDirection.OUTPUT && e.getEndpoint().getDirection() != PortDirection.OUTPUT) ||
-               (v.dir == PortDirection.INPUT && e.getEndpoint().getDirection() != PortDirection.INPUT)) {
-                throw new IllegalArgumentException("Port direction for " + e.getEndpoint().getLocalId() + " incompatible with NEP." +
-                        "CEP " + e.getEndpoint().getDirection() + "  NEP " + v.dir);
+            Vertex vertex = sipToNep.get(toUuid.apply(e.getEndpoint().getServiceInterfacePoint()));
+            if ((vertex.dir == PortDirection.OUTPUT && e.getEndpoint().getDirection() != PortDirection.OUTPUT)
+                    ||  (vertex.dir == PortDirection.INPUT && e.getEndpoint().getDirection() != PortDirection.INPUT)) {
+                throw new IllegalArgumentException("Port direction for "
+                        + e.getEndpoint().getLocalId() + " incompatible with NEP."
+                        + "CEP " + e.getEndpoint().getDirection() + "  NEP " + vertex.dir);
             }
-            return new Vertex(v, e.getEndpoint().getDirection());
+            return new Vertex(vertex, e.getEndpoint().getDirection());
         }).collect(Collectors.toList());
 
         assert vertices.size() > 1;
@@ -77,37 +106,51 @@ class DecompositionAction {
         inV.forEach(i ->
                 outV.stream().filter(o -> i != o).forEach(o -> {
                     GraphPath<Vertex, DefaultEdge> path = DijkstraShortestPath.findPathBetween(graph, i, o);
-                    if(path != null) {
+                    if (path != null) {
                         LOG.debug("Couldn't find path between {} and  {}", i, o);
                     }
                     paths.add(path);
                 })
         );
 
-        if(paths.stream().anyMatch(Objects::isNull)) {
+        if (paths.stream().anyMatch(Objects::isNull)) {
             LOG.info("At least single path between endpoints not found");
             return null;
         }
 
-        List<Subrequrest> result = paths.stream()
+        List<Subrequrest> result = toSublists(paths);
+        return result.isEmpty() ? null : result;
+    }
+
+    private List<Subrequrest> toSublists(Set<GraphPath<Vertex, DefaultEdge>> paths) {
+        return paths.stream()
                 .flatMap(gp -> gp.getVertexList().stream()).collect(Collectors.groupingBy(Vertex::getNodeUuid))
                 .entrySet().stream()
                 .map(e -> {
-                    Set<EndPoint> endpoints = e.getValue().stream().map(this::toEndPoint).collect(Collectors.toSet());
-                    return new Subrequrest(e.getKey(), new ArrayList<>(endpoints));
+                    Set<EndPoint> fromVertexes = e.getValue().stream()
+                            .map(this::toEndPoint).collect(Collectors.toSet());
+                    return new Subrequrest(
+                            e.getKey(),
+                            new ArrayList<>(fromVertexes),
+                            e.getValue().stream().findFirst().get().getActivationDriverId());
                 }).collect(Collectors.toList());
-        return result.isEmpty() ? null : result;
     }
 
-    private EndPoint toEndPoint(Vertex v) {
-        EndPoint ep = endpoints.stream().filter(e -> e.getEndpoint().getServiceInterfacePoint().equals(v.getSip())).findFirst()
+    private EndPoint toEndPoint(Vertex vertex) {
+        EndPoint ep = endpoints.stream()
+                .filter(e -> e.getEndpoint().getServiceInterfacePoint()
+                        .getServiceInterfacePointId().equals(vertex.getSip()))
+                .findFirst()
                 .orElse(new EndPoint(null, null));
-        ep.setSystemNepUuid(v.getUuid());
+        Objects.requireNonNull(vertex.getUuid());
+        ep.setNepRef(TapiUtils.toSysNepRef(vertex.getNodeUuid(), vertex.getUuid()));
         return ep;
     }
 
-    private final Predicate<Vertex> isInput = v -> v.getDir() == PortDirection.BIDIRECTIONAL|| v.getDir() == PortDirection.INPUT;
-    private final Predicate<Vertex> isOutput = v -> v.getDir() == PortDirection.BIDIRECTIONAL || v.getDir() == PortDirection.OUTPUT;
+    private final Predicate<Vertex> isInput = v -> v.getDir() == PortDirection.BIDIRECTIONAL
+            || v.getDir() == PortDirection.INPUT;
+    private final Predicate<Vertex> isOutput = v -> v.getDir() == PortDirection.BIDIRECTIONAL
+            || v.getDir() == PortDirection.OUTPUT;
 
     private void interconnectNode(Graph<Vertex, DefaultEdge> graph, List<Vertex> vertices) {
         vertices.forEach(graph::addVertex);
@@ -149,14 +192,15 @@ class DecompositionAction {
 
             if (topo.getLink() != null) {
                 topo.getLink().stream()
-                        .filter(l -> l.getState() != null && OperationalState.ENABLED == l.getState().getOperationalState())
-                        .forEach(l -> {
-                            //we probably need to take link bidir/unidir into consideration as well
-                    List<Vertex> vertices = l.getNodeEdgePoint().stream()
-                            .map(nep -> graph.vertexSet().stream().filter(v -> v.getUuid().equals(nep)).findFirst())
+                    .filter(l -> OperationalState.ENABLED == l.getOperationalState())
+                    .forEach(l -> {
+                        //we probably need to take link bidir/unidir into consideration as well
+                        List<Vertex> vertices = l.getNodeEdgePoint().stream()
+                            .map(nep -> graph.vertexSet().stream()
+                                    .filter(v -> v.getUuid().equals(nep.getOwnedNodeEdgePointId())).findFirst())
                             .filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
-                    interconnectLink(graph, vertices);
-                });
+                        interconnectLink(graph, vertices);
+                    });
             }
 
             return graph;
@@ -165,23 +209,32 @@ class DecompositionAction {
         }
     }
 
-    private Stream<Vertex> nodeToGraph(Node n) {
-        Uuid nodeUuid = n.getUuid();
-
-
-        return n.getOwnedNodeEdgePoint().stream()
-                .filter(ep -> ep.getLinkPortDirection() != null && ep.getLinkPortDirection() != PortDirection.UNIDENTIFIEDORUNKNOWN)
-                .map(nep -> {
-            List<Uuid> sips = nep.getMappedServiceInterfacePoint();
-            if (sips == null || sips.isEmpty()) {
-                return  new Vertex(nodeUuid, nep.getUuid(), null, nep.getLinkPortDirection());
-            }
-            if (sips.size() > 1) {
-                LOG.warn("NodeEdgePoint {} have multiple ServiceInterfacePoint mapped, selecting first one", nep.getUuid());
-            }
-            return new Vertex(nodeUuid, nep.getUuid(), sips.get(0), nep.getLinkPortDirection());
+    private Stream<Vertex> nodeToGraph(Node node) {
+        Uuid nodeUuid = node.getUuid();
+        String activationDriverId = node.augmentation(NodeAdiAugmentation.class).getActivationDriverId();
+
+
+        return node.getOwnedNodeEdgePoint().stream()
+            .filter(ep -> ep.getLinkPortDirection() != null
+                    && ep.getLinkPortDirection() != PortDirection.UNIDENTIFIEDORUNKNOWN)
+            .map(nep -> {
+                List<Uuid> sips = Collections.emptyList();
+                if (nep.getMappedServiceInterfacePoint() != null) {
+                    sips = nep.getMappedServiceInterfacePoint().stream()
+                        .map(ServiceInterfacePointRef::getServiceInterfacePointId)
+                        .collect(Collectors.toList());
+                }
+
+                if (sips.isEmpty()) {
+                    return  new Vertex(nodeUuid, nep.getUuid(), null, nep.getLinkPortDirection(),activationDriverId);
+                }
+                if (sips.size() > 1) {
+                    LOG.warn("NodeEdgePoint {} have multiple ServiceInterfacePoint mapped, selecting first one",
+                            nep.getUuid());
+                }
+                return new Vertex(nodeUuid, nep.getUuid(), sips.get(0), nep.getLinkPortDirection(),activationDriverId);
 
-        });
+            });
     }
 
     class Vertex implements Comparable<Vertex> {
@@ -189,6 +242,7 @@ class DecompositionAction {
         private final Uuid nodeUuid;
         private final Uuid uuid;
         private final Uuid sip;
+        private final String activationDriverId;
         private final PortDirection dir;
 
         Vertex(Vertex px, PortDirection csDir) {
@@ -196,15 +250,19 @@ class DecompositionAction {
             this.uuid = px.uuid;
             this.sip = px.sip;
             this.dir = csDir;
+            this.activationDriverId = px.activationDriverId;
         }
 
-        Vertex(Uuid nodeUuid, Uuid uuid, Uuid sip, PortDirection dir) {
+        Vertex(Uuid nodeUuid, Uuid uuid, Uuid sip, PortDirection dir, String activationDriverId) {
             this.sip = sip;
             this.dir = dir;
             Objects.requireNonNull(nodeUuid);
             Objects.requireNonNull(uuid);
+            Objects.requireNonNull(activationDriverId);
+
             this.nodeUuid = nodeUuid;
             this.uuid = uuid;
+            this.activationDriverId = activationDriverId;
         }
 
         Uuid getNodeUuid() {
@@ -219,15 +277,19 @@ class DecompositionAction {
             return sip;
         }
 
+        public String getActivationDriverId() {
+            return activationDriverId;
+        }
+
         @Override
-        public boolean equals(Object o) {
-            if (this == o) {
+        public boolean equals(Object other) {
+            if (this == other) {
                 return true;
             }
-            if (o == null || getClass() != o.getClass()) {
+            if (other == null || getClass() != other.getClass()) {
                 return false;
             }
-            Vertex vertex = (Vertex) o;
+            Vertex vertex = (Vertex) other;
             return Objects.equals(uuid, vertex.uuid);
         }
 
@@ -241,11 +303,11 @@ class DecompositionAction {
         }
 
         @Override
-        public int compareTo(Vertex o) {
-            if (o == null) {
+        public int compareTo(Vertex other) {
+            if (other == null) {
                 return -1;
             }
-            return uuid.getValue().compareTo(o.uuid.getValue());
+            return uuid.getValue().compareTo(other.uuid.getValue());
         }
 
         @Override