NSO

Overview

  • NSO gathers, parses, and stores the configuration state of the network devices it manages in a configuration database (CDB). Users and applications can then "ask" NSO to create, read, update, or delete configuration in a programmatic way either ad hoc or through customizable network services.

  • NSO uses software packages called Network Element Drivers (NEDs) to facilitate telnet, SSH, or API interactions with the devices that it manages. The NED provides an abstraction layer that reads in the device's running configuration and parses it into a data-model-validated snapshot in the CDB.

  • The NEDs also allow for the reverse, creating network configuration from CDB data inputs and then sending the configurations to the network devices. There are hundreds of NEDs covering all the Cisco platforms (including IOS-XE, IOS-XR, NX-OS, and ASA) and all major non-Cisco platforms as well

Installation

  • Two modes:

    • System Install: install as an always-on service

    • Local Install: install as standalone on-demand instance, used for development and evaluation

  • Configuration files:

    • ncs.conf: NSO application configuration file. Used to customize aspects of the NSO instance (change ports, enable or disable features, and so on.)

    • packages/: Directory that has symlinks to the NEDs referenced in the --package arguments at setup.

    • logs/: Directory that contains all the logs from NSO. Use this directory when troubleshooting.

Simulator Installation

  • ncs-netsim --dir ~/src/netsim create-network cisco-ios-cli-3.8 2 ios

  • ncs-setup --dest ~/src --netsim-dir ~/src/netsim

  • cd ~/src

  • ncs-netsim --dir ~/src/nso-instance/netsim start|stop internet-rtr0

Setup NCS Instance

  • go to nso-instance folder and start ncs: ncs

  • ncs --status: check status

Setup device authentication

  • NSO uses authgroups to set up credentials for device access. Many authgroups can be configured as needed for the different variations of authentication used across your network. An authgroup can use SNMP or certificates in addition to traditional username/passwords. NSO supports powerful methods of RBAC for identifying and using different authentication and authorization levels depending on the user who is logged into NSO.

  • To setup authgroup

    • login to NSO CLI: ncs_cli -u admin -C

    • enter config mode: config

Adding devices to NSO

  • After having authgroup setup, devices can be added to inventory which need the following information

    • device's IP or FQDN

    • Protocol such as SSH, Telnet, HTTP, Rest and so on and port number

    • authgroup to be used for the device

    • the NED (device driver) to use to connect to the device

  • Add edge-sw01 device:

  • View current context of device: pwd

  • Connect to device: connect

    • By default devices are in locked mode (default)

    • change admin-state of device: state admin-state unlocked, then commit

  • Connect to all devices: devices connect

  • view all devices: show devices list

  • Other ways to add devices:

    1. Manually type commands for each device like above steps

    2. Use an API

    3. Query a production system that has the full device list and save output to a file, then use load merge command from NSO to read it into NSO and commit

    Query and Load merge devices

    • Log into a source nso: ncs_cli -C -u admin

    • show running-config devices device | de-select config: view configuration, filter out its configuration

    • Save output to a file such as devices-config.txt

    • Log into a destination nso: ncs_cli -C -u admin

      • change to config mode: conf

      • load merge devices: load merge /home/developer/devices-config.txt

    • commit to apply the change

    • view devices: show devices list

Sync Configuration from Devices

  • show running-config devices device $device-name config: view device configuration saved in configuraiton database (CDB).

  • devices sync-from: Enable device configuration sync

  • devices device-group IOS-DEVICES check-sync: check device group sync status

Group devices together

  • Create device group and add devices to group

  • Create an ALL group to include all other groups

  • commit to apply changes

Update device configuration

  • Check command commit in dry-run mode: commit dry-run outformat native

  • If everything works, commit again to apply the staged config

Roll back configuration

  • show configuration rollback changes: View the latest changes, if rollback

  • Load up these change and view staged configuration:

