Hello my friend,

For long time I’ve been preparing to write this article and finally you are reading it. The topic is really hot as everything, which is named “open” today, becomes automatically fancy and widely discussed. What we will do today, we’ll explore the OpenConfig capabilities on Arista EOS, Cisco IOS XR and Nokia (Alcatel-Lucent) SR OS and will try to understand how much OpenConfig is really open.

Disclaimer

All the information is provided on “as-is” basis with the status of OpenConfig YANG modules in particular versions of Nokia VSR, Arista vEOS and Cisco IOS XRv. Different version might have different versions of OpenCofngi models and therefore structure of YANG model can be changed.

Brief description

The first time I we heard about OpenConfig project was not too long ago. Actually it was only on Cisco Live 2018. By that time, according to the website of OpenConfig, the project was roughly 3 years old. For me it’s good as it means that project has reached minimum level of maturity, so I’m able to create some scenarios using it. Or at least I hope so, as by the time I’ve started writing it, I haven’t implemented everything I am going to do.

So, what is OpenConfig? The official website gives us the following answer:

“OpenConfig is an informal working group of network operators sharing the goal of moving our networks toward a more dynamic, programmable infrastructure by adopting software-defined networking principles such as declarative configuration and model-driven management and operations; Our initial focus in OpenConfig is on compiling a consistent set of vendor-neutral data models (written in YANG) based on actual operational needs from use cases and requirements from multiple network operators”

Basically, It’s YANG data model, which should be the same across all vendors. Sounds really “open”. Some time ago, when we were reviewing NETCONF/YANG for Nokia (Alcatel-Lucent) SR OS and Cisco IOS XR, we explained that each and every vendor has its own YANG data model, what means that the automation tool, like Ansible, has to have per-vendor drivers, what is definitely requires a lot of developers’ efforts.

Just imagine, that you need to deploy automation only once, as all the vendors understand it in the same way.

That’s the goal of the OpenConfig initiative. Let’s take a look on the status of the OpenConfig YANG model now:

As you see, the current focus of the OpenConfig model lays on standard parameters in the configuration of the network devices: interfaces, ACLs, routing protocols and etc. Actually, most of the configuration regardless of the vendor is done across these parameters. Sure, deep tuning of the performance requires much more, but how often do we need such deep tuning? So. In my eyes, OpenConfig if implemented will ease the live of the network developers and operators a lot.

What we are going to test?

Initially I started writing the article about interfaces and BGP using OpenConfig, but it turned to be very long. That’s why this article is the first in the series about OpenConfig and is focused only on interfaces.

We will try make the following things in our article for 3 OSes (Arista EOS, Cisco IOS XR and Nokia SR OS):

  • Get the configuration done in OpenConfig YANG model for interfaces
  • Edit the desired configuration on OpenConfig YANG model for interfaces
  • Create proper Ansible playbook for configuration of interfaces

The main reason, why I’m reading the configuration from the network device is that I learned that different virtual routers supports different versions of OpenConfig, hence there are some deviations in place in terms of syntax, so I need first of all to understand exact syntax of particular device.

Software version

The following infrastructure is used in my lab:

  • CentOS 7 with python 2.7.
  • Ansible 2.6.0 [NEW!]
  • Arista EOS 4.20.5F [NEW!]
  • Nokia SR OS 16.0.R1
  • Cisco IOS XR 6.1.2

See the previous article to get details how to build the lab

Just some weeks ago the new version of Ansible, which is 2.6.0 at the time of writing, was released. So I’m using it as there are some new modules for NETCONF, which might be useful for such automation.

Topology

The physical topology doesn’t vary from the something we have used previously, so it’s important that all our VNFs are somehow connected to management host:

We’ll use well known topology for data center fabric with 2 spines and 2 leafs with all vendors (Nokia VSR, Arista vEOS and Cisco XRv):

The initial configuration files just enable management access over SSH to devices over management interface: 128_config_initial_SR1 128_config_initial_vEOS2 128_config_initial_XR3 128_config_initial_XR4 128_config_initial_linux

How to read YANG model?

Let’s start with some recap about YANG data models. Some time ago, when we reviewed NETCONF/YANG for Cisco IOS XR, I have shared some information how to understand YANG structure. Here I’ll show more convenient way.

First of all, we need to download data models locally from GitHub repo of OpenConfig. Put it anywhere you like, just remember the exact path. I’ve put it into new folder:

1
2
3
4
$ pwd
/home/aaa/Yang/openconfig
$ ls
public

Then I advise to install pyang” tool, which is very easy and convenient to read YANG data:

1
$ sudo pip install pyang

After that is done, we can review any YANG data we have. To do that I issue the following command:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
.$ pyang -f tree -p ~/Yang/openconfig/public/release/models/ ~/Yang/openconfig/public/release/models/interfaces/openconfig-interfaces.yang
module: openconfig-interfaces
  +--rw interfaces
     +--rw interface* [name]
        +--rw name             -> ../config/name
        +--rw config
        |  +--rw name?            string
        |  +--rw type             identityref
        |  +--rw mtu?             uint16
        |  +--rw loopback-mode?   boolean
        |  +--rw description?     string
        |  +--rw enabled?         boolean
        +--ro state
        |  +--ro name?            string
        |  +--ro type             identityref
        |  +--ro mtu?             uint16
        |  +--ro loopback-mode?   boolean
        |  +--ro description?     string
        |  +--ro enabled?         boolean
        |  +--ro ifindex?         uint32
        |  +--ro admin-status     enumeration
        |  +--ro oper-status      enumeration
        |  +--ro last-change?     oc-types:timeticks64
        |  +--ro counters
        |     +--ro in-octets?             oc-yang:counter64
        |     +--ro in-unicast-pkts?       oc-yang:counter64
        |     +--ro in-broadcast-pkts?     oc-yang:counter64
        |     +--ro in-multicast-pkts?     oc-yang:counter64
        |     +--ro in-discards?           oc-yang:counter64
        |     +--ro in-errors?             oc-yang:counter64
        |     +--ro in-unknown-protos?     oc-yang:counter64
        |     +--ro in-fcs-errors?         oc-yang:counter64
        |     +--ro out-octets?            oc-yang:counter64
        |     +--ro out-unicast-pkts?      oc-yang:counter64
        |     +--ro out-broadcast-pkts?    oc-yang:counter64
        |     +--ro out-multicast-pkts?    oc-yang:counter64
        |     +--ro out-discards?          oc-yang:counter64
        |     +--ro out-errors?            oc-yang:counter64
        |     +--ro carrier-transitions?   oc-yang:counter64
        |     +--ro last-clear?            oc-types:timeticks64
        +--rw hold-time
        |  +--rw config
        |  |  +--rw up?     uint32
        |  |  +--rw down?   uint32
        |  +--ro state
        |     +--ro up?     uint32
        |     +--ro down?   uint32
        +--rw subinterfaces
           +--rw subinterface* [index]
              +--rw index     -> ../config/index
              +--rw config
              |  +--rw index?         uint32
              |  +--rw description?   string
              |  +--rw enabled?       boolean
              +--ro state
                 +--ro index?          uint32
                 +--ro description?    string
                 +--ro enabled?        boolean
                 +--ro name?           string
                 +--ro ifindex?        uint32
                 +--ro admin-status    enumeration
                 +--ro oper-status     enumeration
                 +--ro last-change?    oc-types:timeticks64
                 +--ro counters
                    +--ro in-octets?             oc-yang:counter64
                    +--ro in-unicast-pkts?       oc-yang:counter64
                    +--ro in-broadcast-pkts?     oc-yang:counter64
                    +--ro in-multicast-pkts?     oc-yang:counter64
                    +--ro in-discards?           oc-yang:counter64
                    +--ro in-errors?             oc-yang:counter64
                    +--ro in-unknown-protos?     oc-yang:counter64
                    +--ro in-fcs-errors?         oc-yang:counter64
                    +--ro out-octets?            oc-yang:counter64
                    +--ro out-unicast-pkts?      oc-yang:counter64
                    +--ro out-broadcast-pkts?    oc-yang:counter64
                    +--ro out-multicast-pkts?    oc-yang:counter64
                    +--ro out-discards?          oc-yang:counter64
                    +--ro out-errors?            oc-yang:counter64
                    +--ro carrier-transitions?   oc-yang:counter64
                    +--ro last-clear?            oc-types:timeticks64

You can see many examples on “-f tree” in Internet, what helps to build that tree of YANG model. But there are only few examples on “-p xxx”, which used to set the path to look for dependencies in other modules. If you don’t configure path, you might see the following error:

1
2
3
4
$ pyang -f tree ~/Yang/openconfig/public/release/models/interfaces/openconfig-interfaces.yang
/home/aaa/Yang/openconfig/public/release/models/interfaces/openconfig-interfaces.yang:12: error: module "openconfig-yang-types" not found in search path
/home/aaa/Yang/openconfig/public/release/models/interfaces/openconfig-interfaces.yang:13: error: module "openconfig-types" not found in search path
/home/aaa/Yang/openconfig/public/release/models/interfaces/openconfig-interfaces.yang:14: error: module "openconfig-extensions" not found in search path

After we have understood, how to treat the OpenConfig YANG data models, we can go further.

Which transport to use?

OpenConfig isn’t bounded to any particular transport mechanism according to the official website. So it can be used over:

  • NETCONF
  • RESTCONF
  • gNMI (gRPC Network Management Interface)

In this article we will use NETCONF, as several time previously, so that we have consistent view on network management techniques.

OpenConfig and Cisco IOS XR

I will start with OpenConfig explanation with Cisco IOS XR. The reason why I’m doing it in this way is that Cisco IOS XR has some examples and demos in the Internet, which I used to get to know OpenConfig. So, for me it was essentially to start with something familiar.

#1. Cisco IOS XR. Enabling OpenConfig

There is no specific configuration for OpenConfig on Cisco IOS XR comparing to ordinary NETCONF, so we just enable NETCONF as usual:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
RP/0/0/CPU0:XR4(config)#show conf
Building configuration...
!! IOS XR Configuration 6.1.2
!
control-plane
 management-plane
  inband
   interface GigabitEthernet0/0/0/0.999
    allow NETCONF peer
     address ipv4 192.168.0.0/16
    !
   !
  !
 !
!
netconf agent tty
!
netconf-yang agent
 ssh
!
ssh server netconf vrf MGMT
!
end

 

When this configuration is done, let’s test, what we see in NETCONF call flow:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
$ ssh cisco@XR4 -p 830 -s netconf
The authenticity of host '[xr4]:830 ([192.168.1.112]:830)' can't be established.
RSA key fingerprint is SHA256:wC3Fs9LYR5erMxBxI7F98JIIycXm6EW767POJnpYh9E.
RSA key fingerprint is MD5:e7:16:b8:7a:5a:44:25:f9:7d:b6:93:86:ee:04:97:bb.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[xr4]:830,[192.168.1.112]:830' (RSA) to the list of known hosts.



IMPORTANT:  READ CAREFULLY
Welcome to the Demo Version of Cisco IOS XRv (the "Software").
The Software is subject to and governed by the terms and conditions
of the End User License Agreement and the Supplemental End User
License Agreement accompanying the product, made available at the
time of your order, or posted on the Cisco website at
www.cisco.com/go/terms (collectively, the "Agreement").
As set forth more fully in the Agreement, use of the Software is
strictly limited to internal use in a non-production environment
solely for demonstration and evaluation purposes.  Downloading,
installing, or using the Software constitutes acceptance of the
Agreement, and you are binding yourself and the business entity
that you represent to the Agreement.  If you do not agree to all
of the terms of the Agreement, then Cisco is unwilling to license
the Software to you and (a) you may not download, install or use the
Software, and (b) you may return the Software as more fully set forth
in the Agreement.


Please login with any configured user/password, or cisco/cisco


cisco@xr4's password:
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <capabilities>
  <capability>urn:ietf:params:netconf:base:1.1</capability>
  <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
  <capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</capability>
  <capability>urn:ietf:params:netconf:capability:validate:1.1</capability>
  <capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-lib-cfg?module=Cisco-IOS-XR-aaa-lib-cfg&amp;revision=2015-11-09</capability>
!
! Output ommited
!
  <capability>http://openconfig.net/yang/bgp-multiprotocol?module=openconfig-bgp-multiprotocol&amp;revision=2015-10-09</capability>
  <capability>http://openconfig.net/yang/bgp-operational?module=openconfig-bgp-operational&amp;revision=2015-10-09</capability>
  <capability>http://openconfig.net/yang/bgp-policy?module=openconfig-bgp-policy&amp;revision=2015-10-09&amp;deviation=cisco-xr-bgp-policy-deviations</capability>
  <capability>http://openconfig.net/yang/bgp-types?module=openconfig-bgp-types&amp;revision=2015-05-15</capability>
  <capability>http://openconfig.net/yang/bgp?module=openconfig-bgp&amp;revision=2015-10-09&amp;deviation=cisco-xr-bgp-deviations</capability>
  <capability>http://openconfig.net/yang/openconfig-ext?module=openconfig-extensions&amp;revision=2015-10-09</capability>
  <capability>http://openconfig.net/yang/interface/aggregate?module=openconfig-if-aggregate&amp;revision=2015-11-20&amp;deviation=cisco-xr-openconfig-if-aggregate-deviations</capability>
  <capability>http://openconfig.net/yang/interfaces/ethernet?module=openconfig-if-ethernet&amp;revision=2015-11-20&amp;deviation=cisco-xr-openconfig-if-ethernet-deviations</capability>
  <capability>http://openconfig.net/yang/interfaces/ip?module=openconfig-if-ip&amp;revision=2015-11-20&amp;deviation=cisco-xr-openconfig-if-ip-deviations</capability>
  <capability>http://openconfig.net/yang/interfaces?module=openconfig-interfaces&amp;revision=2015-11-20&amp;deviation=cisco-xr-openconfig-interfaces-deviations</capability>
  <capability>http://openconfig.net/yang/ldp?module=openconfig-mpls-ldp&amp;revision=2015-11-05</capability>
  <capability>http://openconfig.net/yang/rsvp?module=openconfig-mpls-rsvp&amp;revision=2015-11-05</capability>
  <capability>http://openconfig.net/yang/sr?module=openconfig-mpls-sr&amp;revision=2015-11-05</capability>
  <capability>http://openconfig.net/yang/mpls-types?module=openconfig-mpls-types&amp;revision=2015-11-05</capability>
  <capability>http://openconfig.net/yang/mpls?module=openconfig-mpls&amp;revision=2015-11-05&amp;deviation=cisco-xr-openconfig-mpls-deviations</capability>
  <capability>http://openconfig.net/yang/policy-types?module=openconfig-policy-types&amp;revision=2015-10-09</capability>
  <capability>http://openconfig.net/yang/routing-policy?module=openconfig-routing-policy&amp;revision=2015-10-09&amp;deviation=cisco-xr-routing-policy-deviations</capability>
  <capability>http://openconfig.net/yang/telemetry?module=openconfig-telemetry&amp;revision=2016-02-04&amp;deviation=cisco-xr-openconfig-telemetry-deviations</capability>
  <capability>http://openconfig.net/yang/openconfig-types?module=openconfig-types&amp;revision=2015-10-09</capability>
  <capability>http://openconfig.net/yang/vlan?module=openconfig-vlan&amp;revision=2015-10-09&amp;deviation=cisco-xr-openconfig-vlan-deviations</capability>
 </capabilities>
 <session-id>1743594516</session-id>
</hello>
]]>]]>

 

I’ve reduced the output only to filter supported OpenConfig modules, so that I can find, which modules I should use in automation scripts using CLI or Ansible.

From this time, OpenConfig over NETCONF is ready to rock on Cisco IOS XR.

#2. Cisco IOS XR. Get the interface configuration using OpenConfig

Here we start with basic configuration on Cisco IOS XR to create one sub interface and loopback interface to get understanding on how would it look like on OpenConfig:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RP/0/0/CPU0:XR4(config)#show conf
Building configuration...
!! IOS XR Configuration 6.1.2
interface Loopback0
 ipv4 address 10.0.0.44 255.255.255.255
 ipv6 address fc00::10:0:0:44/128
!
interface GigabitEthernet0/0/0/0
 no shutdown
!
interface GigabitEthernet0/0/0/0.34
 ipv4 address 10.33.44.44 255.255.255.0
 ipv6 address fe80::44 link-local
 ipv6 address fc00::10:33:44:44/112
 encapsulation dot1q 34
!
end

 

After we have implemented this configuration, we briefly check, what do we have on Cisco IOS XR router XR4 configured:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
RP/0/0/CPU0:XR4#show ipv4 int br
Interface                      IP-Address      Status          Protocol Vrf-Name
Loopback0                      10.0.0.44       Up              Up       default
MgmtEth0/0/CPU0/0              unassigned      Shutdown        Down     default
GigabitEthernet0/0/0/0         unassigned      Up              Up       default
GigabitEthernet0/0/0/0.34      10.33.44.44     Up              Up       default
GigabitEthernet0/0/0/0.999     192.168.1.112   Up              Up       MGMT
!
!
RP/0/0/CPU0:XR4#show ipv6 int br
Loopback0              [Up/Up]
    fe80::7965:62ff:fe58:f8ec
    fc00::10:0:0:44
MgmtEth0/0/CPU0/0      [Shutdown/Down]
    unassigned
GigabitEthernet0/0/0/0 [Up/Up]
    unassigned
GigabitEthernet0/0/0/0.12 [Up/Up]
    fe80::44
    fc00::10:33:44:44

 

Now, we see in the NETCONF session, what is configured in OpenConfig YANG model. To do this we send RPC request with “get-config” instruction through the opened NETCONF over SSH session:

1
2
3
4
5
6
7
8
9
10
11
12
13
#252
<?xml version="1.0" encoding="utf-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="202">
<get-config>
<source>
<running/>
</source>
<filter>
<interfaces xmlns="http://openconfig.net/yang/interfaces"/>
</filter>
</get-config>
</rpc>
##

 

As response we get extensive RPC reply:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#3800
<?xml version="1.0"?>
<rpc-reply message-id="202" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <data>
  <interfaces xmlns="http://openconfig.net/yang/interfaces">
   <interface>
    <name>Loopback0</name>
    <config>
     <name>Loopback0</name>
     <type xmlns:idx="urn:ietf:params:xml:ns:yang:iana-if-type">idx:softwareLoopback</type>
     <enabled>true</enabled>
    </config>
    <subinterfaces>
     <subinterface>
      <index>0</index>
      <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
       <address>
        <ip>10.0.0.44</ip>
        <config>
         <ip>10.0.0.44</ip>
         <prefix-length>32</prefix-length>
        </config>
       </address>
      </ipv4>
      <ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
       <address>
        <ip xmlns="http://openconfig.net/yang/interfaces">fc00::10:0:0:44</ip>
        <config>
         <ip>fc00::10:0:0:44</ip>
         <prefix-length>128</prefix-length>
        </config>
       </address>
      </ipv6>
     </subinterface>
    </subinterfaces>
   </interface>
   <interface>
    <name>MgmtEth0/0/CPU0/0</name>
    <config>
     <name>MgmtEth0/0/CPU0/0</name>
     <type xmlns:idx="urn:ietf:params:xml:ns:yang:iana-if-type">idx:ethernetCsmacd</type>
     <enabled>false</enabled>
    </config>
    <ethernet xmlns="http://openconfig.net/yang/interfaces/ethernet">
     <config>
      <auto-negotiate>false</auto-negotiate>
     </config>
    </ethernet>
   </interface>
   <interface>
    <name>GigabitEthernet0/0/0/0</name>
    <config>
     <name>GigabitEthernet0/0/0/0</name>
     <type xmlns:idx="urn:ietf:params:xml:ns:yang:iana-if-type">idx:ethernetCsmacd</type>
     <enabled>true</enabled>
    </config>
    <ethernet xmlns="http://openconfig.net/yang/interfaces/ethernet">
     <config>
      <auto-negotiate>false</auto-negotiate>
     </config>
    </ethernet>
    <hold-time>
     <config>
      <up>0</up>
      <down>0</down>
     </config>
     <state>
      <up>0</up>
      <down>0</down>
     </state>
    </hold-time>
    <subinterfaces>
     <subinterface>
      <index>34</index>
      <config>
       <index>34</index>
       <name>GigabitEthernet0/0/0/0.34</name>
       <enabled>true</enabled>
      </config>
      <ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
       <config>
        <enabled>false</enabled>
       </config>
       <address>
        <ip xmlns="http://openconfig.net/yang/interfaces">fc00::10:33:44:44</ip>
        <config>
         <ip>fc00::10:33:44:44</ip>
         <prefix-length>112</prefix-length>
        </config>
       </address>
      </ipv6>
      <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
       <address>
        <ip>10.33.44.44</ip>
        <config>
         <ip>10.33.44.44</ip>
         <prefix-length>24</prefix-length>
        </config>
       </address>
      </ipv4>
      <vlan xmlns="http://openconfig.net/yang/vlan">
       <config>
        <vlan-id>34</vlan-id>
       </config>
      </vlan>
     </subinterface>
     <subinterface>
      <index>999</index>
      <config>
       <index>999</index>
       <name>GigabitEthernet0/0/0/0.999</name>
       <enabled>true</enabled>
      </config>
      <ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
       <config>
        <enabled>false</enabled>
       </config>
      </ipv6>
      <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
       <address>
        <ip>192.168.1.112</ip>
        <config>
         <ip>192.168.1.112</ip>
         <prefix-length>24</prefix-length>
        </config>
       </address>
      </ipv4>
      <vlan xmlns="http://openconfig.net/yang/vlan">
       <config>
        <vlan-id>999</vlan-id>
       </config>
      </vlan>
     </subinterface>
    </subinterfaces>
   </interface>
  </interfaces>
 </data>
</rpc-reply>
##

 

Remember, we have explained the framing of the message previously

In this RPC reply we see all the parameters, which is related to the interfaces we have created including management interface, which is related to another VRF though.

#3. Cisco IOS XR. Edit the interface configuration using OpenConfig

Now it’s time to create our own sub-interface and loopback interface in order to understand, if we understand this OpenConfig YANG data model for interface correct. We will create the “Loopback 1” with another IP address and new sub-interface ”GigabitEthernet0/0/0/0.13” using “edit-config” message in OpenConfg format:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#2111
<?xml version="1.0" encoding="utf-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="100">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="http://openconfig.net/yang/interfaces">
<interface>
<name>Loopback1</name>
<config>
<name>Loopback1</name>
<type xmlns:idx="urn:ietf:params:xml:ns:yang:iana-if-type">idx:softwareLoopback</type>
<enabled>true</enabled>
</config>
<subinterfaces>
<subinterface>
<index>0</index>
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
<address>
<ip>10.0.1.44</ip>
<config>
<ip>10.0.1.44</ip>
<prefix-length>32</prefix-length>
</config>
</address>
</ipv4>
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
<address>
<ip xmlns="http://openconfig.net/yang/interfaces">fc00::10:0:1:44</ip>
<config>
<ip>fc00::10:0:1:44</ip>
<prefix-length>128</prefix-length>
</config>
</address>
</ipv6>
</subinterface>
</subinterfaces>
</interface>
<interface>
<name>GigabitEthernet0/0/0/0</name>
<config>
<name>GigabitEthernet0/0/0/0</name>
<type xmlns:idx="urn:ietf:params:xml:ns:yang:iana-if-type">idx:ethernetCsmacd</type>
<enabled>true</enabled>
</config>
<ethernet xmlns="http://openconfig.net/yang/interfaces/ethernet">
<config>
<auto-negotiate>false</auto-negotiate>
</config>
</ethernet>
<subinterfaces>
<subinterface>
<index>14</index>
<config>
<index>14</index>
<name>GigabitEthernet0/0/0/0.14</name>
<enabled>true</enabled>
</config>
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
<config>
<enabled>false</enabled>
</config>
<address>
<ip xmlns="http://openconfig.net/yang/interfaces">fc00::10:11:44:44</ip>
<config>
<ip>fc00::10:11:44:44</ip>
<prefix-length>112</prefix-length>
</config>
</address>
</ipv6>
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
<address>
<ip>10.11.44.44</ip>
<config>
<ip>10.11.44.44</ip>
<prefix-length>24</prefix-length>
</config>
</address>
</ipv4>
<vlan xmlns="http://openconfig.net/yang/vlan">
<config>
<vlan-id>14</vlan-id>
</config>
</vlan>
</subinterface>
</subinterfaces>
</interface>
</interfaces>
</config>
</edit-config>
</rpc>
##

 

If everything was entered correctly, we will get corresponding “OK”:

1
2
3
4
5
6
#119
<?xml version="1.0"?>
<rpc-reply message-id="100" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <ok/>
</rpc-reply>
##

 

Don’t forget, we deal with Cisco IOS XR, so we need to commit configuration using corresponding “commit” message:

1
2
3
4
5
6
#126
<?xml version="1.0" encoding="UTF-8"?>
<rpc message-id="102" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<commit/>
</rpc>
##

 

And we receive OK again:

1
2
3
4
5
6
#119
<?xml version="1.0"?>
<rpc-reply message-id="100" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <ok/>
</rpc-reply>
##

 

So far the trace looks nice, that’s why we are checking the output of “show interface” at Cisco IOS XR both for IPv4 and IPv6:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
RP/0/0/CPU0:XR4#show ipv4 int br
Interface                      IP-Address      Status          Protocol Vrf-Name
Loopback0                      10.0.0.44       Up              Up       default
Loopback1                      10.0.1.44       Up              Down     default
MgmtEth0/0/CPU0/0              unassigned      Shutdown        Down     default
GigabitEthernet0/0/0/0         unassigned      Up              Up       default
GigabitEthernet0/0/0/0.14      10.11.44.44     Up              Up       default
GigabitEthernet0/0/0/0.34      10.33.44.44     Up              Up       default
GigabitEthernet0/0/0/0.999     192.168.1.112   Up              Up       MGMT
!
!
RP/0/0/CPU0:XR4#show ipv6 int br
Loopback0              [Up/Up]
    fe80::7965:62ff:fe58:f8ec
    fc00::10:0:0:44
Loopback1              [Up/Up]
    fe80::7965:62ff:fe58:f8ec
    fc00::10:0:1:44
