Dev guide netconf 09/23609/1
authorMaros Marsalek <mmarsale@cisco.com>
Thu, 25 Jun 2015 08:20:21 +0000 (10:20 +0200)
committerColin Dixon <colin@colindixon.com>
Tue, 30 Jun 2015 20:02:40 +0000 (20:02 +0000)
Change-Id: I91d8a922e610d74fde092684a8456dd547aeb107
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
(cherry picked from commit 44c0a2a1cfc606eb459a4f5c53a578a3ffdf2789)

manuals/developer-guide/src/main/asciidoc/bk-developers-guide.adoc
manuals/developer-guide/src/main/asciidoc/controller/netconf/odl-netconf-dev.adoc [new file with mode: 0644]

index b524ca0bf690b0b318064d115f8fcd314dfe6059..d5f03be0407314582820a00d79ab7aa63f3e9167 100644 (file)
@@ -70,6 +70,8 @@ include::l2switch/l2switch-dev.adoc[]
 
 include::lacp/lacp-dev.adoc[]
 
+include::controller/netconf/odl-netconf-dev.adoc[]
+
 include::nic/nic-dev.adoc[]
 
 include::neutron/neutron.adoc[]
diff --git a/manuals/developer-guide/src/main/asciidoc/controller/netconf/odl-netconf-dev.adoc b/manuals/developer-guide/src/main/asciidoc/controller/netconf/odl-netconf-dev.adoc
new file mode 100644 (file)
index 0000000..28a89f2
--- /dev/null
@@ -0,0 +1,209 @@
+== NETCONF Developer Guide
+
+NOTE: Reading the NETCONF section in the User Guide is likely useful as
+      it contains an overview of NETCONF in OpenDaylight and a how-to
+      for spawning and configuring NETCONF connectors.
+
+This chapter is recommended for application developers who want to
+interact with mounted NETCONF devices from their application code. It
+tries to demonstrate all the use cases from user guide with
+RESTCONF but now from the code level. One important difference would
+be the demonstration of NETCONF notifications and notification
+listeners. The notifications were not shown using RESTCONF because
+*RESTCONF does not support notifications from mounted NETCONF
+devices.*
+
+NOTE: It may also be useful to read the generic 
+      https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:MD-SAL_App_Tutorial[OpenDaylight
+      MD-SAL app
+      development tutorial] before diving into this chapter.
+      This guide assumes awareness of basic OpenDaylight application
+      development.
+
+=== Sample app overview
+All the examples presented here are implemented by a sample OpenDaylight
+application called *ncmount* in the `coretutorials` OpenDaylight project.
+It can be found on the github mirror of OpenDaylight's repositories:
+
+* https://github.com/opendaylight/coretutorials/tree/stable/lithium/ncmount
+
+or checked out from the official OpenDaylight repository:
+
+* https://git.opendaylight.org/gerrit/#/admin/projects/coretutorials
+
+*The application was built using the
+https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Startup_Project_Archetype[project
+startup maven archetype] and demonstrates how to:*
+
+* preconfigure connectors to NETCONF devices
+* retrieve MountPointService (registry of available mount points)
+* listen and react to changing connection state of netconf-connector
+* add custom device YANG models to the app and work with them
+* read data from device in binding aware format (generated java APIs
+  from provided YANG models)
+* write data into device in binding aware format
+* trigger and listen to NETCONF notifications in binding aware format
+
+Detailed information about the structure of the application can be
+found at:
+https://wiki.opendaylight.org/view/Controller_Core_Functionality_Tutorials:Tutorials:Netconf_Mount
+// TODO Migrate the information from wiki here
+
+NOTE: The code in ncmount is fully *binding aware* (works with generated
+java APIs from provided YANG models). However it is also possible to
+perform the same operations in *binding independent* manner.
+// TODO Add BI NcmountProvider version into the sample app and link it from here
+
+==== NcmountProvider
+The NcmountProvider class (found in NcmountProvider.java) is the central
+point of the ncmount application and all the application logic is
+contained there. The following sections will detail its most interesting
+pieces.
+
+===== Retrieve MountPointService
+The MountPointService is a central registry of all available mount points
+in OpenDaylight. It is just another MD-SAL service and is available from the
++session+ attribute passed by +onSessionInitiated+ callback:
+
+----
+@Override
+public void onSessionInitiated(ProviderContext session) {
+    LOG.info("NcmountProvider Session Initiated");
+
+    // Get references to the data broker and mount service
+    this.mountService = session.getSALService(MountPointService.class);
+
+    ...
+
+    }
+}
+----
+
+===== Listen for connection state changes
+It is important to know when a mount point appears, when it is fully
+connected and when it is disconnected or removed. The exact states of a
+mount point are:
+
+* Connected
+* Connecting
+* Unable to connect
+
+To receive this kind of information, an application has to register
+itself as a notification listener for the preconfigured
+netconf-topology subtree in MD-SAL's datastore. This can be performed
+in the +onSessionInitiated+ callback as well:
+
+----
+@Override
+public void onSessionInitiated(ProviderContext session) {
+
+    ...
+
+    this.dataBroker = session.getSALService(DataBroker.class);
+
+    // Register ourselves as the REST API RPC implementation
+    this.rpcReg = session.addRpcImplementation(NcmountService.class, this);
+
+    // Register ourselves as data change listener for changes on Netconf
+    // nodes. Netconf nodes are accessed via "Netconf Topology" - a special
+    // topology that is created by the system infrastructure. It contains
+    // all Netconf nodes the Netconf connector knows about. NETCONF_TOPO_IID
+    // is equivalent to the following URL:
+    // .../restconf/operational/network-topology:network-topology/topology/topology-netconf
+    if (dataBroker != null) {
+        this.dclReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                NETCONF_TOPO_IID.child(Node.class),
+                this,
+                DataChangeScope.SUBTREE);
+    }
+}
+----
+
+The implementation of the callback from MD-SAL when the data change can be
+found in the
++onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>
+change)+ callback of
+https://github.com/opendaylight/coretutorials/blob/stable/lithium/ncmount/impl/src/main/java/ncmount/impl/NcmountProvider.java[NcmountProvider
+class].
+
+===== Reading data from the device
+The first step when trying to interact with the device is to get the exact
+mount point instance (identified by an instance identifier) from the MountPointService:
+
+----
+@Override
+public Future<RpcResult<ShowNodeOutput>> showNode(ShowNodeInput input) {
+    LOG.info("showNode called, input {}", input);
+
+    // Get the mount point for the specified node
+    // Equivalent to '.../restconf/<config | operational>/opendaylight-inventory:nodes/node/<node-name>/yang-ext:mount/'
+    // Note that we can read both config and operational data from the same
+    // mount point
+    final Optional<MountPoint> xrNodeOptional = mountService.getMountPoint(NETCONF_TOPO_IID
+            .child(Node.class, new NodeKey(new NodeId(input.getNodeName()))));
+
+    Preconditions.checkArgument(xrNodeOptional.isPresent(),
+            "Unable to locate mountpoint: %s, not mounted yet or not configured",
+            input.getNodeName());
+    final MountPoint xrNode = xrNodeOptional.get();
+
+    ....
+}
+----
+
+NOTE: The triggering method in this case is called +showNode+. It is a
+YANG-defined RPC and NcmountProvider serves as an MD-SAL RPC
+implementation among other things. This means that +showNode+ an be
+triggered using RESTCONF.
+
+The next step is to retrieve an instance of the +DataBroker+ API from the
+mount point and start a read transaction:
+
+----
+@Override
+public Future<RpcResult<ShowNodeOutput>> showNode(ShowNodeInput input) {
+
+    ...
+
+    // Get the DataBroker for the mounted node
+    final DataBroker xrNodeBroker = xrNode.getService(DataBroker.class).get();
+    // Start a new read only transaction that we will use to read data
+    // from the device
+    final ReadOnlyTransaction xrNodeReadTx = xrNodeBroker.newReadOnlyTransaction();
+
+    ...
+}
+----
+
+Finally, it is possible to perform the read operation:
+
+----
+@Override
+public Future<RpcResult<ShowNodeOutput>> showNode(ShowNodeInput input) {
+
+    ...
+
+    InstanceIdentifier<InterfaceConfigurations> iid =
+            InstanceIdentifier.create(InterfaceConfigurations.class);
+
+    Optional<InterfaceConfigurations> ifConfig;
+    try {
+        // Read from a transaction is asynchronous, but a simple
+        // get/checkedGet makes the call synchronous
+        ifConfig = xrNodeReadTx.read(LogicalDatastoreType.CONFIGURATION, iid).checkedGet();
+    } catch (ReadFailedException e) {
+        throw new IllegalStateException("Unexpected error reading data from " + input.getNodeName(), e);
+    }
+
+    ...
+}
+----
+
+The instance identifier is used here again to specify a subtree to read
+from the device. At this point application can process the data as it sees
+fit. The ncmount app transforms the data into its own format and returns
+it from +showNode+.
+
+NOTE: More information can be found in the source code of ncmount
+sample app + on wiki:
+https://wiki.opendaylight.org/view/Controller_Core_Functionality_Tutorials:Tutorials:Netconf_Mount