<dependency>
<groupId>org.opendaylight.mdsal.model</groupId>
<artifactId>ietf-inet-types-2013-07-15</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl;
import com.google.common.base.Preconditions;
-import java.util.List;
-
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.NodeManager;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerZipImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NetconfTransactionCreator;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.sf.ChainAction;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.sf.Classifier;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.sf.EtherTypeClassifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
+import java.util.List;
+import java.util.Optional;
+
/**
* Purpose: bootstrap provider implementation of Ios-xe renderer
*/
LOG.info("starting ios-xe renderer");
//TODO register listeners:
// node-manager
- NodeManager nodeManager = new NodeManager(dataBroker, providerContext);
+ final NodeManager nodeManager = new NodeManager(dataBroker, providerContext);
// network-topology
iosXeCapableNodeListener = new IosXeCapableNodeListenerImpl(dataBroker, nodeManager);
// policy-manager and delegates
- PolicyManager policyManager = new PolicyManagerImpl(dataBroker, nodeManager);
+ final PolicyManager policyManager = new PolicyManagerImpl(dataBroker, nodeManager);
final PolicyManager policyManagerZip = new PolicyManagerZipImpl(policyManager);
// renderer-configuration endpoints
}
private void writeRendererCapabilities() {
- WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
-
- ChainAction action = new ChainAction();
- List<SupportedActionDefinition> actionDefinitions =
+ final Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(dataBroker);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", dataBroker);
+ return;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final ChainAction action = new ChainAction();
+ final List<SupportedActionDefinition> actionDefinitions =
ImmutableList.of(new SupportedActionDefinitionBuilder().setActionDefinitionId(action.getId())
- .setSupportedParameterValues(action.getSupportedParameterValues())
- .build());
-
- Classifier etherClassifier = new EtherTypeClassifier(null);
- Classifier ipProtoClassifier = new IpProtoClassifier(etherClassifier.getId());
- List<SupportedClassifierDefinition> classifierDefinitions = ImmutableList
- .of(new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(etherClassifier.getId())
- .setParentClassifierDefinitionId(etherClassifier.getParent())
- .setSupportedParameterValues(etherClassifier.getSupportedParameterValues())
- .build(),
- new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(ipProtoClassifier.getId())
- .setParentClassifierDefinitionId(ipProtoClassifier.getParent())
- .setSupportedParameterValues(ipProtoClassifier.getSupportedParameterValues())
- .build());
-
- Renderer renderer = new RendererBuilder().setName(NodeManager.iosXeRenderer)
- .setCapabilities(new CapabilitiesBuilder().setSupportedActionDefinition(actionDefinitions)
- .setSupportedClassifierDefinition(classifierDefinitions)
- .build())
- .build();
-
- InstanceIdentifier<Renderer> iid = InstanceIdentifier.builder(Renderers.class)
- .child(Renderer.class, new RendererKey(new RendererName(NodeManager.iosXeRenderer)))
- .build();
+ .setSupportedParameterValues(action.getSupportedParameterValues())
+ .build());
+
+ final Classifier etherClassifier = new EtherTypeClassifier(null);
+ final Classifier ipProtoClassifier = new IpProtoClassifier(etherClassifier.getId());
+ final List<SupportedClassifierDefinition> classifierDefinitions = ImmutableList
+ .of(new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(etherClassifier.getId())
+ .setParentClassifierDefinitionId(etherClassifier.getParent())
+ .setSupportedParameterValues(etherClassifier.getSupportedParameterValues())
+ .build(),
+ new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(ipProtoClassifier.getId())
+ .setParentClassifierDefinitionId(ipProtoClassifier.getParent())
+ .setSupportedParameterValues(ipProtoClassifier.getSupportedParameterValues())
+ .build());
+
+ final Renderer renderer = new RendererBuilder().setName(NodeManager.iosXeRenderer)
+ .setCapabilities(new CapabilitiesBuilder().setSupportedActionDefinition(actionDefinitions)
+ .setSupportedClassifierDefinition(classifierDefinitions)
+ .build())
+ .build();
+
+ final InstanceIdentifier<Renderer> iid = InstanceIdentifier.builder(Renderers.class)
+ .child(Renderer.class, new RendererKey(new RendererName(NodeManager.iosXeRenderer)))
+ .build();
writeTransaction.merge(LogicalDatastoreType.OPERATIONAL, iid, renderer, true);
- CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
+ final CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
Futures.addCallback(future, new FutureCallback<Void>() {
@Override
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.MountPoint;
import org.opendaylight.controller.md.sal.binding.api.MountPointService;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NetconfTransactionCreator;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NodeWriter;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
InstanceIdentifier<Node> nodeIid = InstanceIdentifier.builder(NetworkTopology.class)
.child(Topology.class, new TopologyKey(new TopologyId(NodeManager.TOPOLOGY_ID)))
.child(Node.class, new NodeKey(nodeId)).build();
- ReadWriteTransaction rwt = dataBroker.newReadWriteTransaction();
+ java.util.Optional<ReadOnlyTransaction> optionalTransaction =
+ NetconfTransactionCreator.netconfReadOnlyTransaction(dataBroker);
+ if (!optionalTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", dataBroker);
+ return null;
+ }
+ ReadOnlyTransaction transaction = optionalTransaction.get();
try {
CheckedFuture<Optional<Node>, ReadFailedException> submitFuture =
- rwt.read(LogicalDatastoreType.CONFIGURATION, nodeIid);
+ transaction.read(LogicalDatastoreType.CONFIGURATION, nodeIid);
Optional<Node> optional = submitFuture.checkedGet();
if (optional != null && optional.isPresent()) {
Node node = optional.get();
package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
-import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Create;
-import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Delete;
-
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NetconfTransactionCreator;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Create;
+import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Delete;
+
public class PolicyManagerImpl implements PolicyManager {
private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerImpl.class);
} else if (dataBefore != null && dataAfter == null) {
result = syncPolicy(dataBefore, Delete);
} else {
- // TODO implement
+ syncPolicy(dataBefore, Delete);
+ syncPolicy(dataAfter, Create);
result = Futures.immediateFuture(false);
}
//TODO: dump all resolvedRule-rule-peerEP-EP combinantions to status
continue;
}
-
final List<AddressEndpointWithLocation> endpointsWithLocation = dataAfter.getEndpoints()
.getAddressEndpointWithLocation();
final InstanceIdentifier mountpointIid = PolicyManagerUtil.getAbsoluteLocationMountpoint(rendererEndpoint, endpointsWithLocation);
//TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
continue;
}
- PolicyManagerUtil.syncPolicyEntities(sourceSgt, destinationSgt, policyWriter, dataAfter, peerEndpoint);
+ PolicyManagerUtil.syncPolicyEntities(sourceSgt, destinationSgt, policyWriter, dataAfter, peerEndpoint,
+ dataBroker, action);
}
}
//TODO: return real (cumulated) future
- final List<CheckedFuture<Void, TransactionCommitFailedException>> allFutureResults = new ArrayList<>();
+ final List<CheckedFuture<Boolean, TransactionCommitFailedException>> allFutureResults = new ArrayList<>();
if (action.equals(Create)) {
policyWriterPerDeviceCache.values().forEach(pw -> allFutureResults.add(pw.commitToDatastore()));
} else if (action.equals(Delete)) {
policyWriterPerDeviceCache.values().forEach(pw -> allFutureResults.add(pw.removeFromDatastore()));
} else {
LOG.info("unsupported policy manage action: {}", action);
-
}
+ final ListenableFuture<List<Boolean>> cumulativeResult = Futures.allAsList(allFutureResults);
- final ListenableFuture<List<Void>> cumulativeResult = Futures.allAsList(allFutureResults);
-
- return Futures.transform(cumulativeResult, new Function<List<Void>, Boolean>() {
+ return Futures.transform(cumulativeResult, new Function<List<Boolean>, Boolean>() {
@Nullable
@Override
- public Boolean apply(@Nullable final List<Void> input) {
+ public Boolean apply(@Nullable final List<Boolean> input) {
LOG.trace("considering all submits as successful - otherwise there will be exception");
return Boolean.TRUE;
}
}
private CheckedFuture<Void, TransactionCommitFailedException> reportVersion(long version) {
- WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
- InstanceIdentifier<RendererPolicy> iid = InstanceIdentifier.create(Renderers.class)
+ final Optional<ReadWriteTransaction> optionalReadWriteTransaction =
+ NetconfTransactionCreator.netconfReadWriteTransaction(dataBroker);
+ if (!optionalReadWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", dataBroker);
+ return Futures.immediateCheckedFuture(null);
+ }
+ final ReadWriteTransaction readWriteTransaction = optionalReadWriteTransaction.get();
+ final InstanceIdentifier<RendererPolicy> iid = InstanceIdentifier.create(Renderers.class)
.child(Renderer.class, new RendererKey(NodeManager.iosXeRenderer))
.child(RendererPolicy.class);
- wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, new RendererPolicyBuilder().setVersion(version).build());
- return wtx.submit();
+ readWriteTransaction.merge(LogicalDatastoreType.OPERATIONAL, iid,
+ new RendererPolicyBuilder().setVersion(version).build());
+ return readWriteTransaction.submit();
}
@Override
//NOOP
}
- enum DsAction {Create, Delete}
+ public enum DsAction {Create, Delete}
public enum ActionCase {ALLOW, CHAIN}
}
package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
-import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
-import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction.In;
-import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction.Out;
-import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation.CONSUMER;
-import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation.PROVIDER;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionList;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.AppnavPolicyBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.ForwardCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.ForwardBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePath;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.AddressEndpointWithLocationAug;
import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
+import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Create;
+import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Delete;
+
public class PolicyManagerUtil {
private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerUtil.class);
+ private static final String DEFAULT = "class-default";
public static void syncPolicyEntities(final Sgt sourceSgt, final Sgt destinationSgt, PolicyWriter policyWriter,
- final Configuration dataAfter, final PeerEndpointWithPolicy peerEndpoint) {
- // Class map
- final String classMapName = PolicyManagerUtil.generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
- final Match match = PolicyManagerUtil.createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
- final ClassMap classMap = PolicyManagerUtil.createClassMap(classMapName, match);
+ final Configuration dataAfter, final PeerEndpointWithPolicy peerEndpoint,
+ final DataBroker dataBroker, final PolicyManagerImpl.DsAction action) {
+ // Action
final Map<PolicyManagerImpl.ActionCase, Action> actionMap = PolicyManagerUtil.getActionInDirection(dataAfter, peerEndpoint);
if (actionMap == null || actionMap.isEmpty()) {
LOG.debug("no usable action found for EP-sgt[{}] | peerEP-sgt[{}]",
sourceSgt, destinationSgt);
return;
}
- policyWriter.cache(classMap);
- // Policy map entry
- if (actionMap.containsKey(PolicyManagerImpl.ActionCase.CHAIN)) {
- ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+ // TODO allow action not supported
+
+ // Resolve chain action - create
+ if (actionMap.containsKey(PolicyManagerImpl.ActionCase.CHAIN) && action.equals(Create)) {
+ ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, policyWriter,
+ dataBroker);
+ }
+ if (actionMap.containsKey(PolicyManagerImpl.ActionCase.CHAIN) && action.equals(Delete)) {
+ ServiceChainingUtil.removeChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, policyWriter);
}
}
return augmentation.getSgt();
}
- private static Match createSecurityGroupMatch(final int sourceTag, final int destinationTag) {
+ static Match createSecurityGroupMatch(final int sourceTag, final int destinationTag) {
final SecurityGroupBuilder sgBuilder = new SecurityGroupBuilder();
final Source source = new SourceBuilder().setTag(sourceTag).build();
final Destination destination = new DestinationBuilder().setTag(destinationTag).build();
public static PolicyMap createPolicyMap(final String policyMapName, final List<Class> policyMapEntries) {
// Create default class entry
- final AppnavPolicyBuilder appnavPolicyBuilder = new AppnavPolicyBuilder();
- appnavPolicyBuilder.setPassThrough(true);
final ClassBuilder defaultBuilder = new ClassBuilder();
- defaultBuilder.setName(new ClassNameType("class-default"))
- .setKey(new ClassKey(new ClassNameType("class-default")))
- .setAppnavPolicy(appnavPolicyBuilder.build());
+ defaultBuilder.setName(new ClassNameType(DEFAULT))
+ .setKey(new ClassKey(new ClassNameType(DEFAULT)));
+ // TODO add pass-through value
policyMapEntries.add(defaultBuilder.build());
// Construct policy map
final PolicyMapBuilder policyMapBuilder = new PolicyMapBuilder();
private static Map<PolicyManagerImpl.ActionCase, Action> getActionInDirection(final Configuration data, final PeerEndpointWithPolicy peer) {
- final List<ResolvedRule> rulesInDirection = new ArrayList<>();
+ final Set<ResolvedRule> rulesInDirection = new HashSet<>();
// Find all rules in desired direction
for (RuleGroupWithRendererEndpointParticipation ruleGroupKey :
peer.getRuleGroupWithRendererEndpointParticipation()) {
- final EndpointPolicyParticipation participation = ruleGroupKey.getRendererEndpointParticipation();
final RuleGroup ruleGroup = findRuleGroup(data, ruleGroupKey);
if (ruleGroup == null || ruleGroup.getResolvedRule() == null) {
continue;
if (resolvedRule.getClassifier() == null || resolvedRule.getAction() == null) {
continue;
}
- // TODO only first Classifier used
- final Classifier classifier = resolvedRule.getClassifier().get(0);
- final HasDirection.Direction direction = classifier.getDirection();
- if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
- (participation.equals(CONSUMER) && direction.equals(In))) {
- rulesInDirection.add(resolvedRule);
- }
+ rulesInDirection.add(resolvedRule);
}
}
if (rulesInDirection.isEmpty()) {
}
return null;
}
-
}
package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.CheckedFuture;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NetconfTransactionCreator;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.rsp.manager.rev160421.RendererPathStates;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.rsp.manager.rev160421.renderer.path.states.RendererPathState;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.rsp.manager.rev160421.renderer.path.states.RendererPathStateKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.rsp.manager.rev160421.renderer.path.states.renderer.path.state.ConfiguredRenderedPaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.rsp.manager.rev160421.renderer.path.states.renderer.path.state.configured.rendered.paths.ConfiguredRenderedPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.rsp.manager.rev160421.renderer.path.states.renderer.path.state.configured.rendered.paths.ConfiguredRenderedPathKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RendererName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChainBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.config.service.chain.grouping.IpBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.security.cert.PKIXRevocationChecker;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
public class ServiceChainingUtil {
private static final Logger LOG = LoggerFactory.getLogger(ServiceChainingUtil.class);
+ private static final String RSP_SUFFIX = "-gbp-rsp";
+ private static final String RSP_REVERSED_SUFFIX = "-gbp-rsp-Reverse";
static ServiceFunctionPath getServicePath(final List<ParameterValue> params) {
if (params == null || params.isEmpty()) {
return serviceFunctionPath;
}
- static void resolveChainAction(final PeerEndpointWithPolicy peerEndpoint, final Sgt sourceSgt,
- final Sgt destinationSgt, final Map<PolicyManagerImpl.ActionCase, Action> actionMap,
- final String classMapName, PolicyWriter policyWriter) {
- final List<Class> entries = new ArrayList<>();
+ static void resolveNewChainAction(final PeerEndpointWithPolicy peerEndpoint, final Sgt sourceSgt,
+ final Sgt destinationSgt, final Map<PolicyManagerImpl.ActionCase, Action> actionMap,
+ PolicyWriter policyWriter, final DataBroker dataBroker) {
+ final List<Class> policyMapEntries = new ArrayList<>();
final Action action = actionMap.get(PolicyManagerImpl.ActionCase.CHAIN);
final ServiceFunctionPath servicePath = ServiceChainingUtil.getServicePath(action.getParameterValue());
- if (servicePath == null) {
+ if (servicePath == null || servicePath.getName() == null) {
//TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
return;
}
//TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
return;
}
- final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(servicePath, tenantId);
+ final RenderedServicePath directPath = ServiceChainingUtil.createRenderedPath(servicePath, tenantId, dataBroker);
+ // Rsp found, create class-map and policy-map entry
+ final String classMapName = PolicyManagerUtil.generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
+ final Match match = PolicyManagerUtil.createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
+ final ClassMap classMap = PolicyManagerUtil.createClassMap(classMapName, match);
+ policyMapEntries.add(PolicyManagerUtil.createPolicyEntry(classMapName, directPath, PolicyManagerImpl.ActionCase.CHAIN));
+ RenderedServicePath reversedPath = null;
+ if (servicePath.isSymmetric()) {
+ // symmetric path is in opposite direction. Roles of renderer and peer endpoint will invert
+ reversedPath = ServiceChainingUtil.createSymmetricRenderedPath(servicePath, directPath, tenantId, dataBroker);
+ // Reversed Rsp found, create class-map and policy-map entry in opposite direction
+ final String oppositeClassMapName = PolicyManagerUtil.generateClassMapName(destinationSgt.getValue(), sourceSgt.getValue());
+ final Match oppositeMatch = PolicyManagerUtil.createSecurityGroupMatch(destinationSgt.getValue(), sourceSgt.getValue());
+ final ClassMap oppositeClassMap = PolicyManagerUtil.createClassMap(oppositeClassMapName, oppositeMatch);
+ policyMapEntries.add(PolicyManagerUtil.createPolicyEntry(oppositeClassMapName, reversedPath, PolicyManagerImpl.ActionCase.CHAIN));
+ policyWriter.cache(oppositeClassMap);
+ }
// Create appropriate service path && remote forwarder
- final boolean sfcPartSucessful = setSfcPart(renderedPath, policyWriter);
- if (!sfcPartSucessful) {
+ final boolean sfcPartSuccessful = setSfcPart(servicePath, directPath, reversedPath, policyWriter);
+ if (!sfcPartSuccessful) {
//TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
return;
}
+ policyWriter.cache(classMap);
+ policyWriter.cache(policyMapEntries);
+ }
- // atomic creation of symmetric policy-entries
- final Class policyEntry = PolicyManagerUtil.createPolicyEntry(classMapName, renderedPath, PolicyManagerImpl.ActionCase.CHAIN);
- if (!servicePath.isSymmetric()) {
- entries.add(policyEntry);
- } else {
- // symmetric path is in opposite direction. Roles of renderer and peer endpoint will invert
- final RenderedServicePath symmetricPath = ServiceChainingUtil
- .createSymmetricRenderedPath(servicePath, renderedPath, tenantId);
- if (symmetricPath == null) {
- //TODO: dump particular resolvedRule-rule-peerEP-EP combinantions to status
- return;
- } else {
- final String oppositeClassMapName = PolicyManagerUtil.generateClassMapName(destinationSgt.getValue(),
- sourceSgt.getValue());
- final Class policyEntrySymmetric = PolicyManagerUtil.createPolicyEntry(oppositeClassMapName,
- symmetricPath, PolicyManagerImpl.ActionCase.CHAIN);
+ static void removeChainAction(final PeerEndpointWithPolicy peerEndpoint, final Sgt sourceSgt, final Sgt destinationSgt,
+ final Map<PolicyManagerImpl.ActionCase, Action> actionMap, PolicyWriter policyWriter) {
+ final Action action = actionMap.get(PolicyManagerImpl.ActionCase.CHAIN);
+ final ServiceFunctionPath servicePath = ServiceChainingUtil.getServicePath(action.getParameterValue());
+ if (servicePath == null || servicePath.getName() == null) {
+ return;
+ }
+ final TenantId tenantId = PolicyManagerUtil.getTenantId(peerEndpoint);
+ if (tenantId == null) {
+ return;
+ }
+ // Cache class-maps, appropriate policy-map entries and service-chains
+ final List<Class> policyMapEntries = new ArrayList<>();
+ final String classMapName = PolicyManagerUtil.generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
+ final ClassMap classMap = PolicyManagerUtil.createClassMap(classMapName, null);
+ final RspName rspName = generateRspName(servicePath, tenantId);
+ final ServiceChain serviceChain = findServiceChainToRsp(rspName);
+ policyMapEntries.add(PolicyManagerUtil.createPolicyEntry(classMapName, null, PolicyManagerImpl.ActionCase.CHAIN));
+ policyWriter.cache(classMap);
+ policyWriter.cache(serviceChain);
+ if (servicePath.isSymmetric()) {
+ final String oppositeClassMapName = PolicyManagerUtil.generateClassMapName(destinationSgt.getValue(), sourceSgt.getValue());
+ final ClassMap oppositeClassMap = PolicyManagerUtil.createClassMap(oppositeClassMapName, null);
+ final RspName reversedRspName = generateReversedRspName(servicePath, tenantId);
+ final ServiceChain reversedServiceChain = findServiceChainToRsp(reversedRspName);
+ policyMapEntries.add(PolicyManagerUtil.createPolicyEntry(oppositeClassMapName, null, PolicyManagerImpl.ActionCase.CHAIN));
+ policyWriter.cache(oppositeClassMap);
+ policyWriter.cache(reversedServiceChain);
+ }
+ policyWriter.cache(policyMapEntries);
+ // TODO remove other sfc stuff - forwarders, etc.
+ }
- entries.add(policyEntry);
- entries.add(policyEntrySymmetric);
- }
+ private static ServiceChain findServiceChainToRsp(final RspName rspName) {
+ // Do not actually remove rsp from DS, could be used by someone else
+ final RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+ if (renderedServicePath == null) {
+ LOG.debug("Rendered service path not found, if there is service-path created according to that rsp, " +
+ "it cannot be removed. Rendered path name: {} ", rspName.getValue());
+ return null;
}
- policyWriter.cache(entries);
+ // Construct service chain with key
+ final Long pathId = renderedServicePath.getPathId();
+ final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
+ final ServiceChainBuilder serviceChainBuilder = new ServiceChainBuilder();
+ servicePathBuilder.setServicePathId(pathId)
+ .setKey(new ServicePathKey(pathId));
+ serviceChainBuilder.setServicePath(Collections.singletonList(servicePathBuilder.build()));
+ return serviceChainBuilder.build();
}
- static RenderedServicePath createRenderedPath(final ServiceFunctionPath sfp, final TenantId tenantId) {
+ static RenderedServicePath createRenderedPath(final ServiceFunctionPath sfp, final TenantId tenantId,
+ final DataBroker dataBroker) {
RenderedServicePath renderedServicePath;
// Try to read existing RSP
- final RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp");
+ final RspName rspName = generateRspName(sfp, tenantId);
renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
if (renderedServicePath != null) {
return renderedServicePath;
.build();
renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, input);
LOG.info("Rendered service path {} created", rspName.getValue());
+ checkSfcRspStatus(rspName, dataBroker);
return renderedServicePath;
}
static RenderedServicePath createSymmetricRenderedPath(final ServiceFunctionPath sfp, final RenderedServicePath rsp,
- final TenantId tenantId) {
+ final TenantId tenantId, final DataBroker dataBroker) {
RenderedServicePath reversedRenderedPath;
// Try to read existing RSP
- final RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp-Reverse");
+ final RspName rspName = generateReversedRspName(sfp, tenantId);
reversedRenderedPath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
if (reversedRenderedPath != null) {
return reversedRenderedPath;
}
LOG.info("Reversed rendered service path with name {} not found, creating a new one ..", rspName.getValue());
- reversedRenderedPath = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
+ reversedRenderedPath = SfcProviderRenderedPathAPI.createReverseRenderedServicePathEntry(rsp);
LOG.info("Rendered service path {} created", rspName.getValue());
+ checkSfcRspStatus(rspName, dataBroker);
return reversedRenderedPath;
}
* @param mountpoint used to access specific device
* @return true if Local Forwarder is present, false otherwise
*/
- static boolean checkLocalForwarderPresence(DataBroker mountpoint) {
+ private static boolean checkLocalForwarderPresence(DataBroker mountpoint) {
InstanceIdentifier<Local> localSffIid = InstanceIdentifier.builder(Native.class)
.child(ServiceChain.class)
.child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
.child(Local.class).build();
- ReadWriteTransaction rwt = mountpoint.newReadWriteTransaction();
- CheckedFuture<Optional<Local>, ReadFailedException> submitFuture = rwt.read(LogicalDatastoreType.CONFIGURATION,
- localSffIid);
try {
+ java.util.Optional<ReadOnlyTransaction> optionalTransaction =
+ NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
+ if (!optionalTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ ReadOnlyTransaction transaction = optionalTransaction.get();
+ CheckedFuture<Optional<Local>, ReadFailedException> submitFuture =
+ transaction.read(LogicalDatastoreType.CONFIGURATION,
+ localSffIid);
Optional<Local> optionalLocalSff = submitFuture.checkedGet();
+ transaction.close(); // Release lock
return optionalLocalSff.isPresent();
} catch (ReadFailedException e) {
LOG.warn("Read transaction failed to {} ", e);
public static boolean checkServicePathPresence(DataBroker mountpoint) {
InstanceIdentifier<ServiceChain> serviceChainIid = InstanceIdentifier.builder(Native.class)
.child(ServiceChain.class).build();
- ReadWriteTransaction rwt = mountpoint.newReadWriteTransaction();
- CheckedFuture<Optional<ServiceChain>, ReadFailedException> submitFuture = rwt.read(LogicalDatastoreType.CONFIGURATION,
+ java.util.Optional<ReadOnlyTransaction> optionalTransaction =
+ NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
+ if (!optionalTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ ReadOnlyTransaction transaction = optionalTransaction.get();
+ CheckedFuture<Optional<ServiceChain>, ReadFailedException> submitFuture = transaction.read(LogicalDatastoreType.CONFIGURATION,
serviceChainIid);
try {
Optional<ServiceChain> optionalServiceChain = submitFuture.checkedGet();
return null;
}
+ private static RspName generateRspName(final ServiceFunctionPath serviceFunctionPath, final TenantId tenantId) {
+ return new RspName(serviceFunctionPath.getName().getValue() + tenantId.getValue() + RSP_SUFFIX);
+ }
+
+ private static RspName generateReversedRspName(final ServiceFunctionPath serviceFunctionPath, final TenantId tenantId) {
+ return new RspName(serviceFunctionPath.getName().getValue() + tenantId.getValue() + RSP_REVERSED_SUFFIX);
+ }
+
private static <T> Supplier<Boolean> createNegativePathWithLogSupplier(final T value, final Consumer<T> logCommand) {
return () -> {
// fireLog
};
}
- static boolean setSfcPart(final RenderedServicePath renderedServicePath, PolicyWriter policyWriter) {
+ static boolean setSfcPart(final ServiceFunctionPath serviceFunctionPath, final RenderedServicePath renderedServicePath,
+ final RenderedServicePath reversedRenderedServicePath, PolicyWriter policyWriter) {
+ if (!checkLocalForwarderPresence(policyWriter.getCurrentMountpoint())) {
+ appendLocalSff(policyWriter);
+ } else {
+ LOG.info("Local forwarder for node {} is already created", policyWriter.getCurrentNodeId());
+ }
+ boolean outcome = true;
+ // Direct path
final java.util.Optional<RenderedServicePath> renderedServicePathSafe = java.util.Optional.ofNullable(renderedServicePath);
- final java.util.Optional<RenderedServicePathHop> renderedServicePathHop = renderedServicePathSafe
- .map(RenderedServicePath::getRenderedServicePathHop)
- .map(rspHop -> Iterables.getFirst(rspHop, null));
-
- final boolean outcome;
- if (!renderedServicePathHop.isPresent()) {
- LOG.warn("Rendered service path {} does not contain any hop",
- renderedServicePathSafe.map(RenderedServicePath::getName).map(RspName::getValue).orElse("n/a"));
+ if (renderedServicePathSafe.isPresent()) {
+ if (renderedServicePath.getRenderedServicePathHop() != null
+ && !renderedServicePath.getRenderedServicePathHop().isEmpty()) {
+ if (!resolveRenderedServicePath(renderedServicePath, policyWriter)) {
+ outcome = false;
+ }
+ }
+ else {
+ LOG.warn("Rendered service path {} does not contain any hop",
+ renderedServicePathSafe.map(RenderedServicePath::getName).map(RspName::getValue).orElse("n/a"));
+ outcome = false;
+ }
+ }
+ else {
+ LOG.warn("Rendered service path is null");
outcome = false;
- } else {
- final RenderedServicePathHop firstHop = renderedServicePathHop.get();
- final SffName sffName = firstHop.getServiceFunctionForwarder();
-
- // Forwarders
- //
- // If classifier node is also forwarder, first entry in service path has to point to first service function
- // (Local case)
- //
- // If first hop Sff is on different node, first service path entry has to point to that specific service
- // forwarder (Remote case)
-
- // Local case (only when does not exist)
-
- if (!checkLocalForwarderPresence(policyWriter.getCurrentMountpoint())) {
- appendLocalSff(policyWriter);
+ }
+ if (serviceFunctionPath.isSymmetric()) {
+ // Reversed path
+ final java.util.Optional<RenderedServicePath> reversedRenderedServicePathSafe = java.util.Optional.ofNullable(reversedRenderedServicePath);
+ if (reversedRenderedServicePathSafe.isPresent()) {
+ if (reversedRenderedServicePath.getRenderedServicePathHop() != null
+ && !reversedRenderedServicePath.getRenderedServicePathHop().isEmpty()) {
+ if (!resolveRenderedServicePath(reversedRenderedServicePath, policyWriter)) {
+ outcome = false;
+ }
+ } else {
+ LOG.warn("Rendered service path {} does not contain any hop",
+ reversedRenderedServicePathSafe.map(RenderedServicePath::getName).map(RspName::getValue).orElse("n/a"));
+ outcome = false;
+ }
} else {
- LOG.info("Local forwarder for node {} is already created", policyWriter.getCurrentNodeId());
+ LOG.warn("Reversed rendered service path is null");
+ outcome = false;
}
+ }
+ return outcome;
+ }
- // Remote case
- final java.util.Optional<ServiceFunctionForwarder> serviceFunctionForwarder = java.util.Optional.ofNullable(
- SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName));
+ private static boolean resolveRenderedServicePath(final RenderedServicePath renderedServicePath, PolicyWriter policyWriter) {
+ final RenderedServicePathHop firstHop = renderedServicePath.getRenderedServicePathHop().get(0);
+ if (firstHop == null) {
+ return false;
+ }
+ final SffName sffName = firstHop.getServiceFunctionForwarder();
- outcome = serviceFunctionForwarder.map(sff -> java.util.Optional.ofNullable(sff.getIpMgmtAddress())
+ // Forwarders
+ //
+ // If classifier node is also forwarder, first entry in service path has to point to first service function
+ // (Local case)
+ //
+ // If first hop Sff is on different node, first service path entry has to point to that specific service
+ // forwarder (Remote case)
+
+ final java.util.Optional<ServiceFunctionForwarder> serviceFunctionForwarder = java.util.Optional.ofNullable(
+ SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName));
+ return serviceFunctionForwarder.map(sff -> java.util.Optional.ofNullable(sff.getIpMgmtAddress())
.map(IpAddress::getIpv4Address)
.map((ipv4Address) -> ipv4Address.getValue())
.map(addressValue -> {
// Service chain
final List<Services> services = new ArrayList<>();
- //TODO: servicesBuilder is never used
final ServicesBuilder servicesBuilder = new ServicesBuilder();
servicesBuilder.setServiceIndexId(renderedServicePath.getStartingIndex())
.setServiceTypeChoice(serviceTypeChoice);
+ services.add(servicesBuilder.build());
final List<ServicePath> servicePaths = new ArrayList<>();
final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
servicePathBuilder.setKey(new ServicePathKey(renderedServicePath.getPathId()))
).orElseGet(createNegativePathWithLogSupplier(sffName.getValue(),
(value) -> LOG.error("Sff with name {} does not exist", value))
);
- }
-
- return outcome;
}
private static void appendLocalSff(final PolicyWriter policyWriter) {
return sfBuilder.build();
}
+ private static void checkSfcRspStatus(final RspName rspName, final DataBroker dataBroker) {
+ /** TODO A better way to do this is to register listener and wait for notification than using hardcoded timeout
+ * with Thread.sleep(). Example in class BridgeDomainManagerImpl
+ */
+ ConfiguredRenderedPath renderedPath = null;
+ LOG.info("Waiting for SFC to configure path {} ...", rspName.getValue());
+
+ byte attempt = 0;
+ do {
+ attempt++;
+ // Wait
+ try {
+ Thread.sleep(5000L);
+ } catch (InterruptedException e) {
+ LOG.error("Thread interrupted while waiting ... {} ", e);
+ }
+ // Read actual status
+ final InstanceIdentifier<ConfiguredRenderedPath> statusIid = InstanceIdentifier.builder(RendererPathStates.class)
+ .child(RendererPathState.class, new RendererPathStateKey(new RendererName("ios-xe-renderer")))
+ .child(ConfiguredRenderedPaths.class)
+ .child(ConfiguredRenderedPath.class, new ConfiguredRenderedPathKey(rspName)).build();
+ final java.util.Optional<ReadWriteTransaction> optionalTransaction =
+ NetconfTransactionCreator.netconfReadWriteTransaction(dataBroker);
+ if (!optionalTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", dataBroker);
+ return;
+ }
+ ReadWriteTransaction transaction = optionalTransaction.get();
+ try {
+ final CheckedFuture<Optional<ConfiguredRenderedPath>, ReadFailedException> submitFuture =
+ transaction.read(LogicalDatastoreType.OPERATIONAL, statusIid);
+ final Optional<ConfiguredRenderedPath> optionalPath = submitFuture.checkedGet();
+ if (optionalPath.isPresent()) {
+ renderedPath = optionalPath.get();
+ }
+ } catch (ReadFailedException e) {
+ LOG.warn("Failed while read rendered path status ... {} ", e.getMessage());
+ }
+ if (renderedPath == null || renderedPath.getPathStatus() == null ||
+ renderedPath.getPathStatus().equals(ConfiguredRenderedPath.PathStatus.InProgress)) {
+ LOG.info("Still waiting for SFC ... ");
+ } else if (renderedPath.getPathStatus().equals(ConfiguredRenderedPath.PathStatus.Failure)) {
+ LOG.warn("SFC failed to configure rsp");
+ } else if (renderedPath.getPathStatus().equals(ConfiguredRenderedPath.PathStatus.Success)) {
+ LOG.info("RSP {} configured by SFC", rspName.getValue());
+ try {
+ Thread.sleep(5000); // Just for sure, maybe will be safe to remove this
+ } catch (InterruptedException e) {
+ LOG.error("Thread interrupted while waiting ... {} ", e);
+ }
+ return;
+ }
+ }
+ while (attempt <= 6);
+ LOG.warn("Maximum number of attempts reached");
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.netconf.api.NetconfDocumentedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+/**
+ * Purpose: safely create transaction
+ */
+
+public class NetconfTransactionCreator {
+
+ private final static Logger LOG = LoggerFactory.getLogger(NetconfTransactionCreator.class);
+ private static final long TIMEOUT = 5000L;
+
+ public static Optional<ReadOnlyTransaction> netconfReadOnlyTransaction(DataBroker mountpoint) {
+ int attempt = 0;
+ do {
+ try {
+ return Optional.ofNullable(mountpoint.newReadOnlyTransaction());
+ } catch (RuntimeException e) {
+ final Optional<Throwable> optionalCause = Optional.ofNullable(e.getCause());
+ final Optional<Class> optionalCauseClass = optionalCause.map(Throwable::getClass);
+ if (optionalCauseClass.isPresent() && optionalCauseClass.get().equals(NetconfDocumentedException.class)) {
+ attempt++;
+ LOG.warn("NetconfDocumentedException thrown, retrying ({})...", attempt);
+ try {
+ Thread.sleep(TIMEOUT);
+ } catch (InterruptedException i) {
+ LOG.error("Thread interrupted while waiting ... {} ", i);
+ }
+ } else {
+ LOG.error("Runtime exception ... {}", e.getMessage(), e);
+ return Optional.empty();
+ }
+ }
+ } while (attempt <= 5);
+ LOG.error("Maximum number of attempts reached");
+ return Optional.empty();
+ }
+
+ public static Optional<WriteTransaction> netconfWriteOnlyTransaction(DataBroker mountpoint) {
+ int attempt = 0;
+ do {
+ try {
+ return Optional.of(mountpoint.newWriteOnlyTransaction());
+ } catch (RuntimeException e) {
+ final Optional<Throwable> optionalCause = Optional.ofNullable(e.getCause());
+ final Optional<Class> optionalCauseClass = optionalCause.map(Throwable::getClass);
+ if (optionalCauseClass.isPresent() && optionalCauseClass.get().equals(NetconfDocumentedException.class)) {
+ attempt++;
+ LOG.warn("NetconfDocumentedException thrown, retrying ({})...", attempt);
+ try {
+ Thread.sleep(TIMEOUT);
+ } catch (InterruptedException i) {
+ LOG.error("Thread interrupted while waiting ... {} ", i);
+ }
+ } else {
+ LOG.error("Runtime exception ... {}", e.getMessage());
+ return Optional.empty();
+ }
+ }
+ } while (attempt <= 5);
+ LOG.error("Maximum number of attempts reached");
+ return Optional.empty();
+ }
+
+ public static Optional<ReadWriteTransaction> netconfReadWriteTransaction(DataBroker mountpoint) {
+ int attempt = 0;
+ do {
+ try {
+ return Optional.of(mountpoint.newReadWriteTransaction());
+ } catch (RuntimeException e) {
+ final Optional<Throwable> optionalCause = Optional.ofNullable(e.getCause());
+ final Optional<Class> optionalCauseClass = optionalCause.map(Throwable::getClass);
+ if (optionalCauseClass.isPresent() && optionalCauseClass.get().equals(NetconfDocumentedException.class)) {
+ attempt++;
+ LOG.warn("NetconfDocumentedException thrown, retrying ({})...", attempt);
+ try {
+ Thread.sleep(TIMEOUT);
+ } catch (InterruptedException i) {
+ LOG.error("Thread interrupted while waiting ... {} ", i);
+ }
+ } else {
+ LOG.error("Runtime exception ... {}", e.getMessage());
+ return Optional.empty();
+ }
+ }
+ } while (attempt <= 5);
+ LOG.error("Maximum number of attempts reached");
+ return Optional.empty();
+ }
+}
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
public class NodeWriter {
private static final Logger LOG = LoggerFactory.getLogger(NodeWriter.class);
- private List<RendererNode> rendererNodesCache;
+ private final List<RendererNode> rendererNodesCache;
public NodeWriter() {
rendererNodesCache = new ArrayList<>();
*/
public void commitToDatastore(DataBroker dataBroker) {
RendererNodes rendererNodes = buildRendererNodes();
- WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
- InstanceIdentifier<RendererNodes> iid = buildRendererNodesIid();
+ final Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(dataBroker);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", dataBroker);
+ return;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier<RendererNodes> iid = buildRendererNodesIid();
try {
- wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, rendererNodes, true);
- CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+ writeTransaction.merge(LogicalDatastoreType.OPERATIONAL, iid, rendererNodes, true);
+ CheckedFuture<Void, TransactionCommitFailedException> submitFuture = writeTransaction.submit();
submitFuture.checkedGet();
// Clear cache
rendererNodesCache.clear();
* @param dataBroker appropriate data provider
*/
public void removeFromDatastore(DataBroker dataBroker) {
- WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ final Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(dataBroker);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", dataBroker);
+ return;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
for (RendererNode nodeToRemove : rendererNodesCache) {
InstanceIdentifier<RendererNode> iid = buildRendererNodeIid(nodeToRemove);
try {
- wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
- CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+ writeTransaction.delete(LogicalDatastoreType.OPERATIONAL, iid);
+ CheckedFuture<Void, TransactionCommitFailedException> submitFuture = writeTransaction.submit();
submitFuture.checkedGet();
// Clear cache
} catch (TransactionCommitFailedException e) {
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.ServiceChainingUtil;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.Interface;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernet;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernetKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePath;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.Local;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfName;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
serviceChains.add(serviceChain);
}
- public CheckedFuture<Void, TransactionCommitFailedException> commitToDatastore() {
- WriteTransaction wtx = mountpoint.newWriteOnlyTransaction();
- // GBP
- // Class maps
- for (ClassMap entry : classMapEntries) {
- InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
- wtx.merge(LogicalDatastoreType.CONFIGURATION, classMapIid, entry);
- LOG.info("Created class-map {} on node {}", entry.getName(), nodeId.getValue());
- }
-
- // Policy map
- PolicyMap policyMap = PolicyManagerUtil.createPolicyMap(policyMapName, policyMapEntries);
- InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier();
- wtx.merge(LogicalDatastoreType.CONFIGURATION, policyMapIid, policyMap);
- LOG.info("Created policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
-
- // Interface
- ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
- InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
- wtx.merge(LogicalDatastoreType.CONFIGURATION, servicePolicyIid, servicePolicy);
- LOG.info("Service-policy interface {}, bound to policy-map {} created on node {}",
- interfaceName, policyMap.getName(), nodeId.getValue());
-
- //SFC
- // Local forwarder (if some service chain exists, otherwise is useless)
- if (!serviceChains.isEmpty()) {
- InstanceIdentifier<Local> localIid = localSffInstanceIdentifier();
- wtx.merge(LogicalDatastoreType.CONFIGURATION, localIid, localForwarder);
- LOG.info("Local forwarder created on node {}", nodeId.getValue());
- }
-
- // Remote forwarders
- for (ServiceFfName forwarder : remoteForwarders) {
- InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
- wtx.merge(LogicalDatastoreType.CONFIGURATION, forwarderIid, forwarder);
- LOG.info("Remote forwarder {} created on node {}", forwarder.getName(), nodeId.getValue());
- }
-
- // Service paths
- for (ServiceChain serviceChain : serviceChains) {
- for (ServicePath entry : serviceChain.getServicePath()) {
- InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
- wtx.merge(LogicalDatastoreType.CONFIGURATION, servicePathIid, entry);
- LOG.info("Service path with Id {} created on node {}", entry.getServicePathId(), nodeId.getValue());
- }
- }
-
- return wtx.submit();
- }
-
- public CheckedFuture<Void, TransactionCommitFailedException> removeFromDatastore() {
- ReadWriteTransaction wtx = mountpoint.newReadWriteTransaction();
- //GBP
- // Interface
- InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
- wtx.delete(LogicalDatastoreType.CONFIGURATION, servicePolicyIid);
- LOG.info("Service-policy removed from interface {} on node {}", interfaceName, nodeId.getValue());
-
- // Policy map
- InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier();
- wtx.delete(LogicalDatastoreType.CONFIGURATION, policyMapIid);
- LOG.info("Policy-map removed from node node {}", nodeId.getValue());
-
- // Class map
- for (ClassMap entry : classMapEntries) {
- InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
- wtx.delete(LogicalDatastoreType.CONFIGURATION, classMapIid);
- LOG.info("Class-map {} removed from node {}", entry.getName(), nodeId.getValue());
- }
-
- //SFC
- // Service paths
- for (ServiceChain serviceChain : serviceChains) {
- for (ServicePath entry : serviceChain.getServicePath()) {
- InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
- wtx.delete(LogicalDatastoreType.CONFIGURATION, servicePathIid);
- LOG.info("Service path with Id {} removed from node {}", entry.getServicePathId(), nodeId.getValue());
- }
- }
-
- // Remote forwarders
- for (ServiceFfName forwarder : remoteForwarders) {
- InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
- wtx.delete(LogicalDatastoreType.CONFIGURATION, forwarderIid);
- LOG.info("Remote forwarder {} removed from node {}", forwarder.getName(), nodeId.getValue());
- }
-
- // Local forwarder - remove only if there is no more service-paths on device. If paths removed above were last
- // ones, remove local forwarder. If there are still some paths present, they were created by sfc and local
- // forwarder cannot be removed (because it was created by sfc as well)
- if (ServiceChainingUtil.checkServicePathPresence(mountpoint)) {
- InstanceIdentifier<Local> localIid = localSffInstanceIdentifier();
- wtx.delete(LogicalDatastoreType.CONFIGURATION, localIid);
- LOG.info("Local forwarder removed from node {}", nodeId.getValue());
- }
-
- return wtx.submit();
- }
-
- private InstanceIdentifier<ClassMap> classMapInstanceIdentifier(ClassMap classMap) {
- return InstanceIdentifier.builder(Native.class)
- .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
- }
-
- private InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier() {
- return InstanceIdentifier.builder(Native.class)
- .child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
- }
-
- private InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(String ethernetName) {
- return InstanceIdentifier.builder(Native.class)
- .child(Interface.class)
- .child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
- .child(ServicePolicy.class)
- .build();
- }
-
- private InstanceIdentifier<Local> localSffInstanceIdentifier() {
- return InstanceIdentifier.builder(Native.class)
- .child(ServiceChain.class)
- .child(ServiceFunctionForwarder.class)
- .child(Local.class).build();
- }
-
- private InstanceIdentifier<ServiceFfName> remoteSffInstanceIdentifier(ServiceFfName sffName) {
- return InstanceIdentifier.builder(Native.class)
- .child(ServiceChain.class)
- .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
- .child(ServiceFfName.class, new ServiceFfNameKey(sffName.getName())).build();
- }
-
- private InstanceIdentifier<ServicePath> servicePathInstanceIdentifier(ServicePathKey key) {
- return InstanceIdentifier.builder(Native.class)
- .child(ServiceChain.class)
- .child(ServicePath.class, key).build();
+ public CheckedFuture<Boolean, TransactionCommitFailedException> commitToDatastore() {
+ LOG.info("Configuring policy on node {} ... ", nodeId.getValue());
+ // SFC
+ boolean localResult = PolicyWriterUtil.writeLocal(localForwarder, nodeId, mountpoint);
+ boolean remoteResult = PolicyWriterUtil.writeRemote(remoteForwarders, nodeId, mountpoint);
+ boolean servicePathsResult = PolicyWriterUtil.writeServicePaths(serviceChains, nodeId, mountpoint);
+ // GBP - maintain order!
+ boolean classMapResult = PolicyWriterUtil.writeClassMaps(classMapEntries, nodeId, mountpoint);
+ boolean policyMapResult = PolicyWriterUtil.writePolicyMap(policyMapName, policyMapEntries, nodeId, mountpoint);
+ boolean interfaceResult = PolicyWriterUtil.writeInterface(policyMapName, interfaceName, nodeId, mountpoint);
+ // Result
+ LOG.info("Policy configuration on node {} completed", nodeId.getValue());
+ return Futures.immediateCheckedFuture(classMapResult && policyMapResult && interfaceResult && localResult
+ && remoteResult && servicePathsResult);
+ }
+
+ public CheckedFuture<Boolean, TransactionCommitFailedException> removeFromDatastore() {
+ LOG.info("Removing policy from node {} ... ", nodeId.getValue());
+ // GBP - maintain order!
+ boolean policyMapEntriesResult = PolicyWriterUtil.removePolicyMapEntries(policyMapName, policyMapEntries,
+ nodeId, mountpoint);
+ boolean classMapResult = PolicyWriterUtil.removeClassMaps(classMapEntries, nodeId, mountpoint);
+ // TODO remove class map?
+ // SFC
+ boolean servicePathsResult = PolicyWriterUtil.removeServicePaths(serviceChains, nodeId, mountpoint);
+ boolean localResult = PolicyWriterUtil.removeLocal(nodeId, mountpoint);
+ // TODO remove remote forwarders
+ // Result
+ LOG.info("Policy removed from node {}", nodeId.getValue());
+ return Futures.immediateCheckedFuture(classMapResult && policyMapEntriesResult && servicePathsResult
+ && localResult);
}
public String getManagementIpAddress() {
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.ServiceChainingUtil;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.Interface;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernet;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._interface.GigabitEthernetKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePath;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.Local;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfName;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Purpose: Util class for every policy writer
+ */
+class PolicyWriterUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PolicyWriterUtil.class);
+
+ static boolean writeClassMaps(final List<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
+ if (classMapEntries == null || classMapEntries.isEmpty()) {
+ return true;
+ }
+ for (ClassMap entry : classMapEntries) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
+ writeMergeTransaction(writeTransaction, classMapIid, entry);
+ // Check
+ final java.util.Optional<ReadOnlyTransaction> optionalTransaction =
+ NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
+ if (!optionalTransaction.isPresent()) {
+ LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final ReadOnlyTransaction readTransaction = optionalTransaction.get();
+ if (checkWritten(readTransaction, classMapIid) == null) {
+ return false;
+ }
+ LOG.info("Created class-map {} on node {}", entry.getName(), nodeId.getValue());
+ }
+ return true;
+ }
+
+ static boolean removeClassMaps(final List<ClassMap> classMapEntries, final NodeId nodeId, final DataBroker mountpoint) {
+ boolean result = true;
+ if (classMapEntries == null || classMapEntries.isEmpty()) {
+ return true;
+ }
+ for (ClassMap entry : classMapEntries) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier<ClassMap> classMapIid = classMapInstanceIdentifier(entry);
+ deleteTransaction(writeTransaction, classMapIid);
+ // Check
+ final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
+ NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
+ if (!optionalReadTransaction.isPresent()) {
+ LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final ReadOnlyTransaction readTransaction = optionalReadTransaction.get();
+ result = checkRemoved(readTransaction, classMapIid);
+ LOG.info("Class-map {} removed from node {}", entry.getName(), nodeId.getValue());
+ }
+ return result;
+ }
+
+ static boolean writePolicyMap(final String policyMapName, final List<Class> policyMapEntries, NodeId nodeId,
+ final DataBroker mountpoint) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final PolicyMap policyMap = PolicyManagerUtil.createPolicyMap(policyMapName, policyMapEntries);
+ final InstanceIdentifier<PolicyMap> policyMapIid = policyMapInstanceIdentifier(policyMapName);
+ writeMergeTransaction(writeTransaction, policyMapIid, policyMap);
+ // Check
+ final java.util.Optional<ReadOnlyTransaction> optionalReadTransaction =
+ NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
+ if (!optionalReadTransaction.isPresent()) {
+ LOG.warn("Failed to create read-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final ReadOnlyTransaction readTransaction = optionalReadTransaction.get();
+ if (checkWritten(readTransaction, policyMapIid) == null) {
+ return false;
+ }
+ LOG.info("Created policy-map {} on node {}", policyMap.getName(), nodeId.getValue());
+ return true;
+ }
+
+ static boolean removePolicyMapEntries(final String policyMapName, final List<Class> policyMapEntries,
+ final NodeId nodeId, final DataBroker mountpoint) {
+ if (policyMapEntries == null || policyMapEntries.isEmpty()) {
+ return true;
+ }
+ for (Class entry : policyMapEntries) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier policyMapEntryIid = policyMapEntryInstanceIdentifier(policyMapName, entry.getName());
+ if (deleteTransaction(writeTransaction, policyMapEntryIid)) {
+ LOG.info("Policy map entry {} removed from node {}", entry.getName(), nodeId.getValue());
+ }
+ }
+ return true;
+ }
+
+ static boolean writeInterface(final String policyMapName, final String interfaceName, final NodeId nodeId,
+ final DataBroker mountpoint) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final ServicePolicy servicePolicy = PolicyManagerUtil.createServicePolicy(policyMapName, Direction.Input);
+ final InstanceIdentifier<ServicePolicy> servicePolicyIid = interfaceInstanceIdentifier(interfaceName);
+ writeMergeTransaction(writeTransaction, servicePolicyIid, servicePolicy);
+ LOG.info("Service-policy interface {}, bound to policy-map {} created on node {}",
+ interfaceName, policyMapName, nodeId.getValue());
+ return true;
+ }
+
+ static boolean writeLocal(final Local localForwarder, final NodeId nodeId, final DataBroker mountpoint) {
+ if (localForwarder == null) {
+ return true;
+ }
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier<Local> localIid = localSffInstanceIdentifier();
+ writeMergeTransaction(writeTransaction, localIid, localForwarder);
+ LOG.info("Local forwarder created on node {}", nodeId.getValue());
+ return true;
+ }
+
+ static boolean removeLocal(final NodeId nodeId, final DataBroker mountpoint) {
+ // Remove local forwarder only when there are no more service-paths
+ if (ServiceChainingUtil.checkServicePathPresence(mountpoint)) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier<Local> localIid = localSffInstanceIdentifier();
+ deleteTransaction(writeTransaction, localIid);
+ LOG.info("Local forwarder removed from node {}", nodeId.getValue());
+ }
+ return true;
+ }
+
+ static boolean writeRemote(final List<ServiceFfName> remoteForwarders, final NodeId nodeId,
+ final DataBroker mountpoint) {
+ if (remoteForwarders == null || remoteForwarders.isEmpty()) {
+ return true;
+ }
+ for (ServiceFfName forwarder : remoteForwarders) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier<ServiceFfName> forwarderIid = remoteSffInstanceIdentifier(forwarder);
+ writeMergeTransaction(writeTransaction, forwarderIid, forwarder);
+ LOG.info("Remote forwarder {} created on node {}", forwarder.getName(), nodeId.getValue());
+ }
+ return true;
+ }
+
+ static boolean writeServicePaths(final List<ServiceChain> serviceChains, final NodeId nodeId,
+ final DataBroker mountpoint) {
+ for (org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain serviceChain : serviceChains) {
+ for (ServicePath entry : serviceChain.getServicePath()) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(entry.getKey());
+ writeMergeTransaction(writeTransaction, servicePathIid, entry);
+ LOG.info("Service path with ID: {} created on node {}", entry.getServicePathId(), nodeId.getValue());
+ }
+ }
+ return true;
+ }
+
+ static boolean removeServicePaths(final List<ServiceChain> serviceChains, final NodeId nodeId,
+ final DataBroker mountpoint) {
+ if (serviceChains == null || serviceChains.isEmpty()) {
+ return true;
+ }
+ for (ServiceChain chain : serviceChains) {
+ List<ServicePath> servicePaths = chain.getServicePath();
+ if (servicePaths == null || servicePaths.isEmpty()) {
+ continue;
+ }
+ for (ServicePath servicePath : servicePaths) {
+ final java.util.Optional<WriteTransaction> optionalWriteTransaction =
+ NetconfTransactionCreator.netconfWriteOnlyTransaction(mountpoint);
+ if (!optionalWriteTransaction.isPresent()) {
+ LOG.warn("Failed to create write-only transaction, mountpoint: {}", mountpoint);
+ return false;
+ }
+ final WriteTransaction writeTransaction = optionalWriteTransaction.get();
+ final InstanceIdentifier<ServicePath> servicePathIid = servicePathInstanceIdentifier(servicePath.getKey());
+ if (deleteTransaction(writeTransaction, servicePathIid)) {
+ LOG.info("Service-path with ID: {} removed from node {}", servicePath.getServicePathId(),
+ nodeId.getValue());
+ }
+ }
+ }
+ return true;
+ }
+
+ private static InstanceIdentifier<ClassMap> classMapInstanceIdentifier(final ClassMap classMap) {
+ return InstanceIdentifier.builder(Native.class)
+ .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
+ }
+
+ private static InstanceIdentifier<PolicyMap> policyMapInstanceIdentifier(final String policyMapName) {
+ return InstanceIdentifier.builder(Native.class)
+ .child(PolicyMap.class, new PolicyMapKey(policyMapName)).build();
+ }
+
+ private static InstanceIdentifier<Class> policyMapEntryInstanceIdentifier(final String policyMapName,
+ final ClassNameType classNameType) {
+ return InstanceIdentifier.builder(Native.class)
+ .child(PolicyMap.class, new PolicyMapKey(policyMapName))
+ .child(Class.class, new ClassKey(classNameType)).build();
+ }
+
+ private static InstanceIdentifier<ServicePolicy> interfaceInstanceIdentifier(final String ethernetName) {
+ return InstanceIdentifier.builder(Native.class)
+ .child(Interface.class)
+ .child(GigabitEthernet.class, new GigabitEthernetKey(ethernetName))
+ .child(ServicePolicy.class)
+ .build();
+ }
+
+ private static InstanceIdentifier<Local> localSffInstanceIdentifier() {
+ return InstanceIdentifier.builder(Native.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
+ .child(ServiceFunctionForwarder.class)
+ .child(Local.class).build();
+ }
+
+ private static InstanceIdentifier<ServiceFfName> remoteSffInstanceIdentifier(final ServiceFfName sffName) {
+ return InstanceIdentifier.builder(Native.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
+ .child(ServiceFfName.class, new ServiceFfNameKey(sffName.getName())).build();
+ }
+
+ private static InstanceIdentifier<ServicePath> servicePathInstanceIdentifier(final ServicePathKey key) {
+ return InstanceIdentifier.builder(Native.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain.class)
+ .child(ServicePath.class, key).build();
+ }
+
+ private static <U extends DataObject> void writeMergeTransaction(final WriteTransaction transaction,
+ final InstanceIdentifier<U> addIID,
+ final U data) {
+ try {
+ transaction.merge(LogicalDatastoreType.CONFIGURATION, addIID, data);
+ final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
+ submitFuture.checkedGet();
+ } catch (TransactionCommitFailedException e) {
+ LOG.error("Write transaction failed to {}", e.getMessage());
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ }
+
+ private static <U extends DataObject> boolean deleteTransaction(final WriteTransaction transaction,
+ final InstanceIdentifier<U> addIID) {
+ try {
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, addIID);
+ final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = transaction.submit();
+ submitFuture.checkedGet();
+ return true;
+ } catch (TransactionCommitFailedException e) {
+ LOG.error("Write transaction failed to {}", e.getMessage());
+ return false;
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ return false;
+ }
+ }
+
+ private static <U extends DataObject> U checkWritten(final ReadOnlyTransaction transaction,
+ final InstanceIdentifier<U> readIID) {
+ for (int attempt = 1; attempt <= 5; attempt++) {
+ try {
+ final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
+ transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
+ final Optional<U> optional = submitFuture.checkedGet();
+ if (optional != null && optional.isPresent()) {
+ transaction.close(); // Release lock
+ return optional.get();
+ } else {
+ // Could take some time until specific configuration appears on device, try to read a few times
+ Thread.sleep(2000L);
+ }
+ } catch (InterruptedException i) {
+ LOG.error("Thread interrupted while waiting ... {} ", i);
+ } catch (ReadFailedException e) {
+ LOG.warn("Read transaction failed to {} ", e);
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ }
+ return null;
+ }
+
+ private static <U extends DataObject> boolean checkRemoved(final ReadOnlyTransaction transaction,
+ final InstanceIdentifier<U> readIID) {
+ for (int attempt = 1; attempt <= 5; attempt++) {
+ try {
+ final CheckedFuture<Optional<U>, ReadFailedException> submitFuture =
+ transaction.read(LogicalDatastoreType.CONFIGURATION, readIID);
+ final Optional<U> optional = submitFuture.checkedGet();
+ if (optional != null && optional.isPresent()) {
+ // Could take some time until specific configuration is removed from the device
+ Thread.sleep(2000L);
+ } else {
+ transaction.close(); // Release lock
+ return true;
+ }
+ } catch (InterruptedException i) {
+ LOG.error("Thread interrupted while waiting ... {} ", i);
+ } catch (ReadFailedException e) {
+ LOG.warn("Read transaction failed to {} ", e);
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ }
+ return false;
+ }
+
+}
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
Mockito.when(roTx.read(Matchers.eq(LogicalDatastoreType.OPERATIONAL), rendererServicePathIICaptor.capture()))
.thenReturn(Futures.immediateCheckedFuture(Optional.of(renderedSP)));
- final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(serviceFunctionPath, tenantId);
+ final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(serviceFunctionPath, tenantId,
+ dataBroker);
Assert.assertEquals(renderedSP, renderedPath);
final InstanceIdentifier<RenderedServicePath> ii = rendererServicePathIICaptor.getValue();
Assert.assertEquals("sfp-name-01tenant-id-01-gbp-rsp", ii.firstKeyOf(RenderedServicePath.class).getName().getValue());
final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(
- serviceFunctionPath, renderedServicePath, tenantId);
+ serviceFunctionPath, renderedServicePath, tenantId, dataBroker);
Assert.assertEquals(renderedServicePath, symmetricRenderedPath);
final InstanceIdentifier<RenderedServicePath> ii = rendererServicePathIICaptor.getValue();
Assert.assertEquals("sfp-name-01tenant-id-02-gbp-rsp-Reverse", ii.firstKeyOf(RenderedServicePath.class).getName().getValue());
}
+
+ @Test
+ public void testMatch() {
+ Match result = PolicyManagerUtil.createSecurityGroupMatch(10, 20);
+ assertNotNull(result);
+ }
}
\ No newline at end of file
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
+import org.mockito.internal.verification.Times;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.NetconfTransactionCreator;
import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChainBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
ServiceChainingUtil.class,
SfcProviderServicePathAPI.class,
SfcProviderRenderedPathAPI.class,
- SfcProviderServiceForwarderAPI.class
+ SfcProviderServiceForwarderAPI.class,
+ NetconfTransactionCreator.class
})
public class ServiceChainingUtilTest {
private ArgumentCaptor<RenderedServicePath> rspCaptor;
@Captor
private ArgumentCaptor<List<Class>> listClassCaptor;
+ @Captor
+ private ArgumentCaptor<ClassMap> classMapCaptor;
@Mock
private PolicyWriter policyWriter;
@Mock
stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
stub(method(ServiceChainingUtil.class, "setSfcPart")).toReturn(true);
- ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+ ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, policyWriter, dataBroker);
+ Mockito.verify(policyWriter).cache(classMapCaptor.capture());
Mockito.verify(policyWriter).cache(listClassCaptor.capture());
Mockito.verifyNoMoreInteractions(policyWriter);
Assert.assertEquals(1, listClassCaptor.getValue().size());
stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
stub(method(ServiceChainingUtil.class, "setSfcPart")).toReturn(true);
- ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+ ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, policyWriter, dataBroker);
+ Mockito.verify(policyWriter, Mockito.times(2)).cache(classMapCaptor.capture());
Mockito.verify(policyWriter).cache(listClassCaptor.capture());
Mockito.verifyNoMoreInteractions(policyWriter);
Assert.assertEquals(2, listClassCaptor.getValue().size());
stub(method(ServiceChainingUtil.class, "setSfcPart")).toReturn(true);
stub(method(ServiceChainingUtil.class, "createSymmetricRenderedPath")).toReturn(null);
- ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
-
+ ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, policyWriter, dataBroker);
+ Mockito.verify(policyWriter, Mockito.times(2)).cache(classMapCaptor.capture());
+ Mockito.verify(policyWriter).cache(listClassCaptor.capture());
Mockito.verifyNoMoreInteractions(policyWriter);
}
stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
stub(method(ServiceChainingUtil.class, "setSfcPart")).toReturn(false);
- ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+ ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, policyWriter, dataBroker);
Mockito.verifyNoMoreInteractions(policyWriter);
}
final RenderedServicePath rsp = createRsp("unit-rsp-02");
stub(method(SfcProviderRenderedPathAPI.class, "readRenderedServicePath")).toReturn(rsp);
- ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+ ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, policyWriter, dataBroker);
Mockito.verifyNoMoreInteractions(policyWriter);
}
final Map<PolicyManagerImpl.ActionCase, Action> actionMap = createActionMap(false);
final String classMapName = "unit-class-map-name-01";
- ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+ ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, policyWriter, dataBroker);
Mockito.verifyNoMoreInteractions(policyWriter);
}
final SfcProviderRenderedPathAPI api = PowerMockito.mock(SfcProviderRenderedPathAPI.class);
PowerMockito.when(api.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(rsp);
- final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(sfp, tenantId);
+ final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(sfp, tenantId, dataBroker);
Assert.assertEquals("123_plainunit-tennant-01-gbp-rsp", rspNameCaptor.getValue().getValue());
Assert.assertEquals(rsp, renderedPath);
PowerMockito.when(api.createRenderedServicePathAndState(
sfpCaptor.capture(), createRspCaptor.capture()
)).thenReturn(rsp);
+ PowerMockito.mockStatic(NetconfTransactionCreator.class);
+ final NetconfTransactionCreator creator = PowerMockito.mock(NetconfTransactionCreator.class);
+ PowerMockito.when(creator.netconfReadWriteTransaction(dataBroker)).thenReturn(java.util.Optional.empty());
- final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(sfp, tenantId);
+ final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(sfp, tenantId, dataBroker);
Assert.assertEquals("123_plainunit-tennant-01-gbp-rsp", rspNameCaptor.getValue().getValue());
final SfcProviderRenderedPathAPI api = PowerMockito.mock(SfcProviderRenderedPathAPI.class);
PowerMockito.when(api.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(rsp);
- final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(sfp, rsp, tennantId);
+ final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(sfp, rsp, tennantId, dataBroker);
Assert.assertEquals("unit-sfp-02_plaintenant-02-gbp-rsp-Reverse", rspNameCaptor.getValue().getValue());
Assert.assertEquals(rsp, symmetricRenderedPath);
PowerMockito.mockStatic(SfcProviderRenderedPathAPI.class);
final SfcProviderRenderedPathAPI api = PowerMockito.mock(SfcProviderRenderedPathAPI.class);
PowerMockito.when(api.readRenderedServicePath(rspNameCaptor.capture())).thenReturn(null);
- PowerMockito.when(api.createSymmetricRenderedServicePathAndState(rspCaptor.capture())).thenReturn(rsp);
+ PowerMockito.when(api.createReverseRenderedServicePathEntry(rspCaptor.capture())).thenReturn(rsp);
+ PowerMockito.mockStatic(NetconfTransactionCreator.class);
+ final NetconfTransactionCreator creator = PowerMockito.mock(NetconfTransactionCreator.class);
+ PowerMockito.when(creator.netconfReadWriteTransaction(dataBroker)).thenReturn(java.util.Optional.empty());
- final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(sfp, rsp, tennantId);
+ final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(sfp, rsp, tennantId, dataBroker);
Assert.assertEquals("unit-sfp-02_plaintenant-02-gbp-rsp-Reverse", rspNameCaptor.getValue().getValue());
Assert.assertEquals(rsp, rspCaptor.getValue());
Assert.assertEquals(rsp, symmetricRenderedPath);
}
- @Test
- public void testCheckLocalForwarderPresence() throws Exception {
- final Local local = new LocalBuilder().build();
-
- Mockito.when(rwTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), Matchers.<InstanceIdentifier<Local>>any()))
- .thenReturn(Futures.<Optional<Local>, ReadFailedException>immediateCheckedFuture(Optional.of(local)))
- .thenReturn(Futures.<Optional<Local>, ReadFailedException>immediateCheckedFuture(Optional.absent()))
- .thenReturn(Futures.<Optional<Local>, ReadFailedException>immediateFailedCheckedFuture(new ReadFailedException("n/a")));
-
- Assert.assertTrue(ServiceChainingUtil.checkLocalForwarderPresence(dataBroker));
- Assert.assertFalse(ServiceChainingUtil.checkLocalForwarderPresence(dataBroker));
- Assert.assertFalse(ServiceChainingUtil.checkLocalForwarderPresence(dataBroker));
- Assert.assertFalse(ServiceChainingUtil.checkLocalForwarderPresence(dataBroker));
- }
-
- @Test
- public void testCheckServicePathPresence() throws Exception {
- final ServiceChain serviceChainOk = new ServiceChainBuilder()
- .setServicePath(Collections.singletonList(new ServicePathBuilder().build()))
- .build();
- final ServiceChain serviceChainBad1 = new ServiceChainBuilder()
- .setServicePath(Collections.emptyList())
- .build();
- final ServiceChain serviceChainBad2 = new ServiceChainBuilder().build();
-
- Mockito.when(rwTx.read(Matchers.eq(LogicalDatastoreType.CONFIGURATION), Matchers.<InstanceIdentifier<ServiceChain>>any()))
- .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateCheckedFuture(Optional.of(serviceChainOk)))
- .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateCheckedFuture(Optional.of(serviceChainBad1)))
- .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateCheckedFuture(Optional.of(serviceChainBad2)))
- .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateCheckedFuture(Optional.absent()))
- .thenReturn(Futures.<Optional<ServiceChain>, ReadFailedException>immediateFailedCheckedFuture(new ReadFailedException("n/a")));
-
- Assert.assertFalse(ServiceChainingUtil.checkServicePathPresence(dataBroker));
- Assert.assertTrue(ServiceChainingUtil.checkServicePathPresence(dataBroker));
- Assert.assertTrue(ServiceChainingUtil.checkServicePathPresence(dataBroker));
- Assert.assertTrue(ServiceChainingUtil.checkServicePathPresence(dataBroker));
- Assert.assertFalse(ServiceChainingUtil.checkServicePathPresence(dataBroker));
- }
-
@Test
public void testFindServiceFunctionPath() throws Exception {
final String sfcNameValue = "123";
.setName(new SffName("unit-sff-03"))
.setIpMgmtAddress(new IpAddress(new Ipv4Address("1.2.3.4")))
.build();
+ final ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
+ sfpBuilder.setSymmetric(false);
+ final ServiceFunctionPath sfp = sfpBuilder.build();
stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(sff);
-
- final boolean outcome = ServiceChainingUtil.setSfcPart(rsp, policyWriter);
+ final boolean outcome = ServiceChainingUtil.setSfcPart(sfp, rsp, null, policyWriter);
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
Assert.assertTrue(outcome);
.setName(new SffName("unit-sff-03"))
.setIpMgmtAddress(new IpAddress(new Ipv4Address("1.2.3.4")))
.build();
+ final ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
+ sfpBuilder.setSymmetric(false);
+ final ServiceFunctionPath sfp = sfpBuilder.build();
stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(false);
final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(sff);
-
- final boolean outcome = ServiceChainingUtil.setSfcPart(rsp, policyWriter);
+ final boolean outcome = ServiceChainingUtil.setSfcPart(sfp, rsp, null, policyWriter);
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
Assert.assertTrue(outcome);
@Test
public void testSetSfcPart_fail01() throws Exception {
- Assert.assertFalse(ServiceChainingUtil.setSfcPart(null, policyWriter));
+ final ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
+ sfpBuilder.setSymmetric(false);
+ final ServiceFunctionPath sfp = sfpBuilder.build();
+
+ Assert.assertFalse(ServiceChainingUtil.setSfcPart(sfp, null, null, policyWriter));
final RenderedServicePathBuilder rspBuilder = new RenderedServicePathBuilder().setName(new RspName("unit-rsp-05"));
- Assert.assertFalse(ServiceChainingUtil.setSfcPart(rspBuilder.build(), policyWriter));
+ Assert.assertFalse(ServiceChainingUtil.setSfcPart(sfp, rspBuilder.build(), null, policyWriter));
rspBuilder.setRenderedServicePathHop(Collections.emptyList());
- Assert.assertFalse(ServiceChainingUtil.setSfcPart(rspBuilder.build(), policyWriter));
+ Assert.assertFalse(ServiceChainingUtil.setSfcPart(sfp, rspBuilder.build(), null, policyWriter));
rspBuilder.setRenderedServicePathHop(Collections.singletonList(null));
- Assert.assertFalse(ServiceChainingUtil.setSfcPart(rspBuilder.build(), policyWriter));
-
- Mockito.verifyNoMoreInteractions(policyWriter);
+ Assert.assertFalse(ServiceChainingUtil.setSfcPart(sfp, rspBuilder.build(), null, policyWriter));
}
@Test
public void testSetSfcPart_fail02() throws Exception {
final RenderedServicePath rsp = createRsp("unit-rsp-03");
+ final ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
+ sfpBuilder.setSymmetric(false);
+ final ServiceFunctionPath sfp = sfpBuilder.build();
Mockito.doReturn(Futures.immediateCheckedFuture(Optional.absent()))
.when(rwTx).read(Mockito.eq(LogicalDatastoreType.CONFIGURATION), Mockito.<InstanceIdentifier<Local>>any());
final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(null);
- final boolean outcome = ServiceChainingUtil.setSfcPart(rsp, policyWriter);
+ final boolean outcome = ServiceChainingUtil.setSfcPart(sfp, rsp, null, policyWriter);
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
Assert.assertFalse(outcome);
final ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder()
.setName(new SffName("unit-sff-03"))
.setIpMgmtAddress(null);
+ final ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
+ sfpBuilder.setSymmetric(false);
+ final ServiceFunctionPath sfp = sfpBuilder.build();
stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(
sffBuilder.build());
- Assert.assertFalse(ServiceChainingUtil.setSfcPart(rsp, policyWriter));
+ Assert.assertFalse(ServiceChainingUtil.setSfcPart(sfp, rsp, null, policyWriter));
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
final ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder()
.setName(new SffName("unit-sff-03"))
.setIpMgmtAddress(new IpAddress((Ipv4Address) null));
+ final ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
+ sfpBuilder.setSymmetric(false);
+ final ServiceFunctionPath sfp = sfpBuilder.build();
stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(
sffBuilder.build());
- Assert.assertFalse(ServiceChainingUtil.setSfcPart(rsp, policyWriter));
+ Assert.assertFalse(ServiceChainingUtil.setSfcPart(sfp, rsp, null, policyWriter));
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
Mockito.verifyNoMoreInteractions(policyWriter);
}
-
@Test
public void testForwarderTypeChoice() throws Exception {
final String sffValue = "unit-xx";