ONOS-5808: Allocate BW from ConnectivityIntentCompiler and unit tests for partial failure

Change-Id: I2eb3c16efbce619db6d0d2ba415a35752a61ece4
diff --git a/cli/src/main/java/org/onosproject/cli/net/ResourcesCommand.java b/cli/src/main/java/org/onosproject/cli/net/ResourcesCommand.java
index 22b0f87..ca61f55 100644
--- a/cli/src/main/java/org/onosproject/cli/net/ResourcesCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/ResourcesCommand.java
@@ -120,9 +120,22 @@
         } else {
             String resourceName = resource.simpleTypeName();
             if (resource instanceof ContinuousResource) {
-                print("%s%s: %f", Strings.repeat(" ", level),
-                                  resourceName,
-                                  ((ContinuousResource) resource).value());
+                if (availablesOnly) {
+                    // Get the total resource
+                    double total = ((ContinuousResource) resource).value();
+                    // Get allocated resource
+                    double allocated = resourceService.getResourceAllocations(resource.id()).stream()
+                            .mapToDouble(rA -> ((ContinuousResource) rA.resource()).value())
+                            .sum();
+                    // Difference
+                    double difference = total - allocated;
+                    print("%s%s: %f", Strings.repeat(" ", level),
+                          resourceName, difference);
+                } else {
+                    print("%s%s: %f", Strings.repeat(" ", level),
+                          resourceName,
+                          ((ContinuousResource) resource).value());
+                }
                 // Continuous resource is terminal node, stop here
                 return;
             } else {
diff --git a/core/api/src/main/java/org/onosproject/net/intent/Key.java b/core/api/src/main/java/org/onosproject/net/intent/Key.java
index b4dab2d..e8e4af7 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/Key.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/Key.java
@@ -19,6 +19,8 @@
 import com.google.common.hash.HashFunction;
 import com.google.common.hash.Hashing;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.net.resource.ResourceConsumerId;
 
 import java.nio.charset.StandardCharsets;
 import java.util.Objects;
@@ -28,7 +30,7 @@
  */
 // TODO maybe pull this up to utils
 @Beta
-public abstract class Key implements Comparable<Key> {
+public abstract class Key implements Comparable<Key>, ResourceConsumer {
 
     //TODO consider making this a HashCode object (worry about performance)
     private final long hash;
@@ -54,6 +56,8 @@
      * Creates a key based on the provided string.
      * <p>
      * Note: Two keys with equal value, but different appId, are not equal.
+     * Warning: it is caller responsibility to make sure the hashed value of
+     * {@code value} is unique.
      * </p>
      *
      * @param key the provided string
@@ -79,6 +83,11 @@
         return new LongKey(key, appId);
     }
 
+    @Override
+    public ResourceConsumerId consumerId() {
+        return ResourceConsumerId.of(hash(), getClass());
+    }
+
     private static final class StringKey extends Key {
 
         private final ApplicationId appId;
diff --git a/core/api/src/test/java/org/onosproject/net/NetTestTools.java b/core/api/src/test/java/org/onosproject/net/NetTestTools.java
index d6227a7..dd03a09 100644
--- a/core/api/src/test/java/org/onosproject/net/NetTestTools.java
+++ b/core/api/src/test/java/org/onosproject/net/NetTestTools.java
@@ -76,17 +76,27 @@
     }
 
     // Crates a new host with the specified id
-    public static Host host(String id, String did) {
+    public static Host host(String id, String did, long port) {
         return new DefaultHost(PID, hid(id), valueOf(1234), vlanId((short) 2),
-                               new HostLocation(did(did), portNumber(1), 321),
+                               new HostLocation(did(did), portNumber(port), 321),
                                new HashSet<>());
     }
 
+    // Crates a new host with the specified id
+    public static Host host(String id, String did) {
+        return host(id, did, 1);
+    }
+
     // Short-hand for creating a connection point.
     public static ConnectPoint connectPoint(String id, int port) {
         return new ConnectPoint(did(id), portNumber(port));
     }
 
+    // Short-hand for creating a connection point.
+    public static ConnectPoint connectPointNoOF(String id, int port) {
+        return new ConnectPoint(DeviceId.deviceId(id), portNumber(port));
+    }
+
     // Short-hand for creating a link.
     public static Link link(String src, int sp, String dst, int dp) {
         return new DefaultLink(PID,
@@ -95,6 +105,14 @@
                                Link.Type.DIRECT, Link.State.ACTIVE);
     }
 
+    // Short-hand for creating a link.
+    public static Link linkNoPrefixes(String src, int sp, String dst, int dp) {
+        return new DefaultLink(PID,
+                               connectPointNoOF(src, sp),
+                               connectPointNoOF(dst, dp),
+                               Link.Type.DIRECT, Link.State.ACTIVE);
+    }
+
     /**
      * Short-hand for creating a link.
      *
@@ -110,21 +128,21 @@
     public static Path createPath(String... ids) {
         List<Link> links = new ArrayList<>();
         for (int i = 0; i < ids.length - 1; i++) {
-            links.add(link(ids[i], i, ids[i + 1], i));
+            links.add(link(ids[i], 2, ids[i + 1], 1));
         }
         return new DefaultPath(PID, links, ids.length);
     }
 
-    // Creates a path that leads through the given devices.
+    // Creates a path that leads through the given hosts.
     public static Path createPath(boolean srcIsEdge, boolean dstIsEdge, String... ids) {
         List<Link> links = new ArrayList<>();
         for (int i = 0; i < ids.length - 1; i++) {
             if (i == 0 && srcIsEdge) {
-                links.add(DefaultEdgeLink.createEdgeLink(host(ids[i], ids[i + 1]), true));
+                links.add(DefaultEdgeLink.createEdgeLink(host(ids[i], ids[i + 1], 1), true));
             } else if (i == ids.length - 2 && dstIsEdge) {
-                links.add(DefaultEdgeLink.createEdgeLink(host(ids[i + 1], ids[i]), false));
+                links.add(DefaultEdgeLink.createEdgeLink(host(ids[i + 1], ids[i], 2), false));
             } else {
-                links.add(link(ids[i], i, ids[i + 1], i));
+                links.add(link(ids[i], 2, ids[i + 1], 1));
             }
         }
         return new DefaultPath(PID, links, ids.length);
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
index a944ca6..cef5b67 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
@@ -17,9 +17,9 @@
 
 import com.google.common.base.MoreObjects;
 import org.onlab.graph.Weight;
-import org.onlab.util.Bandwidth;
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.core.GroupId;
+import org.onosproject.net.DefaultPath;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.ElementId;
 import org.onosproject.net.HostId;
@@ -38,13 +38,7 @@
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
-import org.onosproject.net.resource.DiscreteResourceId;
-import org.onosproject.net.resource.Resource;
-import org.onosproject.net.resource.ResourceAllocation;
-import org.onosproject.net.resource.ResourceConsumer;
-import org.onosproject.net.resource.ResourceId;
-import org.onosproject.net.resource.ResourceListener;
-import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.provider.ProviderId;
 import org.onosproject.net.topology.DefaultTopologyEdge;
 import org.onosproject.net.topology.DefaultTopologyVertex;
 import org.onosproject.net.topology.LinkWeigher;
@@ -52,13 +46,13 @@
 import org.onosproject.net.topology.TopologyVertex;
 import org.onosproject.store.Timestamp;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -185,8 +179,7 @@
      * Mock path service for creating paths within the test.
      *
      */
-    public static class Mp2MpMockPathService
-            extends PathServiceAdapter {
+    public static class Mp2MpMockPathService extends PathServiceAdapter {
 
         final String[] pathHops;
         final String[] reversePathHops;
@@ -242,84 +235,74 @@
         }
     }
 
-    public static final class MockResourceService implements ResourceService {
+    /**
+     * Mock path service for creating paths for MP2SP intent tests, returning
+     * pre-determined paths.
+     */
+    public static class FixedMP2MPMockPathService extends PathServiceAdapter {
 
-        private final double bandwidth;
+        final String[] pathHops;
 
-        public static ResourceService makeBandwidthResourceService(double bandwidth) {
-            return new MockResourceService(bandwidth);
-        }
+        public static final String DPID_1 = "of:s1";
+        public static final String DPID_2 = "of:s2";
+        public static final String DPID_3 = "of:s3";
+        public static final String DPID_4 = "of:s4";
 
-        private MockResourceService(double bandwidth) {
-            this.bandwidth = bandwidth;
+        /**
+         * Constructor that provides a set of hops to mock.
+         *
+         * @param pathHops path hops to mock
+         */
+        public FixedMP2MPMockPathService(String[] pathHops) {
+            this.pathHops = pathHops;
         }
 
         @Override
-        public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<? extends Resource> resources) {
-            return null;
-        }
-
-        @Override
-        public boolean release(List<ResourceAllocation> allocations) {
-            return false;
-        }
-
-        @Override
-        public boolean release(ResourceConsumer consumer) {
-            return false;
-        }
-
-        @Override
-        public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
-            return null;
-        }
-
-        @Override
-        public <T> Collection<ResourceAllocation> getResourceAllocations(DiscreteResourceId parent, Class<T> cls) {
-            return null;
-        }
-
-        @Override
-        public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) {
-            return null;
-        }
-
-        @Override
-        public Set<Resource> getAvailableResources(DiscreteResourceId parent) {
-            return null;
-        }
-
-        @Override
-        public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) {
-            return null;
-        }
-
-        @Override
-        public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) {
-            return null;
-        }
-
-        @Override
-        public Set<Resource> getRegisteredResources(DiscreteResourceId parent) {
-            return null;
-        }
-
-        @Override
-        public boolean isAvailable(Resource resource) {
-            if (!resource.isTypeOf(Bandwidth.class)) {
-                return false;
+        public Set<Path> getPaths(ElementId src, ElementId dst) {
+            List<Link> links = new ArrayList<>();
+            Set<Path> result = new HashSet<>();
+            ProviderId providerId = new ProviderId("of", "foo");
+            DefaultPath path;
+            if (src.toString().equals(DPID_1) && dst.toString().equals(DPID_4)) {
+                links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
+                links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
+            } else if (src.toString().equals(DPID_2) && dst.toString().equals(DPID_4)) {
+                links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 3));
+                links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
+            } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_1)) {
+                links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
+                links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
+            } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_2)) {
+                links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
+                links.add(NetTestTools.linkNoPrefixes(pathHops[0], 3, dst.toString(), 1));
+            } else {
+                return result;
             }
+            path = new DefaultPath(providerId, links, 3);
+            result.add(path);
 
-            Optional<Double> value = resource.valueAs(Double.class);
-            return value.filter(requested -> requested <= bandwidth).isPresent();
+            return result;
         }
 
         @Override
-        public void addListener(ResourceListener listener) {
-        }
+        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
+            final Set<Path> paths = getPaths(src, dst);
 
-        @Override
-        public void removeListener(ResourceListener listener) {
+            for (Path path : paths) {
+                final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
+                final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
+                if (srcDevice != null && dstDevice != null) {
+                    final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
+                    final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
+                    final Link link = link(src.toString(), 1, dst.toString(), 1);
+
+                    final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
+                    if (weightValue.isNegative()) {
+                        return new HashSet<>();
+                    }
+                }
+            }
+            return paths;
         }
     }
 
@@ -500,5 +483,4 @@
             return true;
         }
     }
-
 }
diff --git a/core/api/src/test/java/org/onosproject/net/resource/MockResourceService.java b/core/api/src/test/java/org/onosproject/net/resource/MockResourceService.java
index 436a763..3a8b4e4 100644
--- a/core/api/src/test/java/org/onosproject/net/resource/MockResourceService.java
+++ b/core/api/src/test/java/org/onosproject/net/resource/MockResourceService.java
@@ -20,6 +20,7 @@
 
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
 import org.onlab.util.Tools;
 import org.onosproject.net.TributarySlot;
 
@@ -35,10 +36,22 @@
 
 public class MockResourceService implements ResourceService {
 
+    private double bandwidth = 1000.0;
     private final Map<Resource, ResourceConsumer> assignment = new HashMap<>();
     public Set<Short> availableVlanLabels = new HashSet<>();
     public Set<Integer> availableMplsLabels = new HashSet<>();
 
+    public MockResourceService(){}
+
+    // To express a custom bandwidth available (in bps)
+    public static ResourceService makeCustomBandwidthResourceService(double bandwidth) {
+        return new MockResourceService(bandwidth);
+    }
+
+    private MockResourceService(double bandwidth) {
+        this.bandwidth = bandwidth;
+    }
+
     @Override
     public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<? extends Resource> resources) {
         assignment.putAll(
@@ -181,6 +194,11 @@
 
     @Override
     public boolean isAvailable(Resource resource) {
+        if (resource.isTypeOf(Bandwidth.class)) {
+            // If there's is enough bandwidth available return true; false otherwise
+            Optional<Double> value = resource.valueAs(Double.class);
+            return value.filter(requested -> requested <= bandwidth).isPresent();
+        }
         return true;
     }
 
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
index 6f2ed13..7b79f95 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
@@ -51,8 +51,9 @@
 import org.onosproject.net.intent.impl.phase.FinalIntentProcessPhase;
 import org.onosproject.net.intent.impl.phase.IntentProcessPhase;
 import org.onosproject.net.intent.impl.phase.Skipped;
-import org.osgi.service.component.ComponentContext;
+import org.onosproject.net.resource.ResourceConsumer;
 import org.onosproject.net.resource.ResourceService;
+import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 
 import java.util.Collection;
@@ -344,9 +345,8 @@
             post(event);
             switch (event.type()) {
                 case WITHDRAWN:
-                    // release resources allocated to withdrawn intent
-                    if (!resourceService.release(event.subject().id())) {
-                        log.error("Failed to release resources allocated to {}", event.subject().id());
+                    if (!skipReleaseResourcesOnWithdrawal) {
+                        releaseResources(event.subject());
                     }
                     break;
                 default:
@@ -363,6 +363,41 @@
         public void onUpdate(IntentData intentData) {
             trackerService.trackIntent(intentData);
         }
+
+        private void releaseResources(Intent intent) {
+            // If a resource group is set on the intent, the resource consumer is
+            // set equal to it. Otherwise it's set to the intent key
+            ResourceConsumer resourceConsumer =
+                    intent.resourceGroup() != null ? intent.resourceGroup() : intent.key();
+
+            // By default the resource doesn't get released
+            boolean removeResource = false;
+
+            if (intent.resourceGroup() == null) {
+                // If the intent doesn't have a resource group, it means the
+                // resource was registered using the intent key, so it can be
+                // released
+                removeResource = true;
+            } else {
+                // When a resource group is set, we make sure there are no other
+                // intents using the same resource group, before deleting the
+                // related resources.
+                Long remainingIntents =
+                        Tools.stream(store.getIntents())
+                             .filter(i -> i.resourceGroup().equals(intent.resourceGroup()))
+                             .count();
+                if (remainingIntents == 0) {
+                    removeResource = true;
+                }
+            }
+
+            if (removeResource) {
+                // Release resources allocated to withdrawn intent
+                if (!resourceService.release(resourceConsumer)) {
+                    log.error("Failed to release resources allocated to {}", resourceConsumer);
+                }
+            }
+        }
     }
 
     // Store delegate enabled only when performing intent throughput tests
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
index 74e94b1..0489c85 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
@@ -17,32 +17,48 @@
 
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.onlab.graph.DefaultEdgeWeigher;
 import org.onlab.graph.ScalarWeight;
 import org.onlab.graph.Weight;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.DisjointPath;
 import org.onosproject.net.ElementId;
 import org.onosproject.net.Path;
+import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.intent.ConnectivityIntent;
 import org.onosproject.net.intent.Constraint;
 import org.onosproject.net.intent.IntentCompiler;
 import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
 import org.onosproject.net.intent.constraint.HashedPathSelectionConstraint;
 import org.onosproject.net.intent.impl.PathNotFoundException;
-import org.onosproject.net.resource.ResourceQueryService;
 import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.net.resource.ResourceId;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
 import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.PathService;
 import org.onosproject.net.topology.TopologyEdge;
 import org.onosproject.net.topology.TopologyVertex;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Base class for compilers of various
@@ -54,6 +70,11 @@
 
     private static final ProviderId PID = new ProviderId("core", "org.onosproject.core", true);
 
+    private static final Logger log = LoggerFactory.getLogger(ConnectivityIntentCompiler.class);
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected IntentExtensionService intentManager;
 
@@ -61,7 +82,7 @@
     protected PathService pathService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ResourceQueryService resourceService;
+    protected ResourceService resourceService;
 
     /**
      * Returns an edge-weight capable of evaluating links on the basis of the
@@ -164,6 +185,155 @@
     }
 
     /**
+     * Allocates the bandwidth specified as intent constraint on each link
+     * composing the intent, if a bandwidth constraint is specified.
+     *
+     * @param intent the intent requesting bandwidth allocation
+     * @param connectPoints the connect points composing the intent path computed
+     */
+    protected void allocateBandwidth(ConnectivityIntent intent,
+                                     List<ConnectPoint> connectPoints) {
+        // Retrieve bandwidth constraint if exists
+        List<Constraint> constraints = intent.constraints();
+
+        if (constraints == null) {
+            return;
+        }
+
+        Optional<Constraint> constraint =
+                constraints.stream()
+                           .filter(c -> c instanceof BandwidthConstraint)
+                           .findAny();
+
+        // If there is no bandwidth constraint continue
+        if (!constraint.isPresent()) {
+            return;
+        }
+
+        BandwidthConstraint bwConstraint = (BandwidthConstraint) constraint.get();
+
+        double bw = bwConstraint.bandwidth().bps();
+
+        // If a resource group is set on the intent, the resource consumer is
+        // set equal to it. Otherwise it's set to the intent key
+        ResourceConsumer newResourceConsumer =
+                intent.resourceGroup() != null ? intent.resourceGroup() : intent.key();
+
+        // Get the list of current resource allocations
+        Collection<ResourceAllocation> resourceAllocations =
+                resourceService.getResourceAllocations(newResourceConsumer);
+
+        // Get the list of resources already allocated from resource allocations
+        List<Resource> resourcesAllocated =
+                resourcesFromAllocations(resourceAllocations);
+
+        // Get the list of resource ids for resources already allocated
+        List<ResourceId> idsResourcesAllocated = resourceIds(resourcesAllocated);
+
+        // Create the list of incoming resources requested. Exclude resources
+        // already allocated.
+        List<Resource> incomingResources =
+                resources(connectPoints, bw).stream()
+                                            .filter(r -> !resourcesAllocated.contains(r))
+                                            .collect(Collectors.toList());
+
+        if (incomingResources.isEmpty()) {
+            return;
+        }
+
+        // Create the list of resources to be added, meaning their key is not
+        // present in the resources already allocated
+        List<Resource> resourcesToAdd =
+                incomingResources.stream()
+                                 .filter(r -> !idsResourcesAllocated.contains(r.id()))
+                                 .collect(Collectors.toList());
+
+        // Resources to updated are all the new valid resources except the
+        // resources to be added
+        List<Resource> resourcesToUpdate = Lists.newArrayList(incomingResources);
+        resourcesToUpdate.removeAll(resourcesToAdd);
+
+        // If there are no resources to update skip update procedures
+        if (!resourcesToUpdate.isEmpty()) {
+            // Remove old resources that need to be updated
+            // TODO: use transaction updates when available in the resource service
+            List<ResourceAllocation> resourceAllocationsToUpdate =
+                    resourceAllocations.stream()
+                            .filter(rA -> resourceIds(resourcesToUpdate).contains(rA.resource().id()))
+                            .collect(Collectors.toList());
+            log.debug("Releasing bandwidth for intent {}: {} bps", newResourceConsumer, resourcesToUpdate);
+            resourceService.release(resourceAllocationsToUpdate);
+
+            // Update resourcesToAdd with the list of both the new resources and
+            // the resources to update
+            resourcesToAdd.addAll(resourcesToUpdate);
+        }
+
+        // Look also for resources allocated using the intent key and -if any-
+        // remove them
+        if (intent.resourceGroup() != null) {
+            // Get the list of current resource allocations made by intent key
+            Collection<ResourceAllocation> resourceAllocationsByKey =
+                    resourceService.getResourceAllocations(intent.key());
+
+            resourceService.release(Lists.newArrayList(resourceAllocationsByKey));
+        }
+
+        // Allocate resources
+        log.debug("Allocating bandwidth for intent {}: {} bps", newResourceConsumer, resourcesToAdd);
+        List<ResourceAllocation> allocations =
+                resourceService.allocate(newResourceConsumer, resourcesToAdd);
+
+        if (allocations.isEmpty()) {
+            log.debug("No resources allocated for intent {}", newResourceConsumer);
+        }
+
+        log.debug("Done allocating bandwidth for intent {}", newResourceConsumer);
+    }
+
+    /**
+     * Produces a list of resources from a list of resource allocations.
+     *
+     * @param rAs the list of resource allocations
+     * @return a list of resources retrieved from the resource allocations given
+     */
+    private static List<Resource> resourcesFromAllocations(Collection<ResourceAllocation> rAs) {
+        return rAs.stream()
+                  .map(ResourceAllocation::resource)
+                  .collect(Collectors.toList());
+    }
+
+    /**
+     * Creates a list of continuous bandwidth resources given a list of connect
+     * points and a bandwidth.
+     *
+     * @param cps the list of connect points
+     * @param bw the bandwidth expressed as a double
+     * @return the list of resources
+     */
+    private static List<Resource> resources(List<ConnectPoint> cps, double bw) {
+        return cps.stream()
+                  // Make sure the element id is a valid device id
+                  .filter(cp -> cp.elementId() instanceof DeviceId)
+                  // Create a continuous resource for each CP we're going through
+                  .map(cp -> Resources.continuous(cp.deviceId(), cp.port(),
+                                                  Bandwidth.class).resource(bw))
+                  .collect(Collectors.toList());
+    }
+
+    /**
+     * Returns a list of resource ids given a list of resources.
+     *
+     * @param resources the list of resources
+     * @return the list of resource ids retrieved from the resources given
+     */
+    private static List<ResourceId> resourceIds(List<Resource> resources) {
+        return resources.stream()
+                        .map(Resource::id)
+                        .collect(Collectors.toList());
+    }
+
+    /**
      * Edge-weight capable of evaluating link cost using a set of constraints.
      */
     protected class ConstraintBasedLinkWeigher extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
index f2283a0..4d6270a 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
@@ -22,6 +22,7 @@
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultLink;
 import org.onosproject.net.DefaultPath;
 import org.onosproject.net.DeviceId;
@@ -35,7 +36,6 @@
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentCompilationException;
 import org.onosproject.net.intent.LinkCollectionIntent;
-import org.onosproject.net.intent.PathIntent;
 import org.onosproject.net.intent.constraint.AsymmetricPathConstraint;
 import org.slf4j.Logger;
 
@@ -45,6 +45,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static org.onosproject.net.Link.Type.EDGE;
 import static org.onosproject.net.flow.DefaultTrafficSelector.builder;
@@ -115,22 +116,6 @@
                 .build();
     }
 
-    // Creates a path intent from the specified path and original connectivity intent.
-    private Intent createPathIntent(Path path, Host src, Host dst,
-                                    HostToHostIntent intent) {
-        TrafficSelector selector = builder(intent.selector())
-                .matchEthSrc(src.mac()).matchEthDst(dst.mac()).build();
-        return PathIntent.builder()
-                .appId(intent.appId())
-                .key(intent.key())
-                .selector(selector)
-                .treatment(intent.treatment())
-                .path(path)
-                .constraints(intent.constraints())
-                .priority(intent.priority())
-                .build();
-    }
-
     private FilteredConnectPoint getFilteredPointFromLink(Link link) {
         FilteredConnectPoint filteredConnectPoint;
         if (link.src().elementId() instanceof DeviceId) {
@@ -147,14 +132,13 @@
                                              Host src,
                                              Host dst,
                                              HostToHostIntent intent) {
-        /*
-         * The path contains also the edge links, these are not necessary
-         * for the LinkCollectionIntent.
-         */
-        Set<Link> coreLinks = path.links()
-                .stream()
-                .filter(link -> !link.type().equals(EDGE))
-                .collect(Collectors.toSet());
+        // Try to allocate bandwidth
+        List<ConnectPoint> pathCPs =
+                path.links().stream()
+                            .flatMap(l -> Stream.of(l.src(), l.dst()))
+                            .collect(Collectors.toList());
+
+        allocateBandwidth(intent, pathCPs);
 
         Link ingressLink = path.links().get(0);
         Link egressLink = path.links().get(path.links().size() - 1);
@@ -167,6 +151,15 @@
                 .matchEthDst(dst.mac())
                 .build();
 
+        /*
+         * The path contains also the edge links, these are not necessary
+         * for the LinkCollectionIntent.
+         */
+        Set<Link> coreLinks = path.links()
+                .stream()
+                .filter(link -> !link.type().equals(EDGE))
+                .collect(Collectors.toSet());
+
         return LinkCollectionIntent.builder()
                 .key(intent.key())
                 .appId(intent.appId())
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
index 3b4dca9..7e6cf3d 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
@@ -38,6 +38,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
 
@@ -85,7 +87,7 @@
                 continue;
             }
 
-            Path path = getPath(intent, ingressPoint.deviceId(), intent.egressPoint().deviceId());
+            Path path = getPath(intent, ingressPoint.deviceId(), egressPoint.deviceId());
 
             if (path != null) {
                 hasPaths = true;
@@ -106,6 +108,23 @@
             }
         }
 
+        // Allocate bandwidth on existing paths if a bandwidth constraint is set
+        List<ConnectPoint> ingressCPs =
+                intent.filteredIngressPoints().stream()
+                                              .map(fcp -> fcp.connectPoint())
+                                              .collect(Collectors.toList());
+        ConnectPoint egressCP = intent.filteredEgressPoint().connectPoint();
+
+        List<ConnectPoint> pathCPs =
+                links.values().stream()
+                              .flatMap(l -> Stream.of(l.src(), l.dst()))
+                              .collect(Collectors.toList());
+
+        pathCPs.addAll(ingressCPs);
+        pathCPs.add(egressCP);
+
+        allocateBandwidth(intent, pathCPs);
+
         if (!hasPaths) {
             throw new IntentException("Cannot find any path between ingress and egress points.");
         } else if (!allowMissingPaths && missingSomePaths) {
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
index 94fe6ed..10e24eb 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
@@ -73,6 +73,8 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static java.util.Arrays.asList;
 import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
@@ -122,8 +124,8 @@
     @Override
     public List<Intent> compile(PointToPointIntent intent, List<Intent> installable) {
         log.trace("compiling {} {}", intent, installable);
-        ConnectPoint ingressPoint = intent.ingressPoint();
-        ConnectPoint egressPoint = intent.egressPoint();
+        ConnectPoint ingressPoint = intent.filteredIngressPoint().connectPoint();
+        ConnectPoint egressPoint = intent.filteredEgressPoint().connectPoint();
 
         if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
             return createZeroHopLinkCollectionIntent(intent);
@@ -157,6 +159,15 @@
                                        intent));
     }
 
+    /**
+     * Creates an unprotected intent.
+     * @param ingressPoint the ingress connect point
+     * @param egressPoint the egress connect point
+     * @param intent the original intent
+     * @return the compilation result
+     * @deprecated 1.10.0
+     */
+    @Deprecated
     private List<Intent> createUnprotectedIntent(ConnectPoint ingressPoint,
                                                  ConnectPoint egressPoint,
                                                  PointToPointIntent intent) {
@@ -177,6 +188,20 @@
         Path path = getPathOrException(intent, intent.filteredIngressPoint().connectPoint().deviceId(),
                                        intent.filteredEgressPoint().connectPoint().deviceId());
 
+        // Allocate bandwidth if a bandwidth constraint is set
+        ConnectPoint ingressCP = intent.filteredIngressPoint().connectPoint();
+        ConnectPoint egressCP = intent.filteredEgressPoint().connectPoint();
+
+        List<ConnectPoint> pathCPs =
+                path.links().stream()
+                            .flatMap(l -> Stream.of(l.src(), l.dst()))
+                            .collect(Collectors.toList());
+
+        pathCPs.add(ingressCP);
+        pathCPs.add(egressCP);
+
+        allocateBandwidth(intent, pathCPs);
+
         return asList(createLinkCollectionIntent(ImmutableSet.copyOf(path.links()),
                                                  path.cost(),
                                                  intent));
@@ -292,6 +317,21 @@
         if (reusableIntents != null && reusableIntents.size() > 1) {
             return reusableIntents;
         } else {
+            // Allocate bandwidth if a bandwidth constraint is set
+            ConnectPoint ingressCP = intent.filteredIngressPoint().connectPoint();
+            ConnectPoint egressCP = intent.filteredEgressPoint().connectPoint();
+
+            List<ConnectPoint> pathCPs =
+                    onlyPath.links().stream()
+                            .flatMap(l -> Stream.of(l.src(), l.dst()))
+                            .collect(Collectors.toList());
+
+            pathCPs.add(ingressCP);
+            pathCPs.add(egressCP);
+
+            // Allocate bandwidth if a bandwidth constraint is set
+            allocateBandwidth(intent, pathCPs);
+
             links.add(createEdgeLink(ingressPoint, true));
             links.addAll(onlyPath.links());
             links.add(createEdgeLink(egressPoint, false));
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
index 504e4f3..369e52b 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
@@ -34,6 +34,8 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
 
@@ -76,6 +78,7 @@
             }
 
             Path path = getPath(intent, intent.ingressPoint().deviceId(), egressPoint.deviceId());
+
             if (path != null) {
                 hasPaths = true;
                 links.addAll(path.links());
@@ -84,6 +87,23 @@
             }
         }
 
+        // Allocate bandwidth if a bandwidth constraint is set
+        ConnectPoint ingressCP = intent.filteredIngressPoint().connectPoint();
+        List<ConnectPoint> egressCPs =
+                intent.filteredEgressPoints().stream()
+                        .map(fcp -> fcp.connectPoint())
+                        .collect(Collectors.toList());
+
+        List<ConnectPoint> pathCPs =
+                links.stream()
+                     .flatMap(l -> Stream.of(l.src(), l.dst()))
+                     .collect(Collectors.toList());
+
+        pathCPs.add(ingressCP);
+        pathCPs.addAll(egressCPs);
+
+        allocateBandwidth(intent, pathCPs);
+
         if (!hasPaths) {
             throw new IntentException("Cannot find any path between ingress and egress points.");
         } else if (!allowMissingPaths && missingSomePaths) {
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompilerTest.java
index d6333ff..a0104a1 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompilerTest.java
@@ -16,27 +16,40 @@
 package org.onosproject.net.intent.impl.compiler;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
 import org.hamcrest.Matchers;
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
 import org.onosproject.TestApplicationId;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.FilteredConnectPoint;
 import org.onosproject.net.Host;
 import org.onosproject.net.HostId;
 import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.host.HostService;
 import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.net.intent.Constraint;
 import org.onosproject.net.intent.HostToHostIntent;
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.Key;
 import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.resource.ContinuousResource;
 import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -44,10 +57,8 @@
 import static org.easymock.EasyMock.*;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.everyItem;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.is;
-import static org.onosproject.net.NetTestTools.connectPoint;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertEquals;
 import static org.onosproject.net.NetTestTools.hid;
 import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
 
@@ -55,6 +66,8 @@
  * Unit tests for the HostToHost intent compiler.
  */
 public class HostToHostIntentCompilerTest extends AbstractIntentTest {
+    private static final ApplicationId APPID = new TestApplicationId("foo");
+
     private static final String HOST_ONE_MAC = "00:00:00:00:00:01";
     private static final String HOST_TWO_MAC = "00:00:00:00:00:02";
     private static final String HOST_ONE_VLAN = "None";
@@ -62,24 +75,29 @@
     private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
     private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
 
-    private static final int PORT_1 = 1;
+    private static final String S1 = "s1";
+    private static final String S2 = "s2";
+    private static final String S3 = "s3";
+    private static final String S4 = "s4";
+    private static final String S5 = "s5";
+    private static final String S6 = "s6";
+    private static final String S7 = "s7";
+    private static final String S8 = "s8";
 
-    private static final String HOP_1 = "h1";
-    private static final String HOP_2 = "h2";
-    private static final String HOP_3 = "h3";
-    private static final String HOP_4 = "h4";
-    private static final String HOP_5 = "h5";
-    private static final String HOP_6 = "h6";
-    private static final String HOP_7 = "h7";
-    private static final String HOP_8 = "h8";
+    private static final DeviceId DID_S1 = DeviceId.deviceId("of:" + S1);
+    private static final DeviceId DID_S2 = DeviceId.deviceId("of:" + S2);
+    private static final DeviceId DID_S3 = DeviceId.deviceId("of:" + S3);
+    private static final DeviceId DID_S8 = DeviceId.deviceId("of:" + S8);
 
-    private static final ApplicationId APPID = new TestApplicationId("foo");
+    private static final PortNumber PORT_1 = PortNumber.portNumber(1);
+    private static final PortNumber PORT_2 =  PortNumber.portNumber(2);
 
     private TrafficSelector selector = new IntentTestsMocks.MockSelector();
     private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
 
     private HostId hostOneId = HostId.hostId(HOST_ONE);
     private HostId hostTwoId = HostId.hostId(HOST_TWO);
+
     private HostService mockHostService;
 
     @Override
@@ -105,17 +123,34 @@
     /**
      * Creates a HostToHost intent based on two host Ids.
      *
-     * @param oneIdString string for host one id
-     * @param twoIdString string for host two id
+     * @param oneIdString the string for host one id
+     * @param twoIdString the string for host two id
      * @return HostToHostIntent for the two hosts
      */
-    private HostToHostIntent makeIntent(String oneIdString, String twoIdString) {
+    private HostToHostIntent makeIntent(String oneIdString,
+                                        String twoIdString) {
+        return makeIntent(oneIdString, twoIdString, Lists.newArrayList());
+    }
+
+    /**
+     * Creates a HostToHost intent based on two host Ids and a list of
+     * constraints.
+     *
+     * @param oneIdString the string for host one id
+     * @param twoIdString the string for host two id
+     * @param constraints the intent constraints
+     * @return HostToHostIntent for the two hosts
+     */
+    private HostToHostIntent makeIntent(String oneIdString,
+                                        String twoIdString,
+                                        List<Constraint> constraints) {
         return HostToHostIntent.builder()
                 .appId(APPID)
                 .one(hid(oneIdString))
                 .two(hid(twoIdString))
                 .selector(selector)
                 .treatment(treatment)
+                .constraints(constraints)
                 .build();
     }
 
@@ -126,11 +161,29 @@
      * @return HostToHost intent compiler
      */
     private HostToHostIntentCompiler makeCompiler(String[] hops) {
+        return makeCompiler(hops, null);
+    }
+
+    /**
+     * Creates a compiler for HostToHost intents.
+     *
+     * @param hops string array describing the path hops to use when compiling
+     * @param resourceService the resource service
+     * @return HostToHost intent compiler
+     */
+    private HostToHostIntentCompiler makeCompiler(String[] hops,
+                                                  ResourceService resourceService) {
         HostToHostIntentCompiler compiler =
                 new HostToHostIntentCompiler();
         compiler.pathService = new IntentTestsMocks.MockPathService(hops);
         compiler.hostService = mockHostService;
-        compiler.resourceService = new MockResourceService();
+
+        if (resourceService == null) {
+            compiler.resourceService = new MockResourceService();
+        } else {
+            compiler.resourceService = resourceService;
+        }
+
         return compiler;
     }
 
@@ -145,7 +198,7 @@
                                              HOST_TWO);
         assertThat(intent, is(notNullValue()));
 
-        String[] hops = {HOST_ONE, HOP_1, HOP_2, HOP_3, HOP_4, HOP_5, HOP_6, HOP_7, HOP_8, HOST_TWO};
+        String[] hops = {HOST_ONE, S1, S2, S3, S4, S5, S6, S7, S8, HOST_TWO};
         HostToHostIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
 
@@ -161,34 +214,34 @@
         Set<Link> links = forwardLCIntent.links();
         assertThat(links, hasSize(7));
         Set<FilteredConnectPoint> ingressPoints = ImmutableSet.of(
-                new FilteredConnectPoint(connectPoint(HOP_1, PORT_1))
+                new FilteredConnectPoint(new ConnectPoint(DID_S1, PORT_1))
         );
         assertThat(forwardLCIntent.filteredIngressPoints(), is(ingressPoints));
-        assertThat(links, linksHasPath(HOP_1, HOP_2));
-        assertThat(links, linksHasPath(HOP_2, HOP_3));
-        assertThat(links, linksHasPath(HOP_3, HOP_4));
-        assertThat(links, linksHasPath(HOP_4, HOP_5));
-        assertThat(links, linksHasPath(HOP_5, HOP_6));
-        assertThat(links, linksHasPath(HOP_6, HOP_7));
-        assertThat(links, linksHasPath(HOP_7, HOP_8));
+        assertThat(links, linksHasPath(S1, S2));
+        assertThat(links, linksHasPath(S2, S3));
+        assertThat(links, linksHasPath(S3, S4));
+        assertThat(links, linksHasPath(S4, S5));
+        assertThat(links, linksHasPath(S5, S6));
+        assertThat(links, linksHasPath(S6, S7));
+        assertThat(links, linksHasPath(S7, S8));
         Set<FilteredConnectPoint> egressPoints = ImmutableSet.of(
-                new FilteredConnectPoint(connectPoint(HOP_8, PORT_1))
+                new FilteredConnectPoint(new ConnectPoint(DID_S8, PORT_2))
         );
         assertThat(forwardLCIntent.filteredEgressPoints(), is(egressPoints));
 
         LinkCollectionIntent reverseLCIntent = (LinkCollectionIntent) reverseIntent;
         links = reverseLCIntent.links();
         assertThat(reverseLCIntent.links(), hasSize(7));
-        ingressPoints = ImmutableSet.of(new FilteredConnectPoint(connectPoint(HOP_8, PORT_1)));
+        ingressPoints = ImmutableSet.of(new FilteredConnectPoint(new ConnectPoint(DID_S8, PORT_2)));
         assertThat(reverseLCIntent.filteredIngressPoints(), is(ingressPoints));
-        assertThat(links, linksHasPath(HOP_2, HOP_1));
-        assertThat(links, linksHasPath(HOP_3, HOP_2));
-        assertThat(links, linksHasPath(HOP_4, HOP_3));
-        assertThat(links, linksHasPath(HOP_5, HOP_4));
-        assertThat(links, linksHasPath(HOP_6, HOP_5));
-        assertThat(links, linksHasPath(HOP_7, HOP_6));
-        assertThat(links, linksHasPath(HOP_8, HOP_7));
-        egressPoints = ImmutableSet.of(new FilteredConnectPoint(connectPoint(HOP_1, PORT_1)));
+        assertThat(links, linksHasPath(S2, S1));
+        assertThat(links, linksHasPath(S3, S2));
+        assertThat(links, linksHasPath(S4, S3));
+        assertThat(links, linksHasPath(S5, S4));
+        assertThat(links, linksHasPath(S6, S5));
+        assertThat(links, linksHasPath(S7, S6));
+        assertThat(links, linksHasPath(S8, S7));
+        egressPoints = ImmutableSet.of(new FilteredConnectPoint(new ConnectPoint(DID_S1, PORT_1)));
         assertThat(reverseLCIntent.filteredEgressPoints(), is(egressPoints));
 
 
@@ -196,4 +249,63 @@
                    result.stream().map(Intent::key).collect(Collectors.toList()),
                    everyItem(is(intent.key())));
     }
+
+    /**
+     * Tests if bandwidth resources get allocated correctly.
+     */
+    @Test
+    public void testBandwidthConstrainedIntentAllocation() {
+        final double bpsTotal = 1000.0;
+        final double bpsToReserve = 100.0;
+
+        ContinuousResource resourceSw1P1 =
+                Resources.continuous(DID_S1, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw1P2 =
+                Resources.continuous(DID_S1, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw2P1 =
+                Resources.continuous(DID_S2, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw2P2 =
+                Resources.continuous(DID_S2, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw3P1 =
+                Resources.continuous(DID_S3, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw3P2 =
+                Resources.continuous(DID_S3, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+
+        String[] hops = {HOST_ONE, S1, S2, S3, HOST_TWO};
+
+        final ResourceService resourceService =
+                MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+        final List<Constraint> constraints =
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(bpsToReserve)));
+
+        final HostToHostIntent intent = makeIntent(HOST_ONE, HOST_TWO, constraints);
+
+        HostToHostIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+        compiler.compile(intent, null);
+
+        Key intentKey = intent.key();
+
+        ResourceAllocation rAOne = new ResourceAllocation(resourceSw1P1, intentKey);
+        ResourceAllocation rATwo = new ResourceAllocation(resourceSw1P2, intentKey);
+        ResourceAllocation rAThree = new ResourceAllocation(resourceSw2P1, intentKey);
+        ResourceAllocation rAFour = new ResourceAllocation(resourceSw2P2, intentKey);
+        ResourceAllocation rAFive = new ResourceAllocation(resourceSw3P1, intentKey);
+        ResourceAllocation rASix = new ResourceAllocation(resourceSw3P2, intentKey);
+
+        Set<ResourceAllocation> expectedresourceAllocations =
+                ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+        Set<ResourceAllocation> resourceAllocations =
+                ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+        assertThat(resourceAllocations, hasSize(6));
+        assertEquals(expectedresourceAllocations, resourceAllocations);
+    }
 }
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
index 2eb4d9f..6c7d9c1 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
@@ -16,24 +16,42 @@
 package org.onosproject.net.intent.impl.compiler;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import org.hamcrest.Matchers;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
 import org.onosproject.TestApplicationId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.net.intent.Constraint;
 import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentException;
 import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.Key;
 import org.onosproject.net.intent.LinkCollectionIntent;
 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.PartialFailureConstraint;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
+import org.onosproject.net.topology.PathService;
 
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
@@ -42,7 +60,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
-import static org.onosproject.net.NetTestTools.connectPoint;
+import static org.junit.Assert.assertEquals;
 import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
 
 /**
@@ -52,6 +70,26 @@
 
     private static final ApplicationId APPID = new TestApplicationId("foo");
 
+    private static final String S1 = "s1";
+    private static final String S2 = "s2";
+    private static final String S3 = "s3";
+    private static final String S4 = "s4";
+    private static final String S5 = "s5";
+    private static final String S6 = "s6";
+    private static final String S7 = "s7";
+    private static final String S8 = "s8";
+
+    private static final DeviceId DID_1 = DeviceId.deviceId("of:" + S1);
+    private static final DeviceId DID_2 = DeviceId.deviceId("of:" + S2);
+    private static final DeviceId DID_3 = DeviceId.deviceId("of:" + S3);
+    private static final DeviceId DID_4 = DeviceId.deviceId("of:" + S4);
+    private static final DeviceId DID_5 = DeviceId.deviceId("of:" + S5);
+    private static final DeviceId DID_8 = DeviceId.deviceId("of:" + S8);
+
+    private static final PortNumber PORT_1 = PortNumber.portNumber(1);
+    private static final PortNumber PORT_2 =  PortNumber.portNumber(2);
+    private static final PortNumber PORT_3 =  PortNumber.portNumber(3);
+
     private TrafficSelector selector = new IntentTestsMocks.MockSelector();
     private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
 
@@ -59,43 +97,65 @@
      * Creates a MultiPointToSinglePoint intent for a group of ingress points
      * and an egress point.
      *
-     * @param ingressIds array of ingress device ids
-     * @param egressId   device id of the egress point
-     * @return MultiPointToSinglePoint intent
+     * @param ingress the filtered ingress points
+     * @param egress  the filtered egress point
+     * @return a MultiPointToSinglePoint intent
      */
-    private MultiPointToSinglePointIntent makeIntent(String[] ingressIds, String egressId) {
-        Set<ConnectPoint> ingressPoints = new HashSet<>();
-        ConnectPoint egressPoint = connectPoint(egressId, 2);
-
-        for (String ingressId : ingressIds) {
-            ingressPoints.add(connectPoint(ingressId, 1));
-        }
-
-        return MultiPointToSinglePointIntent.builder()
-                .appId(APPID)
-                .selector(selector)
-                .treatment(treatment)
-                .ingressPoints(ingressPoints)
-                .egressPoint(egressPoint)
-                .build();
+    private MultiPointToSinglePointIntent makeIntent(Set<FilteredConnectPoint> ingress,
+                                                     FilteredConnectPoint egress) {
+        return makeIntent(ingress, egress, Lists.newArrayList());
     }
 
     /**
-     * Generate MultiPointToSinglePointIntent with filtered connection point.
+     * Generates a MultiPointToSinglePointIntent with filtered connection point.
      *
      * @param ingress filtered ingress points
      * @param egress filtered egress point
      * @return
      */
-    private MultiPointToSinglePointIntent makeFilteredConnectPointIntent(Set<FilteredConnectPoint> ingress,
-                                                                         FilteredConnectPoint egress,
-                                                                         TrafficSelector trafficSelector) {
+    private MultiPointToSinglePointIntent makeIntent(Set<FilteredConnectPoint> ingress,
+                                                     FilteredConnectPoint egress,
+                                                     TrafficSelector trafficSelector) {
+        return makeIntent(ingress,
+                          egress,
+                          trafficSelector,
+                          Lists.newArrayList());
+    }
+
+    /**
+     * Creates a MultiPointToSinglePoint intent for a group of ingress points,
+     * egress points and a list of constraints.
+     *
+     * @param ingress the filtered ingress point
+     * @param egress the filtered egress point
+     * @param constraints the list of intent constraints
+     * @return a MultiPointToSinglePoint intent
+     */
+    private MultiPointToSinglePointIntent makeIntent(Set<FilteredConnectPoint> ingress,
+                                                     FilteredConnectPoint egress,
+                                                     List<Constraint> constraints) {
+        return makeIntent(ingress, egress, selector, constraints);
+    }
+
+    /**
+     * Generates a MultiPointToSinglePointIntent with filtered connection point.
+     *
+     * @param ingress filtered ingress points
+     * @param egress filtered egress point
+     * @param constraints the list of intent constraints
+     * @return
+     */
+    private MultiPointToSinglePointIntent makeIntent(Set<FilteredConnectPoint> ingress,
+                                                     FilteredConnectPoint egress,
+                                                     TrafficSelector trafficSelector,
+                                                     List<Constraint> constraints) {
         return MultiPointToSinglePointIntent.builder()
                 .appId(APPID)
                 .treatment(treatment)
                 .selector(trafficSelector)
                 .filteredIngressPoints(ingress)
                 .filteredEgressPoint(egress)
+                .constraints(constraints)
                 .build();
     }
 
@@ -103,14 +163,41 @@
      * Creates a compiler for MultiPointToSinglePoint intents.
      *
      * @param hops hops to use while computing paths for this intent
+     * @param pathService the path service
+     * @param resourceService the resource service
+     * @return MultiPointToSinglePoint intent
+     */
+    private MultiPointToSinglePointIntentCompiler makeCompiler(String[] hops,
+                                                               PathService pathService,
+                                                               ResourceService resourceService) {
+        MultiPointToSinglePointIntentCompiler compiler =
+                new MultiPointToSinglePointIntentCompiler();
+
+        compiler.deviceService = new IntentTestsMocks.MockDeviceService();
+
+        if (pathService == null) {
+            compiler.pathService = new IntentTestsMocks.Mp2MpMockPathService(hops);
+        } else {
+            compiler.pathService = pathService;
+        }
+
+        if (resourceService == null) {
+            compiler.resourceService = new MockResourceService();
+        } else {
+            compiler.resourceService = resourceService;
+        }
+
+        return compiler;
+    }
+
+    /**
+     * Creates a compiler for MultiPointToSinglePoint intents.
+     *
+     * @param hops hops to use while computing paths for this intent
      * @return MultiPointToSinglePoint intent
      */
     private MultiPointToSinglePointIntentCompiler makeCompiler(String[] hops) {
-        MultiPointToSinglePointIntentCompiler compiler =
-                new MultiPointToSinglePointIntentCompiler();
-        compiler.pathService = new IntentTestsMocks.Mp2MpMockPathService(hops);
-        compiler.deviceService = new IntentTestsMocks.MockDeviceService();
-        return compiler;
+        return makeCompiler(hops, null, null);
     }
 
     /**
@@ -118,14 +205,15 @@
      */
     @Test
     public void testSingleLongPathCompilation() {
-
-        String[] ingress = {"ingress"};
-        String egress = "egress";
+        Set<FilteredConnectPoint> ingress =
+                Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)));
+        FilteredConnectPoint egress =
+                new FilteredConnectPoint(new ConnectPoint(DID_8, PORT_1));
 
         MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
         assertThat(intent, is(notNullValue()));
 
-        String[] hops = {"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8"};
+        String[] hops = {S2, S3, S4, S5, S6, S7};
         MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
 
@@ -137,14 +225,14 @@
 
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
-            assertThat(linkIntent.links(), hasSize(9));
-            assertThat(linkIntent.links(), linksHasPath("ingress", "h1"));
-            assertThat(linkIntent.links(), linksHasPath("h1", "h2"));
-            assertThat(linkIntent.links(), linksHasPath("h2", "h3"));
-            assertThat(linkIntent.links(), linksHasPath("h4", "h5"));
-            assertThat(linkIntent.links(), linksHasPath("h5", "h6"));
-            assertThat(linkIntent.links(), linksHasPath("h7", "h8"));
-            assertThat(linkIntent.links(), linksHasPath("h8", "egress"));
+            assertThat(linkIntent.links(), hasSize(7));
+            assertThat(linkIntent.links(), linksHasPath(S1, S2));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
+            assertThat(linkIntent.links(), linksHasPath(S4, S5));
+            assertThat(linkIntent.links(), linksHasPath(S5, S6));
+            assertThat(linkIntent.links(), linksHasPath(S6, S7));
+            assertThat(linkIntent.links(), linksHasPath(S7, S8));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
     }
@@ -155,13 +243,52 @@
      */
     @Test
     public void testTwoIngressCompilation() {
-        String[] ingress = {"ingress1", "ingress2"};
-        String egress = "egress";
+        Set<FilteredConnectPoint> ingress =
+                Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+                                new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1)));
+        FilteredConnectPoint egress =
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_1));
 
         MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
         assertThat(intent, is(notNullValue()));
 
-        final String[] hops = {"inner1", "inner2"};
+        final String[] hops = {S3};
+        MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
+        assertThat(compiler, is(notNullValue()));
+
+        List<Intent> result = compiler.compile(intent, null);
+        assertThat(result, is(notNullValue()));
+        assertThat(result, hasSize(1));
+        Intent resultIntent = result.get(0);
+        assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
+
+        if (resultIntent instanceof LinkCollectionIntent) {
+            LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+            assertThat(linkIntent.links(), hasSize(3));
+            assertThat(linkIntent.links(), linksHasPath(S1, S3));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
+        }
+        assertThat("key is inherited", resultIntent.key(), is(intent.key()));
+    }
+
+    /**
+     * Tests a large number of ingress points that share a common path to the
+     * egress point.
+     */
+    @Test
+    public void testMultiIngressCompilation() {
+        Set<FilteredConnectPoint> ingress =
+                Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+                                new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1)),
+                                new FilteredConnectPoint(new ConnectPoint(DID_3, PORT_1)));
+        FilteredConnectPoint egress =
+                new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_1));
+
+        MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
+        assertThat(intent, is(notNullValue()));
+
+        final String[] hops = {S4};
         MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
 
@@ -174,46 +301,10 @@
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
             assertThat(linkIntent.links(), hasSize(4));
