[ONOS] Compute path with Explicit path objects

Change-Id: Ib487688e15db7056283feef7720f610b2f59ad84
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
index 455e36a..3a5eff4 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
@@ -16,21 +16,46 @@
 
 package org.onosproject.pce.pceservice;
 
+import com.google.common.collect.Lists;
+
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
+import static org.onosproject.pce.pceservice.PathComputationTest.D2;
+import static org.easymock.EasyMock.createMock;
 
 import com.google.common.testing.EqualsTester;
 
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.rest.BaseResource;
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.pce.pceservice.constraint.CostConstraint;
+import org.onosproject.pce.pcestore.api.PceStore;
 import org.onosproject.net.intent.constraint.BandwidthConstraint;
 
+import java.util.List;
+
 /**
  * Unit tests for DefaultPcePath class.
  */
 public class DefaultPcePathTest {
+    private PceStore pceStore = createMock(PceStore.class);
+
+    @Before
+    public void setup() {
+
+       ServiceDirectory testDirectory = new TestServiceDirectory()
+                   .add(PceStore.class, pceStore);
+       BaseResource.setServiceDirectory(testDirectory);
+    }
+
+    @After
+    public void tearDownTest() {
+    }
     /**
      * Checks the operation of equals() methods.
      */
@@ -43,7 +68,9 @@
         final String dst1 = "bee";
         final String type1 = "1";
         final String name1 = "pcc";
-
+        final List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+        explicitPathInfoList.add(obj);
         PcePath path1 = DefaultPcePath.builder()
                 .source(src1)
                 .destination(dst1)
@@ -51,6 +78,7 @@
                 .name(name1)
                 .costConstraint(cost1)
                 .bandwidthConstraint(bandwidth1)
+                .explicitPathInfo(explicitPathInfoList)
                 .build();
         path1.id(TunnelId.valueOf("1"));
 
@@ -62,6 +90,7 @@
                 .name(name1)
                 .costConstraint(cost1)
                 .bandwidthConstraint(bandwidth1)
+                .explicitPathInfo(explicitPathInfoList)
                 .build();
         samePath1.id(TunnelId.valueOf("1"));
 
@@ -80,6 +109,7 @@
                 .name(name2)
                 .costConstraint(cost2)
                 .bandwidthConstraint(bandwidth2)
+                .explicitPathInfo(explicitPathInfoList)
                 .build();
         path2.id(TunnelId.valueOf("2"));
 
@@ -97,7 +127,9 @@
         final String dst = "deccan";
         final String type = "2";
         final String name = "pcc4";
-
+        final List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+        explicitPathInfoList.add(obj);
         PcePath path = DefaultPcePath.builder()
                 .source(src)
                 .destination(dst)
@@ -105,6 +137,7 @@
                 .name(name)
                 .costConstraint(cost)
                 .bandwidthConstraint(bandwidth)
+                .explicitPathInfo(explicitPathInfoList)
                 .build();
 
         assertThat(path.source(), is(src));
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
index f78ce9d..54cc1a9 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
@@ -29,10 +29,12 @@
 import static org.onosproject.pce.pceservice.PathComputationTest.D2;
 import static org.onosproject.pce.pceservice.PathComputationTest.D3;
 import static org.onosproject.pce.pceservice.PathComputationTest.D4;
+import static org.onosproject.pce.pceservice.PathComputationTest.D5;
 import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE1;
 import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE2;
 import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE3;
 import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE4;
+import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE5;
 import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
 import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
 import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST;
@@ -47,6 +49,8 @@
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
+import com.google.common.collect.Lists;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -135,9 +139,9 @@
     private static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
 
     private TopologyGraph graph = null;
-    private Device deviceD1, deviceD2, deviceD3, deviceD4;
+    private Device deviceD1, deviceD2, deviceD3, deviceD4, deviceD5;
     private Device pcepDeviceD1, pcepDeviceD2, pcepDeviceD3, pcepDeviceD4;
-    private Link link1, link2, link3, link4;
+    private Link link1, link2, link3, link4, link5, link6;
     protected static int flowsDownloaded;
     private TunnelListener tunnelListener;
     private TopologyListener listener;
@@ -179,12 +183,15 @@
         link2 = PathComputationTest.addLink(DEVICE2, 30, DEVICE4, 40, setCost, 20);
         link3 = PathComputationTest.addLink(DEVICE1, 80, DEVICE3, 70, setCost, 100);
         link4 = PathComputationTest.addLink(DEVICE3, 60, DEVICE4, 50, setCost, 80);
+        link5 = PathComputationTest.addLink(DEVICE2, 60, DEVICE5, 50, setCost, 80);
+        link6 = PathComputationTest.addLink(DEVICE4, 60, DEVICE5, 50, setCost, 80);
 
         Set<TopologyVertex> vertexes = new HashSet<TopologyVertex>();
         vertexes.add(D1);
         vertexes.add(D2);
         vertexes.add(D3);
         vertexes.add(D4);
+        vertexes.add(D5);
 
         this.vertexes = vertexes;
 
@@ -201,6 +208,12 @@
         TopologyEdge edge4 = new DefaultTopologyEdge(D3, D4, link4);
         edges.add(edge4);
 
+        TopologyEdge edge5 = new DefaultTopologyEdge(D2, D5, link5);
+        edges.add(edge5);
+
+        TopologyEdge edge6 = new DefaultTopologyEdge(D4, D5, link6);
+        edges.add(edge6);
+
         this.edges = edges;
 
         graph = new DefaultTopologyGraph(vertexes, edges);
@@ -209,6 +222,7 @@
         DefaultAnnotations.Builder builderDev2 = DefaultAnnotations.builder();
         DefaultAnnotations.Builder builderDev3 = DefaultAnnotations.builder();
         DefaultAnnotations.Builder builderDev4 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev5 = DefaultAnnotations.builder();
 
         // Making L3 devices
         builderDev1.set(AnnotationKeys.TYPE, L3);
@@ -223,15 +237,20 @@
         builderDev4.set(AnnotationKeys.TYPE, L3);
         builderDev4.set(LSRID, "4.4.4.4");
 
+        builderDev5.set(AnnotationKeys.TYPE, L3);
+        builderDev5.set(LSRID, "5.5.5.5");
+
         deviceD1 = new MockDevice(D1.deviceId(), builderDev1.build());
         deviceD2 = new MockDevice(D2.deviceId(), builderDev2.build());
         deviceD3 = new MockDevice(D3.deviceId(), builderDev3.build());
         deviceD4 = new MockDevice(D4.deviceId(), builderDev4.build());
+        deviceD5 = new MockDevice(D5.deviceId(), builderDev5.build());
 
         deviceService.addDevice(deviceD1);
         deviceService.addDevice(deviceD2);
         deviceService.addDevice(deviceD3);
         deviceService.addDevice(deviceD4);
+        deviceService.addDevice(deviceD5);
 
         DeviceCapability device1Cap = netConfigRegistry.addConfig(DeviceId.deviceId("1.1.1.1"), DeviceCapability.class);
         device1Cap.setLabelStackCap(setLabelStackCap)
@@ -257,17 +276,25 @@
         .setSrCap(setSrCap)
         .apply();
 
+        DeviceCapability device5Cap = netConfigRegistry.addConfig(DeviceId.deviceId("5.5.5.5"), DeviceCapability.class);
+        device4Cap.setLabelStackCap(setLabelStackCap)
+                .setLocalLabelCap(setPceccCap)
+                .setSrCap(setSrCap)
+                .apply();
+
         if (bandwidth != 0) {
             List<Resource> resources = new LinkedList<>();
             resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link5.src().deviceId(), link5.src().port(), Bandwidth.class).resource(bandwidth));
 
             resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link5.dst().deviceId(), link5.dst().port(), Bandwidth.class).resource(bandwidth));
 
             resourceService.allocate(IntentId.valueOf(bandwidth), resources);
         }
@@ -283,7 +310,7 @@
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -297,7 +324,7 @@
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -312,7 +339,7 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -327,7 +354,7 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -343,7 +370,7 @@
         constraints.add(costConstraint);
 
         boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(result, is(true));
     }
 
@@ -359,7 +386,7 @@
         constraints.add(costConstraint);
 
         boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(result, is(true));
     }
 
@@ -375,7 +402,7 @@
         constraints.add(costConstraint);
 
         boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(result, is(false));
     }
 
@@ -392,7 +419,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
+                WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -409,7 +437,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -423,7 +452,8 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
+             SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -440,7 +470,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
+                constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -451,11 +482,144 @@
     public void setupPathTest13() {
         build4RouterTopo(false, false, false, false, 0);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
     /**
+     * Tests path setup with explicit path with loose node D2.
+     */
+   @Test
+    public void setupPathTest14() {
+        build4RouterTopo(false, false, false, false, 0);
+
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+        explicitPathInfoList.add(obj);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", null, WITH_SIGNALLING,
+                explicitPathInfoList);
+
+        Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+
+        assertThat(result, is(true));
+        assertThat(tunnel.path().links().equals(links), is(true));
+    }
+
+    /**
+     * Tests path setup with explicit path with loose node D3.
+     */
+   @Test
+   public void setupPathTest15() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+       List<Link> links = new LinkedList<>();
+       links.add(link3);
+       links.add(link4);
+       links.add(link6);
+
+       assertThat(result, is(true));
+       assertThat(tunnel.path().links().equals(links), is(true));
+   }
+
+    /**
+     * Tests path setup with explicit path with loose node D4 , D3 - path fails.
+     */
+   @Test
+   public void setupPathTest16() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D4.deviceId());
+       explicitPathInfoList.add(obj);
+       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       assertThat(result, is(false));
+   }
+
+    /**
+     * Tests path setup with explicit path with strict node D2 - without reacble to src - path fails.
+     */
+   @Test
+   public void setupPathTest17() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       assertThat(result, is(false));
+   }
+
+    /**
+     * Tests path setup with explicit path with loose node D2, strict D2.
+     */
+   @Test
+   public void setupPathTest18() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+       explicitPathInfoList.add(obj);
+       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+       List<Link> links = new LinkedList<>();
+       links.add(link1);
+       links.add(link5);
+
+       assertThat(result, is(true));
+       assertThat(tunnel.path().links().equals(links), is(true));
+   }
+
+    /**
+     * Tests path setup with explicit path with loose D1-D2, strict D2.
+     */
+   @Test
+   public void setupPathTest19() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+       explicitPathInfoList.add(obj);
+       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+       List<Link> links = new LinkedList<>();
+       links.add(link1);
+       links.add(link5);
+
+       assertThat(result, is(true));
+       assertThat(tunnel.path().links().equals(links), is(true));
+   }
+
+    /**
      * Tests path update with increase in bandwidth.
      */
     @Test
@@ -469,7 +633,8 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         // Change constraint and update it.
@@ -507,7 +672,8 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
+                constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(true));
 
         // Change constraint and update it.
@@ -538,7 +704,8 @@
         List<Constraint> constraints = new LinkedList<Constraint>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
@@ -554,6 +721,51 @@
     }
 
     /**
+     * Tests path update without cost/bandwidth constraints and with explicit path object.
+     */
+    @Test
+    public void updatePathTest4() {
+        build4RouterTopo(false, true, true, true, 100);
+
+        // Setup tunnel.
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(60.0));
+        constraints.add(bwConstraint);
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+        explicitPathInfoList.add(obj);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, explicitPathInfoList);
+        assertThat(result, is(true));
+
+        // Change constraint and update it.
+        constraints = new LinkedList<>();
+        bwConstraint = new BandwidthConstraint(Bandwidth.bps(50.0));
+        constraints.add(bwConstraint);
+        constraints.add(costConstraint);
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+
+        Tunnel tunnel = tunnels.iterator().next();
+
+        // Stimulate the effect of LSP ids from protocol msg.
+        tunnelService.updateTunnelWithLspIds(tunnel, "123", "1", State.ACTIVE);
+
+        result = pceManager.updatePath(tunnel.tunnelId(), constraints);
+        assertThat(result, is(true));
+
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(2));
+    }
+
+    /**
      * Tests path release.
      */
     @Test
