示例#1
0
    def pgespresso_stop_backup(self, backup_label):
        """
        Execute a pgespresso_stop_backup

        This method returns a dictionary containing the following data:

         * end_wal
         * timestamp

        :param str backup_label: backup label as returned
            by pgespress_start_backup
        :rtype: psycopg2.extras.DictRow
        """
        try:
            conn = self.connect()
            # Issue a rollback to release any unneeded lock
            conn.rollback()
            cur = conn.cursor(cursor_factory=DictCursor)
            cur.execute(
                "SELECT pgespresso_stop_backup(%s) AS end_wal, "
                "now() AS timestamp", (backup_label, ))
            return cur.fetchone()
        except (PostgresConnectionError, psycopg2.Error) as e:
            msg = "Error issuing pgespresso_stop_backup() command: %s" % (
                str(e).strip())
            _logger.debug(msg)
            raise PostgresException(
                '%s\n'
                'HINT: You might have to manually execute '
                'pgespresso_abort_backup() on your PostgreSQL '
                'server' % msg)
示例#2
0
    def stop_exclusive_backup(self):
        """
        Calls pg_stop_backup() on the PostgreSQL server

        This method returns a dictionary containing the following data:

         * location
         * file_name
         * file_offset
         * timestamp

        :rtype: psycopg2.extras.DictRow
        """
        try:
            conn = self.connect()

            # Rollback to release the transaction, as the pg_stop_backup
            # invocation could will wait until the current WAL file is shipped
            conn.rollback()

            # Stop the backup
            cur = conn.cursor(cursor_factory=DictCursor)
            cur.execute("SELECT location, "
                        "(pg_xlogfile_name_offset(location)).*, "
                        "now() AS timestamp "
                        "FROM pg_stop_backup() AS location")

            return cur.fetchone()
        except (PostgresConnectionError, psycopg2.Error) as e:
            msg = "Error issuing pg_stop_backup command: %s" % str(e).strip()
            _logger.debug(msg)
            raise PostgresException(
                'Cannot terminate exclusive backup. '
                'You might have to manually execute pg_stop_backup '
                'on your PostgreSQL server')
示例#3
0
    def pgespresso_start_backup(self, backup_label):
        """
        Execute a pgespresso_start_backup

        :param str backup_label: label for the backup
        :rtype: tuple
        """
        try:
            conn = self.connect()

            # Issue a rollback to release any unneeded lock
            conn.rollback()

            # Start the concurrent backup
            cur = conn.cursor(cursor_factory=DictCursor)
            cur.execute(
                'SELECT pgespresso_start_backup(%s,%s) AS backup_label, '
                'now() AS timestamp',
                (backup_label, self.config.immediate_checkpoint))
            start_row = cur.fetchone()

            # Rollback to release the transaction, as the connection
            # is to be retained until the end of backup
            conn.rollback()

            return start_row
        except (PostgresConnectionError, psycopg2.Error) as e:
            msg = "pgespresso_start_backup(): %s" % str(e).strip()
            _logger.debug(msg)
            raise PostgresException(msg)
示例#4
0
    def start_exclusive_backup(self, label):
        """
        Calls pg_start_backup() on the PostgreSQL server

        This method returns a dictionary containing the following data:

         * location
         * file_name
         * file_offset
         * timestamp

        :param str label: descriptive string to identify the backup
        :rtype: psycopg2.extras.DictRow
        """
        try:
            conn = self.connect()

            # Rollback to release the transaction, as the pg_start_backup
            # invocation can last up to PostgreSQL's checkpoint_timeout
            conn.rollback()

            # Start an exclusive backup
            cur = conn.cursor(cursor_factory=DictCursor)
            if self.server_version < 80400:
                cur.execute(
                    "SELECT location, "
                    "({pg_walfile_name_offset}(location)).*, "
                    "now() AS timestamp "
                    "FROM pg_start_backup(%s) AS location".format(
                        **self.name_map), (label, ))
            else:
                cur.execute(
                    "SELECT location, "
                    "({pg_walfile_name_offset}(location)).*, "
                    "now() AS timestamp "
                    "FROM pg_start_backup(%s,%s) AS location".format(
                        **self.name_map),
                    (label, self.config.immediate_checkpoint))

            start_row = cur.fetchone()

            # Rollback to release the transaction, as the connection
            # is to be retained until the end of backup
            conn.rollback()

            return start_row
        except (PostgresConnectionError, psycopg2.Error) as e:
            msg = "pg_start_backup(): %s" % str(e).strip()
            _logger.debug(msg)
            raise PostgresException(msg)
示例#5
0
    def start_exclusive_backup(self, backup_label):
        """
        Calls pg_start_backup() on the PostgreSQL server

        :param str backup_label: label for the backup returned by Postgres
        :rtype: tuple
        """
        try:
            conn = self.connect()

            # Issue a rollback to release any unneeded lock
            conn.rollback()

            # Start the exclusive backup
            cur = conn.cursor(cursor_factory=DictCursor)
            if self.server_version < 80400:
                cur.execute(
                    "SELECT location, "
                    "(pg_xlogfile_name_offset(location)).*, "
                    "now() AS timestamp "
                    "FROM pg_start_backup(%s) AS location",
                    (backup_label,))
            else:
                cur.execute(
                    "SELECT location, "
                    "(pg_xlogfile_name_offset(location)).*, "
                    "now() AS timestamp "
                    "FROM pg_start_backup(%s,%s) AS location",
                    (backup_label,
                     self.config.immediate_checkpoint))

            start_row = cur.fetchone()

            # Rollback to release the transaction, as the connection
            # is to be retained until the end of backup
            conn.rollback()

            return start_row
        except (PostgresConnectionError, psycopg2.Error) as e:
            msg = "pg_start_backup(): %s" % str(e).strip()
            _logger.debug(msg)
            raise PostgresException(msg)
