mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 11:50:44 +08:00
feat(ne): connect detail, Huawei/Cisco hop, Cisco hostname probe
Persist full connect test logs (connect_detail) with NE UI detail modal. Add Huawei/Cisco jump CLI templates and generic CLI hop session path. Probe Cisco hostname via show configuration | include hostname (60s timeout). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
778442dc57
commit
dc17f9d15a
15 changed files with 457 additions and 63 deletions
|
|
@ -1,26 +1,43 @@
|
|||
import { isAutoHopTemplate, zteHopTemplate } from "./zteHop";
|
||||
/** Jump-host (hop) templates per vendor. */
|
||||
|
||||
export type HopVendor = "zte" | "linux";
|
||||
import { ciscoHopTemplate, huaweiHopTemplate, isAutoHopTemplate, zteHopTemplate } from "./zteHop";
|
||||
|
||||
export const HOP_VENDORS: HopVendor[] = ["zte", "linux"];
|
||||
export type HopVendor = "zte" | "huawei" | "cisco" | "linux";
|
||||
|
||||
export const HOP_VENDORS: HopVendor[] = ["zte", "huawei", "cisco", "linux"];
|
||||
|
||||
export function isLinuxHopVendor(vendor: string): boolean {
|
||||
return String(vendor || "").toLowerCase() === "linux";
|
||||
}
|
||||
|
||||
export function isCliHopVendor(vendor: string): boolean {
|
||||
const v = String(vendor || "").toLowerCase();
|
||||
return v === "zte" || v === "huawei" || v === "cisco";
|
||||
}
|
||||
|
||||
export function defaultHopTemplate(vendor: string, protocol: string, vrf: string): string {
|
||||
const v = String(vendor || "zte").toLowerCase();
|
||||
if (v === "huawei") return huaweiHopTemplate(protocol, vrf);
|
||||
if (v === "cisco") return ciscoHopTemplate(protocol, vrf);
|
||||
if (v === "linux") return "";
|
||||
return zteHopTemplate(protocol, vrf);
|
||||
}
|
||||
|
||||
export function patchHopVendorChange(
|
||||
vendor: HopVendor,
|
||||
prev: { hop_protocol: string; hop_vrf: string; hop_command_template: string },
|
||||
prev: { hop_protocol: string; hop_vrf: string; hop_command_template: string; hop_vendor?: string },
|
||||
): { hop_vendor: HopVendor; hop_protocol: string; hop_vrf: string; hop_command_template: string } {
|
||||
if (vendor === "linux") {
|
||||
return { hop_vendor: "linux", hop_protocol: "ssh", hop_vrf: "", hop_command_template: "" };
|
||||
}
|
||||
const protocol = prev.hop_protocol || "ssh";
|
||||
const vrf = prev.hop_vrf || "";
|
||||
return {
|
||||
hop_vendor: "zte",
|
||||
hop_protocol: prev.hop_protocol || "ssh",
|
||||
hop_vrf: prev.hop_vrf,
|
||||
hop_command_template: zteHopTemplate(prev.hop_protocol || "ssh", prev.hop_vrf),
|
||||
hop_vendor: vendor,
|
||||
hop_protocol: protocol,
|
||||
hop_vrf: vrf,
|
||||
hop_command_template: defaultHopTemplate(vendor, protocol, vrf),
|
||||
};
|
||||
}
|
||||
|
||||
export { isAutoHopTemplate, zteHopTemplate };
|
||||
export { ciscoHopTemplate, huaweiHopTemplate, isAutoHopTemplate, zteHopTemplate };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/** ZTE device CLI jump commands: ssh/telnet <ip> [vrf <name>]. */
|
||||
/** Vendor CLI jump command templates (placeholders). */
|
||||
|
||||
const LEGACY_HOP_TEMPLATES = new Set([
|
||||
"ssh {target_user}@{target_ip}",
|
||||
|
|
@ -12,8 +12,35 @@ export function zteHopTemplate(protocol: string, vrf: string): string {
|
|||
return v ? `${cmd} {target_ip} vrf {vrf}` : `${cmd} {target_ip}`;
|
||||
}
|
||||
|
||||
export function isAutoHopTemplate(template: string, protocol: string, vrf: string): boolean {
|
||||
/** Cisco: ssh -vrf VRF IP; telnet IP [/vrf VRF]. */
|
||||
export function ciscoHopTemplate(protocol: string, vrf: string): string {
|
||||
const v = String(vrf || "").trim();
|
||||
if (String(protocol || "ssh").toLowerCase() === "telnet") {
|
||||
return v ? `telnet {target_ip} /vrf {vrf}` : `telnet {target_ip}`;
|
||||
}
|
||||
return v ? `ssh -vrf {vrf} {target_ip}` : `ssh {target_ip}`;
|
||||
}
|
||||
|
||||
/** Huawei: telnet [vpn-instance VRF] IP; SSH uses stelnet. */
|
||||
export function huaweiHopTemplate(protocol: string, vrf: string): string {
|
||||
const v = String(vrf || "").trim();
|
||||
if (String(protocol || "ssh").toLowerCase() === "telnet") {
|
||||
return v ? `telnet vpn-instance {vrf} {target_ip}` : `telnet {target_ip}`;
|
||||
}
|
||||
return v ? `stelnet {target_ip} -vpn-instance {vrf}` : `stelnet {target_ip}`;
|
||||
}
|
||||
|
||||
export function isAutoHopTemplate(
|
||||
template: string,
|
||||
vendor: string,
|
||||
protocol: string,
|
||||
vrf: string,
|
||||
): boolean {
|
||||
const t = String(template || "").trim();
|
||||
if (!t || LEGACY_HOP_TEMPLATES.has(t)) return true;
|
||||
const v = String(vendor || "zte").toLowerCase();
|
||||
if (v === "huawei") return t === huaweiHopTemplate(protocol, vrf);
|
||||
if (v === "cisco") return t === ciscoHopTemplate(protocol, vrf);
|
||||
if (v === "linux") return t === "";
|
||||
return t === zteHopTemplate(protocol, vrf);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue