Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Labspg 2442 LG

Download as pdf or txt
Download as pdf or txt
You are on page 1of 37

LABSPG-2442

Lab Guide
Connecting to POD
Task 1: Installing NSO
 Log in to NSO either directly or launch putty from your remote desktop
 Execute the installer to begin installation
[root@nso ~]# ls
1 anaconda-ks.cfg holding nso-4.6.1.3 python_examples tmp-lab
[root@nso ~]#

[root@nso ~]# ./nso-4.6.linux.x86_64.installer.bin nso/4.6


INFO Using temporary directory /tmp/ncs_installer.2359 to stage NCS installation bundle
INFO Unpacked ncs-4.6 in /home/root/nso/4.6
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/root/nso/4.6/ncsrc
INFO NCS installation script finished
INFO Found and unpacked corresponding NETSIM_PACKAGE
INFO NCS installation complete

[root@nso ~]#

 Source ncsrc – adds binaries to your PATH


[root@nso ~]# source nso/4.6/ncsrc

 Setup NSO Project Runtime Directory

[root@nso ~]# ncs-setup --dest nso-lab

 Start NSO

[root@nso ~]# cd nso-lab/


root@nso ~/nso-lab$ ncs
root@nso ~/nso-lab$ ncs --status
vsn: 4.6
SMP support: no
Using epoll: yes
available modules: backplane,netconf,cdb,cli,snmp,webui
running modules: backplane,netconf,cdb,cli,snmp,webui
status: started

 Login to NSO and try the two different CLI:s

root@nso ~/nso-lab$ ncs_cli -u admin -C


admin connected from 10.16.55.18 using ssh on NCS
admin@ncs# exit
root@nso ~/nso-lab$
root@nso ~/nso-lab$ ncs_cli -u admin -J

admin connected from 10.16.55.18 using ssh on NCS


admin@ncs> exit
root@nso ~/nso-lab$

 Login to WebUI – username/password: admin/admin


NSO Packages

 Go to project directory

[root@nso ~]# cd ~/nso-lab/


root@nso ~/nso-lab$ ls packages/
root@nso ~/nso-lab$

 Copy NED packages

root@nso ~/nso-lab$ echo $NCS_DIR


/home/root/nso/4.6
root@nso ~/nso-lab$ cp -r $NCS_DIR/packages/neds/cisco-ios packages/
root@nso ~/nso-lab$ cp -r $NCS_DIR/packages/neds/dell-ftos packages/
root@nso ~/nso-lab$ ls packages/
cisco-ios dell-ftos
root@nso ~/nso-lab$

 Reload packages in NSO

root@nso ~/nso-lab$ ncs_cli -u admin -C

admin connected from 10.16.55.18 using ssh on NCS

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 cisco-ios
result true
}
reload-result {
package dell-ftos
result true
}
admin@ncs#

admin@ncs# show packages package package-version


PACKAGE
NAME VERSION
--------------------
cisco-ios 3.0.0.3
dell-ftos 3.0.1.1

admin@ncs#

admin@ncs# exit
root@nso ~/nso-lab$
Using Netsim

 Go to project directory

[root@nso ~]# cd ~/nso-lab/

 Create netsim devices

root@nso ~/nso-lab$ ncs-netsim create-network packages/cisco-ios 3 c


DEVICE c0 CREATED
DEVICE c1 CREATED
DEVICE c2 CREATED
root@nso ~/nso-lab$

root@nso ~/nso-lab$ ncs-netsim add-to-network packages/dell-ftos 2 dell


DEVICE dell0 CREATED
DEVICE dell1 CREATED
root@nso ~/nso-lab$

 Start netsim devices

root@nso ~/nso-lab$ ncs-netsim start


DEVICE c0 OK STARTED
DEVICE c1 OK STARTED
DEVICE c2 OK STARTED
DEVICE dell0 OK STARTED
DEVICE dell1 OK STARTED
root@nso ~/nso-lab$

 Login to a netsim device

root@nso ~/nso-lab$ ncs-netsim cli-i c1

admin connected from 10.16.55.18 using ssh on NCS


c1>

c1> enable
c1#

c1# show running-config


no service pad
no ip domain-lookup
no ip http server
no ip http secure-server
ip routing
ip source-route
ip vrf my-forward
bgp next-hop Loopback 1
...
!
c1#

c1# exit
root@nso ~/nso-lab$
Task 2: NSO Device Manager

Load Netsim devices into NSO

 Go to project directory

[root@nso ~]# cd ~/nso-lab/

 Export netsim devices connection data

root@nso ~/nso-lab$ ncs-netsim ncs-xml-init > devices.xml

 Import devices connection data into NSO

root@nso ~/nso-lab$ ncs_cli -u admin -C

admin connected from 10.16.55.18 using ssh on NCS


admin@ncs#

admin@ncs# conf
Entering configuration mode terminal
admin@ncs(config)#

admin@ncs(config)# load merge devices.xml


Loading.
5.36 KiB parsed in 0.07 sec (72.98 KiB/sec)
admin@ncs(config)#

admin@ncs(config)# commit
Commit complete.
admin@ncs(config)#

 Check devices in NSO

admin@ncs(config)# show full-configuration devices device c0


devices device c0
address 127.0.0.1
port 10022
ssh host-key ssh-dss
key-data
...
!
!
admin@ncs(config)#
Device Configuration Management

 Perform sync-from

admin@ncs(config)# devices sync-from


sync-result {
device c0
result true
}
sync-result {
device c1
result true
}
sync-result {
device c2
result true
}
sync-result {
device dell0
result true
}
sync-result {
device dell1
result true
}
admin@ncs(config)#

 Perform check-sync

admin@ncs(config)# devices check-sync


sync-result {
device c0
result in-sync
}
sync-result {
device c1
result in-sync
}
sync-result {
device c2
result in-sync
}
sync-result {
device dell0
result in-sync
}
sync-result {
device dell1
result in-sync
}
admin@ncs(config)#
 Configure Devices

admin@ncs(config)# devices device c0 config ios:interface GigabitEthernet 0/1 ip address 10.10.10.1


255.255.255.0
admin@ncs(config-if)#

admin@ncs(config-if)# top
admin@ncs(config)#

admin@ncs(config)# devices device c1 config ios:interface GigabitEthernet 0/2 ip address 10.10.10.20


255.255.255.0
admin@ncs(config-if)#

 Show configuration commands

admin@ncs(config-if)# top
admin@ncs(config)#

admin@ncs(config)# show configuration devices device c0


devices device c0
config
ios:interface GigabitEthernet0/1
ip address 10.10.10.1 255.255.255.0
exit
!
!
admin@ncs(config)#

admin@ncs(config)# show full-configuration devices device c0


devices device c0
address 127.0.0.1
port 10022
ssh host-key ssh-dss
key-data ...
!
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: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
!
!
!
admin@ncs(config)#
 Committing changes

admin@ncs(config)# commit dry-run


cli devices {
device c0 {
config {
ios:interface {
+ GigabitEthernet 0/1 {
+ ip {
+ address {
+ primary {
+ address 10.10.10.1;
+ mask 255.255.255.0;
+ }
+ }
+ }
+ }
}
}
}
device c1 {
config {
ios:interface {
+ GigabitEthernet 0/2 {
+ ip {
+ address {
+ primary {
+ address 10.10.10.20;
+ mask 255.255.255.0;
+ }
+ }
+ }
+ }
}
}
}
}
admin@ncs(config)#

admin@ncs(config)# commit dry-run outformat native


native {
device {
name c0
data interface GigabitEthernet0/1
ip address 10.10.10.1 255.255.255.0
exit
}
device {
name c1
data interface GigabitEthernet0/2
ip address 10.10.10.20 255.255.255.0
exit
}
}
admin@ncs(config)#

admin@ncs(config)# commit
Commit complete.
admin@ncs(config)#
 Exit NSO

admin@ncs(config)# exit
admin@ncs#

admin@ncs# exit
root@nso ~/nso-lab$

 Rollbacks
root@nso ~/nso-lab$ ls logs/
audit.log ncserr.log.siz rollback10001 rollback10006
devel.log ncs-java-vm.log rollback10002 snmp.log
localhost:8080.access ncs.log rollback10003 webui-browser.log
ncserr.log.1 ncs-python-vm.log rollback10004 xpath.trace
ncserr.log.idx netconf.log rollback10005
root@nso ~/nso-lab$

root@nso ~/nso-lab$ more logs/rollback10001


