Brian O'Connor

Adding Intent Impl and shell command to install simple intent

Showing 26 changed files with 895 additions and 49 deletions
1 +package org.onlab.onos.cli.net;
2 +
3 +import org.apache.karaf.shell.commands.Argument;
4 +import org.apache.karaf.shell.commands.Command;
5 +import org.onlab.onos.cli.AbstractShellCommand;
6 +import org.onlab.onos.net.HostId;
7 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
8 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
9 +import org.onlab.onos.net.flow.TrafficSelector;
10 +import org.onlab.onos.net.flow.TrafficTreatment;
11 +import org.onlab.onos.net.host.HostService;
12 +import org.onlab.onos.net.intent.HostToHostIntent;
13 +import org.onlab.onos.net.intent.IntentId;
14 +import org.onlab.onos.net.intent.IntentService;
15 +
16 +/**
17 + * Lists all shortest-paths paths between the specified source and
18 + * destination devices.
19 + */
20 +@Command(scope = "onos", name = "add-intent",
21 + description = "Installs HostToHostIntent between the specified source and destination devices")
22 +public class IntentInstallCommand extends AbstractShellCommand {
23 +
24 + @Argument(index = 0, name = "src", description = "Source device ID",
25 + required = true, multiValued = false)
26 + String src = null;
27 +
28 + @Argument(index = 1, name = "dst", description = "Destination device ID",
29 + required = true, multiValued = false)
30 + String dst = null;
31 +
32 + private static long id = 1;
33 +
34 + @Override
35 + protected void execute() {
36 + IntentService service = get(IntentService.class);
37 + HostService hosts = get(HostService.class);
38 +
39 + HostId srcId = HostId.hostId(src);
40 + HostId dstId = HostId.hostId(dst);
41 +
42 + TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
43 + builder
44 + .matchEthSrc(hosts.getHost(srcId).mac())
45 + .matchEthDst(hosts.getHost(dstId).mac());
46 +
47 + TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder();
48 +
49 + HostToHostIntent intent = new HostToHostIntent(
50 + new IntentId(id++),
51 + srcId,
52 + dstId,
53 + builder.build(),
54 + treat.build());
55 +
56 + log.info("Adding intent {}", intent);
57 +
58 + service.submit(intent);
59 + }
60 +
61 +}
...@@ -57,6 +57,13 @@ ...@@ -57,6 +57,13 @@
57 </completers> 57 </completers>
58 </command> 58 </command>
59 <command> 59 <command>
60 + <action class="org.onlab.onos.cli.net.IntentInstallCommand"/>
61 + <completers>
62 + <ref component-id="hostIdCompleter"/>
63 + </completers>
64 + </command>
65 +
66 + <command>
60 <action class="org.onlab.onos.cli.net.ClustersListCommand"/> 67 <action class="org.onlab.onos.cli.net.ClustersListCommand"/>
61 </command> 68 </command>
62 <command> 69 <command>
......
1 +package org.onlab.onos.net.intent;
2 +
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +
5 +import java.util.Objects;
6 +
7 +import org.onlab.onos.net.HostId;
8 +import org.onlab.onos.net.flow.TrafficSelector;
9 +import org.onlab.onos.net.flow.TrafficTreatment;
10 +
11 +import com.google.common.base.MoreObjects;
12 +
13 +/**
14 + * Abstraction of point-to-point connectivity.
15 + */
16 +public class HostToHostIntent extends ConnectivityIntent {
17 +
18 + private final HostId src;
19 + private final HostId dst;
20 +
21 + /**
22 + * Creates a new point-to-point intent with the supplied ingress/egress
23 + * ports.
24 + *
25 + * @param id intent identifier
26 + * @param match traffic match
27 + * @param action action
28 + * @param ingressPort ingress port
29 + * @param egressPort egress port
30 + * @throws NullPointerException if {@code ingressPort} or {@code egressPort}
31 + * is null.
32 + */
33 + public HostToHostIntent(IntentId id, HostId src, HostId dst,
34 + TrafficSelector selector, TrafficTreatment treatment) {
35 + super(id, selector, treatment);
36 + this.src = checkNotNull(src);
37 + this.dst = checkNotNull(dst);
38 + }
39 +
40 + /**
41 + * Returns the port on which the ingress traffic should be connected to the
42 + * egress.
43 + *
44 + * @return ingress port
45 + */
46 + public HostId getSrc() {
47 + return src;
48 + }
49 +
50 + /**
51 + * Returns the port on which the traffic should egress.
52 + *
53 + * @return egress port
54 + */
55 + public HostId getDst() {
56 + return dst;
57 + }
58 +
59 + @Override
60 + public boolean equals(Object o) {
61 + if (this == o) {
62 + return true;
63 + }
64 + if (o == null || getClass() != o.getClass()) {
65 + return false;
66 + }
67 + if (!super.equals(o)) {
68 + return false;
69 + }
70 +
71 + HostToHostIntent that = (HostToHostIntent) o;
72 + return Objects.equals(this.src, that.src)
73 + && Objects.equals(this.dst, that.dst);
74 + }
75 +
76 + @Override
77 + public int hashCode() {
78 + return Objects.hash(super.hashCode(), src, dst);
79 + }
80 +
81 + @Override
82 + public String toString() {
83 + return MoreObjects.toStringHelper(getClass())
84 + .add("id", getId())
85 + .add("selector", getTrafficSelector())
86 + .add("treatmetn", getTrafficTreatment())
87 + .add("src", src)
88 + .add("dst", dst)
89 + .toString();
90 + }
91 +
92 +}
...@@ -4,14 +4,17 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -4,14 +4,17 @@ import static com.google.common.base.Preconditions.checkNotNull;
4 4
5 import java.util.Objects; 5 import java.util.Objects;
6 6
7 +import org.onlab.onos.event.AbstractEvent;
8 +
7 import com.google.common.base.MoreObjects; 9 import com.google.common.base.MoreObjects;
8 10
9 /** 11 /**
10 * A class to represent an intent related event. 12 * A class to represent an intent related event.
11 */ 13 */
12 -public class IntentEvent { 14 +public class IntentEvent extends AbstractEvent<IntentState, Intent> {
13 15
14 - // TODO: determine a suitable parent class; if one does not exist, consider introducing one 16 + // TODO: determine a suitable parent class; if one does not exist, consider
17 + // introducing one
15 18
16 private final long time; 19 private final long time;
17 private final Intent intent; 20 private final Intent intent;
...@@ -28,6 +31,7 @@ public class IntentEvent { ...@@ -28,6 +31,7 @@ public class IntentEvent {
28 * @throws NullPointerException if the intent or state is null 31 * @throws NullPointerException if the intent or state is null
29 */ 32 */
30 public IntentEvent(Intent intent, IntentState state, IntentState previous, long time) { 33 public IntentEvent(Intent intent, IntentState state, IntentState previous, long time) {
34 + super(state, intent);
31 this.intent = checkNotNull(intent); 35 this.intent = checkNotNull(intent);
32 this.state = checkNotNull(state); 36 this.state = checkNotNull(state);
33 this.previous = previous; 37 this.previous = previous;
...@@ -35,16 +39,6 @@ public class IntentEvent { ...@@ -35,16 +39,6 @@ public class IntentEvent {
35 } 39 }
36 40
37 /** 41 /**
38 - * Constructor for serializer.
39 - */
40 - protected IntentEvent() {
41 - this.intent = null;
42 - this.state = null;
43 - this.previous = null;
44 - this.time = 0;
45 - }
46 -
47 - /**
48 * Returns the state of the intent which caused the event. 42 * Returns the state of the intent which caused the event.
49 * 43 *
50 * @return the state of the intent 44 * @return the state of the intent
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 +import org.onlab.onos.event.EventListener;
4 +
3 /** 5 /**
4 * Listener for {@link IntentEvent intent events}. 6 * Listener for {@link IntentEvent intent events}.
5 */ 7 */
6 -public interface IntentEventListener { 8 +public interface IntentListener extends EventListener<IntentEvent> {
7 - /**
8 - * Processes the specified intent event.
9 - *
10 - * @param event the event to process
11 - */
12 - void event(IntentEvent event);
13 } 9 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import java.util.Set;
4 3
5 /** 4 /**
6 * Service for application submitting or withdrawing their intents. 5 * Service for application submitting or withdrawing their intents.
...@@ -9,8 +8,8 @@ public interface IntentService { ...@@ -9,8 +8,8 @@ public interface IntentService {
9 /** 8 /**
10 * Submits an intent into the system. 9 * Submits an intent into the system.
11 * 10 *
12 - * This is an asynchronous request meaning that any compiling 11 + * This is an asynchronous request meaning that any compiling or
13 - * or installation activities may be done at later time. 12 + * installation activities may be done at later time.
14 * 13 *
15 * @param intent intent to be submitted 14 * @param intent intent to be submitted
16 */ 15 */
...@@ -19,8 +18,8 @@ public interface IntentService { ...@@ -19,8 +18,8 @@ public interface IntentService {
19 /** 18 /**
20 * Withdraws an intent from the system. 19 * Withdraws an intent from the system.
21 * 20 *
22 - * This is an asynchronous request meaning that the environment 21 + * This is an asynchronous request meaning that the environment may be
23 - * may be affected at later time. 22 + * affected at later time.
24 * 23 *
25 * @param intent intent to be withdrawn 24 * @param intent intent to be withdrawn
26 */ 25 */
...@@ -30,19 +29,26 @@ public interface IntentService { ...@@ -30,19 +29,26 @@ public interface IntentService {
30 * Submits a batch of submit &amp; withdraw operations. Such a batch is 29 * Submits a batch of submit &amp; withdraw operations. Such a batch is
31 * assumed to be processed together. 30 * assumed to be processed together.
32 * 31 *
33 - * This is an asynchronous request meaning that the environment 32 + * This is an asynchronous request meaning that the environment may be
34 - * may be affected at later time. 33 + * affected at later time.
35 * 34 *
36 * @param operations batch of intent operations 35 * @param operations batch of intent operations
37 */ 36 */
38 void execute(IntentOperations operations); 37 void execute(IntentOperations operations);
39 38
40 /** 39 /**
41 - * Returns immutable set of intents currently in the system. 40 + * Returns an iterable of intents currently in the system.
42 * 41 *
43 * @return set of intents 42 * @return set of intents
44 */ 43 */
45 - Set<Intent> getIntents(); 44 + Iterable<Intent> getIntents();
45 +
46 + /**
47 + * Returns the number of intents currently in the system.
48 + *
49 + * @return number of intents
50 + */
51 + long getIntentCount();
46 52
47 /** 53 /**
48 * Retrieves the intent specified by its identifier. 54 * Retrieves the intent specified by its identifier.
...@@ -56,7 +62,8 @@ public interface IntentService { ...@@ -56,7 +62,8 @@ public interface IntentService {
56 * Retrieves the state of an intent by its identifier. 62 * Retrieves the state of an intent by its identifier.
57 * 63 *
58 * @param id intent identifier 64 * @param id intent identifier
59 - * @return the intent state or null if one with the given identifier is not found 65 + * @return the intent state or null if one with the given identifier is not
66 + * found
60 */ 67 */
61 IntentState getIntentState(IntentId id); 68 IntentState getIntentState(IntentId id);
62 69
...@@ -65,12 +72,12 @@ public interface IntentService { ...@@ -65,12 +72,12 @@ public interface IntentService {
65 * 72 *
66 * @param listener listener to be added 73 * @param listener listener to be added
67 */ 74 */
68 - void addListener(IntentEventListener listener); 75 + void addListener(IntentListener listener);
69 76
70 /** 77 /**
71 * Removes the specified listener for intent events. 78 * Removes the specified listener for intent events.
72 * 79 *
73 * @param listener listener to be removed 80 * @param listener listener to be removed
74 */ 81 */
75 - void removeListener(IntentEventListener listener); 82 + void removeListener(IntentListener listener);
76 } 83 }
......
1 +package org.onlab.onos.net.intent;
2 +
3 +import java.util.List;
4 +
5 +import org.onlab.onos.store.Store;
6 +
7 +/**
8 + * Manages inventory of end-station intents; not intended for direct use.
9 + */
10 +public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
11 +
12 + /**
13 + * Creates a new intent.
14 + *
15 + * @param intent intent
16 + * @return appropriate event or null if no change resulted
17 + */
18 + IntentEvent createIntent(Intent intent);
19 +
20 + /**
21 + * Removes the specified intent from the inventory.
22 + *
23 + * @param intentId intent identification
24 + * @return remove event or null if intent was not found
25 + */
26 + IntentEvent removeIntent(IntentId intent);
27 +
28 + /**
29 + * Returns the number of intents in the store.
30 + *
31 + */
32 + long getIntentCount();
33 +
34 + /**
35 + * Returns a collection of all intents in the store.
36 + *
37 + * @return iterable collection of all intents
38 + */
39 + Iterable<Intent> getIntents();
40 +
41 + /**
42 + * Returns the intent with the specified identifer.
43 + *
44 + * @param intentId intent identification
45 + * @return intent or null if not found
46 + */
47 + Intent getIntent(IntentId intentId);
48 +
49 + IntentState getIntentState(IntentId id);
50 +
51 + /**
52 + * Sets the state of the specified intent to the new state.
53 + *
54 + * @param intent intent whose state is to be changed
55 + * @param newState new state
56 + */
57 + IntentEvent setState(Intent intent, IntentState newState);
58 +
59 + IntentEvent addInstallableIntents(IntentId intentId, List<InstallableIntent> result);
60 +
61 + List<InstallableIntent> getInstallableIntents(IntentId intentId);
62 +
63 + void removeInstalledIntents(IntentId intentId);
64 +}
1 +package org.onlab.onos.net.intent;
2 +
3 +import org.onlab.onos.store.StoreDelegate;
4 +
5 +/**
6 + * Infrastructure link store delegate abstraction.
7 + */
8 +public interface IntentStoreDelegate extends StoreDelegate<IntentEvent> {
9 +}
...@@ -12,7 +12,7 @@ import com.google.common.base.MoreObjects; ...@@ -12,7 +12,7 @@ import com.google.common.base.MoreObjects;
12 /** 12 /**
13 * Abstraction of explicitly path specified connectivity intent. 13 * Abstraction of explicitly path specified connectivity intent.
14 */ 14 */
15 -public class PathIntent extends PointToPointIntent { 15 +public class PathIntent extends PointToPointIntent implements InstallableIntent {
16 16
17 private final Path path; 17 private final Path path;
18 18
......
...@@ -11,19 +11,19 @@ import java.util.concurrent.ExecutorService; ...@@ -11,19 +11,19 @@ import java.util.concurrent.ExecutorService;
11 import java.util.concurrent.Executors; 11 import java.util.concurrent.Executors;
12 12
13 /** 13 /**
14 - * Fake implementation of the intent service to assist in developing tests 14 + * Fake implementation of the intent service to assist in developing tests of
15 - * of the interface contract. 15 + * the interface contract.
16 */ 16 */
17 public class FakeIntentManager implements TestableIntentService { 17 public class FakeIntentManager implements TestableIntentService {
18 18
19 private final Map<IntentId, Intent> intents = new HashMap<>(); 19 private final Map<IntentId, Intent> intents = new HashMap<>();
20 private final Map<IntentId, IntentState> intentStates = new HashMap<>(); 20 private final Map<IntentId, IntentState> intentStates = new HashMap<>();
21 private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>(); 21 private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>();
22 - private final Set<IntentEventListener> listeners = new HashSet<>(); 22 + private final Set<IntentListener> listeners = new HashSet<>();
23 23
24 private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>(); 24 private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>();
25 - private final Map<Class<? extends InstallableIntent>, 25 + private final Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> installers
26 - IntentInstaller<? extends InstallableIntent>> installers = new HashMap<>(); 26 + = new HashMap<>();
27 27
28 private final ExecutorService executor = Executors.newSingleThreadExecutor(); 28 private final ExecutorService executor = Executors.newSingleThreadExecutor();
29 private final List<IntentException> exceptions = new ArrayList<>(); 29 private final List<IntentException> exceptions = new ArrayList<>();
...@@ -76,7 +76,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -76,7 +76,8 @@ public class FakeIntentManager implements TestableIntentService {
76 76
77 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) { 77 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
78 @SuppressWarnings("unchecked") 78 @SuppressWarnings("unchecked")
79 - IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass()); 79 + IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent
80 + .getClass());
80 if (installer == null) { 81 if (installer == null) {
81 throw new IntentException("no installer for class " + intent.getClass()); 82 throw new IntentException("no installer for class " + intent.getClass());
82 } 83 }
...@@ -125,7 +126,6 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -125,7 +126,6 @@ public class FakeIntentManager implements TestableIntentService {
125 } 126 }
126 } 127 }
127 128
128 -
129 // Sets the internal state for the given intent and dispatches an event 129 // Sets the internal state for the given intent and dispatches an event
130 private void setState(Intent intent, IntentState state) { 130 private void setState(Intent intent, IntentState state) {
131 IntentState previous = intentStates.get(intent.getId()); 131 IntentState previous = intentStates.get(intent.getId());
...@@ -175,6 +175,11 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -175,6 +175,11 @@ public class FakeIntentManager implements TestableIntentService {
175 } 175 }
176 176
177 @Override 177 @Override
178 + public long getIntentCount() {
179 + return intents.size();
180 + }
181 +
182 + @Override
178 public Intent getIntent(IntentId id) { 183 public Intent getIntent(IntentId id) {
179 return intents.get(id); 184 return intents.get(id);
180 } 185 }
...@@ -185,23 +190,24 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -185,23 +190,24 @@ public class FakeIntentManager implements TestableIntentService {
185 } 190 }
186 191
187 @Override 192 @Override
188 - public void addListener(IntentEventListener listener) { 193 + public void addListener(IntentListener listener) {
189 listeners.add(listener); 194 listeners.add(listener);
190 } 195 }
191 196
192 @Override 197 @Override
193 - public void removeListener(IntentEventListener listener) { 198 + public void removeListener(IntentListener listener) {
194 listeners.remove(listener); 199 listeners.remove(listener);
195 } 200 }
196 201
197 private void dispatch(IntentEvent event) { 202 private void dispatch(IntentEvent event) {
198 - for (IntentEventListener listener : listeners) { 203 + for (IntentListener listener : listeners) {
199 listener.event(event); 204 listener.event(event);
200 } 205 }
201 } 206 }
202 207
203 @Override 208 @Override
204 - public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) { 209 + public <T extends Intent> void registerCompiler(Class<T> cls,
210 + IntentCompiler<T> compiler) {
205 compilers.put(cls, compiler); 211 compilers.put(cls, compiler);
206 } 212 }
207 213
...@@ -216,7 +222,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -216,7 +222,8 @@ public class FakeIntentManager implements TestableIntentService {
216 } 222 }
217 223
218 @Override 224 @Override
219 - public <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) { 225 + public <T extends InstallableIntent> void registerInstaller(Class<T> cls,
226 + IntentInstaller<T> installer) {
220 installers.put(cls, installer); 227 installers.put(cls, installer);
221 } 228 }
222 229
...@@ -252,7 +259,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -252,7 +259,8 @@ public class FakeIntentManager implements TestableIntentService {
252 if (!installers.containsKey(intent.getClass())) { 259 if (!installers.containsKey(intent.getClass())) {
253 Class<?> cls = intent.getClass(); 260 Class<?> cls = intent.getClass();
254 while (cls != Object.class) { 261 while (cls != Object.class) {
255 - // As long as we're within the InstallableIntent class descendants 262 + // As long as we're within the InstallableIntent class
263 + // descendants
256 if (InstallableIntent.class.isAssignableFrom(cls)) { 264 if (InstallableIntent.class.isAssignableFrom(cls)) {
257 IntentInstaller<?> installer = installers.get(cls); 265 IntentInstaller<?> installer = installers.get(cls);
258 if (installer != null) { 266 if (installer != null) {
......
...@@ -51,7 +51,7 @@ public class IntentServiceTest { ...@@ -51,7 +51,7 @@ public class IntentServiceTest {
51 @Test 51 @Test
52 public void basics() { 52 public void basics() {
53 // Make sure there are no intents 53 // Make sure there are no intents
54 - assertEquals("incorrect intent count", 0, service.getIntents().size()); 54 + assertEquals("incorrect intent count", 0, service.getIntentCount());
55 55
56 // Register a compiler and an installer both setup for success. 56 // Register a compiler and an installer both setup for success.
57 service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID))); 57 service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID)));
...@@ -73,8 +73,7 @@ public class IntentServiceTest { ...@@ -73,8 +73,7 @@ public class IntentServiceTest {
73 validateEvents(intent, SUBMITTED, COMPILED, INSTALLED); 73 validateEvents(intent, SUBMITTED, COMPILED, INSTALLED);
74 74
75 // Make sure there is just one intent (and is ours) 75 // Make sure there is just one intent (and is ours)
76 - assertEquals("incorrect intent count", 1, service.getIntents().size()); 76 + assertEquals("incorrect intent count", 1, service.getIntentCount());
77 - assertEquals("incorrect intent", intent, service.getIntent(intent.getId()));
78 77
79 // Reset the listener events 78 // Reset the listener events
80 listener.events.clear(); 79 listener.events.clear();
...@@ -250,7 +249,7 @@ public class IntentServiceTest { ...@@ -250,7 +249,7 @@ public class IntentServiceTest {
250 249
251 250
252 // Fixture to track emitted intent events 251 // Fixture to track emitted intent events
253 - protected class TestListener implements IntentEventListener { 252 + protected class TestListener implements IntentListener {
254 final List<IntentEvent> events = new ArrayList<>(); 253 final List<IntentEvent> events = new ArrayList<>();
255 254
256 @Override 255 @Override
......
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IdGenerator;
4 +
5 +/**
6 + * Base class of {@link IdGenerator} implementations which use {@link IdBlockAllocator} as
7 + * backend.
8 + *
9 + * @param <T> the type of ID
10 + */
11 +public abstract class AbstractBlockAllocatorBasedIdGenerator<T> implements IdGenerator<T> {
12 + protected final IdBlockAllocator allocator;
13 + protected IdBlock idBlock;
14 +
15 + /**
16 + * Constructs an ID generator which use {@link IdBlockAllocator} as backend.
17 + *
18 + * @param allocator
19 + */
20 + protected AbstractBlockAllocatorBasedIdGenerator(IdBlockAllocator allocator) {
21 + this.allocator = allocator;
22 + this.idBlock = allocator.allocateUniqueIdBlock();
23 + }
24 +
25 + @Override
26 + public synchronized T getNewId() {
27 + try {
28 + return convertFrom(idBlock.getNextId());
29 + } catch (UnavailableIdException e) {
30 + idBlock = allocator.allocateUniqueIdBlock();
31 + return convertFrom(idBlock.getNextId());
32 + }
33 + }
34 +
35 + /**
36 + * Returns an ID instance of {@code T} type from the long value.
37 + *
38 + * @param value original long value
39 + * @return ID instance
40 + */
41 + protected abstract T convertFrom(long value);
42 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +public class DummyIdBlockAllocator implements IdBlockAllocator {
4 + private long blockTop;
5 + private static final long BLOCK_SIZE = 0x1000000L;
6 +
7 + /**
8 + * Returns a block of IDs which are unique and unused.
9 + * Range of IDs is fixed size and is assigned incrementally as this method
10 + * called.
11 + *
12 + * @return an IdBlock containing a set of unique IDs
13 + */
14 + @Override
15 + public IdBlock allocateUniqueIdBlock() {
16 + synchronized (this) {
17 + long blockHead = blockTop;
18 + long blockTail = blockTop + BLOCK_SIZE;
19 +
20 + IdBlock block = new IdBlock(blockHead, BLOCK_SIZE);
21 + blockTop = blockTail;
22 +
23 + return block;
24 + }
25 + }
26 +
27 + @Override
28 + public IdBlock allocateUniqueIdBlock(long range) {
29 + throw new UnsupportedOperationException("Not supported yet");
30 + }
31 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import java.util.Arrays;
4 +import java.util.List;
5 +import java.util.Set;
6 +
7 +import org.apache.felix.scr.annotations.Activate;
8 +import org.apache.felix.scr.annotations.Component;
9 +import org.apache.felix.scr.annotations.Deactivate;
10 +import org.apache.felix.scr.annotations.Reference;
11 +import org.apache.felix.scr.annotations.ReferenceCardinality;
12 +import org.onlab.onos.net.ConnectPoint;
13 +import org.onlab.onos.net.Path;
14 +import org.onlab.onos.net.PortNumber;
15 +import org.onlab.onos.net.intent.HostToHostIntent;
16 +import org.onlab.onos.net.intent.IdGenerator;
17 +import org.onlab.onos.net.intent.Intent;
18 +import org.onlab.onos.net.intent.IntentCompiler;
19 +import org.onlab.onos.net.intent.IntentExtensionService;
20 +import org.onlab.onos.net.intent.IntentId;
21 +import org.onlab.onos.net.intent.PathIntent;
22 +import org.onlab.onos.net.topology.PathService;
23 +
24 +/**
25 + * A intent compiler for {@link HostToHostIntent}.
26 + */
27 +@Component(immediate = true)
28 +public class HostToHostIntentCompiler
29 + implements IntentCompiler<HostToHostIntent> {
30 +
31 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
32 + protected IntentExtensionService intentManager;
33 +
34 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
35 + protected PathService pathService;
36 +
37 + private IdGenerator<IntentId> intentIdGenerator;
38 +
39 + @Activate
40 + public void activate() {
41 + IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
42 + intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
43 + intentManager.registerCompiler(HostToHostIntent.class, this);
44 + }
45 +
46 + @Deactivate
47 + public void deactivate() {
48 + intentManager.unregisterCompiler(HostToHostIntent.class);
49 + }
50 +
51 + @Override
52 + public List<Intent> compile(HostToHostIntent intent) {
53 + Set<Path> paths = pathService.getPaths(intent.getSrc(), intent.getDst());
54 + if (paths.isEmpty()) {
55 + throw new PathNotFoundException();
56 + }
57 + Path path = paths.iterator().next();
58 +
59 + return Arrays.asList((Intent) new PathIntent(
60 + intentIdGenerator.getNewId(),
61 + intent.getTrafficSelector(),
62 + intent.getTrafficTreatment(),
63 + new ConnectPoint(intent.getSrc(), PortNumber.ALL),
64 + new ConnectPoint(intent.getDst(), PortNumber.ALL),
65 + path));
66 + }
67 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import static com.google.common.base.Preconditions.checkArgument;
4 +
5 +import java.util.Objects;
6 +import java.util.concurrent.atomic.AtomicLong;
7 +
8 +import com.google.common.base.MoreObjects;
9 +
10 +/**
11 + * A class representing an ID space.
12 + */
13 +public final class IdBlock {
14 + private final long start;
15 + private final long size;
16 +
17 + private final AtomicLong currentId;
18 +
19 + /**
20 + * Constructs a new ID block with the specified size and initial value.
21 + *
22 + * @param start initial value of the block
23 + * @param size size of the block
24 + * @throws IllegalArgumentException if the size is less than or equal to 0
25 + */
26 + public IdBlock(long start, long size) {
27 + checkArgument(size > 0, "size should be more than 0, but %s", size);
28 +
29 + this.start = start;
30 + this.size = size;
31 +
32 + this.currentId = new AtomicLong(start);
33 + }
34 +
35 + // TODO: consider if this method is needed or not
36 + /**
37 + * Returns the initial value.
38 + *
39 + * @return initial value
40 + */
41 + public long getStart() {
42 + return start;
43 + }
44 +
45 + // TODO: consider if this method is needed or not
46 + /**
47 + * Returns the last value.
48 + *
49 + * @return last value
50 + */
51 + public long getEnd() {
52 + return start + size - 1;
53 + }
54 +
55 + /**
56 + * Returns the block size.
57 + *
58 + * @return block size
59 + */
60 + public long getSize() {
61 + return size;
62 + }
63 +
64 + /**
65 + * Returns the next ID in the block.
66 + *
67 + * @return next ID
68 + * @throws UnavailableIdException if there is no available ID in the block.
69 + */
70 + public long getNextId() {
71 + final long id = currentId.getAndIncrement();
72 + if (id > getEnd()) {
73 + throw new UnavailableIdException(String.format(
74 + "used all IDs in allocated space (size: %d, end: %d, current: %d)",
75 + size, getEnd(), id
76 + ));
77 + }
78 +
79 + return id;
80 + }
81 +
82 + // TODO: Do we really need equals and hashCode? Should it contain currentId?
83 + @Override
84 + public boolean equals(Object o) {
85 + if (this == o) {
86 + return true;
87 + }
88 + if (o == null || getClass() != o.getClass()) {
89 + return false;
90 + }
91 +
92 + IdBlock that = (IdBlock) o;
93 + return Objects.equals(this.start, that.start)
94 + && Objects.equals(this.size, that.size)
95 + && Objects.equals(this.currentId.get(), that.currentId.get());
96 + }
97 +
98 + @Override
99 + public int hashCode() {
100 + return Objects.hash(start, size, currentId);
101 + }
102 +
103 + @Override
104 + public String toString() {
105 + return MoreObjects.toStringHelper(getClass())
106 + .add("start", start)
107 + .add("size", size)
108 + .add("currentId", currentId)
109 + .toString();
110 + }
111 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +/**
4 + * An interface that gives unique ID spaces.
5 + */
6 +public interface IdBlockAllocator {
7 + /**
8 + * Allocates a unique Id Block.
9 + *
10 + * @return Id Block.
11 + */
12 + IdBlock allocateUniqueIdBlock();
13 +
14 + /**
15 + * Allocates next unique id and retrieve a new range of ids if needed.
16 + *
17 + * @param range range to use for the identifier
18 + * @return Id Block.
19 + */
20 + IdBlock allocateUniqueIdBlock(long range);
21 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentId;
4 +
5 +/**
6 + * An implementation of {@link net.onrc.onos.core.util.IdGenerator} of intent ID,
7 + * which uses {@link IdBlockAllocator}.
8 + */
9 +public class IdBlockAllocatorBasedIntentIdGenerator extends AbstractBlockAllocatorBasedIdGenerator<IntentId> {
10 +
11 + /**
12 + * Constructs an intent ID generator, which uses the specified ID block allocator
13 + * to generate a global unique intent ID.
14 + *
15 + * @param allocator the ID block allocator to use for generating intent IDs
16 + */
17 + public IdBlockAllocatorBasedIntentIdGenerator(IdBlockAllocator allocator) {
18 + super(allocator);
19 + }
20 +
21 + @Override
22 + protected IntentId convertFrom(long value) {
23 + return new IntentId(value);
24 + }
25 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentException;
4 +
5 +/**
6 + * An exception thrown when a intent compilation fails.
7 + */
8 +public class IntentCompilationException extends IntentException {
9 + private static final long serialVersionUID = 235237603018210810L;
10 +
11 + public IntentCompilationException() {
12 + super();
13 + }
14 +
15 + public IntentCompilationException(String message) {
16 + super(message);
17 + }
18 +
19 + public IntentCompilationException(String message, Throwable cause) {
20 + super(message, cause);
21 + }
22 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentException;
4 +
5 +/**
6 + * An exception thrown when intent installation fails.
7 + */
8 +public class IntentInstallationException extends IntentException {
9 + private static final long serialVersionUID = 3720268258616014168L;
10 +
11 + public IntentInstallationException() {
12 + super();
13 + }
14 +
15 + public IntentInstallationException(String message) {
16 + super(message);
17 + }
18 +
19 + public IntentInstallationException(String message, Throwable cause) {
20 + super(message, cause);
21 + }
22 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentException;
4 +
5 +/**
6 + * An exception thrown when intent removal failed.
7 + */
8 +public class IntentRemovalException extends IntentException {
9 + private static final long serialVersionUID = -5259226322037891951L;
10 +
11 + public IntentRemovalException() {
12 + super();
13 + }
14 +
15 + public IntentRemovalException(String message) {
16 + super(message);
17 + }
18 +
19 + public IntentRemovalException(String message, Throwable cause) {
20 + super(message, cause);
21 + }
22 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import java.util.Iterator;
4 +
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.onlab.onos.ApplicationId;
11 +import org.onlab.onos.net.ConnectPoint;
12 +import org.onlab.onos.net.Link;
13 +import org.onlab.onos.net.flow.DefaultFlowRule;
14 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
15 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
16 +import org.onlab.onos.net.flow.FlowRule;
17 +import org.onlab.onos.net.flow.FlowRuleService;
18 +import org.onlab.onos.net.flow.TrafficSelector;
19 +import org.onlab.onos.net.flow.TrafficTreatment;
20 +import org.onlab.onos.net.flow.criteria.Criterion;
21 +import org.onlab.onos.net.intent.IntentExtensionService;
22 +import org.onlab.onos.net.intent.IntentInstaller;
23 +import org.onlab.onos.net.intent.PathIntent;
24 +
25 +/**
26 + * An intent installer for {@link PathIntent}.
27 + */
28 +@Component(immediate = true)
29 +public class PathIntentInstaller
30 + implements IntentInstaller<PathIntent> {
31 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
32 + protected IntentExtensionService intentManager;
33 +
34 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
35 + private FlowRuleService flowRuleService;
36 +
37 + private final ApplicationId appId = ApplicationId.valueOf(1);
38 +
39 + @Activate
40 + public void activate() {
41 + intentManager.registerInstaller(PathIntent.class, this);
42 + }
43 +
44 + @Deactivate
45 + public void deactivate() {
46 + intentManager.unregisterInstaller(PathIntent.class);
47 + }
48 +
49 + @Override
50 + public void install(PathIntent intent) {
51 + TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
52 + TrafficSelector selector = intent.getTrafficSelector();
53 + for (Criterion c : selector.criteria()) {
54 + builder.add(c);
55 + }
56 +
57 + Iterator<Link> links = intent.getPath().links().iterator();
58 + ConnectPoint prev = links.next().dst();
59 + while (links.hasNext()) {
60 + builder.matchInport(prev.port());
61 + Link link = links.next();
62 +
63 + TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder();
64 + treat.setOutput(link.src().port());
65 +
66 + FlowRule f = new DefaultFlowRule(link.src().deviceId(),
67 + builder.build(), treat.build(), 0, appId);
68 + flowRuleService.applyFlowRules(f);
69 +
70 + prev = link.dst();
71 + }
72 +
73 + }
74 +
75 + @Override
76 + public void uninstall(PathIntent intent) {
77 + //TODO
78 + }
79 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import org.onlab.onos.net.intent.IntentException;
4 +
5 +/**
6 + * An exception thrown when a path is not found.
7 + */
8 +public class PathNotFoundException extends IntentException {
9 + private static final long serialVersionUID = -2087045731049914733L;
10 +
11 + public PathNotFoundException() {
12 + super();
13 + }
14 +
15 + public PathNotFoundException(String message) {
16 + super(message);
17 + }
18 +
19 + public PathNotFoundException(String message, Throwable cause) {
20 + super(message, cause);
21 + }
22 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +/**
4 + * Represents that there is no available IDs.
5 + */
6 +public class UnavailableIdException extends RuntimeException {
7 +
8 + private static final long serialVersionUID = -2287403908433720122L;
9 +
10 + /**
11 + * Constructs an exception with no message and no underlying cause.
12 + */
13 + public UnavailableIdException() {
14 + }
15 +
16 + /**
17 + * Constructs an exception with the specified message.
18 + *
19 + * @param message the message describing the specific nature of the error
20 + */
21 + public UnavailableIdException(String message) {
22 + super(message);
23 + }
24 +
25 + /**
26 + * Constructs an exception with the specified message and the underlying cause.
27 + *
28 + * @param message the message describing the specific nature of the error
29 + * @param cause the underlying cause of this error
30 + */
31 + public UnavailableIdException(String message, Throwable cause) {
32 + super(message, cause);
33 + }
34 +}
1 +/**
2 + * Intent Service Implementation. TODO
3 + */
4 +package org.onlab.onos.net.intent.impl;
...\ No newline at end of file ...\ No newline at end of file
1 +package org.onlab.onos.store.trivial.impl;
2 +
3 +import static org.onlab.onos.net.intent.IntentState.COMPILED;
4 +import static org.slf4j.LoggerFactory.getLogger;
5 +
6 +import java.util.HashMap;
7 +import java.util.List;
8 +import java.util.Map;
9 +
10 +import org.apache.felix.scr.annotations.Activate;
11 +import org.apache.felix.scr.annotations.Component;
12 +import org.apache.felix.scr.annotations.Deactivate;
13 +import org.apache.felix.scr.annotations.Service;
14 +import org.onlab.onos.net.intent.InstallableIntent;
15 +import org.onlab.onos.net.intent.Intent;
16 +import org.onlab.onos.net.intent.IntentEvent;
17 +import org.onlab.onos.net.intent.IntentId;
18 +import org.onlab.onos.net.intent.IntentState;
19 +import org.onlab.onos.net.intent.IntentStore;
20 +import org.onlab.onos.net.intent.IntentStoreDelegate;
21 +import org.onlab.onos.store.AbstractStore;
22 +import org.slf4j.Logger;
23 +
24 +import com.google.common.collect.ImmutableSet;
25 +
26 +@Component(immediate = true)
27 +@Service
28 +public class SimpleIntentStore
29 + extends AbstractStore<IntentEvent, IntentStoreDelegate>
30 + implements IntentStore {
31 +
32 + private final Logger log = getLogger(getClass());
33 + private final Map<IntentId, Intent> intents = new HashMap<>();
34 + private final Map<IntentId, IntentState> states = new HashMap<>();
35 + private final Map<IntentId, List<InstallableIntent>> installable = new HashMap<>();
36 +
37 + @Activate
38 + public void activate() {
39 + log.info("Started");
40 + }
41 +
42 + @Deactivate
43 + public void deactivate() {
44 + log.info("Stopped");
45 + }
46 +
47 + @Override
48 + public IntentEvent createIntent(Intent intent) {
49 + intents.put(intent.getId(), intent);
50 + return this.setState(intent, IntentState.SUBMITTED);
51 + }
52 +
53 + @Override
54 + public IntentEvent removeIntent(IntentId intentId) {
55 + Intent intent = intents.remove(intentId);
56 + installable.remove(intentId);
57 + IntentEvent event = this.setState(intent, IntentState.WITHDRAWN);
58 + states.remove(intentId);
59 + return event;
60 + }
61 +
62 + @Override
63 + public long getIntentCount() {
64 + return intents.size();
65 + }
66 +
67 + @Override
68 + public Iterable<Intent> getIntents() {
69 + return ImmutableSet.copyOf(intents.values());
70 + }
71 +
72 + @Override
73 + public Intent getIntent(IntentId intentId) {
74 + return intents.get(intentId);
75 + }
76 +
77 + @Override
78 + public IntentState getIntentState(IntentId id) {
79 + return states.get(id);
80 + }
81 +
82 + // TODO return dispatch event here... replace with state transition methods
83 + @Override
84 + public IntentEvent setState(Intent intent, IntentState newState) {
85 + IntentId id = intent.getId();
86 + IntentState oldState = states.get(id);
87 + states.put(id, newState);
88 + return new IntentEvent(intent, newState, oldState, System.currentTimeMillis());
89 + }
90 +
91 + @Override
92 + public IntentEvent addInstallableIntents(IntentId intentId, List<InstallableIntent> result) {
93 + installable.put(intentId, result);
94 + return this.setState(intents.get(intentId), COMPILED);
95 + }
96 +
97 + @Override
98 + public List<InstallableIntent> getInstallableIntents(IntentId intentId) {
99 + return installable.get(intentId);
100 + }
101 +
102 + @Override
103 + public void removeInstalledIntents(IntentId intentId) {
104 + installable.remove(intentId);
105 + }
106 +
107 +}