feat: 新增设备巡检模块实现完整的巡检告警功能

新增设备巡检模块核心功能,包括:
- 巡检数据存储与调度系统
- 华为/H3C交换机及Linux服务器采集器
- 设备扩展配置与告警规则管理
- 主机详情页巡检配置入口
- 产品名称自定义设置功能
- 网络设备SSH exec通道兼容处理
This commit is contained in:
2026-10-09 10:37:48 +08:00
parent 9202506c46
commit c64e00d835
75 changed files with 12087 additions and 446 deletions

View File

@@ -0,0 +1,173 @@
"use strict";
/**
* Prompt 解析器 - 从命令输出中提取指标
*
* 分层策略:
* 1. 正则匹配(快,简单场景够用)
* 2. 返回原始输出(解析失败时让用户看原始数据)
*/
/**
* 华为/H3C 交换机命令解析配置
*/
const HUAWEI_H3C_PATTERNS = {
cpu_usage: {
// CPU 使用率:多种可能的格式
patterns: [
/CPU\s+Usage\s*:\s*(\d+)%/i,
/CPU\s+utilization.*one\s+minute:\s*(\d+)%/i,
/CPU\s+Usage\s+:\s*(\d+)%/i,
],
default: null,
},
memory_usage: {
// 内存使用率:多种格式
patterns: [
/Memory\s+Using\s+Percentage\s+Is:\s*(\d+)%/i,
/Memory\s+utilization.*:\s*(\d+)%/i,
],
default: null,
},
};
/**
* 解析单行指标
* @param {string} output - 命令原始输出
* @param {object} config - { patterns: RegExp[], default: any }
* @returns {any} 解析结果
*/
function parseMetric(output, config) {
if (!output || !config?.patterns) return config?.default ?? null;
for (const pattern of config.patterns) {
const match = output.match(pattern);
if (match) {
return parseFloat(match[1]);
}
}
return config.default ?? null;
}
/**
* 解析端口状态
* @param {string} output - 命令输出
* @returns {object} { up_count, down_count, ports }
*/
function parseInterfaceBrief(output) {
const lines = output.split("\n");
const ports = [];
let upCount = 0;
let downCount = 0;
for (const line of lines) {
// 匹配端口行:GigabitEthernet0/0/1 up up
const portMatch = line.match(/^(GigabitEthernet|FastEthernet|Ethernet)(\S+)\s+(\w+)\s+(\w+)/);
if (portMatch) {
const phy = portMatch[3].toLowerCase();
const proto = portMatch[4].toLowerCase();
ports.push({
name: portMatch[1] + portMatch[2],
phy,
protocol: proto,
is_up: phy === "up" && proto === "up",
});
if (phy === "up") upCount++;
else downCount++;
}
}
return { up_count: upCount, down_count: downCount, ports };
}
/**
* 解析电源状态
* @param {string} output - 命令输出
* @returns {object} { normal_count, abnormal_count }
*/
function parsePowerStatus(output) {
const lines = output.split("\n");
let normalCount = 0;
let abnormalCount = 0;
for (const line of lines) {
// 匹配电源状态行
if (/Normal|Supply|OK/i.test(line)) {
normalCount++;
} else if (/Absent|Fault|Error/i.test(line)) {
abnormalCount++;
}
}
return { normal_count: normalCount, abnormal_count: abnormalCount };
}
/**
* 清理交换机输出
* @param {string} output - 原始输出
* @returns {string} 清理后的输出
*/
function cleanOutput(output) {
return output
// 移除提示符
.replace(/<\w+[-A-Za-z0-9]*>/g, "")
// 移除分页标记
.replace(/---- More ----/g, "")
// 移除命令回显
.replace(/^[^\r\n]*\r?\n/, "")
// 移除空行
.replace(/\n{3,}/g, "\n\n")
.trim();
}
/**
* 使用 prompt 风格解析交换机输出
* @param {string} output - 原始命令输出
* @param {object} context - { catalog_id, device_info }
* @returns {object} 结构化指标
*/
function parseSwitchOutput(output, context = {}) {
const cleaned = cleanOutput(output);
const lines = cleaned.split("\n");
const metrics = {
cpu_usage: null,
memory_usage: null,
port_status: [],
power_status: [],
fan_status: [],
};
// 解析 CPU
metrics.cpu_usage = parseMetric(cleaned, HUAWEI_H3C_PATTERNS.cpu_usage);
// 解析内存
metrics.memory_usage = parseMetric(cleaned, HUAWEI_H3C_PATTERNS.memory_usage);
// 解析端口
metrics.port_status = parseInterfaceBrief(cleaned);
// 解析电源
metrics.power_status = parsePowerStatus(cleaned);
// 原始输出(便于调试)
metrics._raw_output = cleaned;
metrics._parse_errors = [];
if (metrics.cpu_usage === null) {
metrics._parse_errors.push("cpu_usage: 无法解析");
}
if (metrics.memory_usage === null) {
metrics._parse_errors.push("memory_usage: 无法解析");
}
return metrics;
}
module.exports = {
parseMetric,
parseInterfaceBrief,
parsePowerStatus,
cleanOutput,
parseSwitchOutput,
};