-            assertThat(linkIntent.links(), linksHasPath("ingress1", "inner1"));
-            assertThat(linkIntent.links(), linksHasPath("ingress2", "inner1"));
-            assertThat(linkIntent.links(), linksHasPath("inner1", "inner2"));
-            assertThat(linkIntent.links(), linksHasPath("inner2", "egress"));
-        }
-        assertThat("key is inherited", resultIntent.key(), is(intent.key()));
-    }
-
-    /**
-     * Tests a large number of ingress points that share a common path to the
-     * egress point.
-     */
-    @Test
-    public void testMultiIngressCompilation() {
-        String[] ingress = {"i1", "i2", "i3", "i4", "i5",
-                "i6", "i7", "i8", "i9", "i10"};
-        String egress = "e";
-
-        MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
-        assertThat(intent, is(notNullValue()));
-
-        final String[] hops = {"n1"};
-        MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
-        assertThat(compiler, is(notNullValue()));
-
-        List<Intent> result = compiler.compile(intent, null);
-        assertThat(result, is(notNullValue()));
-        assertThat(result, hasSize(1));
-        Intent resultIntent = result.get(0);
-        assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
-
-        if (resultIntent instanceof LinkCollectionIntent) {
-            LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
-            assertThat(linkIntent.links(), hasSize(ingress.length + 1));
-            for (String ingressToCheck : ingress) {
-                assertThat(linkIntent.links(),
-                           linksHasPath(ingressToCheck,
-                                        "n1"));
-            }
-            assertThat(linkIntent.links(), linksHasPath("n1", egress));
+            assertThat(linkIntent.links(), linksHasPath(S1, S4));
+            assertThat(linkIntent.links(), linksHasPath(S2, S4));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
+            assertThat(linkIntent.links(), linksHasPath(S4, S5));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
     }
@@ -223,8 +314,11 @@
      */
     @Test
     public void testSameDeviceCompilation() {
-        String[] ingress = {"i1", "i2"};
-        String egress = "i3";
+        Set<FilteredConnectPoint> ingress =
+                Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+                                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_2)));
+        FilteredConnectPoint egress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_3));
 
         MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
         assertThat(intent, is(notNullValue()));
@@ -241,10 +335,7 @@
 
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
-            assertThat(linkIntent.links(), hasSize(ingress.length));
-
-            assertThat(linkIntent.links(), linksHasPath("i1", "i3"));
-            assertThat(linkIntent.links(), linksHasPath("i2", "i3"));
+            assertThat(linkIntent.links(), hasSize(0));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
     }
@@ -256,16 +347,16 @@
     public void testFilteredConnectPointIntent() {
 
         Set<FilteredConnectPoint> ingress = ImmutableSet.of(
-                new FilteredConnectPoint(connectPoint("of1", 1),
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1),
                                          DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
-                new FilteredConnectPoint(connectPoint("of2", 1),
+                new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1),
                                          DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("200")).build())
         );
 
-        FilteredConnectPoint egress = new FilteredConnectPoint(connectPoint("of4", 1));
+        FilteredConnectPoint egress = new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
 
-        MultiPointToSinglePointIntent intent = makeFilteredConnectPointIntent(ingress, egress, selector);
-        String[] hops = {"of3"};
+        MultiPointToSinglePointIntent intent = makeIntent(ingress, egress, selector);
+        String[] hops = {S3};
 
         MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
@@ -280,9 +371,9 @@
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
             assertThat(linkIntent.links(), hasSize(3));
-            assertThat(linkIntent.links(), linksHasPath("of1", "of3"));
-            assertThat(linkIntent.links(), linksHasPath("of2", "of3"));
-            assertThat(linkIntent.links(), linksHasPath("of3", "of4"));
+            assertThat(linkIntent.links(), linksHasPath(S1, S3));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
 
@@ -294,20 +385,22 @@
     @Test
     public void testNonTrivialSelectorsIntent() {
         Set<FilteredConnectPoint> ingress = ImmutableSet.of(
-                new FilteredConnectPoint(connectPoint("of1", 1),
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1),
                                          DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
-                new FilteredConnectPoint(connectPoint("of2", 1),
+                new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1),
                                          DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("200")).build())
         );
 
+        FilteredConnectPoint egress =
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+
         TrafficSelector ipPrefixSelector = DefaultTrafficSelector.builder()
                 .matchIPDst(IpPrefix.valueOf("192.168.100.0/24"))
                 .build();
 
-        FilteredConnectPoint egress = new FilteredConnectPoint(connectPoint("of4", 1));
 
-        MultiPointToSinglePointIntent intent = makeFilteredConnectPointIntent(ingress, egress, ipPrefixSelector);
-        String[] hops = {"of3"};
+        MultiPointToSinglePointIntent intent = makeIntent(ingress, egress, ipPrefixSelector);
+        String[] hops = {S3};
 
         MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
@@ -322,14 +415,177 @@
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
             assertThat(linkIntent.links(), hasSize(3));
-            assertThat(linkIntent.links(), linksHasPath("of1", "of3"));
-            assertThat(linkIntent.links(), linksHasPath("of2", "of3"));
-            assertThat(linkIntent.links(), linksHasPath("of3", "of4"));
+            assertThat(linkIntent.links(), linksHasPath(S1, S3));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
             assertThat(linkIntent.selector(), is(ipPrefixSelector));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
-
     }
 
+    /**
+     * Tests if bandwidth resources get allocated correctly.
+     */
+    @Test
+    public void testBandwidthConstrainedIntentAllocation() {
+        final double bpsTotal = 1000.0;
+        final double bpsToReserve = 100.0;
 
+        ContinuousResource resourceSw1P1 =
+                Resources.continuous(DID_1, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw1P2 =
+                Resources.continuous(DID_1, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw2P1 =
+                Resources.continuous(DID_2, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw2P2 =
+                Resources.continuous(DID_2, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw3P1 =
+                Resources.continuous(DID_3, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw3P2 =
+                Resources.continuous(DID_3, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw3P3 =
+                Resources.continuous(DID_3, PORT_3, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw4P1 =
+                Resources.continuous(DID_4, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw4P2 =
+                Resources.continuous(DID_4, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+
+        String[] hops = {DID_3.toString()};
+
+        final ResourceService resourceService =
+                MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+        final List<Constraint> constraints =
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(bpsToReserve)));
+
+        Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+                new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1)));
+
+        TrafficSelector ipPrefixSelector = DefaultTrafficSelector.builder()
+                .matchIPDst(IpPrefix.valueOf("192.168.100.0/24"))
+                .build();
+
+        FilteredConnectPoint egress = new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+
+        MultiPointToSinglePointIntent intent =
+                makeIntent(ingress, egress, ipPrefixSelector, constraints);
+
+        MultiPointToSinglePointIntentCompiler compiler =
+                makeCompiler(null,
+                             new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+                             resourceService);
+
+        compiler.compile(intent, null);
+
+        Key intentKey = intent.key();
+
+        ResourceAllocation rA1 = new ResourceAllocation(resourceSw1P1, intentKey);
+        ResourceAllocation rA2 = new ResourceAllocation(resourceSw1P2, intentKey);
+        ResourceAllocation rA3 = new ResourceAllocation(resourceSw2P1, intentKey);
+        ResourceAllocation rA4 = new ResourceAllocation(resourceSw2P2, intentKey);
+        ResourceAllocation rA5 = new ResourceAllocation(resourceSw3P1, intentKey);
+        ResourceAllocation rA6 = new ResourceAllocation(resourceSw3P2, intentKey);
+        ResourceAllocation rA7 = new ResourceAllocation(resourceSw3P3, intentKey);
+        ResourceAllocation rA8 = new ResourceAllocation(resourceSw4P1, intentKey);
+        ResourceAllocation rA9 = new ResourceAllocation(resourceSw4P2, intentKey);
+
+        Set<ResourceAllocation> expectedResourceAllocations =
+                ImmutableSet.of(rA1, rA2, rA3, rA4, rA5, rA6, rA7, rA8, rA9);
+
+        Set<ResourceAllocation> resourceAllocations =
+                ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+        assertThat(resourceAllocations, hasSize(9));
+        assertEquals(expectedResourceAllocations, resourceAllocations);
+    }
+
+    /**
+     * Tests if all expected links are present when a partial failure
+     * constraint is used and one ingress is not present.
+     */
+    @Test
+    public void testPartialFailureConstraintSuccess() {
+        Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+                new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_1)));
+
+        FilteredConnectPoint egress =
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+
+        final List<Constraint> constraints =
+                Collections.singletonList(new PartialFailureConstraint());
+
+        MultiPointToSinglePointIntent intent =
+                makeIntent(ingress, egress, constraints);
+
+        String[] hops = {S3};
+
+        MultiPointToSinglePointIntentCompiler compiler =
+                makeCompiler(null,
+                             new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+                             null);
+        assertThat(compiler, is(notNullValue()));
+
+        List<Intent> result = compiler.compile(intent, null);
+        assertThat(result, is(notNullValue()));
+        assertThat(result, hasSize(1));
+
+        Intent resultIntent = result.get(0);
+        assertThat(resultIntent, instanceOf(LinkCollectionIntent.class));
+
+        if (resultIntent instanceof LinkCollectionIntent) {
+            LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+            assertThat(linkIntent.links(), hasSize(2));
+            assertThat(linkIntent.links(), linksHasPath(S1, S3));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
+        }
+        assertThat("key is inherited", resultIntent.key(), is(intent.key()));
+    }
+
+    /**
+     * Exception expected to be raised when an intent does not find all paths
+     * and a partiale failure constraint is not specified.
+     */
+    @Rule
+    public ExpectedException intentException = ExpectedException.none();
+
+    /**
+     * Tests if compiling an intent without partial failure constraints set and
+     * with a missing ingress connect point generates an exception and no other
+     * results.
+     */
+    @Test
+    public void testPartialFailureConstraintFailure() {
+        Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+                new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_1)));
+
+        FilteredConnectPoint egress =
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+
+        MultiPointToSinglePointIntent intent =
+                makeIntent(ingress, egress);
+
+        String[] hops = {S3};
+
+        MultiPointToSinglePointIntentCompiler compiler =
+                makeCompiler(null,
+                             new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+                             null);
+        assertThat(compiler, is(notNullValue()));
+
+        intentException.expect(IntentException.class);
+
+        List<Intent> result = compiler.compile(intent, null);
+        assertThat(result, null);
+    }
 }
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompilerTest.java
index 65251dd..56b6cc2 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompilerTest.java
@@ -22,19 +22,27 @@
 import org.onosproject.TestApplicationId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.FilteredConnectPoint;
 import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.ResourceGroup;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.intent.AbstractIntentTest;
 import org.onosproject.net.intent.Constraint;
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.Key;
 import org.onosproject.net.intent.LinkCollectionIntent;
 import org.onosproject.net.intent.PointToPointIntent;
 import org.onosproject.net.intent.constraint.BandwidthConstraint;
 import org.onosproject.net.intent.impl.PathNotFoundException;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
 import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
 
 import java.util.Collections;
 import java.util.List;
@@ -43,15 +51,9 @@
 
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.everyItem;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.net.NetTestTools.connectPoint;
-import static org.onosproject.net.PortNumber.portNumber;
 import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
 
 /**
@@ -61,43 +63,138 @@
 
     private static final ApplicationId APPID = new TestApplicationId("foo");
 
+    private static final String S1 = "s1";
+    private static final String S2 = "s2";
+    private static final String S3 = "s3";
+    private static final String S4 = "s4";
+    private static final String S5 = "s5";
+    private static final String S6 = "s6";
+    private static final String S7 = "s7";
+    private static final String S8 = "s8";
+
+    private static final DeviceId DID_1 = DeviceId.deviceId("of:" + S1);
+    private static final DeviceId DID_2 = DeviceId.deviceId("of:" + S2);
+    private static final DeviceId DID_3 = DeviceId.deviceId("of:" + S3);
+    private static final DeviceId DID_8 = DeviceId.deviceId("of:" + S8);
+
+    private static final PortNumber PORT_1 = PortNumber.portNumber(1);
+    private static final PortNumber PORT_2 =  PortNumber.portNumber(2);
+
+    private  static final double BPS_TO_RESERVE = 100.0;
+
+    private static final ContinuousResource RESOURCE_SW1_P1 =
+            Resources.continuous(DID_1, PORT_1, Bandwidth.class)
+                     .resource(BPS_TO_RESERVE);
+    private static final ContinuousResource RESOURCE_SW1_P2 =
+            Resources.continuous(DID_1, PORT_2, Bandwidth.class)
+                    .resource(BPS_TO_RESERVE);
+    private static final ContinuousResource RESOURCE_SW2_P1 =
+            Resources.continuous(DID_2, PORT_1, Bandwidth.class)
+                    .resource(BPS_TO_RESERVE);
+    private static final ContinuousResource RESOURCE_SW2_P2 =
+            Resources.continuous(DID_2, PORT_2, Bandwidth.class)
+                    .resource(BPS_TO_RESERVE);
+    private static final ContinuousResource RESOURCE_SW3_P1 =
+            Resources.continuous(DID_3, PORT_1, Bandwidth.class)
+                    .resource(BPS_TO_RESERVE);
+    private static final ContinuousResource RESOURCE_SW3_P2 =
+            Resources.continuous(DID_3, PORT_2, Bandwidth.class)
+                    .resource(BPS_TO_RESERVE);
+
     private TrafficSelector selector = new IntentTestsMocks.MockSelector();
     private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
 
     /**
      * Creates a PointToPoint intent based on ingress and egress device Ids.
      *
-     * @param ingressIdString string for id of ingress device
-     * @param egressIdString  string for id of egress device
+     * @param ingress the ingress connect point
+     * @param egress the egress connect point
      * @return PointToPointIntent for the two devices
      */
