NSO – Part 3

Let’s continue playing around some more with NSO. In the last posts we’ve added our netsim-devices to NSO and managed to push out some simple config & tried rollbacks. Instead of specifying each single router everytime we want to manage them we can instead use device-groups for easier management.

Let’s start with creating two groups for our Core- & Edge-routers:

dmin@ncs# config 
Entering configuration mode terminal
admin@ncs(config)# devices device-group Core device-name [ r0 r1 ]


admin@ncs(config)# devices device-group Edge device-name [ r2 r
Possible completions:
  r0  r1  r3
admin@ncs(config)# devices device-group Edge device-name [ r2 r3 ]


admin@ncs(config)# show full-configuration devices device-group 
devices device-group Core
 device-name [ r0 r1 ]
!
devices device-group Edge
 device-name [ r2 r3 ]

admin@ncs(config)# do show devices device-group
NAME  MEMBER     INDETERMINATES  CRITICALS  MAJORS  MINORS  WARNINGS  
----------------------------------------------------------------------
Core  [ r0 r1 ]  0               0          0       0       0         
Edge  [ r2 r3 ]  0               0          0       0       0 

We can then use the group-name when we want to check if router are in sync f.ex.:

admin@ncs# devices device-group Core check-sync 
sync-result {
    device r0
    result in-sync
}
sync-result {
    device r1
    result in-sync
}

We can also have groups in a group:

devices device-group all
 device-group [ Core Edge ]
!

Let’s also take a look at creating a template that we can later call on to configure something generic on our device(s). By using “{$VARIABLENAME}” NSO gives us the ability to input our own variables when calling the specific template. Here’s an example of a simple VRF-template:

admin@ncs(config)# devices template NEW_VRF
admin@ncs(config-template-NEW_VRF)# config ios:vrf definition {$VRF}
admin@ncs(config-definition-{$VRF})# description {$CUSTOMER}
admin@ncs(config-definition-{$VRF})# rd 3301\:{$VRF}
admin@ncs(config-definition-{$VRF})# address-family ipv4 route-target import 3301\:{$VRF}
admin@ncs(config-import-3301:{$VRF})# exit
admin@ncs(config-definition-{$VRF})# address-family ipv4 route-target exoort 3301\:{$VRF}
admin@ncs(config-export-3301:{$VRF})# exit
admin@ncs(config-definition-{$VRF})# top
admin@ncs(config)# commit

admin@ncs(config)# show full-configuration devices template NEW_VRF 
devices template NEW_VRF
 config
  ios:vrf definition {$VRF}
   description {$CUSTOMER}
   rd          3301:{$VRF}
   address-family ipv4 route-target export 3301:{$VRF}
   !
   address-family ipv4 route-target import 3301:{$VRF}
   !
  !
 !

When we want to configure a new VRF we than only have to name our NEW_VRF-template and input the variables for CUSTOMER & VRF. NSO’s autocomplete/tab feature is excellent here and keeps track of available variables we can use.

admin@ncs(config)# devices device-group Edge apply-template template-name NEW_VRF variable { name CUSTOMER value 'GEKAS' } variable { name VRF value '22222' }
apply-template-result {
    device r2
    result ok
}
apply-template-result {
    device r3
    result ok
}
admin@ncs(config)# commit
Commit complete.
admin@ncs(config)# 

admin@ncs(config)# devices device-group all apply-template template-name NEW_VRF variable { name CUSTOMER value 'MGMT' } variable { name VRF value '999' } 
apply-template-result {
    device r0
    result ok
}
apply-template-result {
    device r1
    result ok
}
apply-template-result {
    device r2
    result ok
}
apply-template-result {
    device r3
    result ok
}

If we login and check our routers we can see that all routers now have the MGMT-vrf & Edge-routers (R2 & R3) also have a customer vrf GEKAS.

$ ncs-netsim cli-i r1

admin connected from 192.168.15.186 using ssh on labb-nso
r1> en
r1# show running-config vrf
vrf definition 999
 description MGMT
 rd          3301:999
 address-family ipv4
  route-target export 3301:999
  route-target import 3301:999
  exit-address-family
 !
!

$ ncs-netsim cli-i r2

