Ncclient
Introduction
Ncclient (short for NETCONF client) is an open source Python module that allows you to develop Python scripts that interact with a NETCONF server.
One issue with this project is that the
documentation page
appears to be broken for some time now (many pages contain lists of empty placeholders).
So, you will have to be comfortable reading
the source code of ncclient on GitHub
as documentation of its API.
Install ncclient
If you followed the instructions for setting up the environment for this tutorial then ncclient is already installed.
Or, use pip if you want to install ncclient separately:
$ pip install ncclient
Start the clixon NETCONF server
The MG-SOFT NetConf browser is a NETCONF client, so we need a NETCONF server to be running. We will use clixon as the NETCONF server. Refer to the clixon chapter in this tutorial for instructions on how install clixon, how to build clixon, how the start the clixon backend daemon, and how to configure SSH to start the clixon NETCONF server.
As a quick sanity check to make sure the NETCONF server is running properly,
manually start an SSH session. You should see a NETCONF hello message from the server:
$ ssh localhost -s netconf username@localhost's password: ******]]>]]> urn:ietf:params:netconf:base:1.1 urn:ietf:params:netconf:base:1.0 urn:ietf:params:netconf:capability:candidate:1.0 urn:ietf:params:netconf:capability:validate:1.1 urn:ietf:params:netconf:capability:startup:1.0 urn:ietf:params:netconf:capability:xpath:1.0 urn:ietf:params:netconf:capability:notification:1.0 4
Type Control-D to exit the SSH session.
Example Python scripts
This repository contains several example Python scripts that use the ncclient Python module.
In the remainder of this chapter we will walk you through those examples.
$ cd ~/yang-tutorial/ncclient $ ls -1 [TODO] output
You may optionally set the following environment variables to configure the address, username, and password of the NETCONF server:
$ export NETCONF_SERVER_ADDRESS="10.0.0.99" # Default: loopback address 127.0.0.1 $ export NETCONF_SERVER_USERNAME="jamesbond" # Default: your current username $ export NETCONF_SERVER_PASSWORD="topsecret" # Default: none (certificate based authentication)
TODO: Test certificate-based SSH authentication
Show the running configuration
TODO: Remove device_params={'name': 'alu'} from all examples; it should not be needed anymore
now that the patch has been submitted to clixon.
The first example script show_config.py shows the running configuration in prettified XML
format:
from ncclient import manager
from bs4 import BeautifulSoup
import netconf_server_info
with manager.connect(host=netconf_server_info.address(),
port=830,
username=netconf_server_info.username(),
password=netconf_server_info.password(),
hostkey_verify=False,
device_params={'name': 'alu'}) as mgr:
config_xml = mgr.get_config(source='running').data_xml
print(BeautifulSoup(config_xml, 'xml').prettify())
Module netconf_server_info is used to read the environment variables that contain the NETCONF
server information:
import psutil
import os
def address():
address = os.getenv('NETCONF_SERVER_ADDRESS')
if address is None:
return '127.0.0.1'
return address
def username():
username = os.getenv('NETCONF_SERVER_USERNAME')
if username is None:
return psutil.Process().username()
return username
def password():
return os.getenv('NETCONF_SERVER_PASSWORD')
Running the show_config.py script produces the following out (this assumes we configured
interface eth0 using the clixon CLI):
<?xml version="1.0" encoding="utf-8"?>
<rpc-reply message-id="urn:uuid:65f61253-834d-4fca-963f-ad7ed528b790">
<data>
<interfaces>
<interface>
<name>
eth0
</name>
<ipv4-address>
1.1.1.1
</ipv4-address>
</interface>
</interfaces>
</data>
</rpc-reply>
Show the client and server capabilties
The example script show_capabilities.py shows the NETCONF client (ncclient) and
server (clixon) capabilities.
from ncclient import manager
from bs4 import BeautifulSoup
import netconf_server_info
with manager.connect(host=netconf_server_info.address(),
port=830,
username=netconf_server_info.username(),
password=netconf_server_info.password(),
hostkey_verify=False,
device_params={'name': 'alu'}) as mgr:
print("Client capabilities:")
for capability in mgr.client_capabilities:
print(f" {capability}")
print("Server capabilities:")
for capability in mgr.server_capabilities:
print(f" {capability}")
The output of this script is:
Client capabilities:
urn:ietf:params:netconf:base:1.0
Server capabilities:
urn:ietf:params:netconf:base:1.1
urn:ietf:params:netconf:base:1.0
urn:ietf:params:netconf:capability:candidate:1.0
urn:ietf:params:netconf:capability:validate:1.1
urn:ietf:params:netconf:capability:startup:1.0
urn:ietf:params:netconf:capability:xpath:1.0
urn:ietf:params:netconf:capability:notification:1.0
Edit the configuration
The example script edit_config.py adds an interface to the configuration:
from ncclient import manager
import netconf_server_info
with manager.connect(host=netconf_server_info.address(),
port=830,
username=netconf_server_info.username(),
password=netconf_server_info.password(),
hostkey_verify=False,
device_params={'name': 'alu'}) as mgr:
cfg_interface = """
<config>
<interfaces xmlns="http://remoteautonomy.com/yang-schemas/interfaces">
<interface>
<name>eth1</name>
<ipv4-address>2.2.2.2</ipv4-address>
</interface>
</interfaces>
</config>
"""
reply = mgr.edit_config(config=cfg_interface)
assert reply.xpath("/rpc-reply/ok") != []
reply = mgr.commit()
assert reply.xpath("/rpc-reply/ok") != []
After running this script, the clixon CLI shows interface eth1 in the configuration:
cli> show configuration
interfaces {
interface {
name eth0;
ipv4-address 1.1.1.1;
}
interface {
name eth1;
ipv4-address 2.2.2.2;
}
}