def get_file_info(self, file, auto_delete=1, dest_directory=None): log_debug(4, file) result = self.rpc_call('config.client.get_file', self.system_id, file) if 'missing' in result: return None dirs_created = None # Older servers will not return directories; if filetype is missing, # assume file if result.get('filetype') == 'directory': if dest_directory: result['path'] = dest_directory.rstrip( os.path.sep) + result['path'] if os.path.isfile(result['path']): raise cfg_exceptions.DirectoryEntryIsFile(result['path']) else: auto_delete = 0 temp_file = result['path'] else: f = file_utils.FileProcessor() temp_file, dirs_created = f.process(result, directory=dest_directory) if auto_delete: self.files_to_delete.append(temp_file) return temp_file, result, dirs_created
def diff(params, cache_only=None): def is_utf8(in_string): """Returns true if input is a valid UTF-8 string, False otherwise.""" if isinstance(in_string, UnicodeType): return True elif isinstance(in_string, StringType): if PY3: return True try: in_string.decode('utf-8') return True except UnicodeDecodeError: return False return False if cache_only: return (0, "no-ops for caching", {}) action_type = 'configfiles.diff' if not _local_permission_check(action_type): log_to_file(0, "permissions error: " + str(action_type)) return _perm_error(action_type) _init() files = params.get('files') or [] fp = file_utils.FileProcessor() missing_files = [] diffs = {} exists = hasattr(os.path, 'lexists') and os.path.lexists or os.path.exists for file in files: path = file['path'] if not exists(path): missing_files.append(path) continue diff = fp.diff(file) if diff: diffs[path] = diff extras = {} if missing_files: extras['missing_files'] = missing_files if diffs: for file in diffs.keys(): if not is_utf8(diffs[file]): diffs[file] = "%s: binary files differ" % file extras['diffs'] = diffs log_to_file( 0, "Files successfully compared: %s %s" % (format_file_string(files, create_key_list()), str(extras))) return 0, "Files successfully compared", extras
def get_file_info(self, config_channel, repopath, revision=None, auto_delete=1, dest_directory=tempfile.gettempdir()): """ given a namepath, return the filename and the rest of the info passed by the server """ result = self.get_raw_file_info(config_channel, repopath, revision) fp = file_utils.FileProcessor() fullpath, dirs_created = fp.process(result, directory=dest_directory, strict_ownership=0) if auto_delete: self.files_to_delete.append(fullpath) del result['file_contents'] return fullpath, result, dirs_created
def deploy(self): """attempt deployment; will rollback if auto_rollback is set""" fp = file_utils.FileProcessor() log_debug(3, "deploying transaction") for dep_file in self.files: if dep_file['filetype'] == 'symlink': self.symlinks.append(dep_file) # 0. handle any dirs we need to create first # a) if the dir exists, then just change the mode and owners, # else create it and then make sure the mode and owners are correct. # b) if there are files, then continue # 1. write new version (tmp) # a) if anything breaks, remove all tmp versions and error out # 2. rename old version to backup # a) if anything breaks, rename all backed up files to original name, # then do 1-a. # 3. rename tmp to target name # a) if anything breaks, remove all deployed files, then do 2-a. # # (yes, this leaves the backup version on disk...) try: # 0. if self.dirs: for directory in self.dirs: dirname = self._normalize_path_to_root(directory['path']) dirmode = directory['filemode'] if os.path.isfile(dirname): raise cfg_exceptions.DirectoryEntryIsFile(dirname) if os.path.isdir(dirname): s = os.stat(dirname) entry = { 'filemode': "%o" % (s[0] & int('07777', 8)), 'uid': s[4], 'gid': s[5], 'filetype': 'directory', } self.changed_dir_info[dirname] = entry log_debug( 3, "directory found, chowning and chmoding to %s as needed: %s" % (dirmode, dirname)) self._chown_chmod_chcon(dirname, dirname, directory) else: log_debug( 3, "directory not found, creating: %s" % dirname) dirs_created = utils.mkdir_p(dirname, None, self.symlinks, self.files) self.new_dirs.extend(dirs_created) self._chown_chmod_chcon(dirname, dirname, directory) if self.deployment_cb: self.deployment_cb(dirname) log_debug(6, "changed_dir_info: %s" % self.changed_dir_info) log_debug(4, "new_dirs: ", self.new_dirs) if not self.newtemp_by_path and not self.files: log_debug( 4, "directory creation complete, no files found to create") return else: log_debug(4, "done with directory creation, moving on to files") # 1. for dep_file in self.files: path = dep_file['path'] log_debug(6, "writing new version of %s to tmp file ..." % path) # make any directories needed... # # TODO: it'd be nice if this had a hook for letting me know # which ones are created... then i could clean created # dirs on rollback (directory, filename) = os.path.split(path) if os.path.isdir(path) and not os.path.islink(path): raise cfg_exceptions.FileEntryIsDirectory(path) if not os.path.exists( directory): # and os.path.isdir(directory): log_debug(7, "creating directories for %s ..." % directory) dirs_created = utils.mkdir_p(directory, None, self.symlinks, self.files) self.new_dirs.extend(dirs_created) log_debug( 7, "directories created and added to list for rollback") # write the new contents to a tmp file, and store the path of the # new tmp file by it's eventual target path self.newtemp_by_path[path], temp_new_dirs = fp.process( dep_file, os.path.sep) self.new_dirs.extend(temp_new_dirs or []) # properly chown and chmod it self._chown_chmod_chcon(self.newtemp_by_path[path], path, dep_file) log_debug(9, "tempfile written: %s" % self.newtemp_by_path[path]) #paths = map(lambda x: x['path'], self.files) paths = list(self.newtemp_by_path.keys()) # 2. for path in paths: if os.path.isdir(path) and not os.path.islink(path): raise cfg_exceptions.FileEntryIsDirectory(path) else: self._rename_to_backup(path) if path in self.backup_by_path: log_debug( 9, "backup file %s written" % self.backup_by_path[path]) # 3. paths.sort(key=lambda s: s.count(os.path.sep)) for path in paths: if self.deployment_cb: self.deployment_cb(path) log_debug(6, "deploying %s ..." % path) os.rename(self.newtemp_by_path[path], path) # race del self.newtemp_by_path[path] log_debug(9, "new version of %s deployed" % path) log_debug(3, "deploy transaction successful") except Exception: #log_debug(1, traceback.format_exception_only(SyntaxError, e)) #traceback.print_exc() if self.auto_rollback: self.rollback() raise