How to upgrade JunOS remotely via NETCONF

In this post I would like to explain how to upgrade JunOS on a router remotely. Imagine that you have dozens of routers and you would like to script it somehow. Below is a script I have written in python. I must say that it really took me some time to comprehend paramiko API but finally I wrote one which does really work. As you might have known, NETCONF is a fantastic protocol by which you can send RPC calls to remote devices. This script opens a netconf channel and sends these command inside this channel.

By using the predefined connection parameters, script opens the netconf channel and sends the command in variable SOFT_ADD which orders the device to fetch the software from JUNOS_URL and then upgrade it.

# A script which upgrades JunOS remotely
import paramiko
import socket
import time
import sys


ssh = paramiko.SSHClient()

CLOSE = """

SOFT_ADD = """

socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

trans = paramiko.Transport(socket)
trans.connect(username=USERNAME, password=PASSWORD)

ch = trans.open_session()
name = ch.set_name('netconf')



#Recieve data returned
data = ch.recv(2048)
while data:
   data = ch.recv(1024)
   print data,
   #if data.find('</rpc-reply>') == 0:
   if data.find('') != -1:
     #We have reached the end of reply



Lets see this script in action; (because it is still a primitive one expect some errors in output but it does the job)

root@linux:~/sbin/netconf# python
<!-- user root, class super-user -->
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="">
/var/tmp/incoming-package.31020                       1742 kB 1742 kBps
Package contains junos-11.1R3.5.tgz ; renaming ...
Formatting alternate root (/dev/ad0s1a)...
/dev/ad0s1a: 299.7MB (613792 sectors) block size 16384, fragment size 2048
        using 4 cylinder groups of 74.94MB, 4796 blks, 9600 inodes.
super-block backups (for fsck -b #) at:
 32, 153504, 306976, 460448
Removing /var/tmp/junos-11.1R3.5.tgz
Installing package '/altroot/cf/packages/install-tmp/junos-11.1R3.5-domestic' ...
Verified junos-boot-srxsme-11.1R3.5.tgz signed by PackageProduction_11_1_0
Verified junos-srxsme-11.1R3.5-domestic signed by PackageProduction_11_1_0
Saving boot file package in /var/sw/pkg/junos-boot-srxsme-11.1R3.5.tgz
JUNOS 11.1R3.5 will become active at next reboot
WARNING: A reboot is required to load this software correctly
WARNING:     Use the 'request system reboot' command
WARNING:         when software installation is complete
Saving state for rollback ...
<!-- netconf error: syntax error, expecting &lt;rpc&gt; -->
<!-- netconf error: syntax error, expecting &lt;rpc&gt; -->
<!-- session end at 2011-08-20 00:14:50 UTC -->

Isn’t it cool? You can include multiple routers to ease upgrade operations or anything you want. If you want to do more, you can check paramiko API along with RPC call documentation to extend your scripts and do more stuff with it.

After I have written this post I have noticed that I forgot to mention to enable netconf protocol in JunOS. Here is the command;

junos# set system services netconf ssh

About: rtoodtoo

Genco has worked for more than 10 years as a Network/Support Engineer. He is also interested in Python, Linux, Security and SD-WAN, currently lives in the Netherlands and works as a Network Support Engineer at Tesla Inc. // JNCIE-SEC #223 / RHCE / PCNSE

12 thoughts on “How to upgrade JunOS remotely via NETCONF”

  1. Hi,

    Check out NCClient, a NETCONF client written in Juniper that, among many other things, hides some of the SSH details of paramiko under a easy-to-use API. Should work very well for the type of tasks you’re looking at.

  2. Hi Carl,
    I had taken a look at this client some time ago. To be honest, I am studying python nowadays so I prefer to do the things a bit harder way due to that but I will look into it once again. Thanks for your comment.

  3. Very helpful — I found that terminating the script works better using this stragety:

    #Recieve data returned
    data = ch.recv(2048)
    while data:
    data = ch.recv(1024)
    print data,
    if data.find(”) != -1:
    #We have reached the end of reply

    Thanks for posting this!

    1. According to paramiko manual it is necessary indeed. If you think it isn’t, I would be happy to hear the reason.

    1. You don’t even have to use python to run through multiple routers. You can write a simple bash script which reads a file containing IP addresses and you can pass the argument to this script. It needs a bit modification though.

You have a feedback?

This site uses Akismet to reduce spam. Learn how your comment data is processed.