# Created by: system
# Date: 2018-01-26 12:53:49
# Via: system
# Type: delta
# Label:
# Comment:
# No: 10001

snmp:snmp {
snmp:agent {
...
}
delete:
snmp:community public;
snmp:vacm {
...
}
delete:
snmp:notify foo;
snmp:usm {
...
}
delete:
snmp:target monitor;
}
root@nso ~/nso-lab$

root@nso ~/nso-lab$ ncs_cli -u admin -C

admin connected from 10.16.55.18 using ssh on NCS


admin@ncs#

admin@ncs# conf
Entering configuration mode terminal
admin@ncs(config)#

admin@ncs(config)# rollback configuration 10006


admin@ncs(config)#

admin@ncs(config)# show configuration


no devices device c0
no devices device c1
no devices device c2
no devices device del0
no devices device del1
snmp agent disabled
no snmp agent version v1
no snmp agent version v2c
no snmp agent version v3
no snmp agent engine-id enterprise-number 32473
no snmp agent engine-id from-text testing
no snmp usm local user initial
no snmp target monitor
no snmp community public
no snmp notify foo
no snmp vacm group initial
no snmp vacm group public
no snmp vacm view internet
no snmp vacm view restricted
admin@ncs(config)#

admin@ncs(config)# revert
All configuration changes will be lost. Proceed? [yes, NO] yes
admin@ncs(config)#

Templates and Groups


 Create Device group
root@nso ~/nso-lab$ ncs_cli -u admin -C

admin connected from 10.16.55.18 using ssh on NCS


admin@ncs#

admin@ncs# conf
Entering configuration mode terminal
admin@ncs(config)#

admin@ncs(config)# devices device-group C device-name c0


admin@ncs(config-device-group-C)# device-name c1
admin@ncs(config-device-group-C)# device-name c2
admin@ncs(config-device-group-C)# device-name dell0

admin@ncs(config-device-group-C)# commit
Commit complete.
admin@ncs(config-device-group-C)#

 Create Device Template


admin@ncs(config)# top
admin@ncs(config)#

admin@ncs(config)# devices template snmp-settings config ios:snmp-server host 192.168.216.23


community-string secret
admin@ncs(config-community-string-secret)#

admin@ncs(config-community-string-secret)# devices template snmp-settings config ios:snmp-server


location Stockholm
admin@ncs(config-config)#
admin@ncs(config-config)# top
admin@ncs(config)#

admin@ncs(config)# show configuration


devices template snmp-settings
config
! first
ios:snmp-server host 192.168.216.23
! first
community-string secret
!
!
ios:snmp-server location Stockholm
!
!
admin@ncs(config)#

admin@ncs(config)# commit
Commit complete.
admin@ncs(config)#

 Apply template to device


admin@ncs(config)# devices device c0 apply-template template-name snmp-settings
apply-template-result {
device c0
result ok
}
admin@ncs(config)#

admin@ncs(config)# show configuration


devices device c0
config
ios:snmp-server host 192.168.216.23 secret
ios:snmp-server location Stockholm
!
!
admin@ncs(config)#

admin@ncs(config)# commit
Commit complete.
admin@ncs(config)#

admin@ncs(config)# exit
admin@ncs#

admin@ncs# exit
root@nso ~/nso-lab$
Task 3 – NSO Service Manager
Service Design
 Go to project directory

[root@nso ~]# cd ~/nso-lab/


root@nso ~/nso-lab$

root@nso ~/nso-lab$ cd packages/


root@nso ~/nso-lab/packages$

root@nso ~/nso-lab/packages$ ls
cisco-ios dell-ftos
root@nso ~/nso-lab/packages$

 Create package skeleton

root@nso ~/nso-lab/packages$ ncs-make-package --service-skeleton python-and-template trunk


root@nso ~/nso-lab/packages$

root@nso ~/nso-lab/packages$ ls trunk/


load-dir package-meta-data.xml src templates test
root@nso ~/nso-lab/packages$

root@nso ~/nso-lab/packages$ cd ..
root@nso ~/nso-lab$

 Configure sample service

root@nso ~/nso-lab$ ncs_cli -u admin -C

admin connected from 10.16.54.194 using ssh on NCS


admin@ncs#

admin@ncs# config
Entering configuration mode terminal
admin@ncs(config)#

admin@ncs(config)# devices device dell0 config force10:interface Vlan 10 tagged GigabitEthernet0/11


