我有一个代码如下,大致功能通过MAC地址是登录到OA核心交换机一层一层找对应的接入交换机,代码可能不全,你先理解下,我等会儿发新需求给你import logging
import re
import time
from netmiko import ConnectHandler
# ----------------------- 日志配置 -----------------------
logging.basicConfig(
filename='mac_manager.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
encoding='utf-8'
)
# ----------------------- 设备配置 -----------------------
DEVICES = {
'oa_core_switch': {
'device_type': 'hp_comware',
'host': '172.17.201.1',
'username': 'user',
'password': 'UESR',
'timeout': 15
},
'aggregation_switch': {
'device_type': 'hp_comware',
'username': 'user',
'password': 'UESR',
'timeout': 15
},
'access_switch': {
'device_type': 'hp_comware',
'username': 'python',
'password': 'USER',
'timeout': 10
}
}
# ----------------------- 增强的LLDP解析 -----------------------
def parse_lldp_neighbor(output):
"""解析LLDP输出获取管理IP"""
management_ip = None
for line in output.splitlines():
if 'Management address' in line and ':' in line:
ip_match = re.search(r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b', line)
if ip_match:
management_ip = ip_match.group()
break
return management_ip
# ----------------------- 设备连接管理 -----------------------
def connect_with_retry(device_info, retries=3, delay=5):
"""带重试机制的设备连接"""
for attempt in range(retries):
try:
conn = ConnectHandler(**device_info)
logging.info(f"成功连接 {device_info['host']}")
return conn
except Exception as e:
logging.error(f"连接失败({attempt + 1}/{retries}): {str(e)}")
time.sleep(delay)
raise ConnectionError(f"无法连接 {device_info['host']}")
# ----------------------- 增强的端口处理 -----------------------
def convert_port_format(physical_port):
"""转换端口格式 XGE -> Ten-GigabitEthernet"""
return physical_port.replace("XGE", "Ten-GigabitEthernet")
def handle_special_aggregation(ip, mac, vlan):
"""处理特殊汇聚交换机"""
try:
# 创建特殊设备配置(根据实际情况调整凭证)
special_device = {
'device_type': 'hp_comware',
'host': ip,
'username': 'user', # 特殊设备的用户名
'password': 'abc#1234567', # 特殊设备的密码
'timeout': 20
}
conn = connect_with_retry(special_device)
# 查找聚合端口
agg_port, phys_ports = get_aggregation_info(conn, mac)
if not agg_port:
return f"{ip} 未找到聚合端口"
# 遍历物理端口查找接入交换机
for port in phys_ports:
access_ip = get_lldp_neighbor(conn, port)
if not access_ip:
continue
# 配置接入交换机
result = configure_access_switch(access_ip, mac, vlan)
if "成功" in result:
return result
return f"{ip} 未找到有效接入链路"
except Exception as e:
logging.error(f"特殊汇聚处理失败: {str(e)}")
return f"特殊设备处理失败: {str(e)}"
finally:
if 'conn' in locals():
conn.disconnect()
def trace_oa_connection(mac, vlan):
"""OA区域全链路追踪(新增函数)"""
try:
oa_conn = connect_with_retry(DEVICES['oa_core_switch'])
# 核心逻辑与trace_fab_connection类似,需补充
agg_port, phys_ports = get_aggregation_info(oa_conn, mac)
if not agg_port:
return "OA核心交换机未找到聚合端口"
# 处理特殊IP范围(保持原有逻辑)
SPECIAL_IPS = {"172.17.201.2", "172.17.201.3", "172.17.201.4", "172.17.201.22"}
for port in phys_ports:
neighbor_ip = get_lldp_neighbor(oa_conn, port)
if not neighbor_ip:
continue
if neighbor_ip in SPECIAL_IPS:
return handle_special_aggregation(neighbor_ip, mac, vlan)
else:
return configure_access_switch(neighbor_ip, mac, vlan)
return "未找到有效链路"
except Exception as e:
logging.error(f"OA区域处理失败: {str(e)}")
return f"处理失败: {str(e)}"
finally:
if oa_conn:
oa_conn.disconnect()
# ----------------------- 通用工具函数 -----------------------
def get_aggregation_info(conn, mac):
"""获取聚合端口信息(核心/汇聚通用)"""
try:
cli_mac = f"{mac[:4]}-{mac[4:8]}-{mac[8:12]}"
output = conn.send_command(f"display mac-address {cli_mac}")
logging.info(f"MAC地址查询结果:\n{output}")
# 查找聚合端口
agg_port = None
for line in output.splitlines():
if 'BAGG' in line:
parts = line.split()
if len(parts) > 1:
agg_port = parts[-2] # 假设聚合口在倒数第二列
break
if not agg_port:
logging.warning("未找到聚合端口")
return None, None
# 获取物理端口
output = conn.send_command(f"display link-aggregation verbose {agg_port}")
logging.info(f"链路聚合信息:\n{output}")
phys_ports = []
for line in output.splitlines():
if any(x in line for x in ['XGE', 'GE']):
port = line.split()[0].replace('(R)', '').strip()
if port not in phys_ports:
phys_ports.append(port)
return agg_port, phys_ports
except Exception as e:
logging.error(f"获取聚合信息失败: {str(e)}")
return None, None
def get_lldp_neighbor(conn, port):
"""获取LLDP邻居信息(核心/汇聚通用)"""
try:
converted_port = convert_port_format(port)
output = conn.send_command(
f"display lldp neighbor-information interface {converted_port} verbose",
read_timeout=60
)
logging.info(f"LLDP邻居信息:\n{output}")
return parse_lldp_neighbor(output)
except Exception as e:
logging.error(f"LLDP查询失败: {str(e)}")
return None
def handle_oamac(raw_mac, vlan):
"""处理OA区域有线MAC"""
try:
mac = re.sub(r'[^0-9a-fA-F]', '', raw_mac).lower()
if len(mac) != 12:
raise ValueError("无效的MAC地址格式")
return trace_oa_connection(mac, vlan)
except Exception as e:
return f"参数错误: {str(e)}"
最新发布