Network Automation using YANG Models across XE, XR, & NX

Introduction to YANG

YANG is a modeling language designed to allow network operators to programmatically represent configuration and operational state data. With respect to the world of networking, YANG's premise is one of unification; a tool to allow programmatic interfaces to routing and switching hardware using modern transport layer protocols carrying structured data, as opposed to raw, unstructured, command line (CLI) data.

One of the primary benefits of YANG as a technology is that it allows a vendor-neutral approach to defining the objects, data types, and their relationships when mapping device operational and configuration data to usable programmatic entities.


YANG Model Definitions

YANG model definitions can be divided into two major categories; industry standard and vendor specific. Industry standard models can be defined by standards defining organizations (SDOs) such as the IETF, or another example is the set of models defined by a group composed of network operators called OpenConfig. These two examples of industry standard sets of models are commonly referred to as IEFT models and OpenConfig models respectively. The vendor specific models are commonly referred to as native models since they are native only to that vendor's network operating system; in the case with Cisco, operating systems. The goal of SDOs, such as IETF and OpenConfig, is to work toward vendor-neutral YANG models. Native YANG models will most likely continue to exist due to the limited support of current SDO YANG models and also due to potential vendor specific feature/functionality.

Yang models can be found on GitHub at https://github.com/YangModels/yang/. Yang models are defined hierarchically as a tree. Each element in the model is called a node. Each node has a name and value or name and child nodes. Yang is structured into modules, where in general, modules consist of three main elements; module-header statements, revision statements, and definition statements. Header statements, as one would expect, define the name of the module, the modules namespace on the network device, the module definition, or any modules imported from a different Yang model. The revision statement simply gives the history about the module. And finally, the most robust, the definition statement is actually the main body that defines the data model.


A Familiar Comparison

Many initial introductions to YANG go right into modules, leafs, nodes, and other elements that comprise the data structure. To help conceptually understand these terms, YANG can be likened to Python datastructures, and to take it further, it is possible to convert YANG to JSON, and then JSON to YAML, and then YAML to Python. Functionally these are all just tools for representing data structures, so seeing how YANG elements map to Python is a useful exercise.

          
            YANG Element      Python Class
            Container         Dictionary
            Container name    Dictionary key
            Leaf name         Dictionary key
            Leaf              Dictionary value
            List              List
            String            String
            Bool              Bool
            Integer           Integer
            Empty             None
          
        

This should help you get a feel for how YANG datastructures map to common entities in Python.


Examination of Basic YANG Data Model Nodes

Throughout this section of the lab, the ietf-interfaces Yang model will be used as reference for examining what makes up a Yang data model. The ietf-interfaces Yang model can be found here for reference: ietf-interfaces.yang

The abbreviated output from the above mentioned ietf-interfaces.yang shows the header statement and the revision statement of the data model:

            
                module ietf-interfaces {

                  namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
                  prefix if;

                  import ietf-yang-types {
                    prefix yang;
                  }

                  organization
                    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";

                  ...

                  description
                    "This module contains a collection of YANG definitions for
                     managing network interfaces.
                     Copyright (c) 2014 IETF Trust and the persons identified as
                     authors of the code.  All rights reserved.
                     Redistribution and use in source and binary forms, with or
                     without modification, is permitted pursuant to, and subject
                     to the license terms contained in, the Simplified BSD License
                     set forth in Section 4.c of the IETF Trust's Legal Provisions
                     Relating to IETF Documents
                     (http://trustee.ietf.org/license-info).
                     This version of this YANG module is part of RFC 7223; see
                     the RFC itself for full legal notices.";

                  revision 2014-05-08 {
                    description
                      "Initial revision.";
                    reference
                      "RFC 7223: A YANG Data Model for Interface Management";
                  }
                ...
            
        

Yang, per RFC6020, has defined four types of nodes used to define a given data model. These include:

  1. Leaf Nodes
  2. Leaf-List Nodes
  3. Container Nodes
  4. List Nodes

A container node does not have a value itself; only a single argument identifier. A container is instead used to define the particulars of an interior data node in the schema tree which means to group related nodes. The group of related nodes are defined as a list and referred to as child nodes within the data tree. The subsequent substatements within the container makeup how each child node is defined. Example substatements include container, description, leaf, leaf-list, list, amongst others. A single defined Yang model can have more than one container grouping like child nodes.

Ietf-interfaces.yang actually has two main containers defined; one for configuration data and the other for operational data. In the truncated output below, you can discern these two are called "interfaces" and "interfaces-state" containers respectively. Make note in the output below the "config false" in the "interfaces-state" container. This is highly important in YANG models as it determines if the object in the tree is a configuration object or to obtain state data. You may sometimes see this annotated as read-only (RO) for state data versus read-write (RW) for configuration data.

            
                module ietf-interfaces {

                  ...

                  /*
                   * Configuration data nodes
                   */

                  container interfaces {
                    description
                      "Interface configuration parameters.";

                     ...

                  /*
                   * Operational state data nodes
                   */

                  container interfaces-state {
                    config false;
                    description
                      "Data nodes for the operational state of interfaces.";

                      ...
            
        

Within each container, the next node type introduced is a list. Remember, a container is composed of like nodes in a list data structure. A list defines a sequence of list entries. A list can contain any number or type of elements including, but not limited to leafs, other lists, or even containers.

            
                module ietf-interfaces {

                  ...

                  /*
                   * Configuration data nodes
                   */

                  container interfaces {
                    description
                      "Interface configuration parameters.";

                    list interface {
                      key "name";

                      description
                        "The list of configured interfaces on the device.
                         The operational state of an interface is available in the
                         /interfaces-state/interface list.  If the configuration of a
                         system-controlled interface cannot be used by the system
                         (e.g., the interface hardware present does not match the
                         interface type), then the configuration is not applied to
                         the system-controlled interface shown in the
                         /interfaces-state/interface list.  If the configuration
                         of a user-controlled interface cannot be used by the system,
                         the configured interface is not instantiated in the
                         /interfaces-state/interface list.";

                     ...

                  /*
                   * Operational state data nodes
                   */

                  container interfaces-state {
                    config false;
                    description
                      "Data nodes for the operational state of interfaces.";

                    list interface {
                      key "name";

                      description
                        "The list of interfaces on the device.
                         System-controlled interfaces created by the system are
                         always present in this list, whether they are configured or
                         not.";

                      ...
            
        

As mentioned above, a list contains other node types. Continuing to use our ietf-interfaces.yang example, within each container's list exists a list of leaf nodes. Leaf nodes contain a value, but no additional child nodes. In just examining the "interfaces" container, you can notice several leaf node arguments representing different aspects of an interface and their respective data types. A few examples from below include the interface name and description that are strings or the enabled leaf that is a boolean defaulting to true for the interface to be enabled or disabled.

            
                module ietf-interfaces {

                  ...

                  /*
                   * Configuration data nodes
                   */

                  container interfaces {
                    description
                      "Interface configuration parameters.";

                    list interface {
                      key "name";

                     leaf name {
                        type string;
                        ...
                      }

                      leaf description {
                        type string;
                        ...
                      }

                      leaf type {
                        type identityref {
                          base interface-type;
                        }
                        ...
                      }

                      leaf enabled {
                        type boolean;
                        default "true";
                        ...
                      }
                      ...
            
        

Examination of YANG Data Models Using Pyang

In this section of the lab, you are going to use a tool called pyang. Pyang is YANG validator and code generator written in Python. Within your development container, the ietf-interfaces.yang file has been provided. Within your container, on the command line (CLI), issue pyang -f tree ietf-interfaces.yang. The -f is a command line option for specifying the format of how you would like to view the YANG model. In this case, we make use of the tree format. This outputs the YANG model like the Linux tree command. You could optionally output the YANG model like found on GitHub using yang. Your output using the tree format option should look like the below. With pyang, we can more quickly and easily perform the same steps as we did above once we understand basic Yang nodes, i.e. containers, lists, and leaves.

            
                pyang -f tree ietf-interfaces.yang
                
            
        

YANG Augmentations

YANG module hierarchy can be augmented or expanded through the insertion of additional nodes into the data model. These augmentations typically reside within another model that are also contained on the server side along with the base model. The augmentation model, will import the base model in the header as discussed above.

The augmentation is done through the use of an "augment" statement within YANG data model hierarchy where the new node(s) should be inserted. Additionally, the "when" statement is used to define conditional logic for when the new node(s) can be used.

Sticking with the same ietf-interfaces YANG model; lets now look at another YANG model, ietf-ip.yang, that provides augmentations. The output from the above mentioned ietf-ip.yang shows the header statement and the augment statement of the data model that provides the the ability to configure and retrieve IP address related information to the ietf-interfaces model:

            
                module ietf-ip {
                 namespace "urn:ietf:params:xml:ns:yang:ietf-ip";
                 prefix ip;
                 import ietf-interfaces {
                   prefix if;
                 }

                 ...

                /*
                  * Configuration data nodes
                  */
                 augment "/if:interfaces/if:interface" {
                   description
                     "Parameters for configuring IP on interfaces.
                      If an interface is not capable of running IP, the server
                      must not allow the client to configure these parameters.";
                   container ipv4 {
                     presence
                       "Enables IPv4 unless the 'enabled' leaf
                        (which defaults to 'true') is set to 'false'";
                     description
                       "Parameters for the IPv4 address family.";
                     ...
            
        

Examination of a Augmentation YANG Data Model Using Pyang

Again, with pyang, you can more quickly and easily perform the same steps as above to view the augments and the respective containers, lists, and leaves that reside under the given augment.

        
            pyang -f tree ietf-ip.yang
            
        
    

YANG Deviations

In a perfect, YANG models would be the same and supported identically by every vendor. However, as we know, it is not a perfect world, thus the RFC specifies a mechanism known as deviations that can reside within YANG models. Deviations can be what YANG models a platform supports, if a platform implements a YANG model differently, etc.

For example, per operating system release, there should exist deviation YANG models, such as the below:

        
            deviation /if:interfaces/if:interface/ip:ipv4/ip:mtu {
                deviate not-supported;
                description  "Not supported in IOS-XE 3.17 release.";
            }
        
    

YANG is a great resource adn tool to have the ability to interact with many network operating systems using the same tooling, as you will see in this lab, but maybe not the same exact models. Throughout the lab, you will use a combination of the IETF, OpenConfig, and Native YANG model definitions to complete a task using different programmatic tooling. Remember, IETF and OpenConfig definitions have only had so much development done in the industry for feature/functionality support and are not supported equally across all three operating systems (XE, XR, & NX). Native YANG models can always be used to accomplish a task when there is lack of IETF or OpenConfig support.

Now that you have a basic understanding of how YANG data models are structured and the node types that encompass the model, proceed to the next lab section to learn about Network Configuration Protocol, also known as NETCONF.