Add Translator for MultipartDescReply 61/2961/1
authorEd Warnicke <eaw@cisco.com>
Wed, 20 Nov 2013 00:41:38 +0000 (18:41 -0600)
committerEd Warnicke <eaw@cisco.com>
Thu, 21 Nov 2013 16:45:39 +0000 (08:45 -0800)
This successfully adds to the information visible
via RESTCONF for inventory.

Also, there's InventoryDataServiceUtils... full of handiness.

Change-Id: Id28b08cff0bb68a2c8ebcee30af8753a947f8559
Signed-off-by: Ed Warnicke <eaw@cisco.com>
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/ConnectionConductorImpl.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/MDController.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/SalRegistrationManager.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/translator/MultiPartMessageDescToNodeUpdatedTranslator.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/util/InventoryDataServiceUtil.java [new file with mode: 0644]

index 22bf210ef943d853d80233f02df7995be7e41a61..7ce355a1e0d12550d8f4cf9a7079d70639926ee5 100644 (file)
@@ -8,17 +8,26 @@
 
 package org.opendaylight.openflowplugin.openflow.md.core;
 
+import java.math.BigInteger;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener;
 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
 import org.opendaylight.openflowplugin.openflow.md.core.session.SessionManager;
 import org.opendaylight.openflowplugin.openflow.md.queue.QueueKeeper;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInputBuilder;
@@ -29,10 +38,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDescBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
@@ -82,7 +94,7 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
         this.connectionAdapter = connectionAdapter;
         conductorState = CONDUCTOR_STATE.HANDSHAKING;
         hsPool = Executors.newFixedThreadPool(1);
-        handshakeManager = new HandshakeManagerImpl(connectionAdapter, 
+        handshakeManager = new HandshakeManagerImpl(connectionAdapter,
                 ConnectionConductor.versionOrder.get(0), ConnectionConductor.versionOrder);
         handshakeManager.setUseVersionBitmap(isBitmapNegotiationEnable);
         handshakeManager.setHandshakeListener(this);
@@ -94,7 +106,7 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
         connectionAdapter.setSystemListener(this);
         connectionAdapter.setConnectionReadyListener(this);
     }
-    
+
     @Override
     public void setQueueKeeper(QueueKeeper<OfHeader, DataObject> queueKeeper) {
         this.queueKeeper = queueKeeper;
@@ -319,16 +331,30 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
         LOG.debug("connection is ready-to-use");
         hsPool.execute(handshakeManager);
     }
-    
+
     @Override
     public void onHandshakeSuccessfull(GetFeaturesOutput featureOutput,
             Short negotiatedVersion) {
         version = negotiatedVersion;
         conductorState = CONDUCTOR_STATE.WORKING;
-        
-        OFSessionUtil.registerSession(this, featureOutput, negotiatedVersion);        
+        OFSessionUtil.registerSession(this, featureOutput, negotiatedVersion);
+        requestDesc();
+    }
+
+    /*
+     *  Send an OFPMP_DESC request message to the switch
+     */
+
+    private void requestDesc() {
+        MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
+        builder.setType(MultipartType.OFPMPDESC);
+        builder.setVersion(getVersion());
+        builder.setFlags(new MultipartRequestFlags(false));
+        builder.setMultipartRequestBody(new MultipartRequestDescBuilder().build());
+        builder.setXid(getSessionContext().getNextXid());
+        getConnectionAdapter().multipartRequest(builder.build());
     }
-    
+
     /**
      * @param isBitmapNegotiationEnable the isBitmapNegotiationEnable to set
      */
@@ -336,7 +362,7 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
             boolean isBitmapNegotiationEnable) {
         this.isBitmapNegotiationEnable = isBitmapNegotiationEnable;
     }
