Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save EduardoSantanaSeverino/c5b8bf380f23a2e442d1dcf3b6db37a2 to your computer and use it in GitHub Desktop.
Save EduardoSantanaSeverino/c5b8bf380f23a2e442d1dcf3b6db37a2 to your computer and use it in GitHub Desktop.
Proxmox Turn On Remote Server
#!/bin/bash
# This script will be run by crontab every one mint
# */1 * * * * /root/scripts/turn-on-pve1-cron/turn-on-pve1-cron.sh 2>&1
# This script will power on a remote server via Wake On Lan, but only 5 mints before the backup job is about to be executed.
# This will be reading the job file /etc/pve/jobs.cfg every time:
# On a CRON JOB every 1 mint
# check if the server is not Power On by checking the file, then
# SSH into the pve_node
# cat file: /etc/pve/jobs.cfg
# iterate loop thorough the vzdump items and for each one:
# check if enable, if NOP continue.
# check if storage pbs-blaze3-pve1, if NOP continue.
# parse schedule property, example: mon..fri 00:00.
# from date object calculate how much time is left for that to happen.
# if 5 mints or less, turn on server.
# wait for the server to be on and able to ssh.
# after waiting, create a file indicating server is up.
execution_time_print () {
local EXECUTION_TIME=$(TZ=America/Toronto date +'%Y-%m-%d %H:%M')
echo "$EXECUTION_TIME - [$1] -"
}
get_date_of_the_week () {
local lower=$(echo "$1" | tr '[:upper:]' '[:lower:]')
local day_num=0
case $lower in
mon) day_num=1;;
tue) day_num=2;;
wed) day_num=3;;
thu) day_num=4;;
fri) day_num=5;;
sat) day_num=6;;
sun) day_num=7;;
*) echo "Invalid day"; exit 1;;
esac
echo $day_num;
}
get_minutes_from_schedule () {
# TODO:
# Update function 'get_minutes_from_schedule' with schedule-analyze to get the next date instead of calculating.
# https://www.reddit.com/r/Proxmox/comments/189bde8/parse_backup_configuration_file_proxmox/
# https://pve.proxmox.com/pve-docs/api-viewer/index.html#/cluster/jobs/schedule-analyze
TZ=America/Toronto
day=$(TZ=$TZ date +"%a")
# Get the current day of the week
current_day=$(TZ=$TZ date +"%a")
# Map day names to their numerical equivalents (1=Mon, 2=Tue, ..., 7=Sun)
current_day_num=$(get_date_of_the_week $current_day)
# Map user input day names to their numerical equivalents
target_day_num=$(get_date_of_the_week $day)
# Calculate the difference in days
days_until_target=$(( (target_day_num - current_day_num + 7) % 7 ))
# Combine the date components and calculate the minutes until that time
target_date=$(TZ=$TZ date -d "$days_until_target days $1" +"%Y-%m-%d %H:%M:%S")
current_time=$(TZ=$TZ date +"%s")
target_time=$(TZ=$TZ date -d "$target_date" +"%s")
minutes_until_target=$(( (target_time - current_time) / 60 ))
# echo "Target Date and Time: $target_date"
# echo "Minutes until Target Time: $minutes_until_target"
echo $minutes_until_target
}
HOST_IP_ADDRESS_PVE1="10.10.10.10"
HOST_IP_ADDRESS_PVE2="10.10.10.11"
HOST_IP_ADDRESS_PBS="10.10.10.12"
SCRIPT_DIR='/root/scripts/turn-on-pve1-cron'
mkdir -p $SCRIPT_DIR
SCRIPT_LOG_FILE="$SCRIPT_DIR/logs.log"
SCRIPT_KEY="$SCRIPT_DIR/key.key"
SCRIPT_SERVER_EXIST="$SCRIPT_DIR/is.server.on.$HOST_IP_ADDRESS_PBS"
PID_FILE="$SCRIPT_DIR/pid.pid"
# if file exists exit... because the server is on.
if test -f "$SCRIPT_SERVER_EXIST"; then
exit 0
fi
# check the pid
if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
exit 0
fi
echo $$ > $PID_FILE
JOBS_CFG_FILE_CONTENT=$(ssh -i $SCRIPT_KEY root@$HOST_IP_ADDRESS_PVE2 'cat /etc/pve/jobs.cfg')
# Use grep to filter lines containing "enable" and store them in an array
mapfile -t JOBS_CFG_ENABLE_ITEMS < <(echo "$JOBS_CFG_FILE_CONTENT" | grep enable)
mapfile -t JOBS_CFG_SCHEDULE_ITEMS < <(echo "$JOBS_CFG_FILE_CONTENT" | grep schedule)
mapfile -t JOBS_CFG_STORAGE_ITEMS < <(echo "$JOBS_CFG_FILE_CONTENT" | grep storage)
TURN_ON_SERVER=false
# Iterate through the array using index
for ((i = 0; i < ${#JOBS_CFG_ENABLE_ITEMS[@]}; i++)); do
# For debbuging purposes to display the current job in the loop.
# echo "Element $i: ${JOBS_CFG_ENABLE_ITEMS[i]} and ${JOBS_CFG_SCHEDULE_ITEMS[i]} and ${JOBS_CFG_STORAGE_ITEMS[i]}"
# If the Job is NOT enabled
if [[ ${JOBS_CFG_ENABLE_ITEMS[i]} == *enabled* && ${JOBS_CFG_ENABLE_ITEMS[i]} == *0* ]]; then
continue; # continue Job is NOT enabled
fi
# If the storage is NOT pbs-blaze3-pve1
if [[ ${JOBS_CFG_STORAGE_ITEMS[i]} != *pbs-blaze3-pve1* ]]; then
continue; # continue the storage is NOT pbs-blaze3-pve1
fi
schedule_item=${JOBS_CFG_SCHEDULE_ITEMS[i]#* }
minutes_to_execute_job=$(get_minutes_from_schedule $schedule_item)
# Check if more than 5 minutes for the next job to be executed.
if [[ "$minutes_to_execute_job" -gt 5 || "$minutes_to_execute_job" -lt 0 ]]; then
continue; # continue becuase it is more than 5 minutes for the next job to be executed.
fi
TURN_ON_SERVER=true
echo "$(execution_time_print INFO) Starting Server -> NO: $i: ${JOBS_CFG_ENABLE_ITEMS[i]} and ${JOBS_CFG_SCHEDULE_ITEMS[i]} and ${JOBS_CFG_STORAGE_ITEMS[i]}." >> $SCRIPT_LOG_FILE
break;
done
if [[ $TURN_ON_SERVER != true ]]; then
rm $PID_FILE
exit 0
fi
echo "$(execution_time_print INFO) Senging: wakeonlan bb:bb:bb:bb:bb:bb && wakeonlan bb:bb:bb:bb:bb:bb." >> $SCRIPT_LOG_FILE
echo -n "$(execution_time_print INFO) " >> $SCRIPT_LOG_FILE
wakeonlan bb:bb:bb:bb:bb:bb >> $SCRIPT_LOG_FILE
echo -n "$(execution_time_print INFO) " >> $SCRIPT_LOG_FILE
wakeonlan bb:bb:bb:bb:bb:bb >> $SCRIPT_LOG_FILE
SUB='1 received,'
COUNTER=1
IS_UP_AND_RUNNING='false'
while [ $COUNTER -lt 60 ];
do
PING_RESULTS=$(ping $HOST_IP_ADDRESS_PBS -c 1)
if [[ "$PING_RESULTS" == *"$SUB"* ]]; then
echo "$(execution_time_print INFO) Server $HOST_IP_ADDRESS_PBS is up and running. $SUB WAS FOUND." >> $SCRIPT_LOG_FILE
IS_UP_AND_RUNNING='true'
COUNTER=60
else
echo "$(execution_time_print ERROR) Still Waiting for $HOST_IP_ADDRESS_PBS. $SUB WAS NOT FOUND." >> $SCRIPT_LOG_FILE
COUNTER=`expr $COUNTER + 1`
sleep 60
fi
done
if [[ "$IS_UP_AND_RUNNING" != 'true' ]]; then
echo "$(execution_time_print ERROR) ENDED. NOT FOUND SERVER. IS_UP_AND_RUNNING: $IS_UP_AND_RUNNING. "
rm $PID_FILE
exit 2
fi
echo "$(execution_time_print INFO) THE SERVER $HOST_IP_ADDRESS_PBS WAS POWERED ON." >> $SCRIPT_LOG_FILE
COUNTER=1
IS_UP_AND_RUNNING='false'
while [ $COUNTER -lt 60 ];
do
status=$(ssh -i $SCRIPT_KEY -o BatchMode=yes -o ConnectTimeout=5 root@$HOST_IP_ADDRESS_PBS echo ok 2>&1)
if [[ "$status" == "ok" ]]; then
echo "$(execution_time_print INFO) Server $HOST_IP_ADDRESS_PBS , YES, it is able to SSH." >> $SCRIPT_LOG_FILE
IS_UP_AND_RUNNING='true'
COUNTER=60
else
echo "$(execution_time_print ERROR) Still Waiting for $HOST_IP_ADDRESS_PBS , NO, it is NOT able to SSH" >> $SCRIPT_LOG_FILE
COUNTER=`expr $COUNTER + 1`
sleep 60
fi
done
if [[ "$IS_UP_AND_RUNNING" != 'true' ]]; then
echo "$(execution_time_print ERROR) ENDED. NOT ABLE TO SSH into SERVER $HOST_IP_ADDRESS_PBS . IS_UP_AND_RUNNING: $IS_UP_AND_RUNNING. "
rm $PID_FILE
exit 2
fi
echo "$(execution_time_print INFO) THE SERVER $HOST_IP_ADDRESS_PBS WAS POWERED ON." > $SCRIPT_SERVER_EXIST
echo "$(execution_time_print INFO) Finished Exec of Turning On Server." >> $SCRIPT_LOG_FILE
rm $PID_FILE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment