-->
<feature name='odl-groupbasedpolicy-vpp' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: VPP renderer '>
<feature version="${project.version}">odl-groupbasedpolicy-base</feature>
+ <feature version="${netconf.version}">odl-netconf-topology</feature>
<bundle>mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.groupbasedpolicy/vpp-renderer/{{VERSION}}</bundle>
<configfile finalname="${config.configfile.directory}/15-l2-l3-domain-extension.xml">mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}/xml/config</configfile>
<artifactId>vpp-renderer</artifactId>
<packaging>bundle</packaging>
- <properties></properties>
+ <properties>
+ <netconf.version>1.1.0-SNAPSHOT</netconf.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-artifacts</artifactId>
+ <version>${netconf.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>mdsal-artifacts</artifactId>
+ <version>${mdsal.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
<dependencies>
<!-- project specific dependencies -->
<groupId>org.opendaylight.mdsal.model</groupId>
<artifactId>ietf-interfaces</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>sal-netconf-connector</artifactId>
+ </dependency>
<!-- testing dependencies -->
<dependency>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
<name>binding-data-broker</name>
</data-broker>
+ <broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <name>binding-osgi-broker</name>
+ </broker>
</module>
</modules>
</data>
@Override
public java.lang.AutoCloseable createInstance() {
- final VppRenderer vppRenderer = new VppRenderer(getDataBrokerDependency());
+ final VppRenderer vppRenderer = new VppRenderer(getDataBrokerDependency(), getBrokerDependency());
LOG.info("VPP Renderer instance has been created");
-/*\r
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.config.yang.config.vpp_provider.impl;\r
-\r
-import com.google.common.base.Preconditions;\r
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class VppRenderer implements AutoCloseable {\r
- private static final Logger LOG = LoggerFactory.getLogger(VppRenderer.class);\r
-\r
- private DataBroker dataBroker;\r
-\r
- public VppRenderer(DataBroker dataBroker) {\r
- Preconditions.checkNotNull(dataBroker);\r
-\r
- this.dataBroker = dataBroker;\r
-\r
- LOG.info("VPP Renderer has Started");\r
- }\r
-\r
- @Override\r
- public void close() throws Exception {\r
- this.dataBroker = null;\r
- }\r
-\r
-}\r
+/*
+ * Copyright (c) 2014 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.controller.config.yang.config.vpp_provider.impl;
+
+import java.util.List;
+
+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.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppNodeListener;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.VppNodeManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.AllowAction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.EtherTypeClassifier;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+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.RendererBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.CapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedActionDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinitionBuilder;
+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;
+
+public class VppRenderer implements AutoCloseable, BindingAwareProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VppRenderer.class);
+
+ private final List<SupportedActionDefinition> actionDefinitions =
+ ImmutableList.of(new SupportedActionDefinitionBuilder().setActionDefinitionId(new AllowAction().getId())
+ .setSupportedParameterValues(new AllowAction().getSupportedParameterValues())
+ .build());
+ private final List<SupportedClassifierDefinition> classifierDefinitions = ImmutableList
+ .of(new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(new EtherTypeClassifier(null).getId())
+ .setSupportedParameterValues(new EtherTypeClassifier(null).getSupportedParameterValues())
+ .build());
+
+ private DataBroker dataBroker;
+ private VppNodeManager vppNodeManager;
+ private VppNodeListener vppNodeListener;
+
+ public VppRenderer(DataBroker dataBroker, BindingAwareBroker bindingAwareBroker) {
+ this.dataBroker = Preconditions.checkNotNull(dataBroker);
+ bindingAwareBroker.registerProvider(this);
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("Closing Vpp renderer");
+ if (vppNodeListener != null) {
+ vppNodeListener.close();
+ }
+ unregisterFromRendererManager();
+ }
+
+ @Override
+ public void onSessionInitiated(BindingAwareBroker.ProviderContext providerContext) {
+ LOG.info("starting vpp renderer");
+
+ // vpp-node-manager
+ vppNodeManager = new VppNodeManager(dataBroker, providerContext);
+ vppNodeListener = new VppNodeListener(dataBroker, vppNodeManager);
+
+ registerToRendererManager();
+ }
+
+ private void registerToRendererManager() {
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+ Renderer renderer = new RendererBuilder().setName(VppNodeManager.vppRenderer)
+ .setRendererNodes(new RendererNodesBuilder().build())
+ .setCapabilities(new CapabilitiesBuilder().setSupportedActionDefinition(actionDefinitions)
+ .setSupportedClassifierDefinition(classifierDefinitions)
+ .build())
+ .build();
+
+ writeTransaction.put(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererIID(renderer.getKey()),
+ renderer, true);
+ CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
+ Futures.addCallback(future, new FutureCallback<Void>() {
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.error("Could not register renderer {}: {}", renderer, throwable);
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ LOG.debug("Renderer {} successfully registered.", renderer);
+ }
+ });
+ }
+
+
+ private void unregisterFromRendererManager() {
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+ writeTransaction.delete(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererIID(new RendererKey(VppNodeManager.vppRenderer)));
+
+ CheckedFuture<Void, TransactionCommitFailedException> future = writeTransaction.submit();
+ Futures.addCallback(future, new FutureCallback<Void>() {
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.error("Could not unregister renderer {}: {}", VppNodeManager.vppRenderer, throwable);
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ LOG.debug("Renderer {} successfully unregistered.", VppNodeManager.vppRenderer);
+ }
+ });
+ }
+}
--- /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.vpp.listener;
+
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.VppNodeManager;
+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.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class VppNodeListener implements DataTreeChangeListener<Node>, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VppNodeListener.class);
+
+ private final ListenerRegistration<VppNodeListener> listenerRegistration;
+ private final VppNodeManager nodeManager;
+
+ public VppNodeListener(DataBroker dataBroker, VppNodeManager nodeManager) {
+ this.nodeManager = Preconditions.checkNotNull(nodeManager);
+ // Register listener
+ final DataTreeIdentifier<Node> networkTopologyPath = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class).child(Node.class).build());
+ listenerRegistration =
+ Preconditions.checkNotNull(dataBroker.registerDataTreeChangeListener(networkTopologyPath, this));
+ LOG.info("Network-Topology VppNodelistener registered");
+ }
+
+ @Override
+ public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> changes) {
+ LOG.debug("Topology Node changed. Changes {}", changes);
+
+ for (DataTreeModification<Node> modification : changes) {
+ DataObjectModification<Node> rootNode = modification.getRootNode();
+ Node dataAfter = rootNode.getDataAfter();
+ Node dataBefore = rootNode.getDataBefore();
+ nodeManager.syncNodes(dataAfter, dataBefore);
+ }
+ }
+
+ public ListenerRegistration<VppNodeListener> getRegistrationObject() {
+ return listenerRegistration;
+ }
+
+ @Override
+ public void close() throws Exception {
+ listenerRegistration.close();
+ }
+}
--- /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.vpp.manager;
+
+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 java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppNodeWriter;
+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.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeKey;
+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.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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public class VppNodeManager {
+
+ public static final RendererName vppRenderer = new RendererName("vpp-renderer");
+ private static final TopologyId TOPOLOGY_ID = new TopologyId("topology-netconf");
+ private static final Logger LOG = LoggerFactory.getLogger(VppNodeManager.class);
+ private static final Map<InstanceIdentifier<Node>, DataBroker> netconfNodeCache = new HashMap<>();
+ private static final String V3PO_CAPABILITY = "(urn:opendaylight:params:xml:ns:yang:v3po?revision=2015-01-05)v3po";
+ private static final String INTERFACES_CAPABILITY =
+ "(urn:ietf:params:xml:ns:yang:ietf-interfaces?revision=2014-05-08)ietf-interfaces";
+ private final DataBroker dataBroker;
+ private final MountPointService mountService;
+ private final List<String> requiredCapabilities;
+
+ public VppNodeManager(DataBroker dataBroker, BindingAwareBroker.ProviderContext session) {
+ this.dataBroker = Preconditions.checkNotNull(dataBroker);
+ mountService = Preconditions.checkNotNull(session.getSALService(MountPointService.class));
+ requiredCapabilities = initializeRequiredCapabilities();
+ }
+
+ static DataBroker getDataBrokerFromCache(InstanceIdentifier<Node> iid) {
+ return netconfNodeCache.get(iid); // TODO read from DS
+ }
+
+ /**
+ * Synchronizes nodes to DataStore based on their modification state which results in
+ * create/update/remove of Node.
+ */
+ public void syncNodes(Node dataAfter, Node dataBefore) {
+ // New node
+ if (dataBefore == null && dataAfter != null) {
+ createNode(dataAfter);
+ }
+ // Connected/disconnected node
+ if (dataBefore != null && dataAfter != null) {
+ updateNode(dataAfter);
+ }
+ // Removed node
+ if (dataBefore != null && dataAfter == null) {
+ removeNode(dataBefore);
+ }
+ }
+
+ private void createNode(Node node) {
+ LOG.info("Registering new node {}", node.getNodeId().getValue());
+ NetconfNode netconfNode = getNodeAugmentation(node);
+ if (netconfNode == null) {
+ return;
+ }
+ NetconfNodeConnectionStatus.ConnectionStatus connectionStatus = netconfNode.getConnectionStatus();
+ switch (connectionStatus) {
+ case Connecting:
+ LOG.info("Connecting device {} ...", node.getNodeId().getValue());
+ break;
+ case Connected:
+ resolveConnectedNode(node, netconfNode);
+ LOG.info("Node {} is capable and ready", node.getNodeId().getValue());
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void updateNode(Node node) {
+ NetconfNode netconfNode = getNodeAugmentation(node);
+ if (netconfNode == null || netconfNode.getConnectionStatus() == null) {
+ return;
+ }
+ NetconfNodeConnectionStatus.ConnectionStatus afterNodeStatus = netconfNode.getConnectionStatus();
+ if (afterNodeStatus.equals(Connected)) {
+ resolveConnectedNode(node, netconfNode);
+ LOG.info("Node {} is capable and ready", node.getNodeId().getValue());
+ }
+ if (afterNodeStatus.equals(Connecting)) {
+ resolveDisconnectedNode(node);
+ LOG.info("Node {} has been disconnected, removing from available nodes", node.getNodeId().getValue());
+ }
+ }
+
+ private void removeNode(Node node) {
+ resolveDisconnectedNode(node);
+ LOG.info("Node {} has been removed", node.getNodeId().getValue());
+ }
+
+ private void resolveConnectedNode(Node node, NetconfNode netconfNode) {
+ InstanceIdentifier<Node> mountPointIid = getMountpointIid(node);
+ // Mountpoint iid == path in renderer-node
+ RendererNode rendererNode = remapNode(mountPointIid);
+ VppNodeWriter vppNodeWriter = new VppNodeWriter();
+ vppNodeWriter.cache(rendererNode);
+ if (!isCapableNetconfDevice(node, netconfNode)) {
+ return;
+ }
+ vppNodeWriter.commitToDatastore(dataBroker);
+ DataBroker mountpoint = getNodeMountPoint(mountPointIid);
+ netconfNodeCache.put(mountPointIid, mountpoint);
+ }
+
+ private void resolveDisconnectedNode(Node node) {
+ InstanceIdentifier<Node> mountPointIid = getMountpointIid(node);
+ RendererNode rendererNode = remapNode(mountPointIid);
+ VppNodeWriter vppNodeWriter = new VppNodeWriter();
+ vppNodeWriter.cache(rendererNode);
+ vppNodeWriter.removeFromDatastore(dataBroker);
+ netconfNodeCache.remove(mountPointIid);
+ }
+
+ private RendererNode remapNode(InstanceIdentifier<Node> path) {
+ RendererNodeBuilder rendererNodeBuilder = new RendererNodeBuilder();
+ rendererNodeBuilder.setKey(new RendererNodeKey(path)).setNodePath(path);
+ return rendererNodeBuilder.build();
+ }
+
+ private InstanceIdentifier<Node> getMountpointIid(Node node) {
+ return InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(TOPOLOGY_ID))
+ .child(Node.class, new NodeKey(node.getNodeId()))
+ .build();
+ }
+
+ private boolean isCapableNetconfDevice(Node node, NetconfNode netconfAugmentation) {
+ if (netconfAugmentation.getAvailableCapabilities() == null
+ || netconfAugmentation.getAvailableCapabilities().getAvailableCapability() == null
+ || netconfAugmentation.getAvailableCapabilities().getAvailableCapability().isEmpty()) {
+ LOG.warn("Node {} does not contain any capabilities", node.getNodeId().getValue());
+ return false;
+ }
+ if (!capabilityCheck(netconfAugmentation.getAvailableCapabilities().getAvailableCapability())) {
+ LOG.warn("Node {} does not contain all capabilities required by vpp-renderer", node.getNodeId().getValue());
+ return false;
+ }
+ return true;
+ }
+
+ private boolean capabilityCheck(final List<String> capabilities) {
+ for (String requiredCapability : requiredCapabilities) {
+ if (!capabilities.contains(requiredCapability)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private DataBroker getNodeMountPoint(InstanceIdentifier<Node> mountPointIid) {
+ Optional<MountPoint> optionalObject = mountService.getMountPoint(mountPointIid);
+ MountPoint mountPoint;
+ if (optionalObject.isPresent()) {
+ mountPoint = optionalObject.get();
+ if (mountPoint != null) {
+ Optional<DataBroker> optionalDataBroker = mountPoint.getService(DataBroker.class);
+ if (optionalDataBroker.isPresent()) {
+ return optionalDataBroker.get();
+ } else {
+ LOG.debug("Cannot obtain data broker from mountpoint {}", mountPoint);
+ }
+ } else {
+ LOG.debug("Cannot obtain mountpoint with IID {}", mountPointIid);
+ }
+ }
+ return null;
+ }
+
+ private NetconfNode getNodeAugmentation(Node node) {
+ NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
+ if (netconfNode == null) {
+ LOG.warn("Node {} is not a netconf device", node.getNodeId().getValue());
+ return null;
+ }
+ return netconfNode;
+ }
+
+ /**
+ * Initialize all common capabilities required by VPP renderer. Any connected node is examined
+ * whether it's
+ * an appropriate device to handle configuration created by this renderer. A device must support
+ * all capabilities
+ * in list below.
+ *
+ * @return list of string representations of required capabilities
+ */
+ private List<String> initializeRequiredCapabilities() {
+ // Required device capabilities
+
+ String[] capabilityEntries = {V3PO_CAPABILITY, INTERFACES_CAPABILITY};
+ return Arrays.asList(capabilityEntries);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.vpp.sf;
+
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.Validator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.action.definition.SupportedParameterValues;
+
+/**
+ * Represent an action definition, and provide tools for generating
+ * flow instructions based on the action.
+ */
+public abstract class Action implements Validator<ActionInstance> {
+
+ /**
+ * Get the action definition for this action.
+ *
+ * @return the {@link ActionDefinition} for this action
+ */
+ public abstract ActionDefinitionId getId();
+
+ /**
+ * Get the action definition for this action.
+ *
+ * @return the {@link ActionDefinition} for this action
+ */
+ public abstract ActionDefinition getActionDef();
+
+ /**
+ * The result represents supported parameters for the action by renderer.
+ *
+ * @return list of supported parameters by the action
+ */
+ public abstract List<SupportedParameterValues> getSupportedParameterValues();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.vpp.sf;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.ValidationResult;
+import org.opendaylight.groupbasedpolicy.api.sf.AllowActionDefinition;
+import org.opendaylight.groupbasedpolicy.dto.ValidationResultBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.action.definition.SupportedParameterValues;
+
+/**
+ * Allow action.
+ */
+public class AllowAction extends Action {
+
+ @Override
+ public ActionDefinitionId getId() {
+ return AllowActionDefinition.ID;
+ }
+
+ @Override
+ public ActionDefinition getActionDef() {
+ return AllowActionDefinition.DEFINITION;
+ }
+
+ @Override
+ public ValidationResult validate(ActionInstance actionInstance) {
+ return new ValidationResultBuilder().success().build();
+ }
+
+ @Override
+ public List<SupportedParameterValues> getSupportedParameterValues() {
+ // allow action definition has no parameter
+ return Collections.emptyList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.vpp.sf;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+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.capabilities.supported.classifier.definition.SupportedParameterValues;
+
+/**
+ * Represent a classifier definition.
+ */
+public abstract class Classifier {
+
+ protected final Classifier parent;
+
+ public static final EtherTypeClassifier ETHER_TYPE_CL = new EtherTypeClassifier(null);
+ public static final IpProtoClassifier IP_PROTO_CL = new IpProtoClassifier(ETHER_TYPE_CL);
+
+ protected Classifier(Classifier parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Get the classifier definition id for this classifier.
+ *
+ * @return the {@link ClassifierDefinitionId} for this classifier
+ */
+ public abstract ClassifierDefinitionId getId();
+
+ /**
+ * Get the classifier definition for this classifier.
+ *
+ * @return the {@link ClassifierDefinition} for this classifier
+ */
+ public abstract ClassifierDefinition getClassifierDefinition();
+
+ /**
+ * Get parent for this classifier.
+ *
+ * @return parent classifier, see {@link Classifier}
+ */
+ public final Classifier getParent() {
+ return parent;
+ }
+
+ /**
+ * The result represents supported parameters for the classifier by renderer.
+ *
+ * @return list of supported parameters by the classifier
+ */
+ public abstract List<SupportedParameterValues> getSupportedParameterValues();
+
+ /**
+ * Checks presence of required {@code params} in order to decide if classifier can update
+ * {@code matches} properly.
+ *
+ * @param params inserted parameters, not null
+ * @throws IllegalArgumentException when any of required {@code params} is not present
+ */
+ protected abstract void checkPresenceOfRequiredParams(Map<String, ParameterValue> params);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.vpp.sf;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.groupbasedpolicy.api.sf.EtherTypeClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+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.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Match on the ether type of the traffic.
+ */
+public class EtherTypeClassifier extends Classifier {
+
+ public EtherTypeClassifier(Classifier parent) {
+ super(parent);
+ }
+
+ @Override
+ public ClassifierDefinitionId getId() {
+ return EtherTypeClassifierDefinition.ID;
+ }
+
+ @Override
+ public ClassifierDefinition getClassifierDefinition() {
+ return EtherTypeClassifierDefinition.DEFINITION;
+ }
+
+ @Override
+ public List<SupportedParameterValues> getSupportedParameterValues() {
+
+ List<SupportedIntValue> values = ImmutableList.of(
+ new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.IPv4_VALUE).build(),
+ new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.IPv6_VALUE).build());
+ SupportedParameterValuesBuilder builder = new SupportedParameterValuesBuilder();
+ builder.setParameterName(new ParameterName(EtherTypeClassifierDefinition.ETHERTYPE_PARAM));
+ builder.setParameterType(new IntBuilder().setSupportedIntValue(values).build());
+
+ return ImmutableList.of(builder.build());
+ }
+
+ @Override
+ protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
+ if (params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM) == null) {
+ throw new IllegalArgumentException(
+ "Parameter " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM + " not specified.");
+ }
+ if (params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM).getIntValue() == null) {
+ throw new IllegalArgumentException(
+ "Value of " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM + " parameter is not present.");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.vpp.sf;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.groupbasedpolicy.api.sf.IpProtoClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+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.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Match on the IP protocol of IP traffic.
+ */
+public class IpProtoClassifier extends Classifier {
+
+ protected IpProtoClassifier(Classifier parent) {
+ super(parent);
+ }
+
+ @Override
+ public ClassifierDefinitionId getId() {
+ return IpProtoClassifierDefinition.ID;
+ }
+
+ @Override
+ public ClassifierDefinition getClassifierDefinition() {
+ return IpProtoClassifierDefinition.DEFINITION;
+ }
+
+ @Override
+ public List<SupportedParameterValues> getSupportedParameterValues() {
+
+ List<SupportedIntValue> values = ImmutableList.of(
+ new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.ICMP_VALUE).build(),
+ new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.SCTP_VALUE).build(),
+ new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.TCP_VALUE).build(),
+ new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.UDP_VALUE).build());
+ SupportedParameterValuesBuilder builder = new SupportedParameterValuesBuilder();
+ builder.setParameterName(new ParameterName(IpProtoClassifierDefinition.PROTO_PARAM));
+ builder.setParameterType(new IntBuilder().setSupportedIntValue(values).build());
+
+ return ImmutableList.of(builder.build());
+ }
+
+ @Override
+ protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
+ if (params.get(IpProtoClassifierDefinition.PROTO_PARAM) == null) {
+ throw new IllegalArgumentException(
+ "Parameter " + IpProtoClassifierDefinition.PROTO_PARAM + " not specified.");
+ }
+ if (params.get(IpProtoClassifierDefinition.PROTO_PARAM).getIntValue() == null) {
+ throw new IllegalArgumentException(
+ "Value of " + IpProtoClassifierDefinition.PROTO_PARAM + " parameter is not present.");
+ }
+ }
+
+ /**
+ * Return the IpProtocol value. May return null.
+ *
+ * @param params the parameters of classifier-instance inserted by user
+ * @return the IpProtocol value
+ */
+ public static Long getIpProtoValue(Map<String, ParameterValue> params) {
+ if (params == null) {
+ return null;
+ }
+ if (params.get(IpProtoClassifierDefinition.PROTO_PARAM) == null) {
+ return null;
+ }
+ Long proto = params.get(IpProtoClassifierDefinition.PROTO_PARAM).getIntValue();
+ if (proto != null) {
+ return proto;
+ }
+ return null;
+ }
+}
-/*\r
- * Copyright (c) 2016 Cisco Systems. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.groupbasedpolicy.renderer.vpp.util;\r
-\r
-\r
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
-import org.opendaylight.yangtools.yang.binding.DataObject;\r
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
-\r
-public class General {\r
-\r
- /**\r
- * Operations that can be executed over ConfigCommand. Operation names reflect operations used in WriteTransaction.\r
- * For more information on these operations, please see the documentation in:\r
- * <br>\r
- * {@link WriteTransaction#put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}<br>\r
- * {@link WriteTransaction#merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}<br>\r
- * {@link WriteTransaction#delete(LogicalDatastoreType, InstanceIdentifier)}<br>\r
- *\r
- */\r
- public enum Operations {\r
- PUT, DELETE, MERGE\r
- }\r
-}\r
+/*
+ * Copyright (c) 2016 Cisco Systems. 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.vpp.util;
+
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class General {
+
+ /**
+ * Operations that can be executed over ConfigCommand. Operation names reflect operations used
+ * in WriteTransaction.
+ * For more information on these operations, please see the documentation in:
+ * <br>
+ * {@link WriteTransaction#put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}
+ * <br>
+ * {@link WriteTransaction#merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}
+ * <br>
+ * {@link WriteTransaction#delete(LogicalDatastoreType, InstanceIdentifier)}<br>
+ */
+ public enum Operations {
+ PUT, DELETE, MERGE
+ }
+}
package org.opendaylight.groupbasedpolicy.renderer.vpp.util;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.VppNodeManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
+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.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeKey;
+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.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;
public class VppIidFactory {
public static InstanceIdentifier<Interface> getInterfaceIID(InterfaceKey interfaceKey) {
return InstanceIdentifier.create(Interfaces.class).child(Interface.class, interfaceKey);
}
+
+ public static InstanceIdentifier<Renderer> getRendererIID(RendererKey rendererKey) {
+ return InstanceIdentifier.create(Renderers.class).child(Renderer.class, rendererKey);
+ }
+
+ public static InstanceIdentifier<RendererNodes> getRendererNodesIid() {
+ return InstanceIdentifier.builder(Renderers.class)
+ .child(Renderer.class, new RendererKey(VppNodeManager.vppRenderer))
+ .child(RendererNodes.class)
+ .build();
+ }
+
+ public static InstanceIdentifier<RendererNode> getRendererNodeIid(RendererNode rendererNode) {
+ return InstanceIdentifier.builder(Renderers.class)
+ .child(Renderer.class, new RendererKey(VppNodeManager.vppRenderer))
+ .child(RendererNodes.class)
+ .child(RendererNode.class, new RendererNodeKey(rendererNode.getNodePath()))
+ .build();
+ }
+
+ public static InstanceIdentifier<Node> getNodeIid(NodeKey key) {
+ TopologyKey topologyKey = new TopologyKey(new TopologyId("topology-netconf"));
+ return InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class,topologyKey)
+ .child(Node.class, key).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.vpp.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.CheckedFuture;
+
+public class VppNodeWriter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VppNodeWriter.class);
+ private List<RendererNode> rendererNodesCache;
+
+ public VppNodeWriter() {
+ rendererNodesCache = new ArrayList<>();
+ }
+
+ public void cache(RendererNode node) {
+ rendererNodesCache.add(node);
+ }
+
+ /**
+ * Put all cached items to data store.
+ *
+ * @param dataBroker appropriate data provider
+ */
+ public void commitToDatastore(DataBroker dataBroker) {
+ RendererNodes rendererNodes = buildRendererNodes();
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ InstanceIdentifier<RendererNodes> iid = VppIidFactory.getRendererNodesIid();
+ try {
+ wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, rendererNodes, true);
+ CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+ submitFuture.checkedGet();
+ // Clear cache
+ rendererNodesCache.clear();
+ } catch (TransactionCommitFailedException e) {
+ LOG.error("Write transaction failed to {}", e.getMessage());
+ } catch (Exception e) {
+ LOG.error("Failed to .. {}", e.getMessage());
+ }
+ }
+
+ /**
+ * Removes all cached items from data store.
+ *
+ * @param dataBroker appropriate data provider
+ */
+ public void removeFromDatastore(DataBroker dataBroker) {
+ WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+ for (RendererNode nodeToRemove : rendererNodesCache) {
+ InstanceIdentifier<RendererNode> iid = VppIidFactory.getRendererNodeIid(nodeToRemove);
+ try {
+ wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+ 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());
+ }
+ }
+ rendererNodesCache.clear();
+ }
+
+ private RendererNodes buildRendererNodes() {
+ RendererNodesBuilder rendererNodesBuilder = new RendererNodesBuilder();
+ rendererNodesBuilder.setRendererNode(new ArrayList<>(rendererNodesCache));
+ return rendererNodesBuilder.build();
+ }
+}
}
}
}
+ // binding aware broker
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-broker-osgi-registry;
+ }
+ }
+ }
}
}
}
import com.google.common.collect.ImmutableList;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUser;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;\r
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;\r
\r
import javax.annotation.Nonnull;\r
import java.util.Collection;\r
@Nonnull\r
@Override\r
public Collection<Class<?>> getClassesFromModules() {\r
- return ImmutableList.of(Interfaces.class, Interface.class, VhostUser.class);\r
+ return ImmutableList.of(Interfaces.class, Interface.class, VhostUser.class, NetworkTopology.class,\r
+ Topology.class, Node.class, NetconfNode.class, Renderer.class);\r
}\r
}\r
--- /dev/null
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.manager;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.*;
+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.vpp.VppRendererDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppNodeListener;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+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.RendererKey;
+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.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
+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.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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test for {@link VppNodeManager} and {@link VppNodeListener}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class VppManagerDataStoreTest extends VppRendererDataBrokerTest {
+
+ private static final String V3PO_CAPABILITY = "(urn:opendaylight:params:xml:ns:yang:v3po?revision=2015-01-05)v3po";
+ private static final String INTERFACES_CAPABILITY =
+ "(urn:ietf:params:xml:ns:yang:ietf-interfaces?revision=2014-05-08)ietf-interfaces";
+ private static final String NODE_NAME = "testVpp";
+
+ private final InstanceIdentifier<Node> nodeIid = VppIidFactory.getNodeIid(new NodeKey(new NodeId(NODE_NAME)));
+
+ @Mock
+ BindingAwareBroker.ProviderContext providerContext;
+ @Mock
+ MountPointService mountPointService;
+ @Mock
+ MountPoint mountPoint;
+ @Mock
+ DataBroker dataBroker2;
+
+ private DataBroker dataBroker;
+ private VppNodeListener vppNodeListener;
+ private VppNodeManager vppNodeManager;
+
+ @Before
+ public void setUp() throws Exception {
+ Mockito.when(providerContext.getSALService(Matchers.<Class<MountPointService>>any()))
+ .thenReturn(mountPointService);
+ Mockito.when(mountPointService.getMountPoint(Matchers.<InstanceIdentifier<Node>>any()))
+ .thenReturn(Optional.of(mountPoint));
+ Mockito.when(mountPoint.getService(Matchers.<Class<DataBroker>>any())).thenReturn(Optional.of(dataBroker2));
+ dataBroker = getDataBroker();
+ vppNodeManager = new VppNodeManager(dataBroker, providerContext);
+ vppNodeListener = new VppNodeListener(dataBroker, vppNodeManager);
+ }
+
+ private Node createNode(final String name, NetconfNodeConnectionStatus.ConnectionStatus status) {
+ Host host = new Host(new IpAddress(new Ipv4Address("192.168.255.101")));
+ PortNumber portNumber = new PortNumber(2830);
+
+ List<String> avaibleCapabilitiesList = new ArrayList<>();
+ avaibleCapabilitiesList.add(V3PO_CAPABILITY);
+ avaibleCapabilitiesList.add(INTERFACES_CAPABILITY);
+
+ NetconfNode netconfNode = new NetconfNodeBuilder().setHost(host)
+ .setPort(portNumber)
+ .setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().build())
+ .setAvailableCapabilities(
+ new AvailableCapabilitiesBuilder().setAvailableCapability(avaibleCapabilitiesList).build())
+ .setConnectionStatus(status)
+ .build();
+
+ return new NodeBuilder().setNodeId(new NodeId(name)).addAugmentation(NetconfNode.class, netconfNode).build();
+ }
+
+ @Test
+ public void connectNode() throws ReadFailedException {
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+ Node testVppNode = createNode(NODE_NAME, NetconfNodeConnectionStatus.ConnectionStatus.Connected);
+
+ writeTransaction.put(LogicalDatastoreType.OPERATIONAL, nodeIid, testVppNode, true);
+
+ writeTransaction.submit();
+
+ ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Renderer>, ReadFailedException> future =
+ readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL,
+ VppIidFactory.getRendererIID(new RendererKey(VppNodeManager.vppRenderer)));
+ Optional<Renderer> rendererOptional = future.checkedGet();
+
+ Assert.assertTrue(rendererOptional.isPresent());
+ Assert.assertEquals(1, rendererOptional.get().getRendererNodes().getRendererNode().size());
+ Assert.assertEquals(nodeIid, rendererOptional.get().getRendererNodes().getRendererNode().get(0).getNodePath());
+ }
+
+ @Test
+ public void disconnectNode() throws ReadFailedException, InterruptedException {
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+ Node testVppNode = createNode(NODE_NAME, NetconfNodeConnectionStatus.ConnectionStatus.Connected);
+
+ writeTransaction.put(LogicalDatastoreType.OPERATIONAL, nodeIid, testVppNode, true);
+
+ writeTransaction.submit();
+
+ ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Renderer>, ReadFailedException> future =
+ readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL,
+ VppIidFactory.getRendererIID(new RendererKey(VppNodeManager.vppRenderer)));
+ Optional<Renderer> rendererOptional = future.checkedGet();
+
+ Assert.assertTrue(rendererOptional.isPresent());
+ Assert.assertEquals(1, rendererOptional.get().getRendererNodes().getRendererNode().size());
+ Assert.assertEquals(nodeIid, rendererOptional.get().getRendererNodes().getRendererNode().get(0).getNodePath());
+
+ WriteTransaction writeTransaction2 = dataBroker.newWriteOnlyTransaction();
+ Node testVppNode2 = createNode(NODE_NAME, NetconfNodeConnectionStatus.ConnectionStatus.Connecting);
+
+ writeTransaction2.put(LogicalDatastoreType.OPERATIONAL, nodeIid, testVppNode2, true);
+
+ writeTransaction2.submit();
+
+ ReadOnlyTransaction readOnlyTransaction2 = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Renderer>, ReadFailedException> future2 =
+ readOnlyTransaction2.read(LogicalDatastoreType.OPERATIONAL,
+ VppIidFactory.getRendererIID(new RendererKey(VppNodeManager.vppRenderer)));
+ Optional<Renderer> rendererOptional2 = future2.checkedGet();
+
+ Assert.assertTrue(rendererOptional2.isPresent());
+ Assert.assertEquals(0, rendererOptional2.get().getRendererNodes().getRendererNode().size());
+ }
+
+ @After
+ public void cleanUp() throws Exception {
+ vppNodeListener.close();
+ }
+}
--- /dev/null
+package org.opendaylight.groupbasedpolicy.renderer.vpp.util;
+
+import com.google.common.util.concurrent.Futures;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+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.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.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link VppNodeWriter}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class VppNodeWriterTest {
+
+ private static final String RENDERER_NAME = "vpp-renderer";
+
+ @Mock
+ private DataBroker dataBroker;
+ @Mock
+ private WriteTransaction wTx;
+ @Captor
+ private ArgumentCaptor<InstanceIdentifier<RendererNodes>> rendererNodesPathCpt;
+ @Captor
+ private ArgumentCaptor<RendererNodes> rendererNodesCpt;
+
+ private InOrder inOrder;
+
+ private VppNodeWriter nodeWriter;
+
+ @Before
+ public void setUp() throws Exception {
+ nodeWriter = new VppNodeWriter();
+ Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wTx);
+ Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testCommitToDatastore_with_node() throws Exception {
+ final RendererNode node = new RendererNodeBuilder().build();
+ nodeWriter.cache(node);
+ nodeWriter.commitToDatastore(dataBroker);
+
+ commonChecks();
+
+ final RendererNodes rendererNodes = rendererNodesCpt.getValue();
+ Assert.assertEquals(1, rendererNodes.getRendererNode().size());
+ }
+
+ @Test
+ public void testCommitToDatastore_empty() throws Exception {
+ nodeWriter.commitToDatastore(dataBroker);
+
+ commonChecks();
+
+ final RendererNodes rendererNodes = rendererNodesCpt.getValue();
+ Assert.assertEquals(0, rendererNodes.getRendererNode().size());
+ }
+
+ private void commonChecks() {
+ inOrder = Mockito.inOrder(dataBroker, wTx);
+ inOrder.verify(dataBroker).newWriteOnlyTransaction();
+ inOrder.verify(wTx).merge(Matchers.eq(LogicalDatastoreType.OPERATIONAL), rendererNodesPathCpt.capture(),
+ rendererNodesCpt.capture(), Matchers.eq(true));
+ inOrder.verify(wTx).submit();
+
+ final InstanceIdentifier<RendererNodes> rendererNodesPath = rendererNodesPathCpt.getValue();
+ Assert.assertEquals(RENDERER_NAME, extractRendererName(rendererNodesPath));
+ }
+
+ private String extractRendererName(final InstanceIdentifier<RendererNodes> rendererNodesPath) {
+ return rendererNodesPath.firstKeyOf(Renderer.class).getName().getValue();
+ }
+}