示例#6
0
    def start_concurrent_backup(self, label):
        """
        Calls pg_start_backup on the PostgreSQL server using the
        API introduced with version 9.6

        This method returns a dictionary containing the following data:

         * location
         * timeline
         * timestamp

        :param str label: descriptive string to identify the backup
        :rtype: psycopg2.extras.DictRow
        """
        try:
            conn = self.connect()

            # Rollback to release the transaction, as the pg_start_backup
            # invocation can last up to PostgreSQL's checkpoint_timeout
            conn.rollback()

            # Start the backup using the api introduced in postgres 9.6
            cur = conn.cursor(cursor_factory=DictCursor)
            cur.execute(
                "SELECT location, "
                "(SELECT timeline_id "
                "FROM pg_control_checkpoint()) AS timeline, "
                "now() AS timestamp "
                "FROM pg_start_backup(%s, %s, FALSE) AS location",
                (label, self.config.immediate_checkpoint))
            start_row = cur.fetchone()

            # Rollback to release the transaction, as the connection
            # is to be retained until the end of backup
            conn.rollback()

            return start_row
        except (PostgresConnectionError, psycopg2.Error) as e:
            msg = "pg_start_backup command: %s" % (str(e).strip(), )
            _logger.debug(msg)
            raise PostgresException(msg)
示例#7
0
 def drop_repslot(self, slot_name):
     """
     Drop a physical replication slot using the streaming connection
     :param str slot_name: Replication slot name
     """
     cursor = self._cursor()
     try:
         # In the following query, the slot name is directly passed
         # to the DROP_REPLICATION_SLOT command, without any
         # quoting. This is a characteristic of the streaming
         # connection, otherwise if will fail with a generic
         # "syntax error"
         cursor.execute('DROP_REPLICATION_SLOT %s' % slot_name)
     except psycopg2.DatabaseError as exc:
         if exc.pgcode == UNDEFINED_OBJECT:
             # A replication slot with the that name does not exist
             raise PostgresInvalidReplicationSlot()
         if exc.pgcode == OBJECT_IN_USE:
             # The replication slot is still in use
             raise PostgresReplicationSlotInUse()
         else:
             raise PostgresException(str(exc).strip())
示例#8
0
    def pgespresso_start_backup(self, label):
        """
        Execute a pgespresso_start_backup

        This method returns a dictionary containing the following data:

         * backup_label
         * timestamp

        :param str label: descriptive string to identify the backup
        :rtype: psycopg2.extras.DictRow
        """
        try:
            conn = self.connect()

            # Rollback to release the transaction,
            # as the pgespresso_start_backup invocation can last
            # up to PostgreSQL's checkpoint_timeout
            conn.rollback()

            # Start the concurrent backup using pgespresso
            cur = conn.cursor(cursor_factory=DictCursor)
            cur.execute(
                'SELECT pgespresso_start_backup(%s,%s) AS backup_label, '
                'now() AS timestamp',
                (label, self.config.immediate_checkpoint))

            start_row = cur.fetchone()

            # Rollback to release the transaction, as the connection
            # is to be retained until the end of backup
            conn.rollback()

            return start_row
        except (PostgresConnectionError, psycopg2.Error) as e:
            msg = "pgespresso_start_backup(): %s" % str(e).strip()
            _logger.debug(msg)
            raise PostgresException(msg)
示例#9
0
 def create_physical_repslot(self, slot_name):
     """
     Create a physical replication slot using the streaming connection
     :param str slot_name: Replication slot name
     """
     cursor = self._cursor()
     try:
         # In the following query, the slot name is directly passed
         # to the CREATE_REPLICATION_SLOT command, without any
         # quoting. This is a characteristic of the streaming
         # connection, otherwise if will fail with a generic
         # "syntax error"
         cursor.execute('CREATE_REPLICATION_SLOT %s PHYSICAL' % slot_name)
     except psycopg2.DatabaseError as exc:
         if exc.pgcode == DUPLICATE_OBJECT:
             # A replication slot with the same name exists
             raise PostgresDuplicateReplicationSlot()
         elif exc.pgcode == CONFIGURATION_LIMIT_EXCEEDED:
             # Unable to create a new physical replication slot.
             # All slots are full.
             raise PostgresReplicationSlotsFull()
         else:
             raise PostgresException(str(exc).strip())
示例#10
0
    def stop_concurrent_backup(self):
        """
        Calls pg_stop_backup on the PostgreSQL server using the
        API introduced with version 9.6

        This method returns a dictionary containing the following data:

         * location
         * timeline
         * backup_label
         * timestamp

        :rtype: psycopg2.extras.DictRow
        """
        try:
            conn = self.connect()

            # Rollback to release the transaction, as the pg_stop_backup
            # invocation could will wait until the current WAL file is shipped
            conn.rollback()

            # Stop the backup  using the api introduced with version 9.6
            cur = conn.cursor(cursor_factory=DictCursor)
            cur.execute(
                'SELECT end_row.lsn AS location, '
                '(SELECT CASE WHEN pg_is_in_recovery() '
                'THEN min_recovery_end_timeline ELSE timeline_id END '
                'FROM pg_control_checkpoint(), pg_control_recovery()'
                ') AS timeline, '
                'end_row.labelfile AS backup_label, '
                'now() AS timestamp FROM pg_stop_backup(FALSE) AS end_row')

            return cur.fetchone()
        except (PostgresConnectionError, psycopg2.Error) as e:
            msg = "Error issuing pg_stop_backup command: %s" % str(e).strip()
            _logger.debug(msg)
            raise PostgresException(msg)