optical intent module

Change-Id: Ifa405ab1d883b293d349f1b66d26a05a0724691f
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
index 95b5041..e91235c 100644
--- 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
@@ -1,7 +1,10 @@
 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;
@@ -9,25 +12,25 @@
 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.IdGenerator;
 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.IntentId;
 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.TopologyGraph;
 import org.onlab.onos.net.topology.TopologyService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -63,12 +66,12 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected CoreService coreService;
 
-    // protected LinkResourceService resourceService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceService;
 
     private ApplicationId appId;
-    private static long intentId = 0x9000000;
 
-    protected IdGenerator<IntentId> intentIdGenerator;
+    //protected <IntentId> intentIdGenerator;
 
     private final InternalOpticalPathProvisioner pathProvisioner = new InternalOpticalPathProvisioner();
 
@@ -106,7 +109,7 @@
         }
 
         private void setuplightpath(Intent intent) {
-           // TODO: considering user policies and optical reach, may generate more OpticalConnectivityIntents
+           // TODO: considering user policies and optical reach
            if (!intent.equals(PointToPointIntent.class)) {
                return;
            }
@@ -116,35 +119,103 @@
                return;
            }
 
-           // Set<Port> port1 = deviceService.getPorts(pktIntent.ingressPoint().deviceId());
+           Topology topology = topologyService.currentTopology();
+           TopologyGraph graph = topologyService.getGraph(topology);
 
-           Set<Link> srcLink = linkService.getLinks(pktIntent.ingressPoint());
-           Set<Link> dstLink = linkService.getLinks(pktIntent.egressPoint());
+           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
+                   }
+               }
+           };
 
-           if (srcLink.isEmpty() || dstLink.isEmpty()) {
+           Set<Path> paths = topologyService.getPaths(topology,
+                   pktIntent.ingressPoint().deviceId(),
+                   pktIntent.egressPoint().deviceId(),
+                   weight);
+
+           if (paths.isEmpty()) {
                return;
            }
 
-           Iterator<Link> itrSrc = srcLink.iterator();
-           Iterator<Link> itrDst = dstLink.iterator();
+           ConnectPoint srcWdmPoint = null;
+           ConnectPoint dstWdmPoint = null;
+           Iterator<Path> itrPath = paths.iterator();
+           Path firstPath = itrPath.next();
+           log.info(firstPath.toString());
 
-           if (!itrSrc.next().annotations().value("linkType").equals("PktOptLink")) {
-               return;
-           }
-           if (!itrDst.next().annotations().value("linkType").equals("PktOptLink")) {
-               return;
+           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);
            }
 
