Beispiel #1
0
 def __init__(self, config, remove_origin=False, debug=False):
     self.remove_origin = remove_origin
     if remove_origin:
         command = 'compress(){ bzip2 -c > "$2" < "$1" && rm -f "$1";}; compress'
     else:
         command = 'compress(){ bzip2 -c > "$2" < "$1";}; compress'
     Command.__init__(self, command, shell=True, check=True, debug=debug)
 def __init__(self, config, remove_origin=False, debug=False):
     self.remove_origin = remove_origin
     if remove_origin:
         command = 'compress(){ bzip2 -c > "$2" < "$1" && rm -f "$1";}; compress'
     else:
         command = 'compress(){ bzip2 -c > "$2" < "$1";}; compress'
     Command.__init__(self, command, shell=True, check=True, debug=debug)
Beispiel #3
0
 def get_remote_status(self):
     """Get the status of the remote server"""
     pg_settings = ("archive_mode", "archive_command", "data_directory")
     pg_query_keys = ("server_txt_version", "current_xlog")
     result = dict.fromkeys(pg_settings + pg_query_keys, None)
     try:
         with self.pg_connect() as conn:
             for name in pg_settings:
                 result[name] = self.get_pg_setting(name)
             try:
                 cur = conn.cursor()
                 cur.execute("SELECT version()")
                 result["server_txt_version"] = cur.fetchone()[0].split()[1]
             except:
                 result["server_txt_version"] = None
             try:
                 cur = conn.cursor()
                 cur.execute("SELECT pg_xlogfile_name(pg_current_xlog_location())")
                 result["current_xlog"] = cur.fetchone()[0]
             except:
                 result["current_xlog"] = None
     except:
         pass
     cmd = Command(self.ssh_command, self.ssh_options)
     result["last_shipped_wal"] = None
     if result["data_directory"] and result["archive_command"]:
         archive_dir = os.path.join(result["data_directory"], "pg_xlog", "archive_status")
         out = cmd.getoutput(None, "ls", "-tr", archive_dir)[0]
         for line in out.splitlines():
             if line.endswith(".done"):
                 name = line[:-5]
                 if xlog.is_wal_file(name):
                     result["last_shipped_wal"] = line[:-5]
     return result
Beispiel #4
0
 def get_remote_status(self):
     '''Get the status of the remote server'''
     pg_settings = ('archive_mode', 'archive_command', 'data_directory')
     pg_query_keys = ('server_txt_version', 'current_xlog')
     result = dict.fromkeys(pg_settings + pg_query_keys, None)
     try:
         with self.pg_connect() as conn:
             for name in pg_settings:
                 result[name] = self.get_pg_setting(name)
             try:
                 cur = conn.cursor()
                 cur.execute("SELECT version()")
                 result['server_txt_version'] = cur.fetchone()[0].split()[1]
             except:
                 result['server_txt_version'] = None
             try:
                 cur = conn.cursor()
                 cur.execute('SELECT pg_xlogfile_name(pg_current_xlog_location())')
                 result['current_xlog'] = cur.fetchone()[0];
             except:
                 result['current_xlog'] = None
     except:
         pass
     cmd = Command(self.ssh_command, self.ssh_options)
     result['last_shipped_wal'] = None
     if result['data_directory'] and result['archive_command']:
         archive_dir = os.path.join(result['data_directory'], 'pg_xlog', 'archive_status')
         out = cmd.getoutput(None, 'ls', '-tr', archive_dir)[0]
         for line in out.splitlines():
             if line.endswith('.done'):
                 name = line[:-5]
                 if xlog.is_wal_file(name):
                     result['last_shipped_wal'] = line[:-5]
     return result
Beispiel #5
0
    def get_remote_status(self):
        """
        Retrieve the last archived WAL using a ssh connection on the remote
        server and executing an ls command.

        :rtype: dict
        """
        remote_status = {}
        with self.server.pg_connect():
            if self.server.server_version < 90400:
                remote_status['last_archived_wal'] = None
                if self.server.get_pg_setting('data_directory') and \
                        self.server.get_pg_setting('archive_command'):
                    # TODO: replace with RemoteUnixCommand
                    cmd = Command(self.ssh_command,
                                  self.ssh_options)
                    archive_dir = os.path.join(
                        self.server.get_pg_setting('data_directory'),
                        'pg_xlog', 'archive_status')
                    out = str(cmd.getoutput('ls', '-tr', archive_dir)[0])
                    for line in out.splitlines():
                        if line.endswith('.done'):
                            name = line[:-5]
                            if xlog.is_any_xlog_file(name):
                                remote_status['last_archived_wal'] = name
                                break
        return remote_status
