mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-25 14:21:33 +02:00
ONOS-1048 - Define interfaces instead of using IntentManager
- Define IntentProcessor interface containing methods to process an intent - Pull out IntentCompiler related tasks to CompilerRegistry - Pull out IntentInstaller related tasks to InstallerRegistry - Create an IntentProcessor subclass as inner class in IntentManager Change-Id: Ia3e8d574a1053e7ddc9b961873ef758c9e0b1b26
This commit is contained in:
parent
054da97e83
commit
b0a47d41c8
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.onosproject.net.intent.Intent;
|
||||||
|
import org.onosproject.net.intent.IntentCompiler;
|
||||||
|
import org.onosproject.net.intent.IntentException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
// TODO: consider a better name
|
||||||
|
class CompilerRegistry {
|
||||||
|
|
||||||
|
private final ConcurrentMap<Class<? extends Intent>,
|
||||||
|
IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the specified compiler for the given intent class.
|
||||||
|
*
|
||||||
|
* @param cls intent class
|
||||||
|
* @param compiler intent compiler
|
||||||
|
* @param <T> the type of intent
|
||||||
|
*/
|
||||||
|
public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
|
||||||
|
compilers.put(cls, compiler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters the compiler for the specified intent class.
|
||||||
|
*
|
||||||
|
* @param cls intent class
|
||||||
|
* @param <T> the type of intent
|
||||||
|
*/
|
||||||
|
public <T extends Intent> void unregisterCompiler(Class<T> cls) {
|
||||||
|
compilers.remove(cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns immutable set of bindings of currently registered intent compilers.
|
||||||
|
*
|
||||||
|
* @return the set of compiler bindings
|
||||||
|
*/
|
||||||
|
public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
|
||||||
|
return ImmutableMap.copyOf(compilers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles an intent recursively.
|
||||||
|
*
|
||||||
|
* @param intent intent
|
||||||
|
* @param previousInstallables previous intent installables
|
||||||
|
* @return result of compilation
|
||||||
|
*/
|
||||||
|
List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
|
||||||
|
if (intent.isInstallable()) {
|
||||||
|
return ImmutableList.of(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerSubclassCompilerIfNeeded(intent);
|
||||||
|
// FIXME: get previous resources
|
||||||
|
List<Intent> installable = new ArrayList<>();
|
||||||
|
for (Intent compiled : getCompiler(intent).compile(intent, previousInstallables, null)) {
|
||||||
|
installable.addAll(compile(compiled, previousInstallables));
|
||||||
|
}
|
||||||
|
return installable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the corresponding intent compiler to the specified intent.
|
||||||
|
*
|
||||||
|
* @param intent intent
|
||||||
|
* @param <T> the type of intent
|
||||||
|
* @return intent compiler corresponding to the specified intent
|
||||||
|
*/
|
||||||
|
private <T extends Intent> IntentCompiler<T> getCompiler(T intent) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
IntentCompiler<T> compiler = (IntentCompiler<T>) compilers.get(intent.getClass());
|
||||||
|
if (compiler == null) {
|
||||||
|
throw new IntentException("no compiler for class " + intent.getClass());
|
||||||
|
}
|
||||||
|
return compiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an intent compiler of the specified intent if an intent compiler
|
||||||
|
* for the intent is not registered. This method traverses the class hierarchy of
|
||||||
|
* the intent. Once an intent compiler for a parent type is found, this method
|
||||||
|
* registers the found intent compiler.
|
||||||
|
*
|
||||||
|
* @param intent intent
|
||||||
|
*/
|
||||||
|
private void registerSubclassCompilerIfNeeded(Intent intent) {
|
||||||
|
if (!compilers.containsKey(intent.getClass())) {
|
||||||
|
Class<?> cls = intent.getClass();
|
||||||
|
while (cls != Object.class) {
|
||||||
|
// As long as we're within the Intent class descendants
|
||||||
|
if (Intent.class.isAssignableFrom(cls)) {
|
||||||
|
IntentCompiler<?> compiler = compilers.get(cls);
|
||||||
|
if (compiler != null) {
|
||||||
|
compilers.put(intent.getClass(), compiler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cls = cls.getSuperclass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,254 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.google.common.collect.ImmutableMap;
|
||||||
|
import org.onosproject.net.flow.FlowRuleOperation;
|
||||||
|
import org.onosproject.net.flow.FlowRuleOperations;
|
||||||
|
import org.onosproject.net.flow.FlowRuleOperationsContext;
|
||||||
|
import org.onosproject.net.intent.Intent;
|
||||||
|
import org.onosproject.net.intent.IntentData;
|
||||||
|
import org.onosproject.net.intent.IntentException;
|
||||||
|
import org.onosproject.net.intent.IntentInstaller;
|
||||||
|
import org.onosproject.net.intent.IntentStore;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
import static org.onlab.util.Tools.isNullOrEmpty;
|
||||||
|
import static org.onosproject.net.intent.IntentState.FAILED;
|
||||||
|
import static org.onosproject.net.intent.IntentState.INSTALLED;
|
||||||
|
import static org.onosproject.net.intent.IntentState.WITHDRAWN;
|
||||||
|
|
||||||
|
// TODO: consider a better name
|
||||||
|
class InstallerRegistry {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(InstallerRegistry.class);
|
||||||
|
|
||||||
|
private final ConcurrentMap<Class<? extends Intent>,
|
||||||
|
IntentInstaller<? extends Intent>> installers = new ConcurrentHashMap<>();
|
||||||
|
/**
|
||||||
|
* Registers the specified installer for the given installable intent class.
|
||||||
|
*
|
||||||
|
* @param cls installable intent class
|
||||||
|
* @param installer intent installer
|
||||||
|
* @param <T> the type of installable intent
|
||||||
|
*/
|
||||||
|
<T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
|
||||||
|
installers.put(cls, installer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters the installer for the given installable intent class.
|
||||||
|
*
|
||||||
|
* @param cls installable intent class
|
||||||
|
* @param <T> the type of installable intent
|
||||||
|
*/
|
||||||
|
<T extends Intent> void unregisterInstaller(Class<T> cls) {
|
||||||
|
installers.remove(cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns immutable set of bindings of currently registered intent installers.
|
||||||
|
*
|
||||||
|
* @return the set of installer bindings
|
||||||
|
*/
|
||||||
|
Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers() {
|
||||||
|
return ImmutableMap.copyOf(installers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the corresponding intent installer to the specified installable intent.
|
||||||
|
*
|
||||||
|
* @param intent intent
|
||||||
|
* @param <T> the type of installable intent
|
||||||
|
* @return intent installer corresponding to the specified installable intent
|
||||||
|
*/
|
||||||
|
private <T extends Intent> IntentInstaller<T> getInstaller(T intent) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass());
|
||||||
|
if (installer == null) {
|
||||||
|
throw new IntentException("no installer for class " + intent.getClass());
|
||||||
|
}
|
||||||
|
return installer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an intent installer of the specified intent if an intent installer
|
||||||
|
* for the intent is not registered. This method traverses the class hierarchy of
|
||||||
|
* the intent. Once an intent installer for a parent type is found, this method
|
||||||
|
* registers the found intent installer.
|
||||||
|
*
|
||||||
|
* @param intent intent
|
||||||
|
*/
|
||||||
|
private void registerSubclassInstallerIfNeeded(Intent intent) {
|
||||||
|
if (!installers.containsKey(intent.getClass())) {
|
||||||
|
Class<?> cls = intent.getClass();
|
||||||
|
while (cls != Object.class) {
|
||||||
|
// As long as we're within the Intent class descendants
|
||||||
|
if (Intent.class.isAssignableFrom(cls)) {
|
||||||
|
IntentInstaller<?> installer = installers.get(cls);
|
||||||
|
if (installer != null) {
|
||||||
|
installers.put(intent.getClass(), installer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cls = cls.getSuperclass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a {@link FlowRuleOperations} instance from the specified intent data.
|
||||||
|
*
|
||||||
|
* @param current intent data stored in the store
|
||||||
|
* @param pending intent data being processed
|
||||||
|
* @param store intent store saving the intent state in this method
|
||||||
|
* @param trackerService objective tracker that is used in this method
|
||||||
|
* @return flow rule operations
|
||||||
|
*/
|
||||||
|
public FlowRuleOperations coordinate(IntentData current, IntentData pending,
|
||||||
|
IntentStore store, ObjectiveTrackerService trackerService) {
|
||||||
|
List<Intent> oldInstallables = (current != null) ? current.installables() : null;
|
||||||
|
List<Intent> newInstallables = pending.installables();
|
||||||
|
|
||||||
|
checkState(isNullOrEmpty(oldInstallables) ||
|
||||||
|
oldInstallables.size() == newInstallables.size(),
|
||||||
|
"Old and New Intent must have equivalent installable intents.");
|
||||||
|
|
||||||
|
List<List<Collection<FlowRuleOperation>>> plans = new ArrayList<>();
|
||||||
|
for (int i = 0; i < newInstallables.size(); i++) {
|
||||||
|
Intent newInstallable = newInstallables.get(i);
|
||||||
|
registerSubclassInstallerIfNeeded(newInstallable);
|
||||||
|
//TODO consider migrating installers to FlowRuleOperations
|
||||||
|
/* FIXME
|
||||||
|
- we need to do another pass on this method about that doesn't
|
||||||
|
require the length of installables to be equal, and also doesn't
|
||||||
|
depend on ordering
|
||||||
|
- we should also reconsider when to start/stop tracking resources
|
||||||
|
*/
|
||||||
|
if (isNullOrEmpty(oldInstallables)) {
|
||||||
|
plans.add(getInstaller(newInstallable).install(newInstallable));
|
||||||
|
} else {
|
||||||
|
Intent oldInstallable = oldInstallables.get(i);
|
||||||
|
checkState(oldInstallable.getClass().equals(newInstallable.getClass()),
|
||||||
|
"Installable Intent type mismatch.");
|
||||||
|
trackerService.removeTrackedResources(pending.key(), oldInstallable.resources());
|
||||||
|
plans.add(getInstaller(newInstallable).replace(oldInstallable, newInstallable));
|
||||||
|
}
|
||||||
|
trackerService.addTrackedResources(pending.key(), newInstallable.resources());
|
||||||
|
// } catch (IntentException e) {
|
||||||
|
// log.warn("Unable to update intent {} due to:", oldIntent.id(), e);
|
||||||
|
// //FIXME... we failed. need to uninstall (if same) or revert (if different)
|
||||||
|
// trackerService.removeTrackedResources(newIntent.id(), newInstallable.resources());
|
||||||
|
// exception = e;
|
||||||
|
// batches = uninstallIntent(oldIntent, oldInstallables);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
return merge(plans).build(new FlowRuleOperationsContext() { // TODO move this out
|
||||||
|
@Override
|
||||||
|
public void onSuccess(FlowRuleOperations ops) {
|
||||||
|
log.debug("Completed installing: {}", pending.key());
|
||||||
|
pending.setState(INSTALLED);
|
||||||
|
store.write(pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(FlowRuleOperations ops) {
|
||||||
|
log.warn("Failed installation: {} {} on {}", pending.key(),
|
||||||
|
pending.intent(), ops);
|
||||||
|
//TODO store.write(pending.setState(BROKEN));
|
||||||
|
pending.setState(FAILED);
|
||||||
|
store.write(pending);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a {@link FlowRuleOperations} instance from the specified intent data.
|
||||||
|
*
|
||||||
|
* @param current intent data stored in the store
|
||||||
|
* @param pending intent date being processed
|
||||||
|
* @param store intent store saving the intent state in this method
|
||||||
|
* @param trackerService objective tracker that is used in this method
|
||||||
|
* @return flow rule operations
|
||||||
|
*/
|
||||||
|
FlowRuleOperations uninstallCoordinate(IntentData current, IntentData pending,
|
||||||
|
IntentStore store, ObjectiveTrackerService trackerService) {
|
||||||
|
List<Intent> installables = current.installables();
|
||||||
|
List<List<Collection<FlowRuleOperation>>> plans = new ArrayList<>();
|
||||||
|
for (Intent installable : installables) {
|
||||||
|
plans.add(getInstaller(installable).uninstall(installable));
|
||||||
|
trackerService.removeTrackedResources(pending.key(), installable.resources());
|
||||||
|
}
|
||||||
|
|
||||||
|
return merge(plans).build(new FlowRuleOperationsContext() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(FlowRuleOperations ops) {
|
||||||
|
log.debug("Completed withdrawing: {}", pending.key());
|
||||||
|
pending.setState(WITHDRAWN);
|
||||||
|
pending.setInstallables(Collections.emptyList());
|
||||||
|
store.write(pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(FlowRuleOperations ops) {
|
||||||
|
log.warn("Failed withdraw: {}", pending.key());
|
||||||
|
pending.setState(FAILED);
|
||||||
|
store.write(pending);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO needs tests... or maybe it's just perfect
|
||||||
|
private FlowRuleOperations.Builder merge(List<List<Collection<FlowRuleOperation>>> 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<Set<FlowRuleOperation>)
|
||||||
|
for (Iterator<List<Collection<FlowRuleOperation>>> itr = plans.iterator(); itr.hasNext();) {
|
||||||
|
List<Collection<FlowRuleOperation>> 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
|
||||||
|
Collection<FlowRuleOperation> stage = plan.get(stageNumber);
|
||||||
|
for (FlowRuleOperation entry : stage) {
|
||||||
|
builder.operation(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,7 +16,6 @@
|
|||||||
package org.onosproject.net.intent.impl;
|
package org.onosproject.net.intent.impl;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import org.apache.felix.scr.annotations.Activate;
|
import org.apache.felix.scr.annotations.Activate;
|
||||||
import org.apache.felix.scr.annotations.Component;
|
import org.apache.felix.scr.annotations.Component;
|
||||||
import org.apache.felix.scr.annotations.Deactivate;
|
import org.apache.felix.scr.annotations.Deactivate;
|
||||||
@ -27,16 +26,13 @@ import org.onosproject.core.CoreService;
|
|||||||
import org.onosproject.core.IdGenerator;
|
import org.onosproject.core.IdGenerator;
|
||||||
import org.onosproject.event.AbstractListenerRegistry;
|
import org.onosproject.event.AbstractListenerRegistry;
|
||||||
import org.onosproject.event.EventDeliveryService;
|
import org.onosproject.event.EventDeliveryService;
|
||||||
import org.onosproject.net.flow.FlowRuleOperation;
|
|
||||||
import org.onosproject.net.flow.FlowRuleOperations;
|
import org.onosproject.net.flow.FlowRuleOperations;
|
||||||
import org.onosproject.net.flow.FlowRuleOperationsContext;
|
|
||||||
import org.onosproject.net.flow.FlowRuleService;
|
import org.onosproject.net.flow.FlowRuleService;
|
||||||
import org.onosproject.net.intent.Intent;
|
import org.onosproject.net.intent.Intent;
|
||||||
import org.onosproject.net.intent.IntentBatchDelegate;
|
import org.onosproject.net.intent.IntentBatchDelegate;
|
||||||
import org.onosproject.net.intent.IntentCompiler;
|
import org.onosproject.net.intent.IntentCompiler;
|
||||||
import org.onosproject.net.intent.IntentData;
|
import org.onosproject.net.intent.IntentData;
|
||||||
import org.onosproject.net.intent.IntentEvent;
|
import org.onosproject.net.intent.IntentEvent;
|
||||||
import org.onosproject.net.intent.IntentException;
|
|
||||||
import org.onosproject.net.intent.IntentExtensionService;
|
import org.onosproject.net.intent.IntentExtensionService;
|
||||||
import org.onosproject.net.intent.IntentInstaller;
|
import org.onosproject.net.intent.IntentInstaller;
|
||||||
import org.onosproject.net.intent.IntentListener;
|
import org.onosproject.net.intent.IntentListener;
|
||||||
@ -53,29 +49,26 @@ import org.onosproject.net.intent.impl.phase.WithdrawRequest;
|
|||||||
import org.onosproject.net.intent.impl.phase.Withdrawn;
|
import org.onosproject.net.intent.impl.phase.Withdrawn;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
import static java.util.concurrent.Executors.newFixedThreadPool;
|
import static java.util.concurrent.Executors.newFixedThreadPool;
|
||||||
import static java.util.concurrent.Executors.newSingleThreadExecutor;
|
import static java.util.concurrent.Executors.newSingleThreadExecutor;
|
||||||
import static org.onlab.util.Tools.groupedThreads;
|
import static org.onlab.util.Tools.groupedThreads;
|
||||||
import static org.onlab.util.Tools.isNullOrEmpty;
|
import static org.onlab.util.Tools.isNullOrEmpty;
|
||||||
import static org.onosproject.net.intent.IntentState.*;
|
import static org.onosproject.net.intent.IntentState.FAILED;
|
||||||
|
import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
|
||||||
|
import static org.onosproject.net.intent.IntentState.WITHDRAWN;
|
||||||
|
import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
|
||||||
import static org.slf4j.LoggerFactory.getLogger;
|
import static org.slf4j.LoggerFactory.getLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,12 +88,6 @@ public class IntentManager
|
|||||||
private static final EnumSet<IntentState> RECOMPILE
|
private static final EnumSet<IntentState> RECOMPILE
|
||||||
= EnumSet.of(INSTALL_REQ, FAILED, WITHDRAW_REQ);
|
= EnumSet.of(INSTALL_REQ, FAILED, WITHDRAW_REQ);
|
||||||
|
|
||||||
// Collections for compiler, installer, and listener are ONOS instance local
|
|
||||||
private final ConcurrentMap<Class<? extends Intent>,
|
|
||||||
IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>();
|
|
||||||
private final ConcurrentMap<Class<? extends Intent>,
|
|
||||||
IntentInstaller<? extends Intent>> installers = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private final AbstractListenerRegistry<IntentEvent, IntentListener>
|
private final AbstractListenerRegistry<IntentEvent, IntentListener>
|
||||||
listenerRegistry = new AbstractListenerRegistry<>();
|
listenerRegistry = new AbstractListenerRegistry<>();
|
||||||
|
|
||||||
@ -124,6 +111,9 @@ public class IntentManager
|
|||||||
private ExecutorService batchExecutor;
|
private ExecutorService batchExecutor;
|
||||||
private ExecutorService workerExecutor;
|
private ExecutorService workerExecutor;
|
||||||
|
|
||||||
|
private final CompilerRegistry compilerRegistry = new CompilerRegistry();
|
||||||
|
private final InstallerRegistry installerRegistry = new InstallerRegistry();
|
||||||
|
private final InternalIntentProcessor processor = new InternalIntentProcessor();
|
||||||
private final IntentStoreDelegate delegate = new InternalStoreDelegate();
|
private final IntentStoreDelegate delegate = new InternalStoreDelegate();
|
||||||
private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
|
private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
|
||||||
private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
|
private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
|
||||||
@ -211,259 +201,32 @@ public class IntentManager
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
|
public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
|
||||||
compilers.put(cls, compiler);
|
compilerRegistry.registerCompiler(cls, compiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Intent> void unregisterCompiler(Class<T> cls) {
|
public <T extends Intent> void unregisterCompiler(Class<T> cls) {
|
||||||
compilers.remove(cls);
|
compilerRegistry.unregisterCompiler(cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
|
public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
|
||||||
return ImmutableMap.copyOf(compilers);
|
return compilerRegistry.getCompilers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
|
public <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
|
||||||
installers.put(cls, installer);
|
installerRegistry.registerInstaller(cls, installer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Intent> void unregisterInstaller(Class<T> cls) {
|
public <T extends Intent> void unregisterInstaller(Class<T> cls) {
|
||||||
installers.remove(cls);
|
installerRegistry.unregisterInstaller(cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers() {
|
public Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers() {
|
||||||
return ImmutableMap.copyOf(installers);
|
return installerRegistry.getInstallers();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the corresponding intent compiler to the specified intent.
|
|
||||||
*
|
|
||||||
* @param intent intent
|
|
||||||
* @param <T> the type of intent
|
|
||||||
* @return intent compiler corresponding to the specified intent
|
|
||||||
*/
|
|
||||||
private <T extends Intent> IntentCompiler<T> getCompiler(T intent) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
IntentCompiler<T> compiler = (IntentCompiler<T>) compilers.get(intent.getClass());
|
|
||||||
if (compiler == null) {
|
|
||||||
throw new IntentException("no compiler for class " + intent.getClass());
|
|
||||||
}
|
|
||||||
return compiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the corresponding intent installer to the specified installable intent.
|
|
||||||
*
|
|
||||||
* @param intent intent
|
|
||||||
* @param <T> the type of installable intent
|
|
||||||
* @return intent installer corresponding to the specified installable intent
|
|
||||||
*/
|
|
||||||
private <T extends Intent> IntentInstaller<T> getInstaller(T intent) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass());
|
|
||||||
if (installer == null) {
|
|
||||||
throw new IntentException("no installer for class " + intent.getClass());
|
|
||||||
}
|
|
||||||
return installer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles an intent recursively.
|
|
||||||
*
|
|
||||||
* @param intent intent
|
|
||||||
* @param previousInstallables previous intent installables
|
|
||||||
* @return result of compilation
|
|
||||||
*/
|
|
||||||
// TODO: make this non-public due to short term hack for ONOS-1051
|
|
||||||
public List<Intent> compileIntent(Intent intent, List<Intent> previousInstallables) {
|
|
||||||
if (intent.isInstallable()) {
|
|
||||||
return ImmutableList.of(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
registerSubclassCompilerIfNeeded(intent);
|
|
||||||
// FIXME: get previous resources
|
|
||||||
List<Intent> installable = new ArrayList<>();
|
|
||||||
for (Intent compiled : getCompiler(intent).compile(intent, previousInstallables, null)) {
|
|
||||||
installable.addAll(compileIntent(compiled, previousInstallables));
|
|
||||||
}
|
|
||||||
return installable;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO javadoc
|
|
||||||
//FIXME
|
|
||||||
// TODO: make this non-public due to short term hack for ONOS-1051
|
|
||||||
public FlowRuleOperations coordinate(IntentData current, IntentData pending) {
|
|
||||||
List<Intent> oldInstallables = (current != null) ? current.installables() : null;
|
|
||||||
List<Intent> newInstallables = pending.installables();
|
|
||||||
|
|
||||||
checkState(isNullOrEmpty(oldInstallables) ||
|
|
||||||
oldInstallables.size() == newInstallables.size(),
|
|
||||||
"Old and New Intent must have equivalent installable intents.");
|
|
||||||
|
|
||||||
List<List<Collection<FlowRuleOperation>>> plans = new ArrayList<>();
|
|
||||||
for (int i = 0; i < newInstallables.size(); i++) {
|
|
||||||
Intent newInstallable = newInstallables.get(i);
|
|
||||||
registerSubclassInstallerIfNeeded(newInstallable);
|
|
||||||
//TODO consider migrating installers to FlowRuleOperations
|
|
||||||
/* FIXME
|
|
||||||
- we need to do another pass on this method about that doesn't
|
|
||||||
require the length of installables to be equal, and also doesn't
|
|
||||||
depend on ordering
|
|
||||||
- we should also reconsider when to start/stop tracking resources
|
|
||||||
*/
|
|
||||||
if (isNullOrEmpty(oldInstallables)) {
|
|
||||||
plans.add(getInstaller(newInstallable).install(newInstallable));
|
|
||||||
} else {
|
|
||||||
Intent oldInstallable = oldInstallables.get(i);
|
|
||||||
checkState(oldInstallable.getClass().equals(newInstallable.getClass()),
|
|
||||||
"Installable Intent type mismatch.");
|
|
||||||
trackerService.removeTrackedResources(pending.key(), oldInstallable.resources());
|
|
||||||
plans.add(getInstaller(newInstallable).replace(oldInstallable, newInstallable));
|
|
||||||
}
|
|
||||||
trackerService.addTrackedResources(pending.key(), newInstallable.resources());
|
|
||||||
// } catch (IntentException e) {
|
|
||||||
// log.warn("Unable to update intent {} due to:", oldIntent.id(), e);
|
|
||||||
// //FIXME... we failed. need to uninstall (if same) or revert (if different)
|
|
||||||
// trackerService.removeTrackedResources(newIntent.id(), newInstallable.resources());
|
|
||||||
// exception = e;
|
|
||||||
// batches = uninstallIntent(oldIntent, oldInstallables);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
return merge(plans).build(new FlowRuleOperationsContext() { // TODO move this out
|
|
||||||
@Override
|
|
||||||
public void onSuccess(FlowRuleOperations ops) {
|
|
||||||
log.debug("Completed installing: {}", pending.key());
|
|
||||||
pending.setState(INSTALLED);
|
|
||||||
store.write(pending);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(FlowRuleOperations ops) {
|
|
||||||
log.warn("Failed installation: {} {} on {}", pending.key(),
|
|
||||||
pending.intent(), ops);
|
|
||||||
//TODO store.write(pending.setState(BROKEN));
|
|
||||||
pending.setState(FAILED);
|
|
||||||
store.write(pending);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a {@link FlowRuleOperations} instance from the specified intent data.
|
|
||||||
*
|
|
||||||
* @param current intent data stored in the store
|
|
||||||
* @param pending intent data that is pending
|
|
||||||
* @return flow rule operations
|
|
||||||
*/
|
|
||||||
// TODO: make this non-public due to short term hack for ONOS-1051
|
|
||||||
public FlowRuleOperations uninstallCoordinate(IntentData current, IntentData pending) {
|
|
||||||
List<Intent> installables = current.installables();
|
|
||||||
List<List<Collection<FlowRuleOperation>>> plans = new ArrayList<>();
|
|
||||||
for (Intent installable : installables) {
|
|
||||||
plans.add(getInstaller(installable).uninstall(installable));
|
|
||||||
trackerService.removeTrackedResources(pending.key(), installable.resources());
|
|
||||||
}
|
|
||||||
|
|
||||||
return merge(plans).build(new FlowRuleOperationsContext() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(FlowRuleOperations ops) {
|
|
||||||
log.debug("Completed withdrawing: {}", pending.key());
|
|
||||||
pending.setState(WITHDRAWN);
|
|
||||||
pending.setInstallables(Collections.emptyList());
|
|
||||||
store.write(pending);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(FlowRuleOperations ops) {
|
|
||||||
log.warn("Failed withdraw: {}", pending.key());
|
|
||||||
pending.setState(FAILED);
|
|
||||||
store.write(pending);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO needs tests... or maybe it's just perfect
|
|
||||||
private FlowRuleOperations.Builder merge(List<List<Collection<FlowRuleOperation>>> 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<Set<FlowRuleOperation>)
|
|
||||||
for (Iterator<List<Collection<FlowRuleOperation>>> itr = plans.iterator(); itr.hasNext();) {
|
|
||||||
List<Collection<FlowRuleOperation>> 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
|
|
||||||
Collection<FlowRuleOperation> stage = plan.get(stageNumber);
|
|
||||||
for (FlowRuleOperation entry : stage) {
|
|
||||||
builder.operation(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers an intent compiler of the specified intent if an intent compiler
|
|
||||||
* for the intent is not registered. This method traverses the class hierarchy of
|
|
||||||
* the intent. Once an intent compiler for a parent type is found, this method
|
|
||||||
* registers the found intent compiler.
|
|
||||||
*
|
|
||||||
* @param intent intent
|
|
||||||
*/
|
|
||||||
private void registerSubclassCompilerIfNeeded(Intent intent) {
|
|
||||||
if (!compilers.containsKey(intent.getClass())) {
|
|
||||||
Class<?> cls = intent.getClass();
|
|
||||||
while (cls != Object.class) {
|
|
||||||
// As long as we're within the Intent class descendants
|
|
||||||
if (Intent.class.isAssignableFrom(cls)) {
|
|
||||||
IntentCompiler<?> compiler = compilers.get(cls);
|
|
||||||
if (compiler != null) {
|
|
||||||
compilers.put(intent.getClass(), compiler);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cls = cls.getSuperclass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers an intent installer of the specified intent if an intent installer
|
|
||||||
* for the intent is not registered. This method traverses the class hierarchy of
|
|
||||||
* the intent. Once an intent installer for a parent type is found, this method
|
|
||||||
* registers the found intent installer.
|
|
||||||
*
|
|
||||||
* @param intent intent
|
|
||||||
*/
|
|
||||||
private void registerSubclassInstallerIfNeeded(Intent intent) {
|
|
||||||
if (!installers.containsKey(intent.getClass())) {
|
|
||||||
Class<?> cls = intent.getClass();
|
|
||||||
while (cls != Object.class) {
|
|
||||||
// As long as we're within the Intent class descendants
|
|
||||||
if (Intent.class.isAssignableFrom(cls)) {
|
|
||||||
IntentInstaller<?> installer = installers.get(cls);
|
|
||||||
if (installer != null) {
|
|
||||||
installers.put(intent.getClass(), installer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cls = cls.getSuperclass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store delegate to re-post events emitted from the store.
|
// Store delegate to re-post events emitted from the store.
|
||||||
@ -525,12 +288,12 @@ public class IntentManager
|
|||||||
IntentData current = store.getIntentData(intentData.key());
|
IntentData current = store.getIntentData(intentData.key());
|
||||||
switch (intentData.state()) {
|
switch (intentData.state()) {
|
||||||
case INSTALL_REQ:
|
case INSTALL_REQ:
|
||||||
return new InstallRequest(this, intentData, Optional.ofNullable(current));
|
return new InstallRequest(processor, intentData, Optional.ofNullable(current));
|
||||||
case WITHDRAW_REQ:
|
case WITHDRAW_REQ:
|
||||||
if (current == null || isNullOrEmpty(current.installables())) {
|
if (current == null || isNullOrEmpty(current.installables())) {
|
||||||
return new Withdrawn(intentData, WITHDRAWN);
|
return new Withdrawn(intentData, WITHDRAWN);
|
||||||
} else {
|
} else {
|
||||||
return new WithdrawRequest(this, intentData, current);
|
return new WithdrawRequest(processor, intentData, current);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// illegal state
|
// illegal state
|
||||||
@ -648,4 +411,26 @@ public class IntentManager
|
|||||||
// TODO ensure that only one batch is in flight at a time
|
// TODO ensure that only one batch is in flight at a time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class InternalIntentProcessor implements IntentProcessor {
|
||||||
|
@Override
|
||||||
|
public List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
|
||||||
|
return compilerRegistry.compile(intent, previousInstallables);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FlowRuleOperations coordinate(IntentData current, IntentData pending) {
|
||||||
|
return installerRegistry.coordinate(current, pending, store, trackerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FlowRuleOperations uninstallCoordinate(IntentData current, IntentData pending) {
|
||||||
|
return installerRegistry.uninstallCoordinate(current, pending, store, trackerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyFlowRules(FlowRuleOperations flowRules) {
|
||||||
|
flowRuleService.apply(flowRules);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.Intent;
|
||||||
|
import org.onosproject.net.intent.IntentData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of methods to process an intent.
|
||||||
|
*
|
||||||
|
* This interface is public, but intended to be used only by IntentManager and
|
||||||
|
* IntentProcessPhase subclasses stored under phase package.
|
||||||
|
*/
|
||||||
|
public interface IntentProcessor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles an intent recursively.
|
||||||
|
*
|
||||||
|
* @param intent intent
|
||||||
|
* @param previousInstallables previous intent installables
|
||||||
|
* @return result of compilation
|
||||||
|
*/
|
||||||
|
List<Intent> compile(Intent intent, List<Intent> previousInstallables);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a {@link FlowRuleOperations} instance from the specified intent data.
|
||||||
|
*
|
||||||
|
* @param current intent data stored in the store
|
||||||
|
* @param pending intent data being processed
|
||||||
|
* @return flow rule operations
|
||||||
|
*/
|
||||||
|
FlowRuleOperations coordinate(IntentData current, IntentData pending);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a {@link FlowRuleOperations} instance from the specified intent data.
|
||||||
|
*
|
||||||
|
* @param current intent data stored in the store
|
||||||
|
* @param pending intent data being processed
|
||||||
|
* @return flow rule operations
|
||||||
|
*/
|
||||||
|
FlowRuleOperations uninstallCoordinate(IntentData current, IntentData pending);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a batch operation of FlowRules.
|
||||||
|
*
|
||||||
|
* @param flowRules batch operation to apply
|
||||||
|
*/
|
||||||
|
// TODO: consider a better name
|
||||||
|
// This methods gives strangeness a bit because
|
||||||
|
// it doesn't receive/return intent related information
|
||||||
|
void applyFlowRules(FlowRuleOperations flowRules);
|
||||||
|
}
|
||||||
@ -18,7 +18,7 @@ package org.onosproject.net.intent.impl.phase;
|
|||||||
import org.onosproject.net.intent.Intent;
|
import org.onosproject.net.intent.Intent;
|
||||||
import org.onosproject.net.intent.IntentData;
|
import org.onosproject.net.intent.IntentData;
|
||||||
import org.onosproject.net.intent.IntentException;
|
import org.onosproject.net.intent.IntentException;
|
||||||
import org.onosproject.net.intent.impl.IntentManager;
|
import org.onosproject.net.intent.impl.IntentProcessor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -34,13 +34,12 @@ final class Compiling implements IntentProcessPhase {
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(Compiling.class);
|
private static final Logger log = LoggerFactory.getLogger(Compiling.class);
|
||||||
|
|
||||||
// TODO: define an interface and use it, instead of IntentManager
|
private final IntentProcessor processor;
|
||||||
private final IntentManager intentManager;
|
|
||||||
private final IntentData pending;
|
private final IntentData pending;
|
||||||
private final IntentData current;
|
private final IntentData current;
|
||||||
|
|
||||||
Compiling(IntentManager intentManager, IntentData pending, IntentData current) {
|
Compiling(IntentProcessor processor, IntentData pending, IntentData current) {
|
||||||
this.intentManager = checkNotNull(intentManager);
|
this.processor = checkNotNull(processor);
|
||||||
this.pending = checkNotNull(pending);
|
this.pending = checkNotNull(pending);
|
||||||
this.current = current;
|
this.current = current;
|
||||||
}
|
}
|
||||||
@ -49,11 +48,12 @@ final class Compiling implements IntentProcessPhase {
|
|||||||
public Optional<IntentProcessPhase> execute() {
|
public Optional<IntentProcessPhase> execute() {
|
||||||
try {
|
try {
|
||||||
List<Intent> installables = (current != null) ? current.installables() : null;
|
List<Intent> installables = (current != null) ? current.installables() : null;
|
||||||
pending.setInstallables(intentManager.compileIntent(pending.intent(), installables));
|
pending.setInstallables(processor.compile(pending.intent(), installables));
|
||||||
return Optional.of(new InstallCoordinating(intentManager, pending, current));
|
return Optional.of(new InstallCoordinating(processor, pending, current));
|
||||||
} catch (IntentException e) {
|
} catch (IntentException e) {
|
||||||
log.debug("Unable to compile intent {} due to: {}", pending.intent(), e);
|
log.debug("Unable to compile intent {} due to: {}", pending.intent(), e);
|
||||||
return Optional.of(new CompilingFailed(pending));
|
return Optional.of(new CompilingFailed(pending));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ package org.onosproject.net.intent.impl.phase;
|
|||||||
import org.onosproject.net.flow.FlowRuleOperations;
|
import org.onosproject.net.flow.FlowRuleOperations;
|
||||||
import org.onosproject.net.intent.IntentData;
|
import org.onosproject.net.intent.IntentData;
|
||||||
import org.onosproject.net.intent.IntentException;
|
import org.onosproject.net.intent.IntentException;
|
||||||
import org.onosproject.net.intent.impl.IntentManager;
|
import org.onosproject.net.intent.impl.IntentProcessor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -34,13 +34,13 @@ final class InstallCoordinating implements IntentProcessPhase {
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(InstallCoordinating.class);
|
private static final Logger log = LoggerFactory.getLogger(InstallCoordinating.class);
|
||||||
|
|
||||||
private final IntentManager intentManager;
|
private final IntentProcessor processor;
|
||||||
private final IntentData pending;
|
private final IntentData pending;
|
||||||
private final IntentData current;
|
private final IntentData current;
|
||||||
|
|
||||||
// TODO: define an interface and use it, instead of IntentManager
|
// TODO: define an interface and use it, instead of IntentManager
|
||||||
InstallCoordinating(IntentManager intentManager, IntentData pending, IntentData current) {
|
InstallCoordinating(IntentProcessor processor, IntentData pending, IntentData current) {
|
||||||
this.intentManager = checkNotNull(intentManager);
|
this.processor = checkNotNull(processor);
|
||||||
this.pending = checkNotNull(pending);
|
this.pending = checkNotNull(pending);
|
||||||
this.current = current;
|
this.current = current;
|
||||||
}
|
}
|
||||||
@ -50,8 +50,8 @@ final class InstallCoordinating implements IntentProcessPhase {
|
|||||||
try {
|
try {
|
||||||
//FIXME we orphan flow rules that are currently on the data plane
|
//FIXME we orphan flow rules that are currently on the data plane
|
||||||
// ... should either reuse them or remove them
|
// ... should either reuse them or remove them
|
||||||
FlowRuleOperations flowRules = intentManager.coordinate(current, pending);
|
FlowRuleOperations flowRules = processor.coordinate(current, pending);
|
||||||
return Optional.of(new Installing(intentManager, pending, flowRules));
|
return Optional.of(new Installing(processor, pending, flowRules));
|
||||||
} catch (IntentException e) {
|
} catch (IntentException e) {
|
||||||
log.warn("Unable to generate a FlowRuleOperations from intent {} due to:", pending.intent().id(), e);
|
log.warn("Unable to generate a FlowRuleOperations from intent {} due to:", pending.intent().id(), e);
|
||||||
return Optional.of(new InstallingFailed(pending));
|
return Optional.of(new InstallingFailed(pending));
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
package org.onosproject.net.intent.impl.phase;
|
package org.onosproject.net.intent.impl.phase;
|
||||||
|
|
||||||
import org.onosproject.net.intent.IntentData;
|
import org.onosproject.net.intent.IntentData;
|
||||||
import org.onosproject.net.intent.impl.IntentManager;
|
import org.onosproject.net.intent.impl.IntentProcessor;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -27,13 +27,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
*/
|
*/
|
||||||
public final class InstallRequest implements IntentProcessPhase {
|
public final class InstallRequest implements IntentProcessPhase {
|
||||||
|
|
||||||
// TODO: define an interface and use it, instead of IntentManager
|
private final IntentProcessor intentManager;
|
||||||
private final IntentManager intentManager;
|
|
||||||
private final IntentData pending;
|
private final IntentData pending;
|
||||||
private final Optional<IntentData> current;
|
private final Optional<IntentData> current;
|
||||||
|
|
||||||
public InstallRequest(IntentManager intentManager, IntentData intentData, Optional<IntentData> current) {
|
public InstallRequest(IntentProcessor processor, IntentData intentData, Optional<IntentData> current) {
|
||||||
this.intentManager = checkNotNull(intentManager);
|
this.intentManager = checkNotNull(processor);
|
||||||
this.pending = checkNotNull(intentData);
|
this.pending = checkNotNull(intentData);
|
||||||
this.current = checkNotNull(current);
|
this.current = checkNotNull(current);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ package org.onosproject.net.intent.impl.phase;
|
|||||||
import org.onosproject.net.flow.FlowRuleOperations;
|
import org.onosproject.net.flow.FlowRuleOperations;
|
||||||
import org.onosproject.net.intent.IntentData;
|
import org.onosproject.net.intent.IntentData;
|
||||||
import org.onosproject.net.intent.IntentException;
|
import org.onosproject.net.intent.IntentException;
|
||||||
import org.onosproject.net.intent.impl.IntentManager;
|
import org.onosproject.net.intent.impl.IntentProcessor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -34,13 +34,12 @@ final class Installing implements IntentProcessPhase {
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(Installing.class);
|
private static final Logger log = LoggerFactory.getLogger(Installing.class);
|
||||||
|
|
||||||
private final IntentManager intentManager;
|
private final IntentProcessor processor;
|
||||||
private final IntentData pending;
|
private final IntentData pending;
|
||||||
private final FlowRuleOperations flowRules;
|
private final FlowRuleOperations flowRules;
|
||||||
|
|
||||||
// TODO: define an interface and use it, instead of IntentManager
|
Installing(IntentProcessor processor, IntentData pending, FlowRuleOperations flowRules) {
|
||||||
Installing(IntentManager intentManager, IntentData pending, FlowRuleOperations flowRules) {
|
this.processor = checkNotNull(processor);
|
||||||
this.intentManager = checkNotNull(intentManager);
|
|
||||||
this.pending = checkNotNull(pending);
|
this.pending = checkNotNull(pending);
|
||||||
this.flowRules = flowRules;
|
this.flowRules = flowRules;
|
||||||
}
|
}
|
||||||
@ -48,7 +47,7 @@ final class Installing implements IntentProcessPhase {
|
|||||||
@Override
|
@Override
|
||||||
public Optional<IntentProcessPhase> execute() {
|
public Optional<IntentProcessPhase> execute() {
|
||||||
try {
|
try {
|
||||||
intentManager.flowRuleService.apply(flowRules); // FIXME we need to provide a context
|
processor.applyFlowRules(flowRules);
|
||||||
return Optional.of(new Installed(pending));
|
return Optional.of(new Installed(pending));
|
||||||
// What kinds of exceptions are thrown by FlowRuleService.apply()?
|
// What kinds of exceptions are thrown by FlowRuleService.apply()?
|
||||||
// Is IntentException a correct exception abstraction?
|
// Is IntentException a correct exception abstraction?
|
||||||
|
|||||||
@ -18,7 +18,7 @@ package org.onosproject.net.intent.impl.phase;
|
|||||||
import org.onosproject.net.flow.FlowRuleOperations;
|
import org.onosproject.net.flow.FlowRuleOperations;
|
||||||
import org.onosproject.net.intent.IntentData;
|
import org.onosproject.net.intent.IntentData;
|
||||||
import org.onosproject.net.intent.IntentException;
|
import org.onosproject.net.intent.IntentException;
|
||||||
import org.onosproject.net.intent.impl.IntentManager;
|
import org.onosproject.net.intent.impl.IntentProcessor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -34,13 +34,12 @@ final class WithdrawCoordinating implements IntentProcessPhase {
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(WithdrawCoordinating.class);
|
private static final Logger log = LoggerFactory.getLogger(WithdrawCoordinating.class);
|
||||||
|
|
||||||
// TODO: define an interface and use it, instead of IntentManager
|
private final IntentProcessor processor;
|
||||||
private final IntentManager intentManager;
|
|
||||||
private final IntentData pending;
|
private final IntentData pending;
|
||||||
private final IntentData current;
|
private final IntentData current;
|
||||||
|
|
||||||
WithdrawCoordinating(IntentManager intentManager, IntentData pending, IntentData current) {
|
WithdrawCoordinating(IntentProcessor processor, IntentData pending, IntentData current) {
|
||||||
this.intentManager = checkNotNull(intentManager);
|
this.processor = checkNotNull(processor);
|
||||||
this.pending = checkNotNull(pending);
|
this.pending = checkNotNull(pending);
|
||||||
this.current = checkNotNull(current);
|
this.current = checkNotNull(current);
|
||||||
}
|
}
|
||||||
@ -49,9 +48,9 @@ final class WithdrawCoordinating implements IntentProcessPhase {
|
|||||||
public Optional<IntentProcessPhase> execute() {
|
public Optional<IntentProcessPhase> execute() {
|
||||||
try {
|
try {
|
||||||
// Note: current.installables() are not null or empty due to createIntentUpdate check
|
// Note: current.installables() are not null or empty due to createIntentUpdate check
|
||||||
FlowRuleOperations flowRules = intentManager.uninstallCoordinate(current, pending);
|
FlowRuleOperations flowRules = processor.uninstallCoordinate(current, pending);
|
||||||
pending.setInstallables(current.installables());
|
pending.setInstallables(current.installables());
|
||||||
return Optional.of(new Withdrawing(intentManager, pending, flowRules));
|
return Optional.of(new Withdrawing(processor, pending, flowRules));
|
||||||
} catch (IntentException e) {
|
} catch (IntentException e) {
|
||||||
log.warn("Unable to generate generate a FlowRuleOperations from intent {} due to:", pending.intent(), e);
|
log.warn("Unable to generate generate a FlowRuleOperations from intent {} due to:", pending.intent(), e);
|
||||||
return Optional.of(new WithdrawingFailed(pending));
|
return Optional.of(new WithdrawingFailed(pending));
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
package org.onosproject.net.intent.impl.phase;
|
package org.onosproject.net.intent.impl.phase;
|
||||||
|
|
||||||
import org.onosproject.net.intent.IntentData;
|
import org.onosproject.net.intent.IntentData;
|
||||||
import org.onosproject.net.intent.impl.IntentManager;
|
import org.onosproject.net.intent.impl.IntentProcessor;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -27,13 +27,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
*/
|
*/
|
||||||
public final class WithdrawRequest implements IntentProcessPhase {
|
public final class WithdrawRequest implements IntentProcessPhase {
|
||||||
|
|
||||||
// TODO: define an interface and use it, instead of IntentManager
|
private final IntentProcessor processor;
|
||||||
private final IntentManager intentManager;
|
|
||||||
private final IntentData pending;
|
private final IntentData pending;
|
||||||
private final IntentData current;
|
private final IntentData current;
|
||||||
|
|
||||||
public WithdrawRequest(IntentManager intentManager, IntentData intentData, IntentData current) {
|
public WithdrawRequest(IntentProcessor processor, IntentData intentData, IntentData current) {
|
||||||
this.intentManager = checkNotNull(intentManager);
|
this.processor = checkNotNull(processor);
|
||||||
this.pending = checkNotNull(intentData);
|
this.pending = checkNotNull(intentData);
|
||||||
this.current = checkNotNull(current);
|
this.current = checkNotNull(current);
|
||||||
}
|
}
|
||||||
@ -43,6 +42,6 @@ public final class WithdrawRequest implements IntentProcessPhase {
|
|||||||
//TODO perhaps we want to validate that the pending and current are the
|
//TODO perhaps we want to validate that the pending and current are the
|
||||||
// same version i.e. they are the same
|
// same version i.e. they are the same
|
||||||
// Note: this call is not just the symmetric version of submit
|
// Note: this call is not just the symmetric version of submit
|
||||||
return Optional.of(new WithdrawCoordinating(intentManager, pending, current));
|
return Optional.of(new WithdrawCoordinating(processor, pending, current));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ package org.onosproject.net.intent.impl.phase;
|
|||||||
|
|
||||||
import org.onosproject.net.flow.FlowRuleOperations;
|
import org.onosproject.net.flow.FlowRuleOperations;
|
||||||
import org.onosproject.net.intent.IntentData;
|
import org.onosproject.net.intent.IntentData;
|
||||||
import org.onosproject.net.intent.impl.IntentManager;
|
import org.onosproject.net.intent.impl.IntentProcessor;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -29,20 +29,19 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
*/
|
*/
|
||||||
class Withdrawing implements IntentProcessPhase {
|
class Withdrawing implements IntentProcessPhase {
|
||||||
|
|
||||||
// TODO: define an interface and use it, instead of IntentManager
|
private final IntentProcessor processor;
|
||||||
private final IntentManager intentManager;
|
|
||||||
private final IntentData pending;
|
private final IntentData pending;
|
||||||
private final FlowRuleOperations flowRules;
|
private final FlowRuleOperations flowRules;
|
||||||
|
|
||||||
Withdrawing(IntentManager intentManager, IntentData pending, FlowRuleOperations flowRules) {
|
Withdrawing(IntentProcessor processor, IntentData pending, FlowRuleOperations flowRules) {
|
||||||
this.intentManager = checkNotNull(intentManager);
|
this.processor = checkNotNull(processor);
|
||||||
this.pending = checkNotNull(pending);
|
this.pending = checkNotNull(pending);
|
||||||
this.flowRules = checkNotNull(flowRules);
|
this.flowRules = checkNotNull(flowRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<IntentProcessPhase> execute() {
|
public Optional<IntentProcessPhase> execute() {
|
||||||
intentManager.flowRuleService.apply(flowRules);
|
processor.applyFlowRules(flowRules);
|
||||||
return Optional.of(new Withdrawn(pending));
|
return Optional.of(new Withdrawn(pending));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user