Пример #1
0
def maketemp(prefix=None, directory=None, symlink=None):
    """Creates a temporary file (guaranteed to be new), using the
       specified prefix.

       Returns the filename and an open stream
    """
    if not directory:
        directory = tempfile.gettempdir()

    dirs_created = None
    if not os.path.exists(directory):
        dirs_created = utils.mkdir_p(directory)

    if not prefix:
    # Create the file in /tmp by default
        prefix = 'rhncfg-tempfile'

    file_prefix = "%s-%s-" % (prefix, os.getpid())
    (fd, filename) = tempfile.mkstemp(prefix=file_prefix, dir=directory)

    if symlink:
        os.unlink(filename)
        os.symlink(symlink, filename)
        open_file = None
    else:
        open_file = os.fdopen(fd, "w+")

    return filename, dirs_created, open_file
Пример #2
0
def maketemp(prefix=None, directory=None, symlink=None):
    """Creates a temporary file (guaranteed to be new), using the
       specified prefix.

       Returns the filename and an open stream
    """
    if not directory:
        directory = tempfile.gettempdir()

    dirs_created = None
    if not os.path.exists(directory):
        dirs_created = utils.mkdir_p(directory)

    if not prefix:
        # Create the file in /tmp by default
        prefix = 'rhncfg-tempfile'

    file_prefix = "%s-%s-" % (prefix, os.getpid())
    (fd, filename) = tempfile.mkstemp(prefix=file_prefix, dir=directory)

    if symlink:
        os.unlink(filename)
        os.symlink(symlink, filename)
        open_file = None
    else:
        open_file = os.fdopen(fd, "w+")

    return filename, dirs_created, open_file
Пример #3
0
def maketemp(prefix=None, directory=None):
    """Creates a temporary file (guaranteed to be new), using the
       specified prefix.

       Returns the filename and a file descriptor
    """
    if not directory:
        directory = tempfile.gettempdir()

    dirs_created = None
    if not os.path.exists(directory):
        dirs_created = utils.mkdir_p(directory)

    if not prefix:
    # Create the file in /tmp by default
        prefix = 'rhncfg-tempfile'

    file_prefix = "%s-%s-" % (prefix, os.getpid())
    (fd, filename) = tempfile.mkstemp(prefix=file_prefix, dir=directory)

    return filename, dirs_created, fd
Пример #4
0
def maketemp(prefix=None, directory=None):
    """Creates a temporary file (guaranteed to be new), using the
       specified prefix.

       Returns the filename and a file descriptor
    """
    if not directory:
        directory = tempfile.gettempdir()

    dirs_created = None
    if not os.path.exists(directory):
        dirs_created = utils.mkdir_p(directory)

    if not prefix:
        # Create the file in /tmp by default
        prefix = 'rhncfg-tempfile'

    file_prefix = "%s-%s-" % (prefix, os.getpid())
    (fd, filename) = tempfile.mkstemp(prefix=file_prefix, dir=directory)

    return filename, dirs_created, fd