admin@ncs(config-Vlan-10)#

admin@ncs(config-Vlan-10)# devices device c0 config ios:interface GigabitEthernet 0/23 switchport


mode trunk
admin@ncs(config-if)#

admin@ncs(config-if)# devices device c0 config ios:interface GigabitEthernet 0/23 switchport trunk


allowed vlan 11
admin@ncs(config-if)#

admin@ncs(config-if)# top
admin@ncs(config)#
admin@ncs(config)# commit dry-run outformat native
native {
device {
name c0
data interface GigabitEthernet0/23
switchport mode trunk
switchport trunk allowed vlan 11
exit
}
device {
name dell0
data interface Vlan 10
no ip address
tagged GigabitEthernet0/11
!
}
}
admin@ncs(config)#

admin@ncs(config)# commit dry-run outformat xml


result-xml <devices xmlns="http://tail-f.com/ns/ncs">
<device>
<name>c0</name>
<config>
<interface xmlns="urn:ios">
<GigabitEthernet>
<name>0/23</name>
<switchport>
<mode>
<trunk/>
</mode>
<trunk>
<allowed>
<vlan>
<vlans>11</vlans>
</vlan>
</allowed>
</trunk>
</switchport>
</GigabitEthernet>
</interface>
</config>
</device>
<device>
<name>dell0</name>
<config>
<interface xmlns="http://tail-f.com/ned/dell-ftos">
<Vlan>
<id>10</id>
<tagged>
<id>GigabitEthernet0/11</id>
</tagged>
</Vlan>
</interface>
</config>
</device>
</devices>

admin@ncs(config)#

admin@ncs(config)# commit
Commit complete.
admin@ncs(config)#

 Create service template

o Remote desktop into workstation


o Goto: Z:\nso-lab\packages\trunk\templates

o Open trunk-template.xml file in Notepad++


o Copy XML blocks (everything between the <config> and </config> tags)
from command output into XML file:

admin@ncs(config)# show full-configuration devices device dell0 config force10:interface Vlan | display
xml
<config xmlns="http://tail-f.com/ns/config/1.0">
<devices xmlns="http://tail-f.com/ns/ncs">
<device>
<name>dell0</name>
<config>
<interface xmlns="http://tail-f.com/ned/dell-ftos">
<Vlan>
<id>10</id>
<tagged>
<id>GigabitEthernet0/11</id>
</tagged>
</Vlan>
</interface>
</config>
</device>
</devices>
</config>
admin@ncs(config)#
admin@ncs(config)# show full-configuration devices device c0 config ios:interface GigabitEthernet 0/23
| display xml
<config xmlns="http://tail-f.com/ns/config/1.0">
<devices xmlns="http://tail-f.com/ns/ncs">
<device>
<name>c0</name>
<config>
<interface xmlns="urn:ios">
<GigabitEthernet>
<name>0/23</name>
<switchport>
<mode>
<trunk/>
</mode>
<trunk>
<allowed>
<vlan>
<vlans>11</vlans>
</vlan>
</allowed>
</trunk>
</switchport>
</GigabitEthernet>
</interface>
</config>
</device>
</devices>
</config>
admin@ncs(config)#
o Resultant XML file
o Parameterise the XML file, so it looks like below, parameters highlighted
in yellow

<config-template xmlns="http://tail-f.com/ns/config/1.0" servicepoint="trunk">


<devices xmlns="http://tail-f.com/ns/ncs">
<device>
<!--
Select the devices from some data structure in the service
model. In this skeleton the devices are specified in a leaf-list.
Select all devices in that leaf-list:
-->
<name>{/endpoint/device}</name>
<config>
<interface xmlns="http://tail-f.com/ned/dell-ftos">
<Vlan>
<id>{string(/vlan)}</id>
<tagged>
<id>GigabitEthernet{interface}</id>
</tagged>
</Vlan>
</interface>
<interface xmlns="urn:ios">
<GigabitEthernet>
<name>{interface}</name>
<switchport>
<mode>
<trunk />
</mode>
<trunk>
<allowed>
<vlan>
<vlans>{/vlan}</vlans>
</vlan>
</allowed>
</trunk>
</switchport>
</GigabitEthernet>
</interface>
</config>
</device>
</devices>
</config-template>

