Beispiel #1
0
    def _dry_run(self, volume, snapshot, datadir):
        """Implement dry-run for LVM snapshots.
        """
        LOG.info("* Would snapshot source volume %s/%s as %s/%s (size=%s)",
                 volume.vg_name, volume.lv_name, volume.vg_name, snapshot.name,
                 format_bytes(snapshot.size * int(volume.vg_extent_size)))
        LOG.info("* Would mount on %s", snapshot.mountpoint
                 or 'generated temporary directory')

        if getmount(self.target_directory) == getmount(datadir):
            LOG.error(
                "Backup directory %s is on the same filesystem as "
                "the source logical volume %s.", self.target_directory,
                volume.device_name())
            LOG.error("This will result in very poor performance and "
                      "has a high potential for failed backups.")
            raise BackupError("Improper backup configuration for LVM.")
Beispiel #2
0
    def backup(self):
        """Run a backup by running through a LVM snapshot against the device
        the MySQL datadir resides on
        """
        # connect to mysql and lookup what we're supposed to snapshot
        try:
            self.client.connect()
            datadir = os.path.realpath(self.client.show_variable("datadir"))
        except MySQLError as exc:
            raise BackupError("[%d] %s" % exc.args)

        LOG.info("Backing up %s via snapshot", datadir)
        # lookup the logical volume mysql's datadir sits on

        try:
            volume = LogicalVolume.lookup_from_fspath(datadir)
        except LookupError as exc:
            raise BackupError("Failed to lookup logical volume for %s: %s" %
                              (datadir, str(exc)))
        except Exception as ex:
            raise BackupError("Failed to lookup logical volume for %s: %s" %
                              (datadir, str(ex)))

        # create a snapshot manager
        snapshot = build_snapshot(self.config["mysql-lvm"],
                                  volume,
                                  suppress_tmpdir=self.dry_run)
        # calculate where the datadirectory on the snapshot will be located
        rpath = relpath(datadir, getmount(datadir))
        snap_datadir = os.path.abspath(os.path.join(snapshot.mountpoint,
                                                    rpath))
        # setup actions to perform at each step of the snapshot process
        setup_actions(
            snapshot=snapshot,
            config=self.config,
            client=self.client,
            snap_datadir=snap_datadir,
            spooldir=self.target_directory,
        )

        if self.dry_run:
            return _dry_run(self.target_directory, volume, snapshot, datadir)

        try:
            snapshot.start(volume)
        except CallbackFailuresError as exc:
            for callback, error in exc.errors:
                LOG.error("%s: %s", callback, error)
            raise BackupError(
                "Error occurred during snapshot process. Aborting.")
        except LVMCommandError as exc:
            # Something failed in the snapshot process
            raise BackupError(str(exc))
        except BaseException as ex:
            LOG.debug(ex)

        return None
Beispiel #3
0
    def _dry_run(self, volume, snapshot, datadir):
        """Implement dry-run for LVM snapshots.
        """
        LOG.info("* Would snapshot source volume %s/%s as %s/%s (size=%s)",
             volume.vg_name,
             volume.lv_name,
             volume.vg_name,
             snapshot.name,
             format_bytes(snapshot.size*int(volume.vg_extent_size)))
        LOG.info("* Would mount on %s",
             snapshot.mountpoint or 'generated temporary directory')

        snapshot_mountpoint = snapshot.mountpoint or tempfile.gettempdir()
        if getmount(self.target_directory) == getmount(datadir):
            LOG.error("Backup directory %s is on the same filesystem as "
                      "the source logical volume %s.",
                      self.target_directory, volume.device_name())
            LOG.error("This will result in very poor performance and "
                      "has a high potential for failed backups.")
            raise BackupError("Improper backup configuration for LVM.")
