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

Lämna ett svar

E-postadressen publiceras inte. Obligatoriska fält är märkta *