Files
SenMeshNet/electron/bridges/inspection/deviceStore.cjs

291 lines
7.5 KiB
JavaScript
Raw Normal View History

"use strict";
/**
* 设备扩展数据存储(巡检相关配置)
*
* 关联 NetMesh 的主机数据,扩展巡检相关字段:
* - 设备类型(catalog_id)
* - 设备层级(core/aggregation/access)
* - 巡检周期
* - 启用状态
* - 自定义告警阈值
* - 上次巡检信息
*
* 周期优先级(从高到低):
* 1. 设备独立设置 inspection_interval
* 2. 设备层级的默认周期 DEVICE_TIER_DEFAULT_INTERVAL
* 3. 系统默认周期 SYS_CONFIG_DEFAULTS.inspection_default_interval
*/
const {
STORAGE_KEY_DEVICE_EXTENSION,
STORAGE_KEY_SYS_CONFIG,
} = require("./storageKeys.cjs");
const {
DEVICE_TIERS,
DEVICE_TIER_LABELS,
DEVICE_TIER_DEFAULT_INTERVAL,
SYS_CONFIG_DEFAULTS,
} = require("./types.cjs");
const { getPresetCatalog } = require("./deviceCatalogStore.cjs");
// ---------- 内存缓存 ----------
let _extensions = null; // { [hostId]: { ... } }
let _sysConfig = null; // { inspection_default_interval: 5, ... }
let _catalog = null; // 设备类型列表
/**
* 从存储加载数据(首次调用时加载,之后用缓存)
* @param {function} readFn - 读取函数 (key) => rawString
*/
function _ensureLoaded(readFn) {
if (_extensions === null) {
const raw = readFn(STORAGE_KEY_DEVICE_EXTENSION);
_extensions = raw ? _safeParse(raw, {}) : {};
}
if (_sysConfig === null) {
const raw = readFn(STORAGE_KEY_SYS_CONFIG);
_sysConfig = raw ? _safeParse(raw, {}) : { ...SYS_CONFIG_DEFAULTS };
// 合并默认值
for (const k of Object.keys(SYS_CONFIG_DEFAULTS)) {
if (_sysConfig[k] === undefined) _sysConfig[k] = SYS_CONFIG_DEFAULTS[k];
}
}
if (_catalog === null) {
_catalog = getPresetCatalog();
}
}
function _safeParse(text, def) {
if (text === null || text === undefined) return def;
let parsed;
try { parsed = JSON.parse(text); }
catch (e) { return def; }
// 防御二次/三次 stringify:inspectionStorage.writeStorage 先 JSON.stringify 一次,
// _save 又 JSON.stringify 一次 → 文件里值是 "\"{...}\"" 这种嵌套字符串
// 连续 parse 直到拿到真正的对象/数组(最多 3 层避免死循环)
let depth = 0;
while (typeof parsed === "string" && parsed.length > 0 && depth < 3) {
let next;
try { next = JSON.parse(parsed); } catch { break; }
if (typeof next === "string" && next === parsed) break;
parsed = next;
depth++;
}
return (parsed !== null && typeof parsed === "object") ? parsed : def;
}
function _save(writeFn, key, data) {
writeFn(key, JSON.stringify(data));
}
// ---------- 系统配置 ----------
/**
* 获取系统配置
*/
function getSysConfig(readFn) {
_ensureLoaded(readFn);
return { ..._sysConfig };
}
/**
* 更新系统配置
*/
function updateSysConfig(readFn, writeFn, updates) {
_ensureLoaded(readFn);
_sysConfig = { ..._sysConfig, ...updates };
_save(writeFn, STORAGE_KEY_SYS_CONFIG, _sysConfig);
return { ..._sysConfig };
}
// ---------- 设备扩展 ----------
/**
* 获取所有设备扩展配置
*/
function getAllExtensions(readFn) {
_ensureLoaded(readFn);
return { ..._extensions };
}
/**
* 获取单个设备的扩展配置
*/
function getExtension(readFn, hostId) {
_ensureLoaded(readFn);
return _extensions[hostId] || null;
}
/**
* 创建/更新设备扩展配置
* @param {string} hostId - NetMesh 主机 ID
* @param {object} data - 扩展配置
* @param {string} data.catalog_id - 设备类型 ID
* @param {string} [data.tier] - 设备层级 core/aggregation/access
* @param {number} [data.inspection_interval] - 巡检周期(分钟),null 表示继承
* @param {boolean} [data.inspection_enabled] - 是否启用巡检
* @param {object} [data.custom_thresholds] - 自定义告警阈值
* @param {string[]} [data.inspection_tags] - 巡检标签
* @param {string} [data.hostname] - 主机名(IP 或域名),用于调度器关联 vault host SSH 配置
*/
function upsertExtension(readFn, writeFn, hostId, data) {
_ensureLoaded(readFn);
const existing = _extensions[hostId] || {
host_id: hostId,
hostname: null,
catalog_id: "",
tier: null,
inspection_interval: null,
inspection_enabled: false,
custom_thresholds: [],
inspection_tags: [],
last_scan_at: null,
last_scan_status: null,
last_scan_error: null,
};
_extensions[hostId] = {
...existing,
...data,
updated_at: Date.now(),
};
_save(writeFn, STORAGE_KEY_DEVICE_EXTENSION, _extensions);
return { ..._extensions[hostId] };
}
/**
* 删除设备扩展配置
*/
function deleteExtension(readFn, writeFn, hostId) {
_ensureLoaded(readFn);
if (_extensions[hostId]) {
delete _extensions[hostId];
_save(writeFn, STORAGE_KEY_DEVICE_EXTENSION, _extensions);
return true;
}
return false;
}
/**
* 计算设备的实际巡检周期(考虑三级继承)
* @param {string} hostId
* @returns {number} 周期(分钟)
*/
function getEffectiveInterval(readFn, hostId) {
_ensureLoaded(readFn);
const ext = _extensions[hostId];
if (!ext) return _sysConfig.inspection_default_interval;
// 1. 设备独立设置
if (typeof ext.inspection_interval === "number" && ext.inspection_interval > 0) {
return ext.inspection_interval;
}
// 2. 设备层级默认
if (ext.tier && DEVICE_TIER_DEFAULT_INTERVAL[ext.tier]) {
return DEVICE_TIER_DEFAULT_INTERVAL[ext.tier];
}
// 3. 系统默认
return _sysConfig.inspection_default_interval;
}
/**
* 获取所有启用了巡检的设备列表(带有效周期)
*/
function getEnabledDevices(readFn) {
_ensureLoaded(readFn);
const result = [];
for (const hostId of Object.keys(_extensions)) {
const ext = _extensions[hostId];
if (ext.inspection_enabled) {
result.push({
...ext,
effective_interval: getEffectiveInterval(readFn, hostId),
});
}
}
return result;
}
/**
* 更新上次巡检信息
*/
function updateLastScan(readFn, writeFn, hostId, status, error = null) {
_ensureLoaded(readFn);
if (!_extensions[hostId]) return false;
_extensions[hostId].last_scan_at = Date.now();
_extensions[hostId].last_scan_status = status;
_extensions[hostId].last_scan_error = error;
_save(writeFn, STORAGE_KEY_DEVICE_EXTENSION, _extensions);
return true;
}
// ---------- 设备类型 ----------
/**
* 获取设备类型列表
*/
function getCatalog() {
if (_catalog === null) {
_catalog = getPresetCatalog();
}
return [..._catalog];
}
/**
* 根据 ID 获取设备类型
*/
function getCatalogById(catalogId) {
const list = getCatalog();
return list.find((c) => c.id === catalogId) || null;
}
// ---------- 设备层级 ----------
/**
* 获取设备层级列表(带中文名称和默认周期)
*/
function getTiers() {
return [
{ key: DEVICE_TIERS.CORE, label: DEVICE_TIER_LABELS.core, default_interval: DEVICE_TIER_DEFAULT_INTERVAL.core },
{ key: DEVICE_TIERS.AGGREGATION, label: DEVICE_TIER_LABELS.aggregation, default_interval: DEVICE_TIER_DEFAULT_INTERVAL.aggregation },
{ key: DEVICE_TIERS.ACCESS, label: DEVICE_TIER_LABELS.access, default_interval: DEVICE_TIER_DEFAULT_INTERVAL.access },
];
}
// ---------- 重置(测试用) ----------
function _resetForTest() {
_extensions = null;
_sysConfig = null;
_catalog = null;
}
module.exports = {
// 系统配置
getSysConfig,
updateSysConfig,
// 设备扩展
getAllExtensions,
getExtension,
upsertExtension,
deleteExtension,
getEffectiveInterval,
getEnabledDevices,
updateLastScan,
// 设备类型
getCatalog,
getCatalogById,
// 设备层级
getTiers,
// 内部
_resetForTest,
};