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