blob: 351016db51f45dca0620129a86ce03ccb5402ce3 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.intent.impl;
Brian O'Connor66630c82014-10-02 21:08:19 -070017
Brian O'Connor64a0369d2015-02-20 22:02:59 -080018import com.google.common.collect.ImmutableList;
Brian O'Connor66630c82014-10-02 21:08:19 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.core.CoreService;
26import org.onosproject.core.IdGenerator;
27import org.onosproject.event.AbstractListenerRegistry;
28import org.onosproject.event.EventDeliveryService;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080029import org.onosproject.net.flow.FlowRule;
Brian O'Connor0e271dc2015-02-04 18:20:25 -080030import org.onosproject.net.flow.FlowRuleOperations;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080031import org.onosproject.net.flow.FlowRuleOperationsContext;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.flow.FlowRuleService;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080033import org.onosproject.net.intent.FlowRuleIntent;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.intent.Intent;
35import org.onosproject.net.intent.IntentBatchDelegate;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.intent.IntentCompiler;
Brian O'Connorcff03322015-02-03 15:28:59 -080037import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.intent.IntentEvent;
Brian O'Connorabafb502014-12-02 22:26:20 -080039import org.onosproject.net.intent.IntentExtensionService;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.intent.IntentListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.intent.IntentService;
42import org.onosproject.net.intent.IntentState;
43import org.onosproject.net.intent.IntentStore;
Brian O'Connorabafb502014-12-02 22:26:20 -080044import org.onosproject.net.intent.IntentStoreDelegate;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080045import org.onosproject.net.intent.Key;
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -080046import org.onosproject.net.intent.impl.phase.FinalIntentProcessPhase;
Sho SHIMIZUce49b602015-02-23 19:15:49 -080047import org.onosproject.net.intent.impl.phase.IntentProcessPhase;
Sho SHIMIZU662c3db2015-02-23 16:59:01 -080048import org.onosproject.net.intent.impl.phase.IntentWorker;
Brian O'Connor66630c82014-10-02 21:08:19 -070049import org.slf4j.Logger;
50
Brian O'Connor64a0369d2015-02-20 22:02:59 -080051import java.util.Collection;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080052import java.util.Collections;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080053import java.util.EnumSet;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080054import java.util.List;
55import java.util.Map;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080056import java.util.concurrent.ExecutionException;
57import java.util.concurrent.ExecutorService;
58import java.util.concurrent.Future;
59import java.util.stream.Collectors;
Brian O'Connorfa81eae2014-10-30 13:20:05 -070060
Brian O'Connorfa81eae2014-10-30 13:20:05 -070061import static com.google.common.base.Preconditions.checkNotNull;
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080062import static java.util.concurrent.Executors.newFixedThreadPool;
Brian O'Connordb15b042015-02-04 14:59:28 -080063import static java.util.concurrent.Executors.newSingleThreadExecutor;
Brian O'Connorbdc7f002015-02-18 20:49:41 -080064import static org.onlab.util.Tools.groupedThreads;
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -080065import static org.onosproject.net.intent.IntentState.FAILED;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080066import static org.onosproject.net.intent.IntentState.INSTALLED;
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -080067import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080068import static org.onosproject.net.intent.IntentState.WITHDRAWN;
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -080069import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
Sho SHIMIZUce49b602015-02-23 19:15:49 -080070import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase;
Brian O'Connorfa81eae2014-10-30 13:20:05 -070071import static org.slf4j.LoggerFactory.getLogger;
Brian O'Connor66630c82014-10-02 21:08:19 -070072
73/**
74 * An implementation of Intent Manager.
75 */
76@Component(immediate = true)
77@Service
78public class IntentManager
79 implements IntentService, IntentExtensionService {
Sho SHIMIZU8b5051d2014-11-05 11:24:13 -080080 private static final Logger log = getLogger(IntentManager.class);
Brian O'Connor66630c82014-10-02 21:08:19 -070081
82 public static final String INTENT_NULL = "Intent cannot be null";
Ray Milkeyf9af43c2015-02-09 16:45:48 -080083 public static final String INTENT_ID_NULL = "Intent key cannot be null";
Brian O'Connor66630c82014-10-02 21:08:19 -070084
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080085 private static final int NUM_THREADS = 12;
86
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080087 private static final EnumSet<IntentState> RECOMPILE
88 = EnumSet.of(INSTALL_REQ, FAILED, WITHDRAW_REQ);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080089
Brian O'Connor66630c82014-10-02 21:08:19 -070090 private final AbstractListenerRegistry<IntentEvent, IntentListener>
tom95329eb2014-10-06 08:40:06 -070091 listenerRegistry = new AbstractListenerRegistry<>();
Brian O'Connor66630c82014-10-02 21:08:19 -070092
Brian O'Connor520c0522014-11-23 23:50:47 -080093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected CoreService coreService;
Brian O'Connor66630c82014-10-02 21:08:19 -070095
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected IntentStore store;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom85258ee2014-10-07 00:10:02 -0700100 protected ObjectiveTrackerService trackerService;
tom95329eb2014-10-06 08:40:06 -0700101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Brian O'Connor66630c82014-10-02 21:08:19 -0700103 protected EventDeliveryService eventDispatcher;
104
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sho SHIMIZU214ac322015-02-23 19:30:15 -0800106 protected FlowRuleService flowRuleService;
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700107
Brian O'Connor520c0522014-11-23 23:50:47 -0800108
Brian O'Connordb15b042015-02-04 14:59:28 -0800109 private ExecutorService batchExecutor;
110 private ExecutorService workerExecutor;
Brian O'Connor520c0522014-11-23 23:50:47 -0800111
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800112 private final CompilerRegistry compilerRegistry = new CompilerRegistry();
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800113 private final InternalIntentProcessor processor = new InternalIntentProcessor();
Brian O'Connor520c0522014-11-23 23:50:47 -0800114 private final IntentStoreDelegate delegate = new InternalStoreDelegate();
115 private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
116 private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
117 private IdGenerator idGenerator;
118
Brian O'Connorb499b352015-02-03 16:46:15 -0800119 private final IntentAccumulator accumulator = new IntentAccumulator(batchDelegate);
Brian O'Connorcff03322015-02-03 15:28:59 -0800120
Brian O'Connor66630c82014-10-02 21:08:19 -0700121 @Activate
122 public void activate() {
123 store.setDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700124 trackerService.setDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700125 eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
Brian O'Connorbdc7f002015-02-18 20:49:41 -0800126 batchExecutor = newSingleThreadExecutor(groupedThreads("onos/intent", "batch"));
127 workerExecutor = newFixedThreadPool(NUM_THREADS, groupedThreads("onos/intent", "worker-%d"));
Brian O'Connor520c0522014-11-23 23:50:47 -0800128 idGenerator = coreService.getIdGenerator("intent-ids");
129 Intent.bindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700130 log.info("Started");
131 }
132
133 @Deactivate
134 public void deactivate() {
135 store.unsetDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700136 trackerService.unsetDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700137 eventDispatcher.removeSink(IntentEvent.class);
Brian O'Connordb15b042015-02-04 14:59:28 -0800138 batchExecutor.shutdown();
Brian O'Connor520c0522014-11-23 23:50:47 -0800139 Intent.unbindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700140 log.info("Stopped");
141 }
142
143 @Override
144 public void submit(Intent intent) {
145 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800146 IntentData data = new IntentData(intent, IntentState.INSTALL_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800147 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700148 }
149
150 @Override
151 public void withdraw(Intent intent) {
152 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800153 IntentData data = new IntentData(intent, IntentState.WITHDRAW_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800154 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700155 }
156
Brian O'Connor66630c82014-10-02 21:08:19 -0700157 @Override
Ray Milkey8c6d00e2015-03-13 14:14:34 -0700158 public void purge(Intent intent) {
159 checkNotNull(intent, INTENT_NULL);
160 IntentData data = new IntentData(intent, IntentState.PURGE_REQ, null);
161 store.addPending(data);
162 }
163
164 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800165 public Intent getIntent(Key key) {
166 return store.getIntent(key);
167 }
168
169 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700170 public Iterable<Intent> getIntents() {
171 return store.getIntents();
172 }
173
174 @Override
175 public long getIntentCount() {
176 return store.getIntentCount();
177 }
178
179 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800180 public IntentState getIntentState(Key intentKey) {
181 checkNotNull(intentKey, INTENT_ID_NULL);
182 return store.getIntentState(intentKey);
Brian O'Connor66630c82014-10-02 21:08:19 -0700183 }
184
185 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800186 public List<Intent> getInstallableIntents(Key intentKey) {
187 checkNotNull(intentKey, INTENT_ID_NULL);
188 return store.getInstallableIntents(intentKey);
Thomas Vachuska10d4abc2014-10-21 12:47:26 -0700189 }
190
191 @Override
Brian O'Connorbe28a872015-02-19 21:44:37 -0800192 public boolean isLocal(Key intentKey) {
193 return store.isMaster(intentKey);
194 }
195
196 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700197 public void addListener(IntentListener listener) {
198 listenerRegistry.addListener(listener);
199 }
200
201 @Override
202 public void removeListener(IntentListener listener) {
203 listenerRegistry.removeListener(listener);
204 }
205
206 @Override
207 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800208 compilerRegistry.registerCompiler(cls, compiler);
Brian O'Connor66630c82014-10-02 21:08:19 -0700209 }
210
211 @Override
212 public <T extends Intent> void unregisterCompiler(Class<T> cls) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800213 compilerRegistry.unregisterCompiler(cls);
Brian O'Connor66630c82014-10-02 21:08:19 -0700214 }
215
216 @Override
217 public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800218 return compilerRegistry.getCompilers();
Brian O'Connor66630c82014-10-02 21:08:19 -0700219 }
220
221 @Override
Jonathan Hart34f1e382015-02-24 16:52:23 -0800222 public Iterable<Intent> getPending() {
223 return store.getPending();
224 }
225
Brian O'Connor66630c82014-10-02 21:08:19 -0700226 // Store delegate to re-post events emitted from the store.
227 private class InternalStoreDelegate implements IntentStoreDelegate {
228 @Override
229 public void notify(IntentEvent event) {
tom85258ee2014-10-07 00:10:02 -0700230 eventDispatcher.post(event);
Brian O'Connor66630c82014-10-02 21:08:19 -0700231 }
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800232
233 @Override
Brian O'Connorcff03322015-02-03 15:28:59 -0800234 public void process(IntentData data) {
235 accumulator.add(data);
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800236 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700237 }
238
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800239 private void buildAndSubmitBatches(Iterable<Key> intentKeys,
Brian O'Connor72a034c2014-11-26 18:24:23 -0800240 boolean compileAllFailed) {
Brian O'Connor72a034c2014-11-26 18:24:23 -0800241 // Attempt recompilation of the specified intents first.
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800242 for (Key key : intentKeys) {
243 Intent intent = store.getIntent(key);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800244 if (intent == null) {
245 continue;
246 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800247 submit(intent);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800248 }
249
250 if (compileAllFailed) {
251 // If required, compile all currently failed intents.
252 for (Intent intent : getIntents()) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800253 IntentState state = getIntentState(intent.key());
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800254 if (RECOMPILE.contains(state)) {
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800255 if (state == WITHDRAW_REQ) {
Brian O'Connor03406a42015-02-03 17:28:57 -0800256 withdraw(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800257 } else {
Brian O'Connor03406a42015-02-03 17:28:57 -0800258 submit(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800259 }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800260 }
261 }
262 }
263
Brian O'Connorb499b352015-02-03 16:46:15 -0800264 //FIXME
265// for (ApplicationId appId : batches.keySet()) {
266// if (batchService.isLocalLeader(appId)) {
267// execute(batches.get(appId).build());
268// }
269// }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800270 }
271
tom95329eb2014-10-06 08:40:06 -0700272 // Topology change delegate
273 private class InternalTopoChangeDelegate implements TopologyChangeDelegate {
274 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800275 public void triggerCompile(Iterable<Key> intentKeys,
tom85258ee2014-10-07 00:10:02 -0700276 boolean compileAllFailed) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800277 buildAndSubmitBatches(intentKeys, compileAllFailed);
tom95329eb2014-10-06 08:40:06 -0700278 }
tom95329eb2014-10-06 08:40:06 -0700279 }
tom85258ee2014-10-07 00:10:02 -0700280
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800281 private Future<FinalIntentProcessPhase> submitIntentData(IntentData data) {
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800282 IntentData current = store.getIntentData(data.key());
Sho SHIMIZUce49b602015-02-23 19:15:49 -0800283 IntentProcessPhase initial = newInitialPhase(processor, data, current);
284 return workerExecutor.submit(new IntentWorker(initial));
Sho SHIMIZU8d9d1362015-02-04 12:28:15 -0800285 }
286
Sho SHIMIZUd42058e2015-02-23 16:16:20 -0800287 private class IntentBatchProcess implements Runnable {
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800288
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800289 protected final Collection<IntentData> data;
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800290
Sho SHIMIZUd42058e2015-02-23 16:16:20 -0800291 IntentBatchProcess(Collection<IntentData> data) {
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800292 this.data = checkNotNull(data);
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800293 }
294
295 @Override
296 public void run() {
297 try {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800298 /*
299 1. wrap each intentdata in a runnable and submit
300 2. wait for completion of all the work
301 3. accumulate results and submit batch write of IntentData to store
302 (we can also try to update these individually)
303 */
304 submitUpdates(waitForFutures(createIntentUpdates()));
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800305 } catch (Exception e) {
306 log.error("Error submitting batches:", e);
307 // FIXME incomplete Intents should be cleaned up
308 // (transition to FAILED, etc.)
309
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800310 // the batch has failed
311 // TODO: maybe we should do more?
312 log.error("Walk the plank, matey...");
Brian O'Connorb499b352015-02-03 16:46:15 -0800313 //FIXME
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800314// batchService.removeIntentOperations(data);
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800315 }
Brian O'Connor3c4b00d2015-02-22 20:42:26 -0800316 accumulator.ready();
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800317 }
318
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800319 private List<Future<FinalIntentProcessPhase>> createIntentUpdates() {
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800320 return data.stream()
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800321 .map(IntentManager.this::submitIntentData)
322 .collect(Collectors.toList());
323 }
324
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800325 private List<FinalIntentProcessPhase> waitForFutures(List<Future<FinalIntentProcessPhase>> futures) {
326 ImmutableList.Builder<FinalIntentProcessPhase> updateBuilder = ImmutableList.builder();
327 for (Future<FinalIntentProcessPhase> future : futures) {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800328 try {
329 updateBuilder.add(future.get());
330 } catch (InterruptedException | ExecutionException e) {
331 //FIXME
332 log.warn("Future failed: {}", e);
333 }
334 }
335 return updateBuilder.build();
336 }
337
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800338 private void submitUpdates(List<FinalIntentProcessPhase> updates) {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800339 store.batchWrite(updates.stream()
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800340 .map(FinalIntentProcessPhase::data)
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800341 .collect(Collectors.toList()));
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800342 }
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800343 }
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -0800344
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700345 private class InternalBatchDelegate implements IntentBatchDelegate {
346 @Override
Brian O'Connorb499b352015-02-03 16:46:15 -0800347 public void execute(Collection<IntentData> operations) {
Brian O'Connorab8ef822015-02-17 18:08:54 -0800348 log.debug("Execute {} operation(s).", operations.size());
349 log.trace("Execute operations: {}", operations);
Sho SHIMIZUd42058e2015-02-23 16:16:20 -0800350 batchExecutor.execute(new IntentBatchProcess(operations));
Brian O'Connordb15b042015-02-04 14:59:28 -0800351 // TODO ensure that only one batch is in flight at a time
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700352 }
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700353 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800354
355 private class InternalIntentProcessor implements IntentProcessor {
356 @Override
357 public List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
358 return compilerRegistry.compile(intent, previousInstallables);
359 }
360
361 @Override
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800362 public void install(IntentData data) {
363 IntentManager.this.install(data);
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800364 }
365
366 @Override
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800367 public void uninstall(IntentData data) {
368 IntentManager.this.uninstall(data);
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800369 }
370
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800371 }
372
373 private void install(IntentData data) {
374 // need to consider if FlowRuleIntent is only one as installable intent or not
375 List<Intent> installables = data.installables();
376 if (!installables.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
377 throw new IllegalStateException("installable intents must be FlowRuleIntent");
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800378 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800379
380 installables.forEach(x -> trackerService.addTrackedResources(data.key(), x.resources()));
381
382 List<Collection<FlowRule>> stages = installables.stream()
383 .map(x -> (FlowRuleIntent) x)
384 .map(FlowRuleIntent::flowRules)
385 .collect(Collectors.toList());
386
387 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
388 for (Collection<FlowRule> rules : stages) {
389 rules.forEach(builder::add);
390 builder.newStage();
391 }
392
393 FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
394 @Override
395 public void onSuccess(FlowRuleOperations ops) {
396 log.debug("Completed installing: {}", data.key());
397 data.setState(INSTALLED);
398 store.write(data);
399 }
400
401 @Override
402 public void onError(FlowRuleOperations ops) {
403 log.warn("Failed installation: {} {} on {}", data.key(), data.intent(), ops);
404 data.setState(FAILED);
405 store.write(data);
406 }
407 });
408
409 flowRuleService.apply(operations);
410 }
411
412 private void uninstall(IntentData data) {
413 List<Intent> installables = data.installables();
414 if (!installables.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
415 throw new IllegalStateException("installable intents must be FlowRuleIntent");
416 }
417
418 installables.forEach(x -> trackerService.removeTrackedResources(data.intent().key(), x.resources()));
419
420 List<Collection<FlowRule>> stages = installables.stream()
421 .map(x -> (FlowRuleIntent) x)
422 .map(FlowRuleIntent::flowRules)
423 .collect(Collectors.toList());
424
425 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
426 for (Collection<FlowRule> rules : stages) {
427 rules.forEach(builder::remove);
428 builder.newStage();
429 }
430
431 FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
432 @Override
433 public void onSuccess(FlowRuleOperations ops) {
434 log.debug("Completed withdrawing: {}", data.key());
435 data.setState(WITHDRAWN);
436 data.setInstallables(Collections.emptyList());
437 store.write(data);
438 }
439
440 @Override
441 public void onError(FlowRuleOperations ops) {
442 log.warn("Failed withdraw: {}", data.key());
443 data.setState(FAILED);
444 store.write(data);
445 }
446 });
447
448 flowRuleService.apply(operations);
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800449 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700450}