Blame SOURCES/BZ-1047793-lvm-snapshot.patch

5e9bef
commit 13bbacb4dd25b83cd29389e0608fde1614537257
5e9bef
Author: Valentina Mukhamedzhanova <vmukhame@redhat.com>
5e9bef
Date:   Mon Jan 12 15:21:46 2015 +0100
5e9bef
5e9bef
     Multiple lvm fixes. BZ 1047793, BZ 1145485
5e9bef
    - add fssnap_abort_on_errors config option
5e9bef
    - fix default for fssnap_automatic_keep in the man page
5e9bef
    - add logging for automatic fssnap events
5e9bef
    - add lvm binary path test to _FSSnap.available
5e9bef
    - check for lvm2 and lvm2-python-libs packages instead of python-lvm
5e9bef
5e9bef
diff --git a/docs/yum.8 b/docs/yum.8
5e9bef
index 998a5ad..a0038f6 100644
5e9bef
--- a/docs/yum.8
5e9bef
+++ b/docs/yum.8
5e9bef
@@ -741,7 +741,7 @@ then you can create and delete snapshots using:
5e9bef
 .br 
5e9bef
 
5e9bef
 .br
5e9bef
-Configuration Options: \fBfssnap_automatic_pre\fP, \fBfssnap_automatic_post\fP, \fBfssnap_automatic_keep\fP, \fBfssnap_percentage\fP, \fBfssnap_devices\fP
5e9bef
+Configuration Options: \fBfssnap_automatic_pre\fP, \fBfssnap_automatic_post\fP, \fBfssnap_automatic_keep\fP, \fBfssnap_percentage\fP, \fBfssnap_devices\fP, \fBfssnap_abort_on_errors\fP
5e9bef
 
5e9bef
 .IP
5e9bef
 .IP "\fBfs\fP"
5e9bef
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
5e9bef
index 0362e85..272e07b 100644
5e9bef
--- a/docs/yum.conf.5
5e9bef
+++ b/docs/yum.conf.5
5e9bef
@@ -873,7 +873,7 @@ Boolean (1, 0, True, False, yes, no) Defaults to False
5e9bef
 .IP
5e9bef
 \fBfssnap_automatic_keep\fR
5e9bef
 How many old snapshots should yum keep when trying to automatically create a 
5e9bef
-new snapshot. Setting to 0 disables this feature. Default is '0'.
5e9bef
+new snapshot. Setting to 0 disables this feature. Default is '1'.
5e9bef
 
5e9bef
 .IP
5e9bef
 \fBfssnap_automatic_percentage\fR
