Brian O'Connor
Committed by Gerrit Code Review

adding purge option to IntentRemoveCommand

Change-Id: Ic97acd9a8308355cd3135ea5df0a470b3579106e
...@@ -221,7 +221,7 @@ public class IntentPushTestCommand extends AbstractShellCommand ...@@ -221,7 +221,7 @@ public class IntentPushTestCommand extends AbstractShellCommand
221 log.warn("install event latch is null"); 221 log.warn("install event latch is null");
222 } 222 }
223 } else if (IGNORE_EVENT.contains(event.type())) { 223 } else if (IGNORE_EVENT.contains(event.type())) {
224 - log.info("Unexpected intent event: {}", event); 224 + log.debug("Unexpected intent event: {}", event);
225 } 225 }
226 } 226 }
227 } 227 }
......
...@@ -17,14 +17,24 @@ package org.onosproject.cli.net; ...@@ -17,14 +17,24 @@ package org.onosproject.cli.net;
17 17
18 import org.apache.karaf.shell.commands.Argument; 18 import org.apache.karaf.shell.commands.Argument;
19 import org.apache.karaf.shell.commands.Command; 19 import org.apache.karaf.shell.commands.Command;
20 +import org.apache.karaf.shell.commands.Option;
20 import org.onosproject.cli.AbstractShellCommand; 21 import org.onosproject.cli.AbstractShellCommand;
21 import org.onosproject.core.ApplicationId; 22 import org.onosproject.core.ApplicationId;
22 import org.onosproject.core.CoreService; 23 import org.onosproject.core.CoreService;
23 import org.onosproject.net.intent.Intent; 24 import org.onosproject.net.intent.Intent;
25 +import org.onosproject.net.intent.IntentEvent;
26 +import org.onosproject.net.intent.IntentListener;
24 import org.onosproject.net.intent.IntentService; 27 import org.onosproject.net.intent.IntentService;
28 +import org.onosproject.net.intent.IntentState;
25 import org.onosproject.net.intent.Key; 29 import org.onosproject.net.intent.Key;
26 30
27 import java.math.BigInteger; 31 import java.math.BigInteger;
32 +import java.util.Objects;
33 +import java.util.concurrent.CountDownLatch;
34 +import java.util.concurrent.TimeUnit;
35 +
36 +import static org.onosproject.net.intent.IntentState.FAILED;
37 +import static org.onosproject.net.intent.IntentState.WITHDRAWN;
28 38
29 /** 39 /**
30 * Removes an intent. 40 * Removes an intent.
...@@ -43,6 +53,16 @@ public class IntentRemoveCommand extends AbstractShellCommand { ...@@ -43,6 +53,16 @@ public class IntentRemoveCommand extends AbstractShellCommand {
43 required = true, multiValued = false) 53 required = true, multiValued = false)
44 String id = null; 54 String id = null;
45 55
56 + @Option(name = "-p", aliases = "--purge",
57 + description = "Purge the intent from the store after removal",
58 + required = false, multiValued = false)
59 + private boolean purgeAfterRemove = false;
60 +
61 + @Option(name = "-s", aliases = "--sync",
62 + description = "Waits for the removal before returning",
63 + required = false, multiValued = false)
64 + private boolean sync = false;
65 +
46 @Override 66 @Override
47 protected void execute() { 67 protected void execute() {
48 IntentService intentService = get(IntentService.class); 68 IntentService intentService = get(IntentService.class);
...@@ -63,8 +83,38 @@ public class IntentRemoveCommand extends AbstractShellCommand { ...@@ -63,8 +83,38 @@ public class IntentRemoveCommand extends AbstractShellCommand {
63 83
64 Key key = Key.of(new BigInteger(id, 16).longValue(), appId); 84 Key key = Key.of(new BigInteger(id, 16).longValue(), appId);
65 Intent intent = intentService.getIntent(key); 85 Intent intent = intentService.getIntent(key);
86 +
87 +
66 if (intent != null) { 88 if (intent != null) {
89 + // set up latch and listener to track uninstall progress
90 + CountDownLatch latch = new CountDownLatch(1);
91 + IntentListener listener = (IntentEvent event) -> {
92 + if (Objects.equals(event.subject().key(), key) &&
93 + (event.type() == IntentEvent.Type.WITHDRAWN
94 + || event.type() == IntentEvent.Type.WITHDRAWN)) {
95 + latch.countDown();
96 + }
97 + };
98 + intentService.addListener(listener);
99 +
100 + // request the withdraw
67 intentService.withdraw(intent); 101 intentService.withdraw(intent);
102 +
103 + if (purgeAfterRemove || sync) {
104 + try {
105 + latch.await(5, TimeUnit.SECONDS);
106 + } catch (InterruptedException e) {
107 + print("Timed out waiting for intent {}", key);
108 + }
109 + // double check the state
110 + IntentState state = intentService.getIntentState(key);
111 + if (purgeAfterRemove && (state == WITHDRAWN || state == FAILED)) {
112 + intentService.purge(key);
68 } 113 }
69 } 114 }
115 + // clean up the listener
116 + intentService.removeListener(listener);
117 + }
118 +
119 + }
70 } 120 }
......
...@@ -112,4 +112,11 @@ public interface IntentService { ...@@ -112,4 +112,11 @@ public interface IntentService {
112 * @param listener listener to be removed 112 * @param listener listener to be removed
113 */ 113 */
114 void removeListener(IntentListener listener); 114 void removeListener(IntentListener listener);
115 +
116 + /**
117 + * Purges a specific intent from the system if it is FAILED or WITHDRAWN.
118 + *
119 + * @param key key of the intent to purge
120 + */
121 + void purge(Key key);
115 } 122 }
......
...@@ -109,4 +109,10 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { ...@@ -109,4 +109,10 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
109 * @return pending intents 109 * @return pending intents
110 */ 110 */
111 Iterable<Intent> getPending(); 111 Iterable<Intent> getPending();
112 +
113 + /** Purges a specific intent from the system if it is FAILED or WITHDRAWN.
114 + *
115 + * @param key key of the intent to purge
116 + */
117 + void purge(Key key);
112 } 118 }
......
...@@ -230,6 +230,11 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -230,6 +230,11 @@ public class FakeIntentManager implements TestableIntentService {
230 listeners.remove(listener); 230 listeners.remove(listener);
231 } 231 }
232 232
233 + @Override
234 + public void purge(Key key) {
235 + // FIXME implement this
236 + }
237 +
233 private void dispatch(IntentEvent event) { 238 private void dispatch(IntentEvent event) {
234 for (IntentListener listener : listeners) { 239 for (IntentListener listener : listeners) {
235 listener.event(event); 240 listener.event(event);
......
...@@ -76,4 +76,9 @@ public class IntentServiceAdapter implements IntentService { ...@@ -76,4 +76,9 @@ public class IntentServiceAdapter implements IntentService {
76 public void removeListener(IntentListener listener) { 76 public void removeListener(IntentListener listener) {
77 77
78 } 78 }
79 +
80 + @Override
81 + public void purge(Key key) {
82 +
83 + }
79 } 84 }
......
...@@ -193,6 +193,11 @@ public class IntentManager ...@@ -193,6 +193,11 @@ public class IntentManager
193 } 193 }
194 194
195 @Override 195 @Override
196 + public void purge(Key key) {
197 + store.purge(key);
198 + }
199 +
200 + @Override
196 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) { 201 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
197 compilerRegistry.registerCompiler(cls, compiler); 202 compilerRegistry.registerCompiler(cls, compiler);
198 } 203 }
......
...@@ -278,6 +278,14 @@ public class GossipIntentStore ...@@ -278,6 +278,14 @@ public class GossipIntentStore
278 .collect(Collectors.toList()); 278 .collect(Collectors.toList());
279 } 279 }
280 280
281 + @Override
282 + public void purge(Key key) {
283 + IntentData data = currentMap.get(key);
284 + if (data.state() == WITHDRAWN || data.state() == FAILED) {
285 + currentMap.remove(key, data);
286 + }
287 + }
288 +
281 private void notifyDelegateIfNotNull(IntentEvent event) { 289 private void notifyDelegateIfNotNull(IntentEvent event) {
282 if (event != null) { 290 if (event != null) {
283 notifyDelegate(event); 291 notifyDelegate(event);
......
...@@ -253,4 +253,12 @@ public class SimpleIntentStore ...@@ -253,4 +253,12 @@ public class SimpleIntentStore
253 .map(IntentData::intent) 253 .map(IntentData::intent)
254 .collect(Collectors.toList()); 254 .collect(Collectors.toList());
255 } 255 }
256 +
257 + @Override
258 + public void purge(Key key) {
259 + IntentData data = current.get(key);
260 + if (data.state() == IntentState.WITHDRAWN || data.state() == IntentState.FAILED) {
261 + current.remove(key, data);
262 + }
263 + }
256 } 264 }
......