tom

Starting to experiment with flow tracking.

...@@ -6,6 +6,7 @@ import com.google.common.base.MoreObjects; ...@@ -6,6 +6,7 @@ import com.google.common.base.MoreObjects;
6 6
7 // TODO Consider renaming. 7 // TODO Consider renaming.
8 // it's an identifier for a Link, but it's not ElementId, so not using LinkId. 8 // it's an identifier for a Link, but it's not ElementId, so not using LinkId.
9 +
9 /** 10 /**
10 * Immutable representation of a link identity. 11 * Immutable representation of a link identity.
11 */ 12 */
...@@ -43,6 +44,15 @@ public class LinkKey { ...@@ -43,6 +44,15 @@ public class LinkKey {
43 this.dst = dst; 44 this.dst = dst;
44 } 45 }
45 46
47 + /**
48 + * Creates a link identifier for the specified link.
49 + *
50 + * @param link link descriptor
51 + */
52 + public LinkKey(Link link) {
53 + this(link.src(), link.dst());
54 + }
55 +
46 @Override 56 @Override
47 public int hashCode() { 57 public int hashCode() {
48 return Objects.hash(src(), dst); 58 return Objects.hash(src(), dst);
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 +import org.onlab.onos.net.Link;
4 +
5 +import java.util.Collection;
6 +
3 /** 7 /**
4 * Abstraction of an intent that can be installed into 8 * Abstraction of an intent that can be installed into
5 * the underlying system without additional compilation. 9 * the underlying system without additional compilation.
6 */ 10 */
7 public interface InstallableIntent extends Intent { 11 public interface InstallableIntent extends Intent {
12 +
13 + /**
14 + * Returns the collection of links that are required for this installable
15 + * intent to exist.
16 + *
17 + * @return collection of links
18 + */
19 + // FIXME: replace this with 'NetworkResource'
20 + Collection<Link> requiredLinks();
21 +
8 } 22 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import java.util.Objects; 3 +import com.google.common.base.MoreObjects;
4 -
5 import org.onlab.onos.net.ConnectPoint; 4 import org.onlab.onos.net.ConnectPoint;
5 +import org.onlab.onos.net.Link;
6 import org.onlab.onos.net.Path; 6 import org.onlab.onos.net.Path;
7 import org.onlab.onos.net.flow.TrafficSelector; 7 import org.onlab.onos.net.flow.TrafficSelector;
8 import org.onlab.onos.net.flow.TrafficTreatment; 8 import org.onlab.onos.net.flow.TrafficTreatment;
9 9
10 -import com.google.common.base.MoreObjects; 10 +import java.util.Collection;
11 +import java.util.Objects;
11 12
12 /** 13 /**
13 * Abstraction of explicitly path specified connectivity intent. 14 * Abstraction of explicitly path specified connectivity intent.
...@@ -86,4 +87,10 @@ public class PathIntent extends PointToPointIntent implements InstallableIntent ...@@ -86,4 +87,10 @@ public class PathIntent extends PointToPointIntent implements InstallableIntent
86 .add("path", path) 87 .add("path", path)
87 .toString(); 88 .toString();
88 } 89 }
90 +
91 + @Override
92 + public Collection<Link> requiredLinks() {
93 + return path.links();
94 + }
95 +
89 } 96 }
......
1 package org.onlab.onos.net.topology; 1 package org.onlab.onos.net.topology;
2 2
3 import org.onlab.onos.event.AbstractEvent; 3 import org.onlab.onos.event.AbstractEvent;
4 +import org.onlab.onos.event.Event;
5 +
6 +import java.util.List;
4 7
5 /** 8 /**
6 * Describes network topology event. 9 * Describes network topology event.
7 */ 10 */
8 public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> { 11 public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> {
9 12
13 + private final List<Event> reasons;
14 +
10 /** 15 /**
11 * Type of topology events. 16 * Type of topology events.
12 */ 17 */
...@@ -23,9 +28,11 @@ public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> { ...@@ -23,9 +28,11 @@ public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> {
23 * 28 *
24 * @param type topology event type 29 * @param type topology event type
25 * @param topology event topology subject 30 * @param topology event topology subject
31 + * @param reasons list of events that triggered topology change
26 */ 32 */
27 - public TopologyEvent(Type type, Topology topology) { 33 + public TopologyEvent(Type type, Topology topology, List<Event> reasons) {
28 super(type, topology); 34 super(type, topology);
35 + this.reasons = reasons;
29 } 36 }
30 37
31 /** 38 /**
...@@ -33,10 +40,24 @@ public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> { ...@@ -33,10 +40,24 @@ public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> {
33 * 40 *
34 * @param type link event type 41 * @param type link event type
35 * @param topology event topology subject 42 * @param topology event topology subject
43 + * @param reasons list of events that triggered topology change
36 * @param time occurrence time 44 * @param time occurrence time
37 */ 45 */
38 - public TopologyEvent(Type type, Topology topology, long time) { 46 + public TopologyEvent(Type type, Topology topology, List<Event> reasons,
47 + long time) {
39 super(type, topology, time); 48 super(type, topology, time);
49 + this.reasons = reasons;
50 + }
51 +
52 +
53 + /**
54 + * Returns the list of events that triggered the topology change.
55 + *
56 + * @return list of events responsible for change in topology; null if
57 + * initial topology computation
58 + */
59 + public List<Event> reasons() {
60 + return reasons;
40 } 61 }
41 62
42 } 63 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 //TODO is this the right package? 2 //TODO is this the right package?
3 3
4 +import org.onlab.onos.net.Link;
5 +
6 +import java.util.Collection;
7 +
4 /** 8 /**
5 * An installable intent used in the unit test. 9 * An installable intent used in the unit test.
6 * 10 *
...@@ -25,4 +29,8 @@ public class TestInstallableIntent extends AbstractIntent implements Installable ...@@ -25,4 +29,8 @@ public class TestInstallableIntent extends AbstractIntent implements Installable
25 super(); 29 super();
26 } 30 }
27 31
32 + @Override
33 + public Collection<Link> requiredLinks() {
34 + return null;
35 + }
28 } 36 }
......
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import com.google.common.collect.HashMultimap;
4 +import com.google.common.collect.SetMultimap;
5 +import org.apache.felix.scr.annotations.Activate;
6 +import org.apache.felix.scr.annotations.Component;
7 +import org.apache.felix.scr.annotations.Deactivate;
8 +import org.apache.felix.scr.annotations.Reference;
9 +import org.apache.felix.scr.annotations.ReferenceCardinality;
10 +import org.apache.felix.scr.annotations.Service;
11 +import org.onlab.onos.event.Event;
12 +import org.onlab.onos.net.Link;
13 +import org.onlab.onos.net.LinkKey;
14 +import org.onlab.onos.net.intent.IntentId;
15 +import org.onlab.onos.net.link.LinkEvent;
16 +import org.onlab.onos.net.topology.TopologyEvent;
17 +import org.onlab.onos.net.topology.TopologyListener;
18 +import org.onlab.onos.net.topology.TopologyService;
19 +import org.slf4j.Logger;
20 +
21 +import java.util.Collection;
22 +import java.util.concurrent.ExecutorService;
23 +
24 +import static com.google.common.base.Preconditions.checkArgument;
25 +import static com.google.common.base.Preconditions.checkNotNull;
26 +import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
27 +import static java.util.concurrent.Executors.newSingleThreadExecutor;
28 +import static org.onlab.util.Tools.namedThreads;
29 +import static org.slf4j.LoggerFactory.getLogger;
30 +
31 +/**
32 + * Entity responsible for tracking installed flows and for monitoring topology
33 + * events to determine what flows are affected by topology changes.
34 + */
35 +@Component
36 +@Service
37 +public class FlowTracker implements FlowTrackerService {
38 +
39 + private final Logger log = getLogger(getClass());
40 +
41 + private final SetMultimap<LinkKey, IntentId> intentsByLink =
42 + synchronizedSetMultimap(HashMultimap.<LinkKey, IntentId>create());
43 +
44 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
45 + protected TopologyService topologyService;
46 +
47 + private ExecutorService executorService =
48 + newSingleThreadExecutor(namedThreads("onos-flowtracker"));
49 +
50 + private TopologyListener listener = new InternalTopologyListener();
51 + private TopologyChangeDelegate delegate;
52 +
53 + @Activate
54 + public void activate() {
55 + topologyService.addListener(listener);
56 + log.info("Started");
57 + }
58 +
59 + @Deactivate
60 + public void deactivate() {
61 + topologyService.removeListener(listener);
62 + log.info("Stopped");
63 + }
64 +
65 + @Override
66 + public void setDelegate(TopologyChangeDelegate delegate) {
67 + checkNotNull(delegate, "Delegate cannot be null");
68 + checkArgument(this.delegate == null || this.delegate == delegate,
69 + "Another delegate already set");
70 + this.delegate = delegate;
71 + }
72 +
73 + @Override
74 + public void unsetDelegate(TopologyChangeDelegate delegate) {
75 + checkArgument(this.delegate == delegate, "Not the current delegate");
76 + this.delegate = null;
77 + }
78 +
79 + @Override
80 + public void addTrackedResources(IntentId intentId, Collection<Link> resources) {
81 + for (Link link : resources) {
82 + intentsByLink.put(new LinkKey(link), intentId);
83 + }
84 + }
85 +
86 + @Override
87 + public void removeTrackedResources(IntentId intentId, Collection<Link> resources) {
88 + for (Link link : resources) {
89 + intentsByLink.remove(new LinkKey(link), intentId);
90 + }
91 + }
92 +
93 + // Internal re-actor to topology change events.
94 + private class InternalTopologyListener implements TopologyListener {
95 + @Override
96 + public void event(TopologyEvent event) {
97 + executorService.execute(new TopologyChangeHandler(event));
98 + }
99 + }
100 +
101 + // Re-dispatcher of topology change events.
102 + private class TopologyChangeHandler implements Runnable {
103 +
104 + private final TopologyEvent event;
105 +
106 + TopologyChangeHandler(TopologyEvent event) {
107 + this.event = event;
108 + }
109 +
110 + @Override
111 + public void run() {
112 + if (event.reasons() == null) {
113 + delegate.bumpIntents(intentsByLink.values());
114 + } else {
115 + for (Event reason : event.reasons()) {
116 + if (reason instanceof LinkEvent) {
117 + LinkEvent linkEvent = (LinkEvent) reason;
118 + if (linkEvent.type() == LinkEvent.Type.LINK_ADDED ||
119 + linkEvent.type() == LinkEvent.Type.LINK_UPDATED) {
120 + delegate.bumpIntents(intentsByLink.get(new LinkKey(linkEvent.subject())));
121 + } else if (linkEvent.type() == LinkEvent.Type.LINK_REMOVED) {
122 + delegate.failIntents(intentsByLink.get(new LinkKey(linkEvent.subject())));
123 + }
124 + }
125 + }
126 + }
127 + }
128 + }
129 +
130 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.Link;
4 +import org.onlab.onos.net.intent.IntentId;
5 +
6 +import java.util.Collection;
7 +
8 +/**
9 + * Auxiliary service for tracking intent path flows and for notifying the
10 + * intent service of environment changes via topology change delegate.
11 + */
12 +public interface FlowTrackerService {
13 +
14 + /**
15 + * Sets a topology change delegate.
16 + *
17 + * @param delegate topology change delegate
18 + */
19 + void setDelegate(TopologyChangeDelegate delegate);
20 +
21 + /**
22 + * Unsets topology change delegate.
23 + *
24 + * @param delegate topology change delegate
25 + */
26 + void unsetDelegate(TopologyChangeDelegate delegate);
27 +
28 + /**
29 + * Adds a path flow to be tracked.
30 + *
31 + * @param intentId intent identity on whose behalf the path is being tracked
32 + * @param resources resources to track
33 + */
34 + public void addTrackedResources(IntentId intentId, Collection<Link> resources);
35 +
36 + /**
37 + * Removes a path flow to be tracked.
38 + *
39 + * @param intentId intent identity on whose behalf the path is being tracked
40 + * @param resources resources to stop tracking
41 + */
42 + public void removeTrackedResources(IntentId intentId, Collection<Link> resources);
43 +
44 +}
1 package org.onlab.onos.net.intent.impl; 1 package org.onlab.onos.net.intent.impl;
2 2
3 -import static com.google.common.base.Preconditions.checkNotNull; 3 +import com.google.common.collect.ImmutableMap;
4 -import static org.onlab.onos.net.intent.IntentState.FAILED;
5 -import static org.onlab.onos.net.intent.IntentState.INSTALLED;
6 -import static org.onlab.onos.net.intent.IntentState.WITHDRAWING;
7 -import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
8 -import static org.slf4j.LoggerFactory.getLogger;
9 -
10 -import java.util.ArrayList;
11 -import java.util.List;
12 -import java.util.Map;
13 -import java.util.concurrent.ConcurrentHashMap;
14 -import java.util.concurrent.ConcurrentMap;
15 -import java.util.concurrent.CopyOnWriteArrayList;
16 -
17 import org.apache.felix.scr.annotations.Activate; 4 import org.apache.felix.scr.annotations.Activate;
18 import org.apache.felix.scr.annotations.Component; 5 import org.apache.felix.scr.annotations.Component;
19 import org.apache.felix.scr.annotations.Deactivate; 6 import org.apache.felix.scr.annotations.Deactivate;
...@@ -38,7 +25,15 @@ import org.onlab.onos.net.intent.IntentStore; ...@@ -38,7 +25,15 @@ import org.onlab.onos.net.intent.IntentStore;
38 import org.onlab.onos.net.intent.IntentStoreDelegate; 25 import org.onlab.onos.net.intent.IntentStoreDelegate;
39 import org.slf4j.Logger; 26 import org.slf4j.Logger;
40 27
41 -import com.google.common.collect.ImmutableMap; 28 +import java.util.ArrayList;
29 +import java.util.List;
30 +import java.util.Map;
31 +import java.util.concurrent.ConcurrentHashMap;
32 +import java.util.concurrent.ConcurrentMap;
33 +
34 +import static com.google.common.base.Preconditions.checkNotNull;
35 +import static org.onlab.onos.net.intent.IntentState.*;
36 +import static org.slf4j.LoggerFactory.getLogger;
42 37
43 /** 38 /**
44 * An implementation of Intent Manager. 39 * An implementation of Intent Manager.
...@@ -57,37 +52,34 @@ public class IntentManager ...@@ -57,37 +52,34 @@ public class IntentManager
57 IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>(); 52 IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>();
58 private final ConcurrentMap<Class<? extends InstallableIntent>, 53 private final ConcurrentMap<Class<? extends InstallableIntent>,
59 IntentInstaller<? extends InstallableIntent>> installers = new ConcurrentHashMap<>(); 54 IntentInstaller<? extends InstallableIntent>> installers = new ConcurrentHashMap<>();
60 - private final CopyOnWriteArrayList<IntentListener> listeners = new CopyOnWriteArrayList<>();
61 55
62 private final AbstractListenerRegistry<IntentEvent, IntentListener> 56 private final AbstractListenerRegistry<IntentEvent, IntentListener>
63 - listenerRegistry = new AbstractListenerRegistry<>(); 57 + listenerRegistry = new AbstractListenerRegistry<>();
64 58
65 private final IntentStoreDelegate delegate = new InternalStoreDelegate(); 59 private final IntentStoreDelegate delegate = new InternalStoreDelegate();
60 + private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
66 61
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected IntentStore store; 63 protected IntentStore store;
69 64
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 + protected FlowTrackerService trackerService;
67 +
68 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected EventDeliveryService eventDispatcher; 69 protected EventDeliveryService eventDispatcher;
72 70
73 @Activate 71 @Activate
74 public void activate() { 72 public void activate() {
75 store.setDelegate(delegate); 73 store.setDelegate(delegate);
74 + trackerService.setDelegate(topoDelegate);
76 eventDispatcher.addSink(IntentEvent.class, listenerRegistry); 75 eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
77 -
78 -// this.intentEvents = new IntentMap<>("intentState", IntentEvent.class, collectionsService);
79 -// this.installableIntents =
80 -// new IntentMap<>("installableIntents", IntentCompilationResult.class, collectionsService);
81 -//
82 -//
83 -// this.intentEvents.addListener(new InternalEntryListener(new InternalIntentEventListener()));
84 -
85 log.info("Started"); 76 log.info("Started");
86 } 77 }
87 78
88 @Deactivate 79 @Deactivate
89 public void deactivate() { 80 public void deactivate() {
90 store.unsetDelegate(delegate); 81 store.unsetDelegate(delegate);
82 + trackerService.unsetDelegate(topoDelegate);
91 eventDispatcher.removeSink(IntentEvent.class); 83 eventDispatcher.removeSink(IntentEvent.class);
92 log.info("Stopped"); 84 log.info("Stopped");
93 } 85 }
...@@ -97,7 +89,6 @@ public class IntentManager ...@@ -97,7 +89,6 @@ public class IntentManager
97 checkNotNull(intent, INTENT_NULL); 89 checkNotNull(intent, INTENT_NULL);
98 registerSubclassCompilerIfNeeded(intent); 90 registerSubclassCompilerIfNeeded(intent);
99 IntentEvent event = store.createIntent(intent); 91 IntentEvent event = store.createIntent(intent);
100 - eventDispatcher.post(event);
101 processStoreEvent(event); 92 processStoreEvent(event);
102 } 93 }
103 94
...@@ -105,7 +96,13 @@ public class IntentManager ...@@ -105,7 +96,13 @@ public class IntentManager
105 public void withdraw(Intent intent) { 96 public void withdraw(Intent intent) {
106 checkNotNull(intent, INTENT_NULL); 97 checkNotNull(intent, INTENT_NULL);
107 IntentEvent event = store.setState(intent, WITHDRAWING); 98 IntentEvent event = store.setState(intent, WITHDRAWING);
108 - eventDispatcher.post(event); 99 + List<InstallableIntent> installables = store.getInstallableIntents(intent.getId());
100 + if (installables != null) {
101 + for (InstallableIntent installable : installables) {
102 + trackerService.removeTrackedResources(intent.getId(),
103 + installable.requiredLinks());
104 + }
105 + }
109 processStoreEvent(event); 106 processStoreEvent(event);
110 } 107 }
111 108
...@@ -178,21 +175,10 @@ public class IntentManager ...@@ -178,21 +175,10 @@ public class IntentManager
178 } 175 }
179 176
180 /** 177 /**
181 - * Invokes all of registered intent event listener.
182 - *
183 - * @param event event supplied to a listener as an argument
184 - */
185 - private void invokeListeners(IntentEvent event) {
186 - for (IntentListener listener : listeners) {
187 - listener.event(event);
188 - }
189 - }
190 -
191 - /**
192 * Returns the corresponding intent compiler to the specified intent. 178 * Returns the corresponding intent compiler to the specified intent.
193 * 179 *
194 * @param intent intent 180 * @param intent intent
195 - * @param <T> the type of intent 181 + * @param <T> the type of intent
196 * @return intent compiler corresponding to the specified intent 182 * @return intent compiler corresponding to the specified intent
197 */ 183 */
198 private <T extends Intent> IntentCompiler<T> getCompiler(T intent) { 184 private <T extends Intent> IntentCompiler<T> getCompiler(T intent) {
...@@ -206,8 +192,9 @@ public class IntentManager ...@@ -206,8 +192,9 @@ public class IntentManager
206 192
207 /** 193 /**
208 * Returns the corresponding intent installer to the specified installable intent. 194 * Returns the corresponding intent installer to the specified installable intent.
195 + *
209 * @param intent intent 196 * @param intent intent
210 - * @param <T> the type of installable intent 197 + * @param <T> the type of installable intent
211 * @return intent installer corresponding to the specified installable intent 198 * @return intent installer corresponding to the specified installable intent
212 */ 199 */
213 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) { 200 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
...@@ -229,10 +216,12 @@ public class IntentManager ...@@ -229,10 +216,12 @@ public class IntentManager
229 // TODO: implement compilation traversing tree structure 216 // TODO: implement compilation traversing tree structure
230 List<InstallableIntent> installable = new ArrayList<>(); 217 List<InstallableIntent> installable = new ArrayList<>();
231 for (Intent compiled : getCompiler(intent).compile(intent)) { 218 for (Intent compiled : getCompiler(intent).compile(intent)) {
232 - installable.add((InstallableIntent) compiled); 219 + InstallableIntent installableIntent = (InstallableIntent) compiled;
220 + installable.add(installableIntent);
221 + trackerService.addTrackedResources(intent.getId(),
222 + installableIntent.requiredLinks());
233 } 223 }
234 IntentEvent event = store.addInstallableIntents(intent.getId(), installable); 224 IntentEvent event = store.addInstallableIntents(intent.getId(), installable);
235 - eventDispatcher.post(event);
236 processStoreEvent(event); 225 processStoreEvent(event);
237 } 226 }
238 227
...@@ -242,13 +231,14 @@ public class IntentManager ...@@ -242,13 +231,14 @@ public class IntentManager
242 * @param intent intent 231 * @param intent intent
243 */ 232 */
244 private void installIntent(Intent intent) { 233 private void installIntent(Intent intent) {
245 - for (InstallableIntent installable : store.getInstallableIntents(intent.getId())) { 234 + List<InstallableIntent> installables = store.getInstallableIntents(intent.getId());
246 - registerSubclassInstallerIfNeeded(installable); 235 + if (installables != null) {
247 - getInstaller(installable).install(installable); 236 + for (InstallableIntent installable : installables) {
237 + registerSubclassInstallerIfNeeded(installable);
238 + getInstaller(installable).install(installable);
239 + }
248 } 240 }
249 -
250 IntentEvent event = store.setState(intent, INSTALLED); 241 IntentEvent event = store.setState(intent, INSTALLED);
251 - eventDispatcher.post(event);
252 processStoreEvent(event); 242 processStoreEvent(event);
253 243
254 } 244 }
...@@ -259,10 +249,12 @@ public class IntentManager ...@@ -259,10 +249,12 @@ public class IntentManager
259 * @param intent intent 249 * @param intent intent
260 */ 250 */
261 private void uninstallIntent(Intent intent) { 251 private void uninstallIntent(Intent intent) {
262 - for (InstallableIntent installable : store.getInstallableIntents(intent.getId())) { 252 + List<InstallableIntent> installables = store.getInstallableIntents(intent.getId());
263 - getInstaller(installable).uninstall(installable); 253 + if (installables != null) {
254 + for (InstallableIntent installable : installables) {
255 + getInstaller(installable).uninstall(installable);
256 + }
264 } 257 }
265 -
266 store.removeInstalledIntents(intent.getId()); 258 store.removeInstalledIntents(intent.getId());
267 store.setState(intent, WITHDRAWN); 259 store.setState(intent, WITHDRAWN);
268 } 260 }
...@@ -321,33 +313,32 @@ public class IntentManager ...@@ -321,33 +313,32 @@ public class IntentManager
321 * Handles state transition of submitted intents. 313 * Handles state transition of submitted intents.
322 */ 314 */
323 private void processStoreEvent(IntentEvent event) { 315 private void processStoreEvent(IntentEvent event) {
324 - invokeListeners(event); 316 + eventDispatcher.post(event);
325 - Intent intent = event.getIntent(); 317 + Intent intent = event.getIntent();
326 - 318 + try {
327 - try { 319 + switch (event.getState()) {
328 - switch (event.getState()) { 320 + case SUBMITTED:
329 - case SUBMITTED: 321 + compileIntent(intent);
330 - compileIntent(intent); 322 + break;
331 - break; 323 + case COMPILED:
332 - case COMPILED: 324 + installIntent(intent);
333 - installIntent(intent); 325 + break;
334 - break; 326 + case INSTALLED:
335 - case INSTALLED: 327 + break;
336 - break; 328 + case WITHDRAWING:
337 - case WITHDRAWING: 329 + uninstallIntent(intent);
338 - uninstallIntent(intent); 330 + break;
339 - break; 331 + case WITHDRAWN:
340 - case WITHDRAWN: 332 + break;
341 - break; 333 + case FAILED:
342 - case FAILED: 334 + break;
343 - break; 335 + default:
344 - default: 336 + throw new IllegalStateException("the state of IntentEvent is illegal: " +
345 - throw new IllegalStateException( 337 + event.getState());
346 - "the state of IntentEvent is illegal: " + event.getState());
347 - }
348 - } catch (IntentException e) {
349 - store.setState(intent, FAILED);
350 } 338 }
339 + } catch (IntentException e) {
340 + store.setState(intent, FAILED);
341 + }
351 342
352 } 343 }
353 344
...@@ -355,9 +346,26 @@ public class IntentManager ...@@ -355,9 +346,26 @@ public class IntentManager
355 private class InternalStoreDelegate implements IntentStoreDelegate { 346 private class InternalStoreDelegate implements IntentStoreDelegate {
356 @Override 347 @Override
357 public void notify(IntentEvent event) { 348 public void notify(IntentEvent event) {
358 - eventDispatcher.post(event);
359 processStoreEvent(event); 349 processStoreEvent(event);
360 } 350 }
361 } 351 }
362 352
353 + // Topology change delegate
354 + private class InternalTopoChangeDelegate implements TopologyChangeDelegate {
355 + @Override
356 + public void bumpIntents(Iterable<IntentId> intentIds) {
357 + for (IntentId intentId : intentIds) {
358 + compileIntent(getIntent(intentId));
359 + }
360 + }
361 +
362 + @Override
363 + public void failIntents(Iterable<IntentId> intentIds) {
364 + for (IntentId intentId : intentIds) {
365 + Intent intent = getIntent(intentId);
366 + uninstallIntent(intent);
367 + compileIntent(intent);
368 + }
369 + }
370 + }
363 } 371 }
......
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentId;
4 +
5 +/**
6 + * Auxiliary delegate for integration of intent manager and flow trackerService.
7 + */
8 +public interface TopologyChangeDelegate {
9 +
10 + /**
11 + * Notifies that topology has changed in such a way that the specified
12 + * intents should be recompiled.
13 + *
14 + * @param intentIds intents that should be recompiled
15 + */
16 + void bumpIntents(Iterable<IntentId> intentIds);
17 +
18 + /**
19 + * Notifies that topology has changed in such a way that the specified
20 + * intents should be marked failed and then recompiled.
21 + *
22 + * @param intentIds intents that should be failed and recompiled
23 + */
24 + void failIntents(Iterable<IntentId> intentIds);
25 +
26 +}
...@@ -125,7 +125,8 @@ implements TopologyStore { ...@@ -125,7 +125,8 @@ implements TopologyStore {
125 // Promote the new topology to current and return a ready-to-send event. 125 // Promote the new topology to current and return a ready-to-send event.
126 synchronized (this) { 126 synchronized (this) {
127 current = newTopology; 127 current = newTopology;
128 - return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, current); 128 + return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED,
129 + current, reasons);
129 } 130 }
130 } 131 }
131 132
......
...@@ -125,7 +125,8 @@ implements TopologyStore { ...@@ -125,7 +125,8 @@ implements TopologyStore {
125 // Promote the new topology to current and return a ready-to-send event. 125 // Promote the new topology to current and return a ready-to-send event.
126 synchronized (this) { 126 synchronized (this) {
127 current = newTopology; 127 current = newTopology;
128 - return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, current); 128 + return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED,
129 + current, reasons);
129 } 130 }
130 } 131 }
131 132
......
...@@ -124,7 +124,8 @@ public class SimpleTopologyStore ...@@ -124,7 +124,8 @@ public class SimpleTopologyStore
124 // Promote the new topology to current and return a ready-to-send event. 124 // Promote the new topology to current and return a ready-to-send event.
125 synchronized (this) { 125 synchronized (this) {
126 current = newTopology; 126 current = newTopology;
127 - return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, current); 127 + return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED,
128 + current, reasons);
128 } 129 }
129 } 130 }
130 131
......
...@@ -15,7 +15,7 @@ name=${2:-onos-1} ...@@ -15,7 +15,7 @@ name=${2:-onos-1}
15 15
16 ssh $remote " 16 ssh $remote "
17 sudo perl -pi.bak -e \"s/127.0.1.1.*/127.0.1.1 $name/g\" /etc/hosts 17 sudo perl -pi.bak -e \"s/127.0.1.1.*/127.0.1.1 $name/g\" /etc/hosts
18 - sudo perl -pi.bak -e \"s/.*/$name/g\" /etc/hostname 18 + sudo perl -pi.bak -e \"local \$/ = ''; s/.*/$name/g\" /etc/hostname
19 sudo hostname $name 19 sudo hostname $name
20 " 2>/dev/null 20 " 2>/dev/null
21 21
......