aboutsummaryrefslogtreecommitdiff
path: root/freenas/snap_trimmer.py
blob: fe884d9c126920ad76f91c9e2ccb2709425cf89b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python3

""" 
Used to trim ZFS snapshots on a FreeNAS appliance if they're being sent from another appliance
and rather than 1:1 replication you want a different retention policy on the backups.
There is nothing elegant about this, and in fact it's fairly inefficient.  It was a quick
solution to a problem I had.  PRs accepted.  If you add an actual hostname, you could set 
verify=True in your http(s) requests.  
"""

import requests
import argparse

api_user = 'root'
api_pass = 'YourPassword'

def delete_snap(id):
    r = requests.delete("https://localhost/api/v1.0/storage/snapshot/{}".format(id), auth=(api_user, api_pass), verify=False)
    if r.status_code != 204:
        print("Could not delete snap: {}. HTTP response {}".format(id, r.status_code))
    return

parser = argparse.ArgumentParser()
parser.add_argument("--filesystem", help="The name of the filesystem to trim snaps for", required=True, type=str)
parser.add_argument("--keephourly", help="The number of hourly snaps to keep", required=True, type=int)
parser.add_argument("--keepdaily", help="The number of daily snaps to keep", required=True, type=int)
parser.add_argument("--keepweekly", help="The number of weekly snaps to keep", required=True, type=int)
parser.add_argument("--keepmonthly", help="The number of monthly snaps to keep", required=True, type=int)
args = parser.parse_args()

filesystem = args.filesystem
keep_hourly = args.keephourly
keep_daily = args.keepdaily
keep_weekly = args.keepweekly 
keep_monthly = args.keepmonthly

query_params = {"limit": 0}
r = requests.get("https://localhost/api/v1.0/storage/snapshot/", verify=False, auth=(api_user, api_pass), params=query_params)

all_snaps = r.json()

my_snaps = []
for snap in all_snaps:
    if filesystem == snap['filesystem']:
        my_snaps.append(snap['fullname'])

hourly_snaps = []
daily_snaps = []
weekly_snaps = []
monthly_snaps = []
for snap in my_snaps:
    if snap[-1:] == 'h':
        hourly_snaps.append(snap)
    elif snap[-1:] == 'd':
        daily_snaps.append(snap)
    elif snap[-1:] == 'w':
        weekly_snaps.append(snap)
    elif snap[-1:] == 'm':
        monthly_snaps.append(snap)
    else:
        print("No idea what's going on here")

# Sort all of our lists, useful later for trimming snaps to the proper numbers
hourly_snaps.sort()
daily_snaps.sort()
weekly_snaps.sort()
monthly_snaps.sort()

if len(hourly_snaps) > keep_hourly:
    to_delete = len(hourly_snaps) - keep_hourly
    snap_names = []
    counter = 0 
    while counter < to_delete:
        snap_names.append(hourly_snaps.pop(0))
        counter = counter + 1 
    for snap in snap_names:
        for result in all_snaps:
            if result['fullname'] == snap:
                delete_snap(result['id'])

if len(daily_snaps) > keep_daily:
    to_delete = len(daily_snaps) - keep_daily
    snap_names = []
    counter = 0 
    while counter < to_delete:
        snap_names.append(daily_snaps.pop(0))
        counter = counter + 1 
    for snap in snap_names:
        for result in all_snaps:
            if result['fullname'] == snap:
                delete_snap(result['id'])

if len(weekly_snaps) > keep_weekly:
    to_delete = len(weekly_snaps) - keep_weekly
    snap_names = []
    counter = 0 
    while counter < to_delete:
        snap_names.append(weekly_snaps.pop(0))
        counter = counter + 1 
    for snap in snap_names:
        for result in all_snaps:
            if result['fullname'] == snap:
                delete_snap(result['id'])

if len(monthly_snaps) > keep_monthly:
    to_delete = len(monthly_snaps) - keep_monthly
    snap_names = []
    counter = 0 
    while counter < to_delete:
        snap_names.append(monthly_snaps.pop(0))
        counter = counter + 1 
    for snap in snap_names:
        for result in all_snaps:
            if result['fullname'] == snap:
                delete_snap(result['id'])