-           ConnectPoint srcWdmPoint = itrSrc.next().dst();
-           ConnectPoint dstWdmPoint = itrDst.next().dst();
+           for (Map<ConnectPoint, ConnectPoint> map : connectionList) {
+               for (Entry<ConnectPoint, ConnectPoint> entry : map.entrySet()) {
 
-           OpticalConnectivityIntent opticalIntent =
-                    new OpticalConnectivityIntent(new IntentId(intentId++),
-                    srcWdmPoint,
-                    dstWdmPoint);
+                   ConnectPoint src = entry.getKey();
+                   ConnectPoint dst = entry.getValue();
 
-           log.info(opticalIntent.toString());
-           intentService.submit(opticalIntent);
+                   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) {
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
index 4e4ebe5..6e595c5 100644
--- 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
@@ -1,13 +1,14 @@
 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 a Transponder port to another
+ * 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 AbstractIntent {
+public class OpticalConnectivityIntent extends Intent {
     protected ConnectPoint src;
     protected ConnectPoint dst;
 
@@ -18,8 +19,9 @@
      * @param src The source transponder port.
      * @param dst The destination transponder port.
      */
-    public OpticalConnectivityIntent(IntentId id, ConnectPoint src, ConnectPoint dst) {
-        super(id);
+    public OpticalConnectivityIntent(ApplicationId appId, ConnectPoint src, ConnectPoint dst) {
+        super(id(OpticalConnectivityIntent.class, src, dst),
+                appId, null);
         this.src = src;
         this.dst = 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
index d0d73d9..1ad828d 100644
--- 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
@@ -1,8 +1,8 @@
 package org.onlab.onos.net.intent;
 
 import java.util.Collection;
-import java.util.Objects;
 
+import org.onlab.onos.ApplicationId;
 import org.onlab.onos.net.ConnectPoint;
 import org.onlab.onos.net.Link;
 import org.onlab.onos.net.Path;
@@ -11,15 +11,18 @@
 
 import com.google.common.base.MoreObjects;
 
-public class OpticalPathIntent extends OpticalConnectivityIntent implements InstallableIntent {
-
+public class OpticalPathIntent extends OpticalConnectivityIntent {
     private final Path path;
     private final TrafficSelector opticalMatch;
     private final TrafficTreatment opticalAction;
 
-    public OpticalPathIntent(IntentId id, TrafficSelector match, TrafficTreatment action,
-                      ConnectPoint ingressPort, ConnectPoint egressPort,
-                      Path path) {
+    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;
@@ -44,32 +47,11 @@
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        if (!super.equals(o)) {
-            return false;
-        }
-
-        OpticalPathIntent that = (OpticalPathIntent) o;
-
-        if (!path.equals(that.path)) {
-            return false;
-        }
-
+    public boolean isInstallable() {
         return true;
     }
 
     @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), path);
-    }
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
@@ -81,7 +63,6 @@
                 .toString();
     }
 
-    @Override
     public Collection<Link> requiredLinks() {
         return path.links();
     }
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
index d888ed3..e44a01b 100644
--- 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
@@ -3,7 +3,7 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.util.ArrayList;
-
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -12,24 +12,28 @@
 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.DefaultEdgeLink;
-
 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.IdGenerator;
 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.IntentId;
+
 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;
 
 /**
@@ -49,14 +53,17 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected PathService pathService;
 
-    // protected LinkResourceService resourceService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TopologyService topologyService;
 
-    protected IdGenerator<IntentId> intentIdGenerator;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
 
     @Activate
     public void activate() {
-        IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
-        intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
         intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
     }
 
@@ -67,29 +74,29 @@
 
     @Override
     public List<Intent> compile(OpticalConnectivityIntent intent) {
-        // TO DO: compute multiple paths using the K-shortest path algorithm
+        // TODO: compute multiple paths using the K-shortest path algorithm
+        List<Intent> retList = new ArrayList<>();
         Path path = calculatePath(intent.getSrcConnectPoint(), intent.getDst());
-        log.info("calculate the lightpath: {}.", path.toString());
+        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));
 
-        // TO DO: choose a wavelength using the first-fit algorithm
         TrafficSelector opticalSelector = null;
         TrafficTreatment opticalTreatment = null;
 
-        List<Intent> retList = new ArrayList<>();
-        int wavelength = assignWavelength(path);
-        log.info("assign the wavelength: {}.", wavelength);
-
         // create a new opticalPathIntent
-        Intent newIntent = new OpticalPathIntent(intentIdGenerator.getNewId(),
-                opticalSelector,
-                opticalTreatment,
+        Intent newIntent = new OpticalPathIntent(intent.appId(),
                 path.src(),
                 path.dst(),
+                opticalSelector,
+                opticalTreatment,
                 path);
 
         retList.add(newIntent);
@@ -97,18 +104,45 @@
         return retList;
     }
 
-    private Path calculatePath(ConnectPoint one, ConnectPoint two) {
-        // TODO: K-shortest path computation algorithm
-        Set<Path> paths = pathService.getPaths(one.deviceId(), two.deviceId());
-        if (paths.isEmpty()) {
-            throw new PathNotFoundException("No optical path from " + one + " to " + two);
-        }
-        return paths.iterator().next();
-    }
+    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
+                }
+            }
+        };
 
-    private int assignWavelength(Path path) {
-        // TODO: wavelength assignment
-        return 1;
+        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
index 2e4f2fd..1f7ef68 100644
--- 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
@@ -19,6 +19,7 @@
 import org.onlab.onos.net.flow.CompletedBatchOperation;
 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;
@@ -29,6 +30,12 @@
 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.Lambda;
+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.ResourceRequest;
+import org.onlab.onos.net.topology.TopologyService;
 import org.slf4j.Logger;
 
 import com.google.common.collect.Lists;
@@ -41,7 +48,6 @@
 
 @Component(immediate = true)
 public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIntent> {
-
     private final Logger log = getLogger(getClass());
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -53,8 +59,16 @@
     @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 static short WAVELENGTH = 80;
+
     @Activate
     public void activate() {
         appId = coreService.registerApplication("org.onlab.onos.net.intent");
@@ -67,42 +81,25 @@
     }
 
     @Override
-    public Future<CompletedBatchOperation> install(OpticalPathIntent intent) {
-        TrafficSelector.Builder builder =
-                DefaultTrafficSelector.builder(intent.selector());
-        Iterator<Link> links = intent.path().links().iterator();
-        ConnectPoint prev = links.next().dst();
-        List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
-        while (links.hasNext()) {
-            builder.matchInport(prev.port());
-            Link link = links.next();
-            TrafficTreatment treatment = builder()
-                    .setOutput(link.src().port()).build();
-
-            FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
-                    builder.build(),
-                    treatment,
-                    100,   // priority is set to 100
-                    appId,
-                    100); // ROADM may need longer cross-connect time, here it is assumed 100ms.
-
-            rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
-            prev = link.dst();
+    public List<FlowRuleBatchOperation> install(OpticalPathIntent intent) {
+        Lambda la = assignWavelength(intent.path().links());
+        if (la == null) {
+            return null;
         }
+        // resourceService.requestResources(la);
+        // la.toInt();
+        //intent.selector().criteria();
 
-        FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
-        Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
-        return future;
-    }
+        //TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
+        //builder.matchLambdaType(la.toInt())
+        //        .matchInport(intent.getSrcConnectPoint().port());
 
-    @Override
-    public Future<CompletedBatchOperation> uninstall(OpticalPathIntent intent) {
         TrafficSelector.Builder builder =
                 DefaultTrafficSelector.builder(intent.selector());
         Iterator<Link> links = intent.path().links().iterator();
         ConnectPoint prev = links.next().dst();
         List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
-
+        // TODO Generate multiple batches
         while (links.hasNext()) {
             builder.matchInport(prev.port());
             Link link = links.next();
@@ -114,15 +111,75 @@
                     treatment,
                     100,
                     appId,
-                    100);
+                    100,
+                    true);
+            rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
+            prev = link.dst();
+        }
+        return Lists.newArrayList(new FlowRuleBatchOperation(rules));
+    }
 
+    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) {
+        TrafficSelector.Builder builder =
+                DefaultTrafficSelector.builder(intent.selector());
+        Iterator<Link> links = intent.path().links().iterator();
+        ConnectPoint prev = links.next().dst();
+        List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
+        // TODO Generate multiple batches
+        while (links.hasNext()) {
+            builder.matchInport(prev.port());
+            Link link = links.next();
+            TrafficTreatment treatment = builder()
+                    .setOutput(link.src().port()).build();
+            FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
+                    builder.build(),
+                    treatment,
+                    100,
+                    appId,
+                    100,
+                    true);
             rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
             prev = link.dst();
         }
-
-        FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
-        Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
-        return future;
+        return Lists.newArrayList(new FlowRuleBatchOperation(rules));
     }
 
 }