@@ -565,7 +777,13 @@
         constraints.add(bwConst);
         constraints.add(costConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+        explicitPathInfoList.add(obj);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, explicitPathInfoList);
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
         assertThat(tunnels.size(), is(1));
@@ -588,7 +806,7 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
         assertThat(tunnels.size(), is(1));
@@ -602,6 +820,31 @@
     }
 
     /**
+     * Tests path release failure.
+     */
+    @Test
+    public void releasePathTest3() {
+        build4RouterTopo(false, false, false, false, 5);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        BandwidthConstraint bwConst = new BandwidthConstraint(Bandwidth.bps(3));
+        constraints.add(bwConst);
+        constraints.add(costConstraint);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+        boolean result;
+        for (Tunnel tunnel : tunnels) {
+            result = pceManager.releasePath(tunnel.tunnelId());
+            assertThat(result, is(true));
+        }
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(0));
+    }
+
+    /**
      * Tests tunnel events added and removed.
      */
     @Test
@@ -614,7 +857,7 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints, SR_WITHOUT_SIGNALLING);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(pceStore.getTunnelInfoCount(), is(1));
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
@@ -645,7 +888,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints,
+                WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(pceStore.getTunnelInfoCount(), is(1));
 
         TunnelEvent event;
@@ -685,7 +929,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints,
+                WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(pceStore.getTunnelInfoCount(), is(1));
         assertThat(pceStore.getFailedPathInfoCount(), is(0));
 
@@ -723,7 +968,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
         assertThat(pceStore.getTunnelInfoCount(), is(1));
         assertThat(pceStore.getFailedPathInfoCount(), is(0));
@@ -765,7 +1011,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -803,7 +1050,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -846,7 +1094,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -884,7 +1133,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -932,7 +1182,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -973,7 +1224,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1014,7 +1266,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1060,7 +1313,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1092,6 +1346,54 @@
         assertThat(pathService.paths().iterator().next().cost(), is((double) 180));
     }
 
+    /**
+     * Tests resilency when link2 availability is changed.
+     */
+    @Test
+    public void resilencyTest12() {
+        build4RouterTopo(true, false, false, false, 10);
+
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(COST);
+        constraints.add(costConstraint);
+        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        constraints.add(localBwConst);
+
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+        explicitPathInfoList.add(obj);
+
+        //Setup the path , tunnel created
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, explicitPathInfoList);
+        assertThat(result, is(true));
+        assertThat(pceStore.getTunnelInfoCount(), is(1));
+        assertThat(pceStore.getFailedPathInfoCount(), is(0));
+
+        List<Event> reasons = new LinkedList<>();
+        final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link2);
+        reasons.add(linkEvent);
+        final TopologyEvent event = new TopologyEvent(
+                TopologyEvent.Type.TOPOLOGY_CHANGED,
+                topology,
+                reasons);
+
+        //Change Topology : remove link2
+        Set<TopologyEdge> tempEdges = new HashSet<>();
+        tempEdges.add(new DefaultTopologyEdge(D2, D4, link2));
+        topologyService.changeInTopology(getGraph(null,  tempEdges));
+        listener.event(event);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link3);
+        links.add(link4);
+
+        //Path fails - no alternate path
+        assertThat(pathService.paths().iterator().hasNext(), is(false));
+    }
+
     @After
     public void tearDown() {
         pceManager.deactivate();
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/DistributedPceStoreTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/DistributedPceStoreTest.java
index e0916a8..c7e6ac9 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/DistributedPceStoreTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/DistributedPceStoreTest.java
@@ -120,7 +120,7 @@
        Constraint bandwidth1 = BandwidthConstraint.of(200, DataRateUnit.BPS);
        constraints1.add(bandwidth1);
 
-       failedPathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
+       failedPathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
 
        // Creates failedPathInfo2
        DeviceId src2 = DeviceId.deviceId("foo2");
@@ -131,7 +131,7 @@
        Constraint bandwidth2 = BandwidthConstraint.of(400, DataRateUnit.BPS);
        constraints2.add(bandwidth2);
 
-       failedPathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2);
+       failedPathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2, null);
 
        // Creates failedPathInfo3
        DeviceId src3 = DeviceId.deviceId("foo3");