o Save trunk-template.xml XML file


 Create service model in YANG

o Remote desktop into workstation


o Goto: Z:\nso-lab\packages\trunk\src\yang
o Open trunk.yang file in Notepad++, and delete the highlighted text below

o Update the Yang file with service model

module trunk {
namespace "http://com/example/trunk";
prefix trunk;

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

list trunk {
key name;

uses ncs:service-data;
ncs:servicepoint "trunk";
leaf name {
type string;
}

list endpoint {
key device;
leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
}
leaf interface {
type string;
}
}
leaf vlan{
type uint16;
}
}
}

o Save trunk.yang YANG file

 Compile and deploy package

[root@nso ~]# cd ~/nso-lab/


root@nso ~/nso-lab$

root@nso ~/nso-lab$ cd packages/trunk/src/


root@nso ~/nso-lab/packages/trunk/src$

root@nso ~/nso-lab/packages/trunk/src$ make


/home/root/nso/4.6/bin/ncsc `ls trunk-ann.yang > /dev/null 2>&1 && echo "-a trunk-ann.yang"` \
--yangpath yang -c -o ../load-dir/trunk.fxs yang/trunk.yang
root@nso ~/nso-lab/packages/trunk/src$

root@nso ~/nso-lab/packages/trunk/src$ cd ../../..


root@nso ~/nso-lab$

root@nso ~/nso-lab$ ncs_cli -u admin -C

admin connected from 10.16.54.194 using ssh on NCS


admin@ncs#
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 cisco-ios
result true
}
reload-result {
package dell-ftos
result true
}
reload-result {
package trunk
result true
}
admin@ncs#

 Create Service Instance

root@nso ~/nso-lab$ ncs_cli -u admin -C

admin connected from 10.16.54.194 using ssh on NCS


admin@ncs#

admin@ncs# conf
Entering configuration mode terminal
admin@ncs(config)#

admin@ncs(config)# trunk myservice endpoint c0 interface 0/2


admin@ncs(config-endpoint-c0)#

admin@ncs(config-endpoint-c0)# endpoint dell0 interface 0/12


admin@ncs(config-endpoint-del0)#

admin@ncs(config-endpoint-del0)# vlan 12
admin@ncs(config-trunk-myservice)#

admin@ncs(config-trunk-myservice)# top
admin@ncs(config)#

admin@ncs(config)# show full-configuration services trunk


trunk myservice
endpoint c0
interface 0/2
!
endpoint del0
interface GigabitEthernet0/12
!
vlan 12
!
admin@ncs(config)#
admin@ncs(config)# commit dry-run outformat native
native {
device {
name c0
data interface GigabitEthernet0/2
switchport mode trunk
switchport trunk allowed vlan 12
exit
}
device {
name del0
data interface Vlan 12
no ip address
!
}
}
admin@ncs(config)#

admin@ncs(config)# commit
Commit complete.
admin@ncs(config)#

Extra tasks

Add constraints to the YANG file.


 Max-elements and min-elements to the endpoint list.
 Range to the vlan leaf

list endpoint {
key device;
max-elements 2;
min-elements 2;

leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
}
leaf interface {
type string;
}
}
leaf vlan {
type uint16 {
range "0..4095";
}
}

Get tab completion when choosing interfaces.


In the service YANG model we just created the interface leaf is of type string, that
means that it’s a free form textual input and no verification that the interface exists is
done. One way of making sure that the user can only choose between existing
interfaces is to make the interface leaf of type leafref. That means a reference to an
existing instance of a leaf in the model. One problem here is that we cant have a leaf
of type leafref pointing at multiple XPATH:s, to solve that we here replace the
interface leaf with a YANG choice with two cases, one for each interface type.

So lets go a head:

First lets create a few interfaces on the devices:


admin@ncs(config)#
admin@ncs(config)# devices device c0 config ios:interface GigabitEthernet 0/1
admin@ncs(config-if)# devices device c0 config ios:interface GigabitEthernet 0/2
admin@ncs(config-if)# devices device c0 config ios:interface GigabitEthernet 0/3
admin@ncs(config-if)# devices device c1 config ios:interface GigabitEthernet 0/1
admin@ncs(config-if)# devices device c1 config ios:interface GigabitEthernet 0/2
admin@ncs(config-if)# devices device c1 config ios:interface GigabitEthernet 0/3
admin@ncs(config-if)#
admin@ncs(config-if)# devices device d0 config force10:interface GigabitEthernet 0/1
admin@ncs(config-GigabitEthernet-0/1)# devices device d0 config force10:interface GigabitEthernet 0/2
admin@ncs(config-GigabitEthernet-0/2)# devices device d0 config force10:interface GigabitEthernet 0/3
admin@ncs(config-GigabitEthernet-0/3)# devices device d1 config force10:interface GigabitEthernet 0/1
admin@ncs(config-GigabitEthernet-0/1)# devices device d1 config force10:interface GigabitEthernet 0/2
admin@ncs(config-GigabitEthernet-0/2)# devices device d1 config force10:interface GigabitEthernet 0/3
admin@ncs(config-GigabitEthernet-0/3)# top
admin@ncs(config)# commit

Get the interface XPATH value


admin@ncs(config)# show full-configuration devices device c0 config ios:interface GigabitEthernet | display
xpath
/devices/device[name='c0']/config/ios:interface/GigabitEthernet[name='0/1']
/devices/device[name='c0']/config/ios:interface/GigabitEthernet[name='0/11']/switchport/mode/trunk
/devices/device[name='c0']/config/ios:interface/GigabitEthernet[name='0/11']/switchport/trunk/allowed/vlan/vla
ns [ 12 ]

admin@ncs(config)# show full-configuration devices device c0 config ios:interface GigabitEthernet | display


xpath | display prefixes
/ncs:devices/ncs:device[ncs:name='c0']/ncs:config/ios:interface/ios:GigabitEthernet[ios:name='0/1']
/ncs:devices/ncs:device[ncs:name='c0']/ncs:config/ios:interface/ios:GigabitEthernet[ios:name='0/11']/ios:switch
port/ios:mode/ios:trunk
/ncs:devices/ncs:device[ncs:name='c0']/ncs:config/ios:interface/ios:GigabitEthernet[ios:name='0/11']/ios:switch
port/ios:trunk/ios:allowed/ios:vlan/ios:vlans [ 12 ]

Update the service YANG model, add a choice just under the interface leaf (you can
remove the interface leaf later of course) and add two cases, one for each interface
type available. The leafs cant have the same name (one disadvantage of the choice
type). You can see in the leafref path that we are taking advantage of a Tail-f YANG
addition called deref, that method takes a leaf of type leafref as input and returns the
XPATH for that instance. The pure YANG equvivalent would be

type leafref {
path
/ncs:devices:ncs:device[ncs:name=../device]/ncs:config/ios:interface/ios:GigabitEther
net/ios:name;
}
The deref returns the full XPATH for the instance i.e:

/ncs:devices/ncs:device[ncs:name=’c0’]

That is why we have to add the /../ after the deref to get to the device config container
which is in the same level as the name leaf.

choice xvendor {
case cisco-GigabitEthernet {
leaf CiscoGigabitEthernet {
when
/ncs:devices/ncs:device[ncs:name=current()/../device]/ncs:config/ios:interface/ios:Gig
abitEthernet/ios:name;
type leafref {
path
deref(../device)/../ncs:config/ios:interface/ios:GigabitEthernet/ios:name;
}
}
}
case dell-GigabitEthernet {
leaf DellGigabitEthernet {
when
/ncs:devices/ncs:device[ncs:name=current()/../device]/ncs:config/force10:interface/for
ce10:GigabitEthernet/force10:id;
type leafref {
path
deref(../device)/../ncs:config/force10:interface/force10:GigabitEthernet/force10:id;
}
}
}
}
Update the service template.

<config-template xmlns="http://tail-f.com/ns/config/1.0">
<devices xmlns="http://tail-f.com/ns/ncs">
<device>
<name>{/endpoint/device}</name>
<config>

<interface xmlns="http://tail-f.com/ned/dell-ftos">
<Vlan>
<id>{string(/vlan)}</id>
<tagged>
<id>GigabitEthernet{DellGigabitEthernet}</id>
</tagged>
</Vlan>
</interface>

<interface xmlns="urn:ios">
<GigabitEthernet>
<name>{CiscoGigabitEthernet}</name>
<switchport>
<mode>
<trunk/>
</mode>
<trunk>
<allowed>
<vlan>
<vlans>{string(/vlan)}</vlans>
</vlan>
</allowed>
</trunk>
</switchport>
</GigabitEthernet>
</interface>

</config>
</device>
</devices>
</config-template>

Reload the packages

admin@ncs(config)# exit
admin@ncs# packages reload

Test your service changes

admin@ncs# config
admin@ncs(config)# trunk myservice2 endpoint c0 CiscoGigabitEthernet 0/
Possible completions:
1 2 3
admin@ncs(config)# trunk myservice2 endpoint dell0 DellGigabitEthernet 0/
Possible completions:
1 2 3
admin@ncs(config)# trunk myservice2 endpoint d0 DellGigabitEthernet 0/1
admin@ncs(config-endpoint-d0)# trunk myservice2 endpoint c0
CiscoGigabitEthernet 0/2
admin@ncs(config-endpoint-d0)# top
admin@ncs(config)# commit dry-run
cli {
local-node {
data devices {
device c0 {
config {
ios:interface {
GigabitEthernet 0/2 {
switchport {
mode {
+ trunk {
+ }
}
trunk {
allowed {
vlan {
+ vlans 55;
}
}
}
}
}
}
}
}
device dell0 {
config {
force10:interface {
+ Vlan 55 {
+ tagged GigabitEthernet0/2;
+ }
}
}
}
}
+trunk mys2 {
+ endpoint c0;
+ endpoint d1;
+ vlan 55;
+}
}
}
As you can see this can quickly become quite complex if you have multiple device
types with multiple interface types. This way of designing your service YANG
models is only recommended if the services instances will be created directly on NSO
by users. If it will be mostly northbound systems like order managers etc that will be
interacting with NSO this kind of design just makes that integration harder and the
recommended way is to use a single leaf for all interface types (as the initial design).
Interface verification can and should still be done but at a lower level. Remember a
northbound system can still check if the interface exists by looking under devices
device in NSO.

Template processing instructions


In the above example we have one interface type per device type so we didn’t have to
use any of the NSO template processing intructions like if/else/foreach. As an extra
task add FastEthernet as a choice in your service and make use of if/else/end to make
sure that your template configures the right interface type.

You can find more information about these instructions in the NSO development
guide. It around page 270 under the chapter “Processing instructions”.

Table 160. Template processing instructions

Syntax Description
Allows to assign new variables or manipulate existing variable
value. If
used to create a new variable, then the scope of visibility of
<?set variable = value?> this variable is limited to the parent tag of the processing
instruction or the current processing instruction block.
Specifically, if a new variable is defined inside a loop, then it
is discarded at the end of each iteration.
Processing instruction block that allows conditional execution
<?if {expression}?
>...<?else?>...<? end?> based on the boolean result of the expression. For the detailed
description see the section called “Conditional Statements”
The expression must evaluate to a (possibly empty) XPath
node-set. The template engine will then iterate over each node
<?foreach {expression}? in the node-set by changing the XPath current context node to
>...<?end?> this node and evaluating all children tags within this context.
For the detailed description see the section called “Loop
Statements”
<?for [variable = initial This processing instruction allows to iterate over the same set
value]; {progress of template tags by changing a variable value. The variable
condition}; [variable = visibility scope obeys the same rules as in the case of set
next value]?>...<?end? > processing instruction, except the variable value is carried over
to the next iteration instead of being discarded at the end of
each iteration. The square brackets indicate optional clauses,
so only the condition expression is mandatory. For the detailed
description see the section called “Loop Statements”
This instruction is analogous to copy_tree function available in
the MAAPI API. The parameter is an XPath expression which
must evaluate to exactly one node in the data tree and indicates
<?copy-tree {source}?>
the source path to copy from. The target path is defined by the
position of the copy-tree instruction in the template
within the current context.
Allows to manipulate the current context node used to
<?set- context-node evaluate XPath expressions in the template. The expression is
{expression}?> evaluated within the current XPath context and must evaluate
to exactly one node in the data tree.

