#!/bin/env python # sim-sync -- sync source trees across machines using information from the machine database # # Michael Thomas # Center for Computation & Technology # Louisiana State University # import sys, os ############################################ ## APP SPECIFIC DEFINES ## # # Usage when (-h, --help) is used, this is the first line showing how to call the app # optionGroups which option groups from etc/options to import. common is always imported. App = "sim-sync.py" Usage = "usage: %prog [options] machine1 machine2..." optionGroups = ['sim-sync'] Purpose = "sync cactus sourcetree to a remote machine" ############################################ ############################################ ## INIT ## if os.path.basename(sys.argv[0]) == App: rp = os.path.realpath(__file__) paths = rp.split(os.sep) paths.pop() paths.pop() global BASE_PATH BASE_PATH = os.sep.join(paths) sys.path.append(BASE_PATH) from lib import * ############################### FUNCTIONS ############################### def GetRsyncInfo(machineEntry): return GetSubbedInfo(machineEntry, ['rsynccmd', 'rsyncopts']) def GetSshInfo(machineEntry): return GetSubbedInfo(machineEntry, ['sshcmd', 'sshopts']) def GetSubbedInfo(machineEntry, keys): global DefineDatabase global SimLib SimLib.VerifyKeys(machineEntry, keys) data = list() for k in keys: d = DefineDatabase.SubAll(machineEntry.GetKey(k)) data.append(d) return data def CompileCommand(machineName, rsyncInfo): global DefineDatabase global ConfigurationDatabase global OptionsManager global SimLib global localMachineName global localMachineEntry # mode of operation sync_parfiles = OptionsManager.GetOption('sync-parfiles') sync_sourcetree = OptionsManager.GetOption('sync-sourcetree') (rsynccmd, rsyncopts) = rsyncInfo if machineName == localMachineName: print "Error, cannot sync to local machine" sys.exit(1) machineEntry = ConfigurationDatabase.GetMachine(machineName) # get our IO machine -- if iomachine doesn't exist, it returns itself. ioMachine = SimLib.GetIOMachine(machineName) if ioMachine != machineName: ioMachineEntry = ConfigurationDatabase.GetMachine(ioMachine) else: ioMachineEntry = machineEntry mreq_keys = ['user', 'sourcebasedir'] ioreq_keys = ['hostname', 'rsynccmd', 'rsyncopts', 'sshcmd', 'sshopts'] user = machineEntry.user sourcebasedir = machineEntry.sourcebasedir # make sure we have all the info we need. SimLib.VerifyKeys(machineEntry, mreq_keys) SimLib.VerifyKeys(ioMachineEntry, ioreq_keys) DefineDatabase.Set('USER', machineEntry.user) sourcebasedir = DefineDatabase.SubAll(machineEntry.sourcebasedir) iohostname = ioMachineEntry.hostname (iorsynccmd, iorsyncopts) = GetRsyncInfo(ioMachineEntry) (sshcmd, sshopts) = GetSshInfo(ioMachineEntry) sshcmd = "%s %s" % (sshcmd, sshopts) trampoline = SimLib.GetTrampoline(ioMachine) if trampoline != None: sshcmd = SimLib.GetSSHCommand(trampoline, sshcmd) rsyncfiles = [] rsyncexcludes = [] rsyncoptions = ['--archive', '--hard-links', '--sparse', '--verbose', '--progress', '--partial', '--stats', '--compress', '--delete', '--delete-excluded'] # sync source tree if sync_sourcetree: sources = ConfigurationDatabase.GetConfigOption('rsync-sources') #print "rsync-sources is: %s " % sources if type(sources) == list: for r in sources: #print "checking if %s exists" % r if os.path.exists(r): rsyncfiles.append(r) # sync par files if sync_parfiles: sources = ConfigurationDatabase.GetConfigOption('rsync-parfiles') #print "rsync-parfiles is: %s " % sources if type(sources) == list: for r in sources: #print "checking if %s exists" % r if os.path.exists(r): rsyncfiles.append(r) # build excludes sources = ConfigurationDatabase.GetConfigOption('rsync-excludes') if type(sources) == list: for r in sources: rsyncoptions.append("--exclude '%s'" % r) fullpath = "%s@%s:%s%s%s" % (user, iohostname, sourcebasedir, os.sep, path) sshcmd = SimLib.QuoteSafe(sshcmd) arguments = " ".join(SimLib.GetArguments()) cmd = "%s --rsh=%s --rsync-path=%s %s %s %s" % (rsynccmd, sshcmd, iorsynccmd, rsyncopts, iorsyncopts, arguments) cmd = "%s %s" % (cmd, " ".join(rsyncoptions)) cmd = "%s %s" % (cmd, " ".join(rsyncfiles)) cmd = "%s %s" % (cmd, fullpath) if machineEntry.HasKey("localsshsetup"): localsshsetup = DefineDatabase.SubAll(machineEntry.localsshsetup) cmd = "{ %s; } && %s" % (localsshsetup, cmd) return cmd ############################### MAIN ############################### def main(env): global OptionsManager global ConfigurationDatabase global SimLib global DefineDatabase global SimEnvironment SimEnvironment = env OptionsManager = SimEnvironment.OptionsManager ConfigurationDatabase = SimEnvironment.ConfigurationDatabase SimLib = SimEnvironment.SimLib DefineDatabase = SimEnvironment.DefineDatabase ############################################ ## HEADER ## if os.path.basename(SimEnvironment.EXECUTABLE) == App: print "sim-sync: sync sourcetree/parfiles from one machine to another\n" print "cdb: %s" % SimEnvironment.cdb if SimEnvironment.udb != None: print "udb: %s" % SimEnvironment.udb print global path global local_sourcebasedir global localMachineName global localMachineEntry machineList = OptionsManager.args if len(machineList) == 0: print "No machines specified" OptionsManager.PrintHelp() sys.exit(1) print "using machines: %s\n" % machineList print "current working directory: %s\n" % os.getcwd() cactusDir = SimEnvironment.CACTUS_PATH print "Cactus Directory: %s" % cactusDir if os.getcwd() != cactusDir: print "Current Working directory does not match Cactus sourcetree, changing to %s" % cactusDir # make sure we're in the Cactus source directory, otherwise all of this will blow way up. os.chdir(cactusDir) # mode of operation sync_parfiles = OptionsManager.GetOption('sync-parfiles') sync_sourcetree = OptionsManager.GetOption('sync-sourcetree') if not(sync_parfiles or sync_sourcetree): print "Error, neither sync-parfiles or sync-sourcetree was specified. should never happen" sys.exit(1) print "Enabled Options:" print "sync-parfiles: %s" % sync_parfiles print "sync-sourcetree: %s" % sync_sourcetree print # get our local_sourcebasedir local_sourcebasedir = SimLib.GetLocalSourceBaseDir() path = SimLib.GetDirSuffix(local_sourcebasedir) print "local_sourcebasedir: %s" % local_sourcebasedir print "path: %s" % path localMachineName = SimEnvironment.LocalMachine localMachineEntry = SimEnvironment.LocalMachineEntry # returns list (rsynccmd, rsyncopts) rsyncInfo = GetRsyncInfo(localMachineEntry) for m in machineList: cmd = CompileCommand(m, rsyncInfo) #print cmd SimLib.ExecuteCommand(cmd) # only run if you are App if os.path.basename(sys.argv[0]) == App: global SimEnvironment SimEnvironment = simenv.SimEnvironment(BASE_PATH, os.path.realpath(sys.argv[0])) SimEnvironment.initApp(usageString=Usage, optionGroups=optionGroups) main(SimEnvironment)