admin connected from 192.168.15.186 using ssh on labb-nso
r2> en
r2# show running-config vrf
vrf definition 22222
 description GEKAS
 rd          3301:22222
 address-family ipv4
  route-target export 3301:22222
  route-target import 3301:22222
  exit-address-family
 !
!
vrf definition 999
 description MGMT
 rd          3301:999
 address-family ipv4
  route-target export 3301:999
  route-target import 3301:999
  exit-address-family
 !
!

Let’s see what happens when we do a manual change and R2 gets out of sync.

r2# conf
Enter configuration commands, one per line. End with CNTL/Z.
r2(config)# vrf definition 999
r2(config-vrf)# description CustomerA
r2(config-vrf)# exit

admin@ncs# devices device-group all check-sync 
sync-result {
    device r0
    result in-sync
}
sync-result {
    device r1
    result in-sync
}
sync-result {
    device r2
    result out-of-sync
    info got: 77727c766ca3b799f52c13a9cb76daa3 expected: 1d88fb85cf89d8f417701fac26e6df3d

}
sync-result {
    device r3
    result in-sync
}
admin@ncs# *** ALARM out-of-sync: got: 77727c766ca3b799f52c13a9cb76daa3 expected: 1d88fb85cf89d8f417701fac26e6df3d

That hash-value isn’t helping us very much, but we can easily check what the actual difference is with compare-config:

admin@ncs# devices device r2 compare-config 
diff 
 devices {
     device r2 {
         config {
             ios:vrf {
                 definition 999 {
-                    description MGMT;
+                    description CustomerA;
                 }
             }
         }
     }
 }


admin@ncs# devices device r2 sync-to       
result true

admin@ncs# devices device-group all check-sync
sync-result {
    device r0
    result in-sync
}
sync-result {
    device r1
    result in-sync
}
sync-result {
    device r2
    result in-sync
}
sync-result {
    device r3
    result in-sync
}

There’s also a pretty cool option to use policy-rules to f.ex warn the user before he/she tries to removes an important vrf. It was pretty tricky however how to figure out how it should be written so I had a lot of trial and error here, but ultimately this is what I ended up with:

admin@ncs(config)# policy rule MGMT foreach /devices/device expr config/ios:vrf/definition[name='999'] warning-message "Device {name} must have a Management-VRF"

A really good command to easier see what path we should check in our expr-string was by using the “| display xpath”:

admin@ncs(config)# show full-configuration devices device r2 config ios:vrf | display xpath
/devices/device[name='r2']/config/ios:vrf/definition[name='22222']/description GEKAS
/devices/device[name='r2']/config/ios:vrf/definition[name='22222']/rd 3301:22222
/devices/device[name='r2']/config/ios:vrf/definition[name='22222']/address-family/ipv4
/devices/device[name='r2']/config/ios:vrf/definition[name='22222']/address-family/ipv4/route-target/export[asn-ip='3301:22222']
/devices/device[name='r2']/config/ios:vrf/definition[name='22222']/address-family/ipv4/route-target/import[asn-ip='3301:22222']
/devices/device[name='r2']/config/ios:vrf/definition[name='999']/description MGMT
/devices/device[name='r2']/config/ios:vrf/definition[name='999']/rd 3301:999
/devices/device[name='r2']/config/ios:vrf/definition[name='999']/address-family/ipv4
/devices/device[name='r2']/config/ios:vrf/definition[name='999']/address-family/ipv4/route-target/export[asn-ip='3301:999']
/devices/device[name='r2']/config/ios:vrf/definition[name='999']/address-family/ipv4/route-target/import[asn-ip='3301:999']

When a user tries to remove the vrf 999 for management they should now get an error:

admin@ncs(config)# no devices device r2 config ios:vrf definition 999 
admin@ncs(config)# show configuration 
devices device r2
 config
  no ios:vrf definition 999
 !
!
admin@ncs(config)# commit
The following warnings were generated:
  Device r2 must have a Management-VRF
Proceed? [yes,no] no
Aborted: by user

I’ve only scratched the surface yet but i’m really starting to dig NSO. 🙂

NSO – Part 2

As we now have NSO up and running on our local VM let’s try and do some basic stuff like actually push out some configuration changes to our network. 🙂

Cisco are nice enough to provide us with a tool (netsim) to simulate devices that we can use NSO on. These are not to be compared with virtual routers using CSRv etc however.

