arista-vlan-sync/arista-vlan-sync.py

132 lines
4.2 KiB
Python

#!/usr/bin/env python3
'''
Script to sync arista vlan from a primary to secondary switches
'''
import os
import re
import paramiko
import time
# environment stuff
from dotenv import load_dotenv
from pathlib import Path # python3 only
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)
version = "1.00" # set a version to the program
# Define master switch details
MASTER_SWITCH = {
"ip": "23.169.120.2",
"username": os.getenv("SSHUSER"),
"password": os.getenv("SSHPASS")
}
# Define list of switches to sync with (with parameters)
SWITCHES = [
{
"ip": "23.169.120.3",
"username": os.getenv("SSHUSER"),
"password": os.getenv("SSHPASS")
},
{
"ip": "23.169.120.4",
"username": os.getenv("SSHUSER"),
"password": os.getenv("SSHPASS")
},
]
# Protected vlans - These wont sync in any way. Listed by vlan id only!
# Saved as tuple as these should only be read and not altered
PROTECTED_VLANS = ("1")
# sync vlan function
def sync_vlans(master_switch, switch):
# Establish SSH connection to master switch
master_client = paramiko.SSHClient()
master_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
master_client.connect(master_switch["ip"], username=master_switch["username"], password=master_switch["password"])
#Create a master vlan list
master_vlan_list = [];
try:
# Retrieve VLAN configuration from master switch
stdin, stdout, stderr = master_client.exec_command("show vlan")
vlan_config = stdout.readlines()
#Loop thru output
for v in vlan_config:
#Find lines that start with a number
if(re.search('^[1-9]', v)):
#Find only active vlans
if(re.search('active', v)):
#Strip all after active keyword
v = re.sub('active.*', 'active', v)
#Filter stuff
v = re.sub(r'\s+',' ',v)
v = v.replace(' ',':')
v = v.split(':')
v = v[:-1]
#Add to the master vlan list
master_vlan_list.append(v)
# Establish SSH connection to the current switch
switch_client = paramiko.SSHClient()
switch_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
switch_client.connect(switch["ip"], username=switch["username"], password=switch["password"])
#Loop through vlan lists
for vl in master_vlan_list:
vlan_num = vl[0]
vlan_name = vl[1]
vlan_state = vl[2]
if(vlan_state == "suspended"):
vlan_state = "suspend"
#Check if vlan not in protected list
if(vlan_num not in PROTECTED_VLANS):
print(f"SYNCING...\tVlan number: {vlan_num}\tVlan name: {vlan_name}\tVlan status: {vlan_state}")
# Apply VLAN configuration to the current switch
device_access = switch_client.invoke_shell()
device_access.send("terminal len 0\n")
# Create a list of commands to send
switch_commands = []
switch_commands.append('config t')
switch_commands.append('vlan '+vlan_num)
switch_commands.append('name '+vlan_name)
switch_commands.append('state '+vlan_state)
switch_commands.append('end')
for cmd in switch_commands:
device_access.send(f"{cmd}\n")
time.sleep(0.5)
output = device_access.recv(65535)
#print(output.decode(), end='')
else:
print(f"PROTECTED VLAN (SKIPPING)...\tVlan number: {vlan_num}\tVlan name: {vlan_name}\tVlan status: {vlan_state}")
print("VLANs synced successfully to switch %s" % switch["ip"])
except Exception as e:
print("Error: %s" % e)
finally:
# Close SSH connections
master_client.close()
switch_client.close()
# Main loop
if __name__ == "__main__":
# Loop through switches and run sync
for switch in SWITCHES:
sync_vlans(MASTER_SWITCH, switch)