Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
a87710144c | |||
23fd5cc5cd | |||
fb4d776bdd |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@serve.zone/nupst",
|
"name": "@serve.zone/nupst",
|
||||||
"version": "4.0.3",
|
"version": "4.0.5",
|
||||||
"exports": "./mod.ts",
|
"exports": "./mod.ts",
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"dev": "deno run --allow-all mod.ts",
|
"dev": "deno run --allow-all mod.ts",
|
||||||
|
88
install.sh
88
install.sh
@@ -10,15 +10,7 @@
|
|||||||
# With version specification:
|
# With version specification:
|
||||||
# curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- --version v4.0.0
|
# curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- --version v4.0.0
|
||||||
#
|
#
|
||||||
# Non-interactive mode (auto-confirm):
|
|
||||||
# curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y
|
|
||||||
#
|
|
||||||
# Downloaded script:
|
|
||||||
# curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh -o nupst-install.sh
|
|
||||||
# sudo bash nupst-install.sh
|
|
||||||
#
|
|
||||||
# Options:
|
# Options:
|
||||||
# -y, --yes Automatically answer yes to all prompts
|
|
||||||
# -h, --help Show this help message
|
# -h, --help Show this help message
|
||||||
# --version VERSION Install specific version (e.g., v4.0.0)
|
# --version VERSION Install specific version (e.g., v4.0.0)
|
||||||
# --install-dir DIR Installation directory (default: /opt/nupst)
|
# --install-dir DIR Installation directory (default: /opt/nupst)
|
||||||
@@ -26,7 +18,6 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Default values
|
# Default values
|
||||||
AUTO_YES=0
|
|
||||||
SHOW_HELP=0
|
SHOW_HELP=0
|
||||||
SPECIFIED_VERSION=""
|
SPECIFIED_VERSION=""
|
||||||
INSTALL_DIR="/opt/nupst"
|
INSTALL_DIR="/opt/nupst"
|
||||||
@@ -36,10 +27,6 @@ GITEA_REPO="serve.zone/nupst"
|
|||||||
# Parse command line arguments
|
# Parse command line arguments
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
-y|--yes)
|
|
||||||
AUTO_YES=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-h|--help)
|
-h|--help)
|
||||||
SHOW_HELP=1
|
SHOW_HELP=1
|
||||||
shift
|
shift
|
||||||
@@ -67,7 +54,6 @@ if [ $SHOW_HELP -eq 1 ]; then
|
|||||||
echo "Usage: $0 [options]"
|
echo "Usage: $0 [options]"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " -y, --yes Automatically answer yes to all prompts"
|
|
||||||
echo " -h, --help Show this help message"
|
echo " -h, --help Show this help message"
|
||||||
echo " --version VERSION Install specific version (e.g., v4.0.0)"
|
echo " --version VERSION Install specific version (e.g., v4.0.0)"
|
||||||
echo " --install-dir DIR Installation directory (default: /opt/nupst)"
|
echo " --install-dir DIR Installation directory (default: /opt/nupst)"
|
||||||
@@ -78,9 +64,6 @@ if [ $SHOW_HELP -eq 1 ]; then
|
|||||||
echo ""
|
echo ""
|
||||||
echo " # Install specific version"
|
echo " # Install specific version"
|
||||||
echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- --version v4.0.0"
|
echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- --version v4.0.0"
|
||||||
echo ""
|
|
||||||
echo " # Non-interactive installation"
|
|
||||||
echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y"
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -90,32 +73,6 @@ if [ "$EUID" -ne 0 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Detect if script is being piped or run directly
|
|
||||||
INTERACTIVE=1
|
|
||||||
if [ ! -t 0 ] || [ ! -t 1 ]; then
|
|
||||||
# Either stdin or stdout is not a terminal
|
|
||||||
if [ $AUTO_YES -ne 1 ]; then
|
|
||||||
echo "Script detected it's running in a non-interactive environment without -y flag."
|
|
||||||
echo "Attempting to find a controlling terminal for interactive prompts..."
|
|
||||||
# Try to use a controlling terminal for user input
|
|
||||||
exec < /dev/tty 2>/dev/null || INTERACTIVE=0
|
|
||||||
|
|
||||||
if [ $INTERACTIVE -eq 0 ]; then
|
|
||||||
echo "ERROR: No controlling terminal available for interactive prompts."
|
|
||||||
echo ""
|
|
||||||
echo "For interactive installation (RECOMMENDED):"
|
|
||||||
echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh -o nupst-install.sh"
|
|
||||||
echo " sudo bash nupst-install.sh"
|
|
||||||
echo ""
|
|
||||||
echo "For non-interactive installation with auto-confirm:"
|
|
||||||
echo " curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "Interactive terminal found, continuing with prompts..."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Helper function to detect OS and architecture
|
# Helper function to detect OS and architecture
|
||||||
detect_platform() {
|
detect_platform() {
|
||||||
local os=$(uname -s)
|
local os=$(uname -s)
|
||||||
@@ -225,22 +182,6 @@ if [ -d "$INSTALL_DIR" ]; then
|
|||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $AUTO_YES -eq 0 ] && [ $INTERACTIVE -eq 1 ]; then
|
|
||||||
if [ $OLD_NODE_INSTALL -eq 1 ]; then
|
|
||||||
echo "This will replace your Node.js installation with a pre-compiled binary."
|
|
||||||
echo "Your configuration in /etc/nupst/config.json will be preserved."
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
echo "Installation directory already exists: $INSTALL_DIR"
|
|
||||||
echo "Do you want to update/reinstall? (Y/n): "
|
|
||||||
read -r update_confirm
|
|
||||||
|
|
||||||
if [[ "$update_confirm" =~ ^[Nn]$ ]]; then
|
|
||||||
echo "Installation cancelled."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Updating existing installation at $INSTALL_DIR..."
|
echo "Updating existing installation at $INSTALL_DIR..."
|
||||||
|
|
||||||
# Check if service exists (enabled or running) and stop it if active
|
# Check if service exists (enabled or running) and stop it if active
|
||||||
@@ -269,17 +210,6 @@ if [ -d "$INSTALL_DIR" ]; then
|
|||||||
echo "Old installation files removed."
|
echo "Old installation files removed."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ $AUTO_YES -eq 0 ] && [ $INTERACTIVE -eq 1 ]; then
|
|
||||||
echo "NUPST will be installed to: $INSTALL_DIR"
|
|
||||||
echo "Continue? (Y/n): "
|
|
||||||
read -r install_confirm
|
|
||||||
|
|
||||||
if [[ "$install_confirm" =~ ^[Nn]$ ]]; then
|
|
||||||
echo "Installation cancelled."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Creating installation directory: $INSTALL_DIR"
|
echo "Creating installation directory: $INSTALL_DIR"
|
||||||
mkdir -p "$INSTALL_DIR"
|
mkdir -p "$INSTALL_DIR"
|
||||||
fi
|
fi
|
||||||
@@ -325,22 +255,8 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Create symlink for global access
|
# Create symlink for global access
|
||||||
if [ $AUTO_YES -eq 0 ] && [ $INTERACTIVE -eq 1 ]; then
|
ln -sf "$BINARY_PATH" "$BIN_DIR/nupst"
|
||||||
echo "Create symlink in $BIN_DIR for global access? (Y/n): "
|
echo "Symlink created: $BIN_DIR/nupst -> $BINARY_PATH"
|
||||||
read -r symlink_confirm
|
|
||||||
|
|
||||||
if [[ ! "$symlink_confirm" =~ ^[Nn]$ ]]; then
|
|
||||||
ln -sf "$BINARY_PATH" "$BIN_DIR/nupst"
|
|
||||||
echo "Symlink created: $BIN_DIR/nupst -> $BINARY_PATH"
|
|
||||||
else
|
|
||||||
echo "Symlink creation skipped."
|
|
||||||
echo "To use NUPST, run: $BINARY_PATH"
|
|
||||||
echo "Or manually create symlink: sudo ln -sf $BINARY_PATH $BIN_DIR/nupst"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
ln -sf "$BINARY_PATH" "$BIN_DIR/nupst"
|
|
||||||
echo "Symlink created: $BIN_DIR/nupst -> $BINARY_PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
16
readme.md
16
readme.md
@@ -29,15 +29,8 @@ dependencies.
|
|||||||
The easiest way to install NUPST is using the automated installer:
|
The easiest way to install NUPST is using the automated installer:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Download and run installer (most reliable)
|
# One-line installation
|
||||||
curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh -o nupst-install.sh
|
curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash
|
||||||
sudo bash nupst-install.sh
|
|
||||||
rm nupst-install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# One-line installation (non-interactive with auto-confirm)
|
|
||||||
curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The installer will:
|
The installer will:
|
||||||
@@ -76,7 +69,6 @@ sudo mv nupst /usr/local/bin/nupst
|
|||||||
The installer script (`install.sh`) supports the following options:
|
The installer script (`install.sh`) supports the following options:
|
||||||
|
|
||||||
```
|
```
|
||||||
-y, --yes Automatically answer yes to all prompts
|
|
||||||
-h, --help Show help message
|
-h, --help Show help message
|
||||||
--version VERSION Install specific version (e.g., --version v4.0.0)
|
--version VERSION Install specific version (e.g., --version v4.0.0)
|
||||||
--install-dir DIR Custom installation directory (default: /opt/nupst)
|
--install-dir DIR Custom installation directory (default: /opt/nupst)
|
||||||
@@ -373,7 +365,7 @@ sudo nupst service disable
|
|||||||
Re-run the installer to update to the latest version:
|
Re-run the installer to update to the latest version:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y
|
curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
The installer will:
|
The installer will:
|
||||||
@@ -461,7 +453,7 @@ The installer script automatically handles the entire migration while preserving
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run the installer (handles stop/update/restart automatically)
|
# Run the installer (handles stop/update/restart automatically)
|
||||||
curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash -s -- -y
|
curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | sudo bash
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
nupst service status
|
nupst service status
|
||||||
|
168
test/manualdocker/00-test-fresh-v4-install.sh
Executable file
168
test/manualdocker/00-test-fresh-v4-install.sh
Executable file
@@ -0,0 +1,168 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Test fresh v4 installation from scratch
|
||||||
|
# Tests the most common user scenario: clean install using curl | bash
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CONTAINER_NAME="nupst-test-fresh-v4"
|
||||||
|
|
||||||
|
echo "================================================"
|
||||||
|
echo " NUPST Fresh v4 Installation Test"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if container already exists
|
||||||
|
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
||||||
|
echo "⚠️ Container ${CONTAINER_NAME} already exists"
|
||||||
|
read -p "Remove and recreate? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "→ Stopping and removing existing container..."
|
||||||
|
docker stop ${CONTAINER_NAME} 2>/dev/null || true
|
||||||
|
docker rm ${CONTAINER_NAME} 2>/dev/null || true
|
||||||
|
else
|
||||||
|
echo "Exiting. Remove manually with: docker rm -f ${CONTAINER_NAME}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "→ Creating Docker container with systemd..."
|
||||||
|
docker run -d \
|
||||||
|
--name ${CONTAINER_NAME} \
|
||||||
|
--privileged \
|
||||||
|
--cgroupns=host \
|
||||||
|
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
|
||||||
|
ubuntu:22.04 \
|
||||||
|
/bin/bash -c "apt-get update && apt-get install -y systemd systemd-sysv && exec /sbin/init"
|
||||||
|
|
||||||
|
echo "→ Waiting for systemd to initialize..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
echo "→ Waiting for dpkg lock to be released..."
|
||||||
|
docker exec ${CONTAINER_NAME} bash -c "
|
||||||
|
while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do
|
||||||
|
echo ' Waiting for dpkg lock...'
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo ' dpkg lock released'
|
||||||
|
"
|
||||||
|
|
||||||
|
echo "→ Installing prerequisites (curl)..."
|
||||||
|
docker exec ${CONTAINER_NAME} bash -c "
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y -qq curl
|
||||||
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Installing NUPST v4 using curl | bash..."
|
||||||
|
echo " Command: curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | bash -s -- -y"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
docker exec ${CONTAINER_NAME} bash -c "
|
||||||
|
curl -sSL https://code.foss.global/serve.zone/nupst/raw/branch/main/install.sh | bash -s -- -y
|
||||||
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "================================================"
|
||||||
|
echo " Verifying Installation"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "→ Checking binary location..."
|
||||||
|
docker exec ${CONTAINER_NAME} bash -c "
|
||||||
|
if [ -f /opt/nupst/nupst ]; then
|
||||||
|
echo ' ✓ Binary exists at /opt/nupst/nupst'
|
||||||
|
ls -lh /opt/nupst/nupst
|
||||||
|
else
|
||||||
|
echo ' ✗ Binary not found at /opt/nupst/nupst'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Checking symlink..."
|
||||||
|
docker exec ${CONTAINER_NAME} bash -c "
|
||||||
|
if [ -L /usr/local/bin/nupst ]; then
|
||||||
|
echo ' ✓ Symlink exists at /usr/local/bin/nupst'
|
||||||
|
ls -lh /usr/local/bin/nupst
|
||||||
|
elif [ -L /usr/bin/nupst ]; then
|
||||||
|
echo ' ✓ Symlink exists at /usr/bin/nupst'
|
||||||
|
ls -lh /usr/bin/nupst
|
||||||
|
else
|
||||||
|
echo ' ✗ Symlink not found in /usr/local/bin or /usr/bin'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Checking PATH integration..."
|
||||||
|
docker exec ${CONTAINER_NAME} bash -c "
|
||||||
|
NUPST_PATH=\$(which nupst 2>/dev/null)
|
||||||
|
if [ -n \"\$NUPST_PATH\" ]; then
|
||||||
|
echo ' ✓ nupst found in PATH at: '\$NUPST_PATH
|
||||||
|
else
|
||||||
|
echo ' ✗ nupst not found in PATH'
|
||||||
|
echo ' PATH contents:'
|
||||||
|
echo \$PATH
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Testing nupst command execution..."
|
||||||
|
docker exec ${CONTAINER_NAME} nupst --version
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Creating minimal config for service test..."
|
||||||
|
docker exec ${CONTAINER_NAME} bash -c "
|
||||||
|
mkdir -p /etc/nupst
|
||||||
|
cat > /etc/nupst/config.json << 'EOF'
|
||||||
|
{
|
||||||
|
\"version\": \"4.0\",
|
||||||
|
\"upsDevices\": [],
|
||||||
|
\"groups\": [],
|
||||||
|
\"checkInterval\": 30000
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo ' ✓ Minimal config created'
|
||||||
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Testing service creation..."
|
||||||
|
docker exec ${CONTAINER_NAME} bash -c "
|
||||||
|
echo ' Running: nupst service enable'
|
||||||
|
nupst service enable
|
||||||
|
|
||||||
|
if [ -f /etc/systemd/system/nupst.service ]; then
|
||||||
|
echo ' ✓ Service file created successfully'
|
||||||
|
else
|
||||||
|
echo ' ✗ Service file creation failed'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "→ Checking if service is enabled..."
|
||||||
|
docker exec ${CONTAINER_NAME} systemctl is-enabled nupst
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "================================================"
|
||||||
|
echo " ✓ Fresh v4 Installation Test Complete"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
echo "Installation verified successfully:"
|
||||||
|
echo " • Binary installed to /opt/nupst/nupst"
|
||||||
|
echo " • Symlink created for global access"
|
||||||
|
echo " • nupst command available in PATH"
|
||||||
|
echo " • Command executes correctly"
|
||||||
|
echo " • Systemd service file created"
|
||||||
|
echo ""
|
||||||
|
echo "Useful commands:"
|
||||||
|
echo " docker exec -it ${CONTAINER_NAME} bash"
|
||||||
|
echo " docker exec ${CONTAINER_NAME} nupst --help"
|
||||||
|
echo " docker exec ${CONTAINER_NAME} nupst service status"
|
||||||
|
echo " docker stop ${CONTAINER_NAME}"
|
||||||
|
echo " docker rm -f ${CONTAINER_NAME}"
|
||||||
|
echo ""
|
@@ -4,19 +4,38 @@ import { logger } from '../logger.ts';
|
|||||||
/**
|
/**
|
||||||
* Migration from v3 (upsList) to v4 (upsDevices)
|
* Migration from v3 (upsList) to v4 (upsDevices)
|
||||||
*
|
*
|
||||||
* Detects v3 format:
|
* Transforms v3 format with flat SNMP config:
|
||||||
* {
|
* {
|
||||||
* upsList: [ ... ],
|
* upsList: [
|
||||||
* groups: [ ... ],
|
* {
|
||||||
* checkInterval: 30000
|
* id: "ups-1",
|
||||||
|
* name: "UPS 1",
|
||||||
|
* host: "192.168.1.1",
|
||||||
|
* port: 161,
|
||||||
|
* community: "public",
|
||||||
|
* version: "1" // string
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* Converts to:
|
* To v4 format with nested SNMP config:
|
||||||
* {
|
* {
|
||||||
* version: "4.0",
|
* version: "4.0",
|
||||||
* upsDevices: [ ... ], // renamed from upsList
|
* upsDevices: [
|
||||||
* groups: [ ... ],
|
* {
|
||||||
* checkInterval: 30000
|
* 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 {
|
export class MigrationV3ToV4 extends BaseMigration {
|
||||||
@@ -25,21 +44,76 @@ export class MigrationV3ToV4 extends BaseMigration {
|
|||||||
readonly toVersion = '4.0';
|
readonly toVersion = '4.0';
|
||||||
|
|
||||||
async shouldRun(config: any): Promise<boolean> {
|
async shouldRun(config: any): Promise<boolean> {
|
||||||
// V3 format has upsList instead of upsDevices
|
// V3 format has upsList OR has upsDevices with flat structure (host at top level)
|
||||||
return !!config.upsList && !config.upsDevices;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
async migrate(config: any): Promise<any> {
|
async migrate(config: any): Promise<any> {
|
||||||
logger.info(`${this.getName()}: Renaming upsList to upsDevices...`);
|
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;
|
||||||
|
|
||||||
|
// Transform each UPS device from v3 flat structure to v4 nested structure
|
||||||
|
const transformedDevices = sourceDevices.map((device: any) => {
|
||||||
|
// 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 || [],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const migrated = {
|
const migrated = {
|
||||||
version: this.toVersion,
|
version: this.toVersion,
|
||||||
upsDevices: config.upsList, // Rename upsList → upsDevices
|
upsDevices: transformedDevices,
|
||||||
groups: config.groups || [],
|
groups: config.groups || [],
|
||||||
checkInterval: config.checkInterval || 30000,
|
checkInterval: config.checkInterval || 30000,
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.success(`${this.getName()}: Migration complete`);
|
logger.success(`${this.getName()}: Migration complete (${transformedDevices.length} devices transformed)`);
|
||||||
return migrated;
|
return migrated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user