Using replace instead install when there is already an intent
Fixes the problem of flows being left on the data plane Change-Id: Iec3db8b460123f2744a57d8c08d14c8effe9ec34
Showing
8 changed files
with
59 additions
and
20 deletions
| ... | @@ -50,7 +50,6 @@ public interface IntentInstaller<T extends Intent> { | ... | @@ -50,7 +50,6 @@ public interface IntentInstaller<T extends Intent> { |
| 50 | * @return flow rule operations to complete the replace | 50 | * @return flow rule operations to complete the replace |
| 51 | * @throws IntentException if issues are encountered while uninstalling the intent | 51 | * @throws IntentException if issues are encountered while uninstalling the intent |
| 52 | */ | 52 | */ |
| 53 | - @Deprecated | ||
| 54 | List<FlowRuleBatchOperation> replace(T oldIntent, T newIntent); | 53 | List<FlowRuleBatchOperation> replace(T oldIntent, T newIntent); |
| 55 | 54 | ||
| 56 | } | 55 | } | ... | ... |
| ... | @@ -49,7 +49,7 @@ class InstallCoordinating implements IntentUpdate { | ... | @@ -49,7 +49,7 @@ class InstallCoordinating implements IntentUpdate { |
| 49 | try { | 49 | try { |
| 50 | //FIXME we orphan flow rules that are currently on the data plane | 50 | //FIXME we orphan flow rules that are currently on the data plane |
| 51 | // ... should either reuse them or remove them | 51 | // ... should either reuse them or remove them |
| 52 | - FlowRuleOperations flowRules = intentManager.coordinate(pending); | 52 | + FlowRuleOperations flowRules = intentManager.coordinate(current, pending); |
| 53 | return Optional.of(new Installing(intentManager, pending, flowRules)); | 53 | return Optional.of(new Installing(intentManager, pending, flowRules)); |
| 54 | } catch (IntentException e) { | 54 | } catch (IntentException e) { |
| 55 | log.warn("Unable to generate a FlowRuleOperations from intent {} due to:", pending.intent().id(), e); | 55 | log.warn("Unable to generate a FlowRuleOperations from intent {} due to:", pending.intent().id(), e); | ... | ... |
| ... | @@ -16,7 +16,6 @@ | ... | @@ -16,7 +16,6 @@ |
| 16 | package org.onosproject.net.intent.impl; | 16 | package org.onosproject.net.intent.impl; |
| 17 | 17 | ||
| 18 | import org.onosproject.net.flow.FlowRuleOperations; | 18 | import org.onosproject.net.flow.FlowRuleOperations; |
| 19 | -import org.onosproject.net.intent.Intent; | ||
| 20 | import org.onosproject.net.intent.IntentData; | 19 | import org.onosproject.net.intent.IntentData; |
| 21 | import org.onosproject.net.intent.IntentException; | 20 | import org.onosproject.net.intent.IntentException; |
| 22 | import org.slf4j.Logger; | 21 | import org.slf4j.Logger; |
| ... | @@ -49,9 +48,6 @@ class Installing implements IntentUpdate { | ... | @@ -49,9 +48,6 @@ class Installing implements IntentUpdate { |
| 49 | public Optional<IntentUpdate> execute() { | 48 | public Optional<IntentUpdate> execute() { |
| 50 | try { | 49 | try { |
| 51 | intentManager.flowRuleService.apply(flowRules); // FIXME we need to provide a context | 50 | intentManager.flowRuleService.apply(flowRules); // FIXME we need to provide a context |
| 52 | - for (Intent installable: pending.installables()) { | ||
| 53 | - intentManager.trackerService.addTrackedResources(pending.key(), installable.resources()); | ||
| 54 | - } | ||
| 55 | return Optional.of(new Installed(pending)); | 51 | return Optional.of(new Installed(pending)); |
| 56 | // What kinds of exceptions are thrown by FlowRuleService.apply()? | 52 | // What kinds of exceptions are thrown by FlowRuleService.apply()? |
| 57 | // Is IntentException a correct exception abstraction? | 53 | // Is IntentException a correct exception abstraction? | ... | ... |
| ... | @@ -66,8 +66,10 @@ import java.util.concurrent.Future; | ... | @@ -66,8 +66,10 @@ import java.util.concurrent.Future; |
| 66 | import java.util.stream.Collectors; | 66 | import java.util.stream.Collectors; |
| 67 | 67 | ||
| 68 | import static com.google.common.base.Preconditions.checkNotNull; | 68 | import static com.google.common.base.Preconditions.checkNotNull; |
| 69 | +import static com.google.common.base.Preconditions.checkState; | ||
| 69 | import static java.util.concurrent.Executors.newFixedThreadPool; | 70 | import static java.util.concurrent.Executors.newFixedThreadPool; |
| 70 | import static java.util.concurrent.Executors.newSingleThreadExecutor; | 71 | import static java.util.concurrent.Executors.newSingleThreadExecutor; |
| 72 | +import static org.onlab.util.Tools.isNullOrEmpty; | ||
| 71 | import static org.onlab.util.Tools.namedThreads; | 73 | import static org.onlab.util.Tools.namedThreads; |
| 72 | import static org.onosproject.net.intent.IntentState.*; | 74 | import static org.onosproject.net.intent.IntentState.*; |
| 73 | import static org.slf4j.LoggerFactory.getLogger; | 75 | import static org.slf4j.LoggerFactory.getLogger; |
| ... | @@ -282,13 +284,42 @@ public class IntentManager | ... | @@ -282,13 +284,42 @@ public class IntentManager |
| 282 | 284 | ||
| 283 | //TODO javadoc | 285 | //TODO javadoc |
| 284 | //FIXME | 286 | //FIXME |
| 285 | - FlowRuleOperations coordinate(IntentData pending) { | 287 | + FlowRuleOperations coordinate(IntentData current, IntentData pending) { |
| 286 | - List<Intent> installables = pending.installables(); | 288 | + List<Intent> oldInstallables = (current != null) ? current.installables() : null; |
| 287 | - List<List<FlowRuleBatchOperation>> plans = new ArrayList<>(installables.size()); | 289 | + List<Intent> newInstallables = pending.installables(); |
| 288 | - for (Intent installable : installables) { | 290 | + |
| 289 | - registerSubclassInstallerIfNeeded(installable); | 291 | + checkState(isNullOrEmpty(oldInstallables) || |
| 292 | + oldInstallables.size() == newInstallables.size(), | ||
| 293 | + "Old and New Intent must have equivalent installable intents."); | ||
| 294 | + | ||
| 295 | + List<List<FlowRuleBatchOperation>> plans = new ArrayList<>(); | ||
| 296 | + for (int i = 0; i < newInstallables.size(); i++) { | ||
| 297 | + Intent newInstallable = newInstallables.get(i); | ||
| 298 | + registerSubclassInstallerIfNeeded(newInstallable); | ||
| 290 | //TODO consider migrating installers to FlowRuleOperations | 299 | //TODO consider migrating installers to FlowRuleOperations |
| 291 | - plans.add(getInstaller(installable).install(installable)); | 300 | + /* FIXME |
| 301 | + - we need to do another pass on this method about that doesn't | ||
| 302 | + require the length of installables to be equal, and also doesn't | ||
| 303 | + depend on ordering | ||
| 304 | + - we should also reconsider when to start/stop tracking resources | ||
| 305 | + */ | ||
| 306 | + if (isNullOrEmpty(oldInstallables)) { | ||
| 307 | + plans.add(getInstaller(newInstallable).install(newInstallable)); | ||
| 308 | + } else { | ||
| 309 | + Intent oldInstallable = oldInstallables.get(i); | ||
| 310 | + checkState(oldInstallable.getClass().equals(newInstallable.getClass()), | ||
| 311 | + "Installable Intent type mismatch."); | ||
| 312 | + trackerService.removeTrackedResources(pending.key(), oldInstallable.resources()); | ||
| 313 | + plans.add(getInstaller(newInstallable).replace(oldInstallable, newInstallable)); | ||
| 314 | + } | ||
| 315 | + trackerService.addTrackedResources(pending.key(), newInstallable.resources()); | ||
| 316 | +// } catch (IntentException e) { | ||
| 317 | +// log.warn("Unable to update intent {} due to:", oldIntent.id(), e); | ||
| 318 | +// //FIXME... we failed. need to uninstall (if same) or revert (if different) | ||
| 319 | +// trackerService.removeTrackedResources(newIntent.id(), newInstallable.resources()); | ||
| 320 | +// exception = e; | ||
| 321 | +// batches = uninstallIntent(oldIntent, oldInstallables); | ||
| 322 | +// } | ||
| 292 | } | 323 | } |
| 293 | 324 | ||
| 294 | return merge(plans).build(new FlowRuleOperationsContext() { // TODO move this out | 325 | return merge(plans).build(new FlowRuleOperationsContext() { // TODO move this out |
| ... | @@ -321,6 +352,7 @@ public class IntentManager | ... | @@ -321,6 +352,7 @@ public class IntentManager |
| 321 | List<List<FlowRuleBatchOperation>> plans = new ArrayList<>(); | 352 | List<List<FlowRuleBatchOperation>> plans = new ArrayList<>(); |
| 322 | for (Intent installable : installables) { | 353 | for (Intent installable : installables) { |
| 323 | plans.add(getInstaller(installable).uninstall(installable)); | 354 | plans.add(getInstaller(installable).uninstall(installable)); |
| 355 | + trackerService.removeTrackedResources(pending.key(), installable.resources()); | ||
| 324 | } | 356 | } |
| 325 | 357 | ||
| 326 | return merge(plans).build(new FlowRuleOperationsContext() { | 358 | return merge(plans).build(new FlowRuleOperationsContext() { |
| ... | @@ -494,7 +526,7 @@ public class IntentManager | ... | @@ -494,7 +526,7 @@ public class IntentManager |
| 494 | case INSTALL_REQ: | 526 | case INSTALL_REQ: |
| 495 | return new InstallRequest(this, intentData, Optional.ofNullable(current)); | 527 | return new InstallRequest(this, intentData, Optional.ofNullable(current)); |
| 496 | case WITHDRAW_REQ: | 528 | case WITHDRAW_REQ: |
| 497 | - if (current == null) { | 529 | + if (current == null || isNullOrEmpty(current.installables())) { |
| 498 | return new Withdrawn(current, WITHDRAWN); | 530 | return new Withdrawn(current, WITHDRAWN); |
| 499 | } else { | 531 | } else { |
| 500 | return new WithdrawRequest(this, intentData, current); | 532 | return new WithdrawRequest(this, intentData, current); | ... | ... |
| ... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
| 16 | package org.onosproject.net.intent.impl; | 16 | package org.onosproject.net.intent.impl; |
| 17 | 17 | ||
| 18 | import com.google.common.collect.HashMultimap; | 18 | import com.google.common.collect.HashMultimap; |
| 19 | +import com.google.common.collect.Lists; | ||
| 19 | import com.google.common.collect.SetMultimap; | 20 | import com.google.common.collect.SetMultimap; |
| 20 | import org.apache.felix.scr.annotations.Activate; | 21 | import org.apache.felix.scr.annotations.Activate; |
| 21 | import org.apache.felix.scr.annotations.Component; | 22 | import org.apache.felix.scr.annotations.Component; |
| ... | @@ -112,10 +113,13 @@ public class LinkCollectionIntentInstaller | ... | @@ -112,10 +113,13 @@ public class LinkCollectionIntentInstaller |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | @Override | 115 | @Override |
| 115 | - public List<FlowRuleBatchOperation> replace(LinkCollectionIntent intent, | 116 | + public List<FlowRuleBatchOperation> replace(LinkCollectionIntent oldIntent, |
| 116 | LinkCollectionIntent newIntent) { | 117 | LinkCollectionIntent newIntent) { |
| 117 | - // FIXME: implement | 118 | + // FIXME: implement this in a more intelligent/less brute force way |
| 118 | - return null; | 119 | + List<FlowRuleBatchOperation> batches = Lists.newArrayList(); |
| 120 | + batches.addAll(uninstall(oldIntent)); | ||
| 121 | + batches.addAll(install(newIntent)); | ||
| 122 | + return batches; | ||
| 119 | } | 123 | } |
| 120 | 124 | ||
| 121 | /** | 125 | /** | ... | ... |
| ... | @@ -47,6 +47,7 @@ class WithdrawCoordinating implements IntentUpdate { | ... | @@ -47,6 +47,7 @@ class WithdrawCoordinating implements IntentUpdate { |
| 47 | @Override | 47 | @Override |
| 48 | public Optional<IntentUpdate> execute() { | 48 | public Optional<IntentUpdate> execute() { |
| 49 | try { | 49 | try { |
| 50 | + // Note: current.installables() are not null or empty due to createIntentUpdate check | ||
| 50 | FlowRuleOperations flowRules = intentManager.uninstallCoordinate(current, pending); | 51 | FlowRuleOperations flowRules = intentManager.uninstallCoordinate(current, pending); |
| 51 | pending.setInstallables(current.installables()); | 52 | pending.setInstallables(current.installables()); |
| 52 | return Optional.of(new Withdrawing(intentManager, pending, flowRules)); | 53 | return Optional.of(new Withdrawing(intentManager, pending, flowRules)); | ... | ... |
| ... | @@ -16,7 +16,6 @@ | ... | @@ -16,7 +16,6 @@ |
| 16 | package org.onosproject.net.intent.impl; | 16 | package org.onosproject.net.intent.impl; |
| 17 | 17 | ||
| 18 | import org.onosproject.net.flow.FlowRuleOperations; | 18 | import org.onosproject.net.flow.FlowRuleOperations; |
| 19 | -import org.onosproject.net.intent.Intent; | ||
| 20 | import org.onosproject.net.intent.IntentData; | 19 | import org.onosproject.net.intent.IntentData; |
| 21 | 20 | ||
| 22 | import java.util.Optional; | 21 | import java.util.Optional; |
| ... | @@ -43,9 +42,6 @@ class Withdrawing implements IntentUpdate { | ... | @@ -43,9 +42,6 @@ class Withdrawing implements IntentUpdate { |
| 43 | @Override | 42 | @Override |
| 44 | public Optional<IntentUpdate> execute() { | 43 | public Optional<IntentUpdate> execute() { |
| 45 | intentManager.flowRuleService.apply(flowRules); | 44 | intentManager.flowRuleService.apply(flowRules); |
| 46 | - for (Intent installable: pending.installables()) { | ||
| 47 | - intentManager.trackerService.removeTrackedResources(pending.key(), installable.resources()); | ||
| 48 | - } | ||
| 49 | return Optional.of(new Withdrawn(pending)); | 45 | return Optional.of(new Withdrawn(pending)); |
| 50 | } | 46 | } |
| 51 | } | 47 | } | ... | ... |
| ... | @@ -34,6 +34,7 @@ import java.nio.file.SimpleFileVisitor; | ... | @@ -34,6 +34,7 @@ import java.nio.file.SimpleFileVisitor; |
| 34 | import java.nio.file.StandardCopyOption; | 34 | import java.nio.file.StandardCopyOption; |
| 35 | import java.nio.file.attribute.BasicFileAttributes; | 35 | import java.nio.file.attribute.BasicFileAttributes; |
| 36 | import java.util.ArrayList; | 36 | import java.util.ArrayList; |
| 37 | +import java.util.Collection; | ||
| 37 | import java.util.List; | 38 | import java.util.List; |
| 38 | import java.util.concurrent.ThreadFactory; | 39 | import java.util.concurrent.ThreadFactory; |
| 39 | 40 | ||
| ... | @@ -84,6 +85,16 @@ public abstract class Tools { | ... | @@ -84,6 +85,16 @@ public abstract class Tools { |
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | /** | 87 | /** |
| 88 | + * Returns true if the collection is null or is empty. | ||
| 89 | + * | ||
| 90 | + * @param collection collection to test | ||
| 91 | + * @return true if null or empty; false otherwise | ||
| 92 | + */ | ||
| 93 | + public static boolean isNullOrEmpty(Collection collection) { | ||
| 94 | + return collection == null || collection.isEmpty(); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + /** | ||
| 87 | * Converts a string from hex to long. | 98 | * Converts a string from hex to long. |
| 88 | * | 99 | * |
| 89 | * @param string hex number in string form; sans 0x | 100 | * @param string hex number in string form; sans 0x | ... | ... |
-
Please register or login to post a comment