Some Commands

  • Note: Tab completion is case-sensitive

  • show running-config devices device internet-router config interface | display [json|xml]: view device's interface configuration

  • show running-config devices device internet-router config interface Vlan * ip address: view ip address of all vlan interfaces

  • show full-configuration devices device $devicename config | nomore: examine device configuration

  • devices device $devicename config: Change to device config configuration mode

  • ios:hostname $newhostname: change hostname of device

  • show configuration: in this context, it will only show current configuration in transaction (new command)

  • devices device * config ios:enable password $password: change password on all devices

  • show devices device dist-sw01 platform [serial-number|version]: View platform information of a device

  • show devices device * platform [serial-number|vesrion]: View platform information of all devices

  • show devices device dist-sw01 live-status port-channel: view live-status of devices, rather than pulling from CDB. Can replace port-channel with other options:

    • ip route

  • devices device dist-sw01 live-status exec show license usage: run show command on device and get returned result

  • devices device dist-sw01 live-status exec any dir: run any dir command

  • devices device dist* live-status exec show license usage | save /home/developer/nexus-license-usage.txt: save output for later usage

Templates

Create a template

  • check the template and commit:

    • show configuration

    • commit

Check and apply template

  • View device list in config mode: do show devices list

  • devices device dist-sw01 apply-template template-name SET-DNS-SERVER

  • show configuration: check configuration to be applied

  • commit or revert to un-staged configuration

Configuration Compliance

There are 2 steps:

  • Building a device template that contains the desired configuration to test.

  • Building a compliance report to check the configuration of a group of devices against a template.

Build device template

  • or show running-configuration | save template.txt

  • check configuration: show configuration

  • and commit

Build compliance report

  • Apply the template: compliance reports report COMPLIANCE-CHECK run

  • Apply the template and save output in specific format: compliance reports report COMPLIANCE-CHECK run outformat {text|html}

  • View the result: cat nso-instance/state/compliance-reports/report*.text

Resolve compliance problems

  • devices device-group ALL apply-template template-name COMPLIANCE-CHECK

NSO Services

  • A declarative method to abstract and automate a task that is done repeatedly

  • can be a customer facing and resource facing service

Service Packages

  • Service packages are a collection of structured files and folders that NSO loads in to the application to extend NSO with new functionality.

  • ncs-make-package is a tool to auto-generate a skeleton structure of files and folders for creating a service package

  • Important files are:

    • loopback-service/src/yang/loopback-service.yang

    • loopback-service/templates/loopback-service-template.xml

  • Generate XML to plug into the template commands

  • Then show configuration and output as xml

  • copy the part between config tags

  • Then put in between config tag of template file above loopback-service/templates/loopback-service-template.xml, then replace ip address 10.10.30.0 with {/dummy}

  • Then save the file and compile Yang Data model

  • Load the new package:

  • Create a service instance

  • If for some reason, the config is changed after sync-from device, it can be redeploy using

ncs-make-package --service-skeleton template --dest nso-instance/packages/simple-service simple-service printf 'module simple-service { namespace "http://com/example/simpleservice"; prefix simple-service; import tailf-ncs { prefix ncs; } list simple-service { key name; uses ncs:service-data; ncs:servicepoint simple-service; leaf name { type string; } leaf device { type leafref { path "/ncs:devices/ncs:device/ncs:name"; } } leaf secret { type string; } } } ' > nso-instance/packages/simple-service/src/yang/simple-service.yang printf ' {./device} {./secret} ' > nso-instance/packages/simple-service/templates/simple-service-template.xml make -C nso-instance/packages/simple-service/src echo "packages reload" | ncs_cli -C -u admin

config simple-service test1 device ios0 secret mypasswd

developer:simple-service > cd $NCS_DIR/examples.ncs/development-guide/cdb-yang developer:cdb-yang > make showcase ./showcase.sh

Setup the demo

Make sure no previous NSO or netsim processes are running

Create an NSO local install with a fresh runtime directory

make[1]: Entering directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang' rm -rf nso-lab-rundir mkdir nso-lab-rundir ncs-setup --dest ./nso-lab-rundir make[1]: Leaving directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang'

Have the environment variable NSO_RUNDIR point to the runtime directory

Showcase: Extending the CDB with Packages

Step 1: Create a package

gmake[1]: Entering directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang/nso-lab-rundir/packages/my-data-entries/src' mkdir -p ../load-dir /home/developer/nso-6.2.1/bin/ncsc ls my-data-entries-ann.yang > /dev/null 2>&1 && echo "-a my-data-entries-ann.yang" --fail-on-warnings -c -o ../load-dir/my-data-entries.fxs yang/my-data-entries.yang gmake[1]: Leaving directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang/nso-lab-rundir/packages/my-data-entries/src'

Step 2: Add package to NSO

