ipwatch
This commit is contained in:
56
backend/app/scripts/check_network_device.py
Normal file
56
backend/app/scripts/check_network_device.py
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script pour vérifier et forcer la mise à jour du flag network_device
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Ajouter le chemin parent pour les imports
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..')))
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from backend.app.models.ip import IP
|
||||
|
||||
# Créer la connexion à la base de données
|
||||
db_path = os.getenv('DB_PATH', './data/db.sqlite')
|
||||
db_url = f"sqlite:///{db_path}"
|
||||
engine = create_engine(db_url, echo=False)
|
||||
SessionLocal = sessionmaker(bind=engine)
|
||||
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# Récupérer toutes les IPs
|
||||
ips = db.query(IP).all()
|
||||
|
||||
print(f"\n📊 Total IPs: {len(ips)}\n")
|
||||
|
||||
updated = 0
|
||||
for ip in ips:
|
||||
# Afficher les IPs avec host défini
|
||||
if ip.host:
|
||||
status_icon = "🟢" if ip.last_status == "online" else "🔴"
|
||||
network_icon = "🔷" if ip.network_device else " "
|
||||
|
||||
print(f"{status_icon} {network_icon} {ip.ip:15s} | Host: {ip.host:15s} | Network: {ip.network_device} | Status: {ip.last_status}")
|
||||
|
||||
# Mettre à jour network_device si host == "Network"
|
||||
should_be_network = (ip.host == "Network")
|
||||
if ip.network_device != should_be_network:
|
||||
ip.network_device = should_be_network
|
||||
updated += 1
|
||||
print(f" ✓ Flag network_device mis à jour pour {ip.ip}: {should_be_network}")
|
||||
|
||||
if updated > 0:
|
||||
db.commit()
|
||||
print(f"\n✅ {updated} IP(s) mise(s) à jour!")
|
||||
else:
|
||||
print(f"\n✓ Tous les flags network_device sont déjà à jour")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
db.close()
|
||||
118
backend/app/scripts/rebuild_ip_relations.py
Normal file
118
backend/app/scripts/rebuild_ip_relations.py
Normal file
@@ -0,0 +1,118 @@
|
||||
"""
|
||||
Reconstruit ip_parent depuis config.yaml, puis recalcule ip_enfant depuis ip_parent.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
CONFIG_PATH = Path(__file__).resolve().parents[3] / "config.yaml"
|
||||
|
||||
|
||||
def load_config() -> Dict[str, Any]:
|
||||
with CONFIG_PATH.open("r", encoding="utf-8") as handle:
|
||||
return yaml.safe_load(handle) or {}
|
||||
|
||||
|
||||
def normalize_children(value: Any) -> Optional[List[str]]:
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, str):
|
||||
return [value] if value else []
|
||||
if isinstance(value, list):
|
||||
return [str(item) for item in value if item]
|
||||
return []
|
||||
|
||||
|
||||
def ensure_columns(conn: sqlite3.Connection) -> None:
|
||||
cursor = conn.execute("PRAGMA table_info(ip)")
|
||||
columns = {row[1] for row in cursor.fetchall()}
|
||||
if "ip_parent" not in columns:
|
||||
conn.execute("ALTER TABLE ip ADD COLUMN ip_parent TEXT")
|
||||
if "ip_enfant" not in columns:
|
||||
conn.execute("ALTER TABLE ip ADD COLUMN ip_enfant TEXT")
|
||||
conn.commit()
|
||||
|
||||
|
||||
def collect_parent_mapping(config: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
|
||||
mapping: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
ip_classes = config.get("ip_classes", {}) or {}
|
||||
for ip_address, data in ip_classes.items():
|
||||
if not isinstance(data, dict):
|
||||
continue
|
||||
if "ip_parent" in data or "ip_enfant" in data:
|
||||
mapping[ip_address] = {
|
||||
"ip_parent": data.get("ip_parent"),
|
||||
"ip_enfant": normalize_children(data.get("ip_enfant"))
|
||||
}
|
||||
|
||||
for host in config.get("hosts", []) or []:
|
||||
if not isinstance(host, dict):
|
||||
continue
|
||||
ip_address = host.get("ip")
|
||||
if not ip_address:
|
||||
continue
|
||||
if "ip_parent" in host or "ip_enfant" in host:
|
||||
entry = mapping.setdefault(ip_address, {})
|
||||
entry.setdefault("ip_parent", host.get("ip_parent"))
|
||||
entry.setdefault("ip_enfant", normalize_children(host.get("ip_enfant")))
|
||||
|
||||
return mapping
|
||||
|
||||
|
||||
def main() -> None:
|
||||
config = load_config()
|
||||
db_path = Path(config.get("database", {}).get("path", "./data/db.sqlite"))
|
||||
mapping = collect_parent_mapping(config)
|
||||
|
||||
if not db_path.exists():
|
||||
raise FileNotFoundError(f"Base de données introuvable: {db_path}")
|
||||
|
||||
conn = sqlite3.connect(db_path)
|
||||
try:
|
||||
ensure_columns(conn)
|
||||
|
||||
if mapping:
|
||||
for ip_address, values in mapping.items():
|
||||
ip_parent = values.get("ip_parent")
|
||||
ip_enfant = values.get("ip_enfant")
|
||||
if ip_enfant is not None:
|
||||
conn.execute(
|
||||
"UPDATE ip SET ip_parent = ?, ip_enfant = ? WHERE ip = ?",
|
||||
(ip_parent, json.dumps(ip_enfant), ip_address)
|
||||
)
|
||||
else:
|
||||
conn.execute(
|
||||
"UPDATE ip SET ip_parent = ? WHERE ip = ?",
|
||||
(ip_parent, ip_address)
|
||||
)
|
||||
|
||||
cursor = conn.execute("SELECT ip, ip_parent FROM ip")
|
||||
rows = cursor.fetchall()
|
||||
parent_children: Dict[str, List[str]] = {}
|
||||
|
||||
for ip_address, ip_parent in rows:
|
||||
if ip_parent:
|
||||
parent_children.setdefault(ip_parent, []).append(ip_address)
|
||||
|
||||
for ip_address, _ in rows:
|
||||
children = parent_children.get(ip_address, [])
|
||||
conn.execute(
|
||||
"UPDATE ip SET ip_enfant = ? WHERE ip = ?",
|
||||
(json.dumps(children), ip_address)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
print("Reconstruction terminée.")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
98
backend/app/scripts/rebuild_ip_relations_from_hosts.py
Normal file
98
backend/app/scripts/rebuild_ip_relations_from_hosts.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""
|
||||
Reconstruit ip_parent/ip_enfant en utilisant le champ host et config.yaml.
|
||||
1) Pour chaque IP avec host, retrouve l'IP du host dans config.yaml et met ip_parent.
|
||||
2) Recalcule ip_enfant depuis ip_parent.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
CONFIG_PATH = Path(__file__).resolve().parents[3] / "config.yaml"
|
||||
|
||||
|
||||
def load_config() -> Dict[str, Any]:
|
||||
with CONFIG_PATH.open("r", encoding="utf-8") as handle:
|
||||
return yaml.safe_load(handle) or {}
|
||||
|
||||
|
||||
def ensure_columns(conn: sqlite3.Connection) -> None:
|
||||
cursor = conn.execute("PRAGMA table_info(ip)")
|
||||
columns = {row[1] for row in cursor.fetchall()}
|
||||
if "ip_parent" not in columns:
|
||||
conn.execute("ALTER TABLE ip ADD COLUMN ip_parent TEXT")
|
||||
if "ip_enfant" not in columns:
|
||||
conn.execute("ALTER TABLE ip ADD COLUMN ip_enfant TEXT")
|
||||
conn.commit()
|
||||
|
||||
|
||||
def host_ip_map(config: Dict[str, Any]) -> Dict[str, str]:
|
||||
mapping: Dict[str, str] = {}
|
||||
for host in config.get("hosts", []) or []:
|
||||
if not isinstance(host, dict):
|
||||
continue
|
||||
name = (host.get("name") or "").strip()
|
||||
ip = (host.get("ip") or "").strip()
|
||||
if name and ip:
|
||||
mapping[name.lower()] = ip
|
||||
return mapping
|
||||
|
||||
|
||||
def main() -> None:
|
||||
config = load_config()
|
||||
db_path = Path(config.get("database", {}).get("path", "./data/db.sqlite"))
|
||||
|
||||
if not db_path.exists():
|
||||
raise FileNotFoundError(f"Base de données introuvable: {db_path}")
|
||||
|
||||
host_map = host_ip_map(config)
|
||||
conn = sqlite3.connect(db_path)
|
||||
try:
|
||||
ensure_columns(conn)
|
||||
|
||||
cursor = conn.execute("SELECT ip, host FROM ip")
|
||||
rows = cursor.fetchall()
|
||||
|
||||
updated = 0
|
||||
skipped = 0
|
||||
for ip_address, host in rows:
|
||||
if not host:
|
||||
skipped += 1
|
||||
continue
|
||||
parent_ip = host_map.get(str(host).lower())
|
||||
if not parent_ip:
|
||||
print(f"[WARN] host sans IP config: {host} (ip {ip_address})")
|
||||
skipped += 1
|
||||
continue
|
||||
conn.execute("UPDATE ip SET ip_parent = ? WHERE ip = ?", (parent_ip, ip_address))
|
||||
updated += 1
|
||||
|
||||
print(f"[INFO] ip_parent mis à jour: {updated} | ignorés: {skipped}")
|
||||
|
||||
config_by_ip = {ip for ip in host_map.values()}
|
||||
parent_children: Dict[str, list[str]] = {}
|
||||
for ip_address, host in rows:
|
||||
host_value = (host or "").strip()
|
||||
if host_value in config_by_ip:
|
||||
parent_children.setdefault(host_value, []).append(ip_address)
|
||||
|
||||
for parent_ip in config_by_ip:
|
||||
children = parent_children.get(parent_ip, [])
|
||||
conn.execute(
|
||||
"UPDATE ip SET ip_enfant = ? WHERE ip = ?",
|
||||
(json.dumps(children), parent_ip)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
print("[INFO] ip_enfant recalculé.")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
135
backend/app/scripts/update_ip_relations.py
Normal file
135
backend/app/scripts/update_ip_relations.py
Normal file
@@ -0,0 +1,135 @@
|
||||
"""
|
||||
Met à jour la base IP avec les champs ip_parent/ip_enfant depuis config.yaml.
|
||||
Ajoute les colonnes si nécessaire et synchronise les relations.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
CONFIG_PATH = Path(__file__).resolve().parents[3] / "config.yaml"
|
||||
|
||||
|
||||
def load_config() -> Dict[str, Any]:
|
||||
with CONFIG_PATH.open("r", encoding="utf-8") as handle:
|
||||
return yaml.safe_load(handle) or {}
|
||||
|
||||
|
||||
def normalize_children(value: Any) -> Optional[List[str]]:
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, str):
|
||||
return [value] if value else []
|
||||
if isinstance(value, list):
|
||||
return [str(item) for item in value if item]
|
||||
return []
|
||||
|
||||
|
||||
def ensure_columns(conn: sqlite3.Connection) -> None:
|
||||
cursor = conn.execute("PRAGMA table_info(ip)")
|
||||
columns = {row[1] for row in cursor.fetchall()}
|
||||
if "ip_parent" not in columns:
|
||||
conn.execute("ALTER TABLE ip ADD COLUMN ip_parent TEXT")
|
||||
if "ip_enfant" not in columns:
|
||||
conn.execute("ALTER TABLE ip ADD COLUMN ip_enfant TEXT")
|
||||
conn.commit()
|
||||
|
||||
|
||||
def collect_config_mapping(config: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
|
||||
mapping: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
ip_classes = config.get("ip_classes", {}) or {}
|
||||
for ip_address, data in ip_classes.items():
|
||||
if not isinstance(data, dict):
|
||||
continue
|
||||
if "ip_parent" in data or "ip_enfant" in data:
|
||||
mapping[ip_address] = {
|
||||
"ip_parent": data.get("ip_parent"),
|
||||
"ip_enfant": normalize_children(data.get("ip_enfant"))
|
||||
}
|
||||
|
||||
for host in config.get("hosts", []) or []:
|
||||
if not isinstance(host, dict):
|
||||
continue
|
||||
ip_address = host.get("ip")
|
||||
if not ip_address:
|
||||
continue
|
||||
if "ip_parent" in host or "ip_enfant" in host:
|
||||
entry = mapping.setdefault(ip_address, {})
|
||||
entry.setdefault("ip_parent", host.get("ip_parent"))
|
||||
entry.setdefault("ip_enfant", normalize_children(host.get("ip_enfant")))
|
||||
|
||||
return mapping
|
||||
|
||||
|
||||
def parse_json_list(value: Optional[str]) -> List[str]:
|
||||
if not value:
|
||||
return []
|
||||
try:
|
||||
parsed = json.loads(value)
|
||||
except json.JSONDecodeError:
|
||||
return []
|
||||
if isinstance(parsed, list):
|
||||
return [str(item) for item in parsed if item]
|
||||
return []
|
||||
|
||||
|
||||
def main() -> None:
|
||||
config = load_config()
|
||||
db_path = Path(config.get("database", {}).get("path", "./data/db.sqlite"))
|
||||
mapping = collect_config_mapping(config)
|
||||
|
||||
if not db_path.exists():
|
||||
raise FileNotFoundError(f"Base de données introuvable: {db_path}")
|
||||
|
||||
conn = sqlite3.connect(db_path)
|
||||
try:
|
||||
ensure_columns(conn)
|
||||
|
||||
if mapping:
|
||||
for ip_address, values in mapping.items():
|
||||
ip_parent = values.get("ip_parent")
|
||||
ip_enfant = values.get("ip_enfant")
|
||||
if ip_parent is None and ip_enfant is None:
|
||||
continue
|
||||
if ip_enfant is not None:
|
||||
ip_enfant_json = json.dumps(ip_enfant)
|
||||
conn.execute(
|
||||
"UPDATE ip SET ip_parent = COALESCE(?, ip_parent), ip_enfant = ? WHERE ip = ?",
|
||||
(ip_parent, ip_enfant_json, ip_address)
|
||||
)
|
||||
else:
|
||||
conn.execute(
|
||||
"UPDATE ip SET ip_parent = COALESCE(?, ip_parent) WHERE ip = ?",
|
||||
(ip_parent, ip_address)
|
||||
)
|
||||
|
||||
cursor = conn.execute("SELECT ip, ip_parent, ip_enfant FROM ip")
|
||||
rows = cursor.fetchall()
|
||||
parent_children: Dict[str, List[str]] = {}
|
||||
|
||||
for ip_address, ip_parent, _ in rows:
|
||||
if ip_parent:
|
||||
parent_children.setdefault(ip_parent, []).append(ip_address)
|
||||
|
||||
for ip_address, _, ip_enfant_raw in rows:
|
||||
existing = parse_json_list(ip_enfant_raw)
|
||||
merged = list(dict.fromkeys(existing + parent_children.get(ip_address, [])))
|
||||
conn.execute(
|
||||
"UPDATE ip SET ip_enfant = ? WHERE ip = ?",
|
||||
(json.dumps(merged), ip_address)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
print("Mise à jour terminée.")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user