Beispiel #6
0
    def get_remote_status(self):
        """
        Get remote information on PostgreSQL using Ssh, such as
        last archived WAL file

        :rtype: dict(str,str|None)
        """
        remote_status = {}
        # Retrieve the last archived WAL using a Ssh connection on
        # the remote server and executing an 'ls' command. Only
        # for pre-9.4 versions of PostgreSQL.
        if self.server.postgres.server_version < 90400:
            remote_status['last_archived_wal'] = None
            if self.server.postgres.get_setting('data_directory') and \
                    self.server.postgres.get_setting('archive_command'):
                # TODO: replace with RemoteUnixCommand
                cmd = Command(self.ssh_command,
                              self.ssh_options,
                              path=self.server.path)
                archive_dir = os.path.join(
                    self.server.postgres.get_setting('data_directory'),
                    'pg_xlog', 'archive_status')
                out = str(cmd.getoutput('ls', '-tr', archive_dir)[0])
                for line in out.splitlines():
                    if line.endswith('.done'):
                        name = line[:-5]
                        if xlog.is_any_xlog_file(name):
                            remote_status['last_archived_wal'] = name
                            break
        return remote_status
 def __init__(self, config, remove_origin=False, debug=False):
     if not config.custom_decompression_filter:
         raise CompressionIncompatibility("custom_decompression_filter")
     self.remove_origin = remove_origin
     if remove_origin:
         template = 'decompress(){ %s > "$2" < "$1" && rm -f "$1";}; decompress'
     else:
         template = 'decompress(){ %s > "$2" < "$1";}; decompress'
     Command.__init__(self, template % config.custom_decompression_filter, shell=True, check=True, debug=debug)
Beispiel #8
0
 def __init__(self, config, remove_origin=False, debug=False):
     if not config.custom_decompression_filter:
         raise CompressionIncompatibility("custom_decompression_filter")
     self.remove_origin = remove_origin
     if remove_origin:
         template = 'decompress(){ %s > "$2" < "$1" && rm -f "$1";}; decompress'
     else:
         template = 'decompress(){ %s > "$2" < "$1";}; decompress'
     Command.__init__(self,
                      template % config.custom_decompression_filter,
                      shell=True,
                      check=True,
                      debug=debug)
Beispiel #9
0
def ssh(server, args):
    warn = args.warning
    crit = args.critical

    from barman.backup_executor import _parse_ssh_command
    from barman.command_wrappers import Command

    ssh_command, ssh_options = _parse_ssh_command(server.config.ssh_command)
    cmd = Command(ssh_command, ssh_options)

    (retval, duration) = timed(cmd, 'true')
    milliseconds = get_milliseconds(duration)
    perfdata_key = "milliseconds"

    if retval == 0:
        exit_check(milliseconds,
                   warn,
                   crit,
                   "SSH command ran in %sms" % (milliseconds),
                   perfdata_key=perfdata_key,
                   perfdata_min=0)
    else:
        critical(
            "Impossible to run a SSH command.",
            get_perfdata_str(perfdata_key, milliseconds, warn, crit, 0, None))
Beispiel #10
0
 def run(self):
     """
     Run a a hook script if configured.
     This method must never throw any exception
     """
     # noinspection PyBroadException
     try:
         if self.script:
             _logger.debug("Attempt to run %s: %s", self.name, self.script)
             cmd = Command(self.script,
                           env_append=self.environment,
                           path=self.backup_manager.server.path,
                           shell=True,
                           check=False)
             self.exit_status = cmd()
             if self.exit_status != 0:
                 details = "%s returned %d\n" \
                           "Output details:\n" \
                           % (self.script, self.exit_status)
                 details += cmd.out
                 details += cmd.err
                 _logger.warning(details)
             else:
                 _logger.debug("%s returned %d", self.script,
                               self.exit_status)
             return self.exit_status
     except Exception as e:
         _logger.exception('Exception running %s', self.name)
         self.exception = e
         return None
