blob: 761a9f21a409075bcd74403cb7a754d4ded33969 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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'Connorf0c5a052015-04-27 00:34:53 -070018import 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'Connorf0c5a052015-04-27 00:34:53 -070051import java.util.Collection;
52import java.util.EnumSet;
53import java.util.List;
54import java.util.Map;
55import java.util.Optional;
56import 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;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070065import static org.onosproject.net.intent.IntentState.*;
Sho SHIMIZUce49b602015-02-23 19:15:49 -080066import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase;
Brian O'Connorfa81eae2014-10-30 13:20:05 -070067import static org.slf4j.LoggerFactory.getLogger;
Brian O'Connor66630c82014-10-02 21:08:19 -070068
69/**
70 * An implementation of Intent Manager.
71 */
72@Component(immediate = true)
73@Service
74public class IntentManager
75 implements IntentService, IntentExtensionService {
Sho SHIMIZU8b5051d2014-11-05 11:24:13 -080076 private static final Logger log = getLogger(IntentManager.class);
Brian O'Connor66630c82014-10-02 21:08:19 -070077
78 public static final String INTENT_NULL = "Intent cannot be null";
Ray Milkeyf9af43c2015-02-09 16:45:48 -080079 public static final String INTENT_ID_NULL = "Intent key cannot be null";
Brian O'Connor66630c82014-10-02 21:08:19 -070080
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080081 private static final int NUM_THREADS = 12;
82
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080083 private static final EnumSet<IntentState> RECOMPILE
84 = EnumSet.of(INSTALL_REQ, FAILED, WITHDRAW_REQ);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080085
Brian O'Connor66630c82014-10-02 21:08:19 -070086 private final AbstractListenerRegistry<IntentEvent, IntentListener>
tom95329eb2014-10-06 08:40:06 -070087 listenerRegistry = new AbstractListenerRegistry<>();
Brian O'Connor66630c82014-10-02 21:08:19 -070088
Brian O'Connor520c0522014-11-23 23:50:47 -080089 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected CoreService coreService;
Brian O'Connor66630c82014-10-02 21:08:19 -070091
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected IntentStore store;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom85258ee2014-10-07 00:10:02 -070096 protected ObjectiveTrackerService trackerService;
tom95329eb2014-10-06 08:40:06 -070097
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Brian O'Connor66630c82014-10-02 21:08:19 -070099 protected EventDeliveryService eventDispatcher;
100
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sho SHIMIZU214ac322015-02-23 19:30:15 -0800102 protected FlowRuleService flowRuleService;
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700103
Brian O'Connor520c0522014-11-23 23:50:47 -0800104
Brian O'Connordb15b042015-02-04 14:59:28 -0800105 private ExecutorService batchExecutor;
106 private ExecutorService workerExecutor;
Brian O'Connor520c0522014-11-23 23:50:47 -0800107
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800108 private final CompilerRegistry compilerRegistry = new CompilerRegistry();
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800109 private final InternalIntentProcessor processor = new InternalIntentProcessor();
Brian O'Connor520c0522014-11-23 23:50:47 -0800110 private final IntentStoreDelegate delegate = new InternalStoreDelegate();
111 private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
112 private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
113 private IdGenerator idGenerator;
114
Brian O'Connorb499b352015-02-03 16:46:15 -0800115 private final IntentAccumulator accumulator = new IntentAccumulator(batchDelegate);
Brian O'Connorcff03322015-02-03 15:28:59 -0800116
Brian O'Connor66630c82014-10-02 21:08:19 -0700117 @Activate
118 public void activate() {
119 store.setDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700120 trackerService.setDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700121 eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
Brian O'Connorbdc7f002015-02-18 20:49:41 -0800122 batchExecutor = newSingleThreadExecutor(groupedThreads("onos/intent", "batch"));
123 workerExecutor = newFixedThreadPool(NUM_THREADS, groupedThreads("onos/intent", "worker-%d"));
Brian O'Connor520c0522014-11-23 23:50:47 -0800124 idGenerator = coreService.getIdGenerator("intent-ids");
125 Intent.bindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700126 log.info("Started");
127 }
128
129 @Deactivate
130 public void deactivate() {
131 store.unsetDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700132 trackerService.unsetDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700133 eventDispatcher.removeSink(IntentEvent.class);
Brian O'Connordb15b042015-02-04 14:59:28 -0800134 batchExecutor.shutdown();
Brian O'Connor520c0522014-11-23 23:50:47 -0800135 Intent.unbindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700136 log.info("Stopped");
137 }
138
139 @Override
140 public void submit(Intent intent) {
141 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800142 IntentData data = new IntentData(intent, IntentState.INSTALL_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800143 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700144 }
145
146 @Override
147 public void withdraw(Intent intent) {
148 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800149 IntentData data = new IntentData(intent, IntentState.WITHDRAW_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800150 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700151 }
152
Brian O'Connor66630c82014-10-02 21:08:19 -0700153 @Override
Ray Milkey8c6d00e2015-03-13 14:14:34 -0700154 public void purge(Intent intent) {
155 checkNotNull(intent, INTENT_NULL);
156 IntentData data = new IntentData(intent, IntentState.PURGE_REQ, null);
157 store.addPending(data);
158 }
159
160 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800161 public Intent getIntent(Key key) {
162 return store.getIntent(key);
163 }
164
165 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700166 public Iterable<Intent> getIntents() {
167 return store.getIntents();
168 }
169
170 @Override
171 public long getIntentCount() {
172 return store.getIntentCount();
173 }
174
175 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800176 public IntentState getIntentState(Key intentKey) {
177 checkNotNull(intentKey, INTENT_ID_NULL);
178 return store.getIntentState(intentKey);
Brian O'Connor66630c82014-10-02 21:08:19 -0700179 }
180
181 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800182 public List<Intent> getInstallableIntents(Key intentKey) {
183 checkNotNull(intentKey, INTENT_ID_NULL);
184 return store.getInstallableIntents(intentKey);
Thomas Vachuska10d4abc2014-10-21 12:47:26 -0700185 }
186
187 @Override
Brian O'Connorbe28a872015-02-19 21:44:37 -0800188 public boolean isLocal(Key intentKey) {
189 return store.isMaster(intentKey);
190 }
191
192 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700193 public void addListener(IntentListener listener) {
194 listenerRegistry.addListener(listener);
195 }
196
197 @Override
198 public void removeListener(IntentListener listener) {
199 listenerRegistry.removeListener(listener);
200 }
201
202 @Override
203 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800204 compilerRegistry.registerCompiler(cls, compiler);
Brian O'Connor66630c82014-10-02 21:08:19 -0700205 }
206
207 @Override
208 public <T extends Intent> void unregisterCompiler(Class<T> cls) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800209 compilerRegistry.unregisterCompiler(cls);
Brian O'Connor66630c82014-10-02 21:08:19 -0700210 }
211
212 @Override
213 public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800214 return compilerRegistry.getCompilers();
Brian O'Connor66630c82014-10-02 21:08:19 -0700215 }
216
217 @Override
Jonathan Hart34f1e382015-02-24 16:52:23 -0800218 public Iterable<Intent> getPending() {
219 return store.getPending();
220 }
221
Brian O'Connor66630c82014-10-02 21:08:19 -0700222 // Store delegate to re-post events emitted from the store.
223 private class InternalStoreDelegate implements IntentStoreDelegate {
224 @Override
225 public void notify(IntentEvent event) {
tom85258ee2014-10-07 00:10:02 -0700226 eventDispatcher.post(event);
Brian O'Connor66630c82014-10-02 21:08:19 -0700227 }
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800228
229 @Override
Brian O'Connorcff03322015-02-03 15:28:59 -0800230 public void process(IntentData data) {
231 accumulator.add(data);
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800232 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700233 }
234
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800235 private void buildAndSubmitBatches(Iterable<Key> intentKeys,
Brian O'Connor72a034c2014-11-26 18:24:23 -0800236 boolean compileAllFailed) {
Brian O'Connor72a034c2014-11-26 18:24:23 -0800237 // Attempt recompilation of the specified intents first.
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800238 for (Key key : intentKeys) {
239 Intent intent = store.getIntent(key);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800240 if (intent == null) {
241 continue;
242 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800243 submit(intent);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800244 }
245
246 if (compileAllFailed) {
247 // If required, compile all currently failed intents.
248 for (Intent intent : getIntents()) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800249 IntentState state = getIntentState(intent.key());
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800250 if (RECOMPILE.contains(state)) {
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800251 if (state == WITHDRAW_REQ) {
Brian O'Connor03406a42015-02-03 17:28:57 -0800252 withdraw(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800253 } else {
Brian O'Connor03406a42015-02-03 17:28:57 -0800254 submit(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800255 }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800256 }
257 }
258 }
259
Brian O'Connorb499b352015-02-03 16:46:15 -0800260 //FIXME
261// for (ApplicationId appId : batches.keySet()) {
262// if (batchService.isLocalLeader(appId)) {
263// execute(batches.get(appId).build());
264// }
265// }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800266 }
267
tom95329eb2014-10-06 08:40:06 -0700268 // Topology change delegate
269 private class InternalTopoChangeDelegate implements TopologyChangeDelegate {
270 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800271 public void triggerCompile(Iterable<Key> intentKeys,
tom85258ee2014-10-07 00:10:02 -0700272 boolean compileAllFailed) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800273 buildAndSubmitBatches(intentKeys, compileAllFailed);
tom95329eb2014-10-06 08:40:06 -0700274 }
tom95329eb2014-10-06 08:40:06 -0700275 }
tom85258ee2014-10-07 00:10:02 -0700276
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800277 private Future<FinalIntentProcessPhase> submitIntentData(IntentData data) {
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800278 IntentData current = store.getIntentData(data.key());
Sho SHIMIZUce49b602015-02-23 19:15:49 -0800279 IntentProcessPhase initial = newInitialPhase(processor, data, current);
280 return workerExecutor.submit(new IntentWorker(initial));
Sho SHIMIZU8d9d1362015-02-04 12:28:15 -0800281 }
282
Sho SHIMIZUd42058e2015-02-23 16:16:20 -0800283 private class IntentBatchProcess implements Runnable {
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800284
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800285 protected final Collection<IntentData> data;
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800286
Sho SHIMIZUd42058e2015-02-23 16:16:20 -0800287 IntentBatchProcess(Collection<IntentData> data) {
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800288 this.data = checkNotNull(data);
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800289 }
290
291 @Override
292 public void run() {
293 try {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800294 /*
295 1. wrap each intentdata in a runnable and submit
296 2. wait for completion of all the work
297 3. accumulate results and submit batch write of IntentData to store
298 (we can also try to update these individually)
299 */
300 submitUpdates(waitForFutures(createIntentUpdates()));
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800301 } catch (Exception e) {
302 log.error("Error submitting batches:", e);
303 // FIXME incomplete Intents should be cleaned up
304 // (transition to FAILED, etc.)
305
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800306 // the batch has failed
307 // TODO: maybe we should do more?
308 log.error("Walk the plank, matey...");
Brian O'Connorb499b352015-02-03 16:46:15 -0800309 //FIXME
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800310// batchService.removeIntentOperations(data);
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800311 }
Brian O'Connor3c4b00d2015-02-22 20:42:26 -0800312 accumulator.ready();
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800313 }
314
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800315 private List<Future<FinalIntentProcessPhase>> createIntentUpdates() {
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800316 return data.stream()
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800317 .map(IntentManager.this::submitIntentData)
318 .collect(Collectors.toList());
319 }
320
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800321 private List<FinalIntentProcessPhase> waitForFutures(List<Future<FinalIntentProcessPhase>> futures) {
322 ImmutableList.Builder<FinalIntentProcessPhase> updateBuilder = ImmutableList.builder();
323 for (Future<FinalIntentProcessPhase> future : futures) {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800324 try {
325 updateBuilder.add(future.get());
326 } catch (InterruptedException | ExecutionException e) {
327 //FIXME
328 log.warn("Future failed: {}", e);
329 }
330 }
331 return updateBuilder.build();
332 }
333
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800334 private void submitUpdates(List<FinalIntentProcessPhase> updates) {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800335 store.batchWrite(updates.stream()
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700336 .map(FinalIntentProcessPhase::data)
337 .collect(Collectors.toList()));
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800338 }
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800339 }
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -0800340
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700341 private class InternalBatchDelegate implements IntentBatchDelegate {
342 @Override
Brian O'Connorb499b352015-02-03 16:46:15 -0800343 public void execute(Collection<IntentData> operations) {
Brian O'Connorab8ef822015-02-17 18:08:54 -0800344 log.debug("Execute {} operation(s).", operations.size());
345 log.trace("Execute operations: {}", operations);
Sho SHIMIZU94b03b12015-04-10 14:53:13 -0700346
347 // batchExecutor is single-threaded, so only one batch is in flight at a time
Sho SHIMIZUd42058e2015-02-23 16:16:20 -0800348 batchExecutor.execute(new IntentBatchProcess(operations));
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700349 }
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700350 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800351
352 private class InternalIntentProcessor implements IntentProcessor {
353 @Override
354 public List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
355 return compilerRegistry.compile(intent, previousInstallables);
356 }
357
358 @Override
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700359 public void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700360 IntentManager.this.apply(toUninstall, toInstall);
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800361 }
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700362 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800363
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700364 private enum Direction {
365 ADD,
366 REMOVE
367 }
368
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700369 private void applyIntentData(Optional<IntentData> intentData,
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700370 FlowRuleOperations.Builder builder,
371 Direction direction) {
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700372 if (!intentData.isPresent()) {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700373 return;
374 }
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700375 IntentData data = intentData.get();
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700376
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700377 List<Intent> intentsToApply = data.installables();
378 if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
379 throw new IllegalStateException("installable intents must be FlowRuleIntent");
380 }
381
382 if (direction == Direction.ADD) {
383 trackerService.addTrackedResources(data.key(), data.intent().resources());
384 intentsToApply.forEach(installable ->
385 trackerService.addTrackedResources(data.key(), installable.resources()));
386 } else {
387 trackerService.removeTrackedResources(data.key(), data.intent().resources());
388 intentsToApply.forEach(installable ->
389 trackerService.removeTrackedResources(data.intent().key(),
390 installable.resources()));
391 }
392
393 // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so.
394 builder.newStage();
395
396 List<Collection<FlowRule>> stages = intentsToApply.stream()
397 .map(x -> (FlowRuleIntent) x)
398 .map(FlowRuleIntent::flowRules)
399 .collect(Collectors.toList());
400
401 for (Collection<FlowRule> rules : stages) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700402 if (direction == Direction.ADD) {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700403 rules.forEach(builder::add);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700404 } else {
Sho SHIMIZUfcf861a2015-04-10 14:37:08 -0700405 rules.forEach(builder::remove);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700406 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800407 }
408
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800409 }
410
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700411 private void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800412 // need to consider if FlowRuleIntent is only one as installable intent or not
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800413
414 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700415 applyIntentData(toUninstall, builder, Direction.REMOVE);
416 applyIntentData(toInstall, builder, Direction.ADD);
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800417
418 FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
419 @Override
420 public void onSuccess(FlowRuleOperations ops) {
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700421 if (toInstall.isPresent()) {
422 IntentData installData = toInstall.get();
423 log.debug("Completed installing: {}", installData.key());
424 installData.setState(INSTALLED);
425 store.write(installData);
426 } else if (toUninstall.isPresent()) {
427 IntentData uninstallData = toUninstall.get();
428 log.debug("Completed withdrawing: {}", uninstallData.key());
429 switch (uninstallData.request()) {
430 case INSTALL_REQ:
431 uninstallData.setState(FAILED);
432 break;
433 case WITHDRAW_REQ:
434 default: //TODO "default" case should not happen
435 uninstallData.setState(WITHDRAWN);
436 break;
437 }
438 store.write(uninstallData);
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700439 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800440 }
441
442 @Override
443 public void onError(FlowRuleOperations ops) {
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700444 // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT)
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700445 if (toInstall.isPresent()) {
446 IntentData installData = toInstall.get();
447 log.warn("Failed installation: {} {} on {}",
448 installData.key(), installData.intent(), ops);
449 installData.setState(CORRUPT);
450 store.write(installData);
451 }
Sho SHIMIZUd4936252015-04-10 15:03:57 -0700452 // if toUninstall was cause of error, then CORRUPT (another job will clean this up)
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700453 if (toUninstall.isPresent()) {
454 IntentData uninstallData = toUninstall.get();
455 log.warn("Failed withdrawal: {} {} on {}",
456 uninstallData.key(), uninstallData.intent(), ops);
457 uninstallData.setState(CORRUPT);
458 store.write(uninstallData);
459 }
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800460 }
461 });
462
463 flowRuleService.apply(operations);
464 }
465
Brian O'Connor66630c82014-10-02 21:08:19 -0700466}