2025-10-19 20:41:09 +00:00
|
|
|
import { BaseMigration } from './base-migration.ts';
|
|
|
|
import { logger } from '../logger.ts';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Migration from v3 (upsList) to v4 (upsDevices)
|
|
|
|
*
|
2025-10-19 21:32:55 +00:00
|
|
|
* Transforms v3 format with flat SNMP config:
|
2025-10-19 20:41:09 +00:00
|
|
|
* {
|
2025-10-19 21:32:55 +00:00
|
|
|
* upsList: [
|
|
|
|
* {
|
|
|
|
* id: "ups-1",
|
|
|
|
* name: "UPS 1",
|
|
|
|
* host: "192.168.1.1",
|
|
|
|
* port: 161,
|
|
|
|
* community: "public",
|
|
|
|
* version: "1" // string
|
|
|
|
* }
|
|
|
|
* ]
|
2025-10-19 20:41:09 +00:00
|
|
|
* }
|
|
|
|
*
|
2025-10-19 21:32:55 +00:00
|
|
|
* To v4 format with nested SNMP config:
|
2025-10-19 20:41:09 +00:00
|
|
|
* {
|
|
|
|
* version: "4.0",
|
2025-10-19 21:32:55 +00:00
|
|
|
* 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: []
|
|
|
|
* }
|
|
|
|
* ]
|
2025-10-19 20:41:09 +00:00
|
|
|
* }
|
|
|
|
*/
|
|
|
|
export class MigrationV3ToV4 extends BaseMigration {
|
|
|
|
readonly order = 4;
|
|
|
|
readonly fromVersion = '3.x';
|
|
|
|
readonly toVersion = '4.0';
|
|
|
|
|
|
|
|
async shouldRun(config: any): Promise<boolean> {
|
2025-10-19 21:41:50 +00:00
|
|
|
// 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)
|
|
|
|
if (config.upsDevices && config.upsDevices.length > 0) {
|
|
|
|
const firstDevice = config.upsDevices[0];
|
|
|
|
// V3 has host at top level, v4 has it nested in snmp object
|
|
|
|
return !!firstDevice.host && !firstDevice.snmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2025-10-19 20:41:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async migrate(config: any): Promise<any> {
|
2025-10-19 21:32:55 +00:00
|
|
|
logger.info(`${this.getName()}: Migrating v3 config to v4 format...`);
|
|
|
|
logger.dim(` - Restructuring UPS devices (flat → nested snmp config)`);
|
|
|
|
|
2025-10-19 21:41:50 +00:00
|
|
|
// Get devices from either upsList or upsDevices (for partially migrated configs)
|
|
|
|
const sourceDevices = config.upsList || config.upsDevices;
|
|
|
|
|
2025-10-19 21:32:55 +00:00
|
|
|
// Transform each UPS device from v3 flat structure to v4 nested structure
|
2025-10-19 21:41:50 +00:00
|
|
|
const transformedDevices = sourceDevices.map((device: any) => {
|
2025-10-19 21:32:55 +00:00
|
|
|
// Build SNMP config object
|
|
|
|
const snmpConfig: any = {
|
|
|
|
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 || [],
|
|
|
|
};
|
|
|
|
});
|
2025-10-19 20:41:09 +00:00
|
|
|
|
|
|
|
const migrated = {
|
|
|
|
version: this.toVersion,
|
2025-10-19 21:32:55 +00:00
|
|
|
upsDevices: transformedDevices,
|
2025-10-19 20:41:09 +00:00
|
|
|
groups: config.groups || [],
|
|
|
|
checkInterval: config.checkInterval || 30000,
|
|
|
|
};
|
|
|
|
|
2025-10-19 21:32:55 +00:00
|
|
|
logger.success(`${this.getName()}: Migration complete (${transformedDevices.length} devices transformed)`);
|
2025-10-19 20:41:09 +00:00
|
|
|
return migrated;
|
|
|
|
}
|
|
|
|
}
|