Allows to manipulate the root node of the XPath accessible tree. This
<?set-root-node expression is evaluated in an XPath context where the accessible tree is the
{expression}?> entire datastore, which means that it is possible to select a root node outside
the current accessible tree. The current context node remains unchanged. Just
like with the set-context-node instruction the expression must
evaluate to exactly one node in the data tree.
Store both the current context node and the root node of the XPath accessible
tree with name being the key to access it later. It is possible to switch to this
<?save-context context later using switch-context with the name. Multiple contexts
name?> can be stored simultaneously under different names. Using save-context with
the same name multiple times will result in the stored context being
overwritten.
Used to switch to a context stored using save-context with the specified
name. This means that both the current context node and the root node of
<?switch-context the XPath accessible tree will be changed to the stored values. switch-
name?> context does not remove the context from the storage and can be used as
many times as needed, however using it with a name that does not exist in the
storage would cause an error.

Python
The python API together with IPython can be really handy when you want to do some
rapid prototyping and test out your ideas. There is a small script already in your bash
PATH of your Linux box called ncs_pycli that will setup a transaction toward you
running NSO instance so you are ready to play around. If you like to download the
script to your own system it can be found in the NSO Developer Hub Github page:
https://github.com/NSO-developer/ncs_pycli

Just type ncs_pycli and it will start a python prompt and give you a root object
pointing to the NSO root. The beauty of IPython is that it gives you some handy
features like tab completion, pretty much like you have in the normal NSO cli.

bash$ ncs_pycli
Your maagic object 'root -> (root)' is now prepared... go have some fun!
trans.compare() to see your current transaction
trans.apply() to commit
trans.revert() to revert changes
Maapi object can be found at m
You can restart the transaction and create a fresh root object by invoking new_trans:
In [1]: new_trans
new transaction created

List all the devices

In [1]: for device in root.ncs__devices.device:


...: print(device.name)
...:
c0
c1
d0
d1

Set device to c0

In [2]: device = root.ncs__devices.device['c0']

Get the type of object

In [8]: type(root.ncs__devices)
Out[8]: ncs.maagic.Container
Help about the objects

In [7]: help(root.ncs__devices)
Help on Container in module ncs.maagic object:

class Container(Node)
| Represents a yang container.
|
| A (non-presence) container node or a list element, contains other nodes.
|
| Method resolution order:
| Container
| Node
| __builtin__.object
|
| Methods defined here:
|
| __init__(self, backend, cs_node, parent=None)
| Initialize Container node. Should not be called explicitly.
|
| __repr__(self)
| Get internal representation.
|
| delete(self)
| Delete the container.
|
| Deletes all nodes inside the container. The container itself is not
| affected as it carries no state of its own.
…..
…..

Set the hostname to C0 of the device (in this case c0)

In [10]: device.config.ios__hostname = 'C0'

See what we have in the transaction

In [11]: trans.compare()
Diff set:
kp=/ncs:devices/device{d1}, op=MOP_MODIFIED, oldv=None, newv=None
kp=/ncs:devices/device{d1}/config/ios:hostname, op=MOP_VALUE_SET,
oldv=None, newv=C0

Commit the change

In [12]: trans.apply()

In [13]:

On your own, now try to create a new trunk service instance via python.
And as a last advanced task, make the service automatically set a random vlan id. I’ll
help you with parts of the code, think about why it is written as it is? How does
FASTMAP work? Extra extra task can be do make sure that the vlan id hasn’t already
been allocated by any other service instance.

Change your main.py in packages/trunk/python/trunk/ to the following:

# -*- mode: python; python-indent: 4 -*-


import ncs
from ncs.application import Service
import random

# ------------------------
# SERVICE CALLBACK EXAMPLE
# ------------------------
class ServiceCallbacks(Service):

# The create() callback is invoked inside NCS FASTMAP and


# must always exist.
@Service.create
def cb_create(self, tctx, root, service, proplist):
self.log.info('Service create(service=', service._path, ')')

vars = ncs.template.Variables()
vars.add('DUMMY', '127.0.0.1')

vlan = random.randint(1, 4095)

for prop in proplist:


if 'vlan' in prop:
print(str(prop[1]) + ' already allocated')
else:
print(str(vlan) + ' new vlan')
pl = proplist + [('vlan', str(vlan))]
return pl

template = ncs.template.Template(service)
template.apply('trunk-template', vars)
Add the missing lines to add the vlan variable to the template, both the missing pieces
in the python code (the variable always needs to exist for the template enginte to
work, it can sometimes be empty but has to exist) and add the missing piece to the
template. Remember to reload packages. If you want to see whats going on you can
always tail the log files:

bash$ cd logs
bash$ tail -f ncs-python*

You might also like