MgmtEth0/0/CPU0/0      [Shutdown/Down]
    unassigned
GigabitEthernet0/0/0/0 [Up/Up]
    unassigned
GigabitEthernet0/0/0/0.14 [Up/Up]
    fe80::250:56ff:fe34:7146
    fc00::10:11:44:44
GigabitEthernet0/0/0/0.34 [Up/Up]
    fe80::44
    fc00::10:33:44:44

 

Both newly created interfaces are up and running so it means that our OpenConfig understanding is correct. Let’s move further to get working Ansible playbook for interface configuration.

#4. Cisco IOS XR. Ansible for OpenConfig with Cisco

Based on the manually creation of NETCONF “edit-config” requests using OpenConfig YANG data model, we’ll create Ansible playbook to make configuration of interfaces using this OpenConfig YANG model.

OpenConfig is claimed to be vendor-agnostic, so I hope that I will need to create the script only once and all the vendors will be managed using it. Nevertheless, I will create some roles in Ansible so that it is easier to manage deviations per vendor if any arise. The structure of Ansible playbooks and roles is similar to what we did recently for Arista automation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
+--ansible
   +--128_lab.yml
   +--group_vars
   |  +--arista
   |  |  +--arista_host.yml
   |  +--cisco
   |  |  +--cisco_host.yml
   |  +--nokia
   |     +--nokia_host.yml
   +--roles
      +--arista
      |  +--128_lab
      |     +--tasks
      |     |  +--main.yml
      |     +--templates
      |     |  +--interfaces.j2
      |     +--vars
      |        +--oc_vEOS2.yml
      +--cisco
      |  +--128_lab
      |     +--tasks
      |     |  +--main.yml
      |     +--templates
      |     |  +--interfaces.j2
      |     +--vars
      |        +--oc_vEOS2.yml
      +--nokia
         +--128_lab
            +--tasks
            |  +--main.yml
            +--templates
            |  +--interfaces.j2
            |  +--network_instance_interfaces.j2
            +--vars
               +--oc_vEOS2.yml

 

Here is connectivity parameters:

1
2
3
4
5
6
$ cat group_vars/cisco/cisco_host.yml
---
ansible_network_os
: iosxr
ansible_user
: cisco
ansible_pass
: cisco
...

 

The structure of the variables follows the OpenConfig YANG data model.

There is single change: there is no possibility to have variable name, which contains symbol “-“, that’s why it’s replaced with “_”.

Here is the example of variables for spine switch XR3 based on Cisco IOS XR:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
.$ cat roles/cisco/128_lab/vars/oc_XR3.yml
---
node
:
    hostname
: XR3
    interfaces
:
        - name
: Loopback0
         type
: softwareLoopback
          enabled
: true
          subinterfaces
:
              - index
: 0
                ipv4
:
                    address
:
                        - ip
: 10.0.0.33
                          prefix_length
: 32
                ipv6
:
                    address
:
                        - ip
: fc00::10:0:0:33
                          prefix_length
: 128
        - name
: GigabitEthernet0/0/0/0
          type
: ethernetCsmacd
          enabled
: true
          ethernet
:
              auto_negotiate
: false
         subinterfaces
:
              - index
: 13
                enabled
: true
                vlan
:
                    vlan_id
: 13
                ipv4
:
                    address
:
                        - ip
: 10.11.33.33
                          prefix_length
: 24
                ipv6
:
                    address
:
                        - ip
: fc00::10:11:33:33
                          prefix_length
: 112
              - index
: 23
                enabled
: true
                vlan
:
                    vlan_id
: 23
                ipv4
:
                    address
:
                        - ip
: 10.22.33.33
                          prefix_length
: 24
                ipv6
:
                    address
:
                        - ip
: fc00::10:22:33:33
                          prefix_length
: 112
...

 

If you look carefully, you will see that this files exactly follows OpenConfig YANG data model we have seen previously in “get-config” RPC reply over NETCONF.

In the same way we create file with variable for XR4. It isn’t shown here, but will be listed in files as usually.

The next step in our Ansible-based automation is to create proper jinja2 template so that config is created automatically. As you see in variables, we are using dictionaries a lot to simplify template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
$ cat roles/cisco/128_lab/templates/interfaces.j2
<config>
  <interfaces xmlns="http://openconfig.net/yang/interfaces">
{% for iface in node.interfaces %}
    <interface>
      <name>{{ iface.name }}</name>
      <config>
        <name>{{ iface.name }}</name>
        <type xmlns:idx="urn:ietf:params:xml:ns:yang:iana-if-type">idx:{{ iface.type }}</type>
        <enabled>{{ iface.enabled|lower }}</enabled>
      </config>
{% if iface.subinterfaces is defined %}
      <subinterfaces>
{% for siface in iface.subinterfaces %}
        <subinterface>
          <index>{{ siface.index }}</index>
{% if siface.index != 0 %}
          <config>
            <index>{{ siface.index }}</index>
            <name>{{ iface.name }}.{{ siface.index }}</name>
            <enabled>{{ siface.enabled|lower }}</enabled>
          </config>
{% endif %}
{% if siface.ipv4 is defined %}
          <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
{% for addr in siface.ipv4.address %}
            <address>
              <ip>{{ addr.ip }}</ip>
              <config>
                <ip>{{ addr.ip }}</ip>
                <prefix-length>{{ addr.prefix_length }}</prefix-length>
              </config>
            </address>
{% endfor %}
          </ipv4>
{% endif %}
{% if siface.ipv6 is defined %}
          <ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
{% for addr in siface.ipv6.address %}
            <address>
              <ip>{{ addr.ip }}</ip>
              <config>
                <ip>{{ addr.ip }}</ip>
                <prefix-length>{{ addr.prefix_length }}</prefix-length>
              </config>
            </address>
{% endfor %}
          </ipv6>
{% endif %}
{% if siface.vlan is defined %}
          <vlan xmlns="http://openconfig.net/yang/vlan">
            <config>
              <vlan-id>{{ siface.vlan.vlan_id }}</vlan-id>
            </config>
          </vlan>
{% endif %}
        </subinterface>
{% endfor %}
      </subinterfaces>
{% endif %}
    </interface>
{% endfor %}
  </interfaces>
</config>

 

The last but not least point is to create the file with tasks. To be honest, I think, it’s the easiest step as it’s very straightforward:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cat roles/cisco/128_lab/tasks/main.yml
---
- name
: IMPORTING VARS
  include_vars
:
      file
: oc_{{ inventory_hostname }}.yml

- name
: CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT
  template
:
      src
: interfaces.j2
      dest
: /tmp/oc_{{ inventory_hostname }}.conf
      mode
: 0755

- name
: OPENCOFNIG // CONFIGURING INTERFACES
  netconf_config
:
      host
: "{{ inventory_hostname }}"
      username
: "{{ ansible_user }}"
      password
: "{{ ansible_pass }}"
      hostkey_verify
: false
      look_for_keys
: false
      xml
: "{{ lookup ('template', 'interfaces.j2') }}"
...

 

The second task in play isn’t necessary and is used primary for debugging in order we can see how exactly the ”config” part of NETCONF “edit-config” message looks like.

Well, there is one more thing we need to do. We need to create general Ansible playbook, which will call roles:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.$ cat 128_lab.yml
---
- hosts
: cisco
  connection
: local
  tags
: cisco
  roles
:
    - { role
: cisco/128_lab, var_vendor: cisco }

- hosts
: nokia
  connection
: local
  tags
: nokia
  roles
:
    - { role
: nokia/128_lab, var_vendor: nokia }

- hosts
: arista
  connection
: local
  tags
: arista
  roles
:
    - { role
: arista/128_lab, var_vendor: arista }
...

 

Up to now we have created everything necessary to automate deployment of spine switches based on Cisco IOS XR.

Before we try it, I will remove all created interfaces and will leave only initial config on Cisco IOS XR based spines XR3 and XR4:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ ansible-playbook 128_lab.yml --limit=cisco
 [WARNING] Ansible is in a world writable directory (/home/aaa/ansible), ignoring it as an ansible.cfg source.

PLAY [cisco] **********************************************************************************************

TASK [Gathering Facts] ************************************************************************************
ok: [XR3]
ok: [XR4]

TASK [cisco/128_lab : IMPORTING VARS] *********************************************************************
ok: [XR3]
ok: [XR4]

TASK [cisco/128_lab : CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT] **************
ok: [XR4]
ok: [XR3]

TASK [cisco/128_lab : OPENCOFNIG // CONFIGURING INTERFACES] ***********************************************
changed: [XR4]
changed: [XR3]

PLAY [nokia] **********************************************************************************************
skipping: no hosts matched

PLAY [arista] *********************************************************************************************
skipping: no hosts matched

PLAY RECAP ************************************************************************************************
XR3                        : ok=4    changed=1    unreachable=0    failed=0  
XR4                        : ok=4    changed=1    unreachable=0    failed=0

 

Looks good. Let’s double check on CLI:

1
2
3
4
5
6
7
8
9
10
RP/0/0/CPU0:XR3#show ipv4 int br
Sat Jul 21 18:57:58.109 UTC

Interface                      IP-Address      Status          Protocol Vrf-Name
Loopback0                      10.0.0.33       Up              Up       default
MgmtEth0/0/CPU0/0              unassigned      Shutdown        Down     default
GigabitEthernet0/0/0/0         unassigned      Up              Up       default
GigabitEthernet0/0/0/0.13      10.11.33.33     Up              Up       default
GigabitEthernet0/0/0/0.23      10.22.33.33     Up              Up       default
GigabitEthernet0/0/0/0.999     192.168.1.111   Up              Up       MGMT

 

Cisco is done. So, we have deployed configuration of the interfaces using OpenConfig YANG data model over NETCONF transport. Let’s check how other vendors behave. Hypothetically there should be no difference. Do you believe? 🙂

OpenConfig and Nokia SR OS

Nokia has introduced support of OpenConfig YANG data models only in the latest version of its SR OS, which is Nokia (Alcatel-Lucent) SR OS 16.0.R1 for the time of the writing. What is interesting, Nokia VSR doesn’t support it yet, but rather physical devices (like Nokia SR 7750/7950 and so on) or Nokia vSIM, which emulates HW of real devices. That’s why we change the initial XML file, we have used all time long (link). The change impacts only one line, which is probably the most important:

1
2
$ sudo cat /var/lib/libvirt/images/sr16-oc.xml | grep "product"
<entry name='product'>TIMOS:address=192.168.1.166/24@active static-route=192.168.0.0/16@192.168.1.1 license-file=ftp://aaa:aaa@192.168.1.1/sros16.lic slot=A chassis=SR-1 card=iom-1 mda/1=me6-100gb-qsfp28</entry>

 

Usage of this line in initial XML descriptor of VM for KVM assures we launch vSIM emulating this particular HW instead of VSR.

When we launch VM and provision the card and MDA, we should see the following outputs, if everything is done correctly. The chassis is SR-1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[]
A:admin@SR6# show chassis  
===============================================================================
System Information
===============================================================================
  Name                              : SR6
  Type                              : 7750 SR-1
  Chassis Topology                  : Standalone
  Location                          : (Not Specified)
  Coordinates                       : (Not Specified)
  CLLI code                         :          
  Number of slots                   : 2
  Oper number of slots              : 2
  Num of faceplate ports/connectors : 6
  Num of physical ports             : 4
  Critical LED state                : Off
  Major LED state                   : Red
  Minor LED state                   : Off
  Over Temperature state            : OK
  Base MAC address                  : 02:a6:ff:00:00:00
  FP Generations                    : FP4
  System Profile                    : profile-a
===============================================================================
Chassis Summary
===============================================================================
Chassis   Role                Status
-------------------------------------------------------------------------------
1         Standalone          up
===============================================================================

 

The following card is installed in the cassis:

1
2
3
4
5
6
7
8
9
10
11
[]
A:admin@SR6# show card
===============================================================================
Card Summary
===============================================================================
Slot      Provisioned Type                         Admin Operational   Comments
              Equipped Type (if different)         State State        
-------------------------------------------------------------------------------
1         iom-1:he                                 up    up            
A         cpm-1                                    up    up/active    
===============================================================================

 

And the following MDA is there:

1
2
3
4
5
6
7
8
9
10
[]
A:admin@SR6# show mda
===============================================================================
MDA Summary
===============================================================================
Slot  Mda   Provisioned Type                            Admin     Operational
                Equipped Type (if different)            State     State
-------------------------------------------------------------------------------
1     1     me6-100gb-qsfp28                            up        up
===============================================================================

 

Such Nokia (Alcatel-Lucent) vSIM supports OpenConfig, so we start with the core topic of the article.

Information about MD-CLI, how to configure and to use it you can find in separate article.

#1. Nokia SR OS. Enabling OpenConfig

We have explained previously how to enable NETCONF in Nokia (Alcatel-Lucent) VSR / SR 7750, but there are some changes in SR OS 16.0.R1, so we’ll cover the full configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[]
A:admin@SR6# admin show configuration
# TiMOS-B-16.0.R1 both/x86_64 Nokia 7750 SR Copyright (c) 2000-2018 Nokia.
configure {
    system {
        name "SR6"
        management-interface {
            netconf {
                admin-state enable
            }
            yang-modules {
                base-r13-modules true
                nokia-modules true
                openconfig-modules true
            }
        }
        security {
            aaa {
                local-profiles {
                    profile "administrative" {
                        default-action permit-all
                        netconf {
                            base-op-authorization {
                                kill-session true
                                lock true
                            }
                        }
                    }
                }
            }
            user-params {
                local-user {
                    user "admin" {
                        password "$2y$10$TQrZlpBDra86.qoexZUzQeBXDY1FcdDhGWdD9lLxMuFyPVSm0OGy6"
                        access {
                            console true
                            netconf true
                        }
                        console {
                            member ["administrative"]
                        }
                    }
                }
            }
        }
    }
}

 

Only configuration related to NETCONF and OpenConfig is shown.

Comparing to previous example, here we have 2 major differences:

  • It’s done in MD-CLI mode.
  • Set of YANG modules are enabled explicitly.

So we need explicitly enable OpenConfig YANG model in order we can use it. Let’s connect to our Nokia SROS based leaf SR6:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
$ ssh admin@SR6 -p 830 -s netconf

admin@sr6's password:
<?xml version="1.0" encoding="UTF-8"?>
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <capabilities>
        <capability>urn:ietf:params:netconf:base:1.0</capability>
        <capability>urn:ietf:params:netconf:base:1.1</capability>
        <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>
        <capability>urn:ietf:params:netconf:capability:notification:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:interleave:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:validate:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:validate:1.1</capability>
        <capability>urn:ietf:params:netconf:capability:startup:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:url:1.0?scheme=ftp,tftp,file</capability>
        <capability>urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&amp;also-supported=report-all</capability>
        ...
        <capability>http://openconfig.net/yang/acl?module=openconfig-acl&amp;revision=2016-01-22</capability>
        <capability>http://openconfig.net/yang/bgp?module=openconfig-bgp&amp;revision=2016-03-31</capability>
        <capability>http://openconfig.net/yang/bgp-policy?module=openconfig-bgp-policy&amp;revision=2016-06-21</capability>
        <capability>http://openconfig.net/yang/bgp-types?module=openconfig-bgp-types&amp;revision=2016-06-21</capability>
        <capability>http://openconfig.net/yang/openconfig-ext?module=openconfig-extensions&amp;revision=2015-10-05</capability>
        <capability>http://openconfig.net/yang/interfaces/aggregate?module=openconfig-if-aggregate&amp;revision=2016-12-22</capability>
        <capability>http://openconfig.net/yang/interfaces/ethernet?module=openconfig-if-ethernet&amp;revision=2016-12-22</capability>
        <capability>http://openconfig.net/yang/interfaces/ip?module=openconfig-if-ip&amp;revision=2016-12-22</capability>
        <capability>http://openconfig.net/yang/interfaces/ip-ext?module=openconfig-if-ip-ext&amp;revision=2016-12-22</capability>
        <capability>http://openconfig.net/yang/types/inet?module=openconfig-inet-types&amp;revision=2017-01-26</capability>
        <capability>http://openconfig.net/yang/interfaces?module=openconfig-interfaces&amp;revision=2016-12-22</capability>
        <capability>http://openconfig.net/yang/openconfig-isis?module=openconfig-isis&amp;revision=2016-10-18</capability>
        <capability>http://openconfig.net/yang/isis-lsdb-types?module=openconfig-isis-lsdb-types&amp;revision=2016-10-18</capability>
        <capability>http://openconfig.net/yang/openconfig-isis-policy?module=openconfig-isis-policy&amp;revision=2016-10-18</capability>
        <capability>http://openconfig.net/yang/isis-types?module=openconfig-isis-types&amp;revision=2016-10-18</capability>
        <capability>http://openconfig.net/yang/lacp?module=openconfig-lacp&amp;revision=2016-05-26</capability>
        <capability>http://openconfig.net/yang/lldp?module=openconfig-lldp&amp;revision=2016-05-16</capability>
        <capability>http://openconfig.net/yang/lldp/types?module=openconfig-lldp-types&amp;revision=2016-05-16</capability>
        <capability>http://openconfig.net/yang/local-routing?module=openconfig-local-routing&amp;revision=2016-05-11</capability>
        <capability>http://openconfig.net/yang/mpls?module=openconfig-mpls&amp;revision=2016-08-08</capability>
        <capability>http://openconfig.net/yang/rsvp?module=openconfig-mpls-rsvp&amp;revision=2016-08-08</capability>
        <capability>http://openconfig.net/yang/mpls-sr?module=openconfig-mpls-sr&amp;revision=2016-08-08</capability>
        <capability>http://openconfig.net/yang/mpls-types?module=openconfig-mpls-types&amp;revision=2016-08-08</capability>
        <capability>http://openconfig.net/yang/network-instance?module=openconfig-network-instance&amp;revision=2015-10-18</capability>
        <capability>http://openconfig.net/yang/network-instance-types?module=openconfig-network-instance-types&amp;revision=2015-10-18</capability>
        <capability>http://openconfig.net/yang/header-fields?module=openconfig-packet-match&amp;revision=2016-04-27</capability>
        <capability>http://openconfig.net/yang/packet-match-types?module=openconfig-packet-match-types&amp;revision=2016-04-27</capability>
        <capability>http://openconfig.net/yang/policy-types?module=openconfig-policy-types&amp;revision=2016-05-12</capability>
        <capability>http://openconfig.net/yang/relay-agent?module=openconfig-relay-agent&amp;revision=2016-05-16</capability>
        <capability>http://openconfig.net/yang/routing-policy?module=openconfig-routing-policy&amp;revision=2016-05-12</capability>
        <capability>http://openconfig.net/yang/rsvp-sr-ext?module=openconfig-rsvp-sr-ext&amp;revision=2017-03-06</capability>
        <capability>http://openconfig.net/yang/openconfig-types?module=openconfig-types&amp;revision=2016-05-31</capability>
        <capability>http://openconfig.net/yang/vlan?module=openconfig-vlan&amp;revision=2016-05-26</capability>
        <capability>http://openconfig.net/yang/vlan-types?module=openconfig-vlan-types&amp;revision=2016-05-26</capability>
        <capability>http://openconfig.net/yang/types/yang?module=openconfig-yang-types&amp;revision=2017-01-26</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_acl_deviations?module=nokia-sr-openconfig-acl-deviations&amp;revision=2016-01-22</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_bgp_policy_deviations?module=nokia-sr-openconfig-bgp-policy-deviations&amp;revision=2016-06-21</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_bgp_deviations?module=nokia-sr-openconfig-bgp-deviations&amp;revision=2016-03-31</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_if_aggregate_deviations?module=nokia-sr-openconfig-if-aggregate-deviations&amp;revision=2016-12-22</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_if_ethernet_deviations?module=nokia-sr-openconfig-if-ethernet-deviations&amp;revision=2016-12-22</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_if_ip_ext_deviations?module=nokia-sr-openconfig-if-ip-ext-deviations&amp;revision=2016-12-22</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_if_ip_deviations?module=nokia-sr-openconfig-if-ip-deviations&amp;revision=2016-12-22</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_interfaces_deviations?module=nokia-sr-openconfig-interfaces-deviations&amp;revision=2016-12-22</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_isis_policy_deviations?module=nokia-sr-openconfig-isis-policy-deviations&amp;revision=2016-10-18</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_lldp_deviations?module=nokia-sr-openconfig-lldp-deviations&amp;revision=2016-05-16</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_mpls_deviations?module=nokia-sr-openconfig-mpls-deviations&amp;revision=2016-08-08</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_network_instance_deviations?module=nokia-sr-openconfig-network-instance-deviations&amp;revision=2015-10-18</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_relay_agent_deviations?module=nokia-sr-openconfig-relay-agent-deviations&amp;revision=2016-05-16</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_routing_policy_deviations?module=nokia-sr-openconfig-routing-policy-deviations&amp;revision=2016-05-12</capability>
        <capability>urn:nokia.com:sros:ns:yang:sr:openconfig_vlan_deviations?module=nokia-sr-openconfig-vlan-deviations&amp;revision=2016-05-26</capability>
    </capabilities>
    <session-id>8</session-id>
</hello>
]]>]]>

 

As I’ve enabled all YANG modules, the output was very long, that’s why only OpenConfig related capabilities are shown.

#2. Nokia SR OS. Get the interface configuration using OpenConfig

Following the same approach we’ve done for Cisco, we’ll configure some interfaces in OpenConfig model.

In MD-CLI Nokia SR OS has dedicated context for OpenConfig configuration.

To make story a shorter, I will show the configuration of one interface:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(gl)[configure openconfig]
A:admin@SR6# info    
    interfaces {
        interface "1/1/c1/1" {
            config {
                name "1/1/c1/1"
                type ethernetCsmacd
                enabled true
            }
            subinterfaces {
                subinterface 13 {
                    config {
                        index 13
                        enabled true
                    }
                    ipv4 {
                        addresses {
                            address 10.11.33.11 {
                                config {
                                    ip 10.11.33.11
                                    prefix-length 24
                                }
                            }
                        }
                    }
                    ipv6 {
                        addresses {
                            address fc00::10:11:33:11 {
                                config {
                                    ip fc00::10:11:33:11
                                    prefix-length 112
                                }
                            }
                        }
                    }
                    vlan {
                        config {
                            vlan-id "13"
                        }
                    }
                }
            }
        }
    }
    network-instances {
        network-instance "Base" {
            config {
                name "Base"
                type DEFAULT_INSTANCE
            }
            interfaces {
                interface "1/1/c1/1.13" {
                    config {
                        id "1/1/c1/1.13"
                        interface "1/1/c1/1"
                        subinterface 13
                        associated-address-families [IPV4 IPV6]
                    }
                }
            }
        }
    }

 

As you see, in Nokia we need to define interfaces in two contexts: interfaces and network-instances, what is different to Cisco implementation. The should be or will be released some documentation for OpenConfig in Nokia (Alcatel-Lucent) SR OS, but as usually I got to it just trying to bring it working using “plug and pray” approach.

That’s how the interfaces is shown in CLI:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[]
A:admin@SR6# show router interface
===============================================================================
Interface Table (Router: Base)
===============================================================================
Interface-Name                   Adm       Opr(v4/v6)  Mode    Port/SapId
   IP-Address                                                  PfxState
-------------------------------------------------------------------------------
oc_1/1/c1/1_13                   Up        Up/Up       Network 1/1/c1/1:13
   10.11.33.11/24                                              n/a
   fc00::10:11:33:11/112                                       PREFERRED
   fe80::f8ac:a6ff:fe16:202/64                                 PREFERRED
-------------------------------------------------------------------------------
Interfaces : 1
===============================================================================

 

As you might spot, we don’t define the name in this configuration. It’s created automatically based on the name of port and subinterface’s index. Now we check how that looks in NETCONF:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?xml version="1.0" encoding="utf-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="202">
  <get-config>
    <source>
      <running/>
    </source>
    <filter>
      <interfaces xmlns="http://openconfig.net/yang/interfaces"/>
    </filter>
  </get-config>
</rpc>
]]>]]>


<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="202" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <interfaces xmlns="http://openconfig.net/yang/interfaces">
            <interface>
                <name>1/1/c1/1</name>
                <config>
                    <name>1/1/c1/1</name>
                    <type>ethernetCsmacd</type>
                    <enabled>true</enabled>
                </config>
                <subinterfaces>
                    <subinterface>
                        <index>13</index>
                        <config>
                            <index>13</index>
                            <enabled>true</enabled>
                        </config>
                        <ipv4>
                            <addresses>
                                <address>
                                    <ip>10.11.33.11</ip>
                                    <config>
                                        <ip>10.11.33.11</ip>
                                        <prefix-length>24</prefix-length>
                                    </config>
                                </address>
                            </addresses>
                        </ipv4>
                        <ipv6>
                            <addresses>
                                <address>
                                    <ip>fc00::10:11:33:11</ip>
                                    <config>
                                        <ip>fc00::10:11:33:11</ip>
                                        <prefix-length>112</prefix-length>
                                    </config>
                                </address>
                            </addresses>
                        </ipv6>
                        <vlan>
                            <config>
                                <vlan-id>13</vlan-id>
                            </config>
                        </vlan>
                    </subinterface>
                </subinterfaces>
            </interface>
        </interfaces>
    </data>
</rpc-reply>
]]>]]>


<?xml version="1.0" encoding="utf-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="202">
  <get-config>
    <source>
      <running/>
    </source>
    <filter>
      <network-instances xmlns="http://openconfig.net/yang/network-instance">
        <network-instance>
          <name>Base</name>
          <interfaces/>
        </network-instance>
      </network-instances>
    </filter>
  </get-config>
</rpc>
]]>]]>


<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="202" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <data>
        <network-instances xmlns="http://openconfig.net/yang/network-instance">
            <network-instance>
                <name>Base</name>
                <interfaces>
                    <interface>
                        <id>1/1/c1/1.13</id>
                        <config>
                            <id>1/1/c1/1.13</id>
                            <interface>1/1/c1/1</interface>
                            <subinterface>13</subinterface>
                            <associated-address-families>IPV4</associated-address-families>
                            <associated-address-families>IPV6</associated-address-families>
                        </config>
                    </interface>
                </interfaces>
            </network-instance>
        </network-instances>
    </data>
