mirror of
https://github.com/hansjone/netx.git
synced 2026-10-10 08:42:32 +08:00
Allow promoting LLDP/WebCRT placeholder NEs to real device types.
Accept generic/linux on update, expose them in the device-type meta list, and auto-pick zte_zxros when vendor changes from a placeholder type. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
14251f4698
commit
48cc381afd
3 changed files with 34 additions and 6 deletions
|
|
@ -59,7 +59,10 @@ def api_list_managed_ne(
|
||||||
|
|
||||||
@router.get("/meta/device-types")
|
@router.get("/meta/device-types")
|
||||||
def api_device_types():
|
def api_device_types():
|
||||||
return {"device_types": list(SUPPORTED_DEVICE_TYPES), "vendors": list(SUPPORTED_VENDORS)}
|
# Include generic/linux so LLDP/WebCRT placeholders can be edited without a bogus select value.
|
||||||
|
from .device_types import WEBCRT_DEVICE_TYPES
|
||||||
|
|
||||||
|
return {"device_types": list(WEBCRT_DEVICE_TYPES), "vendors": list(SUPPORTED_VENDORS)}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/meta/credentials-configured")
|
@router.get("/meta/credentials-configured")
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ from fastapi import HTTPException
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from .device_types import LLDP_DISCOVERED_NE_SOURCE, SUPPORTED_DEVICE_TYPES, SUPPORTED_VENDORS
|
from .device_types import LLDP_DISCOVERED_NE_SOURCE, SUPPORTED_DEVICE_TYPES, SUPPORTED_VENDORS, WEBCRT_DEVICE_TYPES
|
||||||
from .models import ManagedNE
|
from .models import ManagedNE
|
||||||
from .ne_crypto import encrypt_secret
|
from .ne_crypto import encrypt_secret
|
||||||
from .ne_hop_templates import default_bastion_username_template, default_hop_command_template
|
from .ne_hop_templates import default_bastion_username_template, default_hop_command_template
|
||||||
|
|
@ -33,6 +33,10 @@ from .ne_service_common import (
|
||||||
row_to_out,
|
row_to_out,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Inventory create stays strict; updates must also accept WebCRT/LLDP placeholder types
|
||||||
|
# (generic/linux) so operators can open the form and promote them to zte_zxros etc.
|
||||||
|
_ALLOWED_UPDATE_DEVICE_TYPES = frozenset(WEBCRT_DEVICE_TYPES)
|
||||||
|
|
||||||
def list_managed_ne(
|
def list_managed_ne(
|
||||||
db: Session,
|
db: Session,
|
||||||
*,
|
*,
|
||||||
|
|
@ -135,9 +139,10 @@ def update_managed_ne(db: Session, ne_id: str, body: ManagedNeUpdate) -> Managed
|
||||||
raise HTTPException(status_code=400, detail="ip_address_exists")
|
raise HTTPException(status_code=400, detail="ip_address_exists")
|
||||||
row.ip_address = ip
|
row.ip_address = ip
|
||||||
if "device_type" in data:
|
if "device_type" in data:
|
||||||
if data["device_type"] not in SUPPORTED_DEVICE_TYPES:
|
dt = str(data["device_type"] or "").strip()
|
||||||
|
if dt not in _ALLOWED_UPDATE_DEVICE_TYPES:
|
||||||
raise HTTPException(status_code=400, detail="unsupported_device_type")
|
raise HTTPException(status_code=400, detail="unsupported_device_type")
|
||||||
row.device_type = data["device_type"]
|
row.device_type = dt
|
||||||
if "vendor" in data:
|
if "vendor" in data:
|
||||||
v = str(data["vendor"] or "").strip()
|
v = str(data["vendor"] or "").strip()
|
||||||
row.vendor = v if v in SUPPORTED_VENDORS else "Other"
|
row.vendor = v if v in SUPPORTED_VENDORS else "Other"
|
||||||
|
|
|
||||||
|
|
@ -410,7 +410,12 @@ export function NePage() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const vendors = metaQuery.data?.vendors ?? [];
|
const vendors = metaQuery.data?.vendors ?? [];
|
||||||
const deviceTypes = metaQuery.data?.device_types ?? [];
|
const deviceTypes = useMemo(() => {
|
||||||
|
const base = metaQuery.data?.device_types ?? [];
|
||||||
|
const cur = String(form.device_type || "").trim();
|
||||||
|
if (cur && !base.includes(cur)) return [cur, ...base];
|
||||||
|
return base;
|
||||||
|
}, [metaQuery.data?.device_types, form.device_type]);
|
||||||
const credsOk = metaQuery.data?.credentials_configured ?? false;
|
const credsOk = metaQuery.data?.credentials_configured ?? false;
|
||||||
|
|
||||||
const allSelected = useMemo(() => {
|
const allSelected = useMemo(() => {
|
||||||
|
|
@ -921,7 +926,22 @@ export function NePage() {
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<FormLabel required>{t("managedNe.col.vendor")}</FormLabel>
|
<FormLabel required>{t("managedNe.col.vendor")}</FormLabel>
|
||||||
<select required value={form.vendor} onChange={(e) => setForm({ ...form, vendor: e.target.value })}>
|
<select required value={form.vendor} onChange={(e) => {
|
||||||
|
const vendor = e.target.value;
|
||||||
|
setForm((prev) => {
|
||||||
|
const next = { ...prev, vendor };
|
||||||
|
const dt = String(prev.device_type || "").trim().toLowerCase();
|
||||||
|
// LLDP/WebCRT placeholders use generic — pick a sensible driver when vendor is set.
|
||||||
|
if (!dt || dt === "generic" || dt === "other" || dt === "linux") {
|
||||||
|
if (vendor === "ZTE") next.device_type = "zte_zxros";
|
||||||
|
else if (vendor === "Huawei") next.device_type = "huawei";
|
||||||
|
else if (vendor === "Cisco") next.device_type = "cisco_ios";
|
||||||
|
else if (vendor === "Juniper") next.device_type = "juniper_junos";
|
||||||
|
else if (vendor === "Nokia") next.device_type = "nokia_sros";
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}}>
|
||||||
{vendors.map((v) => (
|
{vendors.map((v) => (
|
||||||
<option key={v} value={v}>
|
<option key={v} value={v}>
|
||||||
{v}
|
{v}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue