s3delobs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/usr/bin/python
  2. #
  3. # Author: Tobias Galitzien <tg@trusttheadmin.de>
  4. # Copyright (c) 2012 Tobias Galitzien <tg@trusttheadmin.de>
  5. # Berlin, Germany
  6. #
  7. import sys
  8. import boto.s3.connection
  9. import argparse
  10. import time, datetime, dateutil.parser
  11. now = datetime.datetime.utcnow()
  12. def bailout(msg):
  13. sys.stderr.write(msg)
  14. sys.exit(-1)
  15. def is_obsolete(dt):
  16. try:
  17. age = (now-dt).days
  18. if age <= 7: return False
  19. if age < 35 and dt.day % 7 == 0: return False
  20. return True
  21. except:
  22. return False
  23. def determine_filedate(key, pattern=None):
  24. if pattern:
  25. try:
  26. t = time.strptime(key.name, pattern)
  27. return datetime.datetime(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
  28. except ValueError:
  29. return None
  30. else:
  31. return dateutil.parser.parse(key.last_modified).replace(tzinfo=None)
  32. # parse command line
  33. parser = argparse.ArgumentParser(description = 'delete obsolete archives on s3')
  34. parser.add_argument('-b','--bucket', required = True)
  35. parser.add_argument('-p','--pattern', help = 'use strptime() pattern to determine file date')
  36. parser.add_argument('-m','--mtime', action = 'store_true', help = 'use mtime for file date')
  37. parser.add_argument('-v','--verbose', type = int, default = 0, help = 'set boto debug level')
  38. parser.add_argument('-e','--endpoint', default = 's3.amazonaws.com', help = 'set s3 endpoint (s3-eu-west-1.amazonaws.com for EU buckets, see http://docs.amazonwebservices.com/general/latest/gr/rande.html#s3_region)')
  39. parser.add_argument('-d','--dryrun', action = 'store_true', help = 'don\'t actually delete anything, just show what would be done')
  40. args = parser.parse_args()
  41. # check mode
  42. if not (args.pattern or args.mtime):
  43. print "need either a pattern or the mtime switch"
  44. parser.print_help()
  45. sys.exit()
  46. # connect to s3
  47. try:
  48. s3 = boto.s3.connection.S3Connection(debug = args.verbose, host = args.endpoint)
  49. except boto.exception.S3ResponseError, e:
  50. bailout("cannot connect to S3: %s\n" % e.code)
  51. # open bucket
  52. try:
  53. bucket = s3.get_bucket(args.bucket)
  54. except boto.exception.S3ResponseError, e:
  55. bailout("cannot access bucket %s: %s\n" % (args.bucket,e.code))
  56. for k in bucket.list():
  57. n = k.name
  58. dt = determine_filedate(k, args.pattern)
  59. if dt:
  60. if is_obsolete(dt):
  61. if args.dryrun:
  62. print 'would delete %s, but dryrun mode' % n
  63. else:
  64. if args.verbose:
  65. print 'deleting %s' % n
  66. k.delete()
  67. else:
  68. if args.verbose:
  69. print 'cannot parse %s' % n