In many cases when reverting it is possible that the logical volume is still in
use
(due to unclean virtual machine shutdown for example). This results in the merge
being postponed and the user having to handle that manually later on. This patch
helps detecting such problems and attempts to reactivate the logical volume.
If reactivation fails, the postponed merging can still be detected later on, so
that the utility can function properly and handle this situation.
---
lvsetup/lvsetup.py | 101 ++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 80 insertions(+), 21 deletions(-)
diff --git a/lvsetup/lvsetup.py b/lvsetup/lvsetup.py
index 4f0006b..73c138b 100644
--- a/lvsetup/lvsetup.py
+++ b/lvsetup/lvsetup.py
@@ -2,6 +2,10 @@
Utility for taking shapshots from existing logical volumes
or creates such.
+@author: Plamen Dimitrov
+@copyright: Intra2net AG 2012
+@license: GPL v2
+
The main part of the lvm setup checks whether the provided volume group
exists and if not, creates one from the ramdisk. It then creates a logical
volume if there is no logical volume, takes a snapshot from the logical
@@ -37,12 +41,13 @@ The ramdisk volume group size is in MB.
import logging
import re, os, shutil, time
-from autotest.client import utils, test
+from autotest.client import utils
from autotest.client.shared import error
@error.context_aware
-def vg_ramdisk(vg_name, ramdisk_vg_size, ramdisk_basedir,
ramdisk_sparse_filename):
+def vg_ramdisk(vg_name, ramdisk_vg_size,
+ ramdisk_basedir, ramdisk_sparse_filename):
"""
Create vg on top of ram memory to speed up lv performance.
"""
@@ -181,7 +186,7 @@ def lv_remove(vg_name, lv_name):
(vg_name, lv_name), logging.info)
if not vg_check(vg_name):
- raise error.TestError("Volume group could not be found")
+ raise error.TestError("Volume group could not be found")
if not lv_check(vg_name, lv_name):
raise error.TestError("Logical volume could not be found")
@@ -201,7 +206,7 @@ def lv_create(vg_name, lv_name, lv_size, force_flag = True):
logging.info)
if not vg_check(vg_name):
- raise error.TestError("Volume group could not be found")
+ raise error.TestError("Volume group could not be found")
if lv_check(vg_name, lv_name) and not force_flag:
raise error.TestError("Logical volume already exists")
elif lv_check(vg_name, lv_name) and force_flag:
@@ -224,7 +229,7 @@ def lv_take_snapshot(vg_name, lv_name,
logging.info)
if not vg_check(vg_name):
- raise error.TestError("Volume group could not be found")
+ raise error.TestError("Volume group could not be found")
if lv_check(vg_name, lv_snapshot_name):
raise error.TestError("Snapshot already exists")
if not lv_check(vg_name, lv_name):
@@ -233,7 +238,20 @@ def lv_take_snapshot(vg_name, lv_name,
cmd = ("lvcreate --size " + lv_snapshot_size + " --snapshot " +
" --name " + lv_snapshot_name +
" /dev/" + vg_name + "/" + lv_name)
- result = utils.run(cmd)
+ try:
+ result = utils.run(cmd)
+ except error.CmdError, ex:
+ if ('Logical volume "%s" already exists in volume group "%s"' %
+ (lv_snapshot_name, vg_name) in ex.result_obj.stderr and
+ re.search(re.escape(lv_snapshot_name + " [active]"),
+ utils.run("lvdisplay").stdout)):
+ # the above conditions detect if merge of snapshot was postponed
+ logging.warning(("Logical volume %s is still active! " +
+ "Attempting to deactivate..."), lv_name)
+ lv_reactivate(vg_name, lv_name)
+ result = utils.run(cmd)
+ else:
+ raise ex
logging.info(result.stdout.rstrip())
@@ -244,29 +262,52 @@ def lv_revert(vg_name, lv_name, lv_snapshot_name):
"""
error.context("Reverting original logical volume to snapshot",
logging.info)
-
- if not vg_check(vg_name):
- raise error.TestError("Volume group could not be found")
- if not lv_check(vg_name, lv_snapshot_name):
- raise error.TestError("Snapshot could not be 2found")
- if (not lv_check(vg_name, lv_snapshot_name)
- and not lv_check(vg_name, lv_name)):
- raise error.TestError("Snapshot and its origin could not be found")
- if (lv_check(vg_name, lv_snapshot_name)
- and not lv_check(vg_name, lv_name)):
+ try:
+ if not vg_check(vg_name):
+ raise error.TestError("Volume group could not be found")
+ if not lv_check(vg_name, lv_snapshot_name):
+ raise error.TestError("Snapshot could not be found")
+ if (not lv_check(vg_name, lv_snapshot_name)
+ and not lv_check(vg_name, lv_name)):
+ raise error.TestError("Snapshot and its origin could not be found")
+ if (lv_check(vg_name, lv_snapshot_name)
+ and not lv_check(vg_name, lv_name)):
raise error.TestError("Snapshot origin could not be found")
- cmd = ("lvconvert --merge /dev/%s/%s"
- % (vg_name, lv_snapshot_name))
- result = utils.run(cmd)
- logging.info(result.stdout.rstrip())
+ cmd = ("lvconvert --merge /dev/%s/%s"
+ % (vg_name, lv_snapshot_name))
+ result = utils.run(cmd)
+ if ("Merging of snapshot %s will start next activation." %
+ lv_snapshot_name) in result.stdout:
+ raise error.TestError("The logical volume %s is still active" %
+ lv_name)
+ result = result.stdout.rstrip()
+
+ except error.TestError, ex:
+ # detect if merge of snapshot was postponed
+ # and attempt to reactivate the volume.
+ if (('Snapshot could not be found' in ex and
+ re.search(re.escape(lv_snapshot_name + " [active]"),
+ utils.run("lvdisplay").stdout))
+ or ("The logical volume %s is still active" % lv_name) in ex):
+ logging.warning(("Logical volume %s is still active! " +
+ "Attempting to deactivate..."), lv_name)
+ lv_reactivate(vg_name, lv_name)
+ result = "Continuing after reactivation"
+ elif 'Snapshot could not be found' in ex:
+ logging.error(ex)
+ result = "Could not revert to snapshot"
+ else:
+ raise ex
+ logging.info(result)
[email protected]_aware[M j7
[email protected]_aware
def lv_revert_with_snapshot(vg_name, lv_name,
lv_snapshot_name, lv_snapshot_size):
"""
Perform logical volume merge with snapshot and take a new snapshot.
+
"""
error.context("Reverting to snapshot and taking a new one",
logging.info)
@@ -274,3 +315,21 @@ def lv_revert_with_snapshot(vg_name, lv_name,
lv_revert(vg_name, lv_name, lv_snapshot_name)
lv_take_snapshot(vg_name, lv_name,
lv_snapshot_name, lv_snapshot_size)
+
+
[email protected]_aware
+def lv_reactivate(vg_name, lv_name, timeout = 10):
+ """
+ In case of unclean shutdowns some of the lvs is still active and merging
+ is postponed. Use this function to attempt to deactivate and reactivate
+ all of them to cause the merge to happen.
+ """
+ try:
+ utils.run("lvchange -an /dev/%s/%s" % (vg_name, lv_name))
+ time.sleep(timeout)
+ utils.run("lvchange -ay /dev/%s/%s" % (vg_name, lv_name))
+ time.sleep(timeout)
+ except error.CmdError:
+ logging.error(("Failed to reactivate %s - please, " +
+ "nuke the process that uses it first."), lv_name)
+ raise error.TestError("The logical volume %s is still active" %
lv_name)
--
1.7.11.7
_______________________________________________
Autotest-kernel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/autotest-kernel