<groupId>org.opendaylight.netconf</groupId>
<artifactId>sal-netconf-connector</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types-2013-07-15</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.6.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.6.4</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl;
+import com.google.common.base.Preconditions;
import java.util.List;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
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;
-
/**
* Purpose: bootstrap provider implementation of Ios-xe renderer
*/
private final RendererName rendererName;
private RendererConfigurationListenerImpl rendererConfigurationListener;
private IosXeCapableNodeListenerImpl iosXeCapableNodeListener;
- private PolicyManager policyManager;
- private NodeManager nodeManager;
public IosXeRendererProviderImpl(final DataBroker dataBroker, final BindingAwareBroker broker,
final RendererName rendererName) {
LOG.info("starting ios-xe renderer");
//TODO register listeners:
// node-manager
- nodeManager = new NodeManager(dataBroker, providerContext);
+ NodeManager nodeManager = new NodeManager(dataBroker, providerContext);
// network-topology
iosXeCapableNodeListener = new IosXeCapableNodeListenerImpl(dataBroker, nodeManager);
// policy-manager and delegates
- policyManager = new PolicyManagerImpl(dataBroker);
+ PolicyManager policyManager = new PolicyManagerImpl(dataBroker, nodeManager);
final PolicyManager policyManagerZip = new PolicyManagerZipImpl(policyManager);
// renderer-configuration endpoints
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
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.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.util.NodeWriter;
+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;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connected;
import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connecting;
public static final RendererName iosXeRenderer = new RendererName("ios-xe-renderer");
private static final TopologyId TOPOLOGY_ID = new TopologyId("topology-netconf");
private static final Logger LOG = LoggerFactory.getLogger(NodeManager.class);
- private static final Map<InstanceIdentifier, DataBroker> netconfNodeCache = new HashMap<>();
private final DataBroker dataBroker;
private final MountPointService mountService;
private final List<String> requiredCapabilities;
requiredCapabilities = new RequiredCapabilities().initializeRequiredCapabilities();
}
- static DataBroker getDataBrokerFromCache(InstanceIdentifier iid) {
- return netconfNodeCache.get(iid); // TODO read from DS
- }
-
public void syncNodes(Node dataAfter, Node dataBefore) {
// New node
if (dataBefore == null && dataAfter != null) {
InstanceIdentifier mountPointIid = getMountpointIid(node);
// Mountpoint iid == path in renderer-node
RendererNode rendererNode = remapNode(mountPointIid);
- DataBroker mountpoint = getNodeMountPoint(mountPointIid);
NodeWriter nodeWriter = new NodeWriter();
nodeWriter.cache(rendererNode);
if (isCapableNetconfDevice(node, netconfNode)) {
+ resolveDisconnectedNode(node);
+ return;
+ }
+ IpAddress managementIpAddress = netconfNode.getHost().getIpAddress();
+ if (managementIpAddress == null) {
+ LOG.warn("Node {} does not contain management ip address", node.getNodeId().getValue());
+ resolveDisconnectedNode(node);
return;
}
nodeWriter.commitToDatastore(dataBroker);
- netconfNodeCache.put(mountPointIid, mountpoint);
}
private void resolveDisconnectedNode(Node node) {
NodeWriter nodeWriter = new NodeWriter();
nodeWriter.cache(rendererNode);
nodeWriter.removeFromDatastore(dataBroker);
- netconfNodeCache.remove(mountPointIid);
}
private RendererNode remapNode(InstanceIdentifier path) {
return true;
}
- private DataBroker getNodeMountPoint(InstanceIdentifier mountPointIid) {
+ DataBroker getNodeMountPoint(InstanceIdentifier mountPointIid) {
+ if (mountPointIid == null) {
+ return null;
+ }
Optional<MountPoint> optionalObject = mountService.getMountPoint(mountPointIid);
MountPoint mountPoint;
if (optionalObject.isPresent()) {
return null;
}
+ NodeId getNodeIdByMountpointIid(InstanceIdentifier mountpointIid) {
+ NodeKey identifier = (NodeKey) mountpointIid.firstKeyOf(Node.class);
+ return identifier.getNodeId();
+ }
+
+ String getNodeManagementIpByMountPointIid(InstanceIdentifier mountpointIid) {
+ NodeId nodeId = getNodeIdByMountpointIid(mountpointIid);
+ 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();
+ try {
+ CheckedFuture<Optional<Node>, ReadFailedException> submitFuture =
+ rwt.read(LogicalDatastoreType.CONFIGURATION, nodeIid);
+ Optional<Node> optional = submitFuture.checkedGet();
+ if (optional != null && optional.isPresent()) {
+ Node node = optional.get();
+ if (node != null) {
+ NetconfNode netconfNode = getNodeAugmentation(node);
+ if (netconfNode != null && netconfNode.getHost() != null) {
+ IpAddress ipAddress = netconfNode.getHost().getIpAddress();
+ if (ipAddress != null && ipAddress.getIpv4Address() != null) {
+ return ipAddress.getIpv4Address().getValue();
+ }
+ return null;
+ }
+ }
+ } else {
+ LOG.debug("Failed to read. {}", Thread.currentThread().getStackTrace()[1]);
+ }
+ } catch (ReadFailedException e) {
+ LOG.warn("Read transaction failed to {} ", e);
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ return null;
+ }
+
private NetconfNode getNodeAugmentation(Node node) {
NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
if (netconfNode == null) {
* @return list of string representations of required capabilities
*/
List<String> initializeRequiredCapabilities() {
- String writableDataStore = "urn:ietf:params:netconf:capability:writable-running:1.0";
String capabilityEntries[] = {ned, tailfCommon, tailfCliExtension, tailfMetaExtension, ietfYangTypes,
- ietfInetTypes, writableDataStore};
+ ietfInetTypes};
return Arrays.asList(capabilityEntries);
}
}
package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
-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 java.util.Set;
-
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.groupbasedpolicy.api.sf.AllowActionDefinition;
-import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
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.util.PolicyWriter;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
-import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
-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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.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._class.map.Match;
-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.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathBuilder;
-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.LocalBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.ConfigServiceChainPathModeBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.ServiceIndexBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.Services;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.ServicesBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.ServiceTypeChoice;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.service.type.choice.ServiceFunctionForwarderBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308.config.service.chain.grouping.IpBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
-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.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
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.RendererEndpoint;
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.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;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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(PolicyMapper.class);
+ private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerImpl.class);
+ private static final String policyMapName = "service-chains";
private final DataBroker dataBroker;
- private final PolicyMapper mapper;
- private final String policyMapName = "service-chains";
- private Map<DataBroker, PolicyWriter> perDeviceWriterCache = new HashMap<>();
+ private final NodeManager nodeManager;
- public enum ActionCase { ALLOW, CHAIN }
-
-
- public PolicyManagerImpl(final DataBroker dataBroker) {
+ public PolicyManagerImpl(final DataBroker dataBroker,
+ final NodeManager nodeManager) {
this.dataBroker = Preconditions.checkNotNull(dataBroker);
- mapper = new PolicyMapper(dataBroker);
+ this.nodeManager = Preconditions.checkNotNull(nodeManager);
}
@Override
- public ListenableFuture<Boolean> syncPolicy(final Configuration dataBefore, final Configuration dataAfter) {
- // CREATE
+ public ListenableFuture<Boolean> syncPolicy(final Configuration dataAfter, final Configuration dataBefore) {
+ if (dataBefore == null && dataAfter != null) {
+ return createPolicy(dataAfter);
+ }
+ if (dataBefore != null && dataAfter != null) {
+ return updatePolicy(dataAfter, dataBefore);
+ }
+ if (dataBefore != null) {
+ return deletePolicy(dataBefore);
+ }
+ return Futures.immediateFuture(false);
+ }
+
+ private ListenableFuture<Boolean> syncPolicy(final Configuration dataAfter, DsAction action) {
+ if (dataAfter.getRendererEndpoints() == null
+ || dataAfter.getRendererEndpoints().getRendererEndpoint() == null) {
+ LOG.debug("no configuration obtained - skipping");
+ return Futures.immediateFuture(true);
+ }
+ final Map<DataBroker, PolicyWriter> policyWriterPerDeviceCache = new HashMap<>();
for (RendererEndpoint rendererEndpoint : dataAfter.getRendererEndpoints().getRendererEndpoint()) {
- // Get mountpoint
- if (dataAfter.getEndpoints() == null) {
+ if (dataAfter.getEndpoints() == null || dataAfter.getEndpoints().getAddressEndpointWithLocation() == null) {
+ LOG.debug("renderer-endpoint: missing address-endpoint-with-location");
continue;
}
- DataBroker mountpoint = getAbsoluteLocationMountpoint(rendererEndpoint, dataAfter.getEndpoints()
- .getAddressEndpointWithLocation());
+ final List<AddressEndpointWithLocation> endpointsWithLocation = dataAfter.getEndpoints()
+ .getAddressEndpointWithLocation();
+ final InstanceIdentifier mountpointIid = PolicyManagerUtil.getAbsoluteLocationMountpoint(rendererEndpoint, endpointsWithLocation);
+ final DataBroker mountpoint = nodeManager.getNodeMountPoint(mountpointIid);
if (mountpoint == null) {
+ LOG.debug("no data-broker for mount-point [{}] available", mountpointIid);
continue;
}
- // Initialize appropriate writer
- PolicyWriter policyWriter;
- if (perDeviceWriterCache.containsKey(mountpoint)) {
- policyWriter = perDeviceWriterCache.get(mountpoint);
- } else {
- policyWriter = new PolicyWriter(mountpoint);
- perDeviceWriterCache.put(mountpoint, policyWriter);
+ // Find policy writer
+ PolicyWriter policyWriter = policyWriterPerDeviceCache.get(mountpoint);
+ if (policyWriter == null) {
+ // Initialize new policy writer
+ final String interfaceName = PolicyManagerUtil.getInterfaceNameForPolicyMap(rendererEndpoint, endpointsWithLocation);
+ final NodeId nodeId = nodeManager.getNodeIdByMountpointIid(mountpointIid);
+ final String managementIpAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
+ if (interfaceName == null || managementIpAddress == null) {
+ LOG.debug("can not create policyWriter: interface={}, managementIpAddress={}",
+ interfaceName, managementIpAddress);
+ continue;
+ }
+ policyWriter = new PolicyWriter(mountpoint, interfaceName, managementIpAddress, policyMapName, nodeId);
+ policyWriterPerDeviceCache.put(mountpoint, policyWriter);
}
+
+ final Sgt sourceSgt = PolicyManagerUtil.findSgtTag(rendererEndpoint, dataAfter.getEndpoints()
+ .getAddressEndpointWithLocation());
// Peer Endpoint
for (PeerEndpointWithPolicy peerEndpoint : rendererEndpoint.getPeerEndpointWithPolicy()) {
- // Sgt Tags
- final Sgt sourceSgt = findSgtTag(rendererEndpoint, dataAfter.getEndpoints()
- .getAddressEndpointWithLocation());
- final Sgt destinationSgt = findSgtTag(peerEndpoint, dataAfter.getEndpoints()
+ final Sgt destinationSgt = PolicyManagerUtil.findSgtTag(peerEndpoint, dataAfter.getEndpoints()
.getAddressEndpointWithLocation());
if (sourceSgt == null || destinationSgt == null) {
+ LOG.debug("endpoint-policy: missing sgt value(sourceSgt={}, destinationSgt={})",
+ sourceSgt, destinationSgt);
continue;
}
- syncPolicyEntities(sourceSgt, destinationSgt, policyWriter, dataAfter, peerEndpoint);
+ PolicyManagerUtil.syncPolicyEntities(sourceSgt, destinationSgt, policyWriter, dataAfter, peerEndpoint);
}
}
- // Flush
- perDeviceWriterCache.values().forEach(PolicyWriter::commitToDatastore);
- perDeviceWriterCache.clear();
-
- return Futures.immediateFuture(true);
- }
-
- private void syncPolicyEntities(final Sgt sourceSgt, final Sgt destinationSgt, PolicyWriter policyWriter,
- final Configuration dataAfter, final PeerEndpointWithPolicy peerEndpoint) {
- // Class map
- String classMapName = generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
- Match match = mapper.createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
- ClassMap classMap = mapper.createClassMap(classMapName, match);
- policyWriter.write(classMap);
-
- Map<ActionCase, Action> actionMap = getActionInDirection(dataAfter, peerEndpoint);
- if (actionMap == null || actionMap.isEmpty()) {
- return;
- }
- // Policy map entry
- List<Class> policyMapEntries = new ArrayList<>();
- if (actionMap.containsKey(ActionCase.ALLOW)) {
- policyMapEntries = resolveAllowAction();
+ if (action.equals(Create)) {
+ policyWriterPerDeviceCache.values().forEach(PolicyWriter::commitToDatastore);
+ return Futures.immediateFuture(true);
+ } else if (action.equals(Delete)) {
+ policyWriterPerDeviceCache.values().forEach(PolicyWriter::removeFromDatastore);
+ return Futures.immediateFuture(true);
}
- if (actionMap.containsKey(ActionCase.CHAIN)) {
- policyMapEntries = resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName);
- }
- policyWriter.write(policyMapEntries);
+ return Futures.immediateFuture(false);
}
- private Sgt findSgtTag(final AddressEndpointKey endpointKey,
- final List<AddressEndpointWithLocation> endpointsWithLocation) {
- if (endpointKey == null || endpointsWithLocation == null) {
- return null;
- }
- AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
- endpointsWithLocation);
- AddressEndpointWithLocationAug augmentation = endpointWithLocation.getAugmentation(AddressEndpointWithLocationAug.class);
- if (augmentation == null) {
- return null;
- }
-
- return augmentation.getSgt();
+ private ListenableFuture<Boolean> createPolicy(Configuration data) {
+ return syncPolicy(data, Create);
}
- private List<Class> resolveChainAction(final PeerEndpointWithPolicy peerEndpoint, final Sgt sourceSgt,
- final Sgt destinationSgt, final Map<ActionCase, Action> actionMap,
- final String classMapName) {
- List<Class> entries = new ArrayList<>();
- final Action action = actionMap.get(ActionCase.CHAIN);
- ServiceFunctionPath servicePath = PolicyManagerUtil.getServicePath(action.getParameterValue());
- if (servicePath == null) {
- return null;
- }
- TenantId tenantId = getTenantId(peerEndpoint);
- if (tenantId == null) {
- return null;
- }
- RenderedServicePath renderedPath = PolicyManagerUtil.createRenderedPath(servicePath, tenantId);
- entries.add(mapper.createPolicyEntry(classMapName, renderedPath, ActionCase.CHAIN));
- if (servicePath.isSymmetric()) {
- // symmetric path is in opposite direction. Roles of renderer and peer endpoint will invert
- RenderedServicePath symmetricPath = PolicyManagerUtil
- .createSymmetricRenderedPath(servicePath, renderedPath, tenantId);
- String oppositeClassMapName = generateClassMapName(destinationSgt.getValue(), sourceSgt.getValue());
- entries.add(mapper.createPolicyEntry(oppositeClassMapName, symmetricPath, ActionCase.CHAIN));
- }
- return entries;
- }
-
- private List<Class> resolveAllowAction() {
- List<Class> entries = new ArrayList<>();
- entries.add(mapper.createPolicyEntry(policyMapName, null, ActionCase.ALLOW));
- return entries;
+ private ListenableFuture<Boolean> deletePolicy(Configuration data) {
+ return syncPolicy(data, Delete);
}
- private DataBroker getAbsoluteLocationMountpoint(final RendererEndpoint endpoint,
- final List<AddressEndpointWithLocation> endpointsWithLocation) {
- if (endpoint == null || endpointsWithLocation == null) {
- return null;
- }
- AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
- endpointsWithLocation);
- final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
- final LocationType locationType = absoluteLocation.getLocationType();
- ExternalLocationCase location = (ExternalLocationCase) locationType;
- if (location == null) {
- LOG.warn("Endpoint {} does not contain info about external location",
- endpointWithLocation.getKey().toString());
- return null;
- }
- InstanceIdentifier mountPointId = location.getExternalNodeMountPoint();
- return NodeManager.getDataBrokerFromCache(mountPointId);
- }
-
- private String generateClassMapName(Integer sourceTag, Integer destinationTag) {
- return "srcTag" + sourceTag + "_dstTag" + destinationTag;
- }
-
- private Map<ActionCase, Action> getActionInDirection(Configuration data, PeerEndpointWithPolicy peer) {
- List<ResolvedRule> rulesInDirection = new ArrayList<>();
- // Find all rules in desired direction
- for (RuleGroupWithRendererEndpointParticipation ruleGroupKey :
- peer.getRuleGroupWithRendererEndpointParticipation()) {
- EndpointPolicyParticipation participation = ruleGroupKey.getRendererEndpointParticipation();
- RuleGroup ruleGroup = findRuleGroup(data, ruleGroupKey);
- if (ruleGroup == null || ruleGroup.getResolvedRule() == null) {
- continue;
- }
-
- for (ResolvedRule resolvedRule : ruleGroup.getResolvedRule()) {
- if (resolvedRule == null) {
- continue;
- }
- if (resolvedRule.getClassifier() == null || resolvedRule.getAction() == null) {
- continue;
- }
- // TODO only first Classifier used
- Classifier classifier = resolvedRule.getClassifier().get(0);
- HasDirection.Direction direction = classifier.getDirection();
- if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
- (participation.equals(CONSUMER) && direction.equals(In))) {
- rulesInDirection.add(resolvedRule);
- }
- }
- }
- if (rulesInDirection.isEmpty()) {
- return null; // TODO define drop?
- }
- // TODO use only first rule with ActionDefinitionID for now
- Map<ActionCase, Action> result = new HashMap<>();
- for (ResolvedRule resolvedRule : rulesInDirection) {
- // TODO only first action used for now
- Action action = resolvedRule.getAction().get(0);
- if (action.getActionDefinitionId() != null) {
- ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
- if (actionDefinitionId.equals(AllowActionDefinition.ID)) {
- result.put(ActionCase.ALLOW, action);
- return result;
- } else if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
- result.put(ActionCase.CHAIN, action);
- return result;
- }
- }
- }
- return null;
- }
-
- private RuleGroup findRuleGroup(final Configuration data,
- final RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation) {
- final TenantId tenantId = ruleGroupWithParticipation.getTenantId();
- final ContractId contractId = ruleGroupWithParticipation.getContractId();
- final SubjectName subjectName = ruleGroupWithParticipation.getSubjectName();
- for (RuleGroup ruleGroup : data.getRuleGroups().getRuleGroup()) {
- if (!ruleGroup.getTenantId().equals(tenantId))
- continue;
- if (!ruleGroup.getContractId().equals(contractId)) {
- continue;
- }
- if (ruleGroup.getSubjectName().equals(subjectName)) {
- return ruleGroup;
- }
- }
+ private ListenableFuture<Boolean> updatePolicy(Configuration dataAfter, Configuration dataBefore) {
+ // TODO implement
return null;
}
- private TenantId getTenantId(PeerEndpointWithPolicy peer) {
- for (RuleGroupWithRendererEndpointParticipation ruleGroup :
- peer.getRuleGroupWithRendererEndpointParticipation()) {
- if (ruleGroup.getTenantId() != null) {
- return ruleGroup.getTenantId();
- }
- }
- return null;
- }
-
-
- private void resolveFirstSffOnClassifier(final Ipv4Address nodeIpAddress,
- final Set<RenderedServicePath> firstHops) {
- // Local forwarder
- LocalBuilder localSffBuilder = new LocalBuilder();
- localSffBuilder.setIp(new IpBuilder().setAddress(nodeIpAddress).build());
-
- // TODO add sff to writer
-
- for (RenderedServicePath renderedPath : firstHops) {
- // Remote forwarder
- RenderedServicePathHop firstRenderedPathHop = renderedPath.getRenderedServicePathHop().get(0);
- SffName sffName = firstRenderedPathHop.getServiceFunctionForwarder();
-
- // Remap sff and its management ip address
- org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder serviceFunctionForwarder =
- SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName);
- String sffMgmtIpAddress = serviceFunctionForwarder.getIpMgmtAddress().getIpv4Address().getValue();
-
- ServiceFfNameBuilder remoteSffBuilder = new ServiceFfNameBuilder();
- remoteSffBuilder.setName(sffName.getValue())
- .setKey(new ServiceFfNameKey(sffName.getValue()))
- .setIp(new IpBuilder().setAddress(new Ipv4Address(sffMgmtIpAddress)).build());
- // TODO add sff to writer
-
- // Service chain
- List<Services> services = new ArrayList<>();
- ServiceTypeChoice serviceTypeChoice = sffTypeChoice(sffName.getValue());
- ServicesBuilder servicesBuilder = new ServicesBuilder();
- servicesBuilder.setServiceIndexId(renderedPath.getStartingIndex())
- .setServiceTypeChoice(serviceTypeChoice);
- List<ServicePath> servicePaths = new ArrayList<>();
- ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
- servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
- .setServicePathId(renderedPath.getPathId())
- .setConfigServiceChainPathMode(new ConfigServiceChainPathModeBuilder()
- .setServiceIndex(new ServiceIndexBuilder()
- .setServices(services).build()).build());
- servicePaths.add(servicePathBuilder.build());
- ServiceChainBuilder chainBuilder = new ServiceChainBuilder();
- chainBuilder.setServicePath(servicePaths);
- ServiceChain serviceChain = chainBuilder.build();
- // TODO add service-chain to writer
- }
- }
-
- private ServiceTypeChoice sffTypeChoice(String forwarderName) {
- ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder();
- sffBuilder.setServiceFunctionForwarder(forwarderName);
- return sffBuilder.build();
- }
-
@Override
public void close() {
//NOOP
}
+
+ enum DsAction {Create, Delete}
+
+ public enum ActionCase {ALLOW, CHAIN}
}
+++ /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.manager;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308.PolicyActionType;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Destination;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.DestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Source;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.SourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.Type;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.TypeBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.MatchBuilder;
-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.ClassBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
-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.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.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathBuilder;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
-
-class PolicyMapper {
-
- private final DataBroker dataBroker;
- private static final Logger LOG = LoggerFactory.getLogger(PolicyMapper.class);
-
- PolicyMapper(final DataBroker dataBroker) {
- this.dataBroker = Preconditions.checkNotNull(dataBroker);
- }
-
- Match createSecurityGroupMatch(int sourceTag, int destinationTag) {
- MatchBuilder matchBuilder = new MatchBuilder();
- SecurityGroupBuilder sgBuilder = new SecurityGroupBuilder();
- Source source = new SourceBuilder().setTag(sourceTag).build();
- Destination destination = new DestinationBuilder().setTag(destinationTag).build();
- sgBuilder.setSource(source)
- .setDestination(destination);
- return matchBuilder.setSecurityGroup(sgBuilder.build()).build();
- }
-
- ClassMap createClassMap(final String classMapName, Match match) {
- ClassMapBuilder cmBuilder = new ClassMapBuilder();
- cmBuilder.setName(classMapName)
- .setKey(new ClassMapKey(classMapName))
- .setMatch(match)
- .setPrematch(ClassMap.Prematch.MatchAll);
- return cmBuilder.build();
- }
-
- Class createPolicyEntry(String policyClassName, RenderedServicePath renderedPath,
- PolicyManagerImpl.ActionCase actionCase) {
- // Forward Case
- ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
- if (actionCase.equals(CHAIN) && renderedPath != null) {
- // Chain Action
- ForwardBuilder forwardBuilder = new ForwardBuilder();
- List<ServicePath> servicePaths = new ArrayList<>();
- ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
- servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
- .setServicePathId(renderedPath.getPathId())
- .setServiceIndex(renderedPath.getStartingIndex());
- servicePaths.add(servicePathBuilder.build());
- forwardBuilder.setServicePath(servicePaths);
- forwardCaseBuilder.setForward(forwardBuilder.build());
- }
- // Create Action List
- List<ActionList> actionList = new ArrayList<>();
- ActionListBuilder actionListBuilder = new ActionListBuilder();
- actionListBuilder.setKey(new ActionListKey(PolicyActionType.Forward))
- .setActionType(PolicyActionType.Forward)
- .setActionParam(forwardCaseBuilder.build());
- actionList.add(actionListBuilder.build());
- // Build class entry
- ClassBuilder policyClassBuilder = new ClassBuilder();
- policyClassBuilder.setName(new ClassNameType(policyClassName))
- .setKey(new ClassKey(new ClassNameType(policyClassName)))
- .setActionList(actionList);
- return policyClassBuilder.build();
- }
-
- public Type getServicePolicyType(String name) {
- TypeBuilder typeBuilder = new TypeBuilder();
- org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder serviceChainBuilder =
- new org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder();
- serviceChainBuilder.setName(name)
- .setDirection(org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction.Input);
- typeBuilder.setServiceChain(serviceChainBuilder.build());
- return typeBuilder.build();
- }
-
- PolicyMap policyMap(String policyMapName) {
- PolicyMapBuilder pmBuilder = new PolicyMapBuilder();
- pmBuilder.setName(policyMapName)
- .setKey(new PolicyMapKey(policyMapName))
- .setType(null);
- return pmBuilder.build();
- }
-}
package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
-import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
-import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
-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.rsp.rev140701.CreateRenderedPathInput;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
+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.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
-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.ios.rev160308.ClassNameType;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.PolicyActionType;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroup;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Destination;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.DestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Source;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.SourceBuilder;
+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.ServicePolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.TypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.MatchBuilder;
+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.ClassBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
+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.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+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.subject.feature.instance.ParameterValue;
+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.RendererEndpoint;
+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.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+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;
+
public class PolicyManagerUtil {
private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerUtil.class);
- public static ServiceFunctionPath getServicePath(List<ParameterValue> params) {
- if (params == null || params.isEmpty()) {
- LOG.error("Cannot found service path, parameter value is null");
+ 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 Map<PolicyManagerImpl.ActionCase, Action> actionMap = PolicyManagerUtil.getActionInDirection(dataAfter, peerEndpoint);
+ if (actionMap == null || actionMap.isEmpty()) {
+ return;
+ }
+ policyWriter.cache(classMap);
+
+ // Policy map entry
+ if (actionMap.containsKey(PolicyManagerImpl.ActionCase.CHAIN)) {
+ ServiceChainingUtil.resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName, policyWriter);
+ }
+ }
+
+ public static Sgt findSgtTag(final AddressEndpointKey endpointKey,
+ final List<AddressEndpointWithLocation> endpointsWithLocation) {
+ if (endpointKey == null || endpointsWithLocation == null) {
return null;
}
- Map<String, Object> paramsMap = new HashMap<>();
- for (ParameterValue value : params) {
- if (value.getName() == null)
- continue;
- if (value.getIntValue() != null) {
- paramsMap.put(value.getName().getValue(), value.getIntValue());
- } else if (value.getStringValue() != null) {
- paramsMap.put(value.getName().getValue(), value.getStringValue());
- }
+ final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
+ endpointsWithLocation);
+ final AddressEndpointWithLocationAug augmentation = endpointWithLocation.getAugmentation(AddressEndpointWithLocationAug.class);
+ if (augmentation == null) {
+ return null;
}
- String chainName = null;
- for (String name : paramsMap.keySet()) {
- if (name.equals(ChainActionDefinition.SFC_CHAIN_NAME)) {
- chainName = (String) paramsMap.get(name);
+
+ return augmentation.getSgt();
+ }
+
+ private 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();
+ sgBuilder.setDestination(destination)
+ .setSource(source);
+ final SecurityGroup securityGroup = sgBuilder.build();
+ final MatchBuilder matchBuilder = new MatchBuilder();
+ matchBuilder.setSecurityGroup(securityGroup);
+ return matchBuilder.build();
+ }
+
+ static ClassMap createClassMap(final String classMapName, final Match match) {
+ final ClassMapBuilder cmBuilder = new ClassMapBuilder();
+ cmBuilder.setName(classMapName)
+ .setKey(new ClassMapKey(classMapName))
+ .setPrematch(ClassMap.Prematch.MatchAll)
+ .setMatch(match);
+ return cmBuilder.build();
+ }
+
+ static TenantId getTenantId(final PeerEndpointWithPolicy peer) {
+ for (RuleGroupWithRendererEndpointParticipation ruleGroup :
+ peer.getRuleGroupWithRendererEndpointParticipation()) {
+ if (ruleGroup.getTenantId() != null) {
+ return ruleGroup.getTenantId();
}
}
- if (chainName == null) {
- LOG.error("Cannot found service path, chain name is null");
+ return null;
+ }
+
+ static String generateClassMapName(final int sourceTag, final int destinationTag) {
+ return "srcTag" + sourceTag + "_dstTag" + destinationTag;
+ }
+
+ static Class createPolicyEntry(final String policyClassName, final RenderedServicePath renderedPath,
+ final PolicyManagerImpl.ActionCase actionCase) {
+ // Forward Case
+ final ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
+ if (actionCase.equals(CHAIN) && renderedPath != null) {
+ // Chain Action
+ final ForwardBuilder forwardBuilder = new ForwardBuilder();
+ final List<ServicePath> servicePaths = new ArrayList<>();
+ final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
+ servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
+ .setServicePathId(renderedPath.getPathId())
+ .setServiceIndex(renderedPath.getStartingIndex());
+ servicePaths.add(servicePathBuilder.build());
+ forwardBuilder.setServicePath(servicePaths);
+ forwardCaseBuilder.setForward(forwardBuilder.build());
+ }
+ // Create Action List
+ final List<ActionList> actionList = new ArrayList<>();
+ final ActionListBuilder actionListBuilder = new ActionListBuilder();
+ actionListBuilder.setKey(new ActionListKey(PolicyActionType.Forward))
+ .setActionType(PolicyActionType.Forward)
+ .setActionParam(forwardCaseBuilder.build());
+ actionList.add(actionListBuilder.build());
+ // Build class entry
+ final ClassBuilder policyClassBuilder = new ClassBuilder();
+ policyClassBuilder.setName(new ClassNameType(policyClassName))
+ .setKey(new ClassKey(new ClassNameType(policyClassName)))
+ .setActionList(actionList);
+ return policyClassBuilder.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());
+ policyMapEntries.add(defaultBuilder.build());
+ // Construct policy map
+ final PolicyMapBuilder policyMapBuilder = new PolicyMapBuilder();
+ policyMapBuilder.setName(policyMapName)
+ .setKey(new PolicyMapKey(policyMapName))
+ .setType(PolicyMap.Type.ServiceChain)
+ .setXmlClass(policyMapEntries);
+ return policyMapBuilder.build();
+ }
+
+ public static ServicePolicy createServicePolicy(final String chainName, final ServiceChain.Direction direction) {
+ // Service Chain
+ final ServiceChainBuilder serviceChainBuilder = new ServiceChainBuilder();
+ serviceChainBuilder.setName(chainName) // Same as the policy map name
+ .setDirection(direction);
+ // Service policy
+ final TypeBuilder typeBuilder = new TypeBuilder();
+ typeBuilder.setServiceChain(serviceChainBuilder.build());
+ // Service Policy
+ ServicePolicyBuilder servicePolicyBuilder = new ServicePolicyBuilder();
+ servicePolicyBuilder.setType(typeBuilder.build());
+
+ return servicePolicyBuilder.build();
+ }
+
+ public static InstanceIdentifier getAbsoluteLocationMountpoint(final RendererEndpoint endpoint,
+ final List<AddressEndpointWithLocation> endpointsWithLocation) {
+ if (endpointsWithLocation.isEmpty()) {
return null;
}
- ServiceFunctionPath serviceFunctionPath = findServiceFunctionPath(new SfcName(chainName));
- if (serviceFunctionPath == null) {
- LOG.error("Service function path not found for name {}", chainName);
+ AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
+ endpointsWithLocation);
+ final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
+ final LocationType locationType = absoluteLocation.getLocationType();
+ ExternalLocationCase location = (ExternalLocationCase) locationType;
+ if (location == null) {
+ LOG.warn("Endpoint {} does not contain info about external location",
+ endpointWithLocation.getKey().toString());
return null;
}
- return serviceFunctionPath;
+ return location.getExternalNodeMountPoint();
}
- public static RenderedServicePath createRenderedPath(ServiceFunctionPath sfp, TenantId tenantId) {
- RenderedServicePath renderedServicePath;
- // Try to read existing RSP
- RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp");
- renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
- if (renderedServicePath != null) {
- return renderedServicePath;
+ public static String getInterfaceNameForPolicyMap(final RendererEndpoint endpoint,
+ final List<AddressEndpointWithLocation> endpointsWithLocation) {
+ if (endpoint == null || endpointsWithLocation == null) {
+ return null;
+ }
+ final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
+ endpointsWithLocation);
+ final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
+ final LocationType locationType = absoluteLocation.getLocationType();
+ final ExternalLocationCase location = (ExternalLocationCase) locationType;
+ if (location == null) {
+ LOG.warn("Endpoint {} does not contain info about external location",
+ endpointWithLocation.getKey().toString());
+ return null;
}
- LOG.info("Rendered service path with name {} not found, creating a new one ..", rspName.getValue());
- CreateRenderedPathInput input = new CreateRenderedPathInputBuilder()
- .setParentServiceFunctionPath(sfp.getName().getValue())
- .setName(rspName.getValue())
- .setSymmetric(sfp.isSymmetric())
- .build();
- renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, input);
- LOG.info("Rendered service path {} created", rspName.getValue());
- return renderedServicePath;
+ return location.getExternalNodeConnector();
}
- private static ServiceFunctionPath findServiceFunctionPath(SfcName chainName) {
- ServiceFunctionPaths allPaths = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
- for (ServiceFunctionPath serviceFunctionPath : allPaths.getServiceFunctionPath()) {
- if (serviceFunctionPath.getServiceChainName().equals(chainName)) {
- return serviceFunctionPath;
+
+ private static Map<PolicyManagerImpl.ActionCase, Action> getActionInDirection(final Configuration data, final PeerEndpointWithPolicy peer) {
+ final List<ResolvedRule> rulesInDirection = new ArrayList<>();
+ // 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;
+ }
+
+ for (ResolvedRule resolvedRule : ruleGroup.getResolvedRule()) {
+ if (resolvedRule == 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);
+ }
+ }
+ }
+ if (rulesInDirection.isEmpty()) {
+ return null;
+ }
+ // TODO use only first rule with ActionDefinitionID for now
+ final Map<PolicyManagerImpl.ActionCase, Action> result = new HashMap<>();
+ for (ResolvedRule resolvedRule : rulesInDirection) {
+ // TODO only first action used for now
+ final Action action = resolvedRule.getAction().get(0);
+ if (action.getActionDefinitionId() != null) {
+ final ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
+ // Currently only chain action is supported
+ if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
+ result.put(PolicyManagerImpl.ActionCase.CHAIN, action);
+ return result;
+ }
}
}
return null;
}
- public static RenderedServicePath createSymmetricRenderedPath(ServiceFunctionPath sfp, RenderedServicePath rsp,
- TenantId tenantId) {
- RenderedServicePath reversedRenderedPath;
- // Try to read existing RSP
- RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp-Reverse");
- reversedRenderedPath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
- if (reversedRenderedPath != null) {
- return reversedRenderedPath;
+ private static RuleGroup findRuleGroup(final Configuration data,
+ final RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation) {
+ final TenantId tenantId = ruleGroupWithParticipation.getTenantId();
+ final ContractId contractId = ruleGroupWithParticipation.getContractId();
+ final SubjectName subjectName = ruleGroupWithParticipation.getSubjectName();
+ for (RuleGroup ruleGroup : data.getRuleGroups().getRuleGroup()) {
+ if (!ruleGroup.getTenantId().equals(tenantId)) {
+ continue;
+ }
+ if (!ruleGroup.getContractId().equals(contractId)) {
+ continue;
+ }
+ if (ruleGroup.getSubjectName().equals(subjectName)) {
+ return ruleGroup;
+ }
}
- LOG.info("Reversed rendered service path with name {} not found, creating a new one ..", rspName.getValue());
- reversedRenderedPath = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
- LOG.info("Rendered service path {} created", rspName.getValue());
- return reversedRenderedPath;
+ return null;
}
}
+++ /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.util;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-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.controller.md.sal.common.api.data.TransactionCommitFailedException;
-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.ClassMapKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class PolicyWriter {
-
- private static final Logger LOG = LoggerFactory.getLogger(PolicyWriter.class);
-
- private final DataBroker mountpoint;
- // Local cache
- private List<ClassMap> classMapEntries;
- private List<Class> policyMapEntries;
-
- public PolicyWriter(final DataBroker dataBroker) {
- mountpoint = Preconditions.checkNotNull(dataBroker);
- classMapEntries = new ArrayList<>();
- policyMapEntries = new ArrayList<>();
- }
-
- public void write(ClassMap classMap) {
- classMapEntries.add(classMap);
- }
-
- public void write(List<Class> policyMapEntries) {
- this.policyMapEntries.addAll(policyMapEntries);
- }
-
- public void commitToDatastore() {
- // create and write service-policy
- // create and write policy-map with policyMapEntries
- // create and write class-maps
-
- WriteTransaction wtx = mountpoint.newWriteOnlyTransaction();
- // Class maps
- for (ClassMap entry : classMapEntries) {
- InstanceIdentifier<ClassMap> iid = classMapInstanceIdentifier(entry);
- try {
- wtx.merge(LogicalDatastoreType.CONFIGURATION, iid, entry, true);
- CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
- submitFuture.checkedGet();
- // Clear cache
- classMapEntries.clear();
- } catch (TransactionCommitFailedException e) {
- LOG.error("Write transaction failed to {}", e.getMessage());
- } catch (Exception e) {
- LOG.error("Failed to .. {}", e.getMessage());
- }
- }
- }
-
- private InstanceIdentifier<ClassMap> classMapInstanceIdentifier(ClassMap classMap) {
- return InstanceIdentifier.builder(Native.class)
- .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
- }
-}
--- /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.util;
+
+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.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.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.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.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
+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.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.ServiceChain;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChainBuilder;
+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.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathBuilder;
+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.LocalBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.ConfigServiceChainPathModeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.ServiceIndexBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.Services;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.ServicesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.ServiceTypeChoice;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.service.type.choice.ServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.service.type.choice.ServiceFunctionForwarderBuilder;
+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;
+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.resolved.policy.rev150828.has.actions.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ServiceChainingUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ServiceChainingUtil.class);
+
+ static ServiceFunctionPath getServicePath(final List<ParameterValue> params) {
+ if (params == null || params.isEmpty()) {
+ LOG.error("Cannot found service path, parameter value is null");
+ return null;
+ }
+ final Map<String, Object> paramsMap = new HashMap<>();
+ for (ParameterValue value : params) {
+ if (value.getName() == null)
+ continue;
+ if (value.getIntValue() != null) {
+ paramsMap.put(value.getName().getValue(), value.getIntValue());
+ } else if (value.getStringValue() != null) {
+ paramsMap.put(value.getName().getValue(), value.getStringValue());
+ }
+ }
+ String chainName = null;
+ for (String name : paramsMap.keySet()) {
+ if (name.equals(ChainActionDefinition.SFC_CHAIN_NAME)) {
+ chainName = (String) paramsMap.get(name);
+ }
+ }
+ if (chainName == null) {
+ LOG.error("Cannot found service path, chain name is null");
+ return null;
+ }
+ final ServiceFunctionPath serviceFunctionPath = findServiceFunctionPath(new SfcName(chainName));
+ if (serviceFunctionPath == null) {
+ LOG.error("Service function path not found for name {}", chainName);
+ return null;
+ }
+ 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<>();
+ final Action action = actionMap.get(PolicyManagerImpl.ActionCase.CHAIN);
+ final ServiceFunctionPath servicePath = ServiceChainingUtil.getServicePath(action.getParameterValue());
+ if (servicePath == null) {
+ return;
+ }
+ final TenantId tenantId = PolicyManagerUtil.getTenantId(peerEndpoint);
+ if (tenantId == null) {
+ return;
+ }
+ final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(servicePath, tenantId);
+ // Create appropriate service path && remote forwarder
+ setSfcPart(renderedPath, policyWriter);
+
+ entries.add(PolicyManagerUtil.createPolicyEntry(classMapName, renderedPath, PolicyManagerImpl.ActionCase.CHAIN));
+ if (servicePath.isSymmetric()) {
+ // symmetric path is in opposite direction. Roles of renderer and peer endpoint will invert
+ RenderedServicePath symmetricPath = ServiceChainingUtil
+ .createSymmetricRenderedPath(servicePath, renderedPath, tenantId);
+ final String oppositeClassMapName = PolicyManagerUtil.generateClassMapName(destinationSgt.getValue(), sourceSgt.getValue());
+ entries.add(PolicyManagerUtil.createPolicyEntry(oppositeClassMapName, symmetricPath, PolicyManagerImpl.ActionCase.CHAIN));
+ }
+ policyWriter.cache(entries);
+ }
+
+ static RenderedServicePath createRenderedPath(final ServiceFunctionPath sfp, final TenantId tenantId) {
+ RenderedServicePath renderedServicePath;
+ // Try to read existing RSP
+ final RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp");
+ renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+ if (renderedServicePath != null) {
+ return renderedServicePath;
+ }
+ LOG.info("Rendered service path with name {} not found, creating a new one ..", rspName.getValue());
+ final CreateRenderedPathInput input = new CreateRenderedPathInputBuilder()
+ .setParentServiceFunctionPath(sfp.getName().getValue())
+ .setName(rspName.getValue())
+ .setSymmetric(sfp.isSymmetric())
+ .build();
+ renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, input);
+ LOG.info("Rendered service path {} created", rspName.getValue());
+ return renderedServicePath;
+ }
+
+ static RenderedServicePath createSymmetricRenderedPath(final ServiceFunctionPath sfp, final RenderedServicePath rsp,
+ final TenantId tenantId) {
+ RenderedServicePath reversedRenderedPath;
+ // Try to read existing RSP
+ final RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp-Reverse");
+ 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);
+ LOG.info("Rendered service path {} created", rspName.getValue());
+ return reversedRenderedPath;
+ }
+
+ /**
+ * Method checks up, whether a {@link Local} Service Function Forwarder is present on device or not.
+ *
+ * @param mountpoint used to access specific device
+ * @return true if Local Forwarder is present, false otherwise
+ */
+ 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 {
+ Optional<Local> optionalLocalSff = submitFuture.checkedGet();
+ return optionalLocalSff.isPresent();
+ } catch (ReadFailedException e) {
+ LOG.warn("Read transaction failed to {} ", e);
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ return false;
+ }
+
+ /**
+ * Method checks up, if some {@link ServicePath} is present on device.
+ *
+ * @param mountpoint used to access specific device
+ * @return true if service chain does not exist, is null or does not contain any service path. False otherwise
+ */
+ 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,
+ serviceChainIid);
+ try {
+ Optional<ServiceChain> optionalServiceChain = submitFuture.checkedGet();
+ if (optionalServiceChain.isPresent()) {
+ ServiceChain chain = optionalServiceChain.get();
+ return chain == null || chain.getServicePath() == null || chain.getServicePath().isEmpty();
+ } else {
+ return true;
+ }
+ } catch (ReadFailedException e) {
+ LOG.warn("Read transaction failed to {} ", e);
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ return false;
+ }
+
+ private static ServiceFunctionPath findServiceFunctionPath(final SfcName chainName) {
+ final ServiceFunctionPaths allPaths = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
+ for (ServiceFunctionPath serviceFunctionPath : allPaths.getServiceFunctionPath()) {
+ if (serviceFunctionPath.getServiceChainName().equals(chainName)) {
+ return serviceFunctionPath;
+ }
+ }
+ return null;
+ }
+
+ private static void setSfcPart(final RenderedServicePath renderedServicePath, PolicyWriter policyWriter) {
+ if (renderedServicePath != null && renderedServicePath.getRenderedServicePathHop() != null &&
+ !renderedServicePath.getRenderedServicePathHop().isEmpty()) {
+ final RenderedServicePathHop firstHop = renderedServicePath.getRenderedServicePathHop().get(0);
+ if (firstHop == null) {
+ LOG.error("Rendered service path {} does not contain any hop", renderedServicePath.getName().getValue());
+ return;
+ }
+ final SffName sffName = firstHop.getServiceFunctionForwarder();
+ final ServiceFunctionForwarder serviceFunctionForwarder = SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName);
+ if (serviceFunctionForwarder == null) {
+ LOG.error("Sff with name {} does not exist", sffName.getValue());
+ return;
+ }
+ // 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())) {
+ final LocalBuilder localSffBuilder = new LocalBuilder();
+ localSffBuilder.setIp(new IpBuilder().setAddress(new Ipv4Address(policyWriter.getManagementIpAddress()))
+ .build());
+ policyWriter.cache(localSffBuilder.build());
+ } else {
+ LOG.info("Local forwarder for node {} is already created", policyWriter.getCurrentNodeId());
+ }
+ // Set up choice. If remote, this choice is overwritten
+ ServiceTypeChoice serviceTypeChoice = functionTypeChoice(firstHop.getServiceFunctionName().getValue());
+ // Remote case
+ if (serviceFunctionForwarder.getIpMgmtAddress() == null
+ || serviceFunctionForwarder.getIpMgmtAddress().getIpv4Address() == null) {
+ LOG.error("Cannot create remote forwarder, SFF {} does not contain management ip address",
+ sffName.getValue());
+ return;
+ }
+ final String sffMgmtIpAddress = serviceFunctionForwarder.getIpMgmtAddress().getIpv4Address().getValue();
+ // If local SFF has the same ip as first hop sff, it's the same SFF; no need to create a remote one
+ if (!sffMgmtIpAddress.equals(policyWriter.getManagementIpAddress())) {
+ final ServiceFfNameBuilder remoteSffBuilder = new ServiceFfNameBuilder();
+ remoteSffBuilder.setName(sffName.getValue())
+ .setKey(new ServiceFfNameKey(sffName.getValue()))
+ .setIp(new IpBuilder().setAddress(new Ipv4Address(sffMgmtIpAddress)).build());
+ policyWriter.cache(remoteSffBuilder.build());
+ serviceTypeChoice = forwarderTypeChoice(sffName.getValue());
+ }
+
+ // Service chain
+ final List<Services> services = new ArrayList<>();
+ final ServicesBuilder servicesBuilder = new ServicesBuilder();
+ servicesBuilder.setServiceIndexId(renderedServicePath.getStartingIndex())
+ .setServiceTypeChoice(serviceTypeChoice);
+ final List<ServicePath> servicePaths = new ArrayList<>();
+ final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
+ servicePathBuilder.setKey(new ServicePathKey(renderedServicePath.getPathId()))
+ .setServicePathId(renderedServicePath.getPathId())
+ .setConfigServiceChainPathMode(new ConfigServiceChainPathModeBuilder()
+ .setServiceIndex(new ServiceIndexBuilder()
+ .setServices(services).build()).build());
+ servicePaths.add(servicePathBuilder.build());
+ final ServiceChainBuilder chainBuilder = new ServiceChainBuilder();
+ chainBuilder.setServicePath(servicePaths);
+ final ServiceChain serviceChain = chainBuilder.build();
+ policyWriter.cache(serviceChain);
+ }
+ }
+
+ private static ServiceTypeChoice forwarderTypeChoice(final String forwarderName) {
+ final ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder();
+ sffBuilder.setServiceFunctionForwarder(forwarderName);
+ return sffBuilder.build();
+ }
+
+ private static ServiceTypeChoice functionTypeChoice(final String functionName) {
+ final ServiceFunctionBuilder sfBuilder = new ServiceFunctionBuilder();
+ sfBuilder.setServiceFunction(functionName);
+ return sfBuilder.build();
+ }
+
+}
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer;
import com.google.common.util.concurrent.CheckedFuture;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
--- /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.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PolicyWriter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PolicyWriter.class);
+
+ private final DataBroker mountpoint;
+ // Local cache
+ private final List<ClassMap> classMapEntries;
+ private final List<Class> policyMapEntries;
+ private final List<ServiceFfName> remoteForwarders;
+ private final List<ServiceChain> serviceChains;
+ private final NodeId nodeId;
+ private final String interfaceName;
+ private final String policyMapName;
+ private final String managementIpAddress;
+ private Local localForwarder;
+
+ public PolicyWriter(final DataBroker dataBroker, final String interfaceName, final String ipAddress,
+ final String policyMapName, final NodeId nodeId) {
+ classMapEntries = new ArrayList<>();
+ policyMapEntries = new ArrayList<>();
+ remoteForwarders = new ArrayList<>();
+ serviceChains = new ArrayList<>();
+
+ this.nodeId = Preconditions.checkNotNull(nodeId);
+ mountpoint = Preconditions.checkNotNull(dataBroker);
+ managementIpAddress = Preconditions.checkNotNull(ipAddress);
+ this.interfaceName = Preconditions.checkNotNull(interfaceName);
+ this.policyMapName = Preconditions.checkNotNull(policyMapName);
+ }
+
+ public void cache(ClassMap classMap) {
+ classMapEntries.add(classMap);
+ }
+
+ public void cache(List<Class> policyMapEntries) {
+ this.policyMapEntries.addAll(policyMapEntries);
+ }
+
+ public void cache(Local localForwarder) {
+ this.localForwarder = localForwarder;
+ }
+
+ public void cache(ServiceFfName remoteForwarder) {
+ remoteForwarders.add(remoteForwarder);
+ }
+
+ public void cache(ServiceChain serviceChain) {
+ serviceChains.add(serviceChain);
+ }
+
+ public void 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());
+ }
+ }
+
+ try {
+ CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+ submitFuture.checkedGet();
+ // Clear cache
+ } catch (TransactionCommitFailedException e) {
+ LOG.error("Write transaction failed to {}", e.getMessage());
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ }
+
+ public void 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());
+ }
+
+ try {
+ CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+ submitFuture.checkedGet();
+ } catch (TransactionCommitFailedException e) {
+ LOG.error("Write transaction failed to {}", e.getMessage());
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ }
+
+ 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 String getManagementIpAddress() {
+ return managementIpAddress;
+ }
+
+ public DataBroker getCurrentMountpoint() {
+ return mountpoint;
+ }
+
+ public NodeId getCurrentNodeId() {
+ return nodeId;
+ }
+}
+++ /dev/null
-module ietf-inet-types {
-
- namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
- prefix "inet";
-
- organization
- "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
-
- contact
- "WG Web: <http://tools.ietf.org/wg/netmod/>
- WG List: <mailto:netmod@ietf.org>
-
- WG Chair: David Kessens
- <mailto:david.kessens@nsn.com>
-
- WG Chair: Juergen Schoenwaelder
- <mailto:j.schoenwaelder@jacobs-university.de>
-
- Editor: Juergen Schoenwaelder
- <mailto:j.schoenwaelder@jacobs-university.de>";
-
- description
- "This module contains a collection of generally useful derived
- YANG data types for Internet addresses and related things.
-
- Copyright (c) 2013 IETF Trust and the persons identified as
- authors of the code. All rights reserved.
-
- Redistribution and use in source and binary forms, with or
- without modification, is permitted pursuant to, and subject
- to the license terms contained in, the Simplified BSD License
- set forth in Section 4.c of the IETF Trust's Legal Provisions
- Relating to IETF Documents
- (http://trustee.ietf.org/license-info).
-
- This version of this YANG module is part of RFC 6991; see
- the RFC itself for full legal notices.";
-
- revision 2013-07-15 {
- description
- "This revision adds the following new data types:
- - ip-address-no-zone
- - ipv4-address-no-zone
- - ipv6-address-no-zone";
- reference
- "RFC 6991: Common YANG Data Types";
- }
-
- revision 2010-09-24 {
- description
- "Initial revision.";
- reference
- "RFC 6021: Common YANG Data Types";
- }
-
- /*** collection of types related to protocol fields ***/
-
- typedef ip-version {
- type enumeration {
- enum unknown {
- value "0";
- description
- "An unknown or unspecified version of the Internet
- protocol.";
- }
- enum ipv4 {
- value "1";
- description
- "The IPv4 protocol as defined in RFC 791.";
- }
- enum ipv6 {
- value "2";
- description
- "The IPv6 protocol as defined in RFC 2460.";
- }
- }
- description
- "This value represents the version of the IP protocol.
-
- In the value set and its semantics, this type is equivalent
- to the InetVersion textual convention of the SMIv2.";
- reference
- "RFC 791: Internet Protocol
- RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
- RFC 4001: Textual Conventions for Internet Network Addresses";
- }
-
- typedef dscp {
- type uint8 {
- range "0..63";
- }
- description
- "The dscp type represents a Differentiated Services Code Point
- that may be used for marking packets in a traffic stream.
- In the value set and its semantics, this type is equivalent
- to the Dscp textual convention of the SMIv2.";
- reference
- "RFC 3289: Management Information Base for the Differentiated
- Services Architecture
- RFC 2474: Definition of the Differentiated Services Field
- (DS Field) in the IPv4 and IPv6 Headers
- RFC 2780: IANA Allocation Guidelines For Values In
- the Internet Protocol and Related Headers";
- }
-
- typedef ipv6-flow-label {
- type uint32 {
- range "0..1048575";
- }
- description
- "The ipv6-flow-label type represents the flow identifier or Flow
- Label in an IPv6 packet header that may be used to
- discriminate traffic flows.
-
- In the value set and its semantics, this type is equivalent
- to the IPv6FlowLabel textual convention of the SMIv2.";
- reference
- "RFC 3595: Textual Conventions for IPv6 Flow Label
- RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
- }
-
- typedef port-number {
- type uint16 {
- range "0..65535";
- }
- description
- "The port-number type represents a 16-bit port number of an
- Internet transport-layer protocol such as UDP, TCP, DCCP, or
- SCTP. Port numbers are assigned by IANA. A current list of
- all assignments is available from <http://www.iana.org/>.
-
- Note that the port number value zero is reserved by IANA. In
- situations where the value zero does not make sense, it can
- be excluded by subtyping the port-number type.
- In the value set and its semantics, this type is equivalent
- to the InetPortNumber textual convention of the SMIv2.";
- reference
- "RFC 768: User Datagram Protocol
- RFC 793: Transmission Control Protocol
- RFC 4960: Stream Control Transmission Protocol
- RFC 4340: Datagram Congestion Control Protocol (DCCP)
- RFC 4001: Textual Conventions for Internet Network Addresses";
- }
-
- /*** collection of types related to autonomous systems ***/
-
- typedef as-number {
- type uint32;
- description
- "The as-number type represents autonomous system numbers
- which identify an Autonomous System (AS). An AS is a set
- of routers under a single technical administration, using
- an interior gateway protocol and common metrics to route
- packets within the AS, and using an exterior gateway
- protocol to route packets to other ASes. IANA maintains
- the AS number space and has delegated large parts to the
- regional registries.
-
- Autonomous system numbers were originally limited to 16
- bits. BGP extensions have enlarged the autonomous system
- number space to 32 bits. This type therefore uses an uint32
- base type without a range restriction in order to support
- a larger autonomous system number space.
-
- In the value set and its semantics, this type is equivalent
- to the InetAutonomousSystemNumber textual convention of
- the SMIv2.";
- reference
- "RFC 1930: Guidelines for creation, selection, and registration
- of an Autonomous System (AS)
- RFC 4271: A Border Gateway Protocol 4 (BGP-4)
- RFC 4001: Textual Conventions for Internet Network Addresses
- RFC 6793: BGP Support for Four-Octet Autonomous System (AS)
- Number Space";
- }
-
- /*** collection of types related to IP addresses and hostnames ***/
-
- typedef ip-address {
- type union {
- type inet:ipv4-address;
- type inet:ipv6-address;
- }
- description
- "The ip-address type represents an IP address and is IP
- version neutral. The format of the textual representation
- implies the IP version. This type supports scoped addresses
- by allowing zone identifiers in the address format.";
- reference
- "RFC 4007: IPv6 Scoped Address Architecture";
- }
-
- typedef ipv4-address {
- type string {
- pattern
- '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
- + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
- + '(%[\p{N}\p{L}]+)?';
- }
- description
- "The ipv4-address type represents an IPv4 address in
- dotted-quad notation. The IPv4 address may include a zone
- index, separated by a % sign.
-
- The zone index is used to disambiguate identical address
- values. For link-local addresses, the zone index will
- typically be the interface index number or the name of an
- interface. If the zone index is not present, the default
- zone of the device will be used.
-
- The canonical format for the zone index is the numerical
- format";
- }
-
- typedef ipv6-address {
- type string {
- pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
- + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
- + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
- + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
- + '(%[\p{N}\p{L}]+)?';
- pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
- + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
- + '(%.+)?';
- }
- description
- "The ipv6-address type represents an IPv6 address in full,
- mixed, shortened, and shortened-mixed notation. The IPv6
- address may include a zone index, separated by a % sign.
-
- The zone index is used to disambiguate identical address
- values. For link-local addresses, the zone index will
- typically be the interface index number or the name of an
- interface. If the zone index is not present, the default
- zone of the device will be used.
-
-
-
- The canonical format of IPv6 addresses uses the textual
- representation defined in Section 4 of RFC 5952. The
- canonical format for the zone index is the numerical
- format as described in Section 11.2 of RFC 4007.";
- reference
- "RFC 4291: IP Version 6 Addressing Architecture
- RFC 4007: IPv6 Scoped Address Architecture
- RFC 5952: A Recommendation for IPv6 Address Text
- Representation";
- }
-
- typedef ip-address-no-zone {
- type union {
- type inet:ipv4-address-no-zone;
- type inet:ipv6-address-no-zone;
- }
- description
- "The ip-address-no-zone type represents an IP address and is
- IP version neutral. The format of the textual representation
- implies the IP version. This type does not support scoped
- addresses since it does not allow zone identifiers in the
- address format.";
- reference
- "RFC 4007: IPv6 Scoped Address Architecture";
- }
-
- typedef ipv4-address-no-zone {
- type inet:ipv4-address {
- pattern '[0-9\.]*';
- }
- description
- "An IPv4 address without a zone index. This type, derived from
- ipv4-address, may be used in situations where the zone is
- known from the context and hence no zone index is needed.";
- }
-
- typedef ipv6-address-no-zone {
- type inet:ipv6-address {
- pattern '[0-9a-fA-F:\.]*';
- }
- description
- "An IPv6 address without a zone index. This type, derived from
- ipv6-address, may be used in situations where the zone is
- known from the context and hence no zone index is needed.";
- reference
- "RFC 4291: IP Version 6 Addressing Architecture
- RFC 4007: IPv6 Scoped Address Architecture
- RFC 5952: A Recommendation for IPv6 Address Text
- Representation";
- }
-
- typedef ip-prefix {
- type union {
- type inet:ipv4-prefix;
- type inet:ipv6-prefix;
- }
- description
- "The ip-prefix type represents an IP prefix and is IP
- version neutral. The format of the textual representations
- implies the IP version.";
- }
-
- typedef ipv4-prefix {
- type string {
- pattern
- '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
- + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
- + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
- }
- description
- "The ipv4-prefix type represents an IPv4 address prefix.
- The prefix length is given by the number following the
- slash character and must be less than or equal to 32.
-
- A prefix length value of n corresponds to an IP address
- mask that has n contiguous 1-bits from the most
- significant bit (MSB) and all other bits set to 0.
-
- The canonical format of an IPv4 prefix has all bits of
- the IPv4 address set to zero that are not part of the
- IPv4 prefix.";
- }
-
- typedef ipv6-prefix {
- type string {
- pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
- + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
- + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
- + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
- + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
- pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
- + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
- + '(/.+)';
- }
-
-
- description
- "The ipv6-prefix type represents an IPv6 address prefix.
- The prefix length is given by the number following the
- slash character and must be less than or equal to 128.
-
- A prefix length value of n corresponds to an IP address
- mask that has n contiguous 1-bits from the most
- significant bit (MSB) and all other bits set to 0.
-
- The IPv6 address should have all bits that do not belong
- to the prefix set to zero.
-
- The canonical format of an IPv6 prefix has all bits of
- the IPv6 address set to zero that are not part of the
- IPv6 prefix. Furthermore, the IPv6 address is represented
- as defined in Section 4 of RFC 5952.";
- reference
- "RFC 5952: A Recommendation for IPv6 Address Text
- Representation";
- }
-
- /*** collection of domain name and URI types ***/
-
- typedef domain-name {
- type string {
- pattern
- '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
- + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
- + '|\.';
- length "1..253";
- }
- description
- "The domain-name type represents a DNS domain name. The
- name SHOULD be fully qualified whenever possible.
-
- Internet domain names are only loosely specified. Section
- 3.5 of RFC 1034 recommends a syntax (modified in Section
- 2.1 of RFC 1123). The pattern above is intended to allow
- for current practice in domain name use, and some possible
- future expansion. It is designed to hold various types of
- domain names, including names used for A or AAAA records
- (host names) and other records, such as SRV records. Note
- that Internet host names have a stricter syntax (described
- in RFC 952) than the DNS recommendations in RFCs 1034 and
- 1123, and that systems that want to store host names in
- schema nodes using the domain-name type are recommended to
- adhere to this stricter standard to ensure interoperability.
-
- The encoding of DNS names in the DNS protocol is limited
- to 255 characters. Since the encoding consists of labels
- prefixed by a length bytes and there is a trailing NULL
- byte, only 253 characters can appear in the textual dotted
- notation.
-
- The description clause of schema nodes using the domain-name
- type MUST describe when and how these names are resolved to
- IP addresses. Note that the resolution of a domain-name value
- may require to query multiple DNS records (e.g., A for IPv4
- and AAAA for IPv6). The order of the resolution process and
- which DNS record takes precedence can either be defined
- explicitly or may depend on the configuration of the
- resolver.
-
- Domain-name values use the US-ASCII encoding. Their canonical
- format uses lowercase US-ASCII characters. Internationalized
- domain names MUST be A-labels as per RFC 5890.";
- reference
- "RFC 952: DoD Internet Host Table Specification
- RFC 1034: Domain Names - Concepts and Facilities
- RFC 1123: Requirements for Internet Hosts -- Application
- and Support
- RFC 2782: A DNS RR for specifying the location of services
- (DNS SRV)
- RFC 5890: Internationalized Domain Names in Applications
- (IDNA): Definitions and Document Framework";
- }
-
- typedef host {
- type union {
- type inet:ip-address;
- type inet:domain-name;
- }
- description
- "The host type represents either an IP address or a DNS
- domain name.";
- }
-
- typedef uri {
- type string;
- description
- "The uri type represents a Uniform Resource Identifier
- (URI) as defined by STD 66.
-
- Objects using the uri type MUST be in US-ASCII encoding,
- and MUST be normalized as described by RFC 3986 Sections
- 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary
- percent-encoding is removed, and all case-insensitive
- characters are set to lowercase except for hexadecimal
- digits, which are normalized to uppercase as described in
- Section 6.2.2.1.
-
- The purpose of this normalization is to help provide
- unique URIs. Note that this normalization is not
- sufficient to provide uniqueness. Two URIs that are
- textually distinct after this normalization may still be
- equivalent.
-
- Objects using the uri type may restrict the schemes that
- they permit. For example, 'data:' and 'urn:' schemes
- might not be appropriate.
-
- A zero-length URI is not a valid URI. This can be used to
- express 'URI absent' where required.
-
- In the value set and its semantics, this type is equivalent
- to the Uri SMIv2 textual convention defined in RFC 5017.";
- reference
- "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
- RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
- Group: Uniform Resource Identifiers (URIs), URLs,
- and Uniform Resource Names (URNs): Clarifications
- and Recommendations
- RFC 5017: MIB Textual Conventions for Uniform Resource
- Identifiers (URIs)";
- }
-
-}
\ No newline at end of file
}
}
- grouping config-service-chain-grouping {
- leaf description {
- tailf:info "Service function forwarder description";
- description "Service function forwarder description";
- tailf:cli-multi-value;
- type string {
- tailf:info "LINE;;Up to 256 characters describing this " + "service function forwarder";
- length "1..256";
- }
- }
- container ip {
- tailf:info "IP address for Service Function Forwarder";
- description "IP address for Service Function Forwarder";
- leaf address {
- tailf:info "Set IPv4 address";
- description "Set IPv4 address";
- type inet:ipv4-address {
- tailf:info "A.B.C.D;;IP address of Service Function Forwarder";
- }
- }
- }
- }
-
grouping interface-atm-grouping {
// Removed body
}
/// service-chain
/// ========================================================================
+ grouping config-service-chain-grouping {
+ leaf description {
+ tailf:info "Service function forwarder description";
+ description "Service function forwarder description";
+ tailf:cli-multi-value;
+ type string {
+ tailf:info "LINE;;Up to 256 characters describing this " + "service function forwarder";
+ length "1..256";
+ }
+ }
+ container ip {
+ tailf:info "IP address for Service Function Forwarder";
+ description "IP address for Service Function Forwarder";
+ leaf address {
+ tailf:info "Set IPv4 address";
+ description "Set IPv4 address";
+ type inet:ipv4-address {
+ tailf:info "A.B.C.D;;IP address of Service Function Forwarder";
+ }
+ }
+ }
+ }
+
container service-chain {
tailf:info "Service Chain mode";
description "Service Chain mode";
--- /dev/null
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+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.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+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.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import javax.annotation.Nonnull;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connected;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connecting;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.UnableToConnect;
+
+
+public class NodeManagerTest extends CustomDataBrokerTest {
+
+ private final NodeId NODE_NAME = new NodeId("testNode");
+ private final TopologyId TOPOLOGY_ID = new TopologyId("topology-netconf");
+ private final Ipv4Address IPv4_ADDRESS = new Ipv4Address("174.25.75.11");
+ private NodeManager nodeManager;
+ private DataBroker dataBroker;
+
+ @Nonnull
+ @Override
+ public Collection<java.lang.Class<?>> getClassesFromModules() {
+ return Arrays.asList(Renderers.class, NetworkTopology.class, NetconfNode.class);
+ }
+
+ @Before
+ public void init() {
+ dataBroker = getDataBroker();
+ BindingAwareBroker.ProviderContext context = mock(BindingAwareBroker.ProviderContext.class);
+ MountPointService mountPointService = mock(MountPointService.class);
+ when(context.getSALService(any())).thenReturn(mountPointService);
+ nodeManager = new NodeManager(dataBroker, context);
+ }
+
+ @Test
+ public void testRegisterNewNode_connectingCase() throws Exception {
+ Node testNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(testNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ // Create Cases
+
+ @Test
+ public void testRegisterNewNode_connectedCaseNoIpAddress() throws Exception {
+ Node testNode = createNode(Connected, null, NODE_NAME, Capabilities.None);
+ nodeManager.syncNodes(testNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testRegisterNewNode_connectedCaseNullCapabilities() throws Exception {
+ Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.None);
+ nodeManager.syncNodes(testNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testRegisterNewNode_connectedCasePartialCapabilities() throws Exception {
+ Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial);
+ nodeManager.syncNodes(testNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testRegisterNewNode_connectedCaseFullCapabilities() throws Exception {
+ Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(testNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertNotNull(result);
+ assertTrue(result.size() == 1);
+ }
+
+ @Test
+ public void testRegisterNewNode_unableToConnectCase() throws Exception {
+ Node testNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(testNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testUpdateNode_fromConnectingToConnected() throws Exception {
+ Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(oldNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ assertNotNull(result);
+ assertTrue(result.size() == 1);
+ }
+
+ // Update Cases
+
+ @Test
+ public void testUpdateNode_fromConnectingToUnableToConnect() throws Exception {
+ Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ Node newNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(oldNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testUpdateNode_fromConnectedToConnecting() throws Exception {
+ Node oldNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ Node newNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(oldNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertNotNull(result);
+ assertTrue(result.size() == 1);
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testUpdateNode_fromConnectedToUnableToConnect() throws Exception {
+ Node oldNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ Node newNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(oldNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertNotNull(result);
+ assertTrue(result.size() == 1);
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testUpdateNode_fromUnableToConnectToConnecting() throws Exception {
+ Node oldNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ Node newNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(oldNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testUpdateNode_fromUnableToConnectToConnected() throws Exception {
+ Node oldNode = createNode(UnableToConnect, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(oldNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ assertNotNull(result);
+ assertTrue(result.size() == 1);
+ }
+
+ @Test
+ public void testUpdateNode_advancedCase() throws Exception {
+ Node oldNode = createNode(Connecting, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial);
+ nodeManager.syncNodes(oldNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ // One node is connecting, partial capabilities = empty list
+ assertTrue(result.isEmpty());
+ Node newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Partial);
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ // Update 1.: node is connected, still partial capabilities = empty list
+ assertTrue(result.isEmpty());
+ oldNode = newNode;
+ newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ // Update 2.: node is connected, full capabilities = 1 entry in list
+ assertNotNull(result);
+ assertTrue(result.size() == 1);
+ oldNode = newNode;
+ newNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.None);
+ nodeManager.syncNodes(newNode, oldNode);
+ result = rendererNodesReader();
+ // Update 3.: node remains connected, but without capabilities = empty list
+ assertTrue(result.isEmpty());
+ }
+
+ // Advanced update Case
+
+ @Test
+ public void testRemoveNode() throws Exception {
+ Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ nodeManager.syncNodes(testNode, null);
+ List<RendererNode> result = rendererNodesReader();
+ assertNotNull(result);
+ assertTrue(result.size() == 1);
+ nodeManager.syncNodes(null, testNode);
+ result = rendererNodesReader();
+ assertTrue(result.isEmpty());
+ }
+
+ // Remove Case
+
+ @Test
+ public void getNodeManagementIpByMountPointIid_absentNode() {
+ NodeId testNodeId = new NodeId(NODE_NAME);
+ InstanceIdentifier mountpointIid = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID)))
+ .child(Node.class, new NodeKey(testNodeId)).build();
+ String ipAddress = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
+ assertNull(ipAddress);
+ }
+
+ @Test
+ public void getNodeManagementIpByMountPointIid_ipV4Case() throws Exception {
+ // Put node
+ Node testNode = createNode(Connected, IPv4_ADDRESS, NODE_NAME, Capabilities.Full);
+ InstanceIdentifier<Node> testNodeIid = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID)))
+ .child(Node.class, new NodeKey(testNode.getNodeId())).build();
+ ReadWriteTransaction rwt = dataBroker.newReadWriteTransaction();
+ rwt.put(LogicalDatastoreType.CONFIGURATION, testNodeIid, testNode, true);
+ rwt.submit().checkedGet();
+ InstanceIdentifier mountpointIid = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID)))
+ .child(Node.class, new NodeKey(NODE_NAME)).build();
+ String result = nodeManager.getNodeManagementIpByMountPointIid(mountpointIid);
+ assertEquals(IPv4_ADDRESS.getValue(), result);
+ }
+
+ private Node createNode(final NetconfNodeConnectionStatus.ConnectionStatus connectionStatus,
+ final Ipv4Address ipAddress,
+ final NodeId nodeName,
+ final Capabilities choice) {
+ AvailableCapabilities capabilities = null;
+ switch (choice) {
+ case None: {
+ capabilities = emptyCapabilities();
+ break;
+ }
+ case Partial: {
+ capabilities = partialCapabilities();
+ break;
+ }
+ case Full: {
+ capabilities = fullCapabilities();
+ }
+ }
+ // Netconf node
+ NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder();
+ netconfNodeBuilder.setConnectionStatus(connectionStatus)
+ .setAvailableCapabilities(capabilities)
+ .setHost(new Host(new IpAddress(ipAddress)));
+ // Node
+ NodeBuilder nodeBuilder = new NodeBuilder();
+ nodeBuilder.setNodeId(new NodeId(nodeName))
+ .setKey(new NodeKey(new NodeId(nodeName)))
+ .addAugmentation(NetconfNode.class, netconfNodeBuilder.build());
+ return nodeBuilder.build();
+ }
+
+ // Utility methods
+
+ private List<RendererNode> rendererNodesReader() throws Exception {
+ InstanceIdentifier<Renderers> renderersIid =
+ InstanceIdentifier.builder(Renderers.class).build();
+ ReadWriteTransaction rwt = dataBroker.newReadWriteTransaction();
+ CheckedFuture<Optional<Renderers>, ReadFailedException> submitFuture =
+ rwt.read(LogicalDatastoreType.OPERATIONAL, renderersIid);
+ Optional<Renderers> optionalRenderers = submitFuture.checkedGet();
+ if (optionalRenderers.isPresent()) {
+ Renderers renderers = optionalRenderers.get();
+ if (renderers != null && renderers.getRenderer() != null && !renderers.getRenderer().isEmpty()) {
+ RendererNodes writtenNodes = renderers.getRenderer().get(0).getRendererNodes();
+ if (writtenNodes != null) {
+ return writtenNodes.getRendererNode();
+ }
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private AvailableCapabilities emptyCapabilities() {
+ AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder();
+ return availableCapabilitiesBuilder.build();
+ }
+
+ private AvailableCapabilities partialCapabilities() {
+ final String c1 = "(urn:ios?revision=2016-03-08)ned";
+ final String c2 = "(http://tail-f.com/yang/common?revision=2015-05-22)tailf-common";
+ final String c3 = "(http://tail-f.com/yang/common?revision=2015-03-19)tailf-cli-extensions";
+ String[] capabilityList = {c1, c2, c3};
+ AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder();
+ availableCapabilitiesBuilder.setAvailableCapability(Arrays.asList(capabilityList));
+ return availableCapabilitiesBuilder.build();
+ }
+
+ private AvailableCapabilities fullCapabilities() {
+ final String c1 = "(urn:ios?revision=2016-03-08)ned";
+ final String c2 = "(http://tail-f.com/yang/common?revision=2015-05-22)tailf-common";
+ final String c3 = "(http://tail-f.com/yang/common?revision=2015-03-19)tailf-cli-extensions";
+ final String c4 = "(http://tail-f.com/yang/common?revision=2013-11-07)tailf-meta-extensions";
+ final String c5 = "(urn:ietf:params:xml:ns:yang:ietf-yang-types?revision=2013-07-15)ietf-yang-types";
+ final String c6 = "(urn:ietf:params:xml:ns:yang:ietf-inet-types?revision=2013-07-15)ietf-inet-types";
+ String[] capabilityList = {c1, c2, c3, c4, c5, c6};
+ AvailableCapabilitiesBuilder availableCapabilitiesBuilder = new AvailableCapabilitiesBuilder();
+ availableCapabilitiesBuilder.setAvailableCapability(Arrays.asList(capabilityList));
+ return availableCapabilitiesBuilder.build();
+ }
+
+ private enum Capabilities {None, Partial, Full}
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.ServiceChainingUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriter;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
+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.SfName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderKey;
+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.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathKey;
+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.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+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.forwarding.l2_l3.rev160427.IpPrefixType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2BridgeDomain;
+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.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipationKey;
+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.ConfigurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.EndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererEndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererForwarding;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RuleGroupsBuilder;
+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.endpoints.AddressEndpointWithLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicyKey;
+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.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.ClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRuleBuilder;
+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.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.AddressEndpointWithLocationAugBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+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.PROVIDER;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({RendererPolicyUtil.class, PolicyManagerUtil.class, SfcProviderServiceForwarderAPI.class})
+public class PolicyManagerImplTest {
+
+ private final String address = "address";
+ private final String connector = "connector";
+ private final SfpName servicePath = new SfpName("service-path");
+ private final RspName renderedPath = new RspName("rendered-path");
+ private final SffName forwarderName = new SffName("service-forwarder");
+ private final ContextId contextId_1 = new ContextId("context-id-1");
+ private final ContextId contextId_2 = new ContextId("context-id-2");
+ private final ContextId contextId_3 = new ContextId("context-id-3");
+ private final ContextId contextId_4 = new ContextId("context-id-4");
+ private final ContractId contractId = new ContractId("contract-id");
+ private final String ipAddress = "192.168.50.1";
+ private final NodeId nodeId = new NodeId("node-id");
+ private final SubjectName subjectName = new SubjectName("subject-name");
+ private final TenantId tenantId = new TenantId("tenant-id");
+ private final TopologyId topologyId = new TopologyId("topology-id");
+ private final ActionDefinitionId chainActionDefinitionId = new ActionDefinitionId("Action-Chain");
+ private final ActionDefinitionId otherActionDefinitionId = new ActionDefinitionId("Action-Other");
+ private final SfName functionName = new SfName("service-function");
+ private PolicyManagerImpl policyManager;
+ private DataBroker mountpoint;
+ private NodeManager nodeManager;
+ private WriteTransaction writeTransaction;
+
+ @Before
+ public void init() {
+ mountpoint = mock(DataBroker.class);
+ writeTransaction = mock(WriteTransaction.class);
+ nodeManager = mock(NodeManager.class);
+ policyManager = new PolicyManagerImpl(mountpoint, nodeManager);
+ when(mountpoint.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+ }
+
+ @Test
+ public void testSyncPolicy_emptyConfiguration() throws Exception {
+ Configuration policyConfiguration = createTestConfiguration(null, null, null, null);
+ ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null);
+ assertTrue((boolean) result.get());
+ }
+
+ @Test
+ public void testSyncPolicy_noEndpointsInConfiguration() throws Exception {
+ RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_1, contextId_2, null);
+ Configuration policyConfiguration = createTestConfiguration(null, Collections.singletonList(rendererEndpoint),
+ null, null);
+ ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null);
+ assertTrue((boolean) result.get());
+ }
+
+ @Test
+ public void testSyncPolicy_noMountPoint() throws Exception {
+ AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+ RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3, null);
+ Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+ Collections.singletonList(rendererEndpoint), null, null);
+
+ AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+ AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, false);
+ stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+ when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(null);
+
+ ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null);
+ assertTrue((boolean) result.get());
+ }
+
+ @Test
+ public void testSyncPolicy_nullSgtTags() throws Exception {
+ AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+ RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3, null);
+ Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+ Collections.singletonList(rendererEndpoint), null, null);
+
+ AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+ AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, false);
+ stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+ when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+ when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+ when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+
+ ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null);
+ assertTrue((boolean) result.get());
+ }
+
+ @Test
+ public void testSyncPolicy_emptyRuleGroup() throws Exception {
+ AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+ RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation =
+ createRuleGroupWithRendererEpParticipation(PROVIDER);
+ RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3,
+ ruleGroupWithParticipation);
+ RuleGroup ruleGroup = createRuleGroup(null);
+ Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+ Collections.singletonList(rendererEndpoint), null, ruleGroup);
+
+ AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+ AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, true);
+ stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+ when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+ when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+ when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+
+ ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null);
+ assertTrue((boolean) result.get());
+ }
+
+ @Test
+ public void testSyncPolicy_noActionDefinition() throws Exception {
+ AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+ RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation =
+ createRuleGroupWithRendererEpParticipation(PROVIDER);
+ RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3,
+ ruleGroupWithParticipation);
+
+ RuleGroup ruleGroup = createRuleGroup(createRule(Out, null));
+ Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+ Collections.singletonList(rendererEndpoint), null, ruleGroup);
+
+ AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+ AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, true);
+ stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+ when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+ when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+ when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+
+ ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null);
+ assertTrue((boolean) result.get());
+ }
+
+ @Test
+ public void testSyncPolicy_otherAction() throws Exception {
+ AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+ RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation =
+ createRuleGroupWithRendererEpParticipation(PROVIDER);
+ RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3,
+ ruleGroupWithParticipation);
+
+ RuleGroup ruleGroup = createRuleGroup(createRule(Out, otherActionDefinitionId));
+ Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+ Collections.singletonList(rendererEndpoint), null, ruleGroup);
+
+ AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+ AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, true);
+ stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+ when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+ when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+ when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+
+ ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null);
+ assertTrue((boolean) result.get());
+ }
+
+ @Test
+ public void testSyncPolicy_asymmetricChain() throws Exception {
+ AddressEndpointWithLocation endpointWithLocation = createAddressEndpointWithLocation(contextId_1, null, false);
+ RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation =
+ createRuleGroupWithRendererEpParticipation(PROVIDER);
+ RendererEndpoint rendererEndpoint = createRendererEndpoint(contextId_2, contextId_3,
+ ruleGroupWithParticipation);
+
+ RuleGroup ruleGroup = createRuleGroup(createRule(Out, chainActionDefinitionId));
+ Configuration policyConfiguration = createTestConfiguration(Collections.singletonList(endpointWithLocation),
+ Collections.singletonList(rendererEndpoint), null, ruleGroup);
+
+ AbsoluteLocation location = createAbsoluteLocationExternal(connector, createMountpointIid());
+ AddressEndpointWithLocation lookupEndpoint = createAddressEndpointWithLocation(contextId_4, location, true);
+ stub(method(RendererPolicyUtil.class, "lookupEndpoint")).toReturn(lookupEndpoint);
+ when(nodeManager.getNodeMountPoint(eq(createMountpointIid()))).thenReturn(mountpoint);
+ when(nodeManager.getNodeIdByMountpointIid(eq(createMountpointIid()))).thenReturn(nodeId);
+ when(nodeManager.getNodeManagementIpByMountPointIid(eq(createMountpointIid()))).thenReturn(ipAddress);
+ ServiceFunctionPath sfp = createServiceFunctionPath();
+ stub(method(ServiceChainingUtil.class, "getServicePath")).toReturn(sfp);
+ RenderedServicePath rsp = createRenderedServicePath();
+ stub(method(ServiceChainingUtil.class, "createRenderedPath")).toReturn(rsp);
+ ServiceFunctionForwarder serviceFunctionForwarder = createServiceForwarder();
+ stub(method(SfcProviderServiceForwarderAPI.class, "readServiceFunctionForwarder"))
+ .toReturn(serviceFunctionForwarder);
+
+ ListenableFuture result = policyManager.syncPolicy(policyConfiguration, null);
+ assertTrue((boolean) result.get());
+ }
+
+ private ServiceFunctionForwarder createServiceForwarder() {
+ ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder = new ServiceFunctionForwarderBuilder();
+ serviceFunctionForwarderBuilder.setName(new SffName(forwarderName))
+ .setKey(new ServiceFunctionForwarderKey(new SffName(forwarderName)))
+ .setIpMgmtAddress(new IpAddress(new Ipv4Address(ipAddress)));
+ return serviceFunctionForwarderBuilder.build();
+ }
+
+ // Utility methods
+
+ private InstanceIdentifier createMountpointIid() {
+ return InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(topologyId))
+ .child(Node.class, new NodeKey(nodeId)).build();
+ }
+
+ private ResolvedRule createRule(HasDirection.Direction direction, ActionDefinitionId actionDefinitionId) {
+ ResolvedRuleBuilder resolvedRuleBuilder = new ResolvedRuleBuilder();
+ ClassifierBuilder classifierBuilder = new ClassifierBuilder();
+ classifierBuilder.setDirection(direction);
+ ActionBuilder actionBuilder = new ActionBuilder();
+ actionBuilder.setActionDefinitionId(actionDefinitionId);
+ resolvedRuleBuilder.setClassifier(Collections.singletonList(classifierBuilder.build()))
+ .setAction(Collections.singletonList(actionBuilder.build()));
+ return resolvedRuleBuilder.build();
+ }
+
+ private RuleGroupWithRendererEndpointParticipation createRuleGroupWithRendererEpParticipation(final EndpointPolicyParticipation participation) {
+ RuleGroupWithRendererEndpointParticipationBuilder ruleGroupBuilder = new RuleGroupWithRendererEndpointParticipationBuilder();
+ ruleGroupBuilder.setKey(new RuleGroupWithRendererEndpointParticipationKey(contractId, participation, subjectName,
+ tenantId));
+ return ruleGroupBuilder.build();
+ }
+
+ private AbsoluteLocation createAbsoluteLocationExternal(String connector, InstanceIdentifier mountpoint) {
+ ExternalLocationCaseBuilder externalLocationCaseBuilder = new ExternalLocationCaseBuilder();
+ externalLocationCaseBuilder.setExternalNodeConnector(connector)
+ .setExternalNodeMountPoint(mountpoint);
+ AbsoluteLocationBuilder absoluteLocationBuilder = new AbsoluteLocationBuilder();
+ absoluteLocationBuilder.setLocationType(externalLocationCaseBuilder.build());
+ return absoluteLocationBuilder.build();
+ }
+
+ private ServiceFunctionPath createServiceFunctionPath() {
+ ServiceFunctionPathBuilder serviceFunctionPathBuilder = new ServiceFunctionPathBuilder();
+ serviceFunctionPathBuilder.setKey(new ServiceFunctionPathKey(servicePath))
+ .setSymmetric(false);
+ return serviceFunctionPathBuilder.build();
+ }
+
+ private RenderedServicePath createRenderedServicePath() {
+ RenderedServicePathHopBuilder renderedServicePathHopBuilder = new RenderedServicePathHopBuilder();
+ renderedServicePathHopBuilder.setServiceFunctionForwarder(forwarderName);
+ renderedServicePathHopBuilder.setServiceFunctionName(functionName);
+ renderedServicePathHopBuilder.build();
+
+ RenderedServicePathBuilder renderedServicePathBuilder = new RenderedServicePathBuilder();
+ renderedServicePathBuilder.setKey(new RenderedServicePathKey(renderedPath))
+ .setRenderedServicePathHop(Collections.singletonList(renderedServicePathHopBuilder.build()));
+ return renderedServicePathBuilder.build();
+ }
+
+
+ private AddressEndpointWithLocation createAddressEndpointWithLocation(final ContextId contextId,
+ final AbsoluteLocation location,
+ boolean augmentation) {
+ AddressEndpointWithLocationAugBuilder augmentationBuilder = new AddressEndpointWithLocationAugBuilder();
+ augmentationBuilder.setSgt(new Sgt(1));
+ AddressEndpointWithLocationBuilder addressEndpointBuilder = new AddressEndpointWithLocationBuilder();
+ addressEndpointBuilder.setKey(new AddressEndpointWithLocationKey(address, IpPrefixType.class,
+ contextId, L2BridgeDomain.class))
+ .setAbsoluteLocation(location);
+ if (augmentation) {
+ addressEndpointBuilder.addAugmentation(AddressEndpointWithLocationAug.class, augmentationBuilder.build());
+ }
+ return addressEndpointBuilder.build();
+ }
+
+ private RendererEndpoint createRendererEndpoint(ContextId contextId_1, ContextId contextId_2,
+ RuleGroupWithRendererEndpointParticipation ruleGroup) {
+ PeerEndpointWithPolicyBuilder peerEndpointWithPolicyBuilder = new PeerEndpointWithPolicyBuilder();
+ peerEndpointWithPolicyBuilder.setKey(new PeerEndpointWithPolicyKey(address, IpPrefixType.class, contextId_1,
+ L2BridgeDomain.class))
+ .setRuleGroupWithRendererEndpointParticipation(Collections.singletonList(ruleGroup));
+ RendererEndpointBuilder rendererEndpointBuilder = new RendererEndpointBuilder();
+ rendererEndpointBuilder.setKey(new RendererEndpointKey(address, IpPrefixType.class, contextId_2,
+ L2BridgeDomain.class))
+ .setPeerEndpointWithPolicy(Collections.singletonList(peerEndpointWithPolicyBuilder.build()));
+ return rendererEndpointBuilder.build();
+ }
+
+ private RuleGroup createRuleGroup(ResolvedRule rule) {
+ RuleGroupBuilder ruleGroupBuilder = new RuleGroupBuilder();
+ ruleGroupBuilder.setKey(new RuleGroupKey(contractId, subjectName, tenantId))
+ .setResolvedRule(Collections.singletonList(rule));
+ return ruleGroupBuilder.build();
+ }
+
+ private Configuration createTestConfiguration(final List<AddressEndpointWithLocation> endpointsWithLocation,
+ final List<RendererEndpoint> rendererEndpoints,
+ final RendererForwarding rendererForwarding,
+ final RuleGroup ruleGroup) {
+ // Set endpoints
+ EndpointsBuilder endpointsBuilder = new EndpointsBuilder();
+ endpointsBuilder.setAddressEndpointWithLocation(endpointsWithLocation);
+ // Set renderer endpoints
+ RendererEndpointsBuilder rendererEndpointsBuilder = new RendererEndpointsBuilder();
+ rendererEndpointsBuilder.setRendererEndpoint(rendererEndpoints);
+ // Set rule group
+ RuleGroupsBuilder ruleGroupsBuilder = new RuleGroupsBuilder();
+ ruleGroupsBuilder.setRuleGroup(Collections.singletonList(ruleGroup));
+ // Build configuration
+ ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
+ configurationBuilder.setEndpoints(endpointsBuilder.build())
+ .setRendererEndpoints(rendererEndpointsBuilder.build())
+ .setRendererForwarding(rendererForwarding)
+ .setRuleGroups(ruleGroupsBuilder.build());
+ return configurationBuilder.build();
+ }
+
+
+}
\ No newline at end of file
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.writer.NodeWriter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
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.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;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import static org.junit.Assert.assertNotNull;
+
/**
* Test for {@link PolicyManagerUtil}.
*/
new OpendaylightSfc().setDataProvider(dataBroker);
}
+ @Test
+ public void testCreateClassMap() {
+ ClassMap cm = PolicyManagerUtil.createClassMap("testName", null);
+ assertNotNull(cm);
+ }
+
@Test
public void testGetServicePath() throws Exception {
final ParameterValue paramValueSfc = new ParameterValueBuilder()
Mockito.when(roTx.read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(ServiceFunctionPaths.class)))
.thenReturn(Futures.immediateCheckedFuture(Optional.of(sfPaths)));
- final ServiceFunctionPath servicePath = PolicyManagerUtil.getServicePath(Collections.singletonList(paramValueSfc));
+ final ServiceFunctionPath servicePath = ServiceChainingUtil.getServicePath(Collections.singletonList(paramValueSfc));
Assert.assertEquals(serviceFunctionPath, servicePath);
}
Mockito.when(roTx.read(Matchers.eq(LogicalDatastoreType.OPERATIONAL), rendererServicePathIICaptor.capture()))
.thenReturn(Futures.immediateCheckedFuture(Optional.of(renderedSP)));
- final RenderedServicePath renderedPath = PolicyManagerUtil.createRenderedPath(serviceFunctionPath, tenantId);
+ final RenderedServicePath renderedPath = ServiceChainingUtil.createRenderedPath(serviceFunctionPath, tenantId);
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());
.thenReturn(Futures.immediateCheckedFuture(Optional.of(renderedServicePath)));
- final RenderedServicePath symmetricRenderedPath = PolicyManagerUtil.createSymmetricRenderedPath(
+ final RenderedServicePath symmetricRenderedPath = ServiceChainingUtil.createSymmetricRenderedPath(
serviceFunctionPath, renderedServicePath, tenantId);
Assert.assertEquals(renderedServicePath, symmetricRenderedPath);
final InstanceIdentifier<RenderedServicePath> ii = rendererServicePathIICaptor.getValue();