Disjoint Path Utils Exposed

- to TopologyStores
- to TopologyServices
- to PathServices
- to REST API

Change-Id: Ib2b5840df0f8e94f327ec8f91827d3d850634562

Change-Id: I03e59210e9c79c4f92dcfa8c7983642572708429

Change-Id: Ia5c17d1ded374ef688990bd30e7f99184aaca95b

Change-Id: Ibebae50bc722701e8212263587727ad8abd79805
diff --git a/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java b/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java
index a238c7f..5f84ee9 100644
--- a/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java
+++ b/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java
@@ -27,6 +27,8 @@
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultEdgeLink;
 import org.onosproject.net.DefaultPath;
+import org.onosproject.net.DisjointPath;
+import org.onosproject.net.DefaultDisjointPath;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.EdgeLink;
 import org.onosproject.net.ElementId;
@@ -46,6 +48,8 @@
 
 import java.util.List;
 import java.util.Set;
+import java.util.Map;
+
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -128,6 +132,84 @@
         return edgeToEdgePaths(srcEdge, dstEdge, paths);
     }
 
+    @Override
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) {
+        return getDisjointPaths(src, dst, null);
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight) {
+        checkNotNull(src, ELEMENT_ID_NULL);
+        checkNotNull(dst, ELEMENT_ID_NULL);
+
+        // Get the source and destination edge locations
+        EdgeLink srcEdge = getEdgeLink(src, true);
+        EdgeLink dstEdge = getEdgeLink(dst, false);
+
+        // If either edge is null, bail with no paths.
+        if (srcEdge == null || dstEdge == null) {
+            return ImmutableSet.of();
+        }
+
+        DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
+        DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
+
+        // If the source and destination are on the same edge device, there
+        // is just one path, so build it and return it.
+        if (srcDevice.equals(dstDevice)) {
+            return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
+        }
+
+        // Otherwise get all paths between the source and destination edge
+        // devices.
+        Topology topology = topologyService.currentTopology();
+        Set<DisjointPath> paths = weight == null ?
+                topologyService.getDisjointPaths(topology, srcDevice, dstDevice) :
+                topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight);
+
+        return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
+    }
+
+    @Override
+    public Set<DisjointPath> getSRLGDisjointPaths(ElementId src, ElementId dst,
+                                                  Map<Link, Object> riskProfile) {
+        return getSRLGDisjointPaths(src, dst, null, riskProfile);
+    }
+
+    @Override
+    public Set<DisjointPath> getSRLGDisjointPaths(ElementId src, ElementId dst, LinkWeight weight,
+                                                  Map<Link, Object> riskProfile) {
+        checkNotNull(src, ELEMENT_ID_NULL);
+        checkNotNull(dst, ELEMENT_ID_NULL);
+
+        // Get the source and destination edge locations
+        EdgeLink srcEdge = getEdgeLink(src, true);
+        EdgeLink dstEdge = getEdgeLink(dst, false);
+
+        // If either edge is null, bail with no paths.
+        if (srcEdge == null || dstEdge == null) {
+            return ImmutableSet.of();
+        }
+
+        DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
+        DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
+
+        // If the source and destination are on the same edge device, there
+        // is just one path, so build it and return it.
+        if (srcDevice.equals(dstDevice)) {
+            return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
+        }
+
+        // Otherwise get all paths between the source and destination edge
+        // devices.
+        Topology topology = topologyService.currentTopology();
+        Set<DisjointPath> paths = weight == null ?
+                topologyService.getSRLGDisjointPaths(topology, srcDevice, dstDevice, riskProfile) :
+                topologyService.getSRLGDisjointPaths(topology, srcDevice, dstDevice, weight, riskProfile);
+
+        return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
+    }
+
     // Finds the host edge link if the element ID is a host id of an existing
     // host. Otherwise, if the host does not exist, it returns null and if
     // the element ID is not a host ID, returns NOT_HOST edge link.
@@ -162,6 +244,19 @@
         return endToEndPaths;
     }
 
+    private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink) {
+        Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
+        endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, null));
+        return endToEndPaths;
+    }
+    private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink, Set<DisjointPath> paths) {
+        Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
+        for (DisjointPath path : paths) {
+            endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, path));
+        }
+        return endToEndPaths;
+    }
+
     // Produces a direct edge-to-edge path.
     private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
         List<Link> links = Lists.newArrayListWithCapacity(2);
@@ -179,6 +274,13 @@
         return new DefaultPath(PID, links, 2);
     }
 
+    // Produces a direct edge-to-edge path.
+    private DisjointPath edgeToEdgePathD(EdgeLink srcLink, EdgeLink dstLink, DisjointPath path) {
+        return new DefaultDisjointPath(PID, (DefaultPath) edgeToEdgePath(srcLink, dstLink, path.primary()),
+                                       (DefaultPath) edgeToEdgePath(srcLink, dstLink, path.backup()));
+    }
+
+
     // Special value for edge link to represent that this is really not an
     // edge link since the src or dst are really an infrastructure device.
     private static class NotHost extends DefaultEdgeLink implements EdgeLink {