expire_dumps 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #!/usr/bin/python
  2. # Copyright (C) 2007 Florian Reitmeir <florian@reitmeir.org>
  3. # Copyright (C) 2008 Joerg Jaspert <joerg@debian.org>
  4. # Permission is hereby granted, free of charge, to any person obtaining
  5. # a copy of this software and associated documentation files (the
  6. # "Software"), to deal in the Software without restriction, including
  7. # without limitation the rights to use, copy, modify, merge, publish,
  8. # distribute, sublicense, and/or sell copies of the Software, and to
  9. # permit persons to whom the Software is furnished to do so, subject to
  10. # the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be
  13. # included in all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. # requires: python-dateutil
  23. import glob, os, sys
  24. import time, datetime
  25. import re
  26. from datetime import datetime
  27. from datetime import timedelta
  28. from optparse import OptionParser
  29. RULES = [
  30. {'days':14, 'interval':0},
  31. {'days':31, 'interval':7},
  32. {'days':365, 'interval':31},
  33. {'days':3650, 'interval':365},
  34. # keep 14 days, all each day
  35. # keep 31 days, 1 each 7th day
  36. # keep 365 days, 1 each 31th day
  37. # keep 3650 days, 1 each 365th day
  38. ]
  39. TODAY = datetime.today()
  40. VERBOSE = False
  41. NOACTION = False
  42. PRINT = False
  43. PREFIX = ''
  44. PATH = ''
  45. def all_files(pattern, search_path, pathsep=os.pathsep):
  46. """ Given a search path, yield all files matching the pattern. """
  47. for path in search_path.split(pathsep):
  48. for match in glob.glob(os.path.join(path, pattern)):
  49. yield match
  50. def parse_file_dates(list):
  51. out = []
  52. # dump_2006.05.02-11:52:01.bz2
  53. p = re.compile('^\./dump_([0-9]{4})\.([0-9]{2})\.([0-9]{2})-([0-9]{2}):([0-9]{2}):([0-9]{2})(.xz)?$')
  54. for file in list:
  55. m = p.search(file)
  56. if m:
  57. d = datetime(int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)), int(m.group(5)), int(m.group(6)))
  58. out.append({'name': file, 'date': d})
  59. return out
  60. def prepare_rules(rules):
  61. out = []
  62. for rule in rules:
  63. out.append(
  64. {
  65. 'days':timedelta(days=rule['days']),
  66. 'interval':timedelta(days=rule['interval'])}
  67. )
  68. return out
  69. def expire(rules, list):
  70. t_rules=prepare_rules(rules)
  71. rule = t_rules.pop(0)
  72. last = list.pop(0)
  73. for file in list:
  74. if VERBOSE:
  75. print "current file to expire: " + file['name']
  76. print file['date']
  77. # check if rule applies
  78. if (file['date'] < (TODAY-rule['days'])):
  79. if VERBOSE:
  80. print "move to next rule"
  81. if t_rules:
  82. rule = t_rules.pop(0)
  83. if (last['date'] - file['date']) < rule['interval']:
  84. if VERBOSE:
  85. print "unlink file:" + file['name']
  86. if PRINT:
  87. print file['name']
  88. if not NOACTION:
  89. os.unlink(file['name'])
  90. else:
  91. last = file
  92. if VERBOSE:
  93. print "kept file:" + file['name']
  94. parser = OptionParser()
  95. parser.add_option("-d", "--directory", dest="directory",
  96. help="directory name", metavar="Name")
  97. parser.add_option("-f", "--pattern", dest="pattern",
  98. help="Pattern maybe some glob", metavar="*.backup")
  99. parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
  100. help="verbose")
  101. parser.add_option("-n", "--no-action", action="store_true", dest="noaction", default=False,
  102. help="just prints what would be done, this implies verbose")
  103. parser.add_option("-p", "--print", action="store_true", dest="printfiles", default=False,
  104. help="just print the filenames that should be deleted, this forbids verbose")
  105. (options, args) = parser.parse_args()
  106. if (not options.directory):
  107. parser.error("no directory to check given")
  108. if options.noaction:
  109. VERBOSE=True
  110. NOACTION=True
  111. if options.verbose:
  112. VERBOSE=True
  113. if options.printfiles:
  114. VERBOSE=False
  115. PRINT=True
  116. files = sorted( list(all_files(options.pattern,options.directory)), reverse=True );
  117. if not files:
  118. sys.exit(0)
  119. files_dates = parse_file_dates(files);
  120. expire(RULES, files_dates)