They use practically 0 memory and is more or less just a config-template that we can “login” to and view/change the current config in a CiscoIOS or Juniper CLI-view. There’s no actual topology we can build though and we can’t send any traffic between these devices.

Anyway, let’s start with creating 4 routers running IOS with the names r* in a new directory somewhere suitable.

joco02 at labb-nso in ~/nso-labs/ios
$ source $HOME/ncs-4.7/ncsrc
$ ncs-netsim create-network $NCS_DIR/packages/neds/cisco-ios 4 r
DEVICE r0 CREATED
DEVICE r1 CREATED
DEVICE r2 CREATED
DEVICE r3 CREATED

We then “boot them up” by using ncs-netsim start.

joco02 at labb-nso in ~/nso-labs/ios
$ ncs-netsim start
DEVICE r0 OK STARTED
DEVICE r1 OK STARTED
DEVICE r2 OK STARTED
DEVICE r3 OK STARTED

If we later want to check if all devices are still up and running we can use the command:

joco02 at labb-nso in ~/nso-labs/ios
$ ncs-netsim is-alive
DEVICE r0 OK
DEVICE r1 OK
DEVICE r2 OK
DEVICE r3 OK

We can login to these “routers” and a rather nifty function in netsim is that we can also choose how the CLI should be displayed (juniper or cisco-style) by adding the -i flag. Cisco is also nice enough to provide a base config for us to play around with when using CiscoIOS netsim-devices.

For juniper-style CLI:

$  ncs-netsim cli r0

admin connected from 192.168.15.188 using ssh on labb-nso
admin@r0> show configuration router
bgp 64512 {
    aggregate-address {
        address 10.10.10.1;
        mask    255.255.255.251;
    }
    neighbor 1.2.3.4 {
        remote-as 1;
        ebgp-multihop {
            max-hop 3;
        }
    }
    neighbor 2.3.4.5 {
        remote-as 1;
        activate;
        capability {
            orf {
                prefix-list both;
            }
        }
        weight    300;
    }
}
[ok]

For Cisco-style CLI:

$ ncs-netsim cli-i r0

admin connected from 192.168.15.188 using ssh on labb-nso
r0> enable
r0# show running-config router
router bgp 64512
 aggregate-address 10.10.10.1 255.255.255.251
 neighbor 1.2.3.4 remote-as 1
 neighbor 1.2.3.4 ebgp-multihop 3
 neighbor 2.3.4.5 remote-as 1
 neighbor 2.3.4.5 activate
 neighbor 2.3.4.5 capability orf prefix-list both
 neighbor 2.3.4.5 weight 300
!

There’s also options to create IOS XR, NX, Juniper, Dell ftos & a10 acos devices – but for at least IOS XR it seems there’s no default config included to play with so in this example i’ll just use the IOS for now.

We now have our devices, so let’s set up NSO to use our new netsim-routers it can find in our current folder.

$ ncs-setup --netsim-dir ./netsim --dest .
Using netsim dir ./netsim

If we check our current directory we can see that we got a whole bunch of new files suddenly:

joco02 at labb-nso in ~/nso-labs/ios
$ la
total 52
drwxrwxr-x 8 joco02 joco02 4096 May  4 18:41 ./
drwxrwxr-x 3 joco02 joco02 4096 May  4 18:19 ../
drwxrwxr-x 2 joco02 joco02 4096 May  4 18:41 logs/
drwxrwxr-x 2 joco02 joco02 4096 May  4 18:41 ncs-cdb/
-rw-rw-r-- 1 joco02 joco02 9357 May  4 18:41 ncs.conf
drwxrwxr-x 3 joco02 joco02 4096 May  4 18:41 netsim/
drwxrwxr-x 2 joco02 joco02 4096 May  4 18:41 packages/
-rw-rw-r-- 1 joco02 joco02  608 May  4 18:41 README.ncs
-rw-rw-r-- 1 joco02 joco02 1128 May  4 18:41 README.netsim
drwxrwxr-x 4 joco02 joco02 4096 May  4 18:41 scripts/
drwxrwxr-x 2 joco02 joco02 4096 May  4 18:41 state/

And finally we’re ready to start NSO.

joco02 at labb-nso in ~/nso-labs/ios
$ ncs

joco02 at labb-nso in ~/nso-labs/ios
$ ncs --status | grep status
status: started

When loggin in to the NSO CLI we can chose between using Cisco IOSXR or Juniper style CLI:
$ ncs_cli -C -u admin <- XR
$ ncs_cli -J -u admin <- Juniper

I feel way more at home in the XR so that’s what ill be using.

joco02 at labb-nso in ~/nso-labs/ios
$ ncs_cli -C -u admin

admin connected from 192.168.15.188 using ssh on labb-nso
admin@ncs# 

At this point the only thing NSO knows about our devices are how to connect to them (address/port/authentication) and what type of device it is (Cisco IOS). We can check NSO’s current view of the configuration of each device with:

admin@ncs# show running-config devices device r0
devices device r0
 address   127.0.0.1
 port      10022
 ssh host-key ssh-rsa
  key-data "..long key.."
 !
 authgroup default
 device-type cli ned-id cisco-ios
 state admin-state unlocked
 config
  no ios:service pad
  no ios:ip domain-lookup
  no ios:ip http secure-server
  ios:ip source-route

A nice feature is that we can also use tab-completion to see which devices we have in our database:

admin@ncs# show running-config devices device 
Possible completions:
  r0  r1  r2  r3  |  <cr>

But before we go any further we have to make sure NSO is up to sync with the actual configuration of our devices, so let’s start with checking that it can actually connect to our devices:

admin@ncs# devices connect                              
connect-result {
    device r0
    result true
    info (admin) Connected to r0 - 127.0.0.1:10022
}
connect-result {
    device r1
    result true
    info (admin) Connected to r1 - 127.0.0.1:10023
}
connect-result {
    device r2
    result true
    info (admin) Connected to r2 - 127.0.0.1:10024
}
connect-result {
    device r3
    result true
    info (admin) Connected to r3 - 127.0.0.1:10025
}

And finally lets sync data from the devices, NSO will save this data to its configuration database (CDB) and respond with true if it was successful.

admin@ncs# devices sync-from
sync-result {
    device r0
    result true
}
sync-result {
    device r1
    result true
}
sync-result {
    device r2
    result true
}
sync-result {
    device r3
    result true
}

We can now check NSOs view of R0 config again.

admin@ncs# show running-config devices device r0
devices device r0
 address   127.0.0.1
 port      10022
 ssh host-key ssh-rsa
  key-data "..long key.."
 !
 authgroup default
 device-type cli ned-id cisco-ios
 state admin-state unlocked
 config
  no ios:service pad
  ios:ip vrf my-forward
   bgp next-hop Loopback 1
  !
  ios:ip community-list 1 permit
  ios:ip community-list 2 deny
  ios:ip community-list standard s permit
  no ios:ip domain-lookup
  no ios:ip http server
  no ios:ip http secure-server
  ios:ip routing
  ios:ip source-route
  ios:interface FastEthernet1/0
  exit
  ios:interface Loopback0
  exit
  ios:class-map match-all a
  !
  ios:class-map match-all cmap1
   match mpls experimental topmost 1
   match packet length max 255
   match packet length min 2
   match qos-group 1
  !
  ios:policy-map a
  !
  ios:policy-map map1
   class c1
    drop
    estimate bandwidth delay-one-in 500 milliseconds 100
    priority percent 33
   !
  !
  no ios:spanning-tree optimize bpdu transmission
  ios:mpls ip propagate-ttl
  ios:router bgp 64512
   aggregate-address 10.10.10.1 255.255.255.251
   neighbor 1.2.3.4 remote-as 1
   neighbor 1.2.3.4 ebgp-multihop 3
   neighbor 2.3.4.5 remote-as 1
   neighbor 2.3.4.5 activate
   neighbor 2.3.4.5 capability orf prefix-list both
   neighbor 2.3.4.5 weight 300
  !
 !
!

It’s also possible to filter the output and just check the routing specific config etc:

admin@ncs# show running-config devices device r0 config ios:router
devices device r0
 config
  ios:router bgp 64512
   aggregate-address 10.10.10.1 255.255.255.251
   neighbor 1.2.3.4 remote-as 1
   neighbor 1.2.3.4 ebgp-multihop 3
   neighbor 2.3.4.5 remote-as 1
   neighbor 2.3.4.5 activate
   neighbor 2.3.4.5 capability orf prefix-list both
   neighbor 2.3.4.5 weight 300
  !
 !
!

We can also change the output to f.ex json or xml for easier handling in scripts etc and/or save to a file.

admin@ncs# show running-config devices device r0 config ios:router | display json
{
  "data": {
    "tailf-ncs:devices": {
      "device": [
        {
          "name": "r0",
          "config": {
            "tailf-ned-cisco-ios:router": {
              "bgp": [
                {
                  "as-no": 64512,
                  "aggregate-address": {
                    "address": "10.10.10.1",
                    "mask": "255.255.255.251"
                  },
                  "neighbor": [
                    {
                      "id": "1.2.3.4",
                      "remote-as": 1,
                      "ebgp-multihop": {
                        "max-hop": 3
                      }
                    },
                    {
                      "id": "2.3.4.5",
                      "remote-as": 1,
                      "activate": [null],
                      "capability": {
                        "orf": {
                          "prefix-list": ["both"]
                        }
                      },
                      "weight": 300
                    }
                  ]
                }
              ]
            }
          }
        }
      ]
    }
  }
}

admin@ncs# show running-config devices device r0 config ios:router | display json | save output.json
admin@ncs#  

So how does NSO actually handle configuration changes we want to do in our network? In the ideal world all configuration changes would be performed only via NSO by either the CLI, WebGui, REST etc.

When committing a change NSO will compare the new config with its CDB and calculate the difference. It will then send the needed changes required over to the specific NED that in turn will translate this over to CLI-specific commands to make the change.

Only if all the changes succeeds on the actual device(s) it will be committed to the CDB, if it fails on any device NSO will roll back the changes on all devices, this even works on devices which doesn’t have native rollback like the Cisco IOS.

Here we have a problem though, if any changes are done outside of NSO it will not be known to the CDB and NSO will be out of sync and unable to do these steps correctly. We would then first have to sync the changes to the CDB or overwrite the current device config with what’s stored in NSOs CDB.

Any way, let’s try and make a configuration change! First we specify which device or range of devices we want to change, in this case r0, r1 & r2 and then the actual change, in this case lets add redistribution of static routes.

admin@ncs# config                
Entering configuration mode terminal
admin@ncs(config)# devices device r0..2 config ios:router bgp 64512 redistribute static 
admin@ncs(config-router)# top
admin@ncs(config)#

In this state no changes has actually been made and is local only. NSO will calculate the difference to its CDB, we can view what the actual changes are going to be with show configuration:

admin@ncs(config)# show configuration
devices device r0
 config
  ios:router bgp 64512
   redistribute static
  !
 !
!
devices device r1
 config
  ios:router bgp 64512
   redistribute static
  !
 !
!
devices device r2
 config
  ios:router bgp 64512
   redistribute static
  !
 !
!

We’re committing the change to both the CDB and the actual devices.

admin@ncs(config)# commit | details
entering validate phase for running...
 2019-05-04T19:32:13.672 validate: run pre-trans-lock service callbacks...
 2019-05-04T19:32:13.672 validate: run transforms and transaction hooks...
 2019-05-04T19:32:13.672 validate: run transforms and transaction hooks done [0.000 sec]
 2019-05-04T19:32:13.673 validate: pre-trans-lock service callbacks done [0.000 sec]
 2019-05-04T19:32:13.673 validate: grabbing transaction lock... ok [0.001 sec]
 2019-05-04T19:32:13.674 validate: creating rollback file... ok [0.003 sec]
 2019-05-04T19:32:13.678 validate: run transforms and transaction hooks...
 2019-05-04T19:32:13.678 validate: run transforms and transaction hooks done [0.000 sec]
 2019-05-04T19:32:13.678 validate: mark inactive... ok [0.000 sec]
 2019-05-04T19:32:13.679 validate: pre validate... ok [0.000 sec]
 2019-05-04T19:32:13.679 validate: run validation over the change set...
 2019-05-04T19:32:13.682 validate: validation over the change set done [0.002 sec]
 2019-05-04T19:32:13.682 validate: run dependency-triggered validation...
 2019-05-04T19:32:13.682 validate: dependency-triggered validation done [0.000 sec]
 2019-05-04T19:32:13.682 validate: check configuration policies...
 2019-05-04T19:32:13.682 validate: configuration policies done [0.000 sec]
entering write-start phase for running...
 2019-05-04T19:32:13.682 cdb: write-start
entering prepare phase for running...
 2019-05-04T19:32:13.684 cdb: prepare
 2019-05-04T19:32:13.684 ncs-internal-device-mgr: prepare
entering commit phase for running...
 2019-05-04T19:32:14.929 cdb: commit
 2019-05-04T19:32:14.931 ncs-internal-service-mux: commit
 2019-05-04T19:32:14.931 ncs-internal-device-mgr: commit
Commit complete.

NSO will also store a rollback-file for each commit so it can be rolled back manually if needed. We can find these files in ./logs/:

admin@ncs(config)# do file show logs/rollback10007
# Created by: admin
# Date: 2019-05-04 19:32:13
# Via: cli
# Type: delta
# Label: 
# Comment: 
# No: 10007

ncs:devices {
    ncs:device r0 {
        ncs:config {
            ios:router {
                ios:bgp 64512 {
                    ios:redistribute {
                        delete:
                        ios:static;
                    }
                }
            }
        }
    }
    ncs:device r1 {
        ncs:config {
            ios:router {
                ios:bgp 64512 {
                    ios:redistribute {
                        delete:
                        ios:static;
                    }
                }
            }
        }
    }
    ncs:device r2 {
        ncs:config {
            ios:router {
                ios:bgp 64512 {
                    ios:redistribute {
                        delete:
                        ios:static;
                    }
                 }
             }
         }
     }
 }

But before we do that let’s verify that one of our devices actually have redistribution configured now.

$ ncs-netsim cli-i r1

admin connected from 192.168.15.188 using ssh on labb-nso
r1> en
r1# show running-config router
router bgp 64512
 aggregate-address 10.10.10.1 255.255.255.251
 neighbor 1.2.3.4 remote-as 1
 neighbor 1.2.3.4 ebgp-multihop 3
 neighbor 2.3.4.5 remote-as 1
 neighbor 2.3.4.5 activate
 neighbor 2.3.4.5 capability orf prefix-list both
 neighbor 2.3.4.5 weight 300
 redistribute static

Cool! Let’s do the rollback and see what happens.

admin@ncs(config)# rollback configuration ?
Possible completions:
  10001   2019-05-04 18:44:00 by system via system
  10002   2019-05-04 18:44:03 by system via system
  10003   2019-05-04 18:56:56 by admin via cli
  10004   2019-05-04 18:56:56 by admin via cli
  10005   2019-05-04 18:56:56 by admin via cli
  10006   2019-05-04 18:56:56 by admin via cli
  10007   2019-05-04 19:32:13 by admin via cli
  <cr>    latest
admin@ncs(config)# rollback configuration 10007
admin@ncs(config)# show configuration 
devices device r0
 config
  ios:router bgp 64512
   no redistribute static
  !
 !
!
devices device r1
 config
  ios:router bgp 64512
   no redistribute static
  !
 !
!
devices device r2
 config
  ios:router bgp 64512
   no redistribute static
  !
 !
!
admin@ncs(config)# commit
Commit complete.

Checking back in R1 we can see that we no longer have any static redist configured.

r1# show running-config router
router bgp 64512
 aggregate-address 10.10.10.1 255.255.255.251
 neighbor 1.2.3.4 remote-as 1
 neighbor 1.2.3.4 ebgp-multihop 3
 neighbor 2.3.4.5 remote-as 1
 neighbor 2.3.4.5 activate
 neighbor 2.3.4.5 capability orf prefix-list both
 neighbor 2.3.4.5 weight 300
!

All gone! I think that will be all for tonight, must say i’m impressed with how easy it was to get started! And that not only is NSO free to use for us nerds to play around with, they also provide tools like Netsim and great documentation etc for everyone.

I haven’t had time to check them out myself yet but they also provide labs you can do over at developer.cisco.com/learning/labs/tags/NSO/page/1

Installing NSO

I’ve been wanting to test Cisco’s NSO for a long time now and finally had some spare time to try and get it up and running on a local VM. It’s free for non-production use now so go ahead and grab it over at
https://developer.cisco.com/site/nso/ (available for both MacOS & Linux).

