haiku Вайб 5
This commit is contained in:
parent
3adced13a0
commit
475250eb6f
1 changed files with 125 additions and 0 deletions
|
|
@ -339,12 +339,24 @@ async def _fetch_rack_hosts(dsn: str, table: str) -> list[tuple[str, str, str]]:
|
||||||
|
|
||||||
# ── Main entry point ──────────────────────────────────────────────────────────
|
# ── Main entry point ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DeviceAction:
|
||||||
|
"""Track each device discovery action for summary reporting."""
|
||||||
|
ip: str
|
||||||
|
hostname: str
|
||||||
|
action: str # "ADDED", "UPDATED", "SKIPPED", "IGNORED", "ERROR"
|
||||||
|
reason: str
|
||||||
|
category: str = ""
|
||||||
|
role: str = ""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DiscoveryResult:
|
class DiscoveryResult:
|
||||||
created: int = 0
|
created: int = 0
|
||||||
updated: int = 0
|
updated: int = 0
|
||||||
skipped: int = 0
|
skipped: int = 0
|
||||||
errors: list[str] = field(default_factory=list)
|
errors: list[str] = field(default_factory=list)
|
||||||
|
actions: list[DeviceAction] = field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
async def discover_via_ssh(
|
async def discover_via_ssh(
|
||||||
|
|
@ -514,9 +526,25 @@ async def discover_via_ssh(
|
||||||
if changes:
|
if changes:
|
||||||
logger.info(f"[ssh_discovery] {found.ip} ({found.plugin_name}) - UPDATED: {', '.join(changes)}")
|
logger.info(f"[ssh_discovery] {found.ip} ({found.plugin_name}) - UPDATED: {', '.join(changes)}")
|
||||||
result.updated += 1
|
result.updated += 1
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=found.ip,
|
||||||
|
hostname=hostname,
|
||||||
|
action="UPDATED",
|
||||||
|
reason="; ".join(changes),
|
||||||
|
category=found.category,
|
||||||
|
role=found.role,
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
logger.info(f"[ssh_discovery] {found.ip} ({found.plugin_name}) - SKIPPED: already exists with same values (source={existing.source}, category={existing.category}, role={existing.role}, hostname={existing.hostname})")
|
logger.info(f"[ssh_discovery] {found.ip} ({found.plugin_name}) - SKIPPED: already exists with same values (source={existing.source}, category={existing.category}, role={existing.role}, hostname={existing.hostname})")
|
||||||
result.skipped += 1
|
result.skipped += 1
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=found.ip,
|
||||||
|
hostname=hostname,
|
||||||
|
action="SKIPPED",
|
||||||
|
reason=f"already exists with same values (source={existing.source}, category={existing.category}, role={existing.role}, hostname={existing.hostname})",
|
||||||
|
category=existing.category,
|
||||||
|
role=existing.role,
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
db.add(Device(
|
db.add(Device(
|
||||||
object_id=obj.id,
|
object_id=obj.id,
|
||||||
|
|
@ -529,9 +557,25 @@ async def discover_via_ssh(
|
||||||
))
|
))
|
||||||
logger.info(f"[ssh_discovery] {found.ip} ({found.plugin_name}) - ADDED: category={found.category}, role={found.role}, hostname={hostname}, source=auto_ssh")
|
logger.info(f"[ssh_discovery] {found.ip} ({found.plugin_name}) - ADDED: category={found.category}, role={found.role}, hostname={hostname}, source=auto_ssh")
|
||||||
result.created += 1
|
result.created += 1
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=found.ip,
|
||||||
|
hostname=hostname,
|
||||||
|
action="ADDED",
|
||||||
|
reason=f"new device from plugin {found.plugin_name}",
|
||||||
|
category=found.category,
|
||||||
|
role=found.role,
|
||||||
|
))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error(f"[ssh_discovery] {found.ip} ({found.plugin_name}) - ERROR: {exc}")
|
logger.error(f"[ssh_discovery] {found.ip} ({found.plugin_name}) - ERROR: {exc}")
|
||||||
result.errors.append(f"Error upserting {found.ip}: {exc}")
|
result.errors.append(f"Error upserting {found.ip}: {exc}")
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=found.ip,
|
||||||
|
hostname=hostname,
|
||||||
|
action="ERROR",
|
||||||
|
reason=str(exc),
|
||||||
|
category=found.category,
|
||||||
|
role=found.role,
|
||||||
|
))
|
||||||
|
|
||||||
# Flush after each rack so that subsequent SELECTs (for other racks
|
# Flush after each rack so that subsequent SELECTs (for other racks
|
||||||
# that may share the same device IPs) see the just-added rows.
|
# that may share the same device IPs) see the just-added rows.
|
||||||
|
|
@ -563,6 +607,14 @@ async def discover_via_ssh(
|
||||||
if existing is not None:
|
if existing is not None:
|
||||||
logger.info(f"[ssh_discovery] {mikrotik_ip} (mikrotik) - SKIPPED: already exists (source={existing.source}, category={existing.category}, hostname={existing.hostname})")
|
logger.info(f"[ssh_discovery] {mikrotik_ip} (mikrotik) - SKIPPED: already exists (source={existing.source}, category={existing.category}, hostname={existing.hostname})")
|
||||||
result.skipped += 1
|
result.skipped += 1
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=mikrotik_ip,
|
||||||
|
hostname="mikrotik",
|
||||||
|
action="SKIPPED",
|
||||||
|
reason=f"already exists (source={existing.source}, category={existing.category}, hostname={existing.hostname})",
|
||||||
|
category=existing.category,
|
||||||
|
role=existing.role,
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
db.add(Device(
|
db.add(Device(
|
||||||
object_id=obj.id,
|
object_id=obj.id,
|
||||||
|
|
@ -574,9 +626,25 @@ async def discover_via_ssh(
|
||||||
))
|
))
|
||||||
logger.info(f"[ssh_discovery] {mikrotik_ip} (mikrotik) - ADDED: category=router, role=other, hostname=mikrotik, source=auto_ssh")
|
logger.info(f"[ssh_discovery] {mikrotik_ip} (mikrotik) - ADDED: category=router, role=other, hostname=mikrotik, source=auto_ssh")
|
||||||
result.created += 1
|
result.created += 1
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=mikrotik_ip,
|
||||||
|
hostname="mikrotik",
|
||||||
|
action="ADDED",
|
||||||
|
reason="discovered via SSH_CLIENT",
|
||||||
|
category="router",
|
||||||
|
role="other",
|
||||||
|
))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error(f"[ssh_discovery] {mikrotik_ip} (mikrotik) - ERROR: {exc}")
|
logger.error(f"[ssh_discovery] {mikrotik_ip} (mikrotik) - ERROR: {exc}")
|
||||||
result.errors.append(f"Error upserting {mikrotik_ip}: {exc}")
|
result.errors.append(f"Error upserting {mikrotik_ip}: {exc}")
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=mikrotik_ip,
|
||||||
|
hostname="mikrotik",
|
||||||
|
action="ERROR",
|
||||||
|
reason=str(exc),
|
||||||
|
category="router",
|
||||||
|
role="other",
|
||||||
|
))
|
||||||
|
|
||||||
await db.flush()
|
await db.flush()
|
||||||
else:
|
else:
|
||||||
|
|
@ -605,6 +673,14 @@ async def discover_via_ssh(
|
||||||
if existing is not None:
|
if existing is not None:
|
||||||
logger.info(f"[ssh_discovery] {proxmox_ip} ({hostname}) - SKIPPED: already exists (source={existing.source}, category={existing.category}, hostname={existing.hostname})")
|
logger.info(f"[ssh_discovery] {proxmox_ip} ({hostname}) - SKIPPED: already exists (source={existing.source}, category={existing.category}, hostname={existing.hostname})")
|
||||||
result.skipped += 1
|
result.skipped += 1
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=proxmox_ip,
|
||||||
|
hostname=hostname,
|
||||||
|
action="SKIPPED",
|
||||||
|
reason=f"already exists (source={existing.source}, category={existing.category}, hostname={existing.hostname})",
|
||||||
|
category=existing.category,
|
||||||
|
role=existing.role,
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
db.add(Device(
|
db.add(Device(
|
||||||
object_id=obj.id,
|
object_id=obj.id,
|
||||||
|
|
@ -616,12 +692,61 @@ async def discover_via_ssh(
|
||||||
))
|
))
|
||||||
logger.info(f"[ssh_discovery] {proxmox_ip} ({hostname}) - ADDED: category=vm, role=other, hostname={hostname}, source=auto_ssh")
|
logger.info(f"[ssh_discovery] {proxmox_ip} ({hostname}) - ADDED: category=vm, role=other, hostname={hostname}, source=auto_ssh")
|
||||||
result.created += 1
|
result.created += 1
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=proxmox_ip,
|
||||||
|
hostname=hostname,
|
||||||
|
action="ADDED",
|
||||||
|
reason="discovered via port 8006 scan",
|
||||||
|
category="vm",
|
||||||
|
role="other",
|
||||||
|
))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error(f"[ssh_discovery] {proxmox_ip} ({hostname}) - ERROR: {exc}")
|
logger.error(f"[ssh_discovery] {proxmox_ip} ({hostname}) - ERROR: {exc}")
|
||||||
result.errors.append(f"Error upserting {proxmox_ip}: {exc}")
|
result.errors.append(f"Error upserting {proxmox_ip}: {exc}")
|
||||||
|
result.actions.append(DeviceAction(
|
||||||
|
ip=proxmox_ip,
|
||||||
|
hostname=hostname,
|
||||||
|
action="ERROR",
|
||||||
|
reason=str(exc),
|
||||||
|
category="vm",
|
||||||
|
role="other",
|
||||||
|
))
|
||||||
|
|
||||||
await db.flush()
|
await db.flush()
|
||||||
else:
|
else:
|
||||||
logger.info(f"[ssh_discovery] Proxmox: No servers found via port 8006 scan (reason: no hosts responding on port 8006)")
|
logger.info(f"[ssh_discovery] Proxmox: No servers found via port 8006 scan (reason: no hosts responding on port 8006)")
|
||||||
|
|
||||||
|
# ── Summary Report ─────────────────────────────────────────────────────────────
|
||||||
|
logger.info("=" * 100)
|
||||||
|
logger.info(f"[ssh_discovery] SUMMARY: ADDED={result.created}, UPDATED={result.updated}, SKIPPED={result.skipped}, ERRORS={len(result.errors)}")
|
||||||
|
logger.info("=" * 100)
|
||||||
|
|
||||||
|
# Group actions by status
|
||||||
|
added = [a for a in result.actions if a.action == "ADDED"]
|
||||||
|
updated = [a for a in result.actions if a.action == "UPDATED"]
|
||||||
|
skipped = [a for a in result.actions if a.action == "SKIPPED"]
|
||||||
|
errors = [a for a in result.actions if a.action == "ERROR"]
|
||||||
|
|
||||||
|
if added:
|
||||||
|
logger.info("[ssh_discovery] ADDED devices:")
|
||||||
|
for action in added:
|
||||||
|
logger.info(f" {action.ip:20} ({action.hostname:30}) | category={action.category:15} role={action.role:10} | Reason: {action.reason}")
|
||||||
|
|
||||||
|
if updated:
|
||||||
|
logger.info("[ssh_discovery] UPDATED devices:")
|
||||||
|
for action in updated:
|
||||||
|
logger.info(f" {action.ip:20} ({action.hostname:30}) | category={action.category:15} role={action.role:10} | Reason: {action.reason}")
|
||||||
|
|
||||||
|
if skipped:
|
||||||
|
logger.info("[ssh_discovery] SKIPPED devices:")
|
||||||
|
for action in skipped:
|
||||||
|
logger.info(f" {action.ip:20} ({action.hostname:30}) | category={action.category:15} role={action.role:10} | Reason: {action.reason}")
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
logger.error("[ssh_discovery] ERROR devices:")
|
||||||
|
for action in errors:
|
||||||
|
logger.error(f" {action.ip:20} ({action.hostname:30}) | category={action.category:15} role={action.role:10} | Reason: {action.reason}")
|
||||||
|
|
||||||
|
logger.info("=" * 100)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue