7 months, 2 weeks

NETCONF Protocol – Network Configuration Protocol





The Network Configuration Protocol (NETCONF) is a network management protocol allowing a network management system (NMS) to deliver, modify, and delete configurations of network devices. Standard application programming interfaces (APIs) are available on network devices for the NMS to manage the devices using NETCONF.

NETCONF uses Extensible Markup Language (XML)-based data encoding for the configuration data and protocol messages, and uses a simple remote procedure call (RPC) mechanism to implement communication between a client and a server. The protocol messages are exchanged on the top of a secure transport protocol.
 A client can be a script or an application running on an NMS. A server is typically a network device. 
NETCONF is primarily intended to be used as a device configuration mechanism, whereas SNMP is ordinarily used for monitoring, polling, and fault notification. 

Emergence of NETCONF

-NETCONF uses a hierarchical protocol framework, making it more suitable for on-demand, automated, and big data requirements of cloud-based networks.
-NETCONF uses XML encoding to define messages and uses the RPC mechanism to modify configuration data. This facilitates configuration data management and interoperability between devices from different vendors.
-NETCONF performs operations on devices based on the YANG model, reducing network faults caused by manual configuration errors.
-NETCONF provides security mechanisms such as authentication and authorization to ensure message transmission security.
-NETCONF provides a transaction mechanism to support data classification, storage, and migration, phase-based submission, configuration isolation, as well as overall configuration delivery, verification, and rollback, minimizing the impact on network services.
-NETCONF defines a variety of operation interfaces and supports extension on basis of capabilities. This allows vendors to define their own protocol operations, so as to implement unique management functions.

YANG(Yet Another Next Generation) is a data modeling language for NETCONF. It allows the description of hierarchies of data nodes ("nodes") and the constraints that exist among them. 
A YANG module defines a data model in terms of the data, its hierarchical organization, and the constraints on that data. YANG defines how this data is represented in XML and describe how the content of a message that is being sent to a device capable of being configured via 
NETCONF needs to be formatted. This information includes what kind of fields are included, what fields can be changed by the user, and what fields are read-only

The NETCONF architecture consists of two roles: client and server.

-A client provides the following functions:
    -Manages network devices using NETCONF.
    -Sends RPC requests to a NETCONF server to query or modify one or more parameter values.
    -Learns the status of a managed device based on the alarms and events sent by the NETCONF server of the managed device.
-A server maintains information about managed devices and responds to the client-initiated requests.
    -When receiving a request from a NETCONF client, the NETCONF server parses the request and sends a reply to the client.
    -If a fault or another type of event occurs on a managed device, the NETCONF server reports an alarm or event to the client through the notification mechanism. This allows the client to learn the status of the managed device.

The NETCONF protocol are often conceptually partitioned into four layers:
Secure Transport layer
This layer provides a communication path between the client and server. NETCONF can be layered over any transport protocol that meets basic requirements.

Secure Shell (SSH) is the preferred transport protocol in NETCONF for transmitting XML information. Currently, Huawei devices support SSH as the transport protocol of NETCONF.

Messages layer
This layer provides a simple, transport-independent framing mechanism for encoding RPCs and notifications.

A client encapsulates an RPC request into an <rpc> element and sends it to a server. The server encapsulates the result of processing this request into an <rpc-reply> element and sends it to the client.

Operations layer
This layer defines a set of base protocol operations, which are invoked as RPC methods with XML-encoded parameters.

Content layer
This layer is defined by a data model that manages data. Currently, mainstream data models include Schema and YANG.

Schema is a set of rules defined to describe XML files. A device uses a Schema file (similar to an SNMP MIB file) to provide device configuration and management interfaces for an NMS.


Generally, the client and server perform the following steps to obtain and modify configurations:

-The client and server establish a connection-oriented transport protocol session.
-The client and server exchange Hello messages for capabilities negotiation (for example, both support the latest NETCONF version), preventing ambiguity during data parsing.
-The client sends an <rpc> request to the server.
-The server receives and parses the <rpc> request, and verifies validity of this request based on the definition of the YANG data model.
-The server executes the <rpc> request, and returns an <rpc-reply> message containing the execution result to the client.
-The client receives and parses the <rpc-reply> message.