-    private PointToPointIntent makeIntent(String ingressIdString,
-                                          String egressIdString) {
+    private PointToPointIntent makeIntent(ConnectPoint ingress, ConnectPoint egress) {
         return PointToPointIntent.builder()
                 .appId(APPID)
                 .selector(selector)
                 .treatment(treatment)
-                .filteredIngressPoint(new FilteredConnectPoint(connectPoint(ingressIdString, 1)))
-                .filteredEgressPoint(new FilteredConnectPoint(connectPoint(egressIdString, 1)))
+                .filteredIngressPoint(new FilteredConnectPoint(ingress))
+                .filteredEgressPoint(new FilteredConnectPoint(egress))
                 .build();
     }
 
     /**
-     * Creates a PointToPoint intent based on ingress and egress deviceIds and constraints.
+     * Creates a PointToPoint intent based on ingress and egress deviceIds and
+     * constraints.
      *
-     * @param ingressIdString string for id of ingress device
-     * @param egressIdString  string for id of egress device
+     * @param ingress         the ingress connect point
+     * @param egress          the egress connect point
      * @param constraints     constraints
-     * @return PointToPointIntent for the two device with constraints
+     * @return the PointToPointIntent connecting the two connect points with
+     * constraints
      */
-    private PointToPointIntent makeIntent(String ingressIdString,
-                                          String egressIdString, List<Constraint> constraints) {
+    private PointToPointIntent makeIntent(ConnectPoint ingress,
+                                          ConnectPoint egress,
+                                          List<Constraint> constraints) {
         return PointToPointIntent.builder()
                 .appId(APPID)
                 .selector(selector)
                 .treatment(treatment)
-                .filteredIngressPoint(new FilteredConnectPoint(connectPoint(ingressIdString, 1)))
-                .filteredEgressPoint(new FilteredConnectPoint(connectPoint(egressIdString, 1)))
+                .filteredIngressPoint(new FilteredConnectPoint(ingress))
+                .filteredEgressPoint(new FilteredConnectPoint(egress))
+                .constraints(constraints)
+                .build();
+    }
+
+    /**
+     * Creates a PointToPoint intent based on ingress and egress deviceIds,
+     * constraints and a resource group.
+     *
+     * @param ingress         the ingress connect point
+     * @param egress          the egress connect point
+     * @param constraints     constraints
+     * @param resourceGroup   the resource group
+     * @return the PointToPointIntent connecting the two connect points with
+     * constraints
+     */
+    private PointToPointIntent makeIntent(ConnectPoint ingress,
+                                          ConnectPoint egress,
+                                          List<Constraint> constraints,
+                                          ResourceGroup resourceGroup) {
+        return PointToPointIntent.builder()
+                .appId(APPID)
+                .resourceGroup(resourceGroup)
+                .selector(selector)
+                .treatment(treatment)
+                .filteredIngressPoint(new FilteredConnectPoint(ingress))
+                .filteredEgressPoint(new FilteredConnectPoint(egress))
+                .constraints(constraints)
+                .build();
+    }
+
+    /**
+     * Creates a PointToPoint intent based on an intent key, ingress and egress
+     * deviceIds, constraints and a resource group.
+     *
+     * @param key             the intent key
+     * @param ingress         the ingress connect point
+     * @param egress          the egress connect point
+     * @param constraints     constraints
+     * @param resourceGroup   the resource group
+     * @return the PointToPointIntent connecting the two connect points with
+     * constraints
+     */
+    private PointToPointIntent makeIntent(Key key,
+                                          ConnectPoint ingress,
+                                          ConnectPoint egress,
+                                          List<Constraint> constraints,
+                                          ResourceGroup resourceGroup) {
+        return PointToPointIntent.builder()
+                .appId(APPID)
+                .key(key)
+                .resourceGroup(resourceGroup)
+                .selector(selector)
+                .treatment(treatment)
+                .filteredIngressPoint(new FilteredConnectPoint(ingress))
+                .filteredEgressPoint(new FilteredConnectPoint(egress))
                 .constraints(constraints)
                 .build();
     }
@@ -109,9 +206,7 @@
      * @return HostToHost intent compiler
      */
     private PointToPointIntentCompiler makeCompiler(String[] hops) {
-        PointToPointIntentCompiler compiler = new PointToPointIntentCompiler();
-        compiler.pathService = new IntentTestsMocks.MockPathService(hops);
-        return compiler;
+        return makeCompiler(hops, null);
     }
 
     /**
@@ -121,10 +216,17 @@
      * @param resourceService service to use for resource allocation requests
      * @return point to point compiler
      */
-    private PointToPointIntentCompiler makeCompiler(String[] hops, ResourceService resourceService) {
+    private PointToPointIntentCompiler makeCompiler(String[] hops,
+                                                    ResourceService resourceService) {
         final PointToPointIntentCompiler compiler = new PointToPointIntentCompiler();
-        compiler.resourceService = resourceService;
         compiler.pathService = new IntentTestsMocks.MockPathService(hops);
+
+        if (resourceService == null) {
+            compiler.resourceService = new MockResourceService();
+        } else {
+            compiler.resourceService = resourceService;
+        }
+
         return compiler;
     }
 
@@ -134,9 +236,10 @@
     @Test
     public void testForwardPathCompilation() {
 
-        PointToPointIntent intent = makeIntent("d1", "d8");
+        PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+                                               new ConnectPoint(DID_8, PORT_1));
 
-        String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"};
+        String[] hops = {S1, S2, S3, S4, S5, S6, S7, S8};
         PointToPointIntentCompiler compiler = makeCompiler(hops);
 
         List<Intent> result = compiler.compile(intent, null);
@@ -147,17 +250,17 @@
 
         if (forwardResultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent forwardIntent = (LinkCollectionIntent) forwardResultIntent;
-            FilteredConnectPoint ingressPoint = new FilteredConnectPoint(connectPoint("d1", 1));
-            FilteredConnectPoint egressPoint = new FilteredConnectPoint(connectPoint("d8", 1));
+            FilteredConnectPoint ingressPoint = new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+            FilteredConnectPoint egressPoint = new FilteredConnectPoint(new ConnectPoint(DID_8, PORT_1));
             // 7 links for the hops, plus one default lnk on ingress and egress
             assertThat(forwardIntent.links(), hasSize(hops.length - 1));
-            assertThat(forwardIntent.links(), linksHasPath("d1", "d2"));
-            assertThat(forwardIntent.links(), linksHasPath("d2", "d3"));
-            assertThat(forwardIntent.links(), linksHasPath("d3", "d4"));
-            assertThat(forwardIntent.links(), linksHasPath("d4", "d5"));
-            assertThat(forwardIntent.links(), linksHasPath("d5", "d6"));
-            assertThat(forwardIntent.links(), linksHasPath("d6", "d7"));
-            assertThat(forwardIntent.links(), linksHasPath("d7", "d8"));
+            assertThat(forwardIntent.links(), linksHasPath(S1, S2));
+            assertThat(forwardIntent.links(), linksHasPath(S2, S3));
+            assertThat(forwardIntent.links(), linksHasPath(S3, S4));
+            assertThat(forwardIntent.links(), linksHasPath(S4, S5));
+            assertThat(forwardIntent.links(), linksHasPath(S5, S6));
+            assertThat(forwardIntent.links(), linksHasPath(S6, S7));
+            assertThat(forwardIntent.links(), linksHasPath(S7, S8));
             assertThat(forwardIntent.filteredIngressPoints(), is(ImmutableSet.of(ingressPoint)));
             assertThat(forwardIntent.filteredEgressPoints(), is(ImmutableSet.of(egressPoint)));
         }
@@ -170,9 +273,10 @@
     @Test
     public void testReversePathCompilation() {
 
-        PointToPointIntent intent = makeIntent("d8", "d1");
+        PointToPointIntent intent = makeIntent(new ConnectPoint(DID_8, PORT_1),
+                                               new ConnectPoint(DID_1, PORT_1));
 
-        String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"};
+        String[] hops = {S1, S2, S3, S4, S5, S6, S7, S8};
         PointToPointIntentCompiler compiler = makeCompiler(hops);
 
         List<Intent> result = compiler.compile(intent, null);
@@ -183,16 +287,16 @@
 
         if (reverseResultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent reverseLinkCollectionIntent = (LinkCollectionIntent) reverseResultIntent;
-            FilteredConnectPoint egressPoint = new FilteredConnectPoint(connectPoint("d1", 1));
-            FilteredConnectPoint ingressPoint = new FilteredConnectPoint(connectPoint("d8", 1));
+            FilteredConnectPoint egressPoint = new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+            FilteredConnectPoint ingressPoint = new FilteredConnectPoint(new ConnectPoint(DID_8, PORT_1));
             assertThat(reverseLinkCollectionIntent.links(), hasSize(hops.length - 1));
-            assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d2", "d1"));
-            assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d3", "d2"));
-            assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d4", "d3"));
-            assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d5", "d4"));
-            assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d6", "d5"));
-            assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d7", "d6"));
-            assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d8", "d7"));
+            assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S2, S1));
+            assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S3, S2));
+            assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S4, S3));
+            assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S5, S4));
+            assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S6, S5));
+            assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S7, S6));
+            assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S8, S7));
             assertThat(reverseLinkCollectionIntent.filteredIngressPoints(), is(ImmutableSet.of(ingressPoint)));
             assertThat(reverseLinkCollectionIntent.filteredEgressPoints(), is(ImmutableSet.of(egressPoint)));
         }
@@ -200,24 +304,23 @@
     }
 
     /**
-     * Tests compilation of the intent which designates two different ports on the same switch.
+     * Tests the compilation of an intent which designates two different ports
+     * on the same switch.
      */
     @Test
     public void testSameSwitchDifferentPortsIntentCompilation() {
-        FilteredConnectPoint src = new FilteredConnectPoint(new ConnectPoint(deviceId("1"), portNumber(1)));
-        FilteredConnectPoint dst = new FilteredConnectPoint(new ConnectPoint(deviceId("1"), portNumber(2)));
-        PointToPointIntent intent = PointToPointIntent.builder()
-                .appId(APP_ID)
-                .selector(selector)
-                .treatment(treatment)
-                .filteredIngressPoint(src)
-                .filteredEgressPoint(dst)
-                .build();
+        FilteredConnectPoint src =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+        FilteredConnectPoint dst =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_2));
 
-        String[] hops = {"1"};
-        PointToPointIntentCompiler sut = makeCompiler(hops);
+        PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+                                               new ConnectPoint(DID_1, PORT_2));
 
-        List<Intent> compiled = sut.compile(intent, null);
+        String[] hops = {S1};
+        PointToPointIntentCompiler compiler = makeCompiler(hops);
+
+        List<Intent> compiled = compiler.compile(intent, null);
 
         assertThat("key is inherited",
                    compiled.stream().map(Intent::key).collect(Collectors.toList()),
@@ -238,16 +341,21 @@
      */
     @Test
     public void testBandwidthConstrainedIntentSuccess() {
+        final double bpsTotal = 1000.0;
+        final double bpsToReserve = 100.0;
 
         final ResourceService resourceService =
-                IntentTestsMocks.MockResourceService.makeBandwidthResourceService(1000.0);
+               MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
         final List<Constraint> constraints =
-                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(100.0)));
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(bpsToReserve)));
 
-        final PointToPointIntent intent = makeIntent("s1", "s3", constraints);
+        final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+                                                     new ConnectPoint(DID_3, PORT_2),
+                                                     constraints);
 
-        String[] hops = {"s1", "s2", "s3"};
-        final PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+        String[] hops = {S1, S2, S3};
+        final PointToPointIntentCompiler compiler = makeCompiler(hops,
+                                                                 resourceService);
 
         final List<Intent> compiledIntents = compiler.compile(intent, null);
 
@@ -265,17 +373,21 @@
      */
     @Test
     public void testBandwidthConstrainedIntentFailure() {
+        final double bpsTotal = 10.0;
 
         final ResourceService resourceService =
-                IntentTestsMocks.MockResourceService.makeBandwidthResourceService(10.0);
+                MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
         final List<Constraint> constraints =
-                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(100.0)));
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
 
         try {
-            final PointToPointIntent intent = makeIntent("s1", "s3", constraints);
+            final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+                                                         new ConnectPoint(DID_3, PORT_2),
+                                                         constraints);
 
-            String[] hops = {"s1", "s2", "s3"};
-            final PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+            String[] hops = {S1, S2, S3};
+            final PointToPointIntentCompiler compiler = makeCompiler(hops,
+                                                                     resourceService);
 
             compiler.compile(intent, null);
 
@@ -285,4 +397,189 @@
             assertThat(noPath.getMessage(), containsString("No path"));
         }
     }
+
+    /**
+     * Tests if bandwidth resources get allocated correctly. An intent with a
+     * key only is submitted.
+     */
+    @Test
+    public void testBandwidthConstrainedIntentAllocation() {
+        final double bpsTotal = 1000.0;
+
+        String[] hops = {S1, S2, S3};
+
+        final ResourceService resourceService =
+                MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+        final List<Constraint> constraints =
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
+
+        final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+                                                     new ConnectPoint(DID_3, PORT_2),
+                                                     constraints);
+
+        PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+        compiler.compile(intent, null);
+
+        Key intentKey = intent.key();
+
+        ResourceAllocation rAOne = new ResourceAllocation(RESOURCE_SW1_P1, intentKey);
+        ResourceAllocation rATwo = new ResourceAllocation(RESOURCE_SW1_P2, intentKey);
+        ResourceAllocation rAThree = new ResourceAllocation(RESOURCE_SW2_P1, intentKey);
+        ResourceAllocation rAFour = new ResourceAllocation(RESOURCE_SW2_P2, intentKey);
+        ResourceAllocation rAFive = new ResourceAllocation(RESOURCE_SW3_P1, intentKey);
+        ResourceAllocation rASix = new ResourceAllocation(RESOURCE_SW3_P2, intentKey);
+
+        Set<ResourceAllocation> expectedresourceAllocations =
+                ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+        Set<ResourceAllocation> resourceAllocations =
+                ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+        assertThat(resourceAllocations, hasSize(6));
+        assertEquals(expectedresourceAllocations, resourceAllocations);
+    }
+
+    /**
+     * Tests if bandwidth resources get allocated correctly using the resource
+     * group. An intent with a resource group is submitted.
+     */
+    @Test
+    public void testRGBandwidthConstrainedIntentAllocation() {
+        final double bpsTotal = 1000.0;
+
+        ResourceGroup resourceGroup = ResourceGroup.of(100);
+
+        String[] hops = {S1, S2, S3};
+
+        final ResourceService resourceService =
+                MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+        final List<Constraint> constraints =
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
+
+        final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+                                                     new ConnectPoint(DID_3, PORT_2),
+                                                     constraints,
+                                                     resourceGroup);
+
+        PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+        compiler.compile(intent, null);
+
+        ResourceAllocation rAOne = new ResourceAllocation(RESOURCE_SW1_P1, resourceGroup);
+        ResourceAllocation rATwo = new ResourceAllocation(RESOURCE_SW1_P2, resourceGroup);
+        ResourceAllocation rAThree = new ResourceAllocation(RESOURCE_SW2_P1, resourceGroup);
+        ResourceAllocation rAFour = new ResourceAllocation(RESOURCE_SW2_P2, resourceGroup);
+        ResourceAllocation rAFive = new ResourceAllocation(RESOURCE_SW3_P1, resourceGroup);
+        ResourceAllocation rASix = new ResourceAllocation(RESOURCE_SW3_P2, resourceGroup);
+
+        Set<ResourceAllocation> expectedresourceAllocations =
+                ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+        Set<ResourceAllocation> resourceAllocations =
+                ImmutableSet.copyOf(resourceService.getResourceAllocations(resourceGroup));
+
+        assertThat(resourceAllocations, hasSize(6));
+        assertEquals(expectedresourceAllocations, resourceAllocations);
+    }
+
+    /**
+     * Tests that bandwidth resources don't get allocated twice if the intent
+     * is submitted twice.
+     */
+    @Test
+    public void testTwoBandwidthConstrainedIntentAllocation() {
+        final double bpsTotal = 1000.0;
+
+        String[] hops = {S1, S2, S3};
+
+        final ResourceService resourceService =
+                MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+        final List<Constraint> constraints =
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
+
+        final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+                                                     new ConnectPoint(DID_3, PORT_2),
+                                                     constraints);
+
+        PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+        compiler.compile(intent, null);
+
+        // Resubmit the same intent
+        compiler.compile(intent, null);
+
+        Key intentKey = intent.key();
+
+        ResourceAllocation rAOne = new ResourceAllocation(RESOURCE_SW1_P1, intentKey);
+        ResourceAllocation rATwo = new ResourceAllocation(RESOURCE_SW1_P2, intentKey);
+        ResourceAllocation rAThree = new ResourceAllocation(RESOURCE_SW2_P1, intentKey);
+        ResourceAllocation rAFour = new ResourceAllocation(RESOURCE_SW2_P2, intentKey);
+        ResourceAllocation rAFive = new ResourceAllocation(RESOURCE_SW3_P1, intentKey);
+        ResourceAllocation rASix = new ResourceAllocation(RESOURCE_SW3_P2, intentKey);
+
+        Set<ResourceAllocation> expectedresourceAllocations =
+                ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+        Set<ResourceAllocation> resourceAllocations =
+                ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+        assertThat(resourceAllocations, hasSize(6));
+        assertEquals(expectedresourceAllocations, resourceAllocations);
+    }
+
+    /**
+     * Tests if bandwidth resources get allocated correctly using groups.
+     * An intent asks to allocate bandwidth using the intent key as a reference.
+     * Then, the intent is submitted with the same key and a group set.
+     * Previous allocations should be released and new resources should be
+     * allocated using the group.
+     */
+    @Test
+    public void testKeyRGBandwidthConstrainedIntentAllocation() {
+        final double bpsTotal = 1000.0;
+
+        String[] hops = {S1, S2, S3};
+
+        final ResourceService resourceService =
+                MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+        final List<Constraint> constraints =
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
+
+        final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+                                                     new ConnectPoint(DID_3, PORT_2),
+                                                     constraints);
+
+        PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+        compiler.compile(intent, null);
+
+        Key intentKey = intent.key();
+
+        ResourceGroup resourceGroup = ResourceGroup.of(100);
+
+        final PointToPointIntent newIntent = makeIntent(intentKey,
+                                                        new ConnectPoint(DID_1, PORT_1),
+                                                        new ConnectPoint(DID_3, PORT_2),
+                                                        constraints,
+                                                        resourceGroup);
+
+        compiler.compile(newIntent, null);
+
+        ResourceAllocation rAOne = new ResourceAllocation(RESOURCE_SW1_P1, resourceGroup);
+        ResourceAllocation rATwo = new ResourceAllocation(RESOURCE_SW1_P2, resourceGroup);
+        ResourceAllocation rAThree = new ResourceAllocation(RESOURCE_SW2_P1, resourceGroup);
+        ResourceAllocation rAFour = new ResourceAllocation(RESOURCE_SW2_P2, resourceGroup);
+        ResourceAllocation rAFive = new ResourceAllocation(RESOURCE_SW3_P1, resourceGroup);
+        ResourceAllocation rASix = new ResourceAllocation(RESOURCE_SW3_P2, resourceGroup);
+
+        Set<ResourceAllocation> expectedresourceAllocations =
+                ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+        Set<ResourceAllocation> resourceAllocations =
+                ImmutableSet.copyOf(resourceService.getResourceAllocations(resourceGroup));
+
+        assertThat(resourceAllocations, hasSize(6));
+        assertEquals(expectedresourceAllocations, resourceAllocations);
+    }
 }
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompilerTest.java
index eec242c..ec761d4 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompilerTest.java
@@ -17,32 +17,51 @@
 package org.onosproject.net.intent.impl.compiler;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import org.hamcrest.Matchers;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
 import org.onosproject.TestApplicationId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.net.intent.Constraint;
 import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentException;
 import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.Key;
 import org.onosproject.net.intent.LinkCollectionIntent;
 import org.onosproject.net.intent.SinglePointToMultiPointIntent;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.PartialFailureConstraint;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
+import org.onosproject.net.topology.PathService;
 
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
+
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
-import static org.onosproject.net.NetTestTools.connectPoint;
+import static org.junit.Assert.assertEquals;
 import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
 
 /**
@@ -51,54 +70,93 @@
 public class SinglePointToMultiPointIntentCompilerTest extends AbstractIntentTest {
 
     private static final ApplicationId APPID = new TestApplicationId("foo");
+    private static final String S1 = "s1";
+    private static final String S2 = "s2";
+    private static final String S3 = "s3";
+    private static final String S4 = "s4";
+    private static final String S5 = "s5";
+    private static final String S6 = "s6";
+    private static final String S7 = "s7";
+    private static final String S8 = "s8";
+
+    private static final DeviceId DID_1 = DeviceId.deviceId("of:" + S1);
+    private static final DeviceId DID_2 = DeviceId.deviceId("of:" + S2);
+    private static final DeviceId DID_3 = DeviceId.deviceId("of:" + S3);
+    private static final DeviceId DID_4 = DeviceId.deviceId("of:" + S4);
+    private static final DeviceId DID_5 = DeviceId.deviceId("of:" + S5);
+    private static final DeviceId DID_8 = DeviceId.deviceId("of:" + S8);
+
+    private static final PortNumber PORT_1 = PortNumber.portNumber(1);
+    private static final PortNumber PORT_2 =  PortNumber.portNumber(2);
+    private static final PortNumber PORT_3 =  PortNumber.portNumber(3);
 
     private TrafficSelector selector = new IntentTestsMocks.MockSelector();
     private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
 
-
-
     /**
      * Creates a SinglePointToMultiPoint intent for an ingress point
      * and a group of egress points.
      *
-     * @param ingressId device id of the ingress point
-     * @param egressIds array of egress device ids
-     * @return MultiPointToSinglePoint intent
+     * @param ingress the filtered ingress point
+     * @param egress the set of filtered egress points
+     * @return a single point to multi point intent
      */
-    private SinglePointToMultiPointIntent makeIntent(String ingressId, String[] egressIds) {
-        ConnectPoint ingressPoint = connectPoint(ingressId, 2);
-        Set<ConnectPoint> egressPoints = new HashSet<>();
-
-
-        for (String egressId : egressIds) {
-            egressPoints.add(connectPoint(egressId, 1));
-        }
-
-        return SinglePointToMultiPointIntent.builder()
-                .appId(APPID)
-                .selector(selector)
-                .treatment(treatment)
-                .ingressPoint(ingressPoint)
-                .egressPoints(egressPoints)
-                .build();
+    private SinglePointToMultiPointIntent makeIntent(FilteredConnectPoint ingress,
+                                                     Set<FilteredConnectPoint> egress) {
+        return makeIntent(ingress, egress, selector);
     }
 
     /**
-     * Generate SinglePointToMultiPointIntent with filtered connection point.
+     * Generates SinglePointToMultiPointIntent with filtered connection point
+     * and the specified selector.
      *
-     * @param ingress filtered ingress point
-     * @param egress filtered egress point
-     * @return
+     * @param ingress the filtered ingress point
+     * @param egress the filtered egress point
+     * @param trafficSelector the intent traffic selector
+     * @return a single point to multi point intent
      */
-    private SinglePointToMultiPointIntent makeFilteredConnectPointIntent(FilteredConnectPoint ingress,
-                                                                         Set<FilteredConnectPoint> egress,
-                                                                         TrafficSelector trafficSelector) {
+    private SinglePointToMultiPointIntent makeIntent(FilteredConnectPoint ingress,
+                                                     Set<FilteredConnectPoint> egress,
+                                                     TrafficSelector trafficSelector) {
+        return makeIntent(ingress, egress, trafficSelector, Lists.newArrayList());
+    }
+
+    /**
+     * Generates SinglePointToMultiPointIntent with filtered connection point
+     * and the given constraints set.
+     *
+     * @param ingress the filtered ingress point
+     * @param egress the filtered egress point
+     * @param constraints the list of intent constraints
+     * @return a single point to multi point intent
+     */
+    private SinglePointToMultiPointIntent makeIntent(FilteredConnectPoint ingress,
+                                                     Set<FilteredConnectPoint> egress,
+                                                     List<Constraint> constraints) {
+        return makeIntent(ingress, egress, selector, constraints);
+    }
+
+    /**
+     * Generates SinglePointToMultiPointIntent with filtered connection point,
+     * and the specified traffic selector and intent constraints.
+     *
+     * @param ingress the filtered ingress point
+     * @param egress the set of filtered egress points
+     * @param trafficSelector the intent traffic selector
+     * @param constraints the list of intent constraints
+     * @return a single point to multi point intent
+     */
+    private SinglePointToMultiPointIntent makeIntent(FilteredConnectPoint ingress,
+                                                     Set<FilteredConnectPoint> egress,
+                                                     TrafficSelector trafficSelector,
+                                                     List<Constraint> constraints) {
         return SinglePointToMultiPointIntent.builder()
                 .appId(APPID)
                 .treatment(treatment)
                 .selector(trafficSelector)
                 .filteredIngressPoint(ingress)
                 .filteredEgressPoints(egress)
+                .constraints(constraints)
                 .build();
     }
 
@@ -106,29 +164,58 @@
      * Creates a compiler for SinglePointToMultiPoint intents.
      *
      * @param hops hops to use while computing paths for this intent
-     * @return SinglePointToMultiPoint intent
+     * @param pathService the path service
+     * @param resourceService the resource service
+     * @return a single point to multi point intent compiler
      */
-    private SinglePointToMultiPointIntentCompiler makeCompiler(String[] hops) {
+    private SinglePointToMultiPointIntentCompiler makeCompiler(String[] hops,
+                                                               PathService pathService,
+                                                               ResourceService resourceService) {
         SinglePointToMultiPointIntentCompiler compiler =
                 new SinglePointToMultiPointIntentCompiler();
+        compiler.deviceService = new IntentTestsMocks.MockDeviceService();
 
-        compiler.pathService = new IntentTestsMocks.Mp2MpMockPathService(hops);
+        if (pathService == null) {
+            compiler.pathService = new IntentTestsMocks.Mp2MpMockPathService(hops);
+        } else {
+            compiler.pathService = pathService;
+        }
+
+        if (resourceService == null) {
+            compiler.resourceService = new MockResourceService();
+        } else {
+            compiler.resourceService = resourceService;
+        }
+
         return compiler;
     }
 
     /**
+     * Creates a compiler for SinglePointToMultiPoint intents.
+     *
+     * @param hops the hops to use while computing paths for this intent
+     * @return a single point to multi point intent compiler
+     */
+    private SinglePointToMultiPointIntentCompiler makeCompiler(String[] hops) {
+        return makeCompiler(hops, null, null);
+    }
+
+    /**
      * Tests a single ingress point with 8 hops to its egress point.
      */
     @Test
     public void testSingleLongPathCompilation() {
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+        Set<FilteredConnectPoint> egress =
+                Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_8, PORT_2)));
 
-        String ingress = "ingress";
-        String[] egress = {"egress"};
+        SinglePointToMultiPointIntent intent =
+                makeIntent(ingress, egress);
 
-        SinglePointToMultiPointIntent intent = makeIntent(ingress, egress);
         assertThat(intent, is(notNullValue()));
 
-        String[] hops = {"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8"};
+        String[] hops = {S2, S3, S4, S5, S6, S7};
         SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
 
@@ -140,14 +227,14 @@
 
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
-            assertThat(linkIntent.links(), hasSize(9));
-            assertThat(linkIntent.links(), linksHasPath("ingress", "h1"));
-            assertThat(linkIntent.links(), linksHasPath("h1", "h2"));
-            assertThat(linkIntent.links(), linksHasPath("h2", "h3"));
-            assertThat(linkIntent.links(), linksHasPath("h4", "h5"));
-            assertThat(linkIntent.links(), linksHasPath("h5", "h6"));
-            assertThat(linkIntent.links(), linksHasPath("h7", "h8"));
-            assertThat(linkIntent.links(), linksHasPath("h8", "egress"));
+            assertThat(linkIntent.links(), hasSize(7));
+            assertThat(linkIntent.links(), linksHasPath(S1, S2));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
+            assertThat(linkIntent.links(), linksHasPath(S4, S5));
+            assertThat(linkIntent.links(), linksHasPath(S5, S6));
+            assertThat(linkIntent.links(), linksHasPath(S6, S7));
+            assertThat(linkIntent.links(), linksHasPath(S7, S8));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
     }
