Async NETCONF RPC example with ncclient
ncclient is a great Python library that facilitates client-side scripting and application development around the NETCONF protocol: https://github.com/ncclient/ncclient and used by the even more popular PyEz (https://github.com/Juniper/py-junos-eznc)
Typically, one uses the provided functions in synchronous mode, where replies are awaited and the result returned. I was however in need of asynchronous mode, where operations return immediately, allowing me to do ‘other stuff’ and periodically check if a result came in and process it accordingly.
In search of example code using async mode turned out to be harder than I thought. Starting from a synchronous example script that sends a RPC command to retrieve software information and extract the hostname from it (https://github.com/ncclient/ncclient/blob/master/examples/juniper/execute-rpc.py), I ended up with the following working asynchronous version of the same script:
from ncclient import manager
from ncclient.xml_ import *
import time
from ncclient.devices.junos import JunosDeviceHandler
def connect(host, port, user, password):
conn = manager.connect(host=host,
port=port,
username=user,
password=password,
timeout=10,
device_params={'name': 'junos'},
hostkey_verify=False)
junos_dev_handler = JunosDeviceHandler(
device_params={'name': 'junos',
'local': False})
conn.async_mode = True
rpc = new_ele('get-software-information')
obj = conn.rpc(rpc)
# for demo purposes, we just wait for the result
while not obj.event.is_set():
print('waiting for answer ...')
time.sleep(.3)
result = NCElement(obj.reply,
junos_dev_handler.transform_reply()
).remove_namespaces(obj.reply.xml)
print 'Hostname: ', result.findtext('.//host-name')
if __name__ == '__main__':
connect('pe1', 830, 'lab', 'lab123')
Executed against a device:
$ python async-execute-rpc.py
waiting for answer ...
waiting for answer ...
Hostname: pe1
Done!