Uploaded by Rohit Tarang

Cisco SW. Automate the VLAN creation, Python & netmiko

advertisement
Automate the VLAN
creation process using
Python & Netmiko.
Note:
This article is about a script designed to be executable across all Cisco devices that offer SSH
support, generally devices introduced from the year 2010 and onward. It is specifically
tailored for Cisco devices operating:
-IOS,
-IOS-XE,
-IOS-XR,
-NX-OS
-and SG300.
The script proves particularly valuable in scenarios where switches lack compatibility with
Cisco DNA (Example 2960 or SG300), serving as an effective alternative for streamlined and
efficient management. My tests are built on IOS and IOS-XE devices.
Prerequisites:
Before you proceed with learning about using Netmiko for VLAN automation on Cisco
devices, it's essential to have a foundational understanding of the following:
-Basic Networking Concepts
-Cisco Device Configuration
-Python Programming Basics
-SSH Access to Cisco Devices
Automating VLAN Creation on Cisco devices: Streamlining Network Management with
Python and Netmiko
In the dynamic world of networking, managing VLANs (Virtual Local Area Networks) on
many devices can be a time-consuming and error-prone task. Manually configuring VLANs
on multiple Cisco devices can quickly become tedious and inefficient. Fortunately,
automation can significantly Mitigate this burden, saving you time and effort while enhancing
the overall efficiency of your network management operations.
Why do we sometimes need to automate the VLAN
creation process?
The VLAN creation process on a Cisco switch is easy and straightforward, we only need to
use some commands to get it done:
Switch(config)# vlan 150 (press enter)
Switch(config-vlan)# name Main-VLAN (press enter)
And then if we are using a trunk port with a limited number of VLANs, we need to add our
new created VLAN to that Trunk port.
That process is easy and needs no more than a few seconds to be done, but what if we have
many switches that need to have the same VLAN in our network?! Then we need a way to
automate this process and get it done as fast as possible
What is Netmiko anyway?
Netmiko https://pynet.twb-tech.com/blog/netmiko-python-library.html is an open-source
Python library that allows you to interact with networking devices using SSH. It provides a
high-level interface for configuring and managing network devices, making it easier to
automate network tasks.
Here are some of the key features of Netmiko:
•
Supports a wide variety of network devices including
Cisco, Juniper, Arista, Huawei, and more.
•
Easy to use: Netmiko is easy to use and has a simple API that is easy to learn.
•
Efficient: Netmiko is efficient and can be used to automate complex network tasks.
•
Secure: Netmiko supports SSH authentication and encryption, ensuring that your
network devices are secure.
Setting Up the Environment:
-Install Ubuntu (bare metal or VM) or have it installed on your Windows machine (Windows
Subsystem for Linux WSL)
To set up Ubuntu on Windows Subsystem for Linux (WSL), follow these steps:
1- Enable WSL: Open PowerShell as Administrator and run the following commands to
enable WSL:
wsl --install
Restart-Computer
2- Open Microsoft Store and search for Ubuntu, get the latest version. When getting
Ubuntu is done, Click on the app icon to launch it.
3- Set up your account: The first time you launch Ubuntu, you will be prompted to create
a new user account and password. Follow the prompts to complete the setup process.
4- Update packages: Once the initial setup is complete, update the package lists and
upgrade installed packages by running the following commands:
sudo apt update
sudo apt upgrade
-On Ubuntu we need to install Python, Netmiko and Paramiko using these commands:
sudo
sudo
pip3
pip3
apt install python3
apt install python3-pip
install Netmiko
install paramiko
What is Paramiko anyway?
Paramiko and Netmiko are both Python libraries used for network
automation and managing network devices. to use Netmiko, you
need to have Paramiko installed. Netmiko is built on top of Paramiko
and relies on its SSH implementation for establishing connections and
executing commands on network devices. You can choose to import
Paramiko to your script or not if you are using Netmiko, because
Netmiko already imports Paramiko internally.
Sudo apt update:
in Ubuntu “sudo apt update” is used to update the
package lists for repositories configured on your system.
It's important to run "sudo apt update" periodically
to keep your package lists up to date. After running this
command, you can use "sudo apt upgrade" to
upgrade the installed packages to their latest versions, if
any updates are available.
Sudo apt install python3:
This command installs Python 3 and its related
packages on your Ubuntu system. Once installed,
you'll have access to the Python 3 interpreter and
the necessary tools to develop and run Python
programs.
Sudo apt install python3 pip:
python3-pip installs pip for Python 3. Pip is a
package manager used to install and manage
Python packages from the Python Package Index
(PyPI).
Running a Netmiko script:
To run a netmiko script, you will need two files: one file with a .py extension and another file
with a .json extension.
The .py file is the main script that contains the logic and the commands to be executed on the
network devices. The .json file is a file that contains only a list of the IP addresses of the
network devices, as a Python dictionary. The credentials of the network devices, such as
username, password, and secret, will be collected by asking the user to enter them
interactively.
The advantage of using a .json file for the IP addresses is that it allows you to store the device
information in a structured and readable format, and it also enables you to use a loop or a file
to control multiple devices at once. You can also use different .json files for different groups
of devices or different environments, such as production, testing, or development.
Creating the .py and .json files in Ubuntu:
To create these files we use Nano, which is a lightweight and user-friendly command-line text
editor that allows you to create and modify text files directly from the terminal.
To create the .py file run this command in Ubuntu:
nano create-vlan.py
(inside create-vlan.py paste the script text that you take from this article)
Press Ctrl+O to save, and then press Ctrl+X to exit
Your .py file should look something like this:
To create the .json file run this command in Ubuntu:
nano devices.json
Your .json file should look something like this:
Notice!!
• Use your switches IP addresses!
•You can add as many switches as you like, only be careful with the last one it does not need
to have a comma!!
With that been said, let’s look at the script:
Our script will first prompt for the administrator username, the administrative password
and then the Enable password of the device. Then, it will display two new prompts, one
about the desired VLAN ID and the other about the desired VLAN-name that we want to
create or check. If the VLAN already exists, the script will verify that it is properly configured
on the relevant trunk ports, which are configured with the "switchport trunk allowed vlan
add" command. If the VLAN does not exist, the script will create it and then configure it on
the appropriate trunk ports.
Here is the script:
from netmiko import ConnectHandler
from getpass import getpass
import json
import os
import re
import paramiko
username = getpass ('Enter Your UserName:')
password = getpass('Enter Your Password:')
secret = getpass('Enter Your Enable Password:')
which_vlan = input("wich VLAN do you want to check?: ")
vlan_name = input("vlan name?: ")
working_dir = os.getcwd()
try:
with open(working_dir + '/devices.json', 'r') as json_file:
ip_list = json.load(json_file)
except:
print('No ip list found')
for ip in ip_list.values():
device = {
'device_type': 'cisco_ios',
'ip': ip,
'username': username,
'password': password,
'secret': secret
}
net_connect = ConnectHandler(**device)
net_connect.enable()
show_run_hostname = net_connect.send_command('show run | include
hostname', use_textfsm=True)
match = re.search(r'^hostname\s+([^\n]*)', show_run_hostname,
re.IGNORECASE)
hostname = match.group(1) if match else "N/A"
print('\033[32m' + '*'*60 + '\033[0m')
print('\033[32m' + '*'*60 + '\033[0m')
print(f'Connecting to {ip} {hostname}')
#net_connect.enable()
show_vlan_command = net_connect.send_command('show vlan b',
use_textfsm=True)
vlan_already_there = False
for i in show_vlan_command:
if i['vlan_id'] == which_vlan:
print('The VLAN is already configured')
vlan_already_there = True
if not vlan_already_there:
create_new_vlan = [ f'vlan {which_vlan}', f'name {vlan_name}' ]
create_vlan = net_connect.send_config_set(create_new_vlan)
show_vlan_command = net_connect.send_command(f'show vlan b |
include {which_vlan}', use_textfsm=True)
print(show_vlan_command)
show_interface_command = net_connect.send_command('show interfaces
status', use_textfsm=True)
result = []
for d in show_interface_command:
if d['vlan']=='trunk':
result.append(d)
y = 0
while y < len(result):
a = result[y]['port']
print(f'{a} interface is a trunk')
add_new_vlan_to_trunk = [
(f'interface {a}'),
(f'switchport trunk allowed vlan add {which_vlan}'),
]
show_run_command = net_connect.send_command(f'show run interface {a} |
in allowed', use_textfsm=True)
trunk_is_allowed = 0
if show_run_command == "":
print("trunk is: switch port trunk")
trunk_is_allowed = 1
vlan_in_trunk = False
if show_run_command != "" and (f'{which_vlan}') in show_run_command:
vlan_in_trunk = True
print(f'For VLAN {which_vlan}, the configuration is already present
on the trunk interface {a}')
if not vlan_in_trunk and trunk_is_allowed < 1:
add_vlan_to_trunk =
net_connect.send_config_set(add_new_vlan_to_trunk)
print(f'new vlan {which_vlan} has been allowed on trunk interface
{a}')
y += 1
###End of the script
Notice:
You need to fix the indentation of the script before using it!
I could not find a better way to paste it in this Word document.
Here are screenshots of the script and how the indentation should look
like:
Here is the script with comments to explain it:
# Import the netmiko library for network automation
from netmiko import ConnectHandler
# Import the getpass library for getting user input securely
from getpass import getpass
# Import the json library for parsing JSON files
import json
# Import the os library for interacting with the operating system
import os
# Import the re library for regular expressions
import re
# Import the paramiko library for SSH connections
import paramiko
# Prompt the user to enter their username, password, and enable password
username = getpass ('Enter Your UserName:')
password = getpass('Enter Your Password:')
secret = getpass('Enter Your Enable Password:')
# Prompt the user to enter the VLAN ID and name that they want to check or
create
which_vlan = input("wich VLAN do you want to check?: ")
vlan_name = input("vlan name?: ")
# Get the current working directory
working_dir = os.getcwd()
# Try to open and read the devices.json file that contains the IP addresses
of the switches
try:
with open(working_dir + '/devices.json', 'r') as json_file:
ip_list = json.load(json_file)
# If the file is not found, print an error message
except:
print('No ip list found')
# Loop through the IP addresses in the ip_list dictionary
for ip in ip_list.values():
# Create a device dictionary with the device type, IP address,
username, password, and secret
device = {
'device_type': 'cisco_ios',
'ip': ip,
'username': username,
'password': password,
'secret': secret
}
# Establish a connection to the device using netmiko
net_connect = ConnectHandler(**device)
# Enter the enable mode
net_connect.enable()
# Send the command 'show run | include hostname' and parse the output
using textfsm
show_run_hostname = net_connect.send_command('show run | include
hostname', use_textfsm=True)
# Use a regular expression to extract the hostname from the output
match = re.search(r'^hostname\s+([^\n]*)', show_run_hostname,
re.IGNORECASE)
# Assign the hostname to a variable, or "N/A" if not found
hostname = match.group(1) if match else "N/A"
# Print 60 asterisks in green color
print('\033[32m' + '*'*60 + '\033[0m')
# Print another 60 asterisks in green color
print('\033[32m' + '*'*60 + '\033[0m')
# Print the IP address and the hostname of the device
print(f'Connecting to {ip} {hostname}')
# Enter the enable mode again
#net_connect.enable()
# Send the command 'show vlan b' and parse the output using textfsm
show_vlan_command = net_connect.send_command('show vlan b',
use_textfsm=True)
# Initialize a flag variable to indicate if the VLAN is already
configured
vlan_already_there = False
# Loop through the output of the show vlan command
for i in show_vlan_command:
# If the VLAN ID matches the user input, print a message and set
the flag to True
if i['vlan_id'] == which_vlan:
print('The VLAN is already configured')
vlan_already_there = True
# If the VLAN is not already configured, create a new VLAN with the
user input
if not vlan_already_there:
# Create a list of commands to create the VLAN and assign a name
create_new_vlan = [ f'vlan {which_vlan}', f'name {vlan_name}' ]
# Send the commands to the device using netmiko
create_vlan = net_connect.send_config_set(create_new_vlan)
# Send the command 'show vlan b | include <VLAN ID>' and parse the
output using textfsm
show_vlan_command = net_connect.send_command(f'show vlan b |
include {which_vlan}', use_textfsm=True)
# Print the output of the show vlan command
print(show_vlan_command)
# Send the command 'show interfaces status' and parse the output using
textfsm
show_interface_command = net_connect.send_command('show interfaces
status', use_textfsm=True)
# Initialize an empty list to store the trunk interfaces
result = []
# Loop through the output of the show interfaces command
for d in show_interface_command:
# If the VLAN is trunk, append the interface to the result list
if d['vlan']=='trunk':
result.append(d)
# Initialize a counter variable
y = 0
# Loop through the result list
while y < len(result):
# Assign the port name to a variable
a = result[y]['port']
# Print the port name and indicate that it is a trunk interface
print(f'{a} interface is a trunk')
# Create a list of commands to add the new VLAN to the trunk interface
add_new_vlan_to_trunk = [
(f'interface {a}'),
(f'switchport trunk allowed vlan add {which_vlan}'),
]
# Send the command 'show run interface <port> | in allowed' and parse the
output using textfsm
show_run_command = net_connect.send_command(f'show run interface {a} | in
allowed', use_textfsm=True)
# Initialize a flag variable to indicate if the trunk is allowed
trunk_is_allowed = 0
# If the output is empty, print a message and set the flag to 1
if show_run_command == "":
print("trunk is: switch port trunk")
trunk_is_allowed = 1
# Initialize a flag variable to indicate if the VLAN is in the trunk
vlan_in_trunk = False
# If the output is not empty and contains the VLAN ID, print a message and
set the flag to True
if show_run_command != "" and (f'{which_vlan}') in show_run_command:
vlan_in_trunk = True
print(f'For VLAN {which_vlan}, the configuration is already present on
the trunk interface {a}')
# If the VLAN is not in the trunk and the trunk is not allowed, send the
commands to add the VLAN to the trunk
if not vlan_in_trunk and trunk_is_allowed < 1:
add_vlan_to_trunk = net_connect.send_config_set(add_new_vlan_to_trunk)
print(f'new vlan {which_vlan} has been allowed on trunk interface {a}')
# Increment the counter variable
y += 1
Testing and Verification:
In this example I will create VLAN 113 and name it Test113:
To run the script, we use this command on Ubuntu:
Python3 create-vlan.py
I got 3 switches to test my script on, only the last switch with IP address
172.22.1.130 has a trunk port configured with a limited number of VLANs on it.
Trunk is: switch port trunk means that the trunk interface on that
switch is configured using the command switchport mode trunk.
New vlan 113 has been allowed on trunk interface
Gi0/2 means that the interface Gi0/2 on that switch is a trunk interface
configured with the command switchport trunk allowed vlan add
command.
113 Test113 active means that the VLAN 113 is created and is active.
So, what happens if we run the script again trying to create the same VLAN-ID
113?
The VLAN is already configured means that the VLAN 113 is already created on the
switch.
For VLAN 113, the configuration is already present on the trunk
interface Gi0/2 means that the VLAN 113 is already added to that trunk interface.
Conclusion:
In this article, I have shown how to use Python and Netmiko to automate the VLAN creation process
on Cisco devices. By using these Python modules, I can easily connect to multiple switches, check if
the VLAN already exists, create a new VLAN if needed, and add it to the trunk interfaces. This saves
me time and effort and ensures consistency and accuracy across my network. I hope this article has
been helpful for network administrators who want to use automation to make their life easier. Of
course, this script is not perfect and can be improved in many ways. I welcome any feedback
or suggestions from the readers. I am not a programmer, but a network administrator who loves to
learn new things and share them with others.
Reference
• Python Official Documentation
https://docs.python.org/3/
• Netmiko GitHub Repository
https://github.com/ktbyers/netmiko
• Youtube
https://www.youtube.com/watch?v=5dahqpYiH4g
https://www.youtube.com/watch?v=R7-2DAsPIbE
https://www.youtube.com/watch?v=NSnrvVhbuy8&t=3s
• Stack Overflow - Netmiko
https://stackoverflow.com/questions/tagged/netmiko
• Network Automation using Python 3: An Administrator's Handbook
https://www.amazon.com/Network-Automation-using-PythonAdministrators/dp/B084DH69QV/ref=sr_1_1?crid=LA09Z5LXBOHF&keywords=Network+
Automation+using+Python+3%3A+An+Administrator%27s+Handbook&qid=1705937541&s
prefix=network+automation+using+python+3+an+administrator%27s+handbook%2Caps%2
C151&sr=8-1
Download