-    
+
     protected void shutdownPool() {
         hsPool.shutdownNow();
         LOG.debug("pool is terminated: {}", hsPool.isTerminated());
index 619d8c861d031370a09dfe26945baba6c5640067..58aa5dd3cbf4b2c3502580ef01c5843cc342db8c 100644 (file)
@@ -25,10 +25,13 @@ import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionPro
 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.translator.ErrorTranslator;
 import org.opendaylight.openflowplugin.openflow.md.core.translator.ExperimenterTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.MultiPartMessageDescToNodeUpdatedTranslator;
 import org.opendaylight.openflowplugin.openflow.md.core.translator.PacketInTranslator;
 import org.opendaylight.openflowplugin.openflow.md.queue.PopListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
@@ -75,12 +78,14 @@ public class MDController implements IMDController {
         addMessageTranslator(ErrorMessage.class, OF13, new ErrorTranslator());
         addMessageTranslator(PacketInMessage.class,OF10, new PacketInTranslator());
         addMessageTranslator(PacketInMessage.class,OF13, new PacketInTranslator());
-        addMessageTranslator(ExperimenterMessage.class, OF10, new ExperimenterTranslator());       
+        addMessageTranslator(MultipartReplyMessage.class,OF13, new MultiPartMessageDescToNodeUpdatedTranslator());
+        addMessageTranslator(ExperimenterMessage.class, OF10, new ExperimenterTranslator());
 
         //TODO: move registration to factory
         NotificationPopListener<DataObject> notificationPopListener = new NotificationPopListener<DataObject>();
         addMessagePopListener(PacketReceived.class,notificationPopListener);
         addMessagePopListener(TransmitPacketInput.class, notificationPopListener);
+        addMessagePopListener(NodeUpdated.class, notificationPopListener);
 
         // Push the updated Listeners to Session Manager which will be then picked up by ConnectionConductor eventually
         OFSessionUtil.getSessionManager().setTranslatorMapping(messageTranslators);
index 681aa1b71d0622cc0ba575040536bf6ca8ad7ef6..89f4223b2220f9f85e0446b275e1e34e6558b85a 100644 (file)
@@ -67,7 +67,6 @@ public class SalRegistrationManager implements SessionListener, SwitchInventory
         this.providerContext = session;
         this.publishService = session.getSALService(NotificationProviderService.class);
         this.dataService = session.getSALService(DataProviderService.class);
-
         // We register as listener for Session Manager
         getSessionManager().registerSessionListener(this);
         getSessionManager().setNotificationProviderService(publishService);
@@ -123,10 +122,9 @@ public class SalRegistrationManager implements SessionListener, SwitchInventory
     }
 
     public static InstanceIdentifier<Node> identifierFromDatapathId(BigInteger datapathId) {
-        InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
-
         NodeKey nodeKey = nodeKeyFromDatapathId(datapathId);
-        return builder.node(Node.class, nodeKey).toInstance();
+        InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder(Node.class,nodeKey);
+        return (InstanceIdentifier<Node>) builder.toInstance();
     }
 
     public static NodeKey nodeKeyFromDatapathId(BigInteger datapathId) {
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/translator/MultiPartMessageDescToNodeUpdatedTranslator.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/translator/MultiPartMessageDescToNodeUpdatedTranslator.java
new file mode 100644 (file)
index 0000000..bb1cc8f
--- /dev/null
@@ -0,0 +1,46 @@
+package org.opendaylight.openflowplugin.openflow.md.core.translator;
+
+import java.math.BigInteger;
+
+import org.opendaylight.openflowplugin.openflow.md.core.IMDMessageTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDesc;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MultiPartMessageDescToNodeUpdatedTranslator implements IMDMessageTranslator<OfHeader, DataObject> {
+    protected static final Logger LOG = LoggerFactory.getLogger(PacketInTranslator.class);
+    @Override
+    public NodeUpdated translate(SwitchConnectionDistinguisher cookie,
+            SessionContext sc, OfHeader msg) {
+        if(msg instanceof MultipartReply && ((MultipartReply) msg).getType() == MultipartType.OFPMPDESC) {
+            LOG.info("MultipartReplyMessage Being translated to NodeUpdated ");
+            MultipartReplyMessage message = (MultipartReplyMessage) msg;
+            BigInteger datapathId = sc.getFeatures().getDatapathId();
+            NodeUpdatedBuilder builder = InventoryDataServiceUtil.nodeUpdatedBuilderFromDataPathId(datapathId);
+            FlowCapableNodeUpdatedBuilder fnub = new FlowCapableNodeUpdatedBuilder();
+            MultipartReplyDesc body = (MultipartReplyDesc) message.getMultipartReplyBody();
+            fnub.setHardware(body.getHwDesc());
+            fnub.setManufacturer(body.getMfrDesc());
+            fnub.setSerialNumber(body.getSerialNum());
+            fnub.setDescription(body.getDpDesc());
+            fnub.setSoftware(body.getSwDesc());
+            builder.addAugmentation(FlowCapableNodeUpdated.class, fnub.build());
+            return builder.build();
+        } else {
+            return null;
+        }
+    }
+
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/util/InventoryDataServiceUtil.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/util/InventoryDataServiceUtil.java
new file mode 100644 (file)
index 0000000..546791c
--- /dev/null
@@ -0,0 +1,131 @@
+package org.opendaylight.openflowplugin.openflow.md.util;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InventoryDataServiceUtil {
+    private final static Logger LOG = LoggerFactory.getLogger(InventoryDataServiceUtil.class);
+    /*
+     *   Get an InstanceIdentifier for the Nodes class that is the root of the inventory tree
+     *   We use this alot, so its worth keeping around
+     */
+    private  InstanceIdentifier<Nodes> nodesIdentifier = InstanceIdentifier.builder().node(Nodes.class).toInstance();
+
+    /*
+     * The DataProviderService is how we access the DataTree
+     */
+    private  DataProviderService dataService;
+
+    public InventoryDataServiceUtil(DataProviderService dataService) {
+        // Save the dataService
+        this.dataService = dataService;
+    }
+
+    public  List<Node> readAllNodes() {
+        Nodes nodes = (Nodes) dataService.readOperationalData(nodesIdentifier);
+        return nodes.getNode();
+    }
+
+    public Node readNode(InstanceIdentifier<Node> instance) {
+        return (Node) dataService.readOperationalData(instance);
+    }
+
+    public Node readNode(NodeRef nodeRef) {
+        return readNode((InstanceIdentifier<Node>) nodeRef.getValue());
+    }
+
+    public Node readNode(NodeKey nodeKey) {
+        return readNode(nodeKeyToInstanceIdentifier(nodeKey));
+    }
+
+    public Node readNode(NodeId nodeId) {
+        return readNode(new NodeKey(nodeId));
+    }
+
+
+    public  Node readNodeByDataPath(BigInteger datapathId) {
+        return (Node) dataService.readOperationalData(identifierFromDatapathId(datapathId));
+    }
+
+    public void putNode(Node node) {
+        DataModificationTransaction transaction = dataService.beginTransaction();
+        transaction.putOperationalData(nodesIdentifier, node);
+        transaction.commit();
+    }
+
+    public void putNodeConnector(InstanceIdentifier<Node> instance,NodeConnector nodeConnector) {
+        DataModificationTransaction transaction = dataService.beginTransaction();
+        transaction.putOperationalData(instance, nodeConnector);
+        transaction.commit();
+    }
+
+    public void putNodeConnector(NodeKey nodeKey,NodeConnector nodeConnector) {
+        InstanceIdentifier<Node> instance = nodeKeyToInstanceIdentifier(nodeKey);
+        putNodeConnector(instance,nodeConnector);
+    }
+
+
+
+    public void putNodeConnector(NodeId nodeId,NodeConnector nodeConnector) {
+        putNodeConnector(new NodeKey(nodeId),nodeConnector);
+    }
+
+    public void putNodeConnector(BigInteger datapathId, NodeConnector nodeConnector) {
+        putNodeConnector(new NodeId("openflow:" + datapathId),nodeConnector);
+    }
+
+    public static InstanceIdentifier<Node> identifierFromDatapathId(BigInteger datapathId) {
+        InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+
+        NodeKey nodeKey = nodeKeyFromDatapathId(datapathId);
+        return builder.node(Node.class, nodeKey).toInstance();
+    }
+
+    public static NodeKey nodeKeyFromDatapathId(BigInteger datapathId) {
+        return new NodeKey(nodeIdFromDatapathId(datapathId));
+    }
+
+    public static NodeUpdatedBuilder nodeUpdatedBuilderFromDataPathId(BigInteger datapathId) {
+        NodeUpdatedBuilder builder = new NodeUpdatedBuilder();
+        builder.setId(nodeIdFromDatapathId(datapathId));
+        builder.setNodeRef(nodeRefFromNodeKey(new NodeKey(builder.getId())));
+        return builder;
+    }
+
+    public static NodeId nodeIdFromDatapathId(BigInteger datapathId) {
+        // FIXME: Convert to textual representation of datapathID
+        String current = datapathId.toString();
+        return new NodeId("openflow:" + current);
+    }
+
+    public static NodeRef nodeRefFromNode(Node node) {
+        InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+        return new NodeRef(builder.node(Node.class,node.getKey()).toInstance());
+    }
+
+    public static NodeRef nodeRefFromNodeKey(NodeKey nodeKey) {
+        InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+        return new NodeRef(builder.node(Node.class,nodeKey).toInstance());
+    }
+
+    public static InstanceIdentifier<Node> nodeKeyToInstanceIdentifier(NodeKey nodeKey) {
+        InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+        InstanceIdentifier<Node> instance = builder.node(Node.class,nodeKey).toInstance();
+        return instance;
+    }
+
+}