Пример #5
0
    def process(self, file_struct, directory=None, strict_ownership=1):
        # Older servers will not return directories; if filetype is missing,
        # assume file

        if file_struct.get('filetype') == 'directory':
            if directory is None:
                directory = ""
            return None, utils.mkdir_p(directory + file_struct['path'])

        if directory:
            directory += os.path.split(file_struct['path'])[0]
        if file_struct.get('filetype') == 'symlink':
            if 'symlink' not in file_struct:
                raise Exception("Missing key symlink")

            (fullpath, dirs_created,
             fh) = maketemp(prefix=".rhn-cfg-tmp",
                            directory=directory,
                            symlink=file_struct['symlink'])
            return fullpath, dirs_created

        for k in self.file_struct_fields.keys():
            if k not in file_struct:
                # XXX
                raise Exception("Missing key %s" % k)

        encoding = ''

        if 'encoding' in file_struct:
            encoding = file_struct['encoding']

        contents = file_struct['file_contents']

        if contents and (encoding == 'base64'):
            contents = base64.decodestring(bstr(contents))

        delim_start = file_struct['delim_start']
        delim_end = file_struct['delim_end']

        if ('checksum' in file_struct and 'checksum_type' in file_struct
                and 'verify_contents' in file_struct
                and file_struct['verify_contents']):
            if file_struct['checksum'] != utils.getContentChecksum(
                    file_struct['checksum_type'], contents):
                raise Exception(
                    "Corrupt file received: Content checksums do not match!")
        elif ('md5sum' in file_struct and 'verify_contents' in file_struct
              and file_struct['verify_contents']):
            if file_struct['md5sum'] != utils.getContentChecksum(
                    'md5', contents):
                raise Exception(
                    "Corrupt file received: Content checksums do not match!")
        elif ('verify_contents' in file_struct
              and file_struct['verify_contents']):
            raise Exception(
                "Corrupt file received: missing checksum information!")

        fh = None

        (fullpath, dirs_created, fh) = maketemp(prefix=".rhn-cfg-tmp",
                                                directory=directory)

        try:
            fh.write(sstr(contents))
        except Exception:
            if fh:
                fh.close()  # don't leak fds...
            raise
        else:
            fh.close()

        # try to set mtime and ctime of the file to
        # the last modified time on the server
        if 'modified' in file_struct:
            try:
                modified = xmlrpc_time(file_struct['modified'].value)
                epoch_time = time.mktime(modified)
                os.utime(fullpath, (epoch_time, epoch_time))
            except (ValueError, AttributeError):
                # we can't parse modified time
                pass

        return fullpath, dirs_created
Пример #6
0
    def process(self, file_struct, directory=None, strict_ownership=1):
        # Older servers will not return directories; if filetype is missing,
        # assume file

        if file_struct.get('filetype') == 'directory':
            if directory is None:
                directory = ""
            return None, utils.mkdir_p(directory + file_struct['path'])

        if directory:
            directory += os.path.split(file_struct['path'])[0]
        if file_struct.get('filetype') == 'symlink':
            if 'symlink' not in file_struct:
                raise Exception("Missing key symlink")

            (fullpath, dirs_created, fd) = maketemp(prefix=".rhn-cfg-tmp", directory=directory)
            os.close(fd)
            os.unlink(fullpath)
            os.symlink(file_struct['symlink'], fullpath)
            return fullpath, dirs_created

        for k in self.file_struct_fields.keys():
            if k not in file_struct:
                # XXX
                raise Exception("Missing key %s" % k)

        encoding = ''

        if 'encoding' in file_struct:
            encoding = file_struct['encoding']

        contents = file_struct['file_contents']

        if contents and (encoding == 'base64'):
            contents = base64.decodestring(bstr(contents))

        delim_start = file_struct['delim_start']
        delim_end = file_struct['delim_end']

        if ('checksum' in file_struct
                and 'checksum_type' in file_struct
                and 'verify_contents' in file_struct
                and file_struct['verify_contents']):
            if file_struct['checksum'] != utils.getContentChecksum(
                    file_struct['checksum_type'], contents):
                raise Exception("Corrupt file received: Content checksums do not match!")
        elif ('md5sum' in file_struct and 'verify_contents' in file_struct
                and file_struct['verify_contents']):
            if file_struct['md5sum'] != utils.getContentChecksum(
                    'md5', contents):
                raise Exception("Corrupt file received: Content checksums do not match!")
        elif ('verify_contents' in file_struct
                and file_struct['verify_contents']):
            raise Exception("Corrupt file received: missing checksum information!")


        (fullpath, dirs_created, fd) = maketemp(prefix=".rhn-cfg-tmp", directory=directory)

        try:
            os.write(fd, bstr(contents))
        except Exception:
            raise
        finally:
            os.close(fd)

        # try to set mtime and ctime of the file to
        # the last modified time on the server
        if 'modified' in file_struct:
            try:
                modified = xmlrpc_time(file_struct['modified'].value)
                epoch_time = time.mktime(modified)
                os.utime(fullpath, (epoch_time, epoch_time))
            except (ValueError, AttributeError):
                # we can't parse modified time
                pass

        return fullpath, dirs_created
Пример #7
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
Пример #8
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] & 07777),
                                  '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 = 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 self.backup_by_path.has_key(path):
                        log_debug(9, "backup file %s written" % self.backup_by_path[path])

            # 3.
            paths.sort(key = lambda s: string.count(s, 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