132 lines
4.2 KiB
Python
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) |