Beispiel #4
0
    def backup(self):
        """Run a backup by running through a LVM snapshot against the device
        the MySQL datadir resides on
        """
        # connect to mysql and lookup what we're supposed to snapshot
        try:
            self.client.connect()
            datadir = os.path.realpath(self.client.show_variable("datadir"))
        except MySQLError as exc:
            raise BackupError("[%d] %s" % exc.args)

        LOG.info("Backing up %s via snapshot", datadir)
        # lookup the logical volume mysql's datadir sits on

        try:
            volume = LogicalVolume.lookup_from_fspath(datadir)
        except LookupError as exc:
            raise BackupError("Failed to lookup logical volume for %s: %s" % (datadir, str(exc)))
        except Exception as ex:
            raise BackupError("Failed to lookup logical volume for %s: %s" % (datadir, str(ex)))

        # create a snapshot manager
        snapshot = build_snapshot(self.config["mysql-lvm"], volume, suppress_tmpdir=self.dry_run)
        # calculate where the datadirectory on the snapshot will be located
        rpath = relpath(datadir, getmount(datadir))
        snap_datadir = os.path.abspath(os.path.join(snapshot.mountpoint, rpath))
        # setup actions to perform at each step of the snapshot process
        setup_actions(
            snapshot=snapshot,
            config=self.config,
            client=self.client,
            snap_datadir=snap_datadir,
            spooldir=self.target_directory,
        )

        if self.dry_run:
            return _dry_run(self.target_directory, volume, snapshot, datadir)

        try:
            snapshot.start(volume)
        except CallbackFailuresError as exc:
            for callback, error in exc.errors:
                LOG.error("%s: %s", callback, error)
            raise BackupError("Error occurred during snapshot process. Aborting.")
        except LVMCommandError as exc:
            # Something failed in the snapshot process
            raise BackupError(str(exc))
        except BaseException as ex:
            LOG.debug(ex)

        return None
Beispiel #5
0
    def backup(self):
        """Run a backup by running through a LVM snapshot against the device
        the MySQL datadir resides on
        """
        # connect to mysql and lookup what we're supposed to snapshot
        self.client.connect()
        datadir = os.path.realpath(self.client.show_variable('datadir'))
        LOG.info("Backing up %s via snapshot", datadir)
        # lookup the logical volume mysql's datadir sits on
        try:
            volume = LogicalVolume.lookup_from_fspath(datadir)
        except LookupError as exc:
            raise BackupError("Failed to lookup logical volume for %s: %s" %
                              (datadir, str(exc)))
        except Exception as ex:
            LOG.debug(ex)

        try:
            # create a snapshot manager
            snapshot = build_snapshot(self.config['mysql-lvm'],
                                      volume,
                                      suppress_tmpdir=self.dry_run)
            # calculate where the datadirectory on the snapshot will be located
            rpath = relpath(datadir, getmount(datadir))
            snap_datadir = os.path.abspath(
                os.path.join(snapshot.mountpoint or '/tmp', rpath))

            LOG.debug("Snap Datadir: %s" % snap_datadir)
            # setup actions to perform at each step of the snapshot process
            setup_actions(snapshot=snapshot,
                          config=self.config,
                          client=self.client,
                          datadir=snap_datadir,
                          spooldir=self.target_directory,
                          plugin=self.mysqldump_plugin)
        except Exception as ex:
            LOG.debug(ex)

        if self.config['mysqldump']['bin-log-position']:
            LOG.warn("bin-log-position is not supported with mysqldump-lvm.")
            LOG.warn(
                "Replication status will be saved to the "
                "[mysql:replication] section in %s", self.config.filename)
            self.config['mysqldump']['bin-log-position'] = False

        if self.dry_run:
            self._dry_run(volume, snapshot, datadir)
            # do the normal mysqldump dry-run
            return self.mysqldump_plugin.backup()

        try:
            snapshot.start(volume)
        except CallbackFailuresError as exc:
            # XXX: one of our actions failed.  Log this better
            for callback, error in exc.errors:
                LOG.error("%s", error)
            raise BackupError(
                "Error occurred during snapshot process. Aborting.")
        except LVMCommandError as exc:
            # Something failed in the snapshot process
            raise BackupError(str(exc))
Beispiel #6
0
        LOG.info("Backing up %s via snapshot", datadir)
        # lookup the logical volume mysql's datadir sits on

        try:
            volume = LogicalVolume.lookup_from_fspath(datadir)
        except LookupError, exc:
            raise BackupError("Failed to lookup logical volume for %s: %s" %
                              (datadir, str(exc)))


        # create a snapshot manager
        snapshot = build_snapshot(self.config['mysql-lvm'], volume,
                                  suppress_tmpdir=self.dry_run)
        # calculate where the datadirectory on the snapshot will be located
        rpath = relpath(datadir, getmount(datadir))
        snap_datadir = os.path.abspath(os.path.join(snapshot.mountpoint, rpath))
        # setup actions to perform at each step of the snapshot process
        setup_actions(snapshot=snapshot,
                      config=self.config,
                      client=self.client,
                      snap_datadir=snap_datadir,
                      spooldir=self.target_directory)

        if self.dry_run:
            return self._dry_run(volume, snapshot, datadir)

        try:
            snapshot.start(volume)
        except CallbackFailuresError, exc:
            # XXX: one of our actions failed.  Log this better
