Introduction
In this Learning Lab you will build your first Python application, using the vManage REST API and everything else you've learned in this module:
- SD-WAN and the components of the SD-WAN solution from Cisco
- Interacting with the vManage REST API via the Swagger documentation and Postman.
- Building Python the efunctions
login()
,get_request()
andpost_request()
and the Pythonc classrest_api_lib
.
You will build a custom CLI application that will perform the following tasks:
- Interact with the vManage REST API
- GET data about devices in the fabric, configuration templates, and which devices are associated with which templates.
- Attach and detach configuration templates to and from devices.
Objectives
When you have completed this Learning Lab, you will be able to:
- Build a Python-based CLI application that leverages the vManage REST API to get data, parse data, extract pertinent information, and display it to the user.
Prerequisites
To complete this lab you need:
Completion of Introduction to Cisco SD-WAN REST APIs, and Using Postman to interact with the Cisco SD-WAN REST API, and Using Python to interact with the Cisco SD-WAN REST API. You should be familiar with vManage, the role it plays in the fabric, and the REST API it exposes.
A local clone of the GitHub repository that contains the final version of the application. Refer to the prerequisites of Introduction to Cisco SD-WAN REST APIs for more information.
Python 3.6 or later and a Python virtual environment (venv). Refer to the prerequisites of Introduction to Cisco SD-WAN REST APIs for more information.
Lab infrastructure to target API calls and code. For the purposes of this Learning Lab you will leverage the Cisco SD-WAN 19.2 Reservable Sandbox. Login with username
admin
and passwordC1sco12345
.A local installation of Postman.
Step 1: Useful Python libraries
In the previous Learning Lab, you built the class that performs the authentication and GET and POST API requests. In this step you will explore the Python libraries that you will use throughout the rest of this Learning Lab.
Requests
You used the requests
library in the previous Learning Lab. requests
was developed by Kenneth Reitz and you can find more details about it and the documentation at this link. There are several similar libraries that are available for making REST API calls, and if you prefer to use them instead, you may.
Command Line Interface Creation Kit
The next library that you will use extensively in this Learning Lab is tthe Command Line Interface Creation Kit, known as click
. The library is described on its website as "a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary. ... It aims to make the process of writing command line tools quick and fun while also preventing any frustration caused by the inability to implement an intended CLI API."
Tabulate
The tabulate
library is used to "pretty-print" tabular data in Python. When you want to easily print small tables or have a readable presentation of mixed textual and numeric data, then you can use tabulate
in your Python code. In this Learning Lab, you will use tabulate
in your code to display to the user data that you gather from the vManage REST API. You can find more details about it at the following link.
Step 2: Import libraries and environment variables
In this step you will start building the CLI Python application. You will need an integrated development environment (IDE), such as Visual Studio Code.
Note: You can also open the
sdwan.py
file in the Getting Started GitHub repository if you want to review the completed code.
To build the application from the beginning, create a new Python file called sdwan.py
in your IDE. You can copy and paste the snippets of code in the following steps and by the end of the Learning Lab your code should be similar to the sdwan.py
file in the Getting Started GitHub repository.
We start by importing all the libraries that you will use in your Python code. Next, you define three environment variables called: SDWAN_IP
, SDWAN_USERNAME
and SDWAN_PASSWORD
.
There are several other ways to input data into your code, from passing arguments at the time you start the application to reading values from a file to connecting and extracting values from a database. The three environment variables are imported and stored in the Python code in variables with the same names. You will use them later to connect to the vManage instance represented with the SDWAN_IP
IP address with the username SDWAN_USERNAME
and password SDWAN_PASSWORD
.
The application will then verify that importing the environment variables was successful. If any of the three values is missing, the user receives a message showing how to set the environment variables.
The code so far is similar to the following:
#! /usr/bin/env python
import requests
import sys
import json
import click
import os
import tabulate
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
SDWAN_IP = os.environ.get("SDWAN_IP")
SDWAN_USERNAME = os.environ.get("SDWAN_USERNAME")
SDWAN_PASSWORD = os.environ.get("SDWAN_PASSWORD")
if SDWAN_IP is None or SDWAN_USERNAME is None or SDWAN_PASSWORD is None:
print("CISCO SDWAN details must be set via environment variables before running.")
print(" export SDWAN_IP=10.10.20.90")
print(" export SDWAN_USERNAME=admin")
print(" export SDWAN_PASSWORD=C1sco12345")
print("")
exit("1")
Step 3: An instance of the rest_api_lib class
In the next part of the app code, you will include an instance of the rest_api_lib
class and call the instance sdwanp
.
The three variables for SDWAN_IP
, SDWAN_USERNAME
, and SDWAN_PASSWORD
are passed as inputs into the rest_api_lib
class. An instance of this class is created and a requests
session is created with the vManage instance. In this session, you can use the get_request()
and post_request()
methods to GET and POST data to the vManage REST API.
Note: The following code sample may be missing some underscore characters. Refer to the code in the Getting Started with Cisco SD-WAN GitHub repository.
class rest_api_lib:
def __init__(self, vmanage_ip, username, password):
self.vmanage_ip = vmanage_ip
self.session = {}
self.login(self.vmanage_ip, username, password)
def login(self, vmanage_ip, username, password):
"""Login to vmanage"""
base_url_str = 'https://%s:8443/'%vmanage_ip
login_action = '/j_security_check'
#Format data for loginForm
login_data = {'j_username' : username, 'j_password' : password}
#Url for posting login data
login_url = base_url_str + login_action
sess = requests.session()
#If the vmanage has a certificate signed by a trusted authority change verify to True
login_response = sess.post(url=login_url, data=login_data, verify=False)
if b'<html>' in login_response.content:
print ("Login Failed")
sys.exit(0)
self.session[vmanage_ip] = sess
token_url = 'https://%s/'%vmanage_ip
token_action = '/dataservice/client/token'
token = sess.get(url=token_url)
# print(token)
headers = {'X-XSRF-TOKEN':token}
if token.status_code != 200:
if b'<html>' in token_url.content:
print(token_url)
print ("Login Token Failed")
exit(0)
else:
print("Token Success")
token = token.text
def get_request(self, mount_point):
"""GET request"""
url = "https://%s:8443/dataservice/%s"%(self.vmanage_ip, mount_point)
#print url
response = self.session[self.vmanage_ip].get(url, verify=False)
data = response.content
return data
def post_request(self, mount_point, payload, headers={'Content-Type': 'application/json'}):
"""POST request"""
url = "https://%s:8443/dataservice/%s"%(self.vmanage_ip, mount_point)
payload = json.dumps(payload)
print (payload)
response = self.session[self.vmanage_ip].post(url=url, data=payload, headers=headers, verify=False)
data = response.json()
return data
sdwanp = rest_api_lib(SDWAN_IP, SDWAN_USERNAME, SDWAN_PASSWORD)
Step 4: CLI with click
You will now use click
to create the CLI component of the application. In click
, CLI commands can be attached to other commands of type Group
so that arbitrary nesting of scripts and functions is possible. You group all the commands that the CLI will implement in the application under one group as shown in the following example:
@click.group()
def cli():
"""Command line tool for deploying templates to CISCO SDWAN.
"""
pass
@click.command()
def device_list():
pass
@click.command()
def template_list():
pass
@click.command()
def attached_devices():
pass
@click.command()
def attach():
pass
@click.command()
def detach():
pass
cli.add_command(attach)
cli.add_command(detach)
cli.add_command(device_list)
cli.add_command(attached_devices)
cli.add_command(template_list)
if __name__ == "__main__":
cli()
Five CLI commands are grouped under the cli
Group
: device-list
, template-list
, attached-devices
, attach
and detach
. The commands correspond to what you want the application to do from the beginning:
- Get a list of all the devices in the SD-WAN fabric (
device-list
). - Get a list of all the configuration templates on the vManage instance (
template-list
). - Get a list of all the devices attached to a specific template (
attached-devices
). - Attach a configuration template to a device (
attach
). - Detach a device from a configuration template (
detach
).
In the snippet of code above, the functions don't have any code or functionality behind them at this point. You can see that each one of them is just using pass
. In the next part of this Learning Lab you will start to populate each function with functional code to accomplish what you have planned.
Step 5: List of devices and templates
You will now populate the device_list
and template_list
functions with working code. You should remember that the REST API endpoint and resource that you accessed to get information about all the devices in the fabric was https://{{vmanage}}:{{port}}/dataservice/device
. You already have a session established with the vManage server in the instance of the rest_api_lib
class that you called sdwanp
. You will use the get_request
method of this object to get a list of all the devices in the fabric and store the JSON data that is returned by the API in the response
variable.
Next you extract just the [data]
portion of the JSON and store it in a variable called items
. The items
variable at this point contains all the devices in the fabric and a lot of additional data about each of them as you've seen in previous Learning Labs. You can see the contents of the items
variable when you use the Sandbox vManage instance below:
Click to HERE to expand contents of the items variable
You will now iterate over each item in the items
with a for
loop and extract data for the hostname
, device-type
, uuid
, system-ip
, site-id
, version
and device-model
of each device. After this you use tabulate
to display the data you extracted to the user.
The Python code for the device-list()
function and CLI option with the same name should be similar to the following:
@click.command()
def device_list():
"""Retrieve and return network devices list.
Returns information about each device that is part of the fabric.
Example command:
./sdwan.py device_list
"""
click.secho("Retrieving the devices.")
url = base_url + "/device"
response = requests.get(url=url, headers=header,verify=False)
if response.status_code == 200:
items = response.json()['data']
else:
print("Failed to get list of devices " + str(response.text))
exit()
headers = ["Host-Name", "Device Type", "Device ID", "System IP", "Site ID", "Version", "Device Model"]
table = list()
for item in items:
tr = [item['host-name'], item['device-type'], item['uuid'], item['system-ip'], item['site-id'], item['version'], item['device-model']]
table.append(tr)
try:
click.echo(tabulate.tabulate(table, headers, tablefmt="fancy_grid"))
except UnicodeEncodeError:
click.echo(tabulate.tabulate(table, headers, tablefmt="grid"))
Whether you have been building sdwan.py
from scratch throught this lab or you are viewing the file from the GitHub repository, you can now run the application and try to get a list of all the devices in the SD-WAN fabric.
Preparing to run the application
Before you run the application, in your terminal, add the environment variables for SDWAN_IP
, SDWAN_USERNAME
, and SDWAN_PASSWORD
:
export vManage_IP=10.10.20.90
export vManage_PORT=8443
export vManage_USERNAME=admin
export vManage_PASSWORD=C1sco12345
Retrieving a device list
Run the application and pass in the device_list
parameter:
./sdwan.py device-list
You should get a list of all the devices in the DevNet SD-WAN always-on sandbox:
(venv) root$ python sdwan.py device_list
Retrieving the devices.
╒═══════════════╤═══════════════╤══════════════════════════════════════════╤═════════════╤═══════════╤════════════════╤═════════════════╕
│ Host-Name │ Device Type │ Device ID │ System IP │ Site ID │ Version │ Device Model │
╞═══════════════╪═══════════════╪══════════════════════════════════════════╪═════════════╪═══════════╪════════════════╪═════════════════╡
│ vmanage │ vmanage │ 81ac6722-a226-4411-9d5d-45c0ca7d567b │ 10.10.1.1 │ 101 │ 19.2.2 │ vmanage │
├───────────────┼───────────────┼──────────────────────────────────────────┼─────────────┼───────────┼────────────────┼─────────────────┤
│ vsmart │ vsmart │ f7b49da3-383e-4cd5-abc1-c8e97d345a9f │ 10.10.1.5 │ 101 │ 19.2.2 │ vsmart │
├───────────────┼───────────────┼──────────────────────────────────────────┼─────────────┼───────────┼────────────────┼─────────────────┤
│ vbond │ vbond │ ed0863cb-83e7-496c-b118-068e2371b13c │ 10.10.1.3 │ 101 │ 19.2.2 │ vedge-cloud │
├───────────────┼───────────────┼──────────────────────────────────────────┼─────────────┼───────────┼────────────────┼─────────────────┤
│ dc-cedge01 │ vedge │ CSR-61CD2335-4775-650F-8538-4EC7BDFFD04C │ 10.10.1.11 │ 100 │ 16.12.3.0.3752 │ vedge-CSR-1000v │
├───────────────┼───────────────┼──────────────────────────────────────────┼─────────────┼───────────┼────────────────┼─────────────────┤
│ site1-cedge01 │ vedge │ CSR-807E37A3-537A-07BA-BD71-8FB76DE9DC38 │ 10.10.1.13 │ 1001 │ 16.12.3.0.3752 │ vedge-CSR-1000v │
├───────────────┼───────────────┼──────────────────────────────────────────┼─────────────┼───────────┼────────────────┼─────────────────┤
│ site2-cedge01 │ vedge │ CSR-DE6DAB19-BA1A-E543-959C-FD117F4A6205 │ 10.10.1.15 │ 1002 │ 16.12.3.0.3752 │ vedge-CSR-1000v │
├───────────────┼───────────────┼──────────────────────────────────────────┼─────────────┼───────────┼────────────────┼─────────────────┤
│ site3-vedge01 │ vedge │ 0140a336-5fd5-9829-10d2-f6ba0b177efd │ 10.10.1.17 │ 1003 │ 19.2.2 │ vedge-cloud │
╘═══════════════╧═══════════════╧══════════════════════════════════════════╧═════════════╧═══════════╧════════════════╧═════════════════╛
Retrieving a template list
The template_list()
function is very similar to device_list()
. The main difference is the REST API endpoint that you are accessing, which is https://{{vmanage}}:{{port}}/dataservice/template/device
. The data you extract from the returned JSON is about the Template Name
, Device Type
, Template ID
, Attached devices
and Template version
. You use tabulate
again to display the data to the user. The code for template_list()
is as follows:
@click.command()
def template_list():
"""Retrieve and return templates list.
Returns the templates available on the vManage instance.
Example command:
./sdwan.py template_list
"""
click.secho("Retrieving the templates available.")
url = base_url + "/template/device"
response = requests.get(url=url, headers=header,verify=False)
if response.status_code == 200:
items = response.json()['data']
else:
print("Failed to get list of templates")
exit()
headers = ["Template Name", "Device Type", "Template ID", "Attached devices", "Template version"]
table = list()
for item in items:
tr = [item['templateName'], item['deviceType'], item['templateId'], item['devicesAttached'], item['templateAttached']]
table.append(tr)
try:
click.echo(tabulate.tabulate(table, headers, tablefmt="fancy_grid"))
except UnicodeEncodeError:
click.echo(tabulate.tabulate(table, headers, tablefmt="grid"))
If you run the application after adding the template-list
code and pass in the template-list
parameter:
./sdwan.py template-list
The output should be similar to the following:
(venv) root$ python sdwan.py template_list
Retrieving the templates available.
╒═════════════════════════════╤═════════════════╤══════════════════════════════════════╤════════════════════╤════════════════════╕
│ Template Name │ Device Type │ Template ID │ Attached devices │ Template version │
╞═════════════════════════════╪═════════════════╪══════════════════════════════════════╪════════════════════╪════════════════════╡
│ vSmart_Template │ vsmart │ 90f26d2d-8136-4414-84de-4e8df52374e6 │ 1 │ 9 │
├─────────────────────────────┼─────────────────┼──────────────────────────────────────┼────────────────────┼────────────────────┤
│ Site_1_and_2_cEdge_Template │ vedge-CSR-1000v │ c566d38e-2219-4764-a714-4abeeab607dc │ 2 │ 13 │
├─────────────────────────────┼─────────────────┼──────────────────────────────────────┼────────────────────┼────────────────────┤
│ Site_3_vEdge_Template │ vedge-cloud │ db4c997a-7212-4ec1-906e-ed2b86c3f42f │ 1 │ 13 │
├─────────────────────────────┼─────────────────┼──────────────────────────────────────┼────────────────────┼────────────────────┤
│ DC_cEdge_Template │ vedge-CSR-1000v │ 24d4be69-8038-48a3-b546-c6df199b6e29 │ 1 │ 14 │
╘═════════════════════════════╧═════════════════╧══════════════════════════════════════╧════════════════════╧════════════════════╛
In the next step you will have a look at the attached_devices()
function and how to pass in options to the CLI application you are building.
Step 6: Which devices are attached to which templates?
In this step, you will get a list of all devices attached to a configuration template. Unlike the device_list
and template_list
functions, which did not take any parameters, the attached_devices
function needs as input the template ID in order to return the list of devices attached to it. In order to pass in parameters to the function, the click
library provides @click.option
(). You can specify as many options as you want and also provide a description for what each option means.
You will need to build the URL that specifies the resource in the vManage REST API that will return the devices attached to the template. The REST API documentation shows that the resource for the GET
call to is https://{{vmanage}}:{{port}}/dataservice/template/device/config/attached/templateId
. Using the vManage session that you opened in the sdwanp
instance of the rest_api_lib
class, you get_request
on this resource and store the returned data in a variable called response
.
From the data that is retrieved by the function, you will extract only information pertaining to the hostname
, device IP
, site ID
, host ID
and host type
and use tabulate
to display the data to the user. The code for the attached_devices
function should look similar to the one below:
@click.command()
@click.option("--template", help="Name of the template you wish to retrieve information for")
def attached_devices(template):
"""Retrieve and return devices associated to a template.
Example command:
./sdwan.py attached_devices --template db4c997a-7212-4ec1-906e-ed2b86c3f42f
"""
url = base_url + "/template/device/config/attached/{0}".format(template)
response = requests.get(url=url, headers=header,verify=False)
if response.status_code == 200:
items = response.json()['data']
else:
print("Failed to get template details")
exit()
headers = ["Host Name", "Device IP", "Site ID", "Host ID", "Host Type"]
table = list()
for item in items:
tr = [item['host-name'], item['deviceIP'], item['site-id'], item['uuid'], item['personality']]
table.append(tr)
try:
click.echo(tabulate.tabulate(table, headers, tablefmt="fancy_grid"))
except UnicodeEncodeError:
click.echo(tabulate.tabulate(table, headers, tablefmt="grid"))
Let's run the application and see the output of the new function. Pass in the attached_devices
parameter together with the template ID that you've obtained in the previous step:
python sdwan.py attached-devices --template b7ccd31e-0e59-417d-8f52-72fc9106060a`
The output should be similar to the following if there is at least one device attached to the template:
(venv) root$ python sdwan.py attached_devices --template db4c997a-7212-4ec1-906e-ed2b86c3f42f
╒═══════════════╤═════════════╤═══════════╤══════════════════════════════════════╤═════════════╕
│ Host Name │ Device IP │ Site ID │ Host ID │ Host Type │
╞═══════════════╪═════════════╪═══════════╪══════════════════════════════════════╪═════════════╡
│ site3-vedge01 │ 10.10.1.17 │ 1003 │ 0140a336-5fd5-9829-10d2-f6ba0b177efd │ vedge │
╘═══════════════╧═════════════╧═══════════╧══════════════════════════════════════╧═════════════╛
If your output doesn't have any devices, it just means there are no devices attached to this template. In the next step you'll see how you can attach a template to a specific device.
Step 7: Attaching devices to a configuration template
In this step, you will learn how to attach a configuration template that is available in vManage to devices in the SD-WAN fabric.
Login into the DevNet Always on sandbox vManage GUI at this link with username admin
and password C1sco12345
. On the left hand side in the expandable menu navigate to Configuration -> Templates
and have a look at the Site_3_vEdge_Template
and try to apply it to one of the vEdge devices. In this part of the Learning Lab you will do the exact same steps but using the vManage REST API and Python code for the attach()
function.
The Site_3_vEdge_Template
has several parameters that can be changed and applied at the time of template attachment. These parameters are for the hostname, the IPv4 address on the loopback interface, the IPv4 address on the Gigabit0/0 interface, the system IP and the site ID. All these parameters will be passed into the attach
function as @click.options
. The template ID as well as the target device ID that the template will be attached to will also be passed in as
options.
Since you are making configuration changes with this function, the REST API call will be a POST
and the endpoint that the call will be made to is https://{{vmanage}}:{{port}}/dataservice/template/device/config/attachfeature
. For information about finding the endpoint for attaching templates to devices, refer to the vManage REST API documentation.
In the documentation you can also see that the payload is mandatory and should be similar to the following:
{
"deviceTemplateList":[
{
"templateId":"41f6a440-c5cc-4cc6-9ca1-af18e332a781",
"device":[
{
"csv-status":"complete",
"csv-deviceId":"5e5f45e7-3062-44b2-b6f6-40c682149e05",
"csv-deviceIP":"172.16.255.11",
"csv-host-name":"vm1",
"//system/host-name":"vm1",
"//system/system-ip":"172.16.255.11",
"//system/site-id":"100",
"csv-templateId":"41f6a440-c5cc-4cc6-9ca1-af18e332a781",
"selected":"true"
}
],
"isEdited":false,
"isMasterEdited":false
}
]
}
Based on the VEDGE_BASIC_TEMPLATE
configuration template from the DevNet Sandbox vManage instance, edit the payload with the parameter values you take as input from the user via the @click.option
. Once the payload is built, the
post_requestmethod of the
sdwanpinstance is invoked and the response of this call is displayed to the user. The Python code for the
attach function should look like the following example:
@click.command()
@click.option("--template", help="Name of the template to deploy")
@click.option("--variables", help="Device Template variable values yaml file")
#@click.argument("parameters", nargs=-1)
def attach(template, variables):
"""Attach a template with Cisco SDWAN.
Provide all template parameters and their values as arguments.
Example command:
./sdwan.py attach --template template-id --variables Site-3-vEdge-Variables.yaml
"""
click.secho("Attempting to attach template.")
with open(variables) as f:
config = yaml.safe_load(f.read())
system_ip = config.get("system_ip")
host_name = config.get("host_name")
template_id = template
template_variables = {
"csv-status":"complete",
"csv-deviceId": config.get("device_id"),
"csv-deviceIP": system_ip,
"csv-host-name": host_name,
"//system/host-name": host_name,
"//system/system-ip": system_ip,
"//system/site-id": config.get("site_id"),
"/1/vpn_1_if_name/interface/if-name": config.get("vpn_1_if_name"),
"/1/vpn_1_if_name/interface/ip/address": config.get("vpn_1_if_ipv4_address"),
"/512/vpn-instance/ip/route/0.0.0.0/0/next-hop/vpn_512_next_hop_ip_address/address": config.get("vpn_512_next_hop_ip_address"),
"/512/vpn_512_if_name/interface/if-name": config.get("vpn_512_if_name"),
"/512/vpn_512_if_name/interface/ip/address": config.get("vpn_512_if_ipv4_address"),
"/0/vpn-instance/ip/route/0.0.0.0/0/next-hop/mpls_next_hop/address": config.get("mpls_next_hop"),
"/0/vpn-instance/ip/route/0.0.0.0/0/next-hop/public_internet_next_hop/address": config.get("public_internet_next_hop"),
"/0/vpn_public_internet_interface/interface/if-name": config.get("vpn_public_internet_interface"),
"/0/vpn_public_internet_interface/interface/ip/address": config.get("vpn_public_interface_if_ipv4_address"),
"/0/vpn_mpls_interface/interface/if-name": config.get("vpn_mpls_interface"),
"/0/vpn_mpls_interface/interface/ip/address": config.get("vpn_mpls_if_ipv4_address"),
"//system/gps-location/latitude": config.get("latitude"),
"//system/gps-location/longitude": config.get("longitude")
}
You can now try out the function just defined and run the application with the attach
option. In this case you will need to pass in all the required parameters, with a command similar to the following:
`
python sdwan.py attach --template db4c997a-7212-4ec1-906e-ed2b86c3f42f --variables Site-3-vEdge-Variables.yaml
The output should look similar to the following:
```JSON
Attempting to attach template.
Attached Site 3 vEdge Template
You can verify that the template was successfully applied by running the attached_devices
option once more and passing in the template ID.
Step 8: Detaching template from a device
You've seen how to attach a configuration template to a device. In this step you will build the function to detach
a configuration template from a device. Similar to the attach
function, the detach
function will perform configuration changes to a specific device so the REST API call will be a POST
and the payload for it can be found in the vManage REST API documentation in the Detach Device Templates section.
The detach
payload requires only two parameters: the device Id
and the system IP
of the device from which the template will be detached. The detach
function takes the two parameters as input from the user and passes them into the code via the @click.option
. Once the payload is built, the
post_requestmethod is invoked on the
https://{{vmanage}}:{{port}}/dataservice/template/config/device/mode/cli resource. The response of the REST API call is then displayed to the user.
You can also replicate detaching a configuration template in the vManage GUI, in a method similar to attaching a template. The Python code that will accomplish the exact same thing should be similar to the following:
@click.command()
@click.option("--target", help="ID of the device to detach")
@click.option("--sysip", help="System IP of the system to detach")
def detach(target, sysip):
"""Detach a template with Cisco SDWAN.
Provide all template parameters and their values as arguments.
Example command:
./sdwan.py detach --target 0140a336-5fd5-9829-10d2-f6ba0b177efd --sysip 10.10.1.17
"""
click.secho("Attempting to detach template.")
payload = {
"deviceType":"vedge",
"devices":[
{
"deviceId":str(target),
"deviceIP":str(sysip)
}
]
}
url = base_url + "/template/config/device/mode/cli"
response = requests.post(url=url, data=json.dumps(payload), headers=header, verify=False)
if response.status_code == 200:
id = response.json()["id"]
url = base_url + "/device/action/status/" + str(id)
while(1):
status_res = requests.get(url,headers=header,verify=False)
if status_res.status_code == 200:
push_status = status_res.json()
if push_status['summary']['status'] == "done":
if 'Success' in push_status['summary']['count']:
print("Changed configuration mode to CLI")
elif 'Failure' in push_status['summary']['count']:
print("Failed to change configuration mode to CLI")
exit()
break
else:
print("Failed to detach template with error " + response.text)
exit()
Let's verify that the application is working correctly and try to detach the template you've associated to vEdge03 in the previous step. In order to detach the template you need to pass in the target ID which in this case is the device ID of vEdge03 and the system IP of vEdge03. The application should be run like so: python sdwan.py detach --target 0140a336-5fd5-9829-10d2-f6ba0b177efd --sysip 10.10.1.17
and the output should be similar to the one below:
(venv) root$ python sdwan.py detach --target 0140a336-5fd5-9829-10d2-f6ba0b177efd --sysip 10.10.1.17
Attempting to detach template.
Changed configuration mode to CLI
You can once again check that the template was successfully detached by running the application with the attached_devices
option.
Step 9: The final version of the application
You will now combine all the components that you've built so far into one file and one application.
You've come a long way in this module, from the first Learning Lab in which you learned about what SD-WAN is, what are the components of the Cisco SD-WAN solution and how they interact together, how does the vManage REST API look and how you can interact with it via the swagger page to the second Learning Lab in which you've had a look at POSTMAN and how to make REST API calls with it.
You've used git to clone the repository with all the functions for logging into vManage and sending GET
and POST
REST API calls and you built the rest_api_lib class.
And you've taken the Python class and put it to great use in building your first CLI application for Cisco SD-WAN. You've had a look at the requests, click and tabulate Python libraries and then you built the functions to get a list of all the devices in the fabric, all the templates, all the devices attached to a specific template and attaching and detaching templates to devices.
It is now finally time to bring all the components together and wrap up the application. If you have followed along and built the snippets of code in your own IDE or you have the sdwan.py
file from the github.com repo opened, your final Python application code should be similar to the following:
Note: The following code sample may be missing some underscore characters. Refer to the code in the Getting Started with Cisco SD-WAN GitHub repository.
Click HERE to expand the sdwan.py file
You can follow the instructions in the README.md
file in the GitHub repository and run this application in a Python3 virtual environment with all the Python libraries mentioned in the requirements.txt
installed and use the DevNet Sandbox always-on vManage instance. you should be able to run the application and interact with the REST API and run through all the functions you've created.