@@ -142,7 +142,7 @@
        Constraint bandwidth3 = BandwidthConstraint.of(500, DataRateUnit.BPS);
        constraints3.add(bandwidth3);
 
-       failedPathInfo3 = new PcePathInfo(src3, dst3, name3, constraints3, lspType3);
+       failedPathInfo3 = new PcePathInfo(src3, dst3, name3, constraints3, lspType3, null);
 
        // Creates failedPathInfo4
        DeviceId src4 = DeviceId.deviceId("foo4");
@@ -153,7 +153,7 @@
        Constraint bandwidth4 = BandwidthConstraint.of(600, DataRateUnit.BPS);
        constraints4.add(bandwidth4);
 
-       failedPathInfo4 = new PcePathInfo(src4, dst4, name4, constraints4, lspType4);
+       failedPathInfo4 = new PcePathInfo(src4, dst4, name4, constraints4, lspType4, null);
     }
 
     @After
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/PcePathInfoTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/PcePathInfoTest.java
index 09b60ab..a13c634 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/PcePathInfoTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/PcePathInfoTest.java
@@ -53,10 +53,10 @@
         Constraint bandwidth13 = BandwidthConstraint.of(300, DataRateUnit.BPS);
         constraints1.add(bandwidth13);
 
-        PcePathInfo pathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
+        PcePathInfo pathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
 
         // create same object as above object
-        PcePathInfo samePathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
+        PcePathInfo samePathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
 
         // Create different object.
         DeviceId src2 = DeviceId.deviceId("foo2");
@@ -69,7 +69,7 @@
         Constraint bandwidth22 = BandwidthConstraint.of(800, DataRateUnit.BPS);
         constraints2.add(bandwidth22);
 
-        PcePathInfo pathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2);
+        PcePathInfo pathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2, null);
 
         new EqualsTester().addEqualityGroup(pathInfo1, samePathInfo1)
                           .addEqualityGroup(pathInfo2)
@@ -93,7 +93,7 @@
         Constraint bandwidth3 = BandwidthConstraint.of(300, DataRateUnit.BPS);
         constraints.add(bandwidth3);
 
-        PcePathInfo pathInfo = new PcePathInfo(src, dst, name, constraints, lspType);
+        PcePathInfo pathInfo = new PcePathInfo(src, dst, name, constraints, lspType, null);
 
         assertThat(src, is(pathInfo.src()));
         assertThat(dst, is(pathInfo.dst()));
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java b/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
index 80f62a5..cba8801 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
@@ -22,13 +22,14 @@
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import org.onosproject.incubator.net.tunnel.TunnelId;
-import org.onosproject.net.DeviceId;
 import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pcestore.PcePathInfo;
 import org.onosproject.pce.pcestore.api.PceStore;
 
@@ -43,8 +44,8 @@
     // Set of Path info
     private Set<PcePathInfo> failedPathInfoSet = new HashSet<>();
 
-    // Locally maintain LSRID to device id mapping for better performance.
-    private Map<String, DeviceId> lsrIdDeviceIdMap = new HashMap<>();
+    // Locally maintain with tunnel name as key and corresponding list of explicit path object
+    private Map<String, List<ExplicitPathInfo>> tunnelNameExplicitPathInfoMap = new HashMap<>();
 
     @Override
     public boolean existsTunnelInfo(TunnelId tunnelId) {
@@ -108,4 +109,15 @@
         }
         return true;
     }
+
+    @Override
+    public boolean tunnelNameExplicitPathInfoMap(String tunnelName, List<ExplicitPathInfo> explicitPathInfo) {
+        tunnelNameExplicitPathInfoMap.put(tunnelName, explicitPathInfo);
+        return false;
+    }
+
+    @Override
+    public List<ExplicitPathInfo> getTunnelNameExplicitPathInfoMap(String tunnelName) {
+        return tunnelNameExplicitPathInfoMap.get(tunnelName);
+    }
 }