[Yum-devel] [PATCH] add the fs-snapshot plugin to yum-utils V2
Mike Bonnet
mikeb at redhat.com
Mon Dec 14 16:31:30 UTC 2009
On 12/14/2009 10:34 AM, Josef Bacik wrote:
> Hello,
>
> This is my second pass at a yum plugin for snapshotting filesystems
> before running a yum transaction. I've cleaned the plugin up quite a
> bit since the original posting, and hopefully I've made it easy to add
> in other snapshotting methods for things like LVM and NILFS2. This
> patch is complete with man pages, but the only real option that I've
> added is an exclude option to exclude certain mount points from being
> snapshotted. I've tested this heavily on my system which is btrfs
> (the only thing this plugin will snapshot currently) and it works
> fine. Thanks,
This looks pretty awesome. A couple of comments below:
diff --git a/docs/yum-fs-snapshot.1 b/docs/yum-fs-snapshot.1
new file mode 100644
index 0000000..7686fc4
--- /dev/null
+++ b/docs/yum-fs-snapshot.1
@@ -0,0 +1,30 @@
+.\" yum-fs-snapshot
+.TH YUM-FS-SNAPSHOT 1 "14 DECEMBER 2009" "" "User Manuals"
+.SH NAME
+.B yum-fs-snapshot
+.SH SYNOPSIS
+The
+.B yum-fs-snapshot
+package
+.SH DESCRIPTION
+.BR yum-fs-snapshot(1)
+is a Yum plugin for taking snapshots of your filesystems before running a yum
+transaction. By default it will take a snapshot of any filesystem that can be
+snapshotted, that includes
Missing/truncated text above?
+.SH FILES
+.B yum-fs-snapshot
+uses a configuration file for its specific actions:
+.I /etc/yum/pluginconf.d/fs-snapshot.conf
+.RS
+.SH SEE ALSO
+.nf
+.I yum-fs-snapshot.conf (5)
+.fi
+.PP
+.SH AUTHORS
+.nf
+Josef Bacik <josef at toxicpanda.com>
+.fi
+.SH "SEE ALSO"
+.BR yum (1)
+.BR yum-fs-snapshot.conf (5)
diff --git a/docs/yum-fs-snapshot.conf.5 b/docs/yum-fs-snapshot.conf.5
new file mode 100644
index 0000000..da0bbbb
--- /dev/null
+++ b/docs/yum-fs-snapshot.conf.5
@@ -0,0 +1,28 @@
+.\" yum-fs-snapshot.conf.5
+.TH YUM-FS-SNAPSHOT.CONF 5 "14 DECEMBER 2009" "" "File Formats"
+.SH NAME
+.B yum-fs-snapshot.conf(5)
+
+.SH SYNOPSIS
+.B yum-fs-snapshot.conf(5)
+is the configuration file for
+.B yum-fs-snapshot(1)
+Yum plugin for snapshotting your filesystems before running a yum transaction.
+By default, this plugin will snapshot all filesystems that it is capable of
+snapshotting.
+.SH FILES
+.I /etc/yum/pluginconf.d/fs-snapshot.conf
+.SH FILE FORMAT
+.B yum-fs-snapshot.conf(5)
+utilizes configuration options in the form of
+.IP OPTION=VALUE
+.SH OPTION
+.IP exclude
+This is a space delimited list of the mount points you do not wish to have
+snapshotted by this plugin.
+.SH AUTHOR
+.RS
+Josef Bacik <josef at toxicpanda.com>
+.RS
+.SH SEE ALSO
+.BR yum-fs-snapshot(1)
diff --git a/plugins/fs-snapshot/fs-snapshot.conf b/plugins/fs-snapshot/fs-snapshot.conf
new file mode 100644
index 0000000..e7002aa
--- /dev/null
+++ b/plugins/fs-snapshot/fs-snapshot.conf
@@ -0,0 +1,2 @@
+[main]
+enabled = 1
diff --git a/plugins/fs-snapshot/fs-snapshot.py b/plugins/fs-snapshot/fs-snapshot.py
new file mode 100644
index 0000000..6d2b243
--- /dev/null
+++ b/plugins/fs-snapshot/fs-snapshot.py
@@ -0,0 +1,119 @@
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Copyright 2009 Red Hat, Inc
+# written by Josef Bacik <josef at toxicpanda.com>
+
+"""
+This plugin creates a snapshot before any yum update or yum remove operation on
+any btrfs filesystem that is affected by the update/remove operation.
+
+This is a giant hammer. Please be aware that if you rollback to a previous
+snapshot that any other changes that occured to the filesystem after the
+snapshot takes place will not be in the snapshot. You of course can mount the
+newer version elsewhere and copy the new versions of the files back to your
+rolled-back snapshot. You have been warned.
+"""
+
+from yum.plugins import TYPE_CORE
+from yum.constants import *
+import os
+import sys
+import time
+from subprocess import Popen,PIPE
+
+requires_api_version = '2.4'
+plugin_type = (TYPE_CORE,)
+
+def pretrans_hook(conduit):
+ """
+ This runs before the transaction starts. Try to snapshot anything and
+ everything that is snapshottable, since we do not know what an RPM will
+ modify (thank you scriptlets).
+ """
Should this be using /proc/mounts instead? Could avoid some cases where /etc/mtab doesn't exist or gets out of sync with the actual mounts.
+ if not os.path.exists("/etc/mtab"):
+ conduit.info(1, "fs-snapshot: could not open /etc/mtab")
+ pass
+
+ excludeList = conduit.confString('main', 'exclude', default="").split()
+
+ try:
+ mtabfile = open('/etc/mtab', 'r')
+ for line in mtabfile.readlines():
+ device, mntpnt, type, rest = line.split(' ', 3)
+
+ # skip bind mounts
+ if not rest.find("bind") == -1:
+ continue
+
+ skip = False
+ for pnt in excludeList:
+ if pnt == mntpnt:
+ skip = True
+ break
+
+ if skip:
+ continue
+
+ rc = _create_snapshot(device, mntpnt, type, conduit)
+ if rc == 1:
+ conduit.info(1, "fs-snapshot: error snapshotting " + mntpnt)
+ mtabfile.close()
+ except Exception as (errno, strerror):
+ conduit.info(1, "fs-snapshot: error reading /etc/mtab")
+ pass
+
+def _create_snapshot(device, mntpnt, type, conduit):
+ """
+ Determines if the device is capable of being snapshotted and then calls the
+ appropriate snapshotting function. The idea is you could add something for
+ lvm snapshots, nilfs2 or whatever else here.
+ """
+
+ # at some point it would be nice to add filtering here, so users can specify
+ # which filesystems they don't want snapshotted and we'd automatically match
+ # them here and just return.
+
+ if type == "btrfs":
+ return _create_btrfs_snapshot(mntpnt, conduit)
+
+ return 0
+
+def _create_btrfs_snapshot(dir, conduit):
+ """
+ Runs the commands necessary for a snapshot. Basically its just
+
+ btrfsctl -c /dir/to/snapshot #this syncs the fs
+ btrfsctl -s /dir/to/snapshot/yum-month-date-year-hour:minute
+ /dir/to/snapshot
+
+ and then we're done.
+ """
+
+ #/etc/mtab doesn't have /'s at the end of the mount point, unless of course
+ #the mountpoint is /
+ if not dir.endswith("/"):
+ dir = dir + "/"
+
+ snapname = dir + "yum-" + time.strftime("%m-%d-%y-%H:%M")
+ conduit.info(1, "fs-snapshot: snapshotting " + dir + ": " + snapname)
+ p = Popen(["btrfsctl", "-c", dir], stdout=PIPE, stderr=PIPE)
+ err = p.stderr.read()
+ if err:
+ return 1
You should use p.wait() to check for a non-zero return code from the subprocess, and use that as a failure indicator, along with the stderr output.
+ p = Popen(["btrfsctl", "-s", snapname, dir], stdout=PIPE, stderr=PIPE)
+ err = p.stderr.read()
+ if err:
+ return 1
Same here.
+ return 0
diff --git a/yum-utils.spec b/yum-utils.spec
index 7e62b05..72aec08 100644
--- a/yum-utils.spec
+++ b/yum-utils.spec
@@ -353,6 +353,15 @@ to a repository on the local filesystem, and (re)build that repository. This
means that anything you've downloaded will always exist, even if the original
repo. removes it (and can thus. be reinstalled/downgraded/etc.).
+%package -n yum-plugin-fs-snapshot
+Summary: Yum plugin to automatically snapshot your filesystems during updates
+Group: System Environment/Base
+Requires: yum >= 3.2.22
+
+%description -n yum-plugin-fs-snapshot
+When this plugin is installed it will automatically snapshot any
+filesystem that is touched by the packages in a yum update or yum remove.
+
%prep
%setup -q
@@ -387,6 +396,7 @@ plugins="\
auto-update-debuginfo \
show-leaves \
local \
+ fs-snapshot \
"
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/yum/pluginconf.d/ $RPM_BUILD_ROOT/usr/lib/yum-plugins/
@@ -598,6 +608,12 @@ fi
%config(noreplace) %{_sysconfdir}/yum/pluginconf.d/local.conf
/usr/lib/yum-plugins/local.*
+%files -n yum-plugin-fs-snapshot
+%defattr(1, root, root)
+%config(noreplace) %{_sysconfdir}/yum/pluginconf.d/fs-snapshot.conf
+/usr/lib/yum-plugins/fs-snapshot.*
+%{_mandir}/man1/yum-fs-snapshot.1.*
+%{_mandir}/man5/yum-fs-snapshot.conf.5.*
%changelog
* Sun Nov 8 2009 Tim Lauridsen <timlau at fedoraproject.org>
More information about the Yum-devel
mailing list