]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Deactivate LV before removing
authorDirk Mueller <dirk@dmllr.de>
Fri, 17 Jan 2014 15:45:32 +0000 (16:45 +0100)
committerDirk Mueller <dirk@dmllr.de>
Thu, 13 Feb 2014 17:14:33 +0000 (18:14 +0100)
With certain versions of LVM2, removing an active LV can end up with

  Unable to deactivate open XXX
  libdevmapper exiting with 1 device(s) still suspended.

which causes any lvm command afterwards to hang endlessly on
trying to access the suspended volume. This seems to be caused
by a race with udev, so lets be conservative and do the deactivation,
then wait for udev and then finish the removal.

Closes-Bug: #1270192

Change-Id: I4703133180567090878ea5047dd29d9f97ad85ab

cinder/brick/local_dev/lvm.py

index caccbb087f49eb7b8246953ff911e6675a03bdc1..0c8c10f813aed5ef3872f166cba00e37a5030560 100644 (file)
@@ -558,10 +558,41 @@ class LVM(executor.Executor):
         :param name: Name of LV to delete
 
         """
+
+        def run_udevadm_settle():
+            self._execute('udevadm', 'settle',
+                          root_helper=self._root_helper, run_as_root=True,
+                          check_exit_code=False)
+
         try:
-            self._execute('lvremove',
-                          '-f',
-                          '%s/%s' % (self.vg_name, name),
+            need_force_remove = False
+            # LV removal seems to be a race with udev in
+            # some cases (see LP #1270192), so we do it in several steps:
+
+            # - Deactivate the LV/Snapshot, which triggers udev events
+            # - Wait for udev to finish its job with udevadmn settle
+            # - Remove the LV
+
+            try:
+                self._execute('lvchange', '-y', '-an',
+                              '%s/%s' % (self.vg_name, name),
+                              root_helper=self._root_helper, run_as_root=True)
+            except putils.ProcessExecutionError as err:
+                mesg = (_('Error during lvchange -an: CMD: %(command)s, '
+                        'RESPONSE: %(response)s') %
+                        {'command': err.cmd, 'response': err.stderr})
+                LOG.debug(mesg)
+                need_force_remove = True
+
+            run_udevadm_settle()
+
+            cmd = ['lvremove', ]
+
+            # if deactivation failed, use the --force, lvm!
+            if need_force_remove:
+                cmd.append('-f')
+            cmd.append('%s/%s' % (self.vg_name, name))
+            self._execute(*cmd,
                           root_helper=self._root_helper, run_as_root=True)
         except putils.ProcessExecutionError as err:
             mesg = (_('Error reported running lvremove: CMD: %(command)s, '
@@ -570,9 +601,7 @@ class LVM(executor.Executor):
             LOG.debug(mesg)
 
             LOG.debug(_('Attempting udev settle and retry of lvremove...'))
-            self._execute('udevadm', 'settle',
-                          root_helper=self._root_helper,
-                          run_as_root=True)
+            run_udevadm_settle()
 
             self._execute('lvremove',
                           '-f',