only hold onto backups for 14 days (not 31) and show when the backups will be deleted in the control panel

This commit is contained in:
Joshua Tauberer 2014-09-08 20:09:18 +00:00
parent bab8b515ea
commit 98fc449b49
2 changed files with 33 additions and 8 deletions

View File

@ -14,8 +14,9 @@ import dateutil.parser, dateutil.relativedelta, dateutil.tz
from utils import exclusive_process, load_environment, shell
# settings
keep_backups_for = "31D" # destroy backups older than 31 days except the most recent full backup
# destroy backups when the most recent increment in the chain
# that depends on it is this many days old.
keep_backups_for_days = 14
def backup_status(env):
# What is the current status of backups?
@ -24,8 +25,8 @@ def backup_status(env):
# see how large the storage is.
now = datetime.datetime.now(dateutil.tz.tzlocal())
def reldate(date):
rd = dateutil.relativedelta.relativedelta(now, date)
def reldate(date, ref):
rd = dateutil.relativedelta.relativedelta(ref, date)
if rd.days >= 7: return "%d days" % rd.days
if rd.days > 1: return "%d days, %d hours" % (rd.days, rd.hours)
if rd.days == 1: return "%d day, %d hours" % (rd.days, rd.hours)
@ -44,7 +45,7 @@ def backup_status(env):
backups[key] = {
"date": m.group("date"),
"date_str": date.strftime("%x %X"),
"date_delta": reldate(date),
"date_delta": reldate(date, now),
"full": m.group("incbase") is None,
"previous": m.group("incbase"),
"size": 0,
@ -59,9 +60,27 @@ def backup_status(env):
backups[key]["encsize"] += os.path.getsize(encfn)
# Ensure the rows are sorted reverse chronologically.
# This is relied on by should_force_full().
# This is relied on by should_force_full() and the next step.
backups = sorted(backups.values(), key = lambda b : b["date"], reverse=True)
# When will a backup be deleted?
saw_full = False
deleted_in = None
days_ago = now - datetime.timedelta(days=keep_backups_for_days)
for bak in backups:
if deleted_in:
# Subsequent backups are deleted when the most recent increment
# in the chain would be deleted.
bak["deleted_in"] = deleted_in
if bak["full"]:
# Reset when we get to a full backup. A new chain start next.
saw_full = True
deleted_in = None
elif saw_full and not deleted_in:
# Mark deleted_in only on the first increment after a full backup.
deleted_in = reldate(days_ago, dateutil.parser.parse(bak["date"]))
bak["deleted_in"] = deleted_in
return {
"directory": basedir,
"encpwfile": os.path.join(env['STORAGE_ROOT'], 'backup/secret_key.txt'),
@ -135,7 +154,7 @@ def perform_backup(full_backup):
shell('check_call', [
"/usr/bin/duplicity",
"remove-older-than",
keep_backups_for,
"%dD" % keep_backups_for_days,
"--archive-dir", "/tmp/duplicity-archive-dir",
"--name", "mailinabox",
"--force",

View File

@ -1,4 +1,5 @@
<style>
#backup-status th { text-align: center; }
#backup-status tr.full-backup td { font-weight: bold; }
</style>
@ -19,6 +20,7 @@
<th colspan="2">When</th>
<th>Type</th>
<th>Size</th>
<th>Deleted in...</th>
</thead>
<tbody>
</tbody>
@ -56,8 +58,12 @@ function show_system_backup() {
if (b.full) tr.addClass("full-backup");
tr.append( $('<td/>').text(b.date_str + " " + r.tz) );
tr.append( $('<td/>').text(b.date_delta + " ago") );
tr.append( $('<td/>').text(b.full ? "full" : "incremental") );
tr.append( $('<td/>').text(b.full ? "full" : "increment") );
tr.append( $('<td style="text-align: right"/>').text( nice_size(b.encsize)) );
if (b.deleted_in)
tr.append( $('<td/>').text(b.deleted_in) );
else
tr.append( $('<td class="text-muted">n/a</td>') );
$('#backup-status tbody').append(tr);
total_disk_size += b.size;