Beispiel #7
0
        LOG.info("Backing up %s via snapshot", datadir)
        # lookup the logical volume mysql's datadir sits on

        try:
            volume = LogicalVolume.lookup_from_fspath(datadir)
        except LookupError, exc:
            raise BackupError("Failed to lookup logical volume for %s: %s" %
                              (datadir, str(exc)))

        # create a snapshot manager
        snapshot = build_snapshot(self.config['mysql-lvm'],
                                  volume,
                                  suppress_tmpdir=self.dry_run)
        # calculate where the datadirectory on the snapshot will be located
        rpath = relpath(datadir, getmount(datadir))
        snap_datadir = os.path.abspath(os.path.join(snapshot.mountpoint,
                                                    rpath))
        # setup actions to perform at each step of the snapshot process
        setup_actions(snapshot=snapshot,
                      config=self.config,
                      client=self.client,
                      snap_datadir=snap_datadir,
                      spooldir=self.target_directory)

        if self.dry_run:
            return self._dry_run(volume, snapshot, datadir)

        try:
            snapshot.start(volume)
        except CallbackFailuresError, exc:
Beispiel #8
0
class MysqlDumpLVMBackup(object):
    """A Holland Backup plugin suitable for performing LVM snapshots of a 
    filesystem underlying a live MySQL instance.

    This plugin produces tar archives of a MySQL data directory.
    """
    CONFIGSPEC = CONFIGSPEC

    def __init__(self, name, config, target_directory, dry_run=False):
        self.config = config
        self.config.validate_config(self.CONFIGSPEC)
        LOG.debug("Validated config: %r", self.config)
        self.name = name
        self.target_directory = target_directory
        self.dry_run = dry_run
        self.client = connect_simple(self.config['mysql:client'])
        self.mysqldump_plugin = MySQLDumpPlugin(name, config, target_directory,
                                                dry_run)

    def estimate_backup_size(self):
        """Estimate the backup size this plugin will produce

        This is currently the total directory size of the MySQL datadir
        """

        return self.mysqldump_plugin.estimate_backup_size()

    def configspec(self):
        """INI Spec for the configuration values this plugin supports"""
        return self.CONFIGSPEC

    def backup(self):
        """Run a backup by running through a LVM snapshot against the device
        the MySQL datadir resides on
        """
        # connect to mysql and lookup what we're supposed to snapshot
        self.client.connect()
        datadir = os.path.realpath(self.client.show_variable('datadir'))
        LOG.info("Backing up %s via snapshot", datadir)
        # lookup the logical volume mysql's datadir sits on
        try:
            volume = LogicalVolume.lookup_from_fspath(datadir)
        except LookupError, exc:
            raise BackupError("Failed to lookup logical volume for %s: %s" %
                              (datadir, str(exc)))

        if self.dry_run:
            _dry_run(volume)
            # do the normal mysqldump dry-run
            return self.mysqldump_plugin.backup()

        # create a snapshot manager
        snapshot = build_snapshot(self.config['mysql-lvm'], volume)
        # calculate where the datadirectory on the snapshot will be located
        rpath = relpath(datadir, getmount(datadir))
        snap_datadir = os.path.abspath(os.path.join(snapshot.mountpoint,
                                                    rpath))
        # setup actions to perform at each step of the snapshot process
        setup_actions(snapshot=snapshot,
                      config=self.config,
                      client=self.client,
                      datadir=snap_datadir,
                      spooldir=self.target_directory,
                      plugin=self.mysqldump_plugin)

        try:
            snapshot.start(volume)
        except CallbackFailuresError, exc:
            # XXX: one of our actions failed.  Log this better
            for callback, error in exc.errors:
                LOG.error("%s", error)
            raise BackupError(
                "Error occurred during snapshot process. Aborting.")