mirror of
https://github.com/hansjone/netx.git
synced 2026-10-11 06:50:49 +08:00
Split UME routes and managed-NE service by domain.
Keep thin facades for existing imports, tighten CSV import required columns, and restore Chinese WebCRT connection labels in status responses. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
b03c92bdef
commit
6dc3946bc6
13 changed files with 2596 additions and 2121 deletions
177
netx_api/ume_inventory_router.py
Normal file
177
netx_api/ume_inventory_router.py
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
"""UME inventory NE list/detail."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from .config import settings
|
||||
from .db import get_db
|
||||
from .key_alert_config import (
|
||||
get_key_alert_monitor_config,
|
||||
invalidate_key_alert_config_cache,
|
||||
set_key_alert_monitor_config,
|
||||
)
|
||||
from .key_alert_matcher import (
|
||||
invalidate_key_alert_rule_cache,
|
||||
normalize_match_type,
|
||||
parse_rule_ne_types_payload,
|
||||
rule_match_type,
|
||||
rule_match_value,
|
||||
rule_ne_types,
|
||||
rule_storage_key,
|
||||
serialize_rule_ne_types,
|
||||
)
|
||||
from .models import (
|
||||
UmeAlarmCurrent,
|
||||
UmeAlarmHistory,
|
||||
UmeInventoryNE,
|
||||
UmeKeyAlertForwardLog,
|
||||
UmeKeyAlertRule,
|
||||
UmeSyncJob,
|
||||
)
|
||||
from .oclaw_alarm_forwarder import (
|
||||
forwarder_status,
|
||||
request_forwarder_reconnect,
|
||||
)
|
||||
from .ume_alarm_ws import (
|
||||
cancel_alarm_subscription_manual,
|
||||
clear_local_alarm_subscription_manual,
|
||||
establish_alarm_subscription_manual,
|
||||
get_alarms_coordination_status,
|
||||
get_subscription_status,
|
||||
get_ws_connection_status,
|
||||
get_ws_logs,
|
||||
request_ws_reconnect,
|
||||
)
|
||||
from .ume_support import (
|
||||
UME_KNOWN_RUNTIME_TASKS,
|
||||
_aggregate_rows,
|
||||
_ensure_utc,
|
||||
_list_runtime_tasks,
|
||||
_request_force_sync_after_resume,
|
||||
_runtime_pause_task,
|
||||
_runtime_resume_task,
|
||||
_ume_alarm_host_name,
|
||||
_ume_alarm_ne_group_key,
|
||||
_ume_client,
|
||||
_ume_error_kind,
|
||||
_clear_force_resume_hints,
|
||||
)
|
||||
from .ume_sync_service import sync_alarms_current, sync_alarms_history_full, sync_inventory_full
|
||||
from .ume_token_store import clear_shared_token
|
||||
|
||||
_log = logging.getLogger("netx.ume.router")
|
||||
router = APIRouter(tags=["ume"])
|
||||
|
||||
@router.get("/v1/ume/inventory/ne-types")
|
||||
def ume_list_inventory_ne_types(
|
||||
limit: int = Query(default=500, ge=1, le=2000),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict[str, Any]:
|
||||
from sqlalchemy import func
|
||||
|
||||
rows = (
|
||||
db.query(
|
||||
UmeInventoryNE.ne_type,
|
||||
func.count(UmeInventoryNE.ne_id).label("ne_count"),
|
||||
)
|
||||
.filter(UmeInventoryNE.ne_type != "")
|
||||
.group_by(UmeInventoryNE.ne_type)
|
||||
.order_by(func.count(UmeInventoryNE.ne_id).desc(), UmeInventoryNE.ne_type.asc())
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
items = [{"ne_type": str(ne_type or ""), "ne_count": int(ne_count or 0)} for ne_type, ne_count in rows if str(ne_type or "").strip()]
|
||||
return {"items": items, "total": len(items)}
|
||||
|
||||
|
||||
@router.get("/v1/ume/inventory/ne")
|
||||
def ume_list_ne(
|
||||
keyword: str | None = Query(default=None),
|
||||
page: int = Query(default=1, ge=1),
|
||||
page_size: int = Query(default=50, ge=1, le=500),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict[str, Any]:
|
||||
stmt = db.query(UmeInventoryNE)
|
||||
kw = str(keyword or "").strip()
|
||||
if kw:
|
||||
like = f"%{kw}%"
|
||||
stmt = stmt.filter(
|
||||
UmeInventoryNE.ne_id.ilike(like)
|
||||
| UmeInventoryNE.ne_name.ilike(like)
|
||||
| UmeInventoryNE.user_label.ilike(like)
|
||||
| UmeInventoryNE.ip_address.ilike(like)
|
||||
| UmeInventoryNE.host_name.ilike(like)
|
||||
)
|
||||
total = int(stmt.count())
|
||||
rows = stmt.order_by(UmeInventoryNE.ne_id.asc()).offset((page - 1) * page_size).limit(page_size).all()
|
||||
items = [
|
||||
{
|
||||
"ne_id": str(x.ne_id or ""),
|
||||
"ne_name": str(x.ne_name or ""),
|
||||
"user_label": str(x.user_label or ""),
|
||||
"ip_address": str(x.ip_address or ""),
|
||||
"ipv6_address": str(x.ipv6_address or ""),
|
||||
"ne_type": str(x.ne_type or ""),
|
||||
"device_level": str(x.device_level or ""),
|
||||
"host_name": str(x.host_name or ""),
|
||||
"location": str(x.location or ""),
|
||||
"hardware_version": str(x.hardware_version or ""),
|
||||
"loopback": str(x.loopback or ""),
|
||||
"consistent_state": str(x.consistent_state or ""),
|
||||
"interface_version": str(x.interface_version or ""),
|
||||
"mac": str(x.mac or ""),
|
||||
"admin_status": str(x.admin_status or ""),
|
||||
"address_type": str(x.address_type or ""),
|
||||
"connection_status": str(x.connection_status or ""),
|
||||
"maintain_status": str(x.maintain_status or ""),
|
||||
"net_mask": str(x.net_mask or ""),
|
||||
"create_time": str(x.create_time or ""),
|
||||
"creator": str(x.creator or ""),
|
||||
"last_seen_at": (_ensure_utc(x.last_seen_at) or datetime.now(timezone.utc)).isoformat(),
|
||||
}
|
||||
for x in rows
|
||||
]
|
||||
return {"total": total, "page": page, "page_size": page_size, "items": items}
|
||||
|
||||
|
||||
@router.get("/v1/ume/inventory/ne/{ne_id}")
|
||||
def ume_get_ne(ne_id: str, db: Session = Depends(get_db)) -> dict[str, Any]:
|
||||
row = db.get(UmeInventoryNE, ne_id)
|
||||
if not row:
|
||||
raise HTTPException(status_code=404, detail="ume_ne_not_found")
|
||||
return {
|
||||
"ne_id": str(row.ne_id or ""),
|
||||
"ne_name": str(row.ne_name or ""),
|
||||
"user_label": str(row.user_label or ""),
|
||||
"ip_address": str(row.ip_address or ""),
|
||||
"ipv6_address": str(row.ipv6_address or ""),
|
||||
"ne_type": str(row.ne_type or ""),
|
||||
"device_level": str(row.device_level or ""),
|
||||
"host_name": str(row.host_name or ""),
|
||||
"location": str(row.location or ""),
|
||||
"hardware_version": str(row.hardware_version or ""),
|
||||
"loopback": str(row.loopback or ""),
|
||||
"consistent_state": str(row.consistent_state or ""),
|
||||
"interface_version": str(row.interface_version or ""),
|
||||
"mac": str(row.mac or ""),
|
||||
"admin_status": str(row.admin_status or ""),
|
||||
"address_type": str(row.address_type or ""),
|
||||
"connection_status": str(row.connection_status or ""),
|
||||
"maintain_status": str(row.maintain_status or ""),
|
||||
"net_mask": str(row.net_mask or ""),
|
||||
"create_time": str(row.create_time or ""),
|
||||
"creator": str(row.creator or ""),
|
||||
"vendor": str(row.vendor or ""),
|
||||
"source_type": str(row.source_type or ""),
|
||||
"first_seen_at": (_ensure_utc(row.first_seen_at) or datetime.now(timezone.utc)).isoformat(),
|
||||
"last_seen_at": (_ensure_utc(row.last_seen_at) or datetime.now(timezone.utc)).isoformat(),
|
||||
"raw_json": str(row.raw_json or "{}"),
|
||||
}
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue