Merge branch 'optical-integration' of ssh://gerrit.onlab.us:29418/onos-next into optical-integration
diff --git a/apps/optical/src/main/java/org/onlab/onos/optical/provisioner/OpticalPathProvisioner.java b/apps/optical/src/main/java/org/onlab/onos/optical/provisioner/OpticalPathProvisioner.java
new file mode 100644
index 0000000..9f77cfd
--- /dev/null
+++ b/apps/optical/src/main/java/org/onlab/onos/optical/provisioner/OpticalPathProvisioner.java
@@ -0,0 +1,226 @@
+package org.onlab.onos.optical.provisioner;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.ApplicationId;
+import org.onlab.onos.CoreService;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.Path;
+import org.onlab.onos.net.device.DeviceService;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentEvent;
+import org.onlab.onos.net.intent.IntentExtensionService;
+import org.onlab.onos.net.intent.IntentListener;
+import org.onlab.onos.net.intent.IntentService;
+import org.onlab.onos.net.intent.OpticalConnectivityIntent;
+import org.onlab.onos.net.intent.PointToPointIntent;
+import org.onlab.onos.net.link.LinkService;
+import org.onlab.onos.net.resource.LinkResourceService;
+import org.onlab.onos.net.topology.LinkWeight;
+import org.onlab.onos.net.topology.Topology;
+import org.onlab.onos.net.topology.TopologyEdge;
+
+import org.onlab.onos.net.topology.TopologyService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * OpticalPathProvisioner listens event notifications from the Intent F/W.
+ * It generates one or more opticalConnectivityIntent(s) and submits (or withdraws) to Intent F/W
+ * for adding/releasing capacity at the packet layer.
+ *
+ */
+
+@Component(immediate = true)
+public class OpticalPathProvisioner {
+
+    protected static final Logger log = LoggerFactory
+            .getLogger(OpticalPathProvisioner.class);
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private IntentService intentService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private IntentExtensionService intentExtensionService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkService linkService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TopologyService topologyService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceService;
+
+    private ApplicationId appId;
+
+    //protected <IntentId> intentIdGenerator;
+
+    private final InternalOpticalPathProvisioner pathProvisioner = new InternalOpticalPathProvisioner();
+
+    @Activate
+    protected void activate() {
+        intentService.addListener(pathProvisioner);
+        appId = coreService.registerApplication("org.onlab.onos.optical");
+        log.info("Starting optical path provisoning...");
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        intentService.removeListener(pathProvisioner);
+    }
+
+    public class InternalOpticalPathProvisioner implements IntentListener {
+        @Override
+        public void event(IntentEvent event) {
+            switch (event.type()) {
+                case SUBMITTED:
+                    break;
+                case INSTALLED:
+                    break;
+                case FAILED:
+                    log.info("intent {} failed, calling optical path provisioning APP.", event.subject());
+                    setuplightpath(event.subject());
+                    break;
+                case WITHDRAWN:
+                    log.info("intent {} withdrawn.", event.subject());
+                    teardownLightpath(event.subject());
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        private void setuplightpath(Intent intent) {
+           // TODO: considering user policies and optical reach
+           if (!intent.equals(PointToPointIntent.class)) {
+               return;
+           }
+
+           PointToPointIntent pktIntent = (PointToPointIntent) intent;
+           if (pktIntent.ingressPoint() == null || pktIntent.egressPoint() == null) {
+               return;
+           }
+
+           Topology topology = topologyService.currentTopology();
+
+           LinkWeight weight = new LinkWeight() {
+               @Override
+               public double weight(TopologyEdge edge) {
+                   boolean isOptical = false;
+                   String t = edge.link().annotations().value("linkType");
+                   if (t.equals("WDM")) {
+                      isOptical = true;
+                   }
+                   if (isOptical) {
+                       return 1000;  // optical links
+                   } else {
+                       return 10; // packet links
+                   }
+               }
+           };
+
+           Set<Path> paths = topologyService.getPaths(topology,
+                   pktIntent.ingressPoint().deviceId(),
+                   pktIntent.egressPoint().deviceId(),
+                   weight);
+
+           if (paths.isEmpty()) {
+               return;
+           }
+
+           ConnectPoint srcWdmPoint = null;
+           ConnectPoint dstWdmPoint = null;
+           Iterator<Path> itrPath = paths.iterator();
+           Path firstPath = itrPath.next();
+           log.info(firstPath.toString());
+
+           ArrayList<Map<ConnectPoint, ConnectPoint>> connectionList = new ArrayList<>();
+
+           Iterator<Link> itrLink = firstPath.links().iterator();
+           while (itrLink.hasNext()) {
+               Link link1 = itrLink.next();
+               if (!isOpticalLink(link1)) {
+                   continue;
+               } else {
+                   srcWdmPoint = link1.dst();
+                   dstWdmPoint = srcWdmPoint;
+               }
+
+               while (true) {
+
+                   if (itrLink.hasNext()) {
+                       Link link2 = itrLink.next();
+                       dstWdmPoint = link2.src();
+                   } else {
+                       break;
+                   }
+
+                   if (itrLink.hasNext()) {
+                       Link link3 = itrLink.next();
+                       if (!isOpticalLink(link3)) {
+                          break;
+                       }
+                   } else {
+                       break;
+                   }
+               }
+
+               Map<ConnectPoint, ConnectPoint> pair =
+                       new HashMap<ConnectPoint, ConnectPoint>();
+               pair.put(srcWdmPoint, dstWdmPoint);
+
+               connectionList.add(pair);
+           }
+
+           for (Map<ConnectPoint, ConnectPoint> map : connectionList) {
+               for (Entry<ConnectPoint, ConnectPoint> entry : map.entrySet()) {
+
+                   ConnectPoint src = entry.getKey();
+                   ConnectPoint dst = entry.getValue();
+
+                   Intent opticalIntent = new OpticalConnectivityIntent(appId,
+                          srcWdmPoint,
+                          dstWdmPoint);
+
+                   intentService.submit(opticalIntent);
+
+                   log.info(opticalIntent.toString());
+               }
+           }
+
+        }
+
+        private boolean isOpticalLink(Link link) {
+            boolean isOptical = false;
+            String t = link.annotations().value("linkType");
+            if (t.equals("WDM") || t.equals("PktOptLink")) {
+               isOptical = true;
+            }
+            return isOptical;
+          }
+
+        private void teardownLightpath(Intent intent) {
+          // TODO: tear down the idle lightpath if the utilization is close to zero.
+        }
+
+    }
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java
new file mode 100644
index 0000000..6e595c5
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java
@@ -0,0 +1,55 @@
+package org.onlab.onos.net.intent;
+
+import org.onlab.onos.ApplicationId;
+import org.onlab.onos.net.ConnectPoint;
+
+/**
+ * An optical layer Intent for a connectivity from one Transponder port to another
+ * Transponder port. No trafficSelector as well as trafficTreament are needed.
+ *
+ */
+public class OpticalConnectivityIntent extends Intent {
+    protected ConnectPoint src;
+    protected ConnectPoint dst;
+
+    /**
+     * Constructor.
+     *
+     * @param id  ID for this new Intent object.
+     * @param src The source transponder port.
+     * @param dst The destination transponder port.
+     */
+    public OpticalConnectivityIntent(ApplicationId appId, ConnectPoint src, ConnectPoint dst) {
+        super(id(OpticalConnectivityIntent.class, src, dst),
+                appId, null);
+        this.src = src;
+        this.dst = dst;
+    }
+
+    /**
+     * Constructor for serializer.
+     */
+    protected OpticalConnectivityIntent() {
+        super();
+        this.src = null;
+        this.dst = null;
+    }
+
+    /**
+     * Gets source transponder port.
+     *
+     * @return The source transponder port.
+     */
+    public ConnectPoint getSrcConnectPoint() {
+        return src;
+    }
+
+    /**
+     * Gets destination transponder port.
+     *
+     * @return The source transponder port.
+     */
+    public ConnectPoint getDst() {
+        return dst;
+    }
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/OpticalPathIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalPathIntent.java
new file mode 100644
index 0000000..afa0004
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalPathIntent.java
@@ -0,0 +1,69 @@
+package org.onlab.onos.net.intent;
+
+import java.util.Collection;
+
+import org.onlab.onos.ApplicationId;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.Path;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+
+import com.google.common.base.MoreObjects;
+
+public class OpticalPathIntent extends OpticalConnectivityIntent {
+    private final Path path;
+    // private final TrafficSelector opticalMatch;
+    // private final TrafficTreatment opticalAction;
+
+    public OpticalPathIntent(ApplicationId appId,
+            ConnectPoint src,
+            ConnectPoint dst,
+            TrafficSelector match,
+            TrafficTreatment action,
+            Path path) {
+        super(appId, src, dst);
+        // this.opticalMatch = match;
+        // this.opticalAction = action;
+        this.path = path;
+    }
+
+    protected OpticalPathIntent() {
+        // this.opticalMatch = null;
+        // this.opticalAction = null;
+        this.path = null;
+    }
+
+    public Path path() {
+        return path;
+    }
+/*
+    public TrafficSelector selector() {
+        // return opticalMatch;
+    }
+
+    public TrafficTreatment treatment() {
+        // return opticalAction;
+    }
+*/
+    @Override
+    public boolean isInstallable() {
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("id", id())
+                //.add("match", opticalMatch)
+                //.add("action", opticalAction)
+                .add("ingressPort", this.getSrcConnectPoint())
+                .add("egressPort", this.getDst())
+                .add("path", path)
+                .toString();
+    }
+
+    public Collection<Link> requiredLinks() {
+        return path.links();
+    }
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceRequest.java b/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceRequest.java
index 601a27c..5743d8e 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceRequest.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceRequest.java
@@ -33,4 +33,9 @@
     public Bandwidth bandwidth() {
         return bandwidth;
     }
+
+    @Override
+    public ResourceType type() {
+        return ResourceType.BANDWIDTH;
+    }
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/DefaultLinkResourceRequest.java b/core/api/src/main/java/org/onlab/onos/net/resource/DefaultLinkResourceRequest.java
index 38f90c1..b33e203 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/DefaultLinkResourceRequest.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/DefaultLinkResourceRequest.java
@@ -34,6 +34,12 @@
         this.resources = ImmutableSet.copyOf(resources);
     }
 
+
+    @Override
+    public ResourceType type() {
+        return null;
+    }
+
     @Override
     public IntentId intendId() {
         return intentId;
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceRequest.java b/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceRequest.java
index 30caa2d..05bf61c 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceRequest.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceRequest.java
@@ -5,4 +5,9 @@
  */
 public class LambdaResourceRequest implements ResourceRequest {
 
+    @Override
+    public ResourceType type() {
+        return ResourceType.LAMBDA;
+    }
+
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/ResourceRequest.java b/core/api/src/main/java/org/onlab/onos/net/resource/ResourceRequest.java
index bc3d904..06e3666 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/ResourceRequest.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/ResourceRequest.java
@@ -4,5 +4,11 @@
  * Abstraction of resource request.
  */
 public interface ResourceRequest {
+    /**
+     * Returns the resource type.
+     *
+     * @return the resource type
+     */
+    ResourceType type();
 
 }
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalConnectivityIntentCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalConnectivityIntentCompiler.java
new file mode 100644
index 0000000..9b98cec
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalConnectivityIntentCompiler.java
@@ -0,0 +1,148 @@
+package org.onlab.onos.net.intent.impl;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.CoreService;
+import org.onlab.onos.net.ConnectPoint;
+
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.Path;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentCompiler;
+import org.onlab.onos.net.intent.IntentExtensionService;
+
+import org.onlab.onos.net.intent.OpticalConnectivityIntent;
+import org.onlab.onos.net.intent.OpticalPathIntent;
+import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.onos.net.resource.LinkResourceService;
+import org.onlab.onos.net.topology.LinkWeight;
+import org.onlab.onos.net.topology.PathService;
+import org.onlab.onos.net.topology.Topology;
+import org.onlab.onos.net.topology.TopologyEdge;
+
+import org.onlab.onos.net.topology.TopologyService;
+import org.slf4j.Logger;
+
+/**
+ * Optical compiler for OpticalConnectivityIntent.
+ * It firstly computes K-shortest paths in the optical-layer, then choose the optimal one to assign a wavelength.
+ * Finally, it generates one or more opticalPathintent(s) with opticalMatchs and opticalActions.
+ */
+@Component(immediate = true)
+public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
+
+    private final Logger log = getLogger(getClass());
+    private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected IntentExtensionService intentManager;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PathService pathService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TopologyService topologyService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Activate
+    public void activate() {
+        intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        intentManager.unregisterCompiler(OpticalConnectivityIntent.class);
+    }
+
+    @Override
+    public List<Intent> compile(OpticalConnectivityIntent intent) {
+        // TODO: compute multiple paths using the K-shortest path algorithm
+        List<Intent> retList = new ArrayList<>();
+        Path path = calculatePath(intent.getSrcConnectPoint(), intent.getDst());
+        if (path == null) {
+            return retList;
+        } else {
+            log.info("the computed lightpath is : {}.", path.toString());
+        }
+
+        List<Link> links = new ArrayList<>();
+        // links.add(DefaultEdgeLink.createEdgeLink(intent.getSrcConnectPoint(), true));
+        links.addAll(path.links());
+        //links.add(DefaultEdgeLink.createEdgeLink(intent.getDst(), false));
+
+        TrafficSelector opticalSelector = null;
+        TrafficTreatment opticalTreatment = null;
+
+        // create a new opticalPathIntent
+        Intent newIntent = new OpticalPathIntent(intent.appId(),
+                path.src(),
+                path.dst(),
+                opticalSelector,
+                opticalTreatment,
+                path);
+
+        retList.add(newIntent);
+
+        return retList;
+    }
+
+    private Path calculatePath(ConnectPoint start, ConnectPoint end) {
+        // TODO: support user policies
+        Topology topology = topologyService.currentTopology();
+        LinkWeight weight = new LinkWeight() {
+            @Override
+            public double weight(TopologyEdge edge) {
+                boolean isOptical = false;
+                String t = edge.link().annotations().value("linkType");
+                if (t.equals("WDM")) {
+                   isOptical = true;
+                }
+                if (isOptical) {
+                    return 1; // optical links
+                } else {
+                    return 10000; // packet links
+                }
+            }
+        };
+
+        Set<Path> paths = topologyService.getPaths(topology,
+                start.deviceId(),
+                end.deviceId(),
+                weight);
+
+        Iterator<Path> itr = paths.iterator();
+        while (itr.hasNext()) {
+            Path path = itr.next();
+            if (path.cost() >= 10000) {
+                itr.remove();
+            }
+        }
+
+        if (paths.isEmpty()) {
+            log.info("No optical path found from " + start + " to " + end);
+            return null;
+        } else {
+            return paths.iterator().next();
+        }
+
+    }
+
+}
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java
new file mode 100644
index 0000000..f24916f
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java
@@ -0,0 +1,247 @@
+package org.onlab.onos.net.intent.impl;
+
+import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
+import static org.slf4j.LoggerFactory.getLogger;
+
+
+import java.util.List;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.ApplicationId;
+import org.onlab.onos.CoreService;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.flow.DefaultFlowRule;
+import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.DefaultTrafficTreatment;
+import org.onlab.onos.net.flow.FlowRule;
+import org.onlab.onos.net.flow.FlowRuleBatchEntry;
+import org.onlab.onos.net.flow.FlowRuleBatchOperation;
+import org.onlab.onos.net.flow.FlowRuleService;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
+import org.onlab.onos.net.intent.IntentExtensionService;
+import org.onlab.onos.net.intent.IntentInstaller;
+import org.onlab.onos.net.intent.OpticalPathIntent;
+import org.onlab.onos.net.resource.DefaultLinkResourceRequest;
+import org.onlab.onos.net.resource.Lambda;
+import org.onlab.onos.net.resource.LambdaResourceAllocation;
+import org.onlab.onos.net.resource.LinkResourceAllocations;
+import org.onlab.onos.net.resource.LinkResourceRequest;
+import org.onlab.onos.net.resource.LinkResourceService;
+import org.onlab.onos.net.resource.ResourceAllocation;
+import org.onlab.onos.net.resource.ResourceType;
+import org.onlab.onos.net.topology.TopologyService;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Lists;
+
+/**
+ * OpticaliIntentInstaller for optical path intents.
+ * It essentially generates optical FlowRules and
+ * call the flowRule service to execute them.
+ */
+
+@Component(immediate = true)
+public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIntent> {
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected IntentExtensionService intentManager;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected FlowRuleService flowRuleService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TopologyService topologyService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceService;
+
+    private ApplicationId appId;
+
+    //final short WAVELENGTH = 80;
+
+    @Activate
+    public void activate() {
+        appId = coreService.registerApplication("org.onlab.onos.net.intent");
+        intentManager.registerInstaller(OpticalPathIntent.class, this);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        intentManager.unregisterInstaller(OpticalPathIntent.class);
+    }
+
+    @Override
+    public List<FlowRuleBatchOperation> install(OpticalPathIntent intent) {
+        LinkResourceAllocations allocations = assignWavelength(intent);
+
+        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+        selectorBuilder.matchInport(intent.getSrcConnectPoint().port());
+
+        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+
+        List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
+        ConnectPoint prev = intent.getSrcConnectPoint();
+
+        //TODO throw exception if the lambda was not assigned successfully
+        for (Link link : intent.path().links()) {
+            Lambda la = null;
+            for (ResourceAllocation allocation : allocations.getResourceAllocation(link)) {
+                if (allocation.type() == ResourceType.LAMBDA) {
+                    la = ((LambdaResourceAllocation) allocation).lambda();
+                    break;
+                }
+            }
+
+            if (la == null) {
+                log.info("Lambda was not assigned successfully");
+                return null;
+            }
+
+            treatmentBuilder.setOutput(link.src().port());
+            //treatmentBuilder.setLambda(la.toInt());
+
+            FlowRule rule = new DefaultFlowRule(prev.deviceId(),
+                    selectorBuilder.build(),
+                    treatmentBuilder.build(),
+                    100,
+                    appId,
+                    100,
+                    true);
+            rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
+
+            prev = link.dst();
+            selectorBuilder.matchInport(link.dst().port());
+            //selectorBuilder.setLambda(la.toInt());
+        }
+
+        // build the last T port rule
+        TrafficTreatment treatmentLast = builder()
+                .setOutput(intent.getDst().port()).build();
+        FlowRule rule = new DefaultFlowRule(intent.getDst().deviceId(),
+                selectorBuilder.build(),
+                treatmentLast,
+                100,
+                appId,
+                100,
+                true);
+        rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
+
+        return Lists.newArrayList(new FlowRuleBatchOperation(rules));
+    }
+
+    private LinkResourceAllocations assignWavelength(OpticalPathIntent intent) {
+        LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(),
+                intent.path().links())
+                .addLambdaRequest();
+        LinkResourceAllocations retLambda = resourceService.requestResources(request.build());
+        return retLambda;
+    }
+
+    /*private Lambda assignWavelength(List<Link> links) {
+        // TODO More wavelength assignment algorithm
+        int wavenum = 0;
+        Iterator<Link> itrlink = links.iterator();
+        for (int i = 1; i <= WAVELENGTH; i++) {
+            wavenum = i;
+            boolean found = true;
+            while (itrlink.hasNext()) {
+                Link link = itrlink.next();
+                if (isWavelengthUsed(link, i)) {
+                    found = false;
+                    break;
+                }
+            }
+            // First-Fit wavelength assignment algorithm
+            if (found) {
+                break;
+            }
+        }
+
+        if (wavenum == 0) {
+            return null;
+        }
+
+        Lambda wave = Lambda.valueOf(wavenum);
+        return wave;
+    }
+
+    private boolean isWavelengthUsed(Link link, int i) {
+        Iterable<LinkResourceAllocations> wave = resourceService.getAllocations(link);
+        for (LinkResourceAllocations ir : wave) {
+            //if ir.resources().contains(i) {
+            //}
+        }
+        return false;
+    }*/
+
+    @Override
+    public List<FlowRuleBatchOperation> uninstall(OpticalPathIntent intent) {
+        LinkResourceAllocations allocations = resourceService.getAllocation(intent.id());
+
+        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+        selectorBuilder.matchInport(intent.getSrcConnectPoint().port());
+
+        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+
+        List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
+        ConnectPoint prev = intent.getSrcConnectPoint();
+
+        //TODO throw exception if the lambda was not retrieved successfully
+        for (Link link : intent.path().links()) {
+            Lambda la = null;
+            for (ResourceAllocation allocation : allocations.getResourceAllocation(link)) {
+                if (allocation.type() == ResourceType.LAMBDA) {
+                    la = ((LambdaResourceAllocation) allocation).lambda();
+                    break;
+                }
+            }
+
+            if (la == null) {
+                log.info("Lambda was not retrieved successfully");
+                return null;
+            }
+
+            treatmentBuilder.setOutput(link.src().port());
+            //treatmentBuilder.setLambda(la.toInt());
+
+            FlowRule rule = new DefaultFlowRule(prev.deviceId(),
+                    selectorBuilder.build(),
+                    treatmentBuilder.build(),
+                    100,
+                    appId,
+                    100,
+                    true);
+            rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
+
+            prev = link.dst();
+            selectorBuilder.matchInport(link.dst().port());
+            //selectorBuilder.setLambda(la.toInt());
+        }
+
+        // build the last T port rule
+        TrafficTreatment treatmentLast = builder()
+                .setOutput(intent.getDst().port()).build();
+        FlowRule rule = new DefaultFlowRule(intent.getDst().deviceId(),
+                selectorBuilder.build(),
+                treatmentLast,
+                100,
+                appId,
+                100,
+                true);
+        rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
+
+        return Lists.newArrayList(new FlowRuleBatchOperation(rules));
+    }
+
+}
diff --git a/core/net/src/main/java/org/onlab/onos/net/resource/DefaultLinkResourceAllocations.java b/core/net/src/main/java/org/onlab/onos/net/resource/DefaultLinkResourceAllocations.java
new file mode 100644
index 0000000..76dae01
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/net/resource/DefaultLinkResourceAllocations.java
@@ -0,0 +1,59 @@
+package org.onlab.onos.net.resource;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.intent.IntentId;
+
+/**
+ * Implementation of {@link LinkResourceAllocations}.
+ */
+public class DefaultLinkResourceAllocations implements LinkResourceAllocations {
+    private final LinkResourceRequest request;
+    private final Map<Link, Set<ResourceAllocation>> allocations;
+
+    /**
+     * Creates a new link resource allocations.
+     *
+     * @param request requested resources
+     * @param allocations allocated resources
+     */
+    protected DefaultLinkResourceAllocations(LinkResourceRequest request,
+            Map<Link, Set<ResourceAllocation>> allocations) {
+        this.request = request;
+        this.allocations = allocations;
+    }
+
+    @Override
+    public IntentId intendId() {
+        return request.intendId();
+    }
+
+    @Override
+    public Collection<Link> links() {
+        return request.links();
+    }
+
+    @Override
+    public Set<ResourceRequest> resources() {
+        return request.resources();
+    }
+
+    @Override
+    public ResourceType type() {
+        return null;
+    }
+
+    @Override
+    public Set<ResourceAllocation> getResourceAllocation(Link link) {
+        Set<ResourceAllocation> result = allocations.get(link);
+        if (result == null) {
+            result = Collections.emptySet();
+        }
+        return result;
+    }
+
+}
diff --git a/core/net/src/main/java/org/onlab/onos/net/resource/LinkResourceManager.java b/core/net/src/main/java/org/onlab/onos/net/resource/LinkResourceManager.java
index 7d4da02..a207dbc 100644
--- a/core/net/src/main/java/org/onlab/onos/net/resource/LinkResourceManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/resource/LinkResourceManager.java
@@ -2,6 +2,10 @@
 
 import static org.slf4j.LoggerFactory.getLogger;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -10,6 +14,8 @@
 import org.onlab.onos.net.intent.IntentId;
 import org.slf4j.Logger;
 
+import com.google.common.collect.Sets;
+
 /**
  * Provides basic implementation of link resources allocation.
  */
@@ -31,8 +37,30 @@
 
     @Override
     public LinkResourceAllocations requestResources(LinkResourceRequest req) {
-        // TODO Auto-generated method stub
-        return null;
+        // TODO implement it using a resource data store.
+
+        ResourceAllocation alloc = null;
+        for (ResourceRequest r: req.resources()) {
+            switch (r.type()) {
+            case BANDWIDTH:
+                log.info("requestResources() always returns requested bandwidth");
+                BandwidthResourceRequest br = (BandwidthResourceRequest) r;
+                alloc = new BandwidthResourceAllocation(br.bandwidth());
+                break;
+            case LAMBDA:
+                log.info("requestResources() always returns lambda 7");
+                alloc = new LambdaResourceAllocation(Lambda.valueOf(7));
+                break;
+            default:
+                break;
+            }
+        }
+
+        Map<Link, Set<ResourceAllocation>> allocations = new HashMap<>();
+        for (Link link: req.links()) {
+            allocations.put(link, Sets.newHashSet(alloc));
+        }
+        return new DefaultLinkResourceAllocations(req, allocations);
     }
 
     @Override