@@ -157,14 +244,21 @@
      * and some path segments are not shared.
      */
     @Test
-    public void testTwoIngressCompilation() {
-        String ingress = "ingress";
-        String[] egress = {"egress1", "egress2"};
+    public void testTwoEgressCompilation() {
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+        FilteredConnectPoint egressOne =
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+        FilteredConnectPoint egressTwo =
+                new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_2));
+        Set<FilteredConnectPoint> egress = Sets.newHashSet(egressOne, egressTwo);
 
         SinglePointToMultiPointIntent intent = makeIntent(ingress, egress);
+
         assertThat(intent, is(notNullValue()));
 
-        final String[] hops = {"inner1", "inner2"};
+        final String[] hops = {S2, S3};
         SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
 
@@ -177,28 +271,38 @@
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
             assertThat(linkIntent.links(), hasSize(4));
-            assertThat(linkIntent.links(), linksHasPath("ingress", "inner1"));
-            assertThat(linkIntent.links(), linksHasPath("inner1", "inner2"));
-            assertThat(linkIntent.links(), linksHasPath("inner2", "egress1"));
-            assertThat(linkIntent.links(), linksHasPath("inner2", "egress2"));
+            assertThat(linkIntent.links(), linksHasPath(S1, S2));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
+            assertThat(linkIntent.links(), linksHasPath(S3, S5));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
     }
 
     /**
-     * Tests a large number of ingress points that share a common path to the
-     * egress point.
+     * Tests multiple egress points that share a common path to the ingress
+     * point.
      */
     @Test
-    public void testMultiIngressCompilation() {
-        String ingress = "i";
-        String[] egress = {"e1", "e2", "e3", "e4", "e5",
-                "e6", "e7", "e8", "e9", "e10"};
+    public void testMultiEgressCompilation() {
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+        FilteredConnectPoint egressOne =
+                new FilteredConnectPoint(new ConnectPoint(DID_3, PORT_2));
+        FilteredConnectPoint egressTwo =
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+        FilteredConnectPoint egressThree =
+                new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_2));
+        Set<FilteredConnectPoint> egress = Sets.newHashSet(egressOne,
+                                                           egressTwo,
+                                                           egressThree);
 
         SinglePointToMultiPointIntent intent = makeIntent(ingress, egress);
+
         assertThat(intent, is(notNullValue()));
 
-        final String[] hops = {"n1"};
+        final String[] hops = {S2};
         SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
 
@@ -210,11 +314,11 @@
 
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
-            assertThat(linkIntent.links(), hasSize(egress.length + 1));
-            for (String egressToCheck : egress) {
-                assertThat(linkIntent.links(), linksHasPath("n1", egressToCheck));
-            }
-            assertThat(linkIntent.links(), linksHasPath(ingress, "n1"));
+            assertThat(linkIntent.links(), hasSize(4));
+            assertThat(linkIntent.links(), linksHasPath(S1, S2));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S2, S4));
+            assertThat(linkIntent.links(), linksHasPath(S2, S5));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
     }
@@ -224,8 +328,12 @@
      */
     @Test
     public void testSameDeviceCompilation() {
-        String ingress = "i1";
-        String[] egress = {"i2", "i3"};
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+        Set<FilteredConnectPoint> egress =
+                Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_2)),
+                                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_3)));
 
         SinglePointToMultiPointIntent intent = makeIntent(ingress, egress);
         assertThat(intent, is(notNullValue()));
@@ -242,32 +350,29 @@
 
         if (resultIntent instanceof LinkCollectionIntent) {
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
-            assertThat(linkIntent.links(), hasSize(egress.length));
-
-            assertThat(linkIntent.links(), linksHasPath("i1", "i2"));
-            assertThat(linkIntent.links(), linksHasPath("i1", "i3"));
+            assertThat(linkIntent.links(), hasSize(0));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
     }
 
     /**
-     * Tests filtered ingress and egress.
+     * Tests filtered ingress and egress connect points.
      */
     @Test
     public void testFilteredConnectPointIntent() {
 
-        FilteredConnectPoint ingress = new FilteredConnectPoint(connectPoint("of1", 1));
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
 
         Set<FilteredConnectPoint> egress = ImmutableSet.of(
-                new FilteredConnectPoint(connectPoint("of3", 1),
+                new FilteredConnectPoint(new ConnectPoint(DID_3, PORT_1),
                                          DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
-                new FilteredConnectPoint(connectPoint("of4", 1),
+                new FilteredConnectPoint(new ConnectPoint(DID_4,  PORT_1),
                                          DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("200")).build())
         );
 
-
-        SinglePointToMultiPointIntent intent = makeFilteredConnectPointIntent(ingress, egress, selector);
-        String[] hops = {"of2"};
+        SinglePointToMultiPointIntent intent = makeIntent(ingress, egress, selector);
+        String[] hops = {S2};
 
         SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
@@ -283,9 +388,9 @@
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
             assertThat(linkIntent.links(), hasSize(3));
 
-            assertThat(linkIntent.links(), linksHasPath("of1", "of2"));
-            assertThat(linkIntent.links(), linksHasPath("of2", "of3"));
-            assertThat(linkIntent.links(), linksHasPath("of2", "of4"));
+            assertThat(linkIntent.links(), linksHasPath(S1, S2));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S2, S4));
 
             Set<FilteredConnectPoint> ingressPoints = linkIntent.filteredIngressPoints();
             assertThat("Link collection ingress points do not match base intent",
@@ -299,17 +404,18 @@
     }
 
     /**
-     * Tests selector, filtered ingress and egress.
+     * Tests filtered ingress and egress points with an intent selector set.
      */
     @Test
     public void testNonTrivialSelectorsIntent() {
 
-        FilteredConnectPoint ingress = new FilteredConnectPoint(connectPoint("of1", 1));
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
 
         Set<FilteredConnectPoint> egress = ImmutableSet.of(
-                new FilteredConnectPoint(connectPoint("of3", 1),
+                new FilteredConnectPoint(new ConnectPoint(DID_3, PORT_1),
                                          DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
-                new FilteredConnectPoint(connectPoint("of4", 1),
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_1),
                                          DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("200")).build())
         );
 
@@ -317,8 +423,8 @@
                 .matchIPDst(IpPrefix.valueOf("192.168.100.0/24"))
                 .build();
 
-        SinglePointToMultiPointIntent intent = makeFilteredConnectPointIntent(ingress, egress, ipPrefixSelector);
-        String[] hops = {"of2"};
+        SinglePointToMultiPointIntent intent = makeIntent(ingress, egress, ipPrefixSelector);
+        String[] hops = {S2};
 
         SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
         assertThat(compiler, is(notNullValue()));
@@ -334,9 +440,9 @@
             LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
             assertThat(linkIntent.links(), hasSize(3));
 
-            assertThat(linkIntent.links(), linksHasPath("of1", "of2"));
-            assertThat(linkIntent.links(), linksHasPath("of2", "of3"));
-            assertThat(linkIntent.links(), linksHasPath("of2", "of4"));
+            assertThat(linkIntent.links(), linksHasPath(S1, S2));
+            assertThat(linkIntent.links(), linksHasPath(S2, S3));
+            assertThat(linkIntent.links(), linksHasPath(S2, S4));
 
             Set<FilteredConnectPoint> ingressPoints = linkIntent.filteredIngressPoints();
             assertThat("Link collection ingress points do not match base intent",
@@ -347,6 +453,172 @@
             assertThat(linkIntent.selector(), is(ipPrefixSelector));
         }
         assertThat("key is inherited", resultIntent.key(), is(intent.key()));
+    }
 
+    /**
+     * Tests if bandwidth resources get allocated correctly.
+     */
+    @Test
+    public void testBandwidthConstrainedIntentAllocation() {
+        final double bpsTotal = 1000.0;
+        final double bpsToReserve = 100.0;
+
+        ContinuousResource resourceSw1P1 =
+                Resources.continuous(DID_1, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw1P2 =
+                Resources.continuous(DID_1, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw2P1 =
+                Resources.continuous(DID_2, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw2P2 =
+                Resources.continuous(DID_2, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw3P1 =
+                Resources.continuous(DID_3, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw3P2 =
+                Resources.continuous(DID_3, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw3P3 =
+                Resources.continuous(DID_3, PORT_3, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw4P1 =
+                Resources.continuous(DID_4, PORT_1, Bandwidth.class)
+                        .resource(bpsToReserve);
+        ContinuousResource resourceSw4P2 =
+                Resources.continuous(DID_4, PORT_2, Bandwidth.class)
+                        .resource(bpsToReserve);
+
+        String[] hops = {DID_3.toString()};
+
+        final ResourceService resourceService =
+                MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+        final List<Constraint> constraints =
+                Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(bpsToReserve)));
+
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_1));
+
+        Set<FilteredConnectPoint> egress = ImmutableSet.of(
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_2)),
+                new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_2)));
+
+        TrafficSelector ipPrefixSelector = DefaultTrafficSelector.builder()
+                .matchIPDst(IpPrefix.valueOf("192.168.100.0/24"))
+                .build();
+
+        SinglePointToMultiPointIntent intent =
+                makeIntent(ingress, egress, ipPrefixSelector, constraints);
+
+        SinglePointToMultiPointIntentCompiler compiler =
+                makeCompiler(null,
+                             new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+                             resourceService);
+
+        compiler.compile(intent, null);
+
+        Key intentKey = intent.key();
+
+        ResourceAllocation rA1 = new ResourceAllocation(resourceSw1P1, intentKey);
+        ResourceAllocation rA2 = new ResourceAllocation(resourceSw1P2, intentKey);
+        ResourceAllocation rA3 = new ResourceAllocation(resourceSw2P1, intentKey);
+        ResourceAllocation rA4 = new ResourceAllocation(resourceSw2P2, intentKey);
+        ResourceAllocation rA5 = new ResourceAllocation(resourceSw3P1, intentKey);
+        ResourceAllocation rA6 = new ResourceAllocation(resourceSw3P2, intentKey);
+        ResourceAllocation rA7 = new ResourceAllocation(resourceSw3P3, intentKey);
+        ResourceAllocation rA8 = new ResourceAllocation(resourceSw4P1, intentKey);
+        ResourceAllocation rA9 = new ResourceAllocation(resourceSw4P2, intentKey);
+
+        Set<ResourceAllocation> expectedResourceAllocations =
+                ImmutableSet.of(rA1, rA2, rA3, rA4, rA5, rA6, rA7, rA8, rA9);
+
+        Set<ResourceAllocation> resourceAllocations =
+                ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+        assertThat(resourceAllocations, hasSize(9));
+        assertEquals(expectedResourceAllocations, resourceAllocations);
+    }
+
+    /**
+     * Tests if all expected links are present when a partial failure
+     * constraint is used and one ingress is not present.
+     */
+    @Test
+    public void testPartialFailureConstraintSuccess() {
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+        Set<FilteredConnectPoint> egress = ImmutableSet.of(
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2)),
+                new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_2)));
+
+        final List<Constraint> constraints =
+                Collections.singletonList(new PartialFailureConstraint());
+
+        SinglePointToMultiPointIntent intent =
+                makeIntent(ingress, egress, constraints);
+
+        String[] hops = {S3};
+
+        SinglePointToMultiPointIntentCompiler compiler =
+                makeCompiler(null,
+                             new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+                             null);
+        assertThat(compiler, is(notNullValue()));
+
+        List<Intent> result = compiler.compile(intent, null);
+        assertThat(result, is(notNullValue()));
+        assertThat(result, hasSize(1));
+
+        Intent resultIntent = result.get(0);
+        assertThat(resultIntent, instanceOf(LinkCollectionIntent.class));
+
+        if (resultIntent instanceof LinkCollectionIntent) {
+            LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+            assertThat(linkIntent.links(), hasSize(2));
+            assertThat(linkIntent.links(), linksHasPath(S1, S3));
+            assertThat(linkIntent.links(), linksHasPath(S3, S4));
+        }
+        assertThat("key is inherited", resultIntent.key(), is(intent.key()));
+    }
+
+    /**
+     * Exception expected to be raised when an intent does not find all paths
+     * and a partiale failure constraint is not specified.
+     */
+    @Rule
+    public ExpectedException intentException = ExpectedException.none();
+
+    /**
+     * Tests if compiling an intent without partial failure constraints set and
+     * with a missing egress connect point generates an exception and no other
+     * results.
+     */
+    @Test
+    public void testPartialFailureConstraintFailure() {
+        FilteredConnectPoint ingress =
+                new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+        Set<FilteredConnectPoint> egress = ImmutableSet.of(
+                new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2)),
+                new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_2)));
+
+        SinglePointToMultiPointIntent intent =
+                makeIntent(ingress, egress);
+
+        String[] hops = {S3};
+
+        SinglePointToMultiPointIntentCompiler compiler =
+                makeCompiler(null,
+                             new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+                             null);
+        assertThat(compiler, is(notNullValue()));
+
+        intentException.expect(IntentException.class);
+
+        List<Intent> result = compiler.compile(intent, null);
+        assertThat(result, null);
     }
 }