5e9bef
@@ -887,6 +887,21 @@ first match (positive or negative) wins.
5e9bef
 Default is: !*/swap !*/lv_swap glob:/etc/yum/fssnap.d/*.conf
5e9bef
 
5e9bef
 .IP
5e9bef
+\fBfssnap_abort_on_errors\fR
5e9bef
+When fssnap_automatic_pre or fssnap_automatic_post is enabled, it's possible to specify which
5e9bef
+fssnap errors should make the transaction fail. The default is `any'.
5e9bef
+
5e9bef
+`broken-setup' - Abort current transaction if snapshot support is unavailable because
5e9bef
+lvm is missing or broken.
5e9bef
+
5e9bef
+`snapshot-failure' - Abort current transaction if creating a snapshot fails (e.g. there is not enough
5e9bef
+free space to make a snapshot).
5e9bef
+
5e9bef
+`any' - Abort current transaction if any of the above occurs.
5e9bef
+
5e9bef
+`none' - Never abort a transaction in case of errors.
5e9bef
+
5e9bef
+.IP
5e9bef
 \fBdepsolve_loop_limit\fR
5e9bef
 Set the number of times any attempt to depsolve before we just give up. This
5e9bef
 shouldn't be needed as yum should always solve or fail, however it has been
5e9bef
diff --git a/yum/__init__.py b/yum/__init__.py
5e9bef
index 6d2c078..347aa7c 100644
5e9bef
--- a/yum/__init__.py
5e9bef
+++ b/yum/__init__.py
5e9bef
@@ -1727,6 +1727,13 @@ much more problems).
5e9bef
         :raises: :class:`yum.Errors.YumRPMTransError` if there is a
5e9bef
            transaction cannot be completed
5e9bef
         """
5e9bef
+        if (self.conf.fssnap_automatic_pre or self.conf.fssnap_automatic_post) and not self.fssnap.available:
5e9bef
+            msg = _("Snapshot support not available.")
5e9bef
+            if self.conf.fssnap_abort_on_errors in ('broken-setup', 'any'):
5e9bef
+                raise Errors.YumRPMTransError(msg="Aborting transaction.", errors=msg)
5e9bef
+            else:
5e9bef
+                self.verbose_logger.critical(msg)
5e9bef
+
5e9bef
         if self.fssnap.available and ((self.conf.fssnap_automatic_pre or
5e9bef
                                        self.conf.fssnap_automatic_post) and
5e9bef
                                       self.conf.fssnap_automatic_keep):
5e9bef
@@ -1748,17 +1755,30 @@ much more problems).
5e9bef
                 if num > self.conf.fssnap_automatic_keep:
5e9bef
                     todel.append(snap['dev'])
5e9bef
             # Display something to the user?
5e9bef
-            self.fssnap.del_snapshots(devices=todel)
5e9bef
+            snaps = self.fssnap.del_snapshots(devices=todel)
5e9bef
+            if len(snaps):
5e9bef
+                self.verbose_logger.info(_("Deleted %u snapshots.") % len(snaps))
5e9bef
 
5e9bef
         if (self.fssnap.available and
5e9bef
             (not self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST) and
5e9bef
             self.conf.fssnap_automatic_pre)):
5e9bef
             if not self.fssnap.has_space(self.conf.fssnap_percentage):
5e9bef
-                msg = _("Not enough space to create pre. FS snapshot, aborting transaction.")
5e9bef
-                raise Errors.YumRPMTransError(msg=msg, errors=[])
5e9bef
+                msg = _("Not enough space to create pre. FS snapshot.")
5e9bef
+                if self.conf.fssnap_abort_on_errors in ('snapshot-failure', 'any'):
5e9bef
+                    raise Errors.YumRPMTransError(msg="Aborting transaction", errors=msg)
5e9bef
+                else:
5e9bef
+                    self.verbose_logger.critical(msg)
5e9bef
             else:
5e9bef
                 tags = {'*': ['reason=automatic']} # FIXME: pre. tags
5e9bef
-                self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags)
5e9bef
+                snaps = self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags)
5e9bef
+                if not snaps:
5e9bef
+                    msg = _("Failed to create snapshot")
5e9bef
+                    if self.conf.fssnap_abort_on_errors in ('snapshot-failure', 'any'):
5e9bef
+                        raise Errors.YumRPMTransError(msg="Aborting transaction", errors=msg)
5e9bef
+                    else:
5e9bef
+                        self.verbose_logger.critical(msg)
5e9bef
+                for (odev, ndev) in snaps:
5e9bef
+                    self.verbose_logger.info(_("Created snapshot from %s, results is: %s") % (odev, ndev))
5e9bef
 
5e9bef
         self.plugins.run('pretrans')
5e9bef
 
5e9bef
@@ -1895,11 +1915,14 @@ much more problems).
5e9bef
             self.conf.fssnap_automatic_post)):
5e9bef
             if not self.fssnap.has_space(self.conf.fssnap_percentage):
5e9bef
                 msg = _("Not enough space to create post trans FS snapshot.")
5e9bef
-                self.logger.critical(msg)
5e9bef
+                self.verbose_logger.critical(msg)
5e9bef
             else:
5e9bef
                 tags = {'*': ['reason=automatic']} # FIXME: post tags
5e9bef
-                self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags)
5e9bef
-
5e9bef
+                snaps = self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags)
5e9bef
+                if not snaps:
5e9bef
+                    self.verbose_logger.critical(_("Failed to create snapshot"))
5e9bef
+                for (odev, ndev) in snaps:
5e9bef
+                    self.verbose_logger.info(_("Created snapshot from %s, results is: %s") % (odev, ndev))
5e9bef
         return resultobject
5e9bef
 
5e9bef
     def verifyTransaction(self, resultobject=None, txmbr_cb=None):
5e9bef
diff --git a/yum/config.py b/yum/config.py
5e9bef
index 8eab5bc..02061ba 100644
5e9bef
--- a/yum/config.py
5e9bef
+++ b/yum/config.py
5e9bef
@@ -899,6 +899,7 @@ class YumConf(StartupConf):
5e9bef
     fssnap_devices = ListOption("!*/swap !*/lv_swap "
5e9bef
                                 "glob:/etc/yum/fssnap.d/*.conf",
5e9bef
                                 parse_default=True)
5e9bef
+    fssnap_abort_on_errors = SelectionOption('any', ('broken-setup', 'snapshot-failure', 'any', 'none'))
5e9bef
 
5e9bef
     depsolve_loop_limit = PositiveIntOption(100, names_of_0=["<forever>"])
5e9bef
 
5e9bef
diff --git a/yum/fssnapshots.py b/yum/fssnapshots.py
5e9bef
index e912ea1..9af252d 100755
5e9bef
--- a/yum/fssnapshots.py
5e9bef
+++ b/yum/fssnapshots.py
5e9bef
@@ -146,7 +143,8 @@ class _FSSnap(object):
5e9bef
             devices = []
5e9bef
 
5e9bef
         self.version = _ver
5e9bef
-        self.available = bool(lvm)
5e9bef
+        # Parts of the API seem to work even when lvm is not actually installed, hence the path test
5e9bef
+        self.available = bool(lvm and os.path.exists("/sbin/lvm"))
5e9bef
         self.postfix_static = "_yum_"
5e9bef
         self._postfix = None
5e9bef
         self._root = root
5e9bef
diff --git a/yumcommands.py b/yumcommands.py
5e9bef
index a18bc5c..e77d209 100644
5e9bef
--- a/yumcommands.py
5e9bef
+++ b/yumcommands.py
5e9bef
@@ -4264,11 +4264,13 @@ class FSSnapshotCommand(YumCommand):
5e9bef
             subcommand = 'summary'
5e9bef
 
5e9bef
         if not base.fssnap.available:
5e9bef
-            if not base.rpmdb.searchNames(['python-lvm']):
5e9bef
-                print _("Snapshot support not available, no python-lvm package installed.")
5e9bef
-            else:
5e9bef
-                print _("Snapshot support not available, python-lvm is old/broken.")
5e9bef
-            return 0, [basecmd + ' ' + subcommand + ' done']
5e9bef
+            msg = _("Snapshot support not available, please check your lvm installation.")
5e9bef
+            if not base.rpmdb.searchNames(['lvm2']):
5e9bef
+                msg += " " + _("No lvm2 package installed.")
5e9bef
+            if not base.rpmdb.searchNames(['lvm2-python-libs']):
5e9bef
+                msg += " " + _("No lvm2-python-libs package installed.")
5e9bef
+            print msg
5e9bef
+            return 1, [basecmd + ' ' + subcommand + ' done']
5e9bef
 
5e9bef
         if subcommand == 'list':
5e9bef
             snaps = base.fssnap.old_snapshots()
5e9bef
@@ -4301,10 +4303,11 @@ class FSSnapshotCommand(YumCommand):
5e9bef
         if subcommand == 'create':
5e9bef
             tags = {'*': ['reason=manual']}
5e9bef
             pc = base.conf.fssnap_percentage
5e9bef
-            for (odev, ndev) in base.fssnap.snapshot(pc, tags=tags):
5e9bef
-                print _("Created snapshot from %s, results is: %s") %(odev,ndev)
5e9bef
-            else:
5e9bef
+            snaps = base.fssnap.snapshot(pc, tags=tags)
5e9bef
+            if not snaps:
5e9bef
                 print _("Failed to create snapshots")
5e9bef
+            for (odev, ndev) in snaps:
5e9bef
+                print _("Created snapshot from %s, results is: %s") %(odev,ndev)
5e9bef
 
5e9bef
         if subcommand == 'summary':
5e9bef
             snaps = base.fssnap.old_snapshots()
5e9bef
commit 29440b1175411c3ccaca6010df8dec2d96088fbd
5e9bef
Author: Valentina Mukhamedzhanova <vmukhame@redhat.com>
5e9bef
Date:   Thu Jul 9 15:26:29 2015 +0200
5e9bef
5e9bef
    Stop caching fssnapshot postfixes and add microseconds
5e9bef
5e9bef
diff --git a/yum/fssnapshots.py b/yum/fssnapshots.py
5e9bef
index a07271d..10ec012 100755
5e9bef
--- a/yum/fssnapshots.py
5e9bef
+++ b/yum/fssnapshots.py
5e9bef
@@ -3,6 +3,7 @@
5e9bef
 import os
5e9bef
 import fnmatch
5e9bef
 import time
5e9bef
+from datetime import datetime
5e9bef
 
5e9bef
 import subprocess
5e9bef
 
5e9bef
@@ -228,23 +229,13 @@ class _FSSnap(object):
5e9bef
 
5e9bef
         return ret
5e9bef
 
