コード例 #1
0
ファイル: mirror.py プロジェクト: ensoft/enbackup
def mirror_remote(src_dir):
    #
    # This isn't invoked as a top-level operation so don't create a full
    # logfile; just use standard debugging-level support.
    #
    logger = enbackup.log.Logger('mirror')

    try:
        config = enbackup.utils.DefaultConfigParser(
                            { "Paths" :
                                { "src_dir_restrict": src_dir_restrict_default
                                }
                            })
        config.read(cfg_file_path)
        src_dir_restrict = config.get("Paths", "src_dir_restrict")

        (path_is_valid, msg) = validate_local_dir(src_dir, src_dir_restrict)

        if not path_is_valid:
            logger.log(msg)
            raise MirrorCmdError(src_dir, msg)

        #
        # If all is well, start the rsync server to mirror the requested
        # directory.  If currently running as root, make sure we drop down to
        # the enbackup user account for actually running the rsync.  We don't
        # really expect this to happen on the remote end, but best to be
        # sure!
        #
        rsync_cmd_str = mirror_cmd_remote + "{0}".format(src_dir)

        if os.geteuid() == 0:
            rsync_cmd = ["su", get_username(), "--command", rsync_cmd_str]
        else:
            rsync_cmd = rsync_cmd_str.split()

        logger.debug("Remote mirror command: {0}".format(rsync_cmd))

        logger.debug("About to lock '{0}' for remote mirror".
                    format(src_dir))
        with DirLock("mirror-remote (PID {0})".format(os.getpid()),
                     src_dir):
            run_cmd(rsync_cmd, logger)
        logger.debug("Remote mirror done")
    except Exception as e:
        logger.error("Failed remote mirror: {}".format(e))
        raise
コード例 #2
0
ファイル: notify.py プロジェクト: ensoft/enbackup
def notify_remote(server, remote_subcommand):
    ssh_user = get_username()

    #
    # Verify that the 'server' argument is a simple name -- no spaces,
    # escaping, quotes, etc. permitted -- before running the command.
    # If running as root, switch to the enbackup user before running
    # the SSH so that the right key gets picked up.  In future we
    # could make this configurable...
    #
    if re.match("([A-Za-z0-9/\-_:]+)", server):
        ssh_cmd_str = "ssh {0}@{1} enbackup notify {2}".format(
                        ssh_user, server, " ".join(remote_subcommand))

        if os.geteuid() == 0:
            ssh_cmd = ["su", ssh_user, "--command", ssh_cmd_str]
        else:
            ssh_cmd = ssh_cmd_str.split()

        run_cmd(ssh_cmd, logger)
    else:
        logger.error("Server '{0}' name is not in the correct format".format(
                     server))
コード例 #3
0
ファイル: mirror.py プロジェクト: ensoft/enbackup
def mirror_local(src, tgt_dir):
    #
    # Start recording details of this operation to a logfile:
    #
    logger = start_logger()

    try:
        config = enbackup.utils.DefaultConfigParser(
                        { "Paths" :
                            { "tgt_dir_restrict": tgt_dir_restrict_default },
                          "Logging" :
                            { "log_email": email_default,
                              "log_filter": "" }})
        config.read(cfg_file_path)
        tgt_dir_restrict = config.get("Paths", "tgt_dir_restrict")
        email_to = config.get("Logging", "log_email")
        log_filter_file = config.get("Logging", "log_filter")

        #
        # Check the target directory is valid on this server.
        #
        (path_is_valid, msg) = validate_local_dir(tgt_dir, tgt_dir_restrict)

        if not path_is_valid:
            logger.log(msg)
            raise MirrorCmdError(tgt_dir, msg)

        #
        # Get the source directory.  This is selected from the config file,
        # based on the incoming argument, so we trust it's a sane value:
        #
        try:
            src_server = config.get(src, "src_server")
            src_dir    = config.get(src, "src_dir")
        except ConfigParser.NoSectionError:
            logger.log("No source entry found in %s matching keyword '%s'" %
                       (cfg_file_path, src))
            raise

        #
        # Work out which directory we're going to be writing to so we can
        # lock it.  The target directory depends on the format of the
        # source directory passed to rsync:
        # - If the source ends in a '/' then the contents are mirrored;
        #   the target is just the target dir as passed by the caller.
        # - If the source does not end in a '/' then everything will
        #   be copied into a subdirectory -- we should append the source
        #   directory name to the passed target directory to get the
        #   path to lock.
        #
        # This behavior falls out nicely if we just use the 'basename'
        # function to extract the last element of the source directory:
        #
        lock_dir = os.path.join(tgt_dir, os.path.basename(src_dir))

        #
        # If all is well, spawn rsync to mirror the data across.
        # Any failures will result in an exception which will
        # get propagated up to the caller.  If currently running as root,
        # make sure we drop down to the enbackup user account for actually
        # running the rsync (we don't want to open any remote connections
        # as root).
        #
        if src_server != "":
            src = "{0}:{1}".format(src_server, src_dir)
        else:
            src = src_dir

        rsync_cmd_str = mirror_cmd_local + "{0} {1}".format(src, tgt_dir)

        if os.geteuid() == 0:
            rsync_cmd = ["su", get_username(), "--command", rsync_cmd_str]
        else:
            rsync_cmd = rsync_cmd_str.split()

        logger.debug("Local mirror command: {0}".format(rsync_cmd))

        logger.debug("About to lock '{0}' for local mirror".format(lock_dir))
        start_time = datetime.datetime.now()
        with DirLock("mirror-local (PID: {0})".format(os.getpid()),
                     lock_dir):
            (rc, output, err) = run_cmd_output(rsync_cmd, logger)
        logger.debug("Local mirror done")
        duration = datetime.datetime.now() - start_time

        #
        # Filter the results of the rsync to remove noise, then record them
        # in a log file, and send an email with the details.
        #
        if log_filter_file != "":
            log_filter = StringFilter(log_filter_file)
            filtered_output = log_filter.filter(output.split("\n"), True)
            filtered_output = "\n".join(filtered_output)
        else:
            filtered_output = output

        if rc == 0:
            subject = "Mirror {0} completed".format(src)
            result_msg =                                                          \
                "Mirroring has completed successfully!\n"                         \
                "    from: {0}\n"                                                 \
                "    to:   {1}\n"                                                 \
                "Total elapsed time: {2}\n\n"                                     \
                "############ rsync summary log ############\n\n"                 \
                "{3}".format(src, tgt_dir, duration, filtered_output)
        else:
            subject = "Mirror {0} FAILED".format(src)
            result_msg =                                                          \
                "Mirroring of {0} to {1} FAILED (code {2}), please investigate."  \
                "\n\n{3}\n\n{4}".format(src, tgt_dir, rc, filtered_output, err)

        logger.log(result_msg)
        logger.send_email(subject, result_msg, email_to)
    except Exception as e:
        logger.error("Failed local mirror: {}".format(e))
        raise