Files
2025-11-23 19:57:05 +01:00

155 lines
4.5 KiB
Bash

#!/bin/bash
# Set up logging
LOG_DIR="/var/log/devbench"
LOG_FILE="$LOG_DIR/provision_vm_$(date +%Y%m%d_%H%M%S).log"
# Create log directory if it doesn't exist
mkdir -p "$LOG_DIR"
chmod 777 "$LOG_DIR"
# Function to log messages
log() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] $1" | tee -a "$LOG_FILE"
}
log "Starting provision_vm.sh with arguments: $*"
# Check if enough arguments were provided for the remote script.
# The remote 'provision_vm.sh' script expects at least 2 arguments: <command> <vm_name>.
if [ "$#" -lt 2 ]; then
error_msg="Error: Please provide at least two arguments for the remote command."
log "$error_msg"
echo "Usage: $0 <command> <vm_name>"
echo "Example: $0 create username_vmname"
echo " $0 status username_vmname"
exit 1
fi
# SSH connection details
SSH_USER="asf"
SSH_HOST="asf-server.duckdns.org"
SSH_PORT="49152"
SSH_PASS="ASF"
# The path to the script on the remote server
REMOTE_SCRIPT_PATH="./provision_vm.sh"
# Get command and VM name from arguments
COMMAND="$1"
VM_NAME="$2"
# Validate command
if [[ ! "$COMMAND" =~ ^(create|status|delete|start|stop|activate)$ ]]; then
log "Error: Invalid command '$COMMAND'. Must be one of: create, status, delete, start, stop, activate"
exit 1
fi
# Validate VM name format (username_vmname)
if [[ ! "$VM_NAME" =~ ^[a-zA-Z0-9_]+_[a-zA-Z0-9_-]+$ ]]; then
log "Error: Invalid VM name format. Must be in format: username_vmname"
exit 1
fi
# Extract username from VM name (everything before first underscore)
USERNAME="${VM_NAME%%_*}"
log "Command: $COMMAND, VM: $VM_NAME, User: $USERNAME"
# Check if sshpass is available
if ! command -v sshpass &> /dev/null; then
log "Error: sshpass is not installed. Please install it with 'apt-get install sshpass'"
exit 1
fi
# Check if we can resolve the host
if ! getent hosts "$SSH_HOST" >/dev/null 2>&1; then
log "Error: Cannot resolve host $SSH_HOST"
exit 1
fi
# Create a temporary file to capture output
TEMP_OUTPUT=$(mktemp)
log "Temporary output file: $TEMP_OUTPUT"
# Function to clean up temp file
cleanup() {
if [ -f "$TEMP_OUTPUT" ]; then
rm -f "$TEMP_OUTPUT"
log "Temporary files cleaned up"
fi
}
# Set up trap to ensure cleanup happens on script exit
trap cleanup EXIT
# Build the full SSH command
SSH_CMD="ssh -p $SSH_PORT -o StrictHostKeyChecking=no -o ConnectTimeout=10 -o ServerAliveInterval=60 -o ServerAliveCountMax=30"
FULL_CMD="$REMOTE_SCRIPT_PATH $COMMAND $VM_NAME"
log "Executing remote command: $FULL_CMD"
# Execute the remote command with sshpass and capture output
{
# Increase timeout to 1800 seconds (30 minutes) and ensure we capture all output
if ! output=$(timeout 1800 sshpass -p "$SSH_PASS" $SSH_CMD "$SSH_USER@$SSH_HOST" "$FULL_CMD" 2>&1); then
EXIT_CODE=$?
# Capture any partial output even if command failed
echo "$output"
if [ $EXIT_CODE -eq 124 ]; then
log "ERROR: Command timed out after 30 minutes"
exit 124
else
log "ERROR: Command failed with exit code $EXIT_CODE"
exit $EXIT_CODE
fi
else
# Command succeeded, output the result
echo "$output"
fi
} | tee "$TEMP_OUTPUT"
# Process the output to extract connection information
SSH_PORT=""
VNC_PORT=""
VM_NAME_ACTUAL=""
# Read the output line by line to parse connection info
while IFS= read -r line; do
# Extract SSH port (e.g., "SSH Port: 6004")
if [[ $line == *"SSH Port:"* ]]; then
SSH_PORT=$(echo "$line" | grep -oE 'SSH Port: [0-9]+' | cut -d' ' -f3)
# Extract VNC port (e.g., "VNC Port: 5004")
elif [[ $line == *"VNC Port:"* ]]; then
VNC_PORT=$(echo "$line" | grep -oE 'VNC Port: [0-9]+' | cut -d' ' -f3)
# Extract VM name from success message
elif [[ $line == *"VM"*"Created and Ready"* ]]; then
VM_NAME_ACTUAL=$(echo "$line" | sed -n 's/.*VM \([^ ]*\) Created and Ready.*/\1/p')
fi
# Log each line to the log file
log "$line"
done < "$TEMP_OUTPUT"
# Output the connection information in a structured format
echo "VM_CREATION_COMPLETE"
if [ -n "$VM_NAME_ACTUAL" ]; then
echo "VM_NAME=$VM_NAME_ACTUAL"
fi
if [ -n "$SSH_PORT" ]; then
echo "SSH_PORT=$SSH_PORT"
fi
if [ -n "$VNC_PORT" ]; then
echo "VNC_PORT=$VNC_PORT"
fi
# Check if the command was successful
if [ ${PIPESTATUS[0]} -eq 0 ]; then
log "Remote command executed successfully"
exit 0
else
log "Remote command failed"
exit 1
fi
log "Provisioning script completed successfully"