"""Import des IPs SANEF (export iTop 'Interface réseau') → table server_ips. Usage: python tools/import_sanef_ips.py """ import csv import os import argparse from sqlalchemy import create_engine, text DATABASE_URL = os.getenv("DATABASE_URL_DEMO") or os.getenv("DATABASE_URL") \ or "postgresql://patchcenter:PatchCenter2026!@localhost:5432/patchcenter_demo" def main(): parser = argparse.ArgumentParser() parser.add_argument("csv_path") parser.add_argument("--replace", action="store_true", help="Vider server_ips avant l'import") args = parser.parse_args() engine = create_engine(DATABASE_URL) print(f"[INFO] DB: {DATABASE_URL.split('@')[-1]}") print(f"[INFO] CSV: {args.csv_path}") with open(args.csv_path, "r", encoding="utf-8-sig", newline="") as f: reader = csv.DictReader(f) rows = list(reader) print(f"[INFO] {len(rows)} lignes") conn = engine.connect().execution_options(isolation_level="AUTOCOMMIT") if args.replace: conn.execute(text("DELETE FROM server_ips")) print("[OK] server_ips vidé") linked = 0 missing = 0 skipped = 0 for r in rows: vm_name = (r.get("Machine virtuelle->Nom") or "").strip() ip = (r.get("Adresse IP") or "").strip() gw = (r.get("Passerelle") or "").strip() or None mask = (r.get("Masque de sous réseau") or "").strip() or None vrf = (r.get("VRF") or "").strip() or None if not vm_name or not ip: skipped += 1 continue srv = conn.execute(text("SELECT id FROM servers WHERE hostname=:h"), {"h": vm_name}).fetchone() if not srv: missing += 1 continue try: conn.execute(text(""" INSERT INTO server_ips (server_id, ip_address, is_primary, gateway, netmask, vrf) VALUES (:sid, :ip, true, :gw, :mask, :vrf) """), {"sid": srv.id, "ip": ip, "gw": gw, "mask": mask, "vrf": vrf}) linked += 1 except Exception as e: # colonnes optionnelles peut-être absentes, fallback minimal try: conn.execute(text(""" INSERT INTO server_ips (server_id, ip_address, is_primary) VALUES (:sid, :ip, true) """), {"sid": srv.id, "ip": ip}) linked += 1 except Exception as e2: print(f" [ERR] {vm_name} {ip}: {str(e2)[:150]}") skipped += 1 conn.close() print(f"[DONE] Liés: {linked} | Hostname introuvable: {missing} | Ignoré: {skipped}") if __name__ == "__main__": main()