Multiple lvm fixes. BZ 1047793, BZ 1145485 master
authorValentina Mukhamedzhanova <vmukhame@redhat.com>
Mon, 12 Jan 2015 14:21:46 +0000 (15:21 +0100)
committerValentina Mukhamedzhanova <vmukhame@redhat.com>
Mon, 12 Jan 2015 14:21:46 +0000 (15:21 +0100)
- add fssnap_abort_on_errors config option
- fix default for fssnap_automatic_keep in the man page
- add logging for automatic fssnap events
- add lvm binary path test to _FSSnap.available
- check for lvm2 and lvm2-python-libs packages instead of python-lvm

docs/yum.8
docs/yum.conf.5
yum/__init__.py
yum/config.py
yum/fssnapshots.py
yumcommands.py

index 998a5ad..a0038f6 100644 (file)
@@ -741,7 +741,7 @@ then you can create and delete snapshots using:
 .br 
 
 .br
-Configuration Options: \fBfssnap_automatic_pre\fP, \fBfssnap_automatic_post\fP, \fBfssnap_automatic_keep\fP, \fBfssnap_percentage\fP, \fBfssnap_devices\fP
+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
 
 .IP
 .IP "\fBfs\fP"
index 0362e85..272e07b 100644 (file)
@@ -873,7 +873,7 @@ Boolean (1, 0, True, False, yes, no) Defaults to False
 .IP
 \fBfssnap_automatic_keep\fR
 How many old snapshots should yum keep when trying to automatically create a 
-new snapshot. Setting to 0 disables this feature. Default is '0'.
+new snapshot. Setting to 0 disables this feature. Default is '1'.
 
 .IP
 \fBfssnap_automatic_percentage\fR
@@ -887,6 +887,21 @@ first match (positive or negative) wins.
 Default is: !*/swap !*/lv_swap glob:/etc/yum/fssnap.d/*.conf
 
 .IP
+\fBfssnap_abort_on_errors\fR
+When fssnap_automatic_pre or fssnap_automatic_post is enabled, it's possible to specify which
+fssnap errors should make the transaction fail. The default is `any'.
+
+`broken-setup' - Abort current transaction if snapshot support is unavailable because
+lvm is missing or broken.
+
+`snapshot-failure' - Abort current transaction if creating a snapshot fails (e.g. there is not enough
+free space to make a snapshot).
+
+`any' - Abort current transaction if any of the above occurs.
+
+`none' - Never abort a transaction in case of errors.
+
+.IP
 \fBdepsolve_loop_limit\fR
 Set the number of times any attempt to depsolve before we just give up. This
 shouldn't be needed as yum should always solve or fail, however it has been
index 6d2c078..347aa7c 100644 (file)
@@ -1727,6 +1727,13 @@ much more problems).
         :raises: :class:`yum.Errors.YumRPMTransError` if there is a
            transaction cannot be completed
         """
+        if (self.conf.fssnap_automatic_pre or self.conf.fssnap_automatic_post) and not self.fssnap.available:
+            msg = _("Snapshot support not available.")
+            if self.conf.fssnap_abort_on_errors in ('broken-setup', 'any'):
+                raise Errors.YumRPMTransError(msg="Aborting transaction.", errors=msg)
+            else:
+                self.verbose_logger.critical(msg)
+
         if self.fssnap.available and ((self.conf.fssnap_automatic_pre or
                                        self.conf.fssnap_automatic_post) and
                                       self.conf.fssnap_automatic_keep):
@@ -1748,17 +1755,30 @@ much more problems).
                 if num > self.conf.fssnap_automatic_keep:
                     todel.append(snap['dev'])
             # Display something to the user?
-            self.fssnap.del_snapshots(devices=todel)
+            snaps = self.fssnap.del_snapshots(devices=todel)
+            if len(snaps):
+                self.verbose_logger.info(_("Deleted %u snapshots.") % len(snaps))
 
         if (self.fssnap.available and
             (not self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST) and
             self.conf.fssnap_automatic_pre)):
             if not self.fssnap.has_space(self.conf.fssnap_percentage):
-                msg = _("Not enough space to create pre. FS snapshot, aborting transaction.")
-                raise Errors.YumRPMTransError(msg=msg, errors=[])
+                msg = _("Not enough space to create pre. FS snapshot.")
+                if self.conf.fssnap_abort_on_errors in ('snapshot-failure', 'any'):
+                    raise Errors.YumRPMTransError(msg="Aborting transaction", errors=msg)
+                else:
+                    self.verbose_logger.critical(msg)
             else:
                 tags = {'*': ['reason=automatic']} # FIXME: pre. tags
-                self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags)
+                snaps = self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags)
+                if not snaps:
+                    msg = _("Failed to create snapshot")
+                    if self.conf.fssnap_abort_on_errors in ('snapshot-failure', 'any'):
+                        raise Errors.YumRPMTransError(msg="Aborting transaction", errors=msg)
+                    else:
+                        self.verbose_logger.critical(msg)
+                for (odev, ndev) in snaps:
+                    self.verbose_logger.info(_("Created snapshot from %s, results is: %s") % (odev, ndev))
 
         self.plugins.run('pretrans')
 
@@ -1895,11 +1915,14 @@ much more problems).
             self.conf.fssnap_automatic_post)):
             if not self.fssnap.has_space(self.conf.fssnap_percentage):
                 msg = _("Not enough space to create post trans FS snapshot.")
-                self.logger.critical(msg)
+                self.verbose_logger.critical(msg)
             else:
                 tags = {'*': ['reason=automatic']} # FIXME: post tags
-                self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags)
-
+                snaps = self.fssnap.snapshot(self.conf.fssnap_percentage, tags=tags)
+                if not snaps:
+                    self.verbose_logger.critical(_("Failed to create snapshot"))
+                for (odev, ndev) in snaps:
+                    self.verbose_logger.info(_("Created snapshot from %s, results is: %s") % (odev, ndev))
         return resultobject
 
     def verifyTransaction(self, resultobject=None, txmbr_cb=None):
index 8eab5bc..02061ba 100644 (file)
@@ -899,6 +899,7 @@ class YumConf(StartupConf):
     fssnap_devices = ListOption("!*/swap !*/lv_swap "
                                 "glob:/etc/yum/fssnap.d/*.conf",
                                 parse_default=True)
+    fssnap_abort_on_errors = SelectionOption('any', ('broken-setup', 'snapshot-failure', 'any', 'none'))
 
     depsolve_loop_limit = PositiveIntOption(100, names_of_0=["<forever>"])
 
index e912ea1..9af252d 100755 (executable)
@@ -55,9 +55,6 @@ def _list_vg_names():
     names = lvm.listVgNames()
 
     if not names: # Could be just broken...
-        if not os.path.exists("/sbin/lvm"):
-            return [] # Minimal install etc.
-
         p = subprocess.Popen(["/sbin/lvm", "vgs", "-o", "vg_name"],
                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         err = p.wait()
@@ -146,7 +143,8 @@ class _FSSnap(object):
             devices = []
 
         self.version = _ver
-        self.available = bool(lvm)
+        # Parts of the API seem to work even when lvm is not actually installed, hence the path test
+        self.available = bool(lvm and os.path.exists("/sbin/lvm"))
         self.postfix_static = "_yum_"
         self._postfix = None
         self._root = root
index a18bc5c..e77d209 100644 (file)
@@ -4264,11 +4264,13 @@ class FSSnapshotCommand(YumCommand):
             subcommand = 'summary'
 
         if not base.fssnap.available:
-            if not base.rpmdb.searchNames(['python-lvm']):
-                print _("Snapshot support not available, no python-lvm package installed.")
-            else:
-                print _("Snapshot support not available, python-lvm is old/broken.")
-            return 0, [basecmd + ' ' + subcommand + ' done']
+            msg = _("Snapshot support not available, please check your lvm installation.")
+            if not base.rpmdb.searchNames(['lvm2']):
+                msg += " " + _("No lvm2 package installed.")
+            if not base.rpmdb.searchNames(['lvm2-python-libs']):
+                msg += " " + _("No lvm2-python-libs package installed.")
+            print msg
+            return 1, [basecmd + ' ' + subcommand + ' done']
 
         if subcommand == 'list':
             snaps = base.fssnap.old_snapshots()
@@ -4301,10 +4303,11 @@ class FSSnapshotCommand(YumCommand):
         if subcommand == 'create':
             tags = {'*': ['reason=manual']}
             pc = base.conf.fssnap_percentage
-            for (odev, ndev) in base.fssnap.snapshot(pc, tags=tags):
-                print _("Created snapshot from %s, results is: %s") %(odev,ndev)
-            else:
+            snaps = base.fssnap.snapshot(pc, tags=tags)
+            if not snaps:
                 print _("Failed to create snapshots")
+            for (odev, ndev) in snaps:
+                print _("Created snapshot from %s, results is: %s") %(odev,ndev)
 
         if subcommand == 'summary':
             snaps = base.fssnap.old_snapshots()