backup-manager: add ability to start archives

This will allow things to run completely on autopilot, creating
archives on S3 when necessary.
This commit is contained in:
Ryan Tucker 2011-09-29 11:22:54 -04:00
parent b5533a843f
commit abbbbba970

View file

@ -3,6 +3,8 @@
# Script to manage S3-stored backups # Script to manage S3-stored backups
import optparse import optparse
import os
import pwd
import secrets import secrets
import sys import sys
import time import time
@ -11,6 +13,8 @@ from boto.s3.connection import S3Connection
from boto.s3.key import Key from boto.s3.key import Key
import boto.exception import boto.exception
from subprocess import *
def open_s3(accesskey, sharedkey): def open_s3(accesskey, sharedkey):
return S3Connection(accesskey, sharedkey) return S3Connection(accesskey, sharedkey)
@ -148,6 +152,23 @@ def make_restore_script(backup, expire=86400):
return output return output
def start_archive(hosts):
"Starts an archive operation for a list of hosts."
if 'LOGNAME' in os.environ:
username = os.environ['LOGNAME']
else:
try:
username = pwd.getpwuid(os.getuid()).pw_name
except KeyError:
username = 'nobody'
cmd = ['/usr/share/backuppc/bin/BackupPC_archiveStart', 'archives3',
username]
cmd.extend(hosts)
proc = Popen(cmd)
proc.communicate()
def main(): def main():
# check command line options # check command line options
parser = optparse.OptionParser( parser = optparse.OptionParser(
@ -175,6 +196,8 @@ def main():
help="Test mode; don't actually delete") help="Test mode; don't actually delete")
parser.add_option("-u", "--unfinalized", dest="unfinalized", parser.add_option("-u", "--unfinalized", dest="unfinalized",
action="store_true", help="Consider unfinalized backups") action="store_true", help="Consider unfinalized backups")
parser.add_option("-s", "--start-backups", dest="start",
action="store_true", help="When used with --age, start backups for hosts with fewer than keep+1 backups")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
@ -195,6 +218,9 @@ def main():
if args[0] != 'delete' and options.age: if args[0] != 'delete' and options.age:
parser.error('--age only makes sense with delete') parser.error('--age only makes sense with delete')
if options.start and not (args[0] == 'delete' and options.age):
parser.error('--start-backups only makes sense with delete and --age')
if args[0] != 'script' and (options.expire or options.filename): if args[0] != 'script' and (options.expire or options.filename):
parser.error('--expire and --filename only make sense with script') parser.error('--expire and --filename only make sense with script')
@ -271,11 +297,13 @@ def main():
elif args[0] == 'delete': elif args[0] == 'delete':
if options.age: if options.age:
maxage = int(options.age)*86400 maxage = int(options.age)*86400
needs_backup = []
for bucket in buckets: for bucket in buckets:
hostnames = list_backups(bucket) hostnames = list_backups(bucket)
for hostname in hostnames.keys(): for hostname in hostnames.keys():
backups = hostnames[hostname] backups = hostnames[hostname]
backuplist = sorted(backups.keys()) backuplist = sorted(backups.keys())
oldest_timestamp = -1
# remove a number of recent backups from the delete list # remove a number of recent backups from the delete list
to_ignore = int(options.keep) to_ignore = int(options.keep)
while to_ignore > 0: while to_ignore > 0:
@ -289,9 +317,12 @@ def main():
sys.stdout.write('Ignoring in-progress backup %s #%i\n' % (hostname, backupnum)) sys.stdout.write('Ignoring in-progress backup %s #%i\n' % (hostname, backupnum))
else: else:
sys.stdout.write('Keeping recent backup %s #%i (%i files, age %.2f days)\n' % (hostname, backupnum, filecount, delta/86400.0)) sys.stdout.write('Keeping recent backup %s #%i (%i files, age %.2f days)\n' % (hostname, backupnum, filecount, delta/86400.0))
if timestamp < oldest_timestamp:
oldest_timestamp = timestamp
to_ignore -= 1 to_ignore -= 1
else: else:
to_ignore = 0 to_ignore = 0
deletes = 0
for backupnum in backuplist: for backupnum in backuplist:
filecount = len(backups[backupnum]['keys']) filecount = len(backups[backupnum]['keys'])
if backups[backupnum]['finalized'] > 0: if backups[backupnum]['finalized'] > 0:
@ -318,6 +349,12 @@ def main():
backups[backupnum]['finalkey'].delete() backups[backupnum]['finalkey'].delete()
sys.stdout.write('!') sys.stdout.write('!')
sys.stdout.write('\n') sys.stdout.write('\n')
deletes += 1
if (len(backuplist)-deletes) < int(options.keep):
needs_backup.append((oldest_timestamp, hostname))
if options.start and len(needs_backup) > 0:
sys.stdout.write('Starting archive operations for hosts: %s\n' % ', '.join(x[1] for x in sorted(needs_backup)))
start_archive([x[1] for x in sorted(needs_backup)])
elif options.host and options.backupnum: elif options.host and options.backupnum:
for bucket in buckets: for bucket in buckets:
hostnames = list_backups(bucket) hostnames = list_backups(bucket)