本文目录导读:

针对自动化清理未使用的 VLAN,需要结合 网络设备类型(如 Cisco、华为、H3C、Juniper)和 管理方式(SNMP、SSH、NETCONF、REST API)来设计脚本,以下是通用的实现思路和关键步骤,以 SSH + Python (Netmiko/Napalm) 为例:
核心思路
- 识别未使用 VLAN:对比 VLAN 数据库与接口配置、Trunk 允许列表、VTP 等动态信息。
- 清理动作:删除未关联任何接口(Access/Trunk 均未使用)的 VLAN(保留默认 VLAN,如 VLAN 1)。
- 安全机制:自动验证、回滚、确认提示、保护关键 VLAN 列表。
示例脚本框架(Python + Netmiko)
from netmiko import ConnectHandler
import re
# 设备连接参数
device = {
'device_type': 'cisco_ios', # 根据设备调整
'host': '192.168.1.100',
'username': 'admin',
'password': 'cisco123',
'secret': 'enable_pwd'
}
# 需要保留的 VLAN 列表(不删除)
KEEP_VLANS = [1, 1002, 1003, 1004, 1005] # 保留默认 VLAN 和保留 VLAN
def get_all_vlans(ssh):
"""获取设备上所有 VLAN 列表"""
output = ssh.send_command("show vlan brief")
vlan_ids = re.findall(r'^(\d+)\s', output, re.MULTILINE)
return [int(v) for v in vlan_ids]
def get_used_vlans(ssh):
"""通过接口配置获取可能被使用的 VLAN"""
# 方法1:查看所有接口的 Access VLAN
used_vlans = set()
output = ssh.send_command("show interfaces status | include ^Gi|^Fa|^Eth") # 适配实际接口名模式
for line in output.splitlines():
parts = line.split()
# 假设第3列是 VLAN(如 "1" 或 "trunk")
if len(parts) >= 4:
vlan = parts[2] # 需根据实际输出调整
if vlan.isdigit():
used_vlans.add(int(vlan))
# 方法2:获取 Trunk 口允许的 VLAN(更全面)
output = ssh.send_command("show interfaces trunk")
for line in output.splitlines():
if "Vlans allowed" in line:
# 解析如 "1,20,30-40"
for part in line.split(':')[1].split(','):
part = part.strip()
if '-' in part:
start, end = part.split('-')
used_vlans.update(range(int(start), int(end)+1))
elif part.isdigit():
used_vlans.add(int(part))
return used_vlans
def delete_vlan(ssh, vlan_id):
"""安全删除指定 VLAN"""
print(f"Attempting to delete VLAN {vlan_id}...")
# 先检查确认(可选)
confirm = input(f"Delete VLAN {vlan_id}? (y/n): ").lower()
if confirm != 'y':
return False
commands = [
"configure terminal",
f"no vlan {vlan_id}",
"end"
]
output = ssh.send_config_set(commands)
return "deleted" in output.lower() or "configured" in output.lower()
def main():
ssh = ConnectHandler(**device)
ssh.enable()
all_vlans = get_all_vlans(ssh)
used_vlans = get_used_vlans(ssh)
print(f"All VLANs: {all_vlans}")
print(f"Used VLANs: {used_vlans}")
# 找出未使用的 VLAN(排除保留 VLAN)
unused = [v for v in all_vlans if v not in used_vlans and v not in KEEP_VLANS]
print(f"Unused VLANs (candidates for deletion): {unused}")
# 逐个删除(安全提示)
for vlan in unused:
delete_vlan(ssh, vlan)
ssh.disconnect()
if __name__ == "__main__":
main()
关键注意事项
- 保留关键 VLAN:必须排除
VLAN 1(默认 Native VLAN)、VTP/管理 VLAN、动态 VLAN 等。 - Trunk 端口允许列表:VLAN 即使未关联 Access 口,也可能被 Trunk 口允许并通过(实际在传输数据)。建议同时检查
show interface trunk和show vlan。 - 动态 VLAN:如果使用 VTP Client/Server 或 GVRP,需考虑动态学习到的 VLAN。
- 先验证再执行:建议先
--dry-run模式只打印不删除:def delete_vlan_dryrun(vlan_id): print(f"[DRY-RUN] Would delete VLAN {vlan_id}") return True - 权限与安全:脚本需具有
enable权限,且最好从堡垒机或安全脚本执行环境运行。 - 设备差异:不同厂商命令不同,如:
- 华为:
undo vlan vlan-id - H3C:
undo vlan vlan-id - Juniper:
delete vlans vlan-name - Cisco NX-OS:
no vlan vlan-id
- 华为:
更完善的自动化方案
| 方法 | 优势 | 场景 |
|---|---|---|
| Ansible Playbook | 支持批量、幂等性、日志记录 | 多设备批量清理 |
| NETCONF/YANG | 结构化数据,精准识别未使用 VLAN | 现代设备(如 IOS XE, Junos) |
| REST API (如 Cisco DNA Center) | 集中管理,图形化界面 | 大规模园区网 |
| SNMP | 无需 SSH 凭证,只读先扫描(如 snmpwalk) |
只审计未清理 |
进阶:基于时间戳的清理
如果设备支持(如 show vlan 带创建时间),可只清理 created > N days 的 VLAN,避免刚创建但尚未使用的 VLAN 被误删。
重要:生产环境执行时,务必先在测试设备验证,做好配置备份(
show run | redirect flash:pre_cleanup.txt),并保留手动回滚能力。