def interfaces(self): '''return list of interfaces of relevant nodes''' explicit_includes = self.nodelist[:] # by default, work on all nodes if not self.nodelist and not self.grouplist: self.nodelist = synctool_config.get_all_nodes() # check if the nodes exist at all; the user could have given bogus names all_nodes = synctool_config.get_all_nodes() for node in self.nodelist: if not node in all_nodes: stderr("no such node '%s'" % node) return None if self.grouplist: # check if the groups exist at all all_groups = synctool_config.make_all_groups() for group in self.grouplist: if not group in all_groups: stderr("no such group '%s'" % group) return None self.nodelist.extend(synctool_config.get_nodes_in_groups(self.grouplist)) if self.exclude_groups: self.exclude_nodes.extend(synctool_config.get_nodes_in_groups(self.exclude_groups)) for node in self.exclude_nodes: # remove excluded nodes, if not explicitly included if node in self.nodelist and not node in explicit_includes: self.nodelist.remove(node) if len(self.nodelist) <= 0: return [] ifaces = [] for node in self.nodelist: if node in synctool_param.IGNORE_GROUPS and not node in explicit_includes: verbose('node %s is ignored' % node) continue groups = synctool_config.get_groups(node) do_continue = False for group in groups: if group in synctool_param.IGNORE_GROUPS: verbose('group %s is ignored' % group) do_continue = True break if do_continue: continue iface = synctool_config.get_node_interface(node) self.namemap[iface] = node if not iface in ifaces: # make sure we do not have duplicates ifaces.append(iface) return ifaces
def upload(interface, upload_filename, upload_suffix=None): '''copy a file from a node into the overlay/ tree''' if not synctool_param.SCP_CMD: stderr('%s: error: scp_cmd has not been defined in %s' % (os.path.basename(sys.argv[0]), synctool_param.CONF_FILE)) sys.exit(-1) if upload_filename[0] != '/': stderr('error: the filename to upload must be an absolute path') sys.exit(-1) trimmed_upload_fn = upload_filename[1:] # remove leading slash import synctool_overlay # make the known groups lists synctool_config.remove_ignored_groups() synctool_param.MY_GROUPS = synctool_config.get_my_groups() synctool_param.ALL_GROUPS = synctool_config.make_all_groups() if upload_suffix and not upload_suffix in synctool_param.ALL_GROUPS: stderr("no such group '%s'" % upload_suffix) sys.exit(-1) # shadow DRY_RUN because that var can not be used correctly here if '-f' in PASS_ARGS or '--fix' in PASS_ARGS: dry_run = False else: dry_run = True if not synctool_lib.QUIET: stdout('DRY RUN, not uploading any files') terse(synctool_lib.TERSE_DRYRUN, 'not uploading any files') node = NODESET.get_nodename_from_interface(interface) # pretend that the current node is now the given node; # this is needed for find() to find the most optimal reference for the file orig_NODENAME = synctool_param.NODENAME synctool_param.NODENAME = node synctool_config.insert_group(node, node) orig_MY_GROUPS = synctool_param.MY_GROUPS[:] synctool_param.MY_GROUPS = synctool_config.get_my_groups() # see if file is already in the repository (obj, err) = synctool_overlay.find_terse(synctool_overlay.OV_OVERLAY, upload_filename) if err == synctool_overlay.OV_FOUND_MULTIPLE: # multiple source possible # possibilities have already been printed sys.exit(1) if err == synctool_overlay.OV_NOT_FOUND: # no source path found if string.find(upload_filename, '...') >= 0: stderr("%s is not in the repository, don't know what to map this path to\n" "Please give the full path instead of a terse path, or touch the source file\n" "in the repository first and try again" % os.path.basename(upload_filename)) sys.exit(1) # it wasn't a terse path, throw a source path together # This picks the first overlay dir as default source, which may not be correct # but it is a good guess repos_filename = os.path.join(synctool_param.OVERLAY_DIRS[0], trimmed_upload_fn) if upload_suffix: repos_filename = repos_filename + '._' + upload_suffix else: repos_filename = repos_filename + '._' + node # use _nodename as default suffix else: if upload_suffix: # remove the current group suffix an add the specified suffix to the filename arr = string.split(obj.src_path, '.') if len(arr) > 1 and arr[-1][0] == '_': repos_filename = string.join(arr[:-1], '.') repos_filename = repos_filename + '._' + upload_suffix else: repos_filename = obj.src_path synctool_param.NODENAME = orig_NODENAME synctool_param.MY_GROUPS = orig_MY_GROUPS verbose('%s:%s uploaded as %s' % (node, upload_filename, repos_filename)) terse(synctool_lib.TERSE_UPLOAD, repos_filename) unix_out('%s %s:%s %s' % (synctool_param.SCP_CMD, interface, upload_filename, repos_filename)) if dry_run: stdout('would be uploaded as %s' % synctool_lib.prettypath(repos_filename)) else: # first check if the directory in the repository exists repos_dir = os.path.dirname(repos_filename) stat = synctool_stat.SyncStat(repos_dir) if not stat.exists(): verbose('making directory %s' % synctool_lib.prettypath(repos_dir)) unix_out('mkdir -p %s' % repos_dir) synctool_lib.mkdir_p(repos_dir) # make scp command array scp_cmd_arr = shlex.split(synctool_param.SCP_CMD) scp_cmd_arr.append('%s:%s' % (interface, upload_filename)) scp_cmd_arr.append(repos_filename) synctool_lib.run_with_nodename(scp_cmd_arr, NODESET.get_nodename_from_interface(interface)) if os.path.isfile(repos_filename): stdout('uploaded %s' % synctool_lib.prettypath(repos_filename))
def main(): action = get_options() synctool_config.add_myhostname() if synctool_param.NODENAME == None: stderr('unable to determine my nodename, please check %s' % synctool_param.CONF_FILE) sys.exit(1) if synctool_param.NODENAME in synctool_param.IGNORE_GROUPS: stderr('%s: node %s is disabled in the config file' % (synctool_param.CONF_FILE, synctool_param.NODENAME)) sys.exit(1) synctool_config.remove_ignored_groups() synctool_param.MY_GROUPS = synctool_config.get_my_groups() synctool_param.ALL_GROUPS = synctool_config.make_all_groups() if synctool_lib.UNIX_CMD: t = time.localtime(time.time()) unix_out('#') unix_out('# script generated by synctool on %04d/%02d/%02d %02d:%02d:%02d' % (t[0], t[1], t[2], t[3], t[4], t[5])) unix_out('#') unix_out('# NODENAME=%s' % synctool_param.NODENAME) unix_out('# HOSTNAME=%s' % synctool_param.HOSTNAME) unix_out('# MASTERDIR=%s' % synctool_param.MASTERDIR) unix_out('# SYMLINK_MODE=0%o' % synctool_param.SYMLINK_MODE) unix_out('#') if not synctool_lib.DRY_RUN: unix_out('# NOTE: --fix specified, applying updates') unix_out('#') unix_out('') else: if not synctool_lib.QUIET: verbose('my nodename: %s' % synctool_param.NODENAME) verbose('my hostname: %s' % synctool_param.HOSTNAME) verbose('masterdir: %s' % synctool_param.MASTERDIR) verbose('symlink_mode: 0%o' % synctool_param.SYMLINK_MODE) if synctool_param.LOGFILE != None and not synctool_lib.DRY_RUN: verbose('logfile: %s' % synctool_param.LOGFILE) verbose('') if synctool_lib.DRY_RUN: stdout('DRY RUN, not doing any updates') terse(synctool_lib.TERSE_DRYRUN, 'not doing any updates') else: stdout('--fix specified, applying changes') terse(synctool_lib.TERSE_FIXING, ' applying changes') verbose('') synctool_lib.openlog() os.putenv('SYNCTOOL_NODENAME', synctool_param.NODENAME) os.putenv('SYNCTOOL_MASTERDIR', synctool_param.MASTERDIR) if action == ACTION_DIFF: for file in SINGLE_FILES: diff_files(file) elif action == ACTION_RUN_TASKS: if SINGLE_FILES: for single_file in SINGLE_FILES: single_task(single_file) else: run_tasks() elif action == ACTION_REFERENCE: for file in SINGLE_FILES: reference(file) elif SINGLE_FILES: for single_file in SINGLE_FILES: (changed, src) = single_files(single_file) if changed: run_post(src, single_file) run_post_on_directories() else: overlay_files() delete_files() run_post_on_directories() always_run() unix_out('# EOB') synctool_lib.closelog()
# note that the order is important, so do not use # "for obj in dict: callback(obj)" # for dest_path in filelist: callback(dict[dest_path]) if __name__ == '__main__': ## unit test program ## import synctool_config synctool_param.CONF_FILE = '/Users/walter/synctool-test/synctool.conf' synctool_config.read_config() synctool_param.MY_GROUPS = ['node1', 'group1', 'group2', 'all'] synctool_param.ALL_GROUPS = synctool_config.make_all_groups() def visit_callback(obj): # normally you wouldn't use this ... it's just for debugging the group number print 'grp', obj.groupnum print 'src ', obj.print_src() print 'dest', obj.print_dest() # check for .post script postscript = postscript_for_path(obj.src_path, obj.dest_path) if postscript: print 'post %s' % postscript visit(OV_OVERLAY, visit_callback)
def interfaces(self): '''return list of interfaces of relevant nodes''' explicit_includes = self.nodelist[:] # by default, work on all nodes if not self.nodelist and not self.grouplist: self.nodelist = synctool_config.get_nodes_in_groups(["all"]) # check if the nodes exist at all; the user could have given bogus names all_nodes = synctool_config.get_all_nodes() for node in self.nodelist: if not node in all_nodes: stderr("no such node '%s'" % node) return None if self.grouplist: # check if the groups exist at all all_groups = synctool_config.make_all_groups() for group in self.grouplist: if not group in all_groups: stderr("no such group '%s'" % group) return None self.nodelist.extend(synctool_config.get_nodes_in_groups(self.grouplist)) if self.exclude_groups: self.exclude_nodes.extend(synctool_config.get_nodes_in_groups(self.exclude_groups)) for node in self.exclude_nodes: # remove excluded nodes, if not explicitly included if node in self.nodelist and not node in explicit_includes: self.nodelist.remove(node) if len(self.nodelist) <= 0: return [] ifaces = [] ignored_nodes = '' for node in self.nodelist: if node in synctool_param.IGNORE_GROUPS and not node in explicit_includes: verbose('node %s is ignored' % node) if not ignored_nodes: ignored_nodes = node else: ignored_nodes = ignored_nodes + ',' + node continue groups = synctool_config.get_groups(node) do_continue = False for group in groups: if group in synctool_param.IGNORE_GROUPS: verbose('group %s is ignored' % group) if not ignored_nodes: ignored_nodes = node else: ignored_nodes = ignored_nodes + ',' + node do_continue = True break if do_continue: continue iface = synctool_config.get_node_interface(node) self.namemap[iface] = node if not iface in ifaces: # make sure we do not have duplicates ifaces.append(iface) # print message about ignored nodes if ignored_nodes and not synctool_lib.QUIET and not synctool_lib.UNIX_CMD: if synctool_param.TERSE: synctool_lib.terse(synctool_lib.TERSE_WARNING, 'ignored nodes') else: ignored_nodes = 'warning: ignored nodes: ' + ignored_nodes if len(ignored_nodes) < 80: print ignored_nodes else: print 'warning: some nodes are ignored' return ifaces