1 NETCONF Developer Guide
2 =======================
6 Reading the NETCONF section in the User Guide is likely useful as it
7 contains an overview of NETCONF in OpenDaylight and a how-to for
8 spawning and configuring NETCONF connectors.
10 This chapter is recommended for application developers who want to
11 interact with mounted NETCONF devices from their application code. It
12 tries to demonstrate all the use cases from user guide with RESTCONF but
13 now from the code level. One important difference would be the
14 demonstration of NETCONF notifications and notification listeners. The
15 notifications were not shown using RESTCONF because **RESTCONF does not
16 support notifications from mounted NETCONF devices.**
20 It may also be useful to read the generic `OpenDaylight MD-SAL app
22 tutorial <https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:MD-SAL_App_Tutorial>`__
23 before diving into this chapter. This guide assumes awareness of
24 basic OpenDaylight application development.
29 All the examples presented here are implemented by a sample OpenDaylight
30 application called **ncmount** in the ``coretutorials`` OpenDaylight
31 project. It can be found on the github mirror of OpenDaylight’s
34 - https://github.com/opendaylight/coretutorials/tree/stable/boron/ncmount
36 or checked out from the official OpenDaylight repository:
38 - https://git.opendaylight.org/gerrit/#/admin/projects/coretutorials
40 **The application was built using the `project startup maven
41 archetype <https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Startup_Project_Archetype>`__
42 and demonstrates how to:**
44 - preconfigure connectors to NETCONF devices
46 - retrieve MountPointService (registry of available mount points)
48 - listen and react to changing connection state of netconf-connector
50 - add custom device YANG models to the app and work with them
52 - read data from device in binding aware format (generated java APIs
53 from provided YANG models)
55 - write data into device in binding aware format
57 - trigger and listen to NETCONF notifications in binding aware format
59 Detailed information about the structure of the application can be found
61 https://wiki.opendaylight.org/view/Controller_Core_Functionality_Tutorials:Tutorials:Netconf_Mount
65 The code in ncmount is fully **binding aware** (works with generated
66 java APIs from provided YANG models). However it is also possible to
67 perform the same operations in **binding independent** manner.
72 The NcmountProvider class (found in NcmountProvider.java) is the central
73 point of the ncmount application and all the application logic is
74 contained there. The following sections will detail its most interesting
77 Retrieve MountPointService
78 ^^^^^^^^^^^^^^^^^^^^^^^^^^
80 The MountPointService is a central registry of all available mount
81 points in OpenDaylight. It is just another MD-SAL service and is
82 available from the ``session`` attribute passed by
83 ``onSessionInitiated`` callback:
88 public void onSessionInitiated(ProviderContext session) {
89 LOG.info("NcmountProvider Session Initiated");
91 // Get references to the data broker and mount service
92 this.mountService = session.getSALService(MountPointService.class);
99 Listen for connection state changes
100 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
102 It is important to know when a mount point appears, when it is fully
103 connected and when it is disconnected or removed. The exact states of a
112 To receive this kind of information, an application has to register
113 itself as a notification listener for the preconfigured netconf-topology
114 subtree in MD-SAL’s datastore. This can be performed in the
115 ``onSessionInitiated`` callback as well:
120 public void onSessionInitiated(ProviderContext session) {
124 this.dataBroker = session.getSALService(DataBroker.class);
126 // Register ourselves as the REST API RPC implementation
127 this.rpcReg = session.addRpcImplementation(NcmountService.class, this);
129 // Register ourselves as data change listener for changes on Netconf
130 // nodes. Netconf nodes are accessed via "Netconf Topology" - a special
131 // topology that is created by the system infrastructure. It contains
132 // all Netconf nodes the Netconf connector knows about. NETCONF_TOPO_IID
133 // is equivalent to the following URL:
134 // .../restconf/operational/network-topology:network-topology/topology/topology-netconf
135 if (dataBroker != null) {
136 this.dclReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
137 NETCONF_TOPO_IID.child(Node.class),
139 DataChangeScope.SUBTREE);
143 The implementation of the callback from MD-SAL when the data change can
145 ``onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>
146 change)`` callback of `NcmountProvider
147 class <https://github.com/opendaylight/coretutorials/blob/stable/boron/ncmount/impl/src/main/java/ncmount/impl/NcmountProvider.java>`__.
149 Reading data from the device
150 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
152 The first step when trying to interact with the device is to get the
153 exact mount point instance (identified by an instance identifier) from
154 the MountPointService:
159 public Future<RpcResult<ShowNodeOutput>> showNode(ShowNodeInput input) {
160 LOG.info("showNode called, input {}", input);
162 // Get the mount point for the specified node
163 // Equivalent to '.../restconf/<config | operational>/opendaylight-inventory:nodes/node/<node-name>/yang-ext:mount/'
164 // Note that we can read both config and operational data from the same
166 final Optional<MountPoint> xrNodeOptional = mountService.getMountPoint(NETCONF_TOPO_IID
167 .child(Node.class, new NodeKey(new NodeId(input.getNodeName()))));
169 Preconditions.checkArgument(xrNodeOptional.isPresent(),
170 "Unable to locate mountpoint: %s, not mounted yet or not configured",
171 input.getNodeName());
172 final MountPoint xrNode = xrNodeOptional.get();
179 The triggering method in this case is called ``showNode``. It is a
180 YANG-defined RPC and NcmountProvider serves as an MD-SAL RPC
181 implementation among other things. This means that ``showNode`` an
182 be triggered using RESTCONF.
184 The next step is to retrieve an instance of the ``DataBroker`` API from
185 the mount point and start a read transaction:
190 public Future<RpcResult<ShowNodeOutput>> showNode(ShowNodeInput input) {
194 // Get the DataBroker for the mounted node
195 final DataBroker xrNodeBroker = xrNode.getService(DataBroker.class).get();
196 // Start a new read only transaction that we will use to read data
198 final ReadOnlyTransaction xrNodeReadTx = xrNodeBroker.newReadOnlyTransaction();
203 Finally, it is possible to perform the read operation:
208 public Future<RpcResult<ShowNodeOutput>> showNode(ShowNodeInput input) {
212 InstanceIdentifier<InterfaceConfigurations> iid =
213 InstanceIdentifier.create(InterfaceConfigurations.class);
215 Optional<InterfaceConfigurations> ifConfig;
217 // Read from a transaction is asynchronous, but a simple
218 // get/checkedGet makes the call synchronous
219 ifConfig = xrNodeReadTx.read(LogicalDatastoreType.CONFIGURATION, iid).checkedGet();
220 } catch (ReadFailedException e) {
221 throw new IllegalStateException("Unexpected error reading data from " + input.getNodeName(), e);
227 The instance identifier is used here again to specify a subtree to read
228 from the device. At this point application can process the data as it
229 sees fit. The ncmount app transforms the data into its own format and
230 returns it from ``showNode``.
234 More information can be found in the source code of ncmount sample
236 https://wiki.opendaylight.org/view/Controller_Core_Functionality_Tutorials:Tutorials:Netconf_Mount