|
From: Will P. <pa...@us...> - 2006-03-06 12:02:10
|
Update of /cvsroot/ark/sidai/dchunk-utils In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8884/dchunk-utils Added Files: prune-replica-snapshots Log Message: addition --- NEW FILE --- #! /usr/bin/env python ################################################################ # # Copyright (c) 2006, Will Partain # All rights reserved. # # Redistribution and use in source and binary forms, with or # without modification, are permitted provided that the # following conditions are met: # # * Redistributions of source code must retain the above # copyright notice, this list of conditions and the # following disclaimer. # # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the # following disclaimer in the documentation and/or other # materials provided with the distribution. # # * Neither the name of the Arusha Project nor the names of # its contributors may be used to endorse or promote # products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ __version__ = "$Revision: 1.1 $"[11:-2] __doc__ = """ ???? """ #import ark.control import ark.host import getopt,os,re,string,sys #import datetime,os,re,string,sys #import ark.error _yyyymmdd_spec = re.compile(r'^\d\d\d\d-\d\d-\d\d$') verbose = None pretend = None MKDIR_P = '/no/idea/about/mkdir -p' RSYNC = '/no/idea/about/rsync' rsync_verbose = '' rsync_pretend = '' def main(): usage = """Blah blah blah""" getopt_spec = [ 'help' , 'verbose' , 'pretend' , 'rsync-verbose' ] global verbose, pretend global MKDIR_P, RSYNC global rsync_verbose, rsync_pretend # print >>sys.stderr,'v=',verbose,'p=',pretend try: opts, non_opts = getopt.getopt(sys.argv[1:], "hvpr", ["help","verbose","pretend","rsync-verbose"]) except getopt.GetoptError: print >>sys.stderr, usage sys.exit(1) for o, a in opts: if o in ("-h", "--help"): print >>sys.stderr, usage sys.exit(0) if o in ("-v", "--verbose"): verbose = True rsync_verbose = '-v' if o in ("-p", "--pretend"): pretend = True rsync_pretend = '--dry-run' if o in ("-r", "--rsync-verbose"): rsync_verbose = '-v' # opts = ark.control.ArkControl(ark.control.ArkOptions(getopt_spec,usage)) # verbose = opts.isSet('verbose') # if opts.isSet('quiet'): verbose = None # pretend = opts.isSet('pretend') # print >>sys.stderr,'v=',verbose,'p=',pretend # some facts about the machine we're on... RUN_HOST = ark.host.RUN_HOST() # the host we're on here... MKDIR_P = RUN_HOST.pgmResource('MKDIR-P') RSYNC = RUN_HOST.pgmResource('RSYNC') # if opts.isSet('rsync-verbose'): rsync_verbose = '-v' # look over these directory args pretty carefully: # non_opts = opts.cmdLineNonOptions() if len(non_opts) < 2: sys.stderr.write('Must have at least two yyyy-mm-dd arguments\n') sys.exit(1) dirs = non_opts for dir in dirs: match = _yyyymmdd_spec.match(dir) if not match: sys.stderr.write('Argument must be of the form yyyy-mm-dd: %s\n'%dir) sys.exit(1) if not os.path.exists(dir): sys.stderr.write('No such directory: %s\n'%dir) sys.exit(1) if not os.path.isdir(dir): sys.stderr.write('Exists, but isn\'t a directory: %s\n'%dir) sys.exit(1) # the dir names *must* be in order: dirs.sort() for i in xrange(len(dirs)-1): me = dirs[i] rest = dirs[i+1:] do_dir(me,rest) # the business end def do_dir(dir,later_dirs): # first, we check for a sentinel that says "We've done this already" if verbose: print >>sys.stderr, "Doing", dir, "..." sentinel_file = os.path.join(dir,".ARK-SNAPSHOT-PRUNED") if os.path.exists(sentinel_file): if verbose: print >>sys.stderr, "NB: previously done: ",dir return # make the directory we're going to copy to (it mustn't exist): dest_dir = dir+".tmp" if os.path.exists(dest_dir): print >>sys.stderr,"dest dir must not exist:",dest_dir sys.exit(1) # can only have 20 compare-dest args: if len(later_dirs) > 20: later_dirs = later_dirs[0:19] later_dirs_stuff = string.join(map(lambda x:'--compare-dest=../'+x,later_dirs),' ') exclude_items = [ "'*.msf'" # index files for Thunderbird, etc. , ".cache" , ".svn" , "Trash" , "WebStatistics.txt" , "WebStatistics.txt,v" , "cyrus.cache" , "cyrus.index" , "cyrus.squat" , "spam-virii" , "spam05-08" , "spam09-15" , "spam16plus" ] excludes = string.join(map(lambda x:'--exclude='+x,exclude_items),' ') if pretend or verbose: print >> sys.stderr, '[ -d %s ] || %s %s' % (dest_dir,MKDIR_P,dest_dir) if not pretend and not os.path.isdir(dest_dir): (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(dir) # mkdir then: os.makedirs(dest_dir) # and ensure permissions are what we want os.chown(dest_dir,uid,gid) os.chmod(dest_dir,mode) # do the serious business: rsync = RSYNC r_verbose = rsync_verbose r_pretend = rsync_pretend rsync_cmd = '%(rsync)s %(r_verbose)s %(r_pretend)s --archive --delete %(excludes)s --delete-excluded %(later_dirs_stuff)s %(dir)s/ %(dest_dir)s' % vars() if pretend or verbose: print >> sys.stderr, rsync_cmd if not pretend: # Note: if rsync, it is safe to just run it: status = os.system(rsync_cmd) if status != 0: raise ('failed: '+rsync_cmd) # get rid of all symlinks and then the empty directories in the output: find_cmd1 = 'find %(dest_dir)s -type l -print0 | xargs -0r /bin/rm 2> /dev/null' % vars() find_cmd1 = 'find %(dest_dir)s -depth -type d -print0 | xargs -0r /bin/rmdir 2> /dev/null' % vars() find_cmd = find_cmd1 + '; ' + find_cmd2 if pretend or verbose: print >> sys.stderr, find_cmd if not pretend: # Note: if rsync, it is safe to just run it: status = os.system(find_cmd) # We actually *expect* a failing status, so we don't worry about it # move the new to the old: NB: it might have been trashed entirely move_cmd = '/bin/mv %(dir)s %(dir)s.orig && if [ -d %(dest_dir)s ] ; then /bin/mv %(dest_dir)s %(dir)s; fi' % vars() if pretend or verbose: print >> sys.stderr, move_cmd if not pretend: # Note: if move, it is safe to just run it: status = os.system(move_cmd) if status != 0: raise ('failed: '+move_cmd) # finally, put in the sentinel to indicate "We've done this already" if pretend or verbose: print >>sys.stderr, "touch",sentinel_file if not pretend: cmd = "if [ -d %(dir)s ] ; then touch %(sentinel_file)s; fi" % vars() status = os.system(cmd) if status != 0: raise ('failed: '+cmd) return # we're done # --------------------------------------------------------------- # =============================================================== if __name__ == '__main__': main() |