Tracking XPaths on IOS XE

Tracking XPaths on IOS XE

  • #xpath
  • #projects
  • #tools
- Last updated on

Tracking XPaths:

Working with YANG Models is extensive and a bit challenging, we created this guide to help any engineer navigating into the YANG repositories looking for any desired XPath. Visit this Link for more information about XPaths.

(This is a work in progress. We are still looking for a better/efficient way to get that information)

Prerequisites:

  • A macOS or Linux computer with Internet access.
  • Homebrew installed (for macOS users).
  • Git installed.
  • pyenv and pip installed (if not already installed).
  • The pyang and fzf tools were installed.
  • pyang-xpath XPath plugin.

Getting ready:

Homebrew is a popular package manager for MacOS. If you already have Homebrew installed, you can go to the 2nd step to install Git.

  1. Open terminal and paste the following command:
/bin/bash -c \
  "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. Install Git (if not already installed):
brew install git
  1. Git clone the YangModels repository to your computer.
git clone https://github.com/YangModels/yang.git
  1. Install pyenv (if not already installed)
brew install pyenv
  1. Install pyenv version 3.8:
pyenv install 3.8
  1. Create and activate a virtual environment with Python 3.8
  • Get the version and path of Python installed:
pyenv versions
  • Create the virtual environment <fix your 3.8.x version>
~/.pyenv/versions/3.8.x/bin/python -m venv yang
  1. Change the directory and activate the virtual environment
  • Run the following to work within the cloned “yang” repository:
cd yang
  • Activate the virtual environment:
source bin/activate
  1. Install pip:
pip install --upgrade pip
  1. Install pyang:
pip install pyang

Pyang is an extensible YANG (RFC 6020/7950) validator. Provides a framework for plugins that can convert YANG modules to other formats.

  1. Clone the pyang-xpath plugin and record the downloaded path
  • Run the following command to clone the pyang-xpath plugin:
git clone https://github.com/NSO-developer/pyang-xpath.git

This plugin prints the name of each YANG node on a separate line with its full XPath path. This is useful when looking for a particular element in a large YANG file, and looking for the exact path it (or they) are at.

  • Run and copy the path of the pyang-xpath dir to be used in step 4 of “Track XPaths Using pyang and pyang-xpath” section:
find "$(pwd)" -type d -name "pyang-xpath" -print -quit
  1. Install command-line fuzzy finder fuzzy finder (fzf) and ripgrep (rg) command
  • Run the following command to install fuzzy finder:
brew install fzf

It’s an interactive Unix filter for command-line that can be used with any list; files, command history, processes, hostnames, bookmarks, git commits, etc.

  • Run the following command to install ripgrep:
brew install ripgrep

Ripgrep is a line-oriented search tool that recursively searches the current directory for a regex pattern.

Using fuzzy finder and ripgrep we will something like the grep command, but interactive!

Let’s see how everything works:

Let’s say that we are looking for a Xpath equivalent to a Cisco CLI command like: show lldp entry in our case we are working with Cisco XE devices version 17.9.1.

  1. In your computer terminal, let’s go to the yang directory using:
cd yang/vendor/cisco/xe/1791
  1. Let’s start filtering looking for lldp (which is going to be our interesting keyword):
rg --vimgrep lldp | fzf -i

Your terminal should look like this:

cd within yang folder

As soon as you hit enter, you will get into an interactive shell with the greater than sign >

  1. We are looking for an equivalent of show lldp entry, so let’s try completing the command and see:

interactive shell

I highlighted one interesting line list lldp-entry seems to be something related to our command, if you click on that line and hit enter, the terminal will print out that specific result like:

listing lldp entry

What did we get?

Searching inside the 1791 folder we got a module “Cisco-IOS-XE-lldp-oper.yang” that has some relationship with our lldp entry command.

Now, let’s explore inside the module “Cisco-IOS-XE-lldp-oper.yang”

  1. We can see the complete tree of the module running:
pyang -f tree Cisco-IOS-XE-lldp-oper.yang

The output should look like:

darwin@darwins-Mac 1791 % pyang -f tree Cisco-IOS-XE-lldp-oper.yang

module: Cisco-IOS-XE-lldp-oper
+--ro lldp-entries
+--ro lldp-entry* [device-id local-interface connecting-interface]
| +--ro device-id string
| +--ro local-interface string
| +--ro connecting-interface string
| +--ro ttl? uint32
| +--ro capabilities
| | +--ro repeater? empty
| | +--ro bridge? empty
| | +--ro access-point? empty
| | +--ro router? empty
| | +--ro telephone? empty
| | +--ro docsis? empty
| | +--ro station? empty
| | +--ro other? empty
| +--ro port-vlan-id? uint32
| +--ro mau-type? uint32
| +--ro auto-neg
| | +--ro enabled? empty
| | +--ro supported? empty
| +--ro power
| +--ro is-drawing-power? empty
| +--ro power-details
| +--ro power-pair? lldp-ios-xe-oper:lldp-pwr-pair-type
| +--ro power-class? lldp-ios-xe-oper:lldp-pwr-class-type
| +--ro power-device-type? lldp-ios-xe-oper:lldp-pwr-device-type
| +--ro power-source? lldp-ios-xe-oper:lldp-pwr-source-type
| +--ro power-priority? lldp-ios-xe-oper:lldp-pwr-priority-type
| +--ro power-requested? uint32
| +--ro power-allocated? uint32
+--ro lldp-state-details!
| +--ro enabled? boolean
| +--ro hello-timer? uint64
| +--ro system-name? string
| +--ro system-desc? string
| +--ro chassis-id? string
| +--ro chassis-id-type? lldp-ios-xe-oper:chid-subtype
| +--ro frame-in? uint64
| +--ro frame-out? uint64
| +--ro frame-error-in? uint64
| +--ro frame-discard? uint64
| +--ro tlv-discard? uint64
| +--ro tlv-unknown? uint64
| +--ro entries-aged-out? uint64
| +--ro mem-failures? uint64
| +--ro encap-failures? uint64
| +--ro inqueue-overflow? uint64
| +--ro table-overflow? uint64
+--ro lldp-intf-details* [if-name]
+--ro if-name string
+--ro isenabled? boolean
+--ro lldp-neighbor-details* [identifier]
| +--ro identifier string
| +--ro chassis-id? string
| +--ro chassis-id-type? lldp-ios-xe-oper:chid-subtype
| +--ro port-id? string
| +--ro port-id-type? lldp-ios-xe-oper:poid-type
| +--ro port-desc? string
| +--ro system-name? string
| +--ro system-desc? string
| +--ro time-remaining? uint32
| +--ro age? uint32
| +--ro time-since-last-update? uint32
| +--ro mgmt-addrs* []
| | +--ro mgmt-addr? string
| | +--ro mgmt-addr-type? lldp-ios-xe-oper:mgmt-type
| +--ro system-capabilities
| | +--ro repeater? empty
| | +--ro bridge? empty
| | +--ro access-point? empty
| | +--ro router? empty
| | +--ro telephone? empty
| | +--ro docsis? empty
| | +--ro station? empty
| | +--ro other? empty
| +--ro enabled-capabilities
| | +--ro repeater? empty
| | +--ro bridge? empty
| | +--ro access-point? empty
| | +--ro router? empty
| | +--ro telephone? empty
| | +--ro docsis? empty
| | +--ro station? empty
| | +--ro other? empty
| +--ro media-caps? lldp-ios-xe-oper:phy-media-cap
| +--ro ttl? uint32
| +--ro orgtlv-detail* [platform-id]
| | +--ro platform-id string
| | +--ro system-cookie? string
| +--ro peer-src-mac? yang:mac-address
+--ro tx? lldp-ios-xe-oper:tx-state
+--ro rx? lldp-ios-xe-oper:rx-state

You can see the complete tree of the module “Cisco-IOS-XE-lldp-oper.yang” it’s still a lot information to digest, but now you have a hierarchical view of a yang module, but we are still looking for the Xpath though!

  1. The pyang Xpath filter will come into play, using the copied path from step 10
pyang --plugindir <path_to_your_plugin> -f xpath Cisco-IOS-XE-lldp-oper.yang

The output should look like:

darwin@darwins-Mac 1791 % pyang --plugindir <path_to_your_plugin> \
-f xpath Cisco-IOS-XE-lldp-oper.yang

>>> module: Cisco-IOS-XE-lldp-oper
/lldp-entries
/lldp-entries/lldp-entry
/lldp-entries/lldp-entry/device-id
/lldp-entries/lldp-entry/local-interface
/lldp-entries/lldp-entry/connecting-interface
/lldp-entries/lldp-entry/ttl
/lldp-entries/lldp-entry/capabilities
/lldp-entries/lldp-entry/capabilities/repeater
/lldp-entries/lldp-entry/capabilities/bridge
/lldp-entries/lldp-entry/capabilities/access-point
/lldp-entries/lldp-entry/capabilities/router
/lldp-entries/lldp-entry/capabilities/telephone
/lldp-entries/lldp-entry/capabilities/docsis
/lldp-entries/lldp-entry/capabilities/station
/lldp-entries/lldp-entry/capabilities/other
/lldp-entries/lldp-entry/port-vlan-id
/lldp-entries/lldp-entry/mau-type
/lldp-entries/lldp-entry/auto-neg
/lldp-entries/lldp-entry/auto-neg/enabled
/lldp-entries/lldp-entry/auto-neg/supported
/lldp-entries/lldp-entry/power
/lldp-entries/lldp-entry/power/is-drawing-power
/lldp-entries/lldp-entry/power/power-details
/lldp-entries/lldp-entry/power/power-details/power-pair
/lldp-entries/lldp-entry/power/power-details/power-class
/lldp-entries/lldp-entry/power/power-details/power-device-type
/lldp-entries/lldp-entry/power/power-details/power-source
/lldp-entries/lldp-entry/power/power-details/power-priority
/lldp-entries/lldp-entry/power/power-details/power-requested
/lldp-entries/lldp-entry/power/power-details/power-allocated
/lldp-entries/lldp-state-details
/lldp-entries/lldp-state-details/enabled
/lldp-entries/lldp-state-details/hello-timer
/lldp-entries/lldp-state-details/system-name
/lldp-entries/lldp-state-details/system-desc
/lldp-entries/lldp-state-details/chassis-id
/lldp-entries/lldp-state-details/chassis-id-type
/lldp-entries/lldp-state-details/frame-in
/lldp-entries/lldp-state-details/frame-out
/lldp-entries/lldp-state-details/frame-error-in
/lldp-entries/lldp-state-details/frame-discard
/lldp-entries/lldp-state-details/tlv-discard
/lldp-entries/lldp-state-details/tlv-unknown
/lldp-entries/lldp-state-details/entries-aged-out
/lldp-entries/lldp-state-details/mem-failures
/lldp-entries/lldp-state-details/encap-failures
/lldp-entries/lldp-state-details/inqueue-overflow
/lldp-entries/lldp-state-details/table-overflow
/lldp-entries/lldp-intf-details
/lldp-entries/lldp-intf-details/if-name
/lldp-entries/lldp-intf-details/isenabled
/lldp-entries/lldp-intf-details/lldp-neighbor-details
/lldp-entries/lldp-intf-details/lldp-neighbor-details/identifier
/lldp-entries/lldp-intf-details/lldp-neighbor-details/chassis-id
/lldp-entries/lldp-intf-details/lldp-neighbor-details/chassis-id-type
/lldp-entries/lldp-intf-details/lldp-neighbor-details/port-id
/lldp-entries/lldp-intf-details/lldp-neighbor-details/port-id-type
/lldp-entries/lldp-intf-details/lldp-neighbor-details/port-desc
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-name
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-desc
/lldp-entries/lldp-intf-details/lldp-neighbor-details/time-remaining
/lldp-entries/lldp-intf-details/lldp-neighbor-details/age
/lldp-entries/lldp-intf-details/lldp-neighbor-details/time-since-last-update
/lldp-entries/lldp-intf-details/lldp-neighbor-details/mgmt-addrs
/lldp-entries/lldp-intf-details/lldp-neighbor-details/mgmt-addrs/mgmt-addr
/lldp-entries/lldp-intf-details/lldp-neighbor-details/mgmt-addrs/mgmt-addr-type
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities/repeater
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities/bridge
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities/access-point
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities/router
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities/telephone
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities/docsis
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities/station
/lldp-entries/lldp-intf-details/lldp-neighbor-details/system-capabilities/other
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities/repeater
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities/bridge
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities/access-point
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities/router
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities/telephone
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities/docsis
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities/station
/lldp-entries/lldp-intf-details/lldp-neighbor-details/enabled-capabilities/other
/lldp-entries/lldp-intf-details/lldp-neighbor-details/media-caps
/lldp-entries/lldp-intf-details/lldp-neighbor-details/ttl
/lldp-entries/lldp-intf-details/lldp-neighbor-details/orgtlv-detail
/lldp-entries/lldp-intf-details/lldp-neighbor-details/orgtlv-detail/platform-id
/lldp-entries/lldp-intf-details/lldp-neighbor-details/orgtlv-detail/system-cookie
/lldp-entries/lldp-intf-details/lldp-neighbor-details/peer-src-mac
/lldp-entries/lldp-intf-details/tx
/lldp-entries/lldp-intf-details/rx
darwin@darwins-Mac 1791 %

We can see all the XPaths within our module “Cisco-IOS-XE-lldp-oper.yang”, because we are interested in show lldp entry the following lines contain the Xpath for the CLI command:

>>> module: Cisco-IOS-XE-lldp-oper
/lldp-entries
/lldp-entries/lldp-entry

You can try using: | grep statement at the end of the command to reduce the list:

pyang --plugindir <path_to_your_plugin> -f xpath \
 Cisco-IOS-XE-lldp-oper.yang | grep entry

The following would be the reduced list of XPaths:

darwin@darwins-Mac 1791 % pyang --plugindir <path_to_your_plugin> \
 -f xpath Cisco-IOS-XE-lldp-oper.yang | grep entry

>>> module: Cisco-IOS-XE-lldp-oper

/lldp-entries/lldp-entry
/lldp-entries/lldp-entry/device-id
/lldp-entries/lldp-entry/local-interface
/lldp-entries/lldp-entry/connecting-interface
/lldp-entries/lldp-entry/ttl
/lldp-entries/lldp-entry/capabilities
/lldp-entries/lldp-entry/capabilities/repeater
/lldp-entries/lldp-entry/capabilities/bridge
/lldp-entries/lldp-entry/capabilities/access-point
/lldp-entries/lldp-entry/capabilities/router
/lldp-entries/lldp-entry/capabilities/telephone
/lldp-entries/lldp-entry/capabilities/docsis
/lldp-entries/lldp-entry/capabilities/station
/lldp-entries/lldp-entry/capabilities/other
/lldp-entries/lldp-entry/port-vlan-id
/lldp-entries/lldp-entry/mau-type
/lldp-entries/lldp-entry/auto-neg
/lldp-entries/lldp-entry/auto-neg/enabled
/lldp-entries/lldp-entry/auto-neg/supported
/lldp-entries/lldp-entry/power
/lldp-entries/lldp-entry/power/is-drawing-power
/lldp-entries/lldp-entry/power/power-details
/lldp-entries/lldp-entry/power/power-details/power-pair
/lldp-entries/lldp-entry/power/power-details/power-class
/lldp-entries/lldp-entry/power/power-details/power-device-type
/lldp-entries/lldp-entry/power/power-details/power-source
/lldp-entries/lldp-entry/power/power-details/power-priority
/lldp-entries/lldp-entry/power/power-details/power-requested
/lldp-entries/lldp-entry/power/power-details/power-allocated

There is another way to get a more specific XPath line, for this we must match the exact keyword or combination to get any result, for example:

pyang --plugindir <path_to_your_plugin> \
  -f xpath Cisco-IOS-XE-lldp-oper.yang --xpath-name=lldp-entry
pyang --plugindir <path_to_your_plugin> \
  -f xpath Cisco-IOS-XE-lldp-oper.yang --xpath-name=lldp-entry

>>> module: Cisco-IOS-XE-lldp-oper
/lldp-entries/lldp-entry
The XPath Tracking Procedure, authored by Darwin Castro, provides network engineers with a powerful toolkit for efficiently discovering and utilizing XPaths within YANG models. By combining the capabilities of tools like “pyang”, “fzf”, and “ripgrep”, engineers can rapidly pinpoint the XPaths they require, simplifying network automation and management tasks. This procedure empowers engineers to navigate complex YANG repositories with confidence, ultimately enhancing their ability to configure and manage network devices effectively. Whether you are working with Cisco XE devices, as illustrated in this guide, or any other YANG model, this procedure equips you with the tools to achieve XPath precision.

Happy XPath tracking!

Copyright © 2024 Darwin Castro