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