The core operations defined by the NETCONF protocol are as follows:
• <get>: This is used to retrieve information about the state of a device.
• <get-config>: This is used to retrieve an entire configuration (for example, the entire running configuration of your device).
• <edit-config>: This is used to edit a configuration (for example, to change the entire running configuration on your device). Here, edit can refer to creating, deleting, or combining configuration variables.
• <copy-config>: This is used to copy from one configuration to another (for example, to copy your running configuration to your startup configuration).
• <delete-config>: This is used to delete an entire configuration.
• <lock>: This is used to lock a configuration (for example, your running configuration). This allows you to make sure that no other process is manipulating this specific configuration.
• <unlock>: This is used to release a lock that was previously obtained using the <lock> operation.
• <close-session>: This is used to terminate a NETCONF session.
• <kill-session>: This is used to force the termination of a NETCONF session.


Model-Driven Programmability with NETCONF and ncclient

NETCONF uses TCP port 830 and SSH as its transport protocol. Please make sure that your firewall does not block any communications on this port.
YANG is a powerful tool that you can use to model how data should be structured. And while we could use YANG to model any kind of data, it is predominantly used to model the data of the configurational state of network devices.
There are certain models provided by OpenConfig. OpenConfig takes common network structures, such as VLANs or the configuration of the Open Shortest Path First (OSPF)protocol, and implements them consistently across different vendors. The benefit of writing an automation workflow purely using the YANG modules of OpenConfig is that the same workflow can be applied to the devices of different vendors and will have the same configurational effect. This is extremely useful when you are dealing with multi-vendor networks.
For those features that are specific to a vendor platform, most vendors, including Huawei, Cisco, and Juniper, maintain platform- and vendor-specific YANG modules for their specific devices and features.

ncclient is a Python library for NETCONF clients. It aims to offer an intuitive API that sensibly maps the XML-encoded nature of NETCONF to Python constructs and idioms, and make writing network-management scripts easier. Other key features are:
-Supports all operations and capabilities defined in RFC 6241.
-Request pipelining.
-Asynchronous RPC requests.
-Keeping XML out of the way unless really needed.
-Extensible. New transport mappings and capabilities/operations can be easily added.


Connecting to a network device using ncclient

NETCONF is built on top of the Remote Procedure Call(RPC) protocol, and while we could use a generic library that implements this protocol, 
the ncclient package has been purposely built to be used to connect to network devices using NETCONF and, therefore, issue RPC calls to the device.

The following steps will allow us to connect to a network device and retrieve all of the available OpenConfig YANG modules:
1. Import the manager from ncclient using the following command:
from ncclient import manager

2. Create a dictionary with all of the connection details:
conn_info = {
 "host": "<insert your host here>",
 "port": <insert the port number here>,
 "username": "<insert the username here>",
 "password": "<insert the password here>",
 "hostkey_verify": False
}
3. With the connection details defined, we can create a connection to our network device using the ncclient manager, as follows:
device = manager.connect(**conn_info)

4. With our connection established, we can now retrieve the list of available modules. These are also known as the device's capabilities:
capabilities = device.server_capabilities
5. Finally, we can iterate over each of those capabilities and search for the YANG modules that are defined by OpenConfig as shown:
for cap in capabilities:
    if "http://openconfig.net/yang/" in cap:
         print(cap)

Using NETCONF and ncclient to retrieve the running configuration
To establish a connection to your device and retrieve the currently running configuration in XML format, follow these steps:
1. Import the manager from ncclient along with the prettyprint module from the standard library:
from ncclient import manager
import pprint

2. Create a dictionary with all of the connection details:
conn_info = {
 "host": "<insert your host here>",
 "port": <insert the port number here>,
 "username": "<insert the username here>",
 "password": "<insert the password here>",
 "hostkey_verify": False
}
3. With the connection details defined, we can create a connection to our network device using the ncclient manager, as follows:
device = manager.connect(**conn_info)
4. With our connection established, we can retrieve the running configuration using the following: 
conf = device.get_config(source='running').data_xml
5. Finally, print out the running configuration's XML:
pprint.pprint(conf)

While the core concept of ncclient is to be vendor agnostic, version 0.4.1 introduced a number of changes that allowed for more vendor-specific handling. This means that if you know the device you are running against, you can give this information to ncclient and the library will adapt to the specifics of the devices operating system/platform. To do so, we need another connection detail, called device_params, which is a dictionary that contains device-specific information such as the name of this device/vendor. We can modify our conn_info dictionary to look like this when we are dealing with a Juniper device:
 conn_info = {
 "host": "<insert your host here>",
 "port": <insert the port number here>,
 "username": "<insert the username here>",
 "password": "<insert the password here>",
 "hostkey_verify": False,
 "device_params": {
 "name": "junos"
 }
}
Notice that the additional device_params parameter is a dictionary itself. At the time of writing, the following device handlers and their associated vendors are supported: 
• junos for Juniper
• csr for Cisco CSR devices
• nexus for Cisco Nexus devices
• iosxr for Cisco IOS XR devices
• iosxe for Cisco IOS XE devices
• huawei or huaweiyang for Huawei devices
• alu for Alcatel Lucent devices
• h3c for H3C devices
• hpcomware for HP Comware devices
• default for anything that you either don't know the vendor of or is not part of the preceding list

Using NETCONF and ncclient to change the starting configuration

To, first, copy a running configuration to a file and then copy it to the starting configuration, follow these steps:
1. Import the manager from ncclient using the following command:
from ncclient import manager
2. Create a dictionary with all of the connection details:
conn_info = {
 "host": "<insert your host here>",
 "port": <insert the port number here>,
 "username": "<insert the username here>",
 "password": "<insert the password here>",
 "hostkey_verify": False
}

3. With the connection details defined, we can create a connection to our network device using the ncclient manager, as follows:
device = manager.connect(**conn_info)
4. With our connection established, we can first copy the running configuration to a new file, as shown here: 
device.copy_config(source='running', target='file:///current_running.conf')
5. Next, we can copy this newly created current_running.conf file over to our starting configuration using the following:
device.copy_config(source='file:///current_running.conf', target='starting')

Retrieving an interface configuration using NETCONF and ncclient
To retrieve the configured interfaces of your device, follow these steps:
1. Import the manager from ncclient using the following command:
from ncclient import manager
import pprint
2. Create a dictionary with all of the connection details, as follows:
conn_info = {
 "host": "<insert your host here>",
 "port": <insert the port number here>,
 "username": "<insert the username here>",
 "password": "<insert the password here>",
 "hostkey_verify": False
}
3. With the connection details defined, we can create a connection to our network device with the ncclient manager using the following commands:
device = manager.connect(**conn_info)
4. With our connection established, we can now define our filter: 
filter = """
<filter>
 <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietfinterfaces">
 <interface>
 </interface>
 </interfaces>
</filter>
"""
5. With our filter defined, we can apply it to our get_config() command, which is targeted at the running configuration:
conf = device.get_config(source='running', filter=filter).data_xml
6. Finally, print out the XML of the interfaces that was defined in our running configuration:
pprint.pprint(conf)

Changing an interface configuration using NETCONF and ncclient

To create the necessary XML for a new VLAN and to send the newly created VLAN configuration to the networking device, follow these steps:
1. Import the manager from ncclient using the following command:
from ncclient import manager
2. Create a dictionary with all of the connection details using the following commands:
conn_info = {
 "host": "<insert your host here>",
 "port": <insert the port number here>,
 "username": "<insert the username here>",
 "password": "<insert the password here>",
 "hostkey_verify": False
}
3. With the connection details defined, we can create a connection to our network device using the ncclient manager:
device = manager.connect(**conn_info)
4. With our connection established, we can now create the XML that we want to send to our device: 
vlan_conf = """
<vlan xmlns=http://openconfig.net/yang/vlan>
 <vlan-id>10</vlan-id>
 <config>
 <name>New VLAN</name>
 <status>ACTIVE</status>
 <vlan-id>10</vlan-id>
 </config>
</vlan>
"""
5. With our XML ready, we can now send it to the device by using the edit_config() method of the manager:
device.edit_config(target="running", config=vlan_conf)

Reacting to event notifications using NETCONF and ncclient

To subscribe to all notifications from your device, follow these steps:
1. Import the manager from ncclient using the following command:
from ncclient import manager
2. Create a dictionary with all of the connection details using the following commands:
conn_info = {
 "host": "<insert your host here>",
 "port": <insert the port number here>,
 "username": "<insert the username here>",
 "password": "<insert the password here>",
 "hostkey_verify": False
}
3. With the connection details defined, we can create a connection to our network device using the ncclient manager:
device = manager.connect(**conn_info)
4. With our connection established, first, we need to tell ncclient to subscribe to the events, as follows:
device.create_subscription()
5. With our events subscribed to, we now have to wait until an event occurs. To do so, we have to go into an infinite loop to keep our connection up:
while True:
   notification = device.take_notification()
   print(notification.notification_xml)
With our connection established, we can go ahead and create the subscriptions. The create_subscrptions() method, without any arguments, tells the manager to listen for notifications on all events. Once an event has been received, it is put in an internal queue. To retrieve messages from this queue, we use the take_notification()method, which listens on the internal notification queue and, as soon as the manager has put a new notification on it, will execute. Then, we print out the contents of our notification. Again, the notification is an XML-formatted message. With the infinite loop, we can go back to listen for a new notification once the previous notification has been processed/printed out.


 


Responses(0)