</rpc-reply>
]]>]]>

 

The output of “get-config” message looks quite similar to what we have seen in Cisco IOS XR, but for sure it isn’t identical. Even if we omit necessity to created additional network-instance context, we need to tune initial jijna2 template.

That’s what we are going to do.

#3. Nokia SR OS. Edit the interface configuration using OpenConfig

The idea of testing proper “edit-config” messages is explained earlier in Cisco part, so you can follow the logic easily.

We’ll try to create system loopback interface logic, based on the types we can read in OpenConfig YANG models or what we have seen in Cisco part.

Don’t forget to commit changes!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?xml version="1.0" encoding="utf-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
<edit-config>
<target>
<candidate/>
</target>
<config>
  <interfaces xmlns="http://openconfig.net/yang/interfaces">
    <interface>
      <name>system</name>
      <config>
        <name>system</name>
        <type>softwareLoopback</type>
        <enabled>true</enabled>
      </config>
      <subinterfaces>
        <subinterface>
          <index>0</index>
          <ipv4>
           <addresses>
            <address>
              <ip>10.0.0.11</ip>
              <config>
                <ip>10.0.0.11</ip>
                <prefix-length>32</prefix-length>
              </config>
            </address>
           </addresses>
          </ipv4>
          <ipv6>
           <addresses>
            <address>
              <ip>fc00::10:0:0:11</ip>
              <config>
                <ip>fc00::10:0:0:11</ip>
                <prefix-length>128</prefix-length>
              </config>
            </address>
           </addresses>
          </ipv6>
        </subinterface>
      </subinterfaces>
    </interface>
  </interfaces>
</config>
</edit-config>
</rpc>


<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <ok/>
</rpc-reply>
]]>]]>


<?xml version="1.0" encoding="utf-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
<edit-config>
<target>
<candidate/>
</target>
<config>
  <network-instances xmlns="http://openconfig.net/yang/network-instance">
    <network-instance>
      <name>Base</name>
       <config>
         <name>Base</name>
         <type>DEFAULT_INSTANCE</type>
       </config>
       <interfaces>
        <interface>
          <id>system</id>
          <config>
            <id>system</id>
            <interface>system</interface>
            <subinterface>0</subinterface>
            <associated-address-families>IPV4</associated-address-families>
            <associated-address-families>IPV6</associated-address-families>
          </config>
        </interface>
       </interfaces>
    </network-instance>
  </network-instances>
</config>
</edit-config>
</rpc>
]]>]]>


<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <ok/>
</rpc-reply>
]]>]]>


<?xml version="1.0" encoding="UTF-8"?>
<rpc message-id="102" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<commit/>
</rpc>
]]>]]>


<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="102" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <ok/>
</rpc-reply>
]]>]]>

 

After we have sent the proper “edit-config” messages and committed configuration over NETCONF, we can verify, what we see in CLI:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[]
A:admin@SR6# show router interface
===============================================================================
Interface Table (Router: Base)
===============================================================================
Interface-Name                   Adm       Opr(v4/v6)  Mode    Port/SapId
   IP-Address                                                  PfxState
-------------------------------------------------------------------------------
oc_1/1/c1/1_13                   Up        Up/Up       Network 1/1/c1/1:13
   10.11.33.11/24                                              n/a
   fc00::10:11:33:11/112                                       PREFERRED
   fe80::f8ac:a6ff:fe16:202/64                                 PREFERRED
system                           Up        Up/Up       Network system
   10.0.0.11/32                                                n/a
   fc00::10:0:0:11/128                                         PREFERRED
-------------------------------------------------------------------------------
Interfaces : 2
===============================================================================

 

As interfaces is properly reflected, it means that our understanding of OpenConfig YANG in Nokia (Alcate-Lucent) SR OS is correct and we can proceed with Ansible

#4. Nokia SR OS. Ansible for OpenConfig with Cisco

The data structure is fully identical to one we have in case of Cisco. Moreover, we copy already created files for Cisco in Nokia roles:

1
$ cp roles/cisco/128_lab/ roles/nokia/128_lab/

 

This is data structure of Ansible playbook:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
+--ansible
   +--128_lab.yml
   +--group_vars
   |  +--arista
   |  |  +--arista_host.yml
   |  +--cisco
   |  |  +--cisco_host.yml
   |  +--nokia
   |     +--nokia_host.yml
   +--roles
      +--arista
      |  +--128_lab
      |     +--tasks
      |     |  +--main.yml
      |     +--templates
      |     |  +--interfaces.j2
      |     +--vars
      |        +--oc_vEOS2.yml
      +--cisco
      |  +--128_lab
      |     +--tasks
      |     |  +--main.yml
      |     +--templates
      |     |  +--interfaces.j2
      |     +--vars
      |        +--oc_vEOS2.yml
      +--nokia
         +--128_lab
            +--tasks
            |  +--main.yml
            +--templates
            |  +--interfaces.j2
            |  +--network_instance_interfaces.j2
            +--vars
               +--oc_vEOS2.yml

 

Just in the same way as creating Ansible playbook for automating OpenConfig operation with Cisco IOS XR, we start with some authentication data, which will be used:

1
2
3
4
5
6
$ cat group_vars/nokia/nokia_host.yml
---
ansible_network_os
: sros
ansible_user
: admin
ansible_pass
: admin
...

 

Then we go to variable. As you see, there is no changes comparing to variables for Cisco:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
$ cat roles/nokia/128_lab/vars/oc_SR6.yml
---
node
:
    hostname
: SR6
    interfaces
:
        - name
: system
          type
: softwareLoopback
          enabled
: true
          subinterfaces
:
              - index
: 0
               ipv4
:
                    address
:
                        - ip
: 10.0.0.11
                          prefix_length
: 32
                ipv6
:
                    address
:
                        - ip
: fc00::10:0:0:11
                          prefix_length
: 128
        - name
: 1/1/c1/1
          type
: ethernetCsmacd
          enabled
: true
          ethernet
:
              auto_negotiate
: false
          subinterfaces
:
              - index
: 13
                enabled
: true
                vlan
:
                    vlan_id
: 13
                ipv4
:
                    address
:
                        - ip
: 10.11.33.11
                          prefix_length
: 24
                ipv6
:
                    address
:
                        - ip
: fc00::10:11:33:11
                         prefix_length
: 112
              - index
: 14
                enabled
: true
                vlan
:
                    vlan_id
: 14
                ipv4
:
                    address
:
                        - ip
: 10.11.44.11
                          prefix_length
: 24
                ipv6
:
                    address
:
                        - ip
: fc00::10:11:44:11
                          prefix_length
: 112
...

 

To be honest, I find this part particulary important. The data model is the same for all elements, thanks OpenConfig! Only such approach can create truly automation.

The next point in creating proper playbook is tuning the Jinja2 template for interfaces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
$ cat roles/nokia/128_lab/templates/interfaces.j2
<config>
  <interfaces xmlns="http://openconfig.net/yang/interfaces">
{% for iface in node.interfaces %}
    <interface>
      <name>{{ iface.name }}</name>
      <config>
        <name>{{ iface.name }}</name>
{% if ansible_network_os == "iosxr" %}
        <type xmlns:idx="urn:ietf:params:xml:ns:yang:iana-if-type">idx:{{ iface.type }}</type>
{% else %}
        <type>{{ iface.type }}</type>
{% endif %}
        <enabled>{{ iface.enabled|lower }}</enabled>
      </config>
{% if iface.subinterfaces is defined %}
      <subinterfaces>
{% for siface in iface.subinterfaces %}
        <subinterface>
          <index>{{ siface.index }}</index>
{% if siface.index != 0 %}
          <config>
            <index>{{ siface.index }}</index>
{% if ansible_network_os == "iosxr" %}
            <name>{{ iface.name }}.{{ siface.index }}</name>
{% endif %}
            <enabled>{{ siface.enabled|lower }}</enabled>
          </config>
{% endif %}
{% if siface.ipv4 is defined %}
{% if ansible_network_os != "sros" %}
          <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
{% else %}
          <ipv4>
{% endif %}
{% if ansible_network_os != "iosxr" %}
           <addresses>
{% endif %}
{% for addr in siface.ipv4.address %}
            <address>
              <ip>{{ addr.ip }}</ip>
              <config>
                <ip>{{ addr.ip }}</ip>
                <prefix-length>{{ addr.prefix_length }}</prefix-length>
              </config>
            </address>
{% endfor %}
{% if ansible_network_os != "iosxr" %}
           </addresses>
{% endif %}
          </ipv4>
{% endif %}
{% if siface.ipv6 is defined %}
{% if ansible_network_os != "sros" %}
          <ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
{% else %}
          <ipv6>
{% endif %}
{% if ansible_network_os != "iosxr" %}
           <addresses>
{% endif %}
{% for addr in siface.ipv6.address %}
            <address>
              <ip>{{ addr.ip }}</ip>
              <config>
                <ip>{{ addr.ip }}</ip>
                <prefix-length>{{ addr.prefix_length }}</prefix-length>
              </config>
            </address>
{% endfor %}
{% if ansible_network_os != "iosxr" %}
           </addresses>
{% endif %}
          </ipv6>
{% endif %}
{% if siface.vlan is defined %}
{% if ansible_network_os != "sros" %}
          <vlan xmlns="http://openconfig.net/yang/vlan">
{% else %}
          <vlan>
{% endif %}
            <config>
              <vlan-id>{{ siface.vlan.vlan_id }}</vlan-id>
            </config>
          </vlan>
{% endif %}
        </subinterface>
{% endfor %}
      </subinterfaces>
{% endif %}
    </interface>
{% endfor %}
  </interfaces>
</config>

 

It became a bit more complicated comparing to initial one. The complications come from the fact that we need to take into account particular syntax per vendor. For instance, for IP address configuration we put:

  • For Cisco: <ipv4 xmlns=”http://openconfig.net/yang/interfaces/ip”>
  • For Nokia: <ipv4>

Additionally, Nokia put all kind of IP addresses into <addresses> group, whereas there is no such group in Cisco IOS XR.

But again, the syntax is relevant only for Cisco IOS XRv 6.1.2 and Nokia SR OS 16.0.R1. For other versions of NOSes it might changes.

As we have additional configuration in step in Nokia SR OS, we create new template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ cat roles/nokia/128_lab/templates/network_instance_interfaces.j2
<config>
  <network-instances xmlns="http://openconfig.net/yang/network-instance">
    <network-instance>
      <name>Base</name>
      <config>
        <name>Base</name>
        <type>DEFAULT_INSTANCE</type>
      </config>
      <interfaces>
{% for iface in node.interfaces %}
{% for siface in iface.subinterfaces %}
        <interface>
{% if iface.name == "system" %}
          <id>{{ iface.name }}</id>
{% else %}
          <id>{{ iface.name }}.{{ siface.index }}</id>
{% endif %}
          <config>
{% if iface.name == "system" %}
            <id>{{ iface.name }}</id>
{% else %}
            <id>{{ iface.name }}.{{ siface.index }}</id>
{% endif %}
            <interface>{{ iface.name }}</interface>
            <subinterface>{{ siface.index }}</subinterface>
{% if siface.ipv4 is defined %}
            <associated-address-families>IPV4</associated-address-families>
{% endif %}
{% if siface.ipv6 is defined %}
            <associated-address-families>IPV6</associated-address-families>
{% endif %}
          </config>
        </interface>
{% endfor %}
{% endfor %}      
      </interfaces>
    </network-instance>
  </network-instances>
</config>

 

Now we need to extend the Ansible playbook with tasks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ cat roles/nokia/128_lab/tasks/main.yml
---
- name
: IMPORTING VARS
  include_vars
:
      file
: oc_{{ inventory_hostname }}.yml

- name
: CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT I
  template
:
     src
: interfaces.j2
      dest
: /tmp/oc_{{ inventory_hostname }}_if.conf
      mode
: 0755

- name
: OPENCOFNIG // CONFIGURING INTERFACES I
  netconf_config
:
      host
: "{{ inventory_hostname }}"
      username
: "{{ ansible_user }}"
      password
: "{{ ansible_pass }}"
      port
: 830
      hostkey_verify
: false
      look_for_keys
: false
      save
: yes
      xml
: "{{ lookup ('template', 'interfaces.j2') }}"

- name
: CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT II
  template
:
      src
: network_instance_interfaces.j2
      dest
: /tmp/oc_{{ inventory_hostname }}_ni.conf
      mode
: 0755
  when
: ansible_network_os == "sros"

- name
: OPENCOFNIG // CONFIGURING INTERFACES II
  netconf_config
:
      host
: "{{ inventory_hostname }}"
      username
: "{{ ansible_user }}"
      password
: "{{ ansible_pass }}"
      port
: 830
      hostkey_verify
: false
      look_for_keys
: false
      save
: yes
      xml
: "{{ lookup ('template', 'network_instance_interfaces.j2') }}"
  when
: ansible_network_os == "sros"
...

 

If you don’t need to debug the messages, just remove 2nd and 4th task. As you see, we add the condition to check for “ansible_network_os” to play this part of the playbook only for Nokia (Alcatel-Lucent) SR OS. It won’t be played for Cisco IOS XR.

