Esempio n. 1
0
def ov_perror(errorcode, src_path):
	'''print error message for source path'''
	
	if errorcode >= 0:
		# this is not an error but a valid group number
		return
	
	if errorcode == OV_NOT_MY_GROUP:
		# this is not an error but a normal condition
		return
	
	if errorcode == OV_NO_GROUP_EXT:
		if synctool_param.TERSE:
			terse(synctool_lib.TERSE_ERROR, 'no group on %s' % src_path)
		else:
			stderr('no underscored group extension on %s, skipped' % synctool_lib.prettypath(src_path))
	
	elif errorcode == OV_UNKNOWN_GROUP:
		if synctool_param.TERSE:
			terse(synctool_lib.TERSE_ERROR, 'invalid group on %s' % src_path)
		else:
			stderr('unknown group on %s, skipped' % synctool_lib.prettypath(src_path))
Esempio n. 2
0
def run_command(cmd):
	'''run a shell command'''
	
	if cmd[0] != '/':
		# if relative path, use scriptdir
		cmd = synctool_param.SCRIPT_DIR + '/' + cmd
	
	# a command can have arguments
	arr = shlex.split(cmd)
	cmdfile = arr[0]
	
	stat = synctool_stat.SyncStat(cmdfile)
	
	if not stat.exists():
		stderr('error: command %s not found' % synctool_lib.prettypath(cmdfile))
		return
	
	if not stat.isExec():
		stderr("warning: file '%s' is not executable" % synctool_lib.prettypath(cmdfile))
		return
	
	# run the shell command
	synctool_lib.shell_command(cmd)
Esempio n. 3
0
	def mkdir_basepath(self):
		'''call mkdir -p if the destination directory does not exist yet'''
		
		if synctool_lib.DRY_RUN:
			return
		
		# check if the directory exists
		basedir = os.path.dirname(self.dest_path)
		stat = synctool_stat.SyncStat(basedir)
		if not stat.exists():
			# create the directory
			verbose('making directory %s' % synctool_lib.prettypath(basedir))
			unix_out('mkdir -p %s' % basedir)
			synctool_lib.mkdir_p(basedir)
Esempio n. 4
0
def overlay_pass2(filelist, filedict):
	'''do pass #2 of 2; create dictionary of destination paths from list
	Each element in the dictionary is an instance of OverlayEntry'''
	
	for entry in filelist:
		if filedict.has_key(entry.dest_path):
			entry2 = filedict[entry.dest_path]
			
			if entry.groupnum < entry2.groupnum:
				# this group is more important, so override it
				del filedict[entry.dest_path]
				entry2 = None
			
			# duplicate paths are a problem, unless they are directories ...
			elif (not (entry.src_isDir() and entry2.src_isDir())) \
				and entry.groupnum == entry2.groupnum:
				
				if synctool_param.TERSE:
					synctool_lib.terse(synctool_lib.TERSE_ERROR, 'duplicate source paths in repository for:')
					synctool_lib.terse(synctool_lib.TERSE_ERROR, entry.src_path)
					synctool_lib.terse(synctool_lib.TERSE_ERROR, entry2.src_path)
				else:
					stderr('error: duplicate source paths in repository for:\n'
						'error: %s\n'
						'error: %s\n' % (synctool_lib.prettypath(entry.src_path),
							synctool_lib.prettypath(entry2.src_path))
					)
				
				continue
			
			else:
				# this group is less important, skip it
				continue
		
		# add or update filedict
		filedict[entry.dest_path] = entry
Esempio n. 5
0
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))
Esempio n. 6
0
def overlay_pass1(overlay_dir, filelist, dest_dir = '/', 
	highest_groupnum = sys.maxint, handle_postscripts = True):
	'''do pass #1 of 2; create list of source and dest files
	Each element in the list is an instance of SyncObject'''
	
	global POST_SCRIPTS
	
	for entry in os.listdir(overlay_dir):
		src_path = os.path.join(overlay_dir, entry)
		src_statbuf = synctool_stat.SyncStat(src_path)
		
		if src_statbuf.isDir():
			if synctool_param.IGNORE_DOTDIRS and entry[0] == '.':
				continue
			
			isDir = True
		else:
			if synctool_param.IGNORE_DOTFILES and entry[0] == '.':
				continue
			
			isDir = False
		
		# check any ignored files with wildcards
		# before any group extension is examined
		if synctool_param.IGNORE_FILES_WITH_WILDCARDS:
			wildcard_match = False
			for wildcard_entry in synctool_param.IGNORE_FILES_WITH_WILDCARDS:
				if fnmatch.fnmatchcase(entry, wildcard_entry):
					wildcard_match = True
					break
			
			if wildcard_match:
				continue
		
		(name, groupnum, isPost) = split_extension(entry, not isDir)
		
		if groupnum < 0:
			# not a relevant group, so skip it
			# Note that this also prunes trees if you have group-specific subdirs
			
			if groupnum != OV_NOT_MY_GROUP:
				# "not my group" is a rather normal error code, but if it is
				# something else, it's a serious error that we should report
				ov_perror(groupnum, os.path.join(overlay_dir, entry))
			
			continue
		
		if name in synctool_param.IGNORE_FILES:
			continue
		
		# inherit lower group level from parent directory
		if groupnum > highest_groupnum:
			groupnum = highest_groupnum
		
		if isPost:
			if handle_postscripts:
				if not src_statbuf.isExec():
					stderr('warning: .post script %s is not executable, ignored' % synctool_lib.prettypath(src_path))
					continue
				
				# register .post script
				# trigger is the source file that would trigger the .post script to run
				trigger = os.path.join(overlay_dir, name)
				
				if POST_SCRIPTS.has_key(trigger):
					if groupnum >= POST_SCRIPTS[trigger].groupnum:
						continue
				
				POST_SCRIPTS[trigger] = synctool_object.SyncObject(src_path, dest_dir, groupnum, src_statbuf)
			else:
				# unfortunately, the name has been messed up already
				# so therefore just ignore the file and issue a warning
				if synctool_param.TERSE:
					terse(synctool_lib.TERSE_WARNING, 'ignoring %s' % src_path)
				else:
					stderr('warning: ignoring .post script %s' % synctool_lib.prettypath(src_path))
			
			continue
		
		dest_path = os.path.join(dest_dir, name)
		
		filelist.append(synctool_object.SyncObject(src_path, dest_path, groupnum, src_statbuf))
		
		if isDir:
			# recurse into subdir
			overlay_pass1(src_path, filelist, dest_path, groupnum, handle_postscripts)
Esempio n. 7
0
	def print_dest(self):
		return synctool_lib.prettypath(self.dest_path)
Esempio n. 8
0
	def print_src(self):
		return synctool_lib.prettypath(self.src_path)