Ejemplo n.º 1
0
    def get_snapshots(self, root=DEFAULT_POOL):
        snapshots = []

        datasets = self.get_datasets()
        for dataset in datasets:
            # BTRFS in kernel has a weird bug where listing will fail
            # immediately after a filesystem update.  Loop on list until
            # it is successful
            try_again = True
            failure = False
            while try_again:
                try:
                    subvol_reader = reader(StringIO(btrfs_cmd.subvolume.list("--sort=path", "-s", dataset)), delimiter=" ")
                    if failure:
                        log.debug("btrfs listing finished")
                    try_again = False
                except ErrorReturnCode_19:
                    if not failure:
                        failure = True
                        log.debug("btrfs listing failed")
            for row in subvol_reader:
                if 'btrfs-auto-snap' in row[-1:][0] and row[-1:][0].startswith('.btrfs-auto-snap'):
                    _, interval, label = row[-1:][0].split("/")
                    snapshots.append(Snapshot(self, dataset, interval, label, size=1))

        return snapshots
Ejemplo n.º 2
0
Archivo: fs.py Proyecto: gclawes/tardis
    def auto_snapshot(self, interval, keep):
        """create auto-snapshot set with interval,
        purging old snapshots"""
        fs_config = self.get_config()
        now = datetime.now()
        date = "%s-%s-%s-%sh%s" % (str(now.year), str(now.month).zfill(2),
                                   str(now.day).zfill(2),
                                   str(now.hour).zfill(2),
                                   str(now.minute).zfill(2))
        key = "auto-snapshot:%s" % interval

        to_snapshot = []
        exclude = []

        for dataset in sorted(fs_config.keys()):
            if fs_config[dataset]['auto-snapshot']:
                if key in fs_config[dataset].keys():
                    if fs_config[dataset][key]:
                        to_snapshot.append(dataset)
                    else:
                        exclude.append(dataset)
                else:
                    to_snapshot.append(dataset)
            else:
                exclude.append(dataset)

        log.debug("Snapshotting the following: %s" % ' '.join(to_snapshot))
        log.debug("Excluding the following: %s" % ' '.join(exclude))

        for dataset in to_snapshot:
            self.commit_snapshot(dataset, interval, date)
Ejemplo n.º 3
0
    def destroy_snapshot(self, name):
        """callout to zfs command to destroy snapshot"""
        # name = "%s@%s" % (filesystem, interval)

        if env.DRY_RUN:
            log.info("dry-run: would destroy %s" % name)
        else:
            log.debug("destroy_snapshot(%s)" % (name))
            if "@" in name:
                zfs_cmd.destroy(name)
            else:
                log.error("should not be destroying a dataset! name: %s" % name)
Ejemplo n.º 4
0
    def destroy_snapshot(self, name):
        """callout to btrfs command to destroy snapshot"""

        if env.DRY_RUN:
            log.info("dry-run: would destroy %s" % name)
        else:
            log.debug("destroy_snapshot(%s)" % (name))
            if os.access(name, os.F_OK):
                if "/.btrfs-auto-snap/" in name:
                    btrfs_cmd.subvolume.delete(name)
                else:
                    log.error("should not be destroying a dataset! name: %s" % name)
            else:
                log.error("cannot find %s" % name)
Ejemplo n.º 5
0
    def commit_snapshot(self, filesystem, interval, label):
        """call out to zfs command to create snapshot
        return a Snapshot object"""

        name = "%s@zfs-auto-snap_%s-%s" % (filesystem, interval, label)
        current_snapshots = [s.name for s in self.get_snapshots()]

        if name in current_snapshots:
            log.error("snapshot %s already exists, not overwriting!" % name)
            return

        if env.DRY_RUN:
            log.info("dry-run: would commit %s" % name)
        else:
            log.debug("commit_snapshot(%s, %s, %s)" % (filesystem, interval, label))
            zfs_cmd.snapshot(name)
Ejemplo n.º 6
0
    def is_enabled(cls):
        if os.geteuid() != 0:
            log.debug("btrfs is only enabled for the root user!")
            return False

        if not sys.platform.startswith('linux'):
            log.debug("btrfs is only enabled on linux!")
            return False

        elif BTRFS_AVAILABLE:
            if "v0.19" in btrfs_cmd("--version"):
                log.warning("'btrfs' command v0.19 is incompatible, please upgrade to at least v0.20 to enable btrfs")
                return False
            return True
        else:
            return False
Ejemplo n.º 7
0
    def commit_snapshot(self, dataset, interval, label):
        """call out to btrfs command to create snapshot
        return a Snapshot object"""

        snap_dir = os.path.join(dataset, '.btrfs-auto-snap')
        interval_dir = os.path.join(snap_dir, interval)
        destination = os.path.join(interval_dir, label)

        if os.path.exists(destination):
            log.error("snapshot %s already exists, not overwriting!" % destination)
            return

        # if interval_dir isn't a directory, and also isn't a file with that name
        # create the snapshot label directory
        if not os.path.isdir(interval_dir) and not os.path.exists(interval_dir):
            s = os.stat(snap_dir)
            os.mkdir(interval_dir)
            os.chown(interval_dir, s[stat.ST_UID], s[stat.ST_GID])

        if env.DRY_RUN:
            log.info("dry-run: would commit %s" % (destination))
        else:
            log.debug("commit_snapshot(%s, %s, %s)" % (dataset, interval, label))
            btrfs_cmd.subvolume.snapshot(dataset, destination)
Ejemplo n.º 8
0
import stat

from csv import reader
from StringIO import StringIO

from tardis import log, env, Snapshot
from tardis.fs import Filesystem

import re

try:
    from sh import btrfs as btrfs_cmd
    BTRFS_AVAILABLE = True
except:
    BTRFS_AVAILABLE = False
    log.debug("unable to find btrfs command")

from sh import ErrorReturnCode_19


def dir_is_writable(directory):
    s = os.stat(directory)
    mode = s[stat.ST_MODE]
    return bool(
        (mode & stat.S_IWUSR) or
        (mode & stat.S_IWGRP) or
        (mode & stat.S_IWOTH)
    )


class Btrfs(Filesystem):