Beispiel #11
0
    def __init__(self, ssh_command, ssh_options=None, path=None):
        """
        Uses the same commands as the UnixLocalCommand
        but the constructor is overridden and a remote shell is
        initialized using the ssh_command provided by the user

        :param str ssh_command: the ssh command provided by the user
        :param list[str] ssh_options: the options to be passed to SSH
        :param str path: the path to be used if provided, otherwise
          the PATH environment variable will be used
        """
        # Ensure that ssh_option is iterable
        if ssh_options is None:
            ssh_options = []

        if ssh_command is None:
            raise FsOperationFailed('No ssh command provided')
        self.cmd = Command(ssh_command,
                           ssh_options,
                           path=path,
                           shell=True)
        try:
            ret = self.cmd("true")
        except OSError:
            raise FsOperationFailed("Unable to execute %s" % ssh_command)
        if ret != 0:
            raise FsOperationFailed(
                "Connection failed using '%s %s' return code %s" % (
                    ssh_command,
                    ' '.join(ssh_options),
                    ret))
Beispiel #12
0
 def check_ssh(self):
     '''Checks SSH connection'''
     cmd = Command(self.ssh_command, self.ssh_options)
     ret = cmd("true")
     if ret == 0:
         yield ("\tssh: OK", True)
     else:
         yield ("\tssh: FAILED (return code: %s)" % (ret, ), False)
Beispiel #13
0
    def _build_command(self, pipe_command):
        """
        Build the command string and create the actual Command object

        :param pipe_command: the command used to compress/decompress
        :rtype: Command
        """
        command = "barman_command(){ "
        command += pipe_command
        command += ' > "$2" < "$1"'
        command += ";}; barman_command"
        return Command(command, shell=True, check=True, path=self.path)
Beispiel #14
0
    def fetch_remote_status(self):
        """
        Get remote information on PostgreSQL using Ssh, such as
        last archived WAL file

        This method does not raise any exception in case of errors,
        but set the missing values to None in the resulting dictionary.

        :rtype: dict[str, None|str]
        """
        remote_status = {}
        # Retrieve the last archived WAL using a Ssh connection on
        # the remote server and executing an 'ls' command. Only
        # for pre-9.4 versions of PostgreSQL.
        try:
            if self.server.postgres and \
                    self.server.postgres.server_version < 90400:
                remote_status['last_archived_wal'] = None
                if self.server.postgres.get_setting('data_directory') and \
                        self.server.postgres.get_setting('archive_command'):
                    # TODO: replace with RemoteUnixCommand
                    # The Command can raise OSError
                    # if self.ssh_command does not exist.
                    cmd = Command(self.ssh_command,
                                  self.ssh_options,
                                  path=self.server.path)
                    archive_dir = os.path.join(
                        self.server.postgres.get_setting('data_directory'),
                        'pg_xlog', 'archive_status')
                    out = str(cmd.getoutput('ls', '-t', archive_dir)[0])
                    for line in out.splitlines():
                        if line.endswith('.done'):
                            name = line[:-5]
                            if xlog.is_any_xlog_file(name):
                                remote_status['last_archived_wal'] = name
                                break
        except (PostgresConnectionError, OSError) as e:
            _logger.warn("Error retrieving PostgreSQL status: %s", e)
        return remote_status