5e9bef
-    def _get_postfix(self):
5e9bef
-        if self._postfix is None:
5e9bef
-            self._postfix = self.postfix_static
5e9bef
-            self._postfix += time.strftime("%Y%m%d%H%M%S")
5e9bef
-        return self._postfix
5e9bef
-
5e9bef
-    postfix = property(fget=lambda self: self._get_postfix(),
5e9bef
-                       fset=lambda self, value: setattr(self, "_postfix",value),
5e9bef
-                       fdel=lambda self: setattr(self, "_postfix", None),
5e9bef
-                       doc="postfix for snapshots")
5e9bef
 
5e9bef
     def snapshot(self, percentage=100, prefix='', postfix=None, tags={}):
5e9bef
         """ Attempt to take a snapshot, note that errors can happen after
5e9bef
             this function succeeds. """
5e9bef
 
5e9bef
         if postfix is None:
5e9bef
-            postfix = self.postfix
5e9bef
+            postfix = '%s%s' % (self.postfix_static, datetime.now().strftime("%Y%m%d%H%M%S.%f"))
5e9bef
 
5e9bef
         ret = []
5e9bef
         for vgname in self._vgnames:
5e9bef
commit 2678b0a2eb042e011bcafb507eae5ea3565c9110
5e9bef
Author: Valentina Mukhamedzhanova <vmukhame@redhat.com>
5e9bef
Date:   Mon Jul 13 16:28:32 2015 +0200
5e9bef
5e9bef
    Test for lvm binary before using.
5e9bef
5e9bef
diff --git a/yum/fssnapshots.py b/yum/fssnapshots.py
5e9bef
index 10ec012..70f80a0 100755
5e9bef
--- a/yum/fssnapshots.py
5e9bef
+++ b/yum/fssnapshots.py
5e9bef
@@ -155,7 +155,7 @@ class _FSSnap(object):
5e9bef
         if not self._devs:
5e9bef
             return
5e9bef
 
5e9bef
-        self._vgnames = _list_vg_names()
5e9bef
+        self._vgnames = _list_vg_names() if self.available else []
5e9bef
 
5e9bef
     def _use_dev(self, vgname, lv=None):
5e9bef
 
5e9bef
commit e756473a1b01f40f087488f72d002d9993843a84
5e9bef
Author: Valentina Mukhamedzhanova <vmukhame@redhat.com>
5e9bef
Date:   Wed Aug 12 12:54:55 2015 +0200
5e9bef
5e9bef
    Update not enough space messages for fssnapshot
5e9bef
5e9bef
diff --git a/yum/__init__.py b/yum/__init__.py
5e9bef
index 48956e9..84bea3e 100644
5e9bef
--- a/yum/__init__.py
5e9bef
+++ b/yum/__init__.py
5e9bef
@@ -1773,7 +1773,7 @@ much more problems).
5e9bef
             (not self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST) and
5e9bef
             self.conf.fssnap_automatic_pre)):
5e9bef
             if not self.fssnap.has_space(self.conf.fssnap_percentage):
5e9bef
-                msg = _("Not enough space to create pre. FS snapshot.")
5e9bef
+                msg = _("Not enough space on logical volumes to create pre. FS snapshot.")
5e9bef
                 if self.conf.fssnap_abort_on_errors in ('snapshot-failure', 'any'):
5e9bef
                     raise Errors.YumRPMTransError(msg="Aborting transaction", errors=msg)
5e9bef
                 else:
5e9bef
@@ -1926,7 +1926,7 @@ much more problems).
5e9bef
             (not self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST) and
5e9bef
             self.conf.fssnap_automatic_post)):
5e9bef
             if not self.fssnap.has_space(self.conf.fssnap_percentage):
5e9bef
-                msg = _("Not enough space to create post trans FS snapshot.")
5e9bef
+                msg = _("Not enough space on logical volumes to create post trans FS snapshot.")
5e9bef
                 self.verbose_logger.critical(msg)
5e9bef
             else:
5e9bef
                 tags = {'*': ['reason=automatic']} # FIXME: post tags
5e9bef
diff --git a/yumcommands.py b/yumcommands.py
5e9bef
index 4a39ddb..5234260 100644
5e9bef
--- a/yumcommands.py
5e9bef
+++ b/yumcommands.py
5e9bef
@@ -4311,7 +4311,7 @@ class FSSnapshotCommand(YumCommand):
5e9bef
             if base.fssnap.has_space(pc):
5e9bef
                 print _("Space available to take a snapshot.")
5e9bef
             else:
5e9bef
-                print _("Not enough space available to take a snapshot.")
5e9bef
+                print _("Not enough space available on logical volumes to take a snapshot.")
5e9bef
 
5e9bef
         if subcommand == 'create':
5e9bef
             tags = {'*': ['reason=manual']}