remove obsolete volumes daily
authorPeter Palfrader <peter@palfrader.org>
Tue, 28 Mar 2017 11:49:43 +0000 (13:49 +0200)
committerPeter Palfrader <peter@palfrader.org>
Tue, 28 Mar 2017 11:50:01 +0000 (13:50 +0200)
modules/bacula/files/bacula-unlink-removed-volumes [new file with mode: 0755]
modules/bacula/manifests/storage.pp

diff --git a/modules/bacula/files/bacula-unlink-removed-volumes b/modules/bacula/files/bacula-unlink-removed-volumes
new file mode 100755 (executable)
index 0000000..28e1165
--- /dev/null
@@ -0,0 +1,85 @@
+#!/usr/bin/python3
+
+# queries a bacula database for volume names
+# and then removed old volumes from disk that are no longer
+# referenced in the database
+
+# Copyright 2010, 2011, 2013, 2017 Peter Palfrader
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import argparse
+import psycopg2
+import psycopg2.extras
+import os
+import re
+import sys
+from datetime import datetime, timedelta
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-d', '--db-connect-string', metavar='connect-string', dest='db',
+  help='Database connect string')
+parser.add_argument('-D', '--db-connect-string-file', metavar='FILE', dest='dbfile',
+  default='/etc/dsa/bacula-reader-database',
+  help='File to read database connect string from (/etc/dsa/bacula-reader-database)')
+parser.add_argument('-r', '--rootdir', metavar='DIR', dest='root',
+  default='/srv/bacula',
+  help='Directory to start walk in')
+parser.add_argument('-a', '--age', metavar='DAYS', dest='age',
+  default=60.0, type=float,
+  help='Min age to delete files')
+parser.add_argument('-v', '--verbose', dest='verbose', action='store_true')
+parser.add_argument('-n', '--no-do', dest='nodo', action='store_true')
+args = parser.parse_args()
+
+if args.db is not None:
+    pass
+elif args.dbfile is not None:
+    args.db = open(args.dbfile).read().rstrip()
+else:
+    print >>sys.stderr, 'Need one of -d or -D.'
+    sys.exit(1)
+
+cutoff = datetime.now() - timedelta(days=args.age)
+
+conn = psycopg2.connect(args.db)
+cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
+cursor.execute("""
+  SELECT volumename
+  FROM media
+""", {})
+media = set(r['volumename'] for r in cursor.fetchall())
+
+for path, dirs, files in os.walk(args.root):
+  dirs.sort()
+  files.sort()
+  for f in files:
+    if f in media: continue
+    full = os.path.join(path, f)
+    st = os.stat(full)
+    mtime = datetime.fromtimestamp(int(st.st_mtime))
+    if mtime >= cutoff: continue
+    if not args.nodo:
+      os.unlink(full)
+      if args.verbose:
+        print("%s %7d %s"%(mtime, st.st_size, full))
+    else:
+      if args.verbose:
+        print("Would delete %s %7d %s"%(mtime, st.st_size, full))
index b86f8da..941c97b 100644 (file)
@@ -66,5 +66,13 @@ class bacula::storage inherits bacula {
                ;
        }
 
+       file { '/usr/local/bin/bacula-unlink-removed-volumes':
+               source  => 'puppet:///modules/bacula/bacula-unlink-removed-volumes',
+               mode    => '0555',
+       }
+       file { "/etc/cron.d/puppet-bacula-storage-stuff":
+               content => "MAILTO=root\n@daily bacula chronic /usr/local/bin/bacula-unlink-removed-volumes -v\n";
+       }
+
        Bacula::Storage_per_node<<| |>>
 }