admin connected from 127.0.0.1 using console on devpod-4884268602524010749-85755c9897-2gq8k admin@ncs# packages reload reload-result { package my-data-entries result true } admin@ncs# show my-data-entries % No entries found. admin@ncs#

Step 3: Set data

User admin last logged in 2024-04-16T02:13:05.100749+00:00, to devpod-4884268602524010749-85755c9897-2gq8k, from 127.0.0.1 using cli-console admin connected from 127.0.0.1 using console on devpod-4884268602524010749-85755c9897-2gq8k admin@ncs# config Entering configuration mode terminal admin@ncs(config)# my-data-entries "entry number 1" admin@ncs(config-my-data-entries-entry number 1)# dummy 0.0.0.0 admin@ncs(config-my-data-entries-entry number 1)# abort admin@ncs#

Step 4: Inspect the YANG module

User admin last logged in 2024-04-16T02:13:07.428493+00:00, to devpod-4884268602524010749-85755c9897-2gq8k, from 127.0.0.1 using cli-console admin connected from 127.0.0.1 using console on devpod-4884268602524010749-85755c9897-2gq8k admin@ncs# file show packages/my-data-entries/src/yang/my-data-entries.yang | nomore module my-data-entries {

namespace "http://example.com/my-data-entries"; prefix my-data-entries;

import ietf-inet-types { prefix inet; } import tailf-common { prefix tailf; } import tailf-ncs { prefix ncs; }

description "Bla bla...";

revision 2016-01-01 { description "Initial revision."; }

list my-data-entries { description "This is an RFS skeleton service";

} } admin@ncs# show ncs-state loaded-data-models data-model my-data-entries | nomore ncs-state loaded-data-models data-model my-data-entries revision 2016-01-01 namespace http://example.com/my-data-entries prefix my-data-entries exported-to-all admin@ncs#

Showcase: Building and Testing a Model

Step 1: Create a model skeleton

Note: Created the service skeleton package in step 1 of the previous showcase

module my-test-model { namespace "http://example.tail-f.com/my-test-model"; prefix "t";

Step 2: Fill out the model

module my-test-model { namespace "http://example.tail-f.com/my-test-model"; prefix "t";

container host { leaf host-name { type string; description "Hostname for this system"; } leaf-list domains { type string; description "My favourite internet domains"; } container server-admin { description "Administrator contact for this system"; leaf name { type string; } } list user-info { description "Information about team members"; key "name"; leaf name { type string; } leaf expertise { type string; } } } }

Step 3: Compile and load the model

make[1]: Entering directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang/nso-lab-rundir/packages/my-data-entries/src' /home/developer/nso-6.2.1/bin/ncsc ls my-test-model-ann.yang > /dev/null 2>&1 && echo "-a my-test-model-ann.yang" --fail-on-warnings -c -o ../load-dir/my-test-model.fxs yang/my-test-model.yang make[1]: Leaving directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang/nso-lab-rundir/packages/my-data-entries/src'

User admin last logged in 2024-04-16T02:13:07.813294+00:00, to devpod-4884268602524010749-85755c9897-2gq8k, from 127.0.0.1 using cli-console admin connected from 127.0.0.1 using console on devpod-4884268602524010749-85755c9897-2gq8k admin@ncs# packages reload

System upgrade is starting. Sessions in configure mode must exit to operational mode. No configuration changes can be performed until upgrade has completed. System upgrade has completed successfully. reload-result { package my-data-entries result true } admin@ncs#

Step 4: Test the model

User admin last logged in 2024-04-16T02:13:10.603362+00:00, to devpod-4884268602524010749-85755c9897-2gq8k, from 127.0.0.1 using cli-console admin connected from 127.0.0.1 using console on devpod-4884268602524010749-85755c9897-2gq8k admin@ncs# config Entering configuration mode terminal admin@ncs(config)# host host-name my-host admin@ncs(config)# host domains [ tail-f.com tail-f.se ] admin@ncs(config)# host server-admin name Ingrid admin@ncs(config)# host user-info Greta admin@ncs(config-user-info-Greta)# expertise sustainability admin@ncs(config-user-info-Greta)# host user-info Gunvald admin@ncs(config-user-info-Gunvald)# expertise security admin@ncs(config-user-info-Gunvald)# top admin@ncs(config)# show configuration host host-name my-host host domains [ tail-f.com tail-f.se ] host server-admin name Ingrid host user-info Greta expertise sustainability ! host user-info Gunvald expertise security ! admin@ncs(config)# commit Commit complete. admin@ncs(config)# show full-configuration host | display xml | save cdb-init.xml admin@ncs(config)#

cat cdb-init.xml my-host tail-f.com tail-f.se Ingrid Greta sustainability Gunvald security

ncs_load -Fp -p /host my-host tail-f.com tail-f.se Ingrid Greta sustainability Gunvald security

ncs_load -Fc -p /host host host-name my-host host domains [ tail-f.com tail-f.se ] host server-admin name Ingrid host user-info Greta expertise sustainability ! host user-info Gunvald expertise security !

User admin last logged in 2024-04-16T02:13:14.502173+00:00, to devpod-4884268602524010749-85755c9897-2gq8k, from 127.0.0.1 using cli-console admin connected from 127.0.0.1 using console on devpod-4884268602524010749-85755c9897-2gq8k admin@ncs# show running-config host host host-name my-host host domains [ tail-f.com tail-f.se ] host server-admin name Ingrid host user-info Greta expertise sustainability ! host user-info Gunvald expertise security ! admin@ncs# config Entering configuration mode terminal admin@ncs(config)# no host admin@ncs(config)# commit Commit complete. admin@ncs(config)# show full-configuration host % No entries found. admin@ncs(config)# load merge cdb-init.xml Loading. 493 bytes parsed in 0.07 sec (6.44 KiB/sec) admin@ncs(config)# commit dry-run cli { local-node { data host { + host-name my-host; + domains [ tail-f.com tail-f.se ]; server-admin { + name Ingrid; } + user-info Greta { + expertise sustainability; + } + user-info Gunvald { + expertise security; + } } } } admin@ncs(config)# commit Commit complete. admin@ncs(config)# show full-configuration host host host-name my-host host domains [ tail-f.com tail-f.se ] host server-admin name Ingrid host user-info Greta expertise sustainability ! host user-info Gunvald expertise security ! admin@ncs(config)#

Done

developer:cdb-yang > make showcase-rc python3 showcase_rc.py

Setup the demo

Make sure no nso or netsim processes are running

Create an NSO local install with a fresh runtime directory

make[1]: Entering directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang' rm -rf nso-lab-rundir mkdir nso-lab-rundir ncs-setup --dest ./nso-lab-rundir make[1]: Leaving directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang'

Have the environment variable NSO_RUNDIR point to the runtime directory

Done

Showcase: Extending the CDB with Packages

Step 1: Create a package

gmake[1]: Entering directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang/nso-lab-rundir/packages/my-data-entries/src' mkdir -p ../load-dir /home/developer/nso-6.2.1/bin/ncsc ls my-data-entries-ann.yang > /dev/null 2>&1 && echo "-a my-data-entries-ann.yang" --fail-on-warnings -c -o ../load-dir/my-data-entries.fxs yang/my-data-entries.yang gmake[1]: Leaving directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang/nso-lab-rundir/packages/my-data-entries/src'

Step 2: Add package to NSO

POST http://localhost:8080/restconf/operations/tailf-ncs:packages/reload { "tailf-ncs:output": { "reload-result": [ { "package": "my-data-entries", "result": true } ] } }

GET http://localhost:8080/restconf/data/my-data-entries:my-data-entries Status code: 204

Step 3: Set data

PATCH http://localhost:8080/restconf/data { "data": { "my-data-entries:my-data-entries": [ { "name": "ex1", "dummy": "0.0.0.0" } ] } } Status code: 204

Step 4: Inspect the YANG module

GET http://localhost:8080/restconf/data/tailf-ncs-monitoring:ncs-state/loaded-data-models/data-model=my-data-entries { "tailf-ncs-monitoring:data-model": [ { "name": "my-data-entries", "revision": "2016-01-01", "namespace": "http://example.com/my-data-entries", "prefix": "my-data-entries", "exported-to-all": [null] } ] }

GET http://localhost:8080/restconf/data/ietf-yang-library:modules-state/module=my-data-entries,2016-01-01/schema { "ietf-yang-library:schema": "http://localhost:8080/restconf/tailf/modules/my-data-entries/2016-01-01" }

GET http://localhost:8080/restconf/tailf/modules/my-data-entries/2016-01-01 module my-data-entries {

namespace "http://example.com/my-data-entries"; prefix my-data-entries;

import ietf-inet-types { prefix inet; } import tailf-common { prefix tailf; } import tailf-ncs { prefix ncs; }

description "Bla bla...";

revision 2016-01-01 { description "Initial revision."; }

list my-data-entries { description "This is an RFS skeleton service";

} }

