|
#!/bin/bash |
|
# Create Hetzner virtual server snapshots |
|
# Version 1.2 (build 20190723) |
|
# |
|
# Copyright (C) 2017-2019 Daniel Rudolf <www.daniel-rudolf.de> |
|
# |
|
# This program is free software: you can redistribute it and/or modify |
|
# it under the terms of the GNU General Public License as published by |
|
# the Free Software Foundation, version 3 of the License only. |
|
# |
|
# This program is distributed in the hope that it will be useful, |
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
# GNU General Public License for more details. |
|
# |
|
# See <http://www.gnu.org/licenses/> to receive a full-text-copy of |
|
# the GNU General Public License. |
|
|
|
APP_NAME="$(basename "$0")" |
|
set -e |
|
|
|
VERSION="1.2" |
|
BUILD="20190723" |
|
|
|
if [ ! -e /etc/hetzner_api ]; then |
|
echo "$APP_NAME: Unable to read Hetzner API credentials from '/etc/hetzner_api': No such file or directory" >&2 |
|
exit 1 |
|
elif [ ! -f /etc/hetzner_api ]; then |
|
echo "$APP_NAME: Unable to read Hetzner API credentials from '/etc/hetzner_api': Not a regular file" >&2 |
|
exit 1 |
|
elif [ ! -r /etc/hetzner_api ]; then |
|
echo "$APP_NAME: Unable to read Hetzner API credentials from '/etc/hetzner_api': Permission denied" >&2 |
|
exit 1 |
|
fi |
|
|
|
. /etc/hetzner_api |
|
. /usr/local/lib/hetzner_api/lib.sh |
|
|
|
print_usage() { |
|
echo "Usage:" |
|
echo " $APP_NAME [--latest|--oldest] IP_ADDRESS" |
|
} |
|
|
|
# read parameters |
|
SERVER_IP="" |
|
SNAPSHOT_SELECT="latest" |
|
|
|
while [ $# -gt 0 ]; do |
|
if [ "$1" == "--oldest" ] || [ "$1" == "-o" ]; then |
|
SNAPSHOT_SELECT="oldest" |
|
elif [ "$1" == "--latest" ] || [ "$1" == "-l" ]; then |
|
SNAPSHOT_SELECT="latest" |
|
elif [ "$1" == "--help" ] || [ "$1" == "-h" ]; then |
|
print_usage |
|
echo |
|
echo "Application options:" |
|
echo " -l, --latest replace the server's latest snapshot (default)" |
|
echo " -o, --oldest replace the server's oldest snapshot" |
|
echo |
|
echo "Help options:" |
|
echo " -h, --help display this help and exit" |
|
echo " --version output version information and exit" |
|
exit 0 |
|
elif [ "$1" == "--version" ]; then |
|
echo "hetzner-snapshot.sh $VERSION ($BUILD)" |
|
echo "Copyright (C) 2017-2019 Daniel Rudolf" |
|
echo "License GPLv3: GNU GPL version 3 only <http://gnu.org/licenses/gpl.html>." |
|
echo "This is free software: you are free to change and redistribute it." |
|
echo "There is NO WARRANTY, to the extent permitted by law." |
|
echo |
|
echo "Written by Daniel Rudolf <http://www.daniel-rudolf.de/>" |
|
exit 0 |
|
elif [ -z "$SERVER_IP" ]; then |
|
if ! [[ "$1" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then |
|
echo "$APP_NAME: Invalid IP address specified" >&2 |
|
exit 1 |
|
fi |
|
|
|
SERVER_IP="$1" |
|
else |
|
print_usage >&2 |
|
exit 1 |
|
fi |
|
|
|
shift |
|
done |
|
|
|
if [ -z "$SERVER_IP" ]; then |
|
print_usage >&2 |
|
exit 1 |
|
fi |
|
|
|
# function: returns the latest or oldest snapshot |
|
get_snapshot() { |
|
local SNAPSHOT="" |
|
local SNAPSHOT_RESPOSNE="" |
|
|
|
hetzner_api_call --output-var SNAPSHOT_RESPONSE --show-error "GET" "/snapshot/$SERVER_IP" >&2 |
|
|
|
SNAPSHOT="$(echo "$SNAPSHOT_RESPONSE" | php -r ' |
|
$json = json_decode(stream_get_contents(STDIN), true); |
|
if (is_array($json)) { |
|
if (empty($json)) { |
|
exit(0); |
|
} |
|
|
|
$json = (isset($_SERVER["argv"]) && ($_SERVER["argv"] === "--latest")) ? array_reverse($json) : $json; |
|
foreach ($json as $item) { |
|
if (isset($item["snapshot"]) && ($item["snapshot"]["type"] === "snapshot")) { |
|
echo $item["snapshot"]["id"]; |
|
exit(0); |
|
} |
|
} |
|
} |
|
|
|
exit(1); |
|
' -- "--$SNAPSHOT_SELECT")" |
|
|
|
if [ $? -ne 0 ]; then |
|
echo "$APP_NAME: Hetzner API call 'GET /snapshot/$SERVER_IP' failed: Invalid JSON response: $SNAPSHOT_RESPONSE" >&2 |
|
exit 1 |
|
fi |
|
|
|
if [ -n "$SNAPSHOT" ]; then |
|
echo "$SNAPSHOT" |
|
return 0 |
|
fi |
|
|
|
return 1 |
|
} |
|
|
|
# get list of existing snapshots |
|
echo "Retrieving list of snapshots..." |
|
SNAPSHOT="$(get_snapshot || true)" |
|
|
|
# delete the latest snapshot |
|
if [ -n "$SNAPSHOT" ]; then |
|
echo -n "Deleting $SNAPSHOT_SELECT snapshot" |
|
hetzner_api_call --show-error "DELETE" "/snapshot/$SERVER_IP/$SNAPSHOT" |
|
|
|
# deleting a snapshot might take some time |
|
for (( i=1 ; i < 100 ; i++ )); do |
|
echo -n "." |
|
if [ $(($i % 3)) -ne 0 ]; then |
|
sleep 3 |
|
elif [ "$(get_snapshot || true)" != "$SNAPSHOT" ]; then |
|
break |
|
fi |
|
done |
|
echo |
|
|
|
if [ $i -eq 100 ]; then |
|
echo "$APP_NAME: Unable to delete latest snapshot" >&2 |
|
exit 1 |
|
fi |
|
fi |
|
|
|
# create a new snapshot |
|
echo "Creating snapshot..." |
|
hetzner_api_call --show-error "POST" "/snapshot/$SERVER_IP" |
Hi @PhrozenByte, thank you for your reply. Below I'm pasting the echoed command thats being executed. If you need any additional information please let me know. Thank you for your time and effort.
curl --silent --show-error --dump-header /tmp/tmp.CotZnMioDq --output /tmp/tmp.wrnHMrZHhV --user hetzner-api-username:hetzner-api-password --request GET https://robot-ws.your-server.de/snapshot/XX.XX.XXX.XXX