Last active
August 23, 2018 17:40
-
-
Save codymoorhouse/4acce9133664f7fdeb8625a060bae68c to your computer and use it in GitHub Desktop.
Creates a digital ocean snapshot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
################################################################################# | |
# Default Options # | |
################################################################################# | |
DEFAULT_NAME = "Snapshot - " + str(datetime.now().now()) | |
DEFAULT_ALLOWED_SNAPSHOTS = 7 | |
DEFAULT_DATA_CONSISTENCY_MODE = False | |
################################################################################# | |
# Executing / Args # | |
################################################################################# | |
# python3 do-snapshot.py -d droplet_id -t token # | |
# # | |
# Defaults: # | |
# -d, --droplet-id=droplet_id # | |
# The droplet id from digital ocean. In the digital ocean UI, click on # | |
# a droplet and the droplet id will be in the URL. # | |
# -t, --token=token # | |
# The access token from digital ocean. This is generated in the # | |
# digital ocean UI through the API settings. # | |
# # | |
# Optionals: # | |
# -a, --allowed-snapshots=max_allowed_snapshots # | |
# This will lock the amount of snapshots, removing the old extras. # | |
# -c, --consistency-mode # | |
# Powers off droplet before creating snapshot. # | |
# -h, --help # | |
# Print a help message and exit. # | |
# -n, --name=name # | |
# Specify the name of the snapshot to save as. # | |
################################################################################# | |
################################################################################# | |
# DO NOT TOUCH # | |
################################################################################# | |
import getopt | |
import json | |
import sys | |
import requests | |
import time | |
from datetime import datetime | |
def main(argv): | |
global ACCESS_TOKEN, BASE_URL, DROPLET_ID, DROPLET_NAME, HEADERS, ACTION_URL, ALLOWED_SNAPSHOTS, DATA_CONSISTENCY_MODE | |
validate_getopts(argv); | |
BASE_URL = "https://api.digitalocean.com/v2" | |
HEADERS = { | |
"Content-Type": "application/json", | |
"Authorization": "Bearer " + ACCESS_TOKEN | |
} | |
ACTION_URL = BASE_URL + '/droplets/' + DROPLET_ID + '/actions' | |
if (DATA_CONSISTENCY_MODE): | |
set_power("power_off") | |
create_action_info = create_snapshot(DROPLET_NAME) | |
action_info = get_action(create_action_info["action"]["id"]) | |
while (action_info["action"]["status"] != "completed" and action_info["action"]["status"] != "errored"): | |
time.sleep(3) | |
action_info = get_action(create_action_info["action"]["id"]) | |
if (action_info["action"]["status"] == "completed"): | |
print("Snapshot successfully created") | |
purge_snapshots(ALLOWED_SNAPSHOTS) | |
else: | |
print("Snapshot could not be created, an error has occurred") | |
if (DATA_CONSISTENCY_MODE): | |
set_power("power_on") | |
def purge_snapshots(amount): | |
response = get_snapshots(); | |
if (response["meta"]["total"] > int(amount)): | |
snapshots = response["snapshots"] | |
purge_amount = response["meta"]["total"] - int(amount) | |
while (len(snapshots) > 0 and purge_amount > 0): | |
delete_snapshot(snapshots[0]["id"]) | |
snapshots.pop(0) | |
if (len(snapshots) == 0 and purge_amount > 0): | |
response = get_snapshots(); | |
snapshots = response["snapshots"] | |
purge_amount -= 1 | |
return None | |
def create_snapshot(droplet_name): | |
data = { | |
"type": "snapshot", | |
"name": droplet_name | |
} | |
return requests.post(ACTION_URL, headers = HEADERS, json = data).json() | |
def delete_snapshot(snapshot_id): | |
return requests.delete(BASE_URL + '/snapshots/' + str(snapshot_id), headers = HEADERS) | |
def get_snapshots(): | |
return requests.get(BASE_URL + '/droplets/' + DROPLET_ID + "/snapshots", headers = HEADERS).json() | |
def set_power(power_type): | |
data = { "type": power_type } | |
return requests.post(ACTION_URL, headers = HEADERS, json = data).json() | |
def get_action(action_id): | |
return requests.get(ACTION_URL + '/' + str(action_id), headers = HEADERS).json() | |
def validate_getopts(argv): | |
global ACCESS_TOKEN, DROPLET_ID, DROPLET_NAME, ALLOWED_SNAPSHOTS, DATA_CONSISTENCY_MODE | |
try: | |
short_args = "a:cd:ht:n:" | |
long_args = [ "allowed-snapshots=", "consistency-mode" "droplet-id=", "help", "token=", "name=" ] | |
opts, args = getopt.getopt(argv, short_args, long_args) | |
except getopt.GetoptError: | |
usage() | |
sys.exit(2) | |
for opt, arg in opts: | |
if opt in ("-h", "--help"): | |
usage() | |
sys.exit() | |
elif opt in ("-a", "--allowed-snapshots"): | |
ALLOWED_SNAPSHOTS = arg | |
elif opt in ("-c", "--consistency-mode"): | |
DATA_CONSISTENCY_MODE = True | |
elif opt in ("-d", "--droplet-id"): | |
DROPLET_ID = arg | |
elif opt in ("-t", "--token"): | |
ACCESS_TOKEN = arg | |
elif opt in ("-n", "--name"): | |
DROPLET_NAME = arg | |
############ | |
# Required # | |
############ | |
try: | |
ACCESS_TOKEN | |
except: | |
usage() | |
sys.exit(2) | |
try: | |
DROPLET_ID | |
except: | |
usage() | |
sys.exit(2) | |
################ | |
# Not Required # | |
################ | |
try: | |
DROPLET_NAME | |
except: | |
DROPLET_NAME = DEFAULT_NAME | |
try: | |
ALLOWED_SNAPSHOTS | |
except: | |
ALLOWED_SNAPSHOTS = DEFAULT_ALLOWED_SNAPSHOTS | |
try: | |
DATA_CONSISTENCY_MODE | |
except: | |
DATA_CONSISTENCY_MODE = DEFAULT_DATA_CONSISTENCY_MODE | |
def usage(): | |
print("do-snapshot.py -d <droplet_id> -t <access_token> [-n <name>] [-a <allowed_snapshots>] [-c <consisteny_mode>] [-h]") | |
if __name__ == "__main__": | |
main(sys.argv[1:]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment