blob: ebf8112983a9d49bc61456c917805f9f4a086abf [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 SHIMIZUad8ab272016-01-13 22:08:58 -0800296 private CompletableFuture<FinalIntentProcessPhase> submitIntentData(IntentData data) {
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800297 IntentData current = store.getIntentData(data.key());
Sho SHIMIZUce49b602015-02-23 19:15:49 -0800298 IntentProcessPhase initial = newInitialPhase(processor, data, current);
Sho SHIMIZUad8ab272016-01-13 22:08:58 -0800299 return CompletableFuture.supplyAsync(() -> {
Sho SHIMIZU89925242016-01-13 14:20:34 -0800300 Optional<IntentProcessPhase> currentPhase = Optional.of(initial);
301 IntentProcessPhase previousPhase = initial;
302
303 while (currentPhase.isPresent()) {
304 previousPhase = currentPhase.get();
305 currentPhase = previousPhase.execute();
306 }
307 return (FinalIntentProcessPhase) previousPhase;
Sho SHIMIZUad8ab272016-01-13 22:08:58 -0800308 }, workerExecutor);
Sho SHIMIZU8d9d1362015-02-04 12:28:15 -0800309 }
310
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700311 private class InternalBatchDelegate implements IntentBatchDelegate {
312 @Override
Brian O'Connorb499b352015-02-03 16:46:15 -0800313 public void execute(Collection<IntentData> operations) {
Brian O'Connorab8ef822015-02-17 18:08:54 -0800314 log.debug("Execute {} operation(s).", operations.size());
315 log.trace("Execute operations: {}", operations);
Sho SHIMIZU94b03b12015-04-10 14:53:13 -0700316
317 // batchExecutor is single-threaded, so only one batch is in flight at a time
Sho SHIMIZU62bbc602016-01-13 16:54:35 -0800318 batchExecutor.execute(() -> {
319 try {
320 /*
321 1. wrap each intentdata in a runnable and submit
322 2. wait for completion of all the work
323 3. accumulate results and submit batch write of IntentData to store
324 (we can also try to update these individually)
325 */
Sho SHIMIZUe0981722016-01-14 16:02:48 -0800326 List<CompletableFuture<IntentData>> futures = operations.stream()
Sho SHIMIZUd7558932016-01-13 23:47:46 -0800327 .map(IntentManager.this::submitIntentData)
Sho SHIMIZUe0981722016-01-14 16:02:48 -0800328 .map(x -> x.thenApply(FinalIntentProcessPhase::data))
Sho SHIMIZUd7558932016-01-13 23:47:46 -0800329 .map(x -> x.exceptionally(e -> {
330 //FIXME
331 log.warn("Future failed: {}", e);
332 return null;
333 }))
Sho SHIMIZUe0981722016-01-14 16:02:48 -0800334 .collect(Collectors.toList());
335 store.batchWrite(Tools.allOf(futures).join().stream()
Sho SHIMIZUd7558932016-01-13 23:47:46 -0800336 .filter(Objects::nonNull)
Sho SHIMIZUd7558932016-01-13 23:47:46 -0800337 .collect(Collectors.toList()));
Sho SHIMIZU62bbc602016-01-13 16:54:35 -0800338 } catch (Exception e) {
339 log.error("Error submitting batches:", e);
340 // FIXME incomplete Intents should be cleaned up
341 // (transition to FAILED, etc.)
342
343 // the batch has failed
344 // TODO: maybe we should do more?
345 log.error("Walk the plank, matey...");
346 //FIXME
347// batchService.removeIntentOperations(data);
348 }
349 accumulator.ready();
350 });
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700351 }
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700352 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800353
354 private class InternalIntentProcessor implements IntentProcessor {
355 @Override
356 public List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
357 return compilerRegistry.compile(intent, previousInstallables);
358 }
359
360 @Override
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700361 public void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700362 IntentManager.this.apply(toUninstall, toInstall);
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800363 }
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700364 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800365
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700366 private enum Direction {
367 ADD,
368 REMOVE
369 }
370
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700371 private void applyIntentData(Optional<IntentData> intentData,
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700372 FlowRuleOperations.Builder builder,
373 Direction direction) {
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700374 if (!intentData.isPresent()) {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700375 return;
376 }
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700377 IntentData data = intentData.get();
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700378
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700379 List<Intent> intentsToApply = data.installables();
380 if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
381 throw new IllegalStateException("installable intents must be FlowRuleIntent");
382 }
383
384 if (direction == Direction.ADD) {
385 trackerService.addTrackedResources(data.key(), data.intent().resources());
386 intentsToApply.forEach(installable ->
387 trackerService.addTrackedResources(data.key(), installable.resources()));
388 } else {
389 trackerService.removeTrackedResources(data.key(), data.intent().resources());
390 intentsToApply.forEach(installable ->
391 trackerService.removeTrackedResources(data.intent().key(),
392 installable.resources()));
393 }
394
395 // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so.
396 builder.newStage();
397
398 List<Collection<FlowRule>> stages = intentsToApply.stream()
399 .map(x -> (FlowRuleIntent) x)
400 .map(FlowRuleIntent::flowRules)
401 .collect(Collectors.toList());
402
403 for (Collection<FlowRule> rules : stages) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700404 if (direction == Direction.ADD) {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700405 rules.forEach(builder::add);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700406 } else {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700407 rules.forEach(builder::remove);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700408 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800409 }
410
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800411 }
412
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700413 private void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800414 // need to consider if FlowRuleIntent is only one as installable intent or not
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800415
416 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700417 applyIntentData(toUninstall, builder, Direction.REMOVE);
418 applyIntentData(toInstall, builder, Direction.ADD);
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800419
420 FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
421 @Override
422 public void onSuccess(FlowRuleOperations ops) {
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700423 if (toInstall.isPresent()) {
424 IntentData installData = toInstall.get();
425 log.debug("Completed installing: {}", installData.key());
426 installData.setState(INSTALLED);
427 store.write(installData);
428 } else if (toUninstall.isPresent()) {
429 IntentData uninstallData = toUninstall.get();
430 log.debug("Completed withdrawing: {}", uninstallData.key());
431 switch (uninstallData.request()) {
432 case INSTALL_REQ:
433 uninstallData.setState(FAILED);
434 break;
435 case WITHDRAW_REQ:
436 default: //TODO "default" case should not happen
437 uninstallData.setState(WITHDRAWN);
438 break;
439 }
440 store.write(uninstallData);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700441 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800442 }
443
444 @Override
445 public void onError(FlowRuleOperations ops) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700446 // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT)
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700447 if (toInstall.isPresent()) {
448 IntentData installData = toInstall.get();
449 log.warn("Failed installation: {} {} on {}",
450 installData.key(), installData.intent(), ops);
451 installData.setState(CORRUPT);
Brian O'Connor6d8e3172015-04-30 15:43:57 -0700452 installData.incrementErrorCount();
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700453 store.write(installData);
454 }
Sho SHIMIZUd4936252015-04-10 15:03:57 -0700455 // if toUninstall was cause of error, then CORRUPT (another job will clean this up)
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700456 if (toUninstall.isPresent()) {
457 IntentData uninstallData = toUninstall.get();
458 log.warn("Failed withdrawal: {} {} on {}",
459 uninstallData.key(), uninstallData.intent(), ops);
460 uninstallData.setState(CORRUPT);
Brian O'Connor6d8e3172015-04-30 15:43:57 -0700461 uninstallData.incrementErrorCount();
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700462 store.write(uninstallData);
463 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800464 }
465 });
466
Brian O'Connora7674262015-06-04 13:55:18 -0700467 if (log.isTraceEnabled()) {
468 log.trace("applying intent {} -> {} with {} rules: {}",
Sho SHIMIZU98c0a392016-01-14 18:40:53 -0800469 toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
470 toInstall.map(x -> x.key().toString()).orElse("<empty>"),
471 operations.stages().stream().mapToLong(i -> i.size()).sum(),
472 operations.stages());
Brian O'Connora7674262015-06-04 13:55:18 -0700473 }
474
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800475 flowRuleService.apply(operations);
476 }
477
Brian O'Connor66630c82014-10-02 21:08:19 -0700478}