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
Exemple #2
0
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
Exemple #3
0
    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
Exemple #4
0
    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