So, automation using Ansible for interfaces configuration in Nokia (Alcatel-Lucent) SR OS using OpenConfig YANG data models through NETCONF is ready. So we can test it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ ansible-playbook 128_lab.yml --limit=nokia
 [WARNING] Ansible is in a world writable directory (/home/aaa/ansible), ignoring it as an ansible.cfg source.

PLAY [cisco] **********************************************************************************************
skipping: no hosts matched

PLAY [nokia] **********************************************************************************************

TASK [Gathering Facts] ************************************************************************************
ok: [SR2]
ok: [SR1]
ok: [SR6]
ok: [VSR6]

TASK [nokia/128_lab : IMPORTING VARS] *********************************************************************
fatal: [VSR6]: FAILED!
fatal: [SR1]: FAILED!
fatal: [SR2]: FAILED!
ok: [SR6]

TASK [nokia/128_lab : CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT I] ************
ok: [SR6]

TASK [nokia/128_lab : OPENCOFNIG // CONFIGURING INTERFACES I] *********************************************
changed: [SR6]

TASK [nokia/128_lab : CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT II] ***********
ok: [SR6]

TASK [nokia/128_lab : OPENCOFNIG // CONFIGURING INTERFACES II] ********************************************
changed: [SR6]

PLAY [arista] *********************************************************************************************
skipping: no hosts matched
    to retry, use: --limit @/home/aaa/ansible/128_lab.retry

PLAY RECAP ************************************************************************************************
SR1                        : ok=1    changed=0    unreachable=0    failed=1  
SR2                        : ok=1    changed=0    unreachable=0    failed=1  
SR6                        : ok=6    changed=2    unreachable=0    failed=0  
VSR6                       : ok=1    changed=0    unreachable=0    failed=1

 

Only one of 4 VSRs are working, because I haven’t created files with variables for them. The verification shows that all the interfaces we have mentioned in variables are up and running:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[]
A:admin@SR6# show router interface
===============================================================================
Interface Table (Router: Base)
===============================================================================
Interface-Name                   Adm       Opr(v4/v6)  Mode    Port/SapId
   IP-Address                                                  PfxState
-------------------------------------------------------------------------------
oc_1/1/c1/1_13                   Up        Up/Up       Network 1/1/c1/1:13
   10.11.33.11/24                                              n/a
   fc00::10:11:33:11/112                                       PREFERRED
   fe80::f8ac:a6ff:fe16:202/64                                 PREFERRED
oc_1/1/c1/1_14                   Up        Up/Up       Network 1/1/c1/1:14
   10.11.44.11/24                                              n/a
   fc00::10:11:44:11/112                                       PREFERRED
   fe80::f8ac:a6ff:fe16:202/64                                 PREFERRED
system                           Up        Up/Up       Network system
   10.0.0.11/32                                                n/a
   fc00::10:0:0:11/128                                         PREFERRED
-------------------------------------------------------------------------------
Interfaces : 3
===============================================================================

 

2 out of 3 vendors are covered for OpenConfig YANG data models over NETCONF. There only one to go.

OpenConfig and Arista EOS

According to the information I’ve found in the Internet, OpenConfig in Arista EOS is supported starting EOS 4.20.2F, but that time there were a lot of limitations in terms of supported modules and operations (much more read-only rather than read-write). The actual release notes for version 4.20.5F provides much more OpenConfig capabilities, though the latter link requires authentication, so make sure you have registered at Arista website.

#1. Arista EOS. Enabling OpenConfig

According to the links provided above, the configuration of NETCONF at Arista EOS is quite straightforward and requires only configuration of corresponding management API:

1
2
3
4
5
6
7
8
9
vEOS2(config)#management api netconf
vEOS2(config-mgmt-api-netconf)#transport ssh default
vEOS2(config-netconf-transport-default)#vrf mgmt.
vEOS2(config-netconf-transport-default)#show active all
management api netconf
   transport ssh default
      no shutdown
      port 830
      vrf mgmt

 

The strange thing is that the standard port 830 doesn’t work, and any other arbitrary port doesn’t work either. How did I check that? I’m truing to connect to SSH through console in Linux, as I did both for Cisco IOS XR and Nokia (Alcatel-Lucent) SR OS:

1
$ ssh aaa@vEOS2 -p 830 -s netconf

But it hangs and become time out after some time. In order to connect for NETCONF, I need to remove “-p 830” so that I’m connected on standard SSH port 22:

1
2
3
4
$ ssh aaa@vEOS2 -s netconf
Password:

<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability><capability>urn:ietf:params:netconf:base:1.1</capability><capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability><capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</capability><capability>urn:ietf:params:netconf:capability:writable-running:1.0</capability><capability>http://openconfig.net/yang/types/yang?module=openconfig-yang-types&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/policy-types?module=openconfig-policy-types&amp;revision=2017-07-14</capability><capability>http://openconfig.net/yang/ospf-types?module=openconfig-ospf-types&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/aft?module=openconfig-aft&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/local-routing?module=openconfig-local-routing&amp;revision=2017-05-15</capability><capability>http://arista.com/yang/experimental/igmpsnooping?module=arista-exp-eos-igmpsnooping&amp;revision=2017-10-23</capability><capability>http://arista.com/yang/experimental/eos/eos-types?module=arista-eos-types&amp;revision=2016-10-14</capability><capability>http://openconfig.net/yang/interfaces/ip?module=openconfig-if-ip&amp;revision=2017-12-21</capability><capability>http://openconfig.net/yang/network-instance?module=openconfig-network-instance&amp;revision=2017-12-13</capability><capability>http://openconfig.net/yang/types/inet?module=openconfig-inet-types&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/interfaces/aggregate?module=openconfig-if-aggregate&amp;revision=2017-12-21</capability><capability>http://arista.com/yang/openconfig/system/deviations?module=arista-system-deviations&amp;revision=2017-09-24</capability><capability>http://openconfig.net/yang/bgp-types?module=openconfig-bgp-types&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/ldp?module=openconfig-mpls-ldp&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/ospfv2?module=openconfig-ospfv2&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/interfaces/ethernet?module=openconfig-if-ethernet&amp;revision=2017-12-21</capability><capability>urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&amp;revision=2013-07-15</capability><capability>urn:ietf:params:xml:ns:yang:iana-if-type?module=iana-if-type&amp;revision=2017-01-19</capability><capability>http://openconfig.net/yang/aaa/types?module=openconfig-aaa-types&amp;revision=2017-09-18</capability><capability>http://openconfig.net/yang/alarms?module=openconfig-alarms&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/bgp?module=openconfig-bgp&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/lldp/types?module=openconfig-lldp-types&amp;revision=2016-05-16</capability><capability>http://openconfig.net/yang/mpls?module=openconfig-mpls&amp;revision=2017-08-24</capability><capability>http://arista.com/yang/openconfig/lacp/augments?module=arista-lacp-augments&amp;revision=2017-09-14</capability><capability>http://arista.com/yang/openconfig/lldp/augments?module=arista-lldp-augments&amp;revision=2018-03-06</capability><capability>http://openconfig.net/yang/isis-types?module=openconfig-isis-types&amp;revision=2017-08-24</capability><capability>http://arista.com/yang/openconfig/policy/deviations?module=arista-rpol-deviations&amp;revision=2016-02-01</capability><capability>http://openconfig.net/yang/system/logging?module=openconfig-system-logging&amp;revision=2017-09-18</capability><capability>http://openconfig.net/yang/header-fields?module=openconfig-packet-match&amp;revision=2017-12-15</capability><capability>http://openconfig.net/yang/lldp?module=openconfig-lldp&amp;revision=2016-05-16</capability><capability>urn:ietf:params:xml:ns:netconf:base:1.0?module=ietf-netconf&amp;revision=2011-06-01</capability><capability>http://openconfig.net/yang/network-instance-l3?module=openconfig-network-instance-l3&amp;revision=2017-12-13</capability><capability>http://openconfig.net/yang/rsvp?module=openconfig-mpls-rsvp&amp;revision=2017-08-24</capability><capability>http://arista.com/yang/experimental/eos/qos/acl?module=arista-exp-eos-qos-acl-config&amp;revision=2017-09-26</capability><capability>http://openconfig.net/yang/system/terminal?module=openconfig-system-terminal&amp;revision=2017-09-18</capability><capability>http://openconfig.net/yang/mpls-sr?module=openconfig-mpls-sr&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/relay-agent?module=openconfig-relay-agent&amp;revision=2016-05-16</capability><capability>http://arista.com/yang/experimental/eos/qos/config?module=arista-exp-eos-qos-config&amp;revision=2017-09-26</capability><capability>http://openconfig.net/yang/isis-lsdb-types?module=openconfig-isis-lsdb-types&amp;revision=2017-08-24</capability><capability>http://arista.com/yang/openconfig/interfaces/augments?module=arista-intf-augments&amp;revision=2017-10-01</capability><capability>http://arista.com/yang/openconfig/network-instance/vlan/augments?module=arista-vlan-augments&amp;revision=2017-10-01</capability><capability>http://arista.com/yang/cert/gnoi-cert?module=arista-gnoi-cert&amp;revision=2018-01-15</capability><capability>http://openconfig.net/yang/vlan?module=openconfig-vlan&amp;revision=2017-07-14</capability><capability>http://arista.com/yang/experimental/eos/qos?module=arista-exp-eos-qos&amp;revision=2017-09-26</capability><capability>http://openconfig.net/yang/system/procmon?module=openconfig-procmon&amp;revision=2017-09-18</capability><capability>http://arista.com/yang/openconfig/acl/deviations?module=arista-acl-deviations&amp;revision=2017-11-01</capability><capability>http://openconfig.net/yang/bgp-policy?module=openconfig-bgp-policy&amp;revision=2017-07-30</capability><capability>http://arista.com/yang/openconfig/isis/deviations?module=arista-isis-deviations&amp;revision=2017-08-21</capability><capability>http://openconfig.net/yang/platform-types?module=openconfig-platform-types&amp;revision=2017-12-14</capability><capability>http://arista.com/yang/openconfig/relay-agent/deviations?module=arista-relay-agent-deviations&amp;revision=2016-11-21</capability><capability>http://openconfig.net/yang/acl?module=openconfig-acl&amp;revision=2017-05-26</capability><capability>http://arista.com/yang/openconfig/lacp/deviations?module=arista-lacp-deviations&amp;revision=2017-09-07</capability><capability>http://openconfig.net/yang/openconfig-ext?module=openconfig-extensions&amp;revision=2017-04-11</capability><capability>http://openconfig.net/yang/openconfig-types?module=openconfig-types&amp;revision=2017-08-16</capability><capability>http://openconfig.net/yang/aaa?module=openconfig-aaa&amp;revision=2017-09-18</capability><capability>http://openconfig.net/yang/interfaces?module=openconfig-interfaces&amp;revision=2017-12-21</capability><capability>http://openconfig.net/yang/openconfig-isis?module=openconfig-isis&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/platform?module=openconfig-platform&amp;revision=2017-12-14</capability><capability>http://openconfig.net/yang/network-instance-types?module=openconfig-network-instance-types&amp;revision=2017-08-24</capability><capability>http://arista.com/yang/openconfig/interfaces/deviations?module=arista-intf-deviations&amp;revision=2016-12-28</capability><capability>http://arista.com/yang/openconfig/isis/augments?module=arista-isis-augments&amp;revision=2018-01-12</capability><capability>http://arista.com/yang/openconfig/lldp/deviations?module=arista-lldp-deviations&amp;revision=2017-09-07</capability><capability>urn:ietf:params:xml:ns:yang:ietf-interfaces?module=ietf-interfaces&amp;revision=2014-05-08</capability><capability>http://openconfig.net/yang/vlan-types?module=openconfig-vlan-types&amp;revision=2017-07-14</capability><capability>http://arista.com/yang/experimental/multicast?module=arista-exp-eos-multicast&amp;revision=2017-10-20</capability><capability>http://openconfig.net/yang/sr?module=openconfig-segment-routing&amp;revision=2017-01-12</capability><capability>http://arista.com/yang/openconfig/local-routing/deviations?module=arista-local-routing-deviations&amp;revision=2017-11-22</capability><capability>http://arista.com/yang/openconfig/mpls/augments?module=arista-mpls-augments&amp;revision=2017-12-21</capability><capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&amp;revision=2010-10-04</capability><capability>urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&amp;revision=2013-07-15</capability><capability>http://openconfig.net/yang/policy-forwarding?module=openconfig-policy-forwarding&amp;revision=2017-06-21</capability><capability>http://openconfig.net/yang/fib-types?module=openconfig-aft-types&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/lacp?module=openconfig-lacp&amp;revision=2017-05-05</capability><capability>http://openconfig.net/yang/packet-match-types?module=openconfig-packet-match-types&amp;revision=2017-05-26</capability><capability>http://openconfig.net/yang/system?module=openconfig-system&amp;revision=2017-12-15</capability><capability>http://openconfig.net/yang/routing-policy?module=openconfig-routing-policy&amp;revision=2017-07-14</capability><capability>http://arista.com/yang/vlan-translation?module=vlan-translation&amp;revision=2017-11-29</capability><capability>http://openconfig.net/yang/mpls-types?module=openconfig-mpls-types&amp;revision=2017-08-24</capability><capability>http://arista.com/yang/openconfig/network-instances/deviations?module=arista-netinst-deviations&amp;revision=2017-11-10</capability><capability>http://arista.com/yang/experimental/eos?module=arista-exp-eos&amp;revision=2016-11-09</capability><capability>http://arista.com/yang/openconfig/bgp/deviations?module=arista-bgp-deviations&amp;revision=2016-02-01</capability><capability>http://openconfig.net/yang/aaa?module=openconfig-aaa-tacacs&amp;revision=2017-09-18</capability><capability>http://openconfig.net/yang/bgp?module=openconfig-bgp-common-multiprotocol&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/ospfv2?module=openconfig-ospfv2-area-interface&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/aft?module=openconfig-aft-pf&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/openconfig-isis?module=openconfig-isis-routing&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/aft?module=openconfig-aft-ipv4&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/aft?module=openconfig-aft-common&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/ospfv2?module=openconfig-ospfv2-global&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/openconfig-isis?module=openconfig-isis-lsp&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/aft?module=openconfig-aft-ipv6&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/network-instance?module=openconfig-network-instance-l2&amp;revision=2017-12-13</capability><capability>http://openconfig.net/yang/bgp?module=openconfig-bgp-neighbor&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/ospfv2?module=openconfig-ospfv2-area&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/policy-forwarding?module=openconfig-pf-forwarding-policies&amp;revision=2017-06-21</capability><capability>http://openconfig.net/yang/bgp?module=openconfig-bgp-common&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/ospfv2?module=openconfig-ospfv2-common&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/ospfv2?module=openconfig-ospfv2-lsdb&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/mpls?module=openconfig-mpls-igp&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/aft?module=openconfig-aft-mpls&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/bgp-types?module=openconfig-bgp-errors&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/policy-forwarding?module=openconfig-pf-interfaces&amp;revision=2017-06-21</capability><capability>http://openconfig.net/yang/bgp?module=openconfig-bgp-peer-group&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/mpls?module=openconfig-mpls-te&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/policy-forwarding?module=openconfig-pf-path-groups&amp;revision=2017-06-21</capability><capability>http://openconfig.net/yang/aft?module=openconfig-aft-ethernet&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/bgp?module=openconfig-bgp-common-structure&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/bgp?module=openconfig-bgp-global&amp;revision=2017-07-30</capability><capability>http://openconfig.net/yang/mpls?module=openconfig-mpls-static&amp;revision=2017-08-24</capability><capability>http://openconfig.net/yang/aaa?module=openconfig-aaa-radius&amp;revision=2017-09-18</capability></capabilities><session-id>2596996162</session-id></hello>]]>]]>

 

I don’t know, if it’s problem only of Arista vEOS, as I explained previously about VXLAN L3 VNI (link), or Arista EOS in general is affected. I hope colleagues from Arista could clarify this problem.

Also there is interesting fact that Arista sends all capabilities in a single line without “/n” split between lines containing different capabilities, like Nokia and Cisco does.

#2. Arista EOS. Get the interface configuration using OpenConfig

Just in the same fashion we did two times, let’s create two interfaces from CLI to verify the output of NETCONF RPC reply message in OpenConfig YANG data model for interfaces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vEOS2# show run
!
interface Ethernet1
   no switchport
!
interface Ethernet1.23
   logging event link-status
   encapsulation dot1q vlan 23
   ip address 10.22.33.22/24
   ipv6 address fc00::10:22:33:22/112
!
interface Loopback0
   ip address 10.0.0.22/32
   ipv6 address fc00::10:0:0:22/128
!
ip routing
!
end

 

Brief check that interfaces are up and running at Arista EOS based leaf vEOS2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
vEOS2#show ip int br
Interface              IP Address         Status     Protocol         MTU
Ethernet1              unassigned         up         up              1500
Ethernet1.23           10.22.33.22/24     up         up              1500
Loopback0              10.0.0.22/32       up         up             65535
Management1            192.168.44.82/24   up         up              1500
!
!
vEOS2#show ipv6 int br
Interface  Status    MTU  IPv6 Address                  Addr State  Addr Source
---------- ------- ------ ---------------------------- ------------ -----------
Et1.23     up       1500  fe80::250:56ff:fe73:2e21/64   up          link local
                          fc00::10:22:33:22/112         up          config
Lo0        up      65535  fe80::ff:fe00:0/64            up          link local
                          fc00::10:0:0:22/128           up          config

 

Now we can collect info through NETCONF using “edit-config” message:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
#252
<?xml version="1.0" encoding="utf-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="202">
<get-config>
<source>
<running/>
</source>
<filter>
<interfaces xmlns="http://openconfig.net/yang/interfaces"/>
</filter>
</get-config>
</rpc>
##


#222
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="202"><data time-modified="2018-07-23T08:23:54.961644479Z"><interfaces xmlns="http://openconfig.net/yang/interfaces"><interface><name>Management1</name>
#35
<config><description></description>
#23
<enabled>true</enabled>
#96
<load-interval xmlns="http://arista.com/yang/openconfig/interfaces/augments">300</load-interval>
#12
<mtu>0</mtu>
#24
<name>Management1</name>
#27
<type>ethernetCsmacd</type>
#9
</config>
#175
<ethernet xmlns="http://openconfig.net/yang/interfaces/ethernet"><config><fec-encoding xmlns="http://arista.com/yang/openconfig/interfaces/augments"><disabled>false</disabled>
#28
<fire-code>false</fire-code>
#34
<reed-solomon>false</reed-solomon>
#15
</fec-encoding>
#44
<mac-address>00:00:00:00:00:00</mac-address>
#38
<port-speed>SPEED_UNKNOWN</port-speed>
#100
<sfp-1000base-t xmlns="http://arista.com/yang/openconfig/interfaces/augments">false</sfp-1000base-t>
#9
</config>
#11
</ethernet>
#45
<subinterfaces><subinterface><index>0</index>
#24
<config><index>0</index>
#9
</config>
#97
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip"><addresses><address><ip>192.168.44.82</ip>
#30
<config><ip>192.168.44.82</ip>
#33
<prefix-length>24</prefix-length>
#9
</config>
#10
</address>
#12
</addresses>
#32
<config><enabled>false</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv4>
#87
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip"><config><enabled>false</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv6>
#15
</subinterface>
#16
</subinterfaces>
#12
</interface>
#33
<interface><name>Ethernet3</name>
#35
<config><description></description>
#23
<enabled>true</enabled>
#96
<load-interval xmlns="http://arista.com/yang/openconfig/interfaces/augments">300</load-interval>
#12
<mtu>0</mtu>
#22
<name>Ethernet3</name>
#27
<type>ethernetCsmacd</type>
#9
</config>
#175
<ethernet xmlns="http://openconfig.net/yang/interfaces/ethernet"><config><fec-encoding xmlns="http://arista.com/yang/openconfig/interfaces/augments"><disabled>false</disabled>
#28
<fire-code>false</fire-code>
#34
<reed-solomon>false</reed-solomon>
#15
</fec-encoding>
#44
<mac-address>00:00:00:00:00:00</mac-address>
#38
<port-speed>SPEED_UNKNOWN</port-speed>
#100
<sfp-1000base-t xmlns="http://arista.com/yang/openconfig/interfaces/augments">false</sfp-1000base-t>
#9
</config>
#11
</ethernet>
#45
<subinterfaces><subinterface><index>0</index>
#24
<config><index>0</index>
#9
</config>
#87
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip"><config><enabled>false</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv4>
#87
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip"><config><enabled>false</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv6>
#15
</subinterface>
#16
</subinterfaces>
#12
</interface>
#33
<interface><name>Ethernet2</name>
#35
<config><description></description>
#23
<enabled>true</enabled>
#96
<load-interval xmlns="http://arista.com/yang/openconfig/interfaces/augments">300</load-interval>
#12
<mtu>0</mtu>
#22
<name>Ethernet2</name>
#27
<type>ethernetCsmacd</type>
#9
</config>
#175
<ethernet xmlns="http://openconfig.net/yang/interfaces/ethernet"><config><fec-encoding xmlns="http://arista.com/yang/openconfig/interfaces/augments"><disabled>false</disabled>
#28
<fire-code>false</fire-code>
#34
<reed-solomon>false</reed-solomon>
#15
</fec-encoding>
#44
<mac-address>00:00:00:00:00:00</mac-address>
#38
<port-speed>SPEED_UNKNOWN</port-speed>
#100
<sfp-1000base-t xmlns="http://arista.com/yang/openconfig/interfaces/augments">false</sfp-1000base-t>
#9
</config>
#11
</ethernet>
#45
<subinterfaces><subinterface><index>0</index>
#24
<config><index>0</index>
#9
</config>
#87
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip"><config><enabled>false</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv4>
#87
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip"><config><enabled>false</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv6>
#15
</subinterface>
#16
</subinterfaces>
#12
</interface>
#33
<interface><name>Ethernet1</name>
#35
<config><description></description>
#23
<enabled>true</enabled>
#96
<load-interval xmlns="http://arista.com/yang/openconfig/interfaces/augments">300</load-interval>
#12
<mtu>0</mtu>
#22
<name>Ethernet1</name>
#27
<type>ethernetCsmacd</type>
#9
</config>
#175
<ethernet xmlns="http://openconfig.net/yang/interfaces/ethernet"><config><fec-encoding xmlns="http://arista.com/yang/openconfig/interfaces/augments"><disabled>false</disabled>
#28
<fire-code>false</fire-code>
#34
<reed-solomon>false</reed-solomon>
#15
</fec-encoding>
#44
<mac-address>00:00:00:00:00:00</mac-address>
#38
<port-speed>SPEED_UNKNOWN</port-speed>
#100
<sfp-1000base-t xmlns="http://arista.com/yang/openconfig/interfaces/augments">false</sfp-1000base-t>
#9
</config>
#11
</ethernet>
#45
<subinterfaces><subinterface><index>0</index>
#24
<config><index>0</index>
#9
</config>
#66
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip"><addresses>
#12
</addresses>
#31
<config><enabled>true</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv4>
#87
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip"><config><enabled>false</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv6>
#15
</subinterface>
#31
<subinterface><index>23</index>
#35
<config><description></description>
#23
<enabled>true</enabled>
#17
<index>23</index>
#9
</config>
#95
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip"><addresses><address><ip>10.22.33.22</ip>
#28
<config><ip>10.22.33.22</ip>
#33
<prefix-length>24</prefix-length>
#9
</config>
#10
</address>
#12
</addresses>
#31
<config><enabled>true</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv4>
#101
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip"><addresses><address><ip>fc00::10:22:33:22</ip>
#34
<config><ip>fc00::10:22:33:22</ip>
#34
<prefix-length>112</prefix-length>
#9
</config>
#10
</address>
#12
</addresses>
#32
<config><enabled>false</enabled>
#15
<mtu>1500</mtu>
#9
</config>
#7
</ipv6>
#15
</subinterface>
#16
</subinterfaces>
#12
</interface>
#13
</interfaces>
#19
</data></rpc-reply>
##

 

Well, output in Arista vEOS is a bit more difficult to read. We should remove all “#xx” framing symbols and add appropriate “/n” splitters to make it readable by human. I don’t provide the formatted output as it’s quite long (and in A4 pages’ size I’m already close to 60 pages, so I’m not sure you are still reading this article).

There are a couple of points we can spot in the output above:

  • It’s more similar to Cisco in terms of naming additional schemes, like <ipv4 xmlns=”http://openconfig.net/yang/interfaces/ip”>
  • It mixes Arista-proprietary parameters together with OpenConfig, like adding <sfp-1000base-t xmlns=”http://arista.com/yang/openconfig/interfaces/augments”>
  • It DOESN’T contain output of interface Loopback0.

Regarding the last point, again I don’t know, if it’s the problem of Arista EOS in general or Arista vEOS in particular.

#3. Arista EOS. Edit the interface configuration using OpenConfig

As I have configured manually only very small subset of parameters, like IPv4/IPv6 addresses and VLANs, I hope it would be enough to configure them over NETCONF using OpenConfig YANG model as well, without providing rest of parameters. Otherwise we again are going away from truly automation using single data model for devices and single Jinja2 template for NETCONF.

Just in the same way, we’ve done for Nokia (Alcatel-Lucent) SR OS and Cisco IOS XR, we will configure additional subinterface on Arista EOS based leaf vEOS2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#1700
<?xml version="1.0" encoding="utf-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="100">
<edit-config>
<target>
<running/>
</target>
<config>
<interfaces xmlns="http://openconfig.net/yang/interfaces">
<interface>
<name>Ethernet1</name>
<config>
<name>Ethernet1</name>
<type>ethernetCsmacd</type>
<enabled>true</enabled>
</config>
<subinterfaces>
<subinterface>
<index>23</index>
<config>
<index>23</index>
<enabled>true</enabled>
</config>
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
<addresses>
<address>
<ip>10.22.33.22</ip>
<config>
<ip>10.22.33.22</ip>
<prefix-length>24</prefix-length>
</config>
</address>
</addresses>
</ipv4>
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
<addresses>
<address>
<ip>fc00::10:22:33:22</ip>
<config>
<ip>fc00::10:22:33:22</ip>
<prefix-length>112</prefix-length>
</config>
</address>
</addresses>
</ipv6>
<vlan xmlns="http://openconfig.net/yang/vlan">
<config>
<vlan-id>23</vlan-id>
</config>
</vlan>
</subinterface>
<subinterface>
<index>24</index>
<config>
<index>24</index>
<enabled>true</enabled>
</config>
<ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
<addresses>
<address>
<ip>10.22.44.22</ip>
<config>
<ip>10.22.44.22</ip>
<prefix-length>24</prefix-length>
</config>
</address>
</addresses>
</ipv4>
<ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
<addresses>
<address>
<ip>fc00::10:22:44:22</ip>
<config>
<ip>fc00::10:22:44:22</ip>
<prefix-length>112</prefix-length>
</config>
</address>
</addresses>
</ipv6>
<vlan xmlns="http://openconfig.net/yang/vlan">
<config>
<vlan-id>24</vlan-id>
</config>
</vlan>
</subinterface>
</subinterfaces>
</interface>
</interfaces>
</config>
</edit-config>
</rpc>
##


#97
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="100"><ok></ok></rpc-reply>
##

 

And here we come to the point that no changes are applied despite “OK” response from vEOS2 and positive information in logs:

1
2
3
4
vEOS2#
Jul 23 17:37:51 vEOS2 ConfigAgent: %SYS-5-CONFIG_SESSION_ENTERED: User root entered configuration session session345514592380 on UnknownTty (UnknownIpAddr)
Jul 23 17:37:53 vEOS2 ConfigAgent: %SYS-5-CONFIG_SESSION_COMMIT_SUCCESS: User root committed configuration session session345514592380 successfully on UnknownTty (UnknownIpAddr)
Jul 23 17:37:53 vEOS2 ConfigAgent: %SYS-5-CONFIG_SESSION_EXITED: User root exited configuration session session345514592380 on UnknownTty (UnknownIpAddr)

 

If we take a look into configuration of Arista vEOS, there are no changes:

1
2
3
4
5
6
7
8
9
10
11
12
13
vEOS2#show run
! Command: show running-config
! device: vEOS2 (vEOS, EOS-4.20.7M)
!
interface Ethernet1
   no switchport
!
interface Ethernet1.23
   logging event link-status
   encapsulation dot1q vlan 23
   ip address 10.22.33.22/24
   ipv6 address fc00::10:22:33:22/112
!

 

I have done some researches in one or another direction, but still I haven’t succeeded to make it working for Arista EOS. I hope, colleagues from Arista could provide some feedback.

#4. Arista EOS. Ansible for OpenConfig with Cisco

From the automation point of view there is no difference comparing to previous two examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
+--ansible
   +--128_lab.yml
   +--group_vars
   |  +--arista
   |  |  +--arista_host.yml
   |  +--cisco
   |  |  +--cisco_host.yml
   |  +--nokia
   |     +--nokia_host.yml
   +--roles
      +--arista
      |  +--128_lab
      |     +--tasks
      |     |  +--main.yml
      |     +--templates
      |     |  +--interfaces.j2
      |     +--vars
      |        +--oc_vEOS2.yml
      +--cisco
      |  +--128_lab
      |     +--tasks
      |     |  +--main.yml
      |     +--templates
      |     |  +--interfaces.j2
      |     +--vars
      |        +--oc_vEOS2.yml
      +--nokia
         +--128_lab
            +--tasks
            |  +--main.yml
            +--templates
            |  +--interfaces.j2
            |  +--network_instance_interfaces.j2
            +--vars
               +--oc_vEOS2.yml

 

So we just copy, what we have done in Nokia part to Arista:

1
$ cp roles/nokia/128_lab/ roles/arista/128_lab/

Now, as previously, I guide you through key files. This time I do it without further explanation, as I did it twice already.

If you still have questions, refer to previous Cisco IOS XR or Nokia (Alcatel-Lucent) SR OS examples.

Number one is the authentication data:

1
2
3
4
5
6
7
8
$ cat group_vars/arista/arista_host.yml
---
ansible_network_os
: eos
ansible_user
: aaa
ansible_ssh_pass
: aaa
ansible_become
: yes
ansible_become_method
: enable
...

 

Number two is the per node parameters:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
$ cat roles/arista/128_lab/vars/oc_vEOS2.yml
---
node
:
    hostname
: vEOS3
    interfaces
:
        - name
: Loopback0
          type
: softwareLoopback
          enabled
: true
          subinterfaces
:
              - index
: 0
                ipv4
:
                    address
:
                        - ip
: 10.0.0.33
                          prefix_length
: 32
                ipv6
:
                    address
:
                        - ip
: fc00::10:0:0:33
                          prefix_length
: 128
        - name
: Ethernet2
          type
: ethernetCsmacd
          enabled
: true
          ethernet
:
              auto_negotiate
: false
          subinterfaces
:
              - index
: 13
                enabled
: true
                vlan
:
                    vlan_id
: 13
                ipv4
:
                    address
:
                        - ip
: 10.11.33.33
                          prefix_length
: 24
                ipv6
:
                    address
:
                        - ip
: fc00::10:11:33:33
                          prefix_length
: 112
              - index
: 23
                enabled
: true
                vlan
:
                    vlan_id
: 23
                ipv4
:
                    address
:
                        - ip
: 10.22.33.33
                          prefix_length
: 24
                ipv6
:
                    address
:
                        - ip
: fc00::10:22:33:33
                          prefix_length
: 112
...

 

Number three is the Jinja2 template for interfaces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
$ cat roles/arista/128_lab/templates/interfaces.j2
<config>
  <interfaces xmlns="http://openconfig.net/yang/interfaces">
{% for iface in node.interfaces %}
    <interface>
      <name>{{ iface.name }}</name>
      <config>
        <name>{{ iface.name }}</name>
{% if ansible_network_os == "iosxr" %}
        <type xmlns:idx="urn:ietf:params:xml:ns:yang:iana-if-type">idx:{{ iface.type }}</type>
{% else %}
        <type>{{ iface.type }}</type>
{% endif %}
        <enabled>{{ iface.enabled|lower }}</enabled>
      </config>
{% if iface.subinterfaces is defined %}
      <subinterfaces>
{% for siface in iface.subinterfaces %}
        <subinterface>
          <index>{{ siface.index }}</index>
{% if siface.index != 0 %}
          <config>
            <index>{{ siface.index }}</index>
{% if ansible_network_os == "iosxr" %}
            <name>{{ iface.name }}.{{ siface.index }}</name>
{% endif %}
            <enabled>{{ siface.enabled|lower }}</enabled>
          </config>
{% endif %}
{% if siface.ipv4 is defined %}
{% if ansible_network_os != "sros" %}
          <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
{% else %}
          <ipv4>
{% endif %}
{% if ansible_network_os != "iosxr" %}
           <addresses>
{% endif %}
{% for addr in siface.ipv4.address %}
            <address>
              <ip>{{ addr.ip }}</ip>
              <config>
                <ip>{{ addr.ip }}</ip>
                <prefix-length>{{ addr.prefix_length }}</prefix-length>
              </config>
            </address>
{% endfor %}
{% if ansible_network_os != "iosxr" %}
           </addresses>
{% endif %}
          </ipv4>
{% endif %}
{% if siface.ipv6 is defined %}
{% if ansible_network_os != "sros" %}
          <ipv6 xmlns="http://openconfig.net/yang/interfaces/ip">
{% else %}
          <ipv6>
{% endif %}
{% if ansible_network_os != "iosxr" %}
           <addresses>
{% endif %}
{% for addr in siface.ipv6.address %}
            <address>
              <ip>{{ addr.ip }}</ip>
              <config>
                <ip>{{ addr.ip }}</ip>
                <prefix-length>{{ addr.prefix_length }}</prefix-length>
              </config>
            </address>
{% endfor %}
{% if ansible_network_os != "iosxr" %}
           </addresses>
{% endif %}
          </ipv6>
{% endif %}
{% if siface.vlan is defined %}
{% if ansible_network_os != "sros" %}
          <vlan xmlns="http://openconfig.net/yang/vlan">
{% else %}
          <vlan>
{% endif %}
            <config>
              <vlan-id>{{ siface.vlan.vlan_id }}</vlan-id>
            </config>
          </vlan>
{% endif %}
        </subinterface>
{% endfor %}
      </subinterfaces>
{% endif %}
    </interface>
{% endfor %}
  </interfaces>
</config>

 

Point out there is no single change comparing to one we did for Nokia!

Number four is the playbook with tasks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ cat roles/arista/128_lab/tasks/main.yml
---
- name
: IMPORTING VARS
  include_vars
:
      file
: oc_{{ inventory_hostname }}.yml

- name
: CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT I
  template
:
      src
: interfaces.j2
      dest
: /tmp/oc_{{ inventory_hostname }}_if.conf
      mode
: 0755

- name
: OPENCOFNIG // CONFIGURING INTERFACES I
  netconf_config
:
      host
: "{{ inventory_hostname }}"
      username
: "{{ ansible_user }}"
      password
: "{{ ansible_ssh_pass }}"
      port
: 22
      hostkey_verify
: false
      look_for_keys
: false
      datastore
: running
      xml
: "{{ lookup ('template', 'interfaces.j2') }}"

- name
: CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT II
  template
:
      src
: network_instance_interfaces.j2
      dest
: /tmp/oc_{{ inventory_hostname }}_ni.conf
      mode
: 0755
  when
: ansible_network_os == "sros"

- name
: OPENCOFNIG // CONFIGURING INTERFACES II
  netconf_config
:
      host
: "{{ inventory_hostname }}"
      username
: "{{ ansible_user }}"
      password
: "{{ ansible_ssh_pass }}"
      port
: 22
      hostkey_verify
: false
      look_for_keys
: false
      datastore
: running
      xml
: "{{ lookup ('template', 'network_instance_interfaces.j2') }}"
  when
: ansible_network_os == "sros"
...

 

The key point here is port. We have changes it to “22” instead of “830”. Also we have explicitly put datastore as “running” cause it looks like Arista doesn’t support candidate config. There is default fall back, so it isn’t mandatory to specify this. I’ve done it just for sake of clarity.

So the work is done in the same fashion it was done for previous two vendors. If we test the execution of this Ansible playbook, it looks nice :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ ansible-playbook ansible/128_lab.yml --limit=arista

PLAY [cisco] **********************************************************************************************
skipping: no hosts matched

PLAY [nokia] **********************************************************************************************
skipping: no hosts matched

PLAY [arista] *********************************************************************************************

TASK [Gathering Facts] ************************************************************************************
ok: [vEOS2]

TASK [arista/128_lab : IMPORTING VARS] ********************************************************************
k: [vEOS2]

TASK [arista/128_lab : CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT I] ***********
ok: [vEOS2]

TASK [arista/128_lab : OPENCOFNIG // CONFIGURING INTERFACES I] ********************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: SSHError: Could not open socket to vEOS1:22
changed: [vEOS2]

TASK [arista/128_lab : CREATING TEMPORARY FILE TO MANUALLY CHECK THAT EDIT-CONFIG IS CORRECT II] **********
skipping: [vEOS2]

TASK [arista/128_lab : OPENCOFNIG // CONFIGURING INTERFACES II] *******************************************
skipping: [vEOS2]
    to retry, use: --limit @/home/aaa/ansible/128_lab.retry

PLAY RECAP ************************************************************************************************
vEOS2                      : ok=4    changed=1    unreachable=0    failed=0

 

But again, there are no changes in the configuration of the Arista vEOS2 after the playbook is implemented.

Here is the Ansible playbooks created in this lab:

Lessons learned

There are good and bad news:

  • The good news is that vendors are working on the introduction of OpenConfig in their NOSs. And the article shows that there are a lot of similar in terms of OpenConfig in Cisco, Nokia and Arista.
  • The bad news that all vendors has either deviations (something from OpenConfig YANG model isn’t supported) or augments (something vendor specific is added). Both those things you might have seen in the examples provided above.

I hope further development of OpenConfig and IETF YANG models will one day lead to purely programmable in a single manner network using single YANG data model

Greetings and acknowledges

Many thanks for Alex Nichol from Arista for sharing the latest version of Arista vEOS, which supports the latest OpenConfig models implemented in Arista. Thanks for Greg Hankins from Nokia for sharing info on OpenConfig in Nokia and providing configuration guide for VSIM. And special thanks to my friend Nicola Arnoldi, who has shown wonderful ASCII graph editor to me.

Conclusion

In this article we have reviewed what OpenConfig YANG data model is and how this model can be used for configuration of the interfaces for Arista EOS, Cisco IOS XR and Nokia (Alcatel-Lucent) SR OS. In my opinion, the results are quite positive. As we stated in the beginning of the article, in the next one we’ll review the configuration of BGP for undelaying data centre using OpenConfig YANG data model as well. Take care and good bye!

Support us





P.S.

If you have further questions or you need help with your networks, I’m happy to assist you, just send me message. Also don’t forget to share the article on your social media, if you like it.

BR,

Anton Karneliuk