#!/usr/bin/env python # # Expire old snapshots import sys, commands, datetime, os, string pbc = os.getenv('PORTBUILD_CHECKOUT') \ if os.getenv('PORTBUILD_CHECKOUT') else "/a/portbuild" sys.path.insert(0, '%s/admin/lib/python' % pbc) from freebsd import * from freebsd_config import * import zfs CONFIG_SUBDIR="conf" CONFIG_FILENAME="server.conf" ENABLED = True VERBOSE= True expirelist={} now = datetime.datetime.now() print "zexpire: starting at " + now.ctime() config = getConfig( pbc, CONFIG_SUBDIR, CONFIG_FILENAME ) ZFS_VOLUME = config.get( 'ZFS_VOLUME' ) if not ZFS_VOLUME: print "you must define ZFS_VOLUME" sys.exit( 1 ) ZFS_MOUNTPOINT = config.get( 'ZFS_MOUNTPOINT' ) if not ZFS_MOUNTPOINT: print "you must define ZFS_MOUNTPOINT" sys.exit( 1 ) PORTBUILD_DIRECTORY = config.get( 'PORTBUILD_DIRECTORY' ) if not PORTBUILD_DIRECTORY: print "you must define PORTBUILD_DIRECTORY" sys.exit( 1 ) portbuild_directory = os.path.join( ZFS_VOLUME, PORTBUILD_DIRECTORY ) SNAP_DIRECTORY = config.get( 'SNAP_DIRECTORY' ) if not SNAP_DIRECTORY: print "you must define SNAP_DIRECTORY" sys.exit( 1 ) snap_directory = os.path.join( ZFS_VOLUME, SNAP_DIRECTORY ) snap_mountpoint = os.path.join( ZFS_MOUNTPOINT, SNAP_DIRECTORY ) SUPPORTED_ARCHS = config.get( 'SUPPORTED_ARCHS' ) if not SUPPORTED_ARCHS: print "you must define SUPPORTED_ARCHS" sys.exit( 1 ) supported_archs = string.split( SUPPORTED_ARCHS ) ZFS_DEFAULT_EXPIRATION = config.get( 'ZFS_DEFAULT_EXPIRATION' ) if not ZFS_DEFAULT_EXPIRATION: print "you must define ZFS_DEFAULT_EXPIRATION" sys.exit( 1 ) ZFS_SNAPSHOT_EXPIRATION = config.get( 'ZFS_SNAPSHOT_EXPIRATION' ) if not ZFS_SNAPSHOT_EXPIRATION: print "you must define ZFS_SNAPSHOT_EXPIRATION" sys.exit( 1 ) expirelist[ ZFS_VOLUME ] = ZFS_DEFAULT_EXPIRATION expirelist[ portbuild_directory ] = ZFS_DEFAULT_EXPIRATION for arch in supported_archs: expirelist[ os.path.join( portbuild_directory, arch ) ] = ZFS_DEFAULT_EXPIRATION expirelist[ snap_directory ] = ZFS_SNAPSHOT_EXPIRATION try: snapdirs = os.listdir( snap_mountpoint ) for snapdir in snapdirs: subdir = os.path.join( snap_mountpoint, snapdir ) tmp = os.path.join( snap_directory, snapdir ) expirelist[ tmp ] = ZFS_SNAPSHOT_EXPIRATION try: snapsubdirs = os.listdir( subdir ) for snapsubdir in snapsubdirs: expirelist[ os.path.join( tmp, snapsubdir ) ] = ZFS_SNAPSHOT_EXPIRATION except: pass except: pass keys = expirelist.keys() keys.sort() for key in keys: fs = key maxage = 2 try: maxage = int( expirelist[ key ] ) except: pass print if VERBOSE: print "fs: " + str(fs) try: snapdata = zfs.getallsnaps(fs) if VERBOSE: print "snapdata: " + str(snapdata) except zfs.NoSuchFS: print "zexpire: no such fs %s, skipping" % fs continue snaps = (i[0] for i in snapdata) for snap in snaps: try: snapdate = datetime.datetime.strptime(snap, "%Y%m%d%H%M") except ValueError: try: snapdate = datetime.datetime.strptime(snap, "%Y%m%d%H%M%S") except ValueError: print "zexpire: don't know what to do with snap `" + snap + "'" continue if VERBOSE: print "zexpire: examining snapshot %s@%s" % (fs, snap) if (now - snapdate) > datetime.timedelta(days=maxage): print "zexpire: snapshot %s@%s too old, attempting zfs destroy" % (fs, snap) if ENABLED: (err, out) = commands.getstatusoutput("zfs destroy %s@%s" % (fs,snap)) if err: print "zexpire: error deleting snapshot", out then = datetime.datetime.now() print print "zexpire: ending at " + then.ctime()