Showcase: Building and Testing a Model

Step 1: Create a model skeleton

Note: Created the service skeleton package in step 1 of the previous showcase

module my-test-model { namespace "http://example.tail-f.com/my-test-model"; prefix "t";

Step 2: Fill out the model

container host { leaf host-name { type string; description "Hostname for this system"; } leaf-list domains { type string; description "My favourite internet domains"; } container server-admin { description "Administrator contact for this system"; leaf name { type string; } } list user-info { description "Information about team members"; key "name"; leaf name { type string; } leaf expertise { type string; } } } }

Step 3: Compile and load the model

make[1]: Entering directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang/nso-lab-rundir/packages/my-data-entries/src' /home/developer/nso-6.2.1/bin/ncsc ls my-test-model-ann.yang > /dev/null 2>&1 && echo "-a my-test-model-ann.yang" --fail-on-warnings -c -o ../load-dir/my-test-model.fxs yang/my-test-model.yang make[1]: Leaving directory '/home/developer/nso-6.2.1/examples.ncs/development-guide/cdb-yang/nso-lab-rundir/packages/my-data-entries/src' POST http://localhost:8080/restconf/operations/tailf-ncs:packages/reload

{ "tailf-ncs:output": { "reload-result": [ { "package": "my-data-entries", "result": true } ] } }

Step 4: Test the model

PATCH http://localhost:8080/restconf/data { "data": { "my-test-model:host": { "host-name": "my-host", "domains": [ "tail-f.com", "tail-f.se" ], "server-admin": { "name": "Ingrid" }, "user-info": [ { "name": "Greta", "expertise": "sustainability" }, { "name": "Gunvald", "expertise": "security" } ] } } } Status code: 204

GET http://localhost:8080/restconf/data/my-test-model:host { "my-test-model:host": { "host-name": "my-host", "domains": ["tail-f.com", "tail-f.se"], "server-admin": { "name": "Ingrid" }, "user-info": [ { "name": "Greta", "expertise": "sustainability" }, { "name": "Gunvald", "expertise": "security" } ] } }

DELETE http://localhost:8080/restconf/data/my-test-model:host Status code: 204 GET http://localhost:8080/restconf/data/my-test-model:host Status code: 204 PATCH http://localhost:8080/restconf/data Status code: 204 GET http://localhost:8080/restconf/data/my-test-model:host

my-host tail-f.com tail-f.se Ingrid Greta sustainability Gunvald security

Done

developer:cdb-yang >

cat >| templates/loopback.xml << EOF {/device} {/loopback-intf}

{/ip-address} 255.255.255.255

EOF ``` - Reload packages: packages reload - Try to configure a device using created service template: ``` config loopback test device core-rtr0 loopback-intf 201 ip-address 192.168.10.1 top commit dry-run outformat native ```

Note

  • With above service template, there might be some issues such as non-existing device, forgetting to set ip address

  • A well-designed service should produce consistent and reliable device configurations as an incorrect user input can result in the device rejecting the configuration. With different YANG statements, you can prevent that result before you send the configuration to the device.

Preventing incorrect user input

  • Open ~/src/nso-instance/packages/loopback/src/yang/loopback.yang, the YANG model of the loopback service again. To prevent incorrect user input, it should change from the following three leaves:

  • to: (Instead of the string type, use leafref and add a path that points to all devices in NSO)

  • The IP address is modeled as string which allows the user to provide invalid addresses. Use the inet:ipv4-address type instead, and make it mandatory. Doing so ensures that the user cannot forget to configure it. Import the ietf-inet-types module to be able to use the inet:ipv4-address type:

  • add tailf:info statements to all leaves that provides description of what value is expected. First import the tailf-common module. Then add the tailf:info with description to each leaf. The final data model should correspond to what this command generates:

  • Then rebuild the package and reload:

Some commands to debug:

  • commit | debug service

  • commit | details

Reference

Last updated