Showing
13 changed files
with
357 additions
and
86 deletions
... | @@ -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 | ... | ... |
-
Please register or login to post a comment