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

Importing Our Installed Package


Now that we have succesfully installed our hand-built ydk Python module for interacting with openconfig-interfaces, let's verify that it is actually importable and we can see attributes on the classes that were generated.

Verify Module Imports

We must first ensure that the packages that we pip installed are importable. The packages that ydk-gen produces get installed under the ydk namespace using the name we provided during the generate.py call. The modules inside our custom build package will correspond to whatever ad-hoc bundle models were supplied during generation time. While in the ydk-gen folder, type python3.6 to enter the Python interactive interpreter.

    
         python3.6
    

You should now be in the Python interactive interpreter.

    
        [root@234c5dde8ad6 ydk-gen]# python3.6
        Python 3.6.4 (default, Dec 19 2017, 14:48:12)
        [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
        Type "help", "copyright", "credits" or "license" for more information.
        >>>
    

Now, let's attempt to import the package we recently installed. Enter the following import in your interactive Python prompt:

    
    from ydk.models.openconfig_interfaces_lab import openconfig_interfaces
    

No errors so far! Great. This means our openconfig_interfaces_lab package that we build is properly installed and that we can import the YANG-based Python generated classes therein.

Instantiate one of the Auto-Generated Classes

Now that we've confirmed the ability to import classes that we installed, let us attempt to instantiate one of the auto-generated classes and use Python's dir() function to inspect the instance of the Interfaces() class that was dynamically generated from the model.

    
        interfaces = openconfig_interfaces.Interfaces()
        dir(interfaces)
    

You should observe the following:

    
        >>> interfaces = openconfig_interfaces.Interfaces()
        >>> dir(interfaces)
        ['Interface', '__class__', '__delattr__', '__dict__', '__dir__',
        '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
        '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',
        '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
        '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
        '__str__', '__subclasshook__', '_absolute_path', '_child_container_classes',
        '_child_list_classes', '_children_name_map', '_children_yang_names',
        '_get_child_by_seg_name', '_leafs', '_local_refs', '_perform_setattr',
        '_prefix', '_revision', '_segment_path', '_top_entity', 'children',
        'clone_ptr', 'get_absolute_path', 'get_child_by_name', 'get_children',
        'get_name_leaf_data', 'get_order_of_children', 'get_segment_path',
        'has_data', 'has_leaf_or_child_of_name', 'has_list_ancestor',
        'has_operation', 'interface', 'is_presence_container', 'is_top_level_class',
        'parent', 'path', 'set_filter', 'set_value', 'yang_name',
        'yang_parent_name', 'yfilter', 'ylist_key_names']
    

The dir() call should show you the auto-generated class and instance methods and attributes associated with the models we built in the prior module.

Drilling Deeper into the Class Heirarchy

Observe the attributes we are looking at come directly from the YANG model. Let's take it a step further to see if we can contruct and Interface class and correlate the attributes on that class with what was defined in the YANG model downloaded from the device.

Instantiate an instance of an Interface() object and use dir() to inspect its attributes as follows:

    
        interface = interfaces.Interface()
        dir(interface)
    

You should observe the following:

    
        >>> interface = interfaces.Interface()
        >>> dir(interface)
        ['Config', 'HoldTime', 'State', 'Subinterfaces', '__class__', '__delattr__',
        '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
        '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
        '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
        '__sizeof__', '__str__', '__subclasshook__', '_absolute_path', '_child_container_classes',
        '_child_list_classes', '_children_name_map', '_children_yang_names', '_get_child_by_seg_name',
        '_leafs', '_local_refs', '_perform_setattr', '_prefix', '_revision', '_segment_path',
        'children', 'clone_ptr', 'config', 'get_absolute_path', 'get_child_by_name',
        'get_children', 'get_name_leaf_data', 'get_order_of_children', 'get_segment_path',
        'has_data', 'has_leaf_or_child_of_name', 'has_list_ancestor', 'has_operation',
        'hold_time', 'is_presence_container', 'is_top_level_class', 'name', 'parent',
        'path', 'set_filter', 'set_value', 'state', 'subinterfaces', 'yang_name',
        'yang_parent_name', 'yfilter', 'ylist_key_names']
        >>>
    

In the above step, we instantiated an OpenConfig Interface class, which lives under the OpenConfig Interfaces container. We see attributes in this class like state, subinterfaces, name, hold_time, etc that correspond to the attributes defined in the YANG model that we originally downloaded from our device. Referring back to an excerpt from the openconfig-interfaces.yang model that we downloaded, the hold_time attribute corresponds back to this data from the source openconfig-interfaces.yang model we fed into YDK:

    
  grouping interface-phys-holdtime-config {
    description
      "Configuration data for interface hold-time settings --
      applies to physical interfaces.";

    leaf up {
      type uint32;
      units milliseconds;
      default 0;
      description
        "Dampens advertisement when the interface
        transitions from down to up.  A zero value means dampening
        is turned off, i.e., immediate notification.";
    }

    leaf down {
      type uint32;
      units milliseconds;
      default 0;
      description
        "Dampens advertisement when the interface transitions from
        up to down.  A zero value means dampening is turned off,
        i.e., immediate notification.";
    }
  }

  grouping interface-phys-holdtime-state {
    description
      "Operational state data for interface hold-time.";
  }

  grouping interface-phys-holdtime-top {
    description
      "Top-level grouping for setting link transition
      dampening on physical and other types of interfaces.";

    container hold-time {
      description
        "Top-level container for hold-time settings to enable
        dampening advertisements of interface transitions.";

      container config {
        description
          "Configuration data for interface hold-time settings.";

        uses interface-phys-holdtime-config;
      }

      container state {

        config false;

        description
          "Operational state data for interface hold-time.";

        uses interface-phys-holdtime-config;
        uses interface-phys-holdtime-state;
      }
    }
  }
    

The contents of the openconfig_interfaces_lab.openconfig_interfaces.Interfaces.Interface.hold_time object are statically represented by interface-phys-holdtime-state as seen from above. The same is true for all the attributes under the openconfig_interfaces namespace that was imported.

Exit Python Interactive Interpreter

    
    quit()
    

Type quit() and press enter to return back to the container shell. Let's move on to running the auto-generated unit test that YDK creates as a final verification of our created models.