Beispiel #15
0
 def get_remote_status(self):
     '''Get the status of the remote server'''
     pg_settings = ('archive_mode', 'archive_command', 'data_directory')
     pg_query_keys = ('server_txt_version', 'current_xlog')
     result = dict.fromkeys(pg_settings + pg_query_keys, None)
     try:
         with self.pg_connect() as conn:
             for name in pg_settings:
                 result[name] = self.get_pg_setting(name)
             try:
                 cur = conn.cursor()
                 cur.execute("SELECT version()")
                 result['server_txt_version'] = cur.fetchone()[0].split()[1]
             except:
                 result['server_txt_version'] = None
             try:
                 cur = conn.cursor()
                 cur.execute(
                     'SELECT pg_xlogfile_name(pg_current_xlog_location())')
                 result['current_xlog'] = cur.fetchone()[0]
             except:
                 result['current_xlog'] = None
     except:
         pass
     cmd = Command(self.ssh_command, self.ssh_options)
     result['last_shipped_wal'] = None
     if result['data_directory'] and result['archive_command']:
         archive_dir = os.path.join(result['data_directory'], 'pg_xlog',
                                    'archive_status')
         out = cmd.getoutput(None, 'ls', '-tr', archive_dir)[0]
         for line in out.splitlines():
             if line.endswith('.done'):
                 name = line[:-5]
                 if xlog.is_wal_file(name):
                     result['last_shipped_wal'] = line[:-5]
     return result
Beispiel #16
0
 def run_post_backup_script(self, backup_info):
     '''
     Run the post_backup_script if configured.
     This method must never throw any exception
     '''
     try:
         script = self.config.post_backup_script
         if script:
             _logger.info("Attempt to run post_backup_script: %s", script)
             cmd = Command(
                 script,
                 env_append=self.build_script_env(backup_info, 'post'),
                 shell=True, check=False)
             ret = cmd()
             _logger.info("post_backup_script returned %d", ret)
     except Exception:
         _logger.exception('Exception running post_backup_script')
Beispiel #17
0
 def __init__(self, path=None):
     # initialize a shell
     self.internal_cmd = Command(cmd='sh', args=['-c'], path=path)
Beispiel #18
0
 def __init__(self, path=None):
     # initialize a shell
     self.internal_cmd = Command(cmd="sh", args=["-c"], path=path)
Beispiel #19
0
    def fetch_remote_status(self):
        """
        Execute checks for replication-based wal archiving

        This method does not raise any exception in case of errors,
        but set the missing values to None in the resulting dictionary.

        :rtype: dict[str, None|str]
        """
        result = dict.fromkeys(
            ('pg_receivexlog_compatible', 'pg_receivexlog_installed',
             'pg_receivexlog_path', 'pg_receivexlog_version'), None)

        # Detect a pg_receivexlog executable
        pg_receivexlog = utils.which("pg_receivexlog",
                                     self.backup_manager.server.path)

        # Test pg_receivexlog existence
        if pg_receivexlog:
            result["pg_receivexlog_installed"] = True
            result["pg_receivexlog_path"] = pg_receivexlog
        else:
            result["pg_receivexlog_installed"] = False
            return result

        receivexlog = Command(pg_receivexlog, check=True)

        # Obtain the `pg_receivexlog` version
        try:
            receivexlog("--version")
            splitter_version = receivexlog.out.strip().split()
            result["pg_receivexlog_version"] = splitter_version[-1]
            receivexlog_version = Version(
                utils.simplify_version(result["pg_receivexlog_version"]))
        except CommandFailedException as e:
            receivexlog_version = None
            _logger.debug("Error invoking pg_receivexlog: %s", e)

        # Retrieve the PostgreSQL versionn
        pg_version = None
        if self.server.streaming is not None:
            pg_version = self.server.streaming.server_major_version

        # If one of the version is unknown we cannot compare them
        if receivexlog_version is None or pg_version is None:
            return result

        # pg_version is not None so transform into a Version object
        # for easier comparison between versions
        pg_version = Version(pg_version)

        # pg_receivexlog 9.2 is compatible only with PostgreSQL 9.2.
        if "9.2" == pg_version == receivexlog_version:
            result["pg_receivexlog_compatible"] = True

        # other versions are compatible with lesser versions of PostgreSQL
        # WARNING: The development versions of `pg_receivexlog` are considered
        # higher than the stable versions here, but this is not an issue
        # because it accepts everything that is less than
        # the `pg_receivexlog` version(e.g. '9.6' is less than '9.6devel')
        elif "9.2" < pg_version <= receivexlog_version:
            result["pg_receivexlog_compatible"] = True

        else:
            result["pg_receivexlog_compatible"] = False

        return result
Beispiel #20
0
 def __init__(self, path=None):
     # initialize a shell
     self.cmd = Command(cmd='sh -c', shell=True, path=path)