I installed Ubuntu 18.04 LTS on a fresh vmbox (I didn’t manage to get it working on a raspberry), the only other pre-requirements NSO has is:

  • Java JDK-7.0 or higher
  • Ant
  • python2 or python3
  • python-paramiko

To make life simpler I also installed python3-pip

$ sudo apt-get install python3-pip
$ sudo apt-get install default-jdk
$ sudo apt-get install ant
$ pip3 install paramiko
$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment (build 11.0.2+9-Ubuntu-3ubuntu118.04.3)
OpenJDK 64-Bit Server VM (build 11.0.2+9-Ubuntu-3ubuntu118.04.3, mixed mode, sharing)

I then downloaded the file nso-4.7.linux.x86_64.signed.bin from Cisco, installation was actually much more simpler than I had imagined.

joco02 at labb-nso in ~/Downloads
$ ls
nso-4.7.linux.x86_64.signed.bin

$ sh nso-4.7.linux.x86_64.signed.bin --skip-verification
Unpacking...

joco02 at labb-nso in ~/Downloads
$ ls
cisco_x509_verify_release.py  nso-4.7.linux.x86_64.installer.bin  nso-4.7.linux.x86_64.installer.bin.signature  nso-4.7.linux.x86_64.signed.bin  README.signature  tailf.cer

joco02 at labb-nso in ~/Downloads
$ sh nso-4.7.linux.x86_64.installer.bin $HOME/ncs-4.7 --local-install
INFO  Using temporary directory /tmp/ncs_installer.41189 to stage NCS installation bundle
INFO  Unpacked ncs-4.7 in /home/joco02/ncs-4.7
INFO  Found and unpacked corresponding DOCUMENTATION_PACKAGE
INFO  Found and unpacked corresponding EXAMPLE_PACKAGE
INFO  Generating default SSH hostkey (this may take some time)
INFO  SSH hostkey generated
INFO  Environment set-up generated in /home/joco02/ncs-4.7/ncsrc
INFO  NCS installation script finished
INFO  Found and unpacked corresponding NETSIM_PACKAGE
INFO  NCS installation complete

When then have to source our new folder to enable built-in variables and then setup our environment.

joco02 at labb-nso in ~/Downloads
$ source $HOME/ncs-4.7/ncsrc
$ ncs-setup --dest $HOME/ncs-run

That should be everything, we can now start NSO:

$ ncs

To check status we can use:

joco02 at labb-nso in ~/ncs-run
$ ncs --status | grep status
status: started

joco02 at labb-nso in ~/ncs-run
$ ncs --version
4.7

We should now also be able to reach NSO’s GUI/Webpage for administration at http://serverip:8080/login.html

Login credentials are admin / admin

If your like me and allergic to GUIs we can also connect to the CLI instead.

joco02 at labb-nso in ~/ncs-4.7
$ ncs_cli -u admin

admin connected from 192.168.15.188 using ssh on labb-nso
admin@ncs> ?
Possible completions:
  clear      - Clear parameter
  compare    - Compare running configuration to another configuration or a file
  configure  - Manipulate software configuration information
  describe   - Display transparent command information
  exit       - Exit the management session
  file       - Perform file operations
  help       - Provide help information
  id         - Show user id information
  monitor    - Real-time debugging
  ping       - Ping a host
  ping6      - Ping an ipv6 host
  quit       - Exit the management session
  request    - Make system-level requests
  script     - Script actions
  set        - Set CLI properties
  set-path   - Set relative show path
  show       - Show information about the system
  source     - File to source
  switch     - Change CLI style
  templatize - Find patterns in subtree.
  top        - Exit to top level and optionally run command
  traceroute - Trace the route to a remote host
  up         - Exit one level of configuration

We should now be able to do some labs on NSO! 🙂 Cisco luckily provides a few “Network Elements Drivers” for their netsim-devices for lab purposes, if you want to manage your own devices (real/virtual) you will have to buy a license for it as I understand it.

joco02 at labb-nso in ~/ncs-4.7/packages/neds
$ ls
 a10-acos  cisco-ios  cisco-iosxr  cisco-nx  dell-ftos  juniper-junos