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