vManage REST APIs - Cisco SD-WAN 20.3.1 and building the SDWANCLI

7 minute read

Updated:

In this post, we will explore the vManage REST APIs, and use python requests module to interact with vManage for extracting some useful information, including list of devices in our SD-WAN system, list of device templates. We can also make changes to the configuration of SLA Class, template using python. Finally, we make the python scripts as a sdwancli by using python click module. This sdwancli is published in CiscoDevnet CodeExchange.

published

Or you can find it originally on my Github repo.

1. vManage REST APIs basics

There are some excellent materials from Cisco DevNet that can help you get started with the vManage REST APIs. I highly recommend looking at these resources first.

Devnet SD-WAN learning module

The vManage REST API library and documentation are bundled with and installed on the vManage web application software. To access the API documentation from a web browser, use this URL:

https://ip-address:port/apidocs

ip-address is the IP address of the vManage server, and port is the port used for the vManage server, could be either 8443 or 8444.

Since I reinstalled the SD-WAN lab on the new host machine, the vManage server now has the ip-address of 192.168.148.129 (changed from 192.168.134.138 on the old machine).

In our lab, the vManage web server has the URL https://192.168.148.129:8444. We can access the vManage REST API at https://192.168.148.129:8444/apidocs.

2. Click setup

Our project has the following structure:

├── LICENSE
├── poetry.lock
├── pyproject.toml
├── README.md
├── requirements.txt
├── sdwancli.py
├── sdwan-test.py
└── vmanage
    ├── authenticate.py
    ├── bfd.py
    ├── constants.py
    ├── device.py
    ├── ipsec.py
    ├── omp.py
    ├── sla.py
    ├── template.py
    └── utils.py

We use click group function to group multiple commands together. And groups can be nested. We separate the group into modules and import them on the sdwancli.py file. We next add them to the cli group using the add_command. Our main sdwancli is defined in sdwancli.py file as follows:

import click
from vmanage.device import cli_device
from vmanage.template import cli_template
from vmanage.bfd import cli_bfd
from vmanage.sla import cli_sla
from vmanage.omp import cli_omp
from vmanage.ipsec import cli_ipsec

@click.group()
def cli():
    """Command line tool to interact with CISCO SDWAN vManage.
    """
    pass


cli.add_command(cli_device)
cli.add_command(cli_template)
cli.add_command(cli_bfd)
cli.add_command(cli_sla)
cli.add_command(cli_omp)
cli.add_command(cli_ipsec)

Each command has subcommands, for example in the file vmanage/sla.py, we group all SLA subcommands under the cli_sla command and name it as sla.

@click.group(name="sla")
def cli_sla():
    """Commands for managing SLA Class: list, create, edit, delete
    """
    pass


@cli_sla.command(name="list", help="Get list of SLA Classes")

@cli_sla.command(name="create", help="Create a SLA Class")
@click.option("--name", help="name of the SLA Class")
@click.option("--description", help="description of the SLA Class")
@click.option("--loss", help="loss 0 - 100 %")
@click.option("--latency", help="latency 1 - 1000 ms")
@click.option("--jitter", help="jitter 1 - 1000 ms")

With this setting, we can run our commands like:

python sdwancli.py sla list
python sdwancli.py sla create --name "Video-Games3" --description "videogame 3" --loss 1 --latency 20 --jitter 5

We can access the help of each subcommand to know about the arguments using python sdwancli.py {command} {subcommand} --help, for example:

-> % python sdwancli.py sla create --help
Usage: sdwancli.py sla create [OPTIONS]

  Create a SLA Class

Options:
  --name TEXT         name of the SLA Class
  --description TEXT  description of the SLA Class
  --loss TEXT         loss 0 - 100 %
  --latency TEXT      latency 1 - 1000 ms
  --jitter TEXT       jitter 1 - 1000 ms
  --help              Show this message and exit.

3. vManage server information and Authentication

The environment is pre-configured to access my local SD-WAN lab in GNS3. The vManage information is stored in the vmanage/constants.py file as follows:

vmanage = {
    "host": "192.168.148.129",
    "port": "8443",
    "username": "admin",
    "password": "admin"
}

