From c8d2538015858eee2f3e8375219bad7eadb7fab6 Mon Sep 17 00:00:00 2001 From: dv Date: Wed, 8 Apr 2026 12:26:54 +0300 Subject: [PATCH] =?UTF-8?q?haiku=20=D0=B2=D0=B0=D0=B9=D0=B1=208?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/services/device_discovery.py | 70 +++++++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/backend/app/services/device_discovery.py b/backend/app/services/device_discovery.py index b12f003..6e8c406 100644 --- a/backend/app/services/device_discovery.py +++ b/backend/app/services/device_discovery.py @@ -506,7 +506,58 @@ async def discover_via_ssh( result.errors.append(f"SSH to {rack_host} failed: {exc}") continue + # Add the rack itself as a main_server device if it doesn't exist logger.info(f"[ssh_discovery] Processing rack {rack_host} ({rack_name})") + try: + existing_rack = (await db.execute( + select(Device).where( + Device.object_id == obj.id, + Device.ip == rack_host, + ) + )).scalar_one_or_none() + + if existing_rack is None: + rack_hostname = f"rack{rack_name}" + db.add(Device( + object_id=obj.id, + ip=rack_host, + hostname=rack_hostname, + category="embedded", + role="other", + source="auto_ssh", + )) + logger.info(f"[ssh_discovery] {rack_host} ({rack_hostname}) - ADDED: category=main_server, role=other, hostname={rack_hostname}, source=auto_ssh") + result.created += 1 + result.actions.append(DeviceAction( + ip=rack_host, + hostname=rack_hostname, + action="ADDED", + reason="rack main server discovered via SSH connection", + category="embedded", + role="other", + )) + else: + logger.info(f"[ssh_discovery] {rack_host} ({existing_rack.hostname}) - SKIPPED: rack already exists in devices") + result.skipped += 1 + result.actions.append(DeviceAction( + ip=rack_host, + hostname=existing_rack.hostname, + action="SKIPPED", + reason="rack already exists in devices", + category=existing_rack.category, + role=existing_rack.role, + )) + except Exception as exc: + logger.error(f"[ssh_discovery] {rack_host} - ERROR adding rack: {exc}") + result.errors.append(f"Error adding rack {rack_host}: {exc}") + result.actions.append(DeviceAction( + ip=rack_host, + hostname=f"rack{rack_name}", + action="ERROR", + reason=str(exc), + category="embedded", + role="other", + )) devices_found = _parse_config(config_text, rack_host) logger.info(f"[ssh_discovery] Found {len(devices_found)} devices from plugins in {rack_host}") @@ -732,6 +783,7 @@ async def discover_via_ssh( # ── 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(f"[ssh_discovery] Total actions collected: {len(result.actions)}") logger.info("=" * 100) # Group actions by status @@ -740,25 +792,27 @@ async def discover_via_ssh( skipped = [a for a in result.actions if a.action == "SKIPPED"] errors = [a for a in result.actions if a.action == "ERROR"] + logger.info(f"[ssh_discovery] Actions by type: ADDED={len(added)}, UPDATED={len(updated)}, SKIPPED={len(skipped)}, ERROR={len(errors)}") + if added: - logger.info("[ssh_discovery] ADDED devices:") + 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}") + logger.info(f" {action.ip:20} ({action.hostname:30}) | {action.category:15} | {action.role:10} | {action.reason}") if updated: - logger.info("[ssh_discovery] UPDATED devices:") + 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}") + logger.info(f" {action.ip:20} ({action.hostname:30}) | {action.category:15} | {action.role:10} | {action.reason}") if skipped: - logger.info("[ssh_discovery] SKIPPED devices:") + 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}") + logger.info(f" {action.ip:20} ({action.hostname:30}) | {action.category:15} | {action.role:10} | {action.reason}") if errors: - logger.error("[ssh_discovery] ERROR devices:") + 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.error(f" {action.ip:20} ({action.hostname:30}) | {action.category:15} | {action.role:10} | {action.reason}") logger.info("=" * 100)