Intent F/W improvements
- aggregate installables into FlowRuleOperations
- added some impl. to SimpleIntentStore
- created Coordinating State
Change-Id: I5b26ec1fdb7aaff9d5da4f21b2d5a249568ac5ac
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentInstaller.java b/core/api/src/main/java/org/onosproject/net/intent/IntentInstaller.java
index 50c609a..b260080 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentInstaller.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentInstaller.java
@@ -15,16 +15,14 @@
*/
package org.onosproject.net.intent;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
import org.onosproject.net.flow.FlowRuleBatchOperation;
-import org.onosproject.net.flow.FlowRuleOperations;
import java.util.List;
/**
* Abstraction of entity capable of installing intents to the environment.
*/
+//TODO consider refactoring this API
public interface IntentInstaller<T extends Intent> {
/**
* Installs the specified intent to the environment.
@@ -33,32 +31,7 @@
* @return flow rule operations to complete install
* @throws IntentException if issues are encountered while installing the intent
*/
- @Deprecated
List<FlowRuleBatchOperation> install(T intent);
- // FIXME
- default FlowRuleOperations.Builder install2(T intent) {
- FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
- for (FlowRuleBatchOperation batch : install(intent)) {
- for (FlowRuleBatchEntry entry : batch.getOperations()) {
- FlowRule rule = entry.target();
- switch (entry.operator()) {
- case ADD:
- builder.add(rule);
- break;
- case REMOVE:
- builder.remove(rule);
- break;
- case MODIFY:
- builder.modify(rule);
- break;
- default:
- break;
- }
- }
- builder.newStage();
- }
- return builder;
- }
/**
* Uninstalls the specified intent from the environment.
@@ -67,32 +40,7 @@
* @return flow rule operations to complete uninstall
* @throws IntentException if issues are encountered while uninstalling the intent
*/
- @Deprecated
List<FlowRuleBatchOperation> uninstall(T intent);
- // FIXME
- default FlowRuleOperations.Builder uninstall2(T intent) {
- FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
- for (FlowRuleBatchOperation batch : uninstall(intent)) {
- for (FlowRuleBatchEntry entry : batch.getOperations()) {
- FlowRule rule = entry.target();
- switch (entry.operator()) {
- case ADD:
- builder.add(rule);
- break;
- case REMOVE:
- builder.remove(rule);
- break;
- case MODIFY:
- builder.modify(rule);
- break;
- default:
- break;
- }
- }
- builder.newStage();
- }
- return builder;
- }
/**
* Replaces the specified intent with a new one in the environment.
@@ -104,29 +52,5 @@
*/
@Deprecated
List<FlowRuleBatchOperation> replace(T oldIntent, T newIntent);
- // FIXME
- default FlowRuleOperations.Builder replace2(T oldIntent, T newIntent) {
- FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
- for (FlowRuleBatchOperation batch : replace(oldIntent, newIntent)) {
- for (FlowRuleBatchEntry entry : batch.getOperations()) {
- FlowRule rule = entry.target();
- switch (entry.operator()) {
- case ADD:
- builder.add(rule);
- break;
- case REMOVE:
- builder.remove(rule);
- break;
- case MODIFY:
- builder.modify(rule);
- break;
- default:
- break;
- }
- }
- builder.newStage();
- }
- return builder;
- }
}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/Compiling.java b/core/net/src/main/java/org/onosproject/net/intent/impl/Compiling.java
index e784621..eef8d0b 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/Compiling.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/Compiling.java
@@ -46,7 +46,7 @@
try {
List<Intent> installables = (current != null) ? current.installables() : null;
pending.setInstallables(intentManager.compileIntent(pending.intent(), installables));
- return Optional.of(new Installing(intentManager, pending, current));
+ return Optional.of(new Coordinating(intentManager, pending, current));
} catch (PathNotFoundException e) {
log.debug("Path not found for intent {}", pending.intent());
// TODO: revisit to implement failure handling
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/Coordinating.java b/core/net/src/main/java/org/onosproject/net/intent/impl/Coordinating.java
new file mode 100644
index 0000000..3682dbf
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/Coordinating.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.intent.IntentData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+// TODO: better naming because install() method actually generate FlowRuleBatchOperations
+class Coordinating implements IntentUpdate {
+
+ private static final Logger log = LoggerFactory.getLogger(Coordinating.class);
+
+ private final IntentManager intentManager;
+ private final IntentData pending;
+ private final IntentData current;
+
+ // TODO: define an interface and use it, instead of IntentManager
+ Coordinating(IntentManager intentManager, IntentData pending, IntentData current) {
+ this.intentManager = checkNotNull(intentManager);
+ this.pending = checkNotNull(pending);
+ this.current = current;
+ }
+
+ @Override
+ public Optional<IntentUpdate> execute() {
+ try {
+ FlowRuleOperations flowRules = intentManager.coordinate(pending);
+ return Optional.of(new Installing(intentManager, pending, flowRules));
+ } catch (FlowRuleBatchOperationConversionException e) {
+ log.warn("Unable to install intent {} due to:", pending.intent().id(), e.getCause());
+ return Optional.of(new InstallingFailed(pending)); //FIXME
+ }
+ }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/Installing.java b/core/net/src/main/java/org/onosproject/net/intent/impl/Installing.java
index 0d9ce36..c8d0294 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/Installing.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/Installing.java
@@ -31,22 +31,19 @@
private final IntentManager intentManager;
private final IntentData pending;
- private final IntentData current;
+ private final FlowRuleOperations flowRules;
// TODO: define an interface and use it, instead of IntentManager
- Installing(IntentManager intentManager, IntentData pending, IntentData current) {
+ Installing(IntentManager intentManager, IntentData pending, FlowRuleOperations flowRules) {
this.intentManager = checkNotNull(intentManager);
this.pending = checkNotNull(pending);
- this.current = current;
+ this.flowRules = flowRules;
}
@Override
public Optional<IntentUpdate> execute() {
try {
- FlowRuleOperations flowRules = intentManager.coordinate(pending.installables());
- // TODO: call FlowRuleService API to push FlowRules and track resources,
- // which the submitted intent will use.
- intentManager.flowRuleService.apply(flowRules);
+ intentManager.flowRuleService.apply(flowRules); // FIXME we need to provide a context
return Optional.of(new Installed(pending));
} catch (FlowRuleBatchOperationConversionException e) {
log.warn("Unable to install intent {} due to:", pending.intent().id(), e.getCause());
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
index 086578c..65da61a 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
@@ -28,8 +28,13 @@
import org.onosproject.core.IdGenerator;
import org.onosproject.event.AbstractListenerRegistry;
import org.onosproject.event.EventDeliveryService;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleBatchEntry;
import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.FlowRuleEvent;
+import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentBatchDelegate;
@@ -50,6 +55,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -281,19 +287,74 @@
//TODO javadoc
//FIXME
- FlowRuleOperations coordinate(List<Intent> installables) {
- //List<FlowRuleBatchOperation> batches = new ArrayList<>(installables.size());
+ FlowRuleOperations coordinate(IntentData pending) {
+ List<Intent> installables = pending.installables();
+ List<List<FlowRuleBatchOperation>> plans = new ArrayList<>(installables.size());
for (Intent installable : installables) {
try {
registerSubclassInstallerIfNeeded(installable);
//FIXME need to migrate installers to FlowRuleOperations
// FIXME need to aggregate the FlowRuleOperations across installables
- getInstaller(installable).install2(installable).build(null/*FIXME*/);
+ plans.add(getInstaller(installable).install(installable));
} catch (Exception e) { // TODO this should be IntentException
throw new FlowRuleBatchOperationConversionException(null/*FIXME*/, e);
}
}
- return null;
+
+ return merge(plans).build(new FlowRuleOperationsContext() { // FIXME move this out
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Completed installing: {}", pending.key());
+ pending.setState(INSTALLED);
+ store.write(pending);
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ //FIXME store.write(pending.setState(BROKEN));
+ }
+ });
+ }
+
+ // FIXME... needs tests... or maybe it's just perfect
+ private FlowRuleOperations.Builder merge(List<List<FlowRuleBatchOperation>> plans) {
+ FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
+ // Build a batch one stage at a time
+ for (int stageNumber = 0;; stageNumber++) {
+ // Get the sub-stage from each plan (List<FlowRuleBatchOperation>)
+ for (Iterator<List<FlowRuleBatchOperation>> itr = plans.iterator(); itr.hasNext();) {
+ List<FlowRuleBatchOperation> plan = itr.next();
+ if (plan.size() <= stageNumber) {
+ // we have consumed all stages from this plan, so remove it
+ itr.remove();
+ continue;
+ }
+ // write operations from this sub-stage into the builder
+ FlowRuleBatchOperation stage = plan.get(stageNumber);
+ for (FlowRuleBatchEntry entry : stage.getOperations()) {
+ FlowRule rule = entry.target();
+ switch (entry.operator()) {
+ case ADD:
+ builder.add(rule);
+ break;
+ case REMOVE:
+ builder.remove(rule);
+ break;
+ case MODIFY:
+ builder.modify(rule);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ // we are done with the stage, start the next one...
+ if (plans.isEmpty()) {
+ break; // we don't need to start a new stage, we are done.
+ }
+ builder.newStage();
+ }
+ return builder;
}
/**
@@ -311,7 +372,7 @@
installable.resources());
try {
// FIXME need to aggregate the FlowRuleOperations across installables
- getInstaller(installable).uninstall2(installable).build(null/*FIXME*/);
+ getInstaller(installable).uninstall(installable); //.build(null/*FIXME*/);
} catch (IntentException e) {
log.warn("Unable to uninstall intent {} due to:", intent.id(), e);
// TODO: this should never happen. but what if it does?
diff --git a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleIntentStore.java b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleIntentStore.java
index 6658eff..988d02a 100644
--- a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleIntentStore.java
+++ b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleIntentStore.java
@@ -25,6 +25,8 @@
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentEvent;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.IntentStore;
import org.onosproject.net.intent.IntentStoreDelegate;
import org.onosproject.net.intent.Key;
@@ -33,6 +35,7 @@
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -73,6 +76,36 @@
}
@Override
+ public Intent getIntent(IntentId intentId) {
+ for (IntentData data : current.values()) {
+ if (Objects.equals(data.intent().id(), intentId)) {
+ return data.intent();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public IntentState getIntentState(IntentId intentId) {
+ for (IntentData data : current.values()) {
+ if (Objects.equals(data.intent().id(), intentId)) {
+ return data.state();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public List<Intent> getInstallableIntents(IntentId intentId) {
+ for (IntentData data : current.values()) {
+ if (Objects.equals(data.intent().id(), intentId)) {
+ return data.installables();
+ }
+ }
+ return null;
+ }
+
+ @Override
public IntentData getIntentData(Key key) {
return current.get(key);
}
@@ -164,6 +197,12 @@
}
}
+ @Override
+ public Intent getIntent(Key key) {
+ IntentData data = current.get(key);
+ return (data != null) ? data.intent() : null;
+ }
+
@Override
public void addPending(IntentData data) {