Commit 048eeb2b authored by Iustin Pop's avatar Iustin Pop
Browse files

Workaround changed LVM behaviour



The vgreduce command has changed behaviour from when we initially
wrote the code (2.02.02 versus 2.02.66, 4 years delta):

- if there are LVs which will be impacted, it requires --force
- otherwise refuses to proceed, but it still returns exit code 0

We handle this by looking to see if it returns "Wrote out consistent
volume group" (behaviour unchanged), or if it complains about
"--force"; in the case it didn't complete, we retry the operation.

We improve a bit the checking of "vgs", as it uses to fail silently
and we didn't detect it.

New tests for this function should test, I believe, all the expected
variations; at the least we now have data files with the expected
output.
Signed-off-by: default avatarIustin Pop <iustin@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
parent 5d0566de
......@@ -683,6 +683,7 @@ python_tests = \
test/ganeti.runtime_unittest.py \
test/ganeti.serializer_unittest.py \
test/ganeti.ssh_unittest.py \
test/ganeti.storage_unittest.py \
test/ganeti.tools.ensure_dirs_unittest.py \
test/ganeti.uidpool_unittest.py \
test/ganeti.utils.algo_unittest.py \
......@@ -1077,7 +1078,7 @@ check-local: check-dirs
fi; \
for file in doc/iallocator.rst doc/hooks.rst; do \
if test "`sed -ne '4 p' $(top_srcdir)/$$file`" != \
"Documents Ganeti version $$expver"; then \
"Documents Ganeti version $$expver"; then \
echo "Incorrect version in $$file, expected $$expver"; \
exit 1; \
fi; \
......
#
#
# Copyright (C) 2009, 2011 Google Inc.
# Copyright (C) 2009, 2011, 2012 Google Inc.
#
# 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
......@@ -406,6 +406,7 @@ class LvmVgStorage(_LvmBase):
"""
LIST_COMMAND = "vgs"
VGREDUCE_COMMAND = "vgreduce"
# Make sure to update constants.VALID_STORAGE_FIELDS when changing field
# definitions.
......@@ -418,7 +419,7 @@ class LvmVgStorage(_LvmBase):
(constants.SF_ALLOCATABLE, [], True),
]
def _RemoveMissing(self, name):
def _RemoveMissing(self, name, _runcmd_fn=utils.RunCmd):
"""Runs "vgreduce --removemissing" on a volume group.
@type name: string
......@@ -428,13 +429,23 @@ class LvmVgStorage(_LvmBase):
# Ignoring vgreduce exit code. Older versions exit with an error even tough
# the VG is already consistent. This was fixed in later versions, but we
# cannot depend on it.
result = utils.RunCmd(["vgreduce", "--removemissing", name])
result = _runcmd_fn([self.VGREDUCE_COMMAND, "--removemissing", name])
# Keep output in case something went wrong
vgreduce_output = result.output
result = utils.RunCmd(["vgs", "--noheadings", "--nosuffix", name])
if result.failed:
# work around newer LVM version
if ("Wrote out consistent volume group" not in vgreduce_output or
"vgreduce --removemissing --force" in vgreduce_output):
# we need to re-run with --force
result = _runcmd_fn([self.VGREDUCE_COMMAND, "--removemissing",
"--force", name])
vgreduce_output += "\n" + result.output
result = _runcmd_fn([self.LIST_COMMAND, "--noheadings",
"--nosuffix", name])
# we also need to check the output
if result.failed or "Couldn't find device with uuid" in result.output:
raise errors.StorageError(("Volume group '%s' still not consistent,"
" 'vgreduce' output: %r,"
" 'vgs' output: %r") %
......
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'.
Couldn't find all physical volumes for volume group xenvg.
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'.
Couldn't find all physical volumes for volume group xenvg.
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'.
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'.
Wrote out consistent volume group xenvg
Couldn't find device with uuid bHRa26-svpL-ihJX-e0S4-2HNz-wAAi-AlBFtl.
WARNING: Partial LV 4ba7abfa-8459-43b6-b00f-c016244980f0.disk0 needs to be repaired or removed.
WARNING: Partial LV e972960d-4e35-46b2-9cda-7029916b28c1.disk0_data needs to be repaired or removed.
WARNING: Partial LV e972960d-4e35-46b2-9cda-7029916b28c1.disk0_meta needs to be repaired or removed.
WARNING: Partial LV 4fa40b51-dd4d-4fd9-aef1-35cc3a0f1f11.disk0_data needs to be repaired or removed.
WARNING: Partial LV 4fa40b51-dd4d-4fd9-aef1-35cc3a0f1f11.disk0_meta needs to be repaired or removed.
WARNING: Partial LV 0a184b34-1270-4f1a-94df-86da2167cfee.disk0_data needs to be repaired or removed.
WARNING: Partial LV 0a184b34-1270-4f1a-94df-86da2167cfee.disk0_meta needs to be repaired or removed.
WARNING: Partial LV 7e49c8a9-9c65-4e76-810e-bd3d7a1d97a9.disk0_data needs to be repaired or removed.
WARNING: Partial LV 7e49c8a9-9c65-4e76-810e-bd3d7a1d97a9.disk0_meta needs to be repaired or removed.
WARNING: Partial LV 290a3fd4-c035-4fbe-9a18-f5a0889bd45d.disk0_data needs to be repaired or removed.
WARNING: Partial LV 290a3fd4-c035-4fbe-9a18-f5a0889bd45d.disk0_meta needs to be repaired or removed.
WARNING: Partial LV c579be32-c041-4f1b-ae3e-c58aac9c2593.disk0_data needs to be repaired or removed.
WARNING: Partial LV c579be32-c041-4f1b-ae3e-c58aac9c2593.disk0_meta needs to be repaired or removed.
WARNING: Partial LV 47524563-3788-4a89-a61f-4274134dea73.disk0_data needs to be repaired or removed.
WARNING: Partial LV 47524563-3788-4a89-a61f-4274134dea73.disk0_meta needs to be repaired or removed.
WARNING: Partial LV ede9f706-a0dc-4202-96f2-1728240bbf05.disk0_data needs to be repaired or removed.
WARNING: Partial LV ede9f706-a0dc-4202-96f2-1728240bbf05.disk0_meta needs to be repaired or removed.
WARNING: Partial LV 731d9f1b-3f2f-4860-85b3-217a36b9c48e.disk1_data needs to be repaired or removed.
WARNING: Partial LV 731d9f1b-3f2f-4860-85b3-217a36b9c48e.disk1_meta needs to be repaired or removed.
WARNING: Partial LV f449ccfd-4e6b-42d6-9a52-838371988ab5.disk0_data needs to be repaired or removed.
WARNING: Partial LV f449ccfd-4e6b-42d6-9a52-838371988ab5.disk0_meta needs to be repaired or removed.
WARNING: Partial LV 69bb4f61-fd0c-4c89-a57f-5285ae99b3bd.disk0_data needs to be repaired or removed.
WARNING: Partial LV 9c29c24a-97ed-4fc7-b479-7a3385365a71.disk0 needs to be repaired or removed.
WARNING: Partial LV a919d93e-0f51-4e4d-9018-e25ee7d5b36b.disk0 needs to be repaired or removed.
WARNING: Partial LV d2501e6b-56a4-43b6-8856-471e5d49e892.disk0_data needs to be repaired or removed.
WARNING: Partial LV d2501e6b-56a4-43b6-8856-471e5d49e892.disk0_meta needs to be repaired or removed.
WARNING: Partial LV 31a1f85a-ecc8-40c0-88aa-e694626906a3.disk0 needs to be repaired or removed.
WARNING: Partial LV d124d70a-4776-4e00-bf0d-43511c29c534.disk0_data needs to be repaired or removed.
WARNING: Partial LV d124d70a-4776-4e00-bf0d-43511c29c534.disk0_meta needs to be repaired or removed.
WARNING: Partial LV f73b4499-34ec-4f70-a543-e43152a8644a.disk0 needs to be repaired or removed.
WARNING: There are still partial LVs in VG xenvg.
To remove them unconditionally use: vgreduce --removemissing --force.
Proceeding to remove empty missing PVs.
Couldn't find device with uuid NzfYON-F7ky-1Szf-aGf1-v8Xa-Bt1W-8V3bou.
Wrote out consistent volume group xenvg
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'.
Couldn't find all physical volumes for volume group xenvg.
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'.
Couldn't find all physical volumes for volume group xenvg.
Volume group xenvg not found
Couldn't find device with uuid bHRa26-svpL-ihJX-e0S4-2HNz-wAAi-AlBFtl.
xenvg 2 52 0 wz-pn- 1.31t 1.07t
#!/usr/bin/python
#
# Copyright (C) 2012 Google Inc.
#
# 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
# 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., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
"""Script for testing ganeti.storage"""
import re
import unittest
import random
from ganeti import constants
from ganeti import utils
from ganeti import compat
from ganeti import errors
from ganeti import storage
import testutils
class TestVGReduce(testutils.GanetiTestCase):
VGNAME = "xenvg"
LIST_CMD = storage.LvmVgStorage.LIST_COMMAND
VGREDUCE_CMD = storage.LvmVgStorage.VGREDUCE_COMMAND
def _runCmd(self, cmd, **kwargs):
if not self.run_history:
self.fail("Empty run results")
exp_cmd, result = self.run_history.pop(0)
self.assertEqual(cmd, exp_cmd)
return result
def testOldVersion(self):
lvmvg = storage.LvmVgStorage()
stdout = self._ReadTestData("vgreduce-removemissing-2.02.02.txt")
vgs_fail = self._ReadTestData("vgs-missing-pvs-2.02.02.txt")
self.run_history = [
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME],
utils.RunResult(0, None, stdout, "", "", None, None)),
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME],
utils.RunResult(0, None, "", "", "", None, None)),
]
lvmvg._RemoveMissing(self.VGNAME, _runcmd_fn=self._runCmd)
self.assertEqual(self.run_history, [])
for ecode, out in [(1, ""), (0, vgs_fail)]:
self.run_history = [
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME],
utils.RunResult(0, None, stdout, "", "", None, None)),
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME],
utils.RunResult(ecode, None, out, "", "", None, None)),
]
self.assertRaises(errors.StorageError, lvmvg._RemoveMissing, self.VGNAME,
_runcmd_fn=self._runCmd)
self.assertEqual(self.run_history, [])
def testNewVersion(self):
lvmvg = storage.LvmVgStorage()
stdout1 = self._ReadTestData("vgreduce-removemissing-2.02.66-fail.txt")
stdout2 = self._ReadTestData("vgreduce-removemissing-2.02.66-ok.txt")
vgs_fail = self._ReadTestData("vgs-missing-pvs-2.02.66.txt")
# first: require --fail, check that it's used
self.run_history = [
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME],
utils.RunResult(0, None, stdout1, "", "", None, None)),
([self.VGREDUCE_CMD, "--removemissing", "--force", self.VGNAME],
utils.RunResult(0, None, stdout2, "", "", None, None)),
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME],
utils.RunResult(0, None, "", "", "", None, None)),
]
lvmvg._RemoveMissing(self.VGNAME, _runcmd_fn=self._runCmd)
self.assertEqual(self.run_history, [])
# second: make sure --fail is not used if not needed
self.run_history = [
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME],
utils.RunResult(0, None, stdout2, "", "", None, None)),
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME],
utils.RunResult(0, None, "", "", "", None, None)),
]
lvmvg._RemoveMissing(self.VGNAME, _runcmd_fn=self._runCmd)
self.assertEqual(self.run_history, [])
# third: make sure we error out if vgs doesn't find the volume
for ecode, out in [(1, ""), (0, vgs_fail)]:
self.run_history = [
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME],
utils.RunResult(0, None, stdout1, "", "", None, None)),
([self.VGREDUCE_CMD, "--removemissing", "--force", self.VGNAME],
utils.RunResult(0, None, stdout2, "", "", None, None)),
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME],
utils.RunResult(ecode, None, out, "", "", None, None)),
]
self.assertRaises(errors.StorageError, lvmvg._RemoveMissing, self.VGNAME,
_runcmd_fn=self._runCmd)
self.assertEqual(self.run_history, [])
if __name__ == "__main__":
testutils.GanetiTestProgram()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment