mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 02:00:46 +08:00
Skip LLDP placeholder NEs from discovery until credentials are filled.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
90bd323115
commit
2cbdc896f6
2 changed files with 38 additions and 31 deletions
|
|
@ -7,6 +7,7 @@ from fastapi import HTTPException
|
|||
from sqlalchemy.orm import Session
|
||||
|
||||
from .cli_resolve import get_default_profile, infer_device_type_vendor
|
||||
from .device_types import LLDP_DISCOVERED_NE_SOURCE
|
||||
from .models import ManagedNE, TopoDiscoverJob, TopoDiscoverJobItem, UmeInventoryNE
|
||||
from .topology_common import _RAW_PREVIEW_MAX
|
||||
from .topology_schemas import (
|
||||
|
|
@ -24,6 +25,22 @@ def _raw_preview(raw: str, *, limit: int = _RAW_PREVIEW_MAX) -> str:
|
|||
return f"{text[:limit]}\n...[truncated preview {limit}/{len(text)} chars]"
|
||||
|
||||
|
||||
def _is_lldp_placeholder_ne(ne: ManagedNE) -> bool:
|
||||
"""LLDP SSH placeholders have no credentials until the operator promotes them."""
|
||||
return str(ne.source or "").strip().lower() in {LLDP_DISCOVERED_NE_SOURCE, "lldp"}
|
||||
|
||||
|
||||
def _managed_target_dict(ne: ManagedNE) -> dict[str, str]:
|
||||
return {
|
||||
"ne_id": ne.id,
|
||||
"ume_ne_id": "",
|
||||
"ne_name": ne.name or "",
|
||||
"ne_ip": ne.ip_address or "",
|
||||
"vendor": ne.vendor or "",
|
||||
"device_type": ne.device_type or "",
|
||||
}
|
||||
|
||||
|
||||
def _job_out(
|
||||
db: Session,
|
||||
job: TopoDiscoverJob,
|
||||
|
|
@ -138,21 +155,15 @@ def _resolve_scan_targets(
|
|||
targets: list[dict[str, str]] = []
|
||||
if scope == "all_inventory":
|
||||
# Managed inventory first; then UME NEs not already covered by the same management IP.
|
||||
# Skip LLDP placeholders (no login yet); once promoted they join normal inventory.
|
||||
managed_ips: set[str] = set()
|
||||
for ne in db.query(ManagedNE).all():
|
||||
if _is_lldp_placeholder_ne(ne):
|
||||
continue
|
||||
ip = str(ne.ip_address or "").strip()
|
||||
if ip:
|
||||
managed_ips.add(ip)
|
||||
targets.append(
|
||||
{
|
||||
"ne_id": ne.id,
|
||||
"ume_ne_id": "",
|
||||
"ne_name": ne.name or "",
|
||||
"ne_ip": ne.ip_address or "",
|
||||
"vendor": ne.vendor or "",
|
||||
"device_type": ne.device_type or "",
|
||||
}
|
||||
)
|
||||
targets.append(_managed_target_dict(ne))
|
||||
for ume in db.query(UmeInventoryNE).all():
|
||||
uid = str(ume.ne_id or "").strip()
|
||||
if not uid:
|
||||
|
|
@ -173,19 +184,10 @@ def _resolve_scan_targets(
|
|||
if mid in seen:
|
||||
continue
|
||||
ne = db.get(ManagedNE, mid)
|
||||
if ne is None:
|
||||
if ne is None or _is_lldp_placeholder_ne(ne):
|
||||
continue
|
||||
seen.add(mid)
|
||||
targets.append(
|
||||
{
|
||||
"ne_id": ne.id,
|
||||
"ume_ne_id": "",
|
||||
"ne_name": ne.name or "",
|
||||
"ne_ip": ne.ip_address or "",
|
||||
"vendor": ne.vendor or "",
|
||||
"device_type": ne.device_type or "",
|
||||
}
|
||||
)
|
||||
targets.append(_managed_target_dict(ne))
|
||||
for uid in ume_ids:
|
||||
key = f"ume:{uid}"
|
||||
if key in seen:
|
||||
|
|
@ -206,17 +208,10 @@ def _resolve_scan_targets(
|
|||
for mid in list(filter_ids):
|
||||
ne = db.get(ManagedNE, mid)
|
||||
if ne is not None:
|
||||
targets.append(
|
||||
{
|
||||
"ne_id": ne.id,
|
||||
"ume_ne_id": "",
|
||||
"ne_name": ne.name or "",
|
||||
"ne_ip": ne.ip_address or "",
|
||||
"vendor": ne.vendor or "",
|
||||
"device_type": ne.device_type or "",
|
||||
}
|
||||
)
|
||||
filter_ids.discard(mid)
|
||||
if _is_lldp_placeholder_ne(ne):
|
||||
continue
|
||||
targets.append(_managed_target_dict(ne))
|
||||
for uid in list(filter_ids):
|
||||
row = _ume_target_dict(db, uid, default_profile)
|
||||
if row is not None:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from datetime import datetime, timedelta
|
|||
from uuid import uuid4
|
||||
|
||||
from netx_api.db import Base, SessionLocal, engine
|
||||
from netx_api.device_types import LLDP_DISCOVERED_NE_SOURCE
|
||||
from netx_api.lldp_collect_schemas import LldpCollectPolicyUpdate
|
||||
from netx_api.lldp_collect_service import (
|
||||
build_discover_request,
|
||||
|
|
@ -255,6 +256,14 @@ class LldpCollectTests(unittest.TestCase):
|
|||
device_type="cisco_ios",
|
||||
ip_address="10.20.30.1",
|
||||
)
|
||||
placeholder = ManagedNE(
|
||||
id=f"ph-{suffix}",
|
||||
name=f"PH-{suffix}",
|
||||
vendor="Other",
|
||||
device_type="generic",
|
||||
ip_address="",
|
||||
source=LLDP_DISCOVERED_NE_SOURCE,
|
||||
)
|
||||
ume_only = UmeInventoryNE(
|
||||
ne_id=f"u-{suffix}",
|
||||
ne_name=f"U-{suffix}",
|
||||
|
|
@ -271,6 +280,7 @@ class LldpCollectTests(unittest.TestCase):
|
|||
ne_type="ZXCTN",
|
||||
)
|
||||
self.db.add(managed)
|
||||
self.db.add(placeholder)
|
||||
self.db.add(ume_only)
|
||||
self.db.add(ume_dup)
|
||||
self.db.commit()
|
||||
|
|
@ -280,9 +290,11 @@ class LldpCollectTests(unittest.TestCase):
|
|||
self.assertIn((managed.id, ""), ids)
|
||||
self.assertIn((ume_only.ne_id, ume_only.ne_id), ids)
|
||||
self.assertNotIn((ume_dup.ne_id, ume_dup.ne_id), ids)
|
||||
self.assertNotIn((placeholder.id, ""), ids)
|
||||
|
||||
# Cleanup shared DB rows created by this test.
|
||||
self.db.delete(managed)
|
||||
self.db.delete(placeholder)
|
||||
self.db.delete(ume_only)
|
||||
self.db.delete(ume_dup)
|
||||
self.db.commit()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue