blob: a53079765d268d11a57cace95b71e837b363d2d1 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Sho SHIMIZU89925242016-01-13 14:20:34 -08002 * Copyright 2014-2016 Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
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'Connor66630c82014-10-02 21:08:19 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
Sho SHIMIZUe0981722016-01-14 16:02:48 -080024import org.onlab.util.Tools;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.core.CoreService;
26import org.onosproject.core.IdGenerator;
Sho SHIMIZU98c0a392016-01-14 18:40:53 -080027import org.onosproject.event.AbstractListenerManager;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080028import org.onosproject.net.flow.FlowRule;
Brian O'Connor0e271dc2015-02-04 18:20:25 -080029import org.onosproject.net.flow.FlowRuleOperations;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080030import org.onosproject.net.flow.FlowRuleOperationsContext;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.flow.FlowRuleService;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080032import org.onosproject.net.intent.FlowRuleIntent;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.intent.Intent;
34import org.onosproject.net.intent.IntentBatchDelegate;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.intent.IntentCompiler;
Brian O'Connorcff03322015-02-03 15:28:59 -080036import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.intent.IntentEvent;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.intent.IntentExtensionService;
Brian O'Connorabafb502014-12-02 22:26:20 -080039import org.onosproject.net.intent.IntentListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.intent.IntentService;
41import org.onosproject.net.intent.IntentState;
42import org.onosproject.net.intent.IntentStore;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.intent.IntentStoreDelegate;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080044import org.onosproject.net.intent.Key;
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -080045import org.onosproject.net.intent.impl.phase.FinalIntentProcessPhase;
Sho SHIMIZUce49b602015-02-23 19:15:49 -080046import org.onosproject.net.intent.impl.phase.IntentProcessPhase;
Brian O'Connor66630c82014-10-02 21:08:19 -070047import org.slf4j.Logger;
48
Brian O'Connorf0c5a052015-04-27 00:34:53 -070049import java.util.Collection;
50import java.util.EnumSet;
51import java.util.List;
52import java.util.Map;
Sho SHIMIZUab541a52016-01-13 23:29:32 -080053import java.util.Objects;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070054import java.util.Optional;
Sho SHIMIZUad8ab272016-01-13 22:08:58 -080055import java.util.concurrent.CompletableFuture;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070056import java.util.concurrent.ExecutorService;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070057import java.util.stream.Collectors;
Brian O'Connorfa81eae2014-10-30 13:20:05 -070058
Brian O'Connorfa81eae2014-10-30 13:20:05 -070059import static com.google.common.base.Preconditions.checkNotNull;
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080060import static java.util.concurrent.Executors.newFixedThreadPool;
Brian O'Connordb15b042015-02-04 14:59:28 -080061import static java.util.concurrent.Executors.newSingleThreadExecutor;
Brian O'Connorbdc7f002015-02-18 20:49:41 -080062import static org.onlab.util.Tools.groupedThreads;
Sho SHIMIZU98c0a392016-01-14 18:40:53 -080063import static org.onosproject.net.intent.IntentState.CORRUPT;
64import static org.onosproject.net.intent.IntentState.FAILED;
65import static org.onosproject.net.intent.IntentState.INSTALLED;
66import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
67import static org.onosproject.net.intent.IntentState.WITHDRAWING;
68import static org.onosproject.net.intent.IntentState.WITHDRAWN;
69import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
Jonathan Hart96c5a4a2015-07-31 14:23:33 -070070import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
Sho SHIMIZUce49b602015-02-23 19:15:49 -080071import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase;
Changhoon Yoon541ef712015-05-23 17:18:34 +090072import static org.onosproject.security.AppGuard.checkPermission;
Sho SHIMIZU98c0a392016-01-14 18:40:53 -080073import static org.onosproject.security.AppPermission.Type.INTENT_READ;
74import static org.onosproject.security.AppPermission.Type.INTENT_WRITE;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070075import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoonb856b812015-08-10 03:47:19 +090076
Brian O'Connor66630c82014-10-02 21:08:19 -070077
78/**
Brian O'Connorce2d8b52015-07-29 16:24:13 -070079 * An implementation of intent service.
Brian O'Connor66630c82014-10-02 21:08:19 -070080 */
81@Component(immediate = true)
82@Service
83public class IntentManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070084 extends AbstractListenerManager<IntentEvent, IntentListener>
Brian O'Connor66630c82014-10-02 21:08:19 -070085 implements IntentService, IntentExtensionService {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070086
Sho SHIMIZU8b5051d2014-11-05 11:24:13 -080087 private static final Logger log = getLogger(IntentManager.class);
Brian O'Connor66630c82014-10-02 21:08:19 -070088
89 public static final String INTENT_NULL = "Intent cannot be null";
Ray Milkeyf9af43c2015-02-09 16:45:48 -080090 public static final String INTENT_ID_NULL = "Intent key cannot be null";
Brian O'Connor66630c82014-10-02 21:08:19 -070091
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080092 private static final int NUM_THREADS = 12;
93
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080094 private static final EnumSet<IntentState> RECOMPILE
95 = EnumSet.of(INSTALL_REQ, FAILED, WITHDRAW_REQ);
Jonathan Hart96c5a4a2015-07-31 14:23:33 -070096 private static final EnumSet<IntentState> WITHDRAW
97 = EnumSet.of(WITHDRAW_REQ, WITHDRAWING, WITHDRAWN);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080098
Brian O'Connor520c0522014-11-23 23:50:47 -080099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected CoreService coreService;
Brian O'Connor66630c82014-10-02 21:08:19 -0700101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected IntentStore store;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom85258ee2014-10-07 00:10:02 -0700106 protected ObjectiveTrackerService trackerService;
tom95329eb2014-10-06 08:40:06 -0700107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sho SHIMIZU214ac322015-02-23 19:30:15 -0800109 protected FlowRuleService flowRuleService;
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700110
Brian O'Connordb15b042015-02-04 14:59:28 -0800111 private ExecutorService batchExecutor;
112 private ExecutorService workerExecutor;
Brian O'Connor520c0522014-11-23 23:50:47 -0800113
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800114 private final CompilerRegistry compilerRegistry = new CompilerRegistry();
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800115 private final InternalIntentProcessor processor = new InternalIntentProcessor();
Brian O'Connor520c0522014-11-23 23:50:47 -0800116 private final IntentStoreDelegate delegate = new InternalStoreDelegate();
117 private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
118 private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
119 private IdGenerator idGenerator;
120
Brian O'Connorb499b352015-02-03 16:46:15 -0800121 private final IntentAccumulator accumulator = new IntentAccumulator(batchDelegate);
Brian O'Connorcff03322015-02-03 15:28:59 -0800122
Brian O'Connor66630c82014-10-02 21:08:19 -0700123 @Activate
124 public void activate() {
125 store.setDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700126 trackerService.setDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700127 eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
Brian O'Connorbdc7f002015-02-18 20:49:41 -0800128 batchExecutor = newSingleThreadExecutor(groupedThreads("onos/intent", "batch"));
129 workerExecutor = newFixedThreadPool(NUM_THREADS, groupedThreads("onos/intent", "worker-%d"));
Brian O'Connor520c0522014-11-23 23:50:47 -0800130 idGenerator = coreService.getIdGenerator("intent-ids");
131 Intent.bindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700132 log.info("Started");
133 }
134
135 @Deactivate
136 public void deactivate() {
137 store.unsetDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700138 trackerService.unsetDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700139 eventDispatcher.removeSink(IntentEvent.class);
Brian O'Connordb15b042015-02-04 14:59:28 -0800140 batchExecutor.shutdown();
Brian O'Connor3c58e962015-04-28 23:21:51 -0700141 workerExecutor.shutdown();
Brian O'Connor520c0522014-11-23 23:50:47 -0800142 Intent.unbindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700143 log.info("Stopped");
144 }
145
146 @Override
147 public void submit(Intent intent) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900148 checkPermission(INTENT_WRITE);
Brian O'Connor66630c82014-10-02 21:08:19 -0700149 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800150 IntentData data = new IntentData(intent, IntentState.INSTALL_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800151 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700152 }
153
154 @Override
155 public void withdraw(Intent intent) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900156 checkPermission(INTENT_WRITE);
Brian O'Connor66630c82014-10-02 21:08:19 -0700157 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800158 IntentData data = new IntentData(intent, IntentState.WITHDRAW_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800159 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700160 }
161
Brian O'Connor66630c82014-10-02 21:08:19 -0700162 @Override
Ray Milkey8c6d00e2015-03-13 14:14:34 -0700163 public void purge(Intent intent) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900164 checkPermission(INTENT_WRITE);
Ray Milkey8c6d00e2015-03-13 14:14:34 -0700165 checkNotNull(intent, INTENT_NULL);
166 IntentData data = new IntentData(intent, IntentState.PURGE_REQ, null);
167 store.addPending(data);
168 }
169
170 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800171 public Intent getIntent(Key key) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900172 checkPermission(INTENT_READ);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800173 return store.getIntent(key);
174 }
175
176 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700177 public Iterable<Intent> getIntents() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900178 checkPermission(INTENT_READ);
Brian O'Connor66630c82014-10-02 21:08:19 -0700179 return store.getIntents();
180 }
181
182 @Override
Thomas Vachuskac46af202015-06-03 16:43:27 -0700183 public Iterable<IntentData> getIntentData() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900184 checkPermission(INTENT_READ);
Thomas Vachuskac46af202015-06-03 16:43:27 -0700185 return store.getIntentData(false, 0);
186 }
187
188 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700189 public long getIntentCount() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900190 checkPermission(INTENT_READ);
Brian O'Connor66630c82014-10-02 21:08:19 -0700191 return store.getIntentCount();
192 }
193
194 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800195 public IntentState getIntentState(Key intentKey) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900196 checkPermission(INTENT_READ);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800197 checkNotNull(intentKey, INTENT_ID_NULL);
198 return store.getIntentState(intentKey);
Brian O'Connor66630c82014-10-02 21:08:19 -0700199 }
200
201 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800202 public List<Intent> getInstallableIntents(Key intentKey) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900203 checkPermission(INTENT_READ);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800204 checkNotNull(intentKey, INTENT_ID_NULL);
205 return store.getInstallableIntents(intentKey);
Thomas Vachuska10d4abc2014-10-21 12:47:26 -0700206 }
207
208 @Override
Brian O'Connorbe28a872015-02-19 21:44:37 -0800209 public boolean isLocal(Key intentKey) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900210 checkPermission(INTENT_READ);
Brian O'Connorbe28a872015-02-19 21:44:37 -0800211 return store.isMaster(intentKey);
212 }
213
214 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700215 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800216 compilerRegistry.registerCompiler(cls, compiler);
Brian O'Connor66630c82014-10-02 21:08:19 -0700217 }
218
219 @Override
220 public <T extends Intent> void unregisterCompiler(Class<T> cls) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800221 compilerRegistry.unregisterCompiler(cls);
Brian O'Connor66630c82014-10-02 21:08:19 -0700222 }
223
224 @Override
225 public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800226 return compilerRegistry.getCompilers();
Brian O'Connor66630c82014-10-02 21:08:19 -0700227 }
228
229 @Override
Jonathan Hart34f1e382015-02-24 16:52:23 -0800230 public Iterable<Intent> getPending() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900231 checkPermission(INTENT_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900232
Jonathan Hart34f1e382015-02-24 16:52:23 -0800233 return store.getPending();
234 }
235
Brian O'Connor66630c82014-10-02 21:08:19 -0700236 // Store delegate to re-post events emitted from the store.
237 private class InternalStoreDelegate implements IntentStoreDelegate {
238 @Override
239 public void notify(IntentEvent event) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700240 post(event);
Brian O'Connor66630c82014-10-02 21:08:19 -0700241 }
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800242
243 @Override
Brian O'Connorcff03322015-02-03 15:28:59 -0800244 public void process(IntentData data) {
245 accumulator.add(data);
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800246 }
Thomas Vachuskac46af202015-06-03 16:43:27 -0700247
248 @Override
249 public void onUpdate(IntentData intentData) {
250 trackerService.trackIntent(intentData);
251 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700252 }
253
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800254 private void buildAndSubmitBatches(Iterable<Key> intentKeys,
Brian O'Connor72a034c2014-11-26 18:24:23 -0800255 boolean compileAllFailed) {
Brian O'Connor72a034c2014-11-26 18:24:23 -0800256 // Attempt recompilation of the specified intents first.
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800257 for (Key key : intentKeys) {
258 Intent intent = store.getIntent(key);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800259 if (intent == null) {
260 continue;
261 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800262 submit(intent);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800263 }
264
Jonathan Hart0cca3e82015-09-23 17:54:11 -0700265 if (compileAllFailed) {
266 // If required, compile all currently failed intents.
267 for (Intent intent : getIntents()) {
268 IntentState state = getIntentState(intent.key());
269 if (RECOMPILE.contains(state) || intentAllowsPartialFailure(intent)) {
270 if (WITHDRAW.contains(state)) {
271 withdraw(intent);
272 } else {
273 submit(intent);
274 }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800275 }
276 }
277 }
278
Brian O'Connorb499b352015-02-03 16:46:15 -0800279 //FIXME
280// for (ApplicationId appId : batches.keySet()) {
281// if (batchService.isLocalLeader(appId)) {
282// execute(batches.get(appId).build());
283// }
284// }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800285 }
286
tom95329eb2014-10-06 08:40:06 -0700287 // Topology change delegate
288 private class InternalTopoChangeDelegate implements TopologyChangeDelegate {
289 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800290 public void triggerCompile(Iterable<Key> intentKeys,
tom85258ee2014-10-07 00:10:02 -0700291 boolean compileAllFailed) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800292 buildAndSubmitBatches(intentKeys, compileAllFailed);
tom95329eb2014-10-06 08:40:06 -0700293 }
tom95329eb2014-10-06 08:40:06 -0700294 }
tom85258ee2014-10-07 00:10:02 -0700295
Sho SHIMIZU594fb2a2016-01-14 16:12:26 -0800296 private IntentProcessPhase createInitialPhase(IntentData data) {
297 IntentData current = store.getIntentData(data.key());
298 return newInitialPhase(processor, data, current);
299 }
300
301 private FinalIntentProcessPhase process(IntentProcessPhase initial) {
302 Optional<IntentProcessPhase> currentPhase = Optional.of(initial);
303 IntentProcessPhase previousPhase = initial;
304
305 while (currentPhase.isPresent()) {
306 previousPhase = currentPhase.get();
307 currentPhase = previousPhase.execute();
308 }
309 return (FinalIntentProcessPhase) previousPhase;
Sho SHIMIZU8d9d1362015-02-04 12:28:15 -0800310 }
311
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700312 private class InternalBatchDelegate implements IntentBatchDelegate {
313 @Override
Brian O'Connorb499b352015-02-03 16:46:15 -0800314 public void execute(Collection<IntentData> operations) {
Brian O'Connorab8ef822015-02-17 18:08:54 -0800315 log.debug("Execute {} operation(s).", operations.size());
316 log.trace("Execute operations: {}", operations);
Sho SHIMIZU94b03b12015-04-10 14:53:13 -0700317
318 // batchExecutor is single-threaded, so only one batch is in flight at a time
Sho SHIMIZU62bbc602016-01-13 16:54:35 -0800319 batchExecutor.execute(() -> {
320 try {
321 /*
322 1. wrap each intentdata in a runnable and submit
323 2. wait for completion of all the work
324 3. accumulate results and submit batch write of IntentData to store
325 (we can also try to update these individually)
326 */
Sho SHIMIZUe0981722016-01-14 16:02:48 -0800327 List<CompletableFuture<IntentData>> futures = operations.stream()
Sho SHIMIZUb0c4a072016-01-14 16:22:50 -0800328 .map(IntentManager.this::createInitialPhase)
329 .map(CompletableFuture::completedFuture)
330 .map(x -> x.thenApplyAsync(IntentManager.this::process, workerExecutor))
Sho SHIMIZUe0981722016-01-14 16:02:48 -0800331 .map(x -> x.thenApply(FinalIntentProcessPhase::data))
Sho SHIMIZUd7558932016-01-13 23:47:46 -0800332 .map(x -> x.exceptionally(e -> {
333 //FIXME
334 log.warn("Future failed: {}", e);
335 return null;
336 }))
Sho SHIMIZUe0981722016-01-14 16:02:48 -0800337 .collect(Collectors.toList());
338 store.batchWrite(Tools.allOf(futures).join().stream()
Sho SHIMIZUd7558932016-01-13 23:47:46 -0800339 .filter(Objects::nonNull)
Sho SHIMIZUd7558932016-01-13 23:47:46 -0800340 .collect(Collectors.toList()));
Sho SHIMIZU62bbc602016-01-13 16:54:35 -0800341 } catch (Exception e) {
342 log.error("Error submitting batches:", e);
343 // FIXME incomplete Intents should be cleaned up
344 // (transition to FAILED, etc.)
345
346 // the batch has failed
347 // TODO: maybe we should do more?
348 log.error("Walk the plank, matey...");
349 //FIXME
350// batchService.removeIntentOperations(data);
351 }
352 accumulator.ready();
353 });
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700354 }
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700355 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800356
357 private class InternalIntentProcessor implements IntentProcessor {
358 @Override
359 public List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
360 return compilerRegistry.compile(intent, previousInstallables);
361 }
362
363 @Override
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700364 public void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700365 IntentManager.this.apply(toUninstall, toInstall);
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800366 }
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700367 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800368
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700369 private enum Direction {
370 ADD,
371 REMOVE
372 }
373
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700374 private void applyIntentData(Optional<IntentData> intentData,
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700375 FlowRuleOperations.Builder builder,
376 Direction direction) {
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700377 if (!intentData.isPresent()) {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700378 return;
379 }
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700380 IntentData data = intentData.get();
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700381
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700382 List<Intent> intentsToApply = data.installables();
383 if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
384 throw new IllegalStateException("installable intents must be FlowRuleIntent");
385 }
386
387 if (direction == Direction.ADD) {
388 trackerService.addTrackedResources(data.key(), data.intent().resources());
389 intentsToApply.forEach(installable ->
390 trackerService.addTrackedResources(data.key(), installable.resources()));
391 } else {
392 trackerService.removeTrackedResources(data.key(), data.intent().resources());
393 intentsToApply.forEach(installable ->
394 trackerService.removeTrackedResources(data.intent().key(),
395 installable.resources()));
396 }
397
398 // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so.
399 builder.newStage();
400
401 List<Collection<FlowRule>> stages = intentsToApply.stream()
402 .map(x -> (FlowRuleIntent) x)
403 .map(FlowRuleIntent::flowRules)
404 .collect(Collectors.toList());
405
406 for (Collection<FlowRule> rules : stages) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700407 if (direction == Direction.ADD) {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700408 rules.forEach(builder::add);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700409 } else {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700410 rules.forEach(builder::remove);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700411 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800412 }
413
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800414 }
415
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700416 private void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800417 // need to consider if FlowRuleIntent is only one as installable intent or not
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800418
419 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700420 applyIntentData(toUninstall, builder, Direction.REMOVE);
421 applyIntentData(toInstall, builder, Direction.ADD);
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800422
423 FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
424 @Override
425 public void onSuccess(FlowRuleOperations ops) {
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700426 if (toInstall.isPresent()) {
427 IntentData installData = toInstall.get();
428 log.debug("Completed installing: {}", installData.key());
429 installData.setState(INSTALLED);
430 store.write(installData);
431 } else if (toUninstall.isPresent()) {
432 IntentData uninstallData = toUninstall.get();
433 log.debug("Completed withdrawing: {}", uninstallData.key());
434 switch (uninstallData.request()) {
435 case INSTALL_REQ:
436 uninstallData.setState(FAILED);
437 break;
438 case WITHDRAW_REQ:
439 default: //TODO "default" case should not happen
440 uninstallData.setState(WITHDRAWN);
441 break;
442 }
443 store.write(uninstallData);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700444 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800445 }
446
447 @Override
448 public void onError(FlowRuleOperations ops) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700449 // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT)
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700450 if (toInstall.isPresent()) {
451 IntentData installData = toInstall.get();
452 log.warn("Failed installation: {} {} on {}",
453 installData.key(), installData.intent(), ops);
454 installData.setState(CORRUPT);
Brian O'Connor6d8e3172015-04-30 15:43:57 -0700455 installData.incrementErrorCount();
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700456 store.write(installData);
457 }
Sho SHIMIZUd4936252015-04-10 15:03:57 -0700458 // if toUninstall was cause of error, then CORRUPT (another job will clean this up)
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700459 if (toUninstall.isPresent()) {
460 IntentData uninstallData = toUninstall.get();
461 log.warn("Failed withdrawal: {} {} on {}",
462 uninstallData.key(), uninstallData.intent(), ops);
463 uninstallData.setState(CORRUPT);
Brian O'Connor6d8e3172015-04-30 15:43:57 -0700464 uninstallData.incrementErrorCount();
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700465 store.write(uninstallData);
466 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800467 }
468 });
469
Brian O'Connora7674262015-06-04 13:55:18 -0700470 if (log.isTraceEnabled()) {
471 log.trace("applying intent {} -> {} with {} rules: {}",
Sho SHIMIZU98c0a392016-01-14 18:40:53 -0800472 toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
473 toInstall.map(x -> x.key().toString()).orElse("<empty>"),
474 operations.stages().stream().mapToLong(i -> i.size()).sum(),
475 operations.stages());
Brian O'Connora7674262015-06-04 13:55:18 -0700476 }
477
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800478 flowRuleService.apply(operations);
479 }
480
Brian O'Connor66630c82014-10-02 21:08:19 -0700481}