122 lines
3.7 KiB
TypeScript
122 lines
3.7 KiB
TypeScript
import { BaseMigration } from './base-migration.ts';
|
|
import { logger } from '../logger.ts';
|
|
|
|
/**
|
|
* Migration from v3 (upsList) to v4 (upsDevices)
|
|
*
|
|
* Transforms v3 format with flat SNMP config:
|
|
* {
|
|
* upsList: [
|
|
* {
|
|
* id: "ups-1",
|
|
* name: "UPS 1",
|
|
* host: "192.168.1.1",
|
|
* port: 161,
|
|
* community: "public",
|
|
* version: "1" // string
|
|
* }
|
|
* ]
|
|
* }
|
|
*
|
|
* To v4 format with nested SNMP config:
|
|
* {
|
|
* version: "4.0",
|
|
* upsDevices: [
|
|
* {
|
|
* id: "ups-1",
|
|
* name: "UPS 1",
|
|
* snmp: {
|
|
* host: "192.168.1.1",
|
|
* port: 161,
|
|
* community: "public",
|
|
* version: 1, // number
|
|
* timeout: 5000
|
|
* },
|
|
* thresholds: { battery: 60, runtime: 20 },
|
|
* groups: []
|
|
* }
|
|
* ]
|
|
* }
|
|
*/
|
|
export class MigrationV3ToV4 extends BaseMigration {
|
|
readonly fromVersion = '3.x';
|
|
readonly toVersion = '4.0';
|
|
|
|
shouldRun(config: Record<string, unknown>): boolean {
|
|
// V3 format has upsList OR has upsDevices with flat structure (host at top level)
|
|
if (config.upsList && !config.upsDevices) {
|
|
return true; // Classic v3 with upsList
|
|
}
|
|
|
|
// Check if upsDevices exists but has flat structure (v3 format)
|
|
const upsDevices = config.upsDevices as Array<Record<string, unknown>> | undefined;
|
|
if (upsDevices && upsDevices.length > 0) {
|
|
const firstDevice = upsDevices[0];
|
|
// V3 has host at top level, v4 has it nested in snmp object
|
|
return !!firstDevice.host && !firstDevice.snmp;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
migrate(config: Record<string, unknown>): Record<string, unknown> {
|
|
logger.info(`${this.getName()}: Migrating v3 config to v4 format...`);
|
|
logger.dim(` - Restructuring UPS devices (flat → nested snmp config)`);
|
|
|
|
// Get devices from either upsList or upsDevices (for partially migrated configs)
|
|
const sourceDevices = (config.upsList || config.upsDevices) as Array<Record<string, unknown>>;
|
|
|
|
// Transform each UPS device from v3 flat structure to v4 nested structure
|
|
const transformedDevices = sourceDevices.map((device: Record<string, unknown>) => {
|
|
// Build SNMP config object
|
|
const snmpConfig: Record<string, unknown> = {
|
|
host: device.host,
|
|
port: device.port || 161,
|
|
version: typeof device.version === 'string' ? parseInt(device.version, 10) : device.version,
|
|
timeout: device.timeout || 5000,
|
|
};
|
|
|
|
// Add SNMPv1/v2c fields
|
|
if (device.community) {
|
|
snmpConfig.community = device.community;
|
|
}
|
|
|
|
// Add SNMPv3 fields
|
|
if (device.securityLevel) snmpConfig.securityLevel = device.securityLevel;
|
|
if (device.username) snmpConfig.username = device.username;
|
|
if (device.authProtocol) snmpConfig.authProtocol = device.authProtocol;
|
|
if (device.authKey) snmpConfig.authKey = device.authKey;
|
|
if (device.privProtocol) snmpConfig.privProtocol = device.privProtocol;
|
|
if (device.privKey) snmpConfig.privKey = device.privKey;
|
|
|
|
// Add UPS model if present
|
|
if (device.upsModel) snmpConfig.upsModel = device.upsModel;
|
|
if (device.customOIDs) snmpConfig.customOIDs = device.customOIDs;
|
|
|
|
// Return v4 format with nested structure
|
|
return {
|
|
id: device.id,
|
|
name: device.name,
|
|
snmp: snmpConfig,
|
|
thresholds: device.thresholds || {
|
|
battery: 60,
|
|
runtime: 20,
|
|
},
|
|
groups: device.groups || [],
|
|
};
|
|
});
|
|
|
|
const migrated = {
|
|
version: this.toVersion,
|
|
upsDevices: transformedDevices,
|
|
groups: config.groups || [],
|
|
checkInterval: config.checkInterval || 30000,
|
|
};
|
|
|
|
logger.success(
|
|
`${this.getName()}: Migration complete (${transformedDevices.length} devices transformed)`,
|
|
);
|
|
return migrated;
|
|
}
|
|
}
|