diff --git a/db.py b/db.py index 90cb80f..a84ea1d 100644 --- a/db.py +++ b/db.py @@ -96,19 +96,32 @@ def upsert_switch(chassis_id, hostname, mgmt_ip, description, firmware='', vendo conn.close() +def _port_num(port): + """Trailing port digit(s): 'Gi1/9' → '9', 'Te1/10' → '10', '9' → '9'.""" + m = re.search(r'(\d+)$', (port or '').strip()) + return m.group(1) if m else (port or '').strip() + + def upsert_link(chassis_a, port_a, chassis_b, port_b): # Normalize order so A→B and B→A are treated as the same link if chassis_a > chassis_b: chassis_a, chassis_b = chassis_b, chassis_a port_a, port_b = port_b, port_a conn = get_conn() - # Check both orderings before inserting + # Exact match first existing = conn.execute(""" - SELECT id FROM links WHERE - (chassis_a=? AND port_a=? AND chassis_b=? AND port_b=?) OR - (chassis_a=? AND port_a=? AND chassis_b=? AND port_b=?) - """, (chassis_a, port_a, chassis_b, port_b, - chassis_b, port_b, chassis_a, port_a)).fetchone() + SELECT id FROM links WHERE chassis_a=? AND port_a=? AND chassis_b=? AND port_b=? + """, (chassis_a, port_a, chassis_b, port_b)).fetchone() + if not existing: + # Fuzzy match: same chassis pair, same trailing port numbers + # handles 'Gi1/9' vs '9' reported by different vendors for the same cable + rows = conn.execute(""" + SELECT port_a, port_b FROM links WHERE chassis_a=? AND chassis_b=? + """, (chassis_a, chassis_b)).fetchall() + for r in rows: + if _port_num(port_a) == _port_num(r[0]) and _port_num(port_b) == _port_num(r[1]): + existing = True + break if not existing: conn.execute(""" INSERT OR IGNORE INTO links (chassis_a, port_a, chassis_b, port_b)