You can edit the variables in the vmanage/constants.py to point to your own vManage instance, the AlwaysOn SDWAN Sandbox, or the Reservable SDWAN Sandbox.

Note: When you use the AlwaysOn Sandbox, you do not have permission to perform some commands such as edit, create, delete.

4. Develop the first sla list command

4.1. Which API to use?

Let’s open a browser and navigate to our vManage REST APIs documentation at: https://192.168.148.129:8444/apidocs.

The first question we need to ask is which API and which HTTP operation (GET/PUT/POST/DELETE) we use to list the SLA Class. The HTTP operation is easy, we need to use GET operation.

However, for the API, vManage supports quite a lot of functionalities. Let’s search in the browser for the keyword SLA. Here it is, Configuration - Policy SLA Class Builder is the group of APIs that we should pay attention to.

Keep exploring, right there, the first API and also the HTTP operation GET: /template/policy/list/sla. Try it out!

Now, we may face the error since we run directly our GET command without authentication with the vManage. However, we can download the Postman-for-AlwaysOn-Cisco-SD-WAN collection to help us authenticate with the vManage server. We also should create a new SD-WAN environment with our vManage server information.

Now, run again the Try it out! in the vManage REST APIs documentation interface, the response should look like this.

4.2. How vManage Web Interface display this?

So in the previous step, we can get back the SLA list in json format. We may want to present this list in table format. Let’s take a look at the SLA list in the vManage Web Interface.

We go to Configuration > Policies > Centralized Policy > Add a policy > Select SLA Class, to see this table.

4.3. Start developing sla list with python

sla_list function

Now, we have all information we need:

  • The API: /template/policy/list/sla
  • The HTTP operation: GET
  • Output: Table format as in vManage Web Interface or we can customize as we like.
  • We use python rich module to formulate and color to have pretty table.

The function looks like this:

@cli_sla.command(name="list", help="Get list of SLA Classes")
def sla_list():
    headers = authentication(vmanage)
    base_url = "https://" + f'{vmanage["host"]}:{vmanage["port"]}/dataservice'
    api = "/template/policy/list/sla"
    url = base_url + api
    response = requests.get(url=url, headers=headers, verify=False)
    if response.status_code == 200:
        items = response.json()['data']
    else:
        print("Error:: " + str(response.text))
        exit()
    console = Console()
    table = Table(
        "Name", "Loss (%)", "Latency (ms)", "jitter (ms)", "Reference Count",
        "Updated by", "SLA ID", "Last Updated")

    for item in items:
        # breakpoint()
        time_date = datetime.datetime.fromtimestamp(
            item["lastUpdated"]/1000).strftime('%c')
        table.add_row(f'[green]{item["name"]}[/green]',
                      f'[blue]{item["entries"][0]["loss"]}[/blue]',
                      f'[magenta]{item["entries"][0]["latency"]}[/magenta]',
                      f'[cyan]{item["entries"][0]["jitter"]}[/cyan]',
                      f'[orange1]{item["referenceCount"]}[/orange1]',
                      f'[bright_green]{item["owner"]}[/bright_green]',
                      f'[magenta]{item["listId"]}[/magenta]',
                      f'[yellow]{time_date}[/yellow]')
    console.print(table)

First, we authenticate with vManage using authentication(vmanage). It will return the headers that we can put in the requests.get(url=url, headers=headers, verify=False). We receive the response that is exactly as we see with the Try it out! step.

Output of the request call

The response is as follows:

"data": [
    {
      "listId": "9d55345c-61c5-4972-9667-088710d6e014",
      "name": "Transactional-Data",
      "type": "sla",
      "description": "ACI Transactional Data SLA",
      "entries": [
        {
          "jitter": "100",
          "latency": "50",
          "loss": "5"
        }
      ],
      "lastUpdated": 1598695612881,
      "owner": "system",
      "readOnly": false,
      "version": "1.0",
      "infoTag": "aci",
      "referenceCount": 0,
      "references": [],
      "isActivatedByVsmart": false
    },
    {
      "listId": "63c0f996-7cc3-407e-9a75-7f6b6a176980",
      "name": "Bulk-Data",
      "type": "sla",
      "description": "ACI Bulk Data SLA",
      "entries": [
        {
          "jitter": "100",
          "latency": "300",
          "loss": "10"
        }
      ],
      "lastUpdated": 1598695613341,
      "owner": "system",
      "readOnly": false,
      "version": "1.0",
      "infoTag": "aci",
      "referenceCount": 0,
      "references": [],
      "isActivatedByVsmart": false
    },
    {
      "listId": "c6ea38b8-38d0-430b-b576-c582f504f383",
      "name": "Voice-And-Video",
      "type": "sla",
      "description": "ACI Voice And Video SLA",
      "entries": [
        {
          "jitter": "30",
          "latency": "45",
          "loss": "2"
        }
      ],
      "lastUpdated": 1598695612247,
      "owner": "system",
      "readOnly": false,
      "version": "1.0",
      "infoTag": "aci",
      "referenceCount": 0,
      "references": [],
      "isActivatedByVsmart": false
    },
    {
      "listId": "d81de142-24fa-492d-b62c-109310ac829d",
      "name": "Default",
      "type": "sla",
      "description": "ACI Default SLA",
      "entries": [
        {
          "jitter": "100",
          "latency": "300",
          "loss": "25"
        }
      ],
      "lastUpdated": 1598695612067,
      "owner": "system",
      "readOnly": false,
      "version": "1.0",
      "infoTag": "aci",
      "referenceCount": 0,
      "references": [],
      "isActivatedByVsmart": false
    }
  ]

There are four SLA classes that are defined by default in our SD-WAN system.

  • ACI Transactional Data SLA
  • ACI Bulk Data SLA
  • ACI Voice And Video SLA
  • ACI Default SLA

For each class, it is a dictionary dict_keys(['listId', 'name', 'type', 'description', 'entries', 'lastUpdated', 'owner', 'readOnly', 'version', 'infoTag', 'referenceCount', 'references', 'isActivatedByVsmart']). Now, we just need to format it in a table using rich.

Formatting the output with python rich module

First, we define the columns in the table, including: Name, Loss (%), Latency (ms), jitter (ms), Reference Count, and so on.

For each row, we color the information with different colors.

console = Console()
table = Table(
    "Name", "Loss (%)", "Latency (ms)", "jitter (ms)", "Reference Count",
    "Updated by", "SLA ID", "Last Updated")

for item in items:
    # breakpoint()
    time_date = datetime.datetime.fromtimestamp(
        item["lastUpdated"]/1000).strftime('%c')
    table.add_row(f'[green]{item["name"]}[/green]',
                  f'[blue]{item["entries"][0]["loss"]}[/blue]',
                  f'[magenta]{item["entries"][0]["latency"]}[/magenta]',
                  f'[cyan]{item["entries"][0]["jitter"]}[/cyan]',
                  f'[orange1]{item["referenceCount"]}[/orange1]',
                  f'[bright_green]{item["owner"]}[/bright_green]',
                  f'[magenta]{item["listId"]}[/magenta]',
                  f'[yellow]{time_date}[/yellow]')
console.print(table)

The output looks good.

5. Conclusion

In this post, we have going through one example to create the sdwancli sla list command. It’s quite awesome that with a single command we can see the SLA list information, which takes a lot of steps to figure out in the vManage Web Interface. Also, we can customize our information as we like.

It’s easy to extend the sdwancli library to include new commands and subcommands. For example, we can create the omp tlocs or omp tloc-paths following the same steps in Section 4.

Recently, in RouterGods, Dustin (Cisco Press SD-WAN book author), did a live troubleshooting session for control plane problem when onboarding new WAN Edge to the SD-WAN, I have implemented all the TB commands in my python library.

This table compares the commands on the vEdge and the commands using this sdwancli library. Moreover, there are some syntax differences between the commands on vEdge and cEdge. But, with sdwancli, we can just use the same.

vEdge commands Sdwancli commands
show control connections python sdwancli.py control connections –system_ip 2.2.2.1
show control connections-history python sdwancli.py control connections-history –system_ip 2.2.2.1
show bfd sessions python sdwancli.py bfd sessions –system_ip 2.2.2.1
show omp tlocs python sdwancli.py omp tlocs –system_ip 2.2.2.1
show omp tloc-paths python sdwancli.py omp tloc-paths –system_ip 2.2.2.1

And here are the results.

Categories:

Updated:

Comments