Original automation module from the submitted project. Lab credentials and the device inventory are not published.
# vlan_automation.py
# Layer 2 VLAN Provisioning Loop
# Pushes the global VLAN database to every switch in the topology, then applies
# role-specific access-port VLAN assignments based on which block/device type
# each access switch actually serves (Staff, Management, or Guest).
from netmiko import ConnectHandler
from devices import INVENTORY, VLAN_CONFIGS
# Maps each access-layer role to the VLAN its connected end devices belong to,
# based on the Packet Tracer topology (Figure 3.1).
ROLE_VLAN_ASSIGNMENT = {
"access_staff_backoffice": 10, # ACC-BACK -> Staff PCs, laptops, AP
"access_staff": 10, # ACC-STAFF -> Staff PCs, laptops, AP
"access_mgmt": 20, # ACC-FRONTDESK -> Management / front desk devices
"access_guest": 30, # ACC-GUEST -> Guest TVs, smartphones, AP
}
def provision_vlans():
print("[*] Initiating Layer 2 VLAN Automation Broadcast...")
for device in INVENTORY["switches"]:
try:
print(f"[+] Establishing SSH Connection to {device['name']} ({device['block']} Block) "
f"at {device['host']}")
net_connect = ConnectHandler(**{
k: v for k, v in device.items() if k not in ("role", "name", "block")
})
# Global VLAN database compilation - every switch gets the full VLAN set
net_connect.send_config_set(VLAN_CONFIGS)
print(f"[SUCCESS] VLAN database synchronized on {device['name']}\n")
# Apply access-port VLAN assignment if this device has an access-layer role
vlan_id = ROLE_VLAN_ASSIGNMENT.get(device["role"])
if vlan_id:
commands = []
for port_num in range(1, 5):
commands.extend([
f"interface GigabitEthernet0/{port_num}",
"switchport mode access",
f"switchport access vlan {vlan_id}",
"spanning-tree portfast"
])
net_connect.send_config_set(commands)
print(f"[SUCCESS] Access ports on {device['name']} assigned to VLAN {vlan_id} "
f"({device['block']} Block)")
net_connect.disconnect()
except Exception as e:
print(f"[ERROR] Failed configuration on device {device['name']} "
f"({device['host']}): {str(e)}")
if __name__ == "__main__":
provision_vlans()