Revision 048eeb2b
b/Makefile.am | ||
---|---|---|
683 | 683 |
test/ganeti.runtime_unittest.py \ |
684 | 684 |
test/ganeti.serializer_unittest.py \ |
685 | 685 |
test/ganeti.ssh_unittest.py \ |
686 |
test/ganeti.storage_unittest.py \ |
|
686 | 687 |
test/ganeti.tools.ensure_dirs_unittest.py \ |
687 | 688 |
test/ganeti.uidpool_unittest.py \ |
688 | 689 |
test/ganeti.utils.algo_unittest.py \ |
... | ... | |
1077 | 1078 |
fi; \ |
1078 | 1079 |
for file in doc/iallocator.rst doc/hooks.rst; do \ |
1079 | 1080 |
if test "`sed -ne '4 p' $(top_srcdir)/$$file`" != \ |
1080 |
"Documents Ganeti version $$expver"; then \
|
|
1081 |
"Documents Ganeti version $$expver"; then \
|
|
1081 | 1082 |
echo "Incorrect version in $$file, expected $$expver"; \ |
1082 | 1083 |
exit 1; \ |
1083 | 1084 |
fi; \ |
b/lib/storage.py | ||
---|---|---|
1 | 1 |
# |
2 | 2 |
# |
3 | 3 |
|
4 |
# Copyright (C) 2009, 2011 Google Inc. |
|
4 |
# Copyright (C) 2009, 2011, 2012 Google Inc.
|
|
5 | 5 |
# |
6 | 6 |
# This program is free software; you can redistribute it and/or modify |
7 | 7 |
# it under the terms of the GNU General Public License as published by |
... | ... | |
406 | 406 |
|
407 | 407 |
""" |
408 | 408 |
LIST_COMMAND = "vgs" |
409 |
VGREDUCE_COMMAND = "vgreduce" |
|
409 | 410 |
|
410 | 411 |
# Make sure to update constants.VALID_STORAGE_FIELDS when changing field |
411 | 412 |
# definitions. |
... | ... | |
418 | 419 |
(constants.SF_ALLOCATABLE, [], True), |
419 | 420 |
] |
420 | 421 |
|
421 |
def _RemoveMissing(self, name): |
|
422 |
def _RemoveMissing(self, name, _runcmd_fn=utils.RunCmd):
|
|
422 | 423 |
"""Runs "vgreduce --removemissing" on a volume group. |
423 | 424 |
|
424 | 425 |
@type name: string |
... | ... | |
428 | 429 |
# Ignoring vgreduce exit code. Older versions exit with an error even tough |
429 | 430 |
# the VG is already consistent. This was fixed in later versions, but we |
430 | 431 |
# cannot depend on it. |
431 |
result = utils.RunCmd(["vgreduce", "--removemissing", name])
|
|
432 |
result = _runcmd_fn([self.VGREDUCE_COMMAND, "--removemissing", name])
|
|
432 | 433 |
|
433 | 434 |
# Keep output in case something went wrong |
434 | 435 |
vgreduce_output = result.output |
435 | 436 |
|
436 |
result = utils.RunCmd(["vgs", "--noheadings", "--nosuffix", name]) |
|
437 |
if result.failed: |
|
437 |
# work around newer LVM version |
|
438 |
if ("Wrote out consistent volume group" not in vgreduce_output or |
|
439 |
"vgreduce --removemissing --force" in vgreduce_output): |
|
440 |
# we need to re-run with --force |
|
441 |
result = _runcmd_fn([self.VGREDUCE_COMMAND, "--removemissing", |
|
442 |
"--force", name]) |
|
443 |
vgreduce_output += "\n" + result.output |
|
444 |
|
|
445 |
result = _runcmd_fn([self.LIST_COMMAND, "--noheadings", |
|
446 |
"--nosuffix", name]) |
|
447 |
# we also need to check the output |
|
448 |
if result.failed or "Couldn't find device with uuid" in result.output: |
|
438 | 449 |
raise errors.StorageError(("Volume group '%s' still not consistent," |
439 | 450 |
" 'vgreduce' output: %r," |
440 | 451 |
" 'vgs' output: %r") % |
b/test/data/vgreduce-removemissing-2.02.02.txt | ||
---|---|---|
1 |
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'. |
|
2 |
Couldn't find all physical volumes for volume group xenvg. |
|
3 |
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'. |
|
4 |
Couldn't find all physical volumes for volume group xenvg. |
|
5 |
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'. |
|
6 |
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'. |
|
7 |
Wrote out consistent volume group xenvg |
b/test/data/vgreduce-removemissing-2.02.66-fail.txt | ||
---|---|---|
1 |
Couldn't find device with uuid bHRa26-svpL-ihJX-e0S4-2HNz-wAAi-AlBFtl. |
|
2 |
WARNING: Partial LV 4ba7abfa-8459-43b6-b00f-c016244980f0.disk0 needs to be repaired or removed. |
|
3 |
WARNING: Partial LV e972960d-4e35-46b2-9cda-7029916b28c1.disk0_data needs to be repaired or removed. |
|
4 |
WARNING: Partial LV e972960d-4e35-46b2-9cda-7029916b28c1.disk0_meta needs to be repaired or removed. |
|
5 |
WARNING: Partial LV 4fa40b51-dd4d-4fd9-aef1-35cc3a0f1f11.disk0_data needs to be repaired or removed. |
|
6 |
WARNING: Partial LV 4fa40b51-dd4d-4fd9-aef1-35cc3a0f1f11.disk0_meta needs to be repaired or removed. |
|
7 |
WARNING: Partial LV 0a184b34-1270-4f1a-94df-86da2167cfee.disk0_data needs to be repaired or removed. |
|
8 |
WARNING: Partial LV 0a184b34-1270-4f1a-94df-86da2167cfee.disk0_meta needs to be repaired or removed. |
|
9 |
WARNING: Partial LV 7e49c8a9-9c65-4e76-810e-bd3d7a1d97a9.disk0_data needs to be repaired or removed. |
|
10 |
WARNING: Partial LV 7e49c8a9-9c65-4e76-810e-bd3d7a1d97a9.disk0_meta needs to be repaired or removed. |
|
11 |
WARNING: Partial LV 290a3fd4-c035-4fbe-9a18-f5a0889bd45d.disk0_data needs to be repaired or removed. |
|
12 |
WARNING: Partial LV 290a3fd4-c035-4fbe-9a18-f5a0889bd45d.disk0_meta needs to be repaired or removed. |
|
13 |
WARNING: Partial LV c579be32-c041-4f1b-ae3e-c58aac9c2593.disk0_data needs to be repaired or removed. |
|
14 |
WARNING: Partial LV c579be32-c041-4f1b-ae3e-c58aac9c2593.disk0_meta needs to be repaired or removed. |
|
15 |
WARNING: Partial LV 47524563-3788-4a89-a61f-4274134dea73.disk0_data needs to be repaired or removed. |
|
16 |
WARNING: Partial LV 47524563-3788-4a89-a61f-4274134dea73.disk0_meta needs to be repaired or removed. |
|
17 |
WARNING: Partial LV ede9f706-a0dc-4202-96f2-1728240bbf05.disk0_data needs to be repaired or removed. |
|
18 |
WARNING: Partial LV ede9f706-a0dc-4202-96f2-1728240bbf05.disk0_meta needs to be repaired or removed. |
|
19 |
WARNING: Partial LV 731d9f1b-3f2f-4860-85b3-217a36b9c48e.disk1_data needs to be repaired or removed. |
|
20 |
WARNING: Partial LV 731d9f1b-3f2f-4860-85b3-217a36b9c48e.disk1_meta needs to be repaired or removed. |
|
21 |
WARNING: Partial LV f449ccfd-4e6b-42d6-9a52-838371988ab5.disk0_data needs to be repaired or removed. |
|
22 |
WARNING: Partial LV f449ccfd-4e6b-42d6-9a52-838371988ab5.disk0_meta needs to be repaired or removed. |
|
23 |
WARNING: Partial LV 69bb4f61-fd0c-4c89-a57f-5285ae99b3bd.disk0_data needs to be repaired or removed. |
|
24 |
WARNING: Partial LV 9c29c24a-97ed-4fc7-b479-7a3385365a71.disk0 needs to be repaired or removed. |
|
25 |
WARNING: Partial LV a919d93e-0f51-4e4d-9018-e25ee7d5b36b.disk0 needs to be repaired or removed. |
|
26 |
WARNING: Partial LV d2501e6b-56a4-43b6-8856-471e5d49e892.disk0_data needs to be repaired or removed. |
|
27 |
WARNING: Partial LV d2501e6b-56a4-43b6-8856-471e5d49e892.disk0_meta needs to be repaired or removed. |
|
28 |
WARNING: Partial LV 31a1f85a-ecc8-40c0-88aa-e694626906a3.disk0 needs to be repaired or removed. |
|
29 |
WARNING: Partial LV d124d70a-4776-4e00-bf0d-43511c29c534.disk0_data needs to be repaired or removed. |
|
30 |
WARNING: Partial LV d124d70a-4776-4e00-bf0d-43511c29c534.disk0_meta needs to be repaired or removed. |
|
31 |
WARNING: Partial LV f73b4499-34ec-4f70-a543-e43152a8644a.disk0 needs to be repaired or removed. |
|
32 |
WARNING: There are still partial LVs in VG xenvg. |
|
33 |
To remove them unconditionally use: vgreduce --removemissing --force. |
|
34 |
Proceeding to remove empty missing PVs. |
b/test/data/vgreduce-removemissing-2.02.66-ok.txt | ||
---|---|---|
1 |
Couldn't find device with uuid NzfYON-F7ky-1Szf-aGf1-v8Xa-Bt1W-8V3bou. |
|
2 |
Wrote out consistent volume group xenvg |
b/test/data/vgs-missing-pvs-2.02.02.txt | ||
---|---|---|
1 |
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'. |
|
2 |
Couldn't find all physical volumes for volume group xenvg. |
|
3 |
Couldn't find device with uuid 'gg4cmC-4lrT-EN1v-39OA-6S2b-6eEI-wWlJJJ'. |
|
4 |
Couldn't find all physical volumes for volume group xenvg. |
|
5 |
Volume group xenvg not found |
b/test/data/vgs-missing-pvs-2.02.66.txt | ||
---|---|---|
1 |
Couldn't find device with uuid bHRa26-svpL-ihJX-e0S4-2HNz-wAAi-AlBFtl. |
|
2 |
xenvg 2 52 0 wz-pn- 1.31t 1.07t |
b/test/ganeti.storage_unittest.py | ||
---|---|---|
1 |
#!/usr/bin/python |
|
2 |
# |
|
3 |
|
|
4 |
# Copyright (C) 2012 Google Inc. |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or modify |
|
7 |
# it under the terms of the GNU General Public License as published by |
|
8 |
# the Free Software Foundation; either version 2 of the License, or |
|
9 |
# (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, but |
|
12 |
# WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 |
# General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
|
19 |
# 02110-1301, USA. |
|
20 |
|
|
21 |
|
|
22 |
"""Script for testing ganeti.storage""" |
|
23 |
|
|
24 |
import re |
|
25 |
import unittest |
|
26 |
import random |
|
27 |
|
|
28 |
from ganeti import constants |
|
29 |
from ganeti import utils |
|
30 |
from ganeti import compat |
|
31 |
from ganeti import errors |
|
32 |
from ganeti import storage |
|
33 |
|
|
34 |
import testutils |
|
35 |
|
|
36 |
|
|
37 |
class TestVGReduce(testutils.GanetiTestCase): |
|
38 |
VGNAME = "xenvg" |
|
39 |
LIST_CMD = storage.LvmVgStorage.LIST_COMMAND |
|
40 |
VGREDUCE_CMD = storage.LvmVgStorage.VGREDUCE_COMMAND |
|
41 |
|
|
42 |
def _runCmd(self, cmd, **kwargs): |
|
43 |
if not self.run_history: |
|
44 |
self.fail("Empty run results") |
|
45 |
exp_cmd, result = self.run_history.pop(0) |
|
46 |
self.assertEqual(cmd, exp_cmd) |
|
47 |
return result |
|
48 |
|
|
49 |
def testOldVersion(self): |
|
50 |
lvmvg = storage.LvmVgStorage() |
|
51 |
stdout = self._ReadTestData("vgreduce-removemissing-2.02.02.txt") |
|
52 |
vgs_fail = self._ReadTestData("vgs-missing-pvs-2.02.02.txt") |
|
53 |
self.run_history = [ |
|
54 |
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME], |
|
55 |
utils.RunResult(0, None, stdout, "", "", None, None)), |
|
56 |
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME], |
|
57 |
utils.RunResult(0, None, "", "", "", None, None)), |
|
58 |
] |
|
59 |
lvmvg._RemoveMissing(self.VGNAME, _runcmd_fn=self._runCmd) |
|
60 |
self.assertEqual(self.run_history, []) |
|
61 |
for ecode, out in [(1, ""), (0, vgs_fail)]: |
|
62 |
self.run_history = [ |
|
63 |
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME], |
|
64 |
utils.RunResult(0, None, stdout, "", "", None, None)), |
|
65 |
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME], |
|
66 |
utils.RunResult(ecode, None, out, "", "", None, None)), |
|
67 |
] |
|
68 |
self.assertRaises(errors.StorageError, lvmvg._RemoveMissing, self.VGNAME, |
|
69 |
_runcmd_fn=self._runCmd) |
|
70 |
self.assertEqual(self.run_history, []) |
|
71 |
|
|
72 |
def testNewVersion(self): |
|
73 |
lvmvg = storage.LvmVgStorage() |
|
74 |
stdout1 = self._ReadTestData("vgreduce-removemissing-2.02.66-fail.txt") |
|
75 |
stdout2 = self._ReadTestData("vgreduce-removemissing-2.02.66-ok.txt") |
|
76 |
vgs_fail = self._ReadTestData("vgs-missing-pvs-2.02.66.txt") |
|
77 |
# first: require --fail, check that it's used |
|
78 |
self.run_history = [ |
|
79 |
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME], |
|
80 |
utils.RunResult(0, None, stdout1, "", "", None, None)), |
|
81 |
([self.VGREDUCE_CMD, "--removemissing", "--force", self.VGNAME], |
|
82 |
utils.RunResult(0, None, stdout2, "", "", None, None)), |
|
83 |
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME], |
|
84 |
utils.RunResult(0, None, "", "", "", None, None)), |
|
85 |
] |
|
86 |
lvmvg._RemoveMissing(self.VGNAME, _runcmd_fn=self._runCmd) |
|
87 |
self.assertEqual(self.run_history, []) |
|
88 |
# second: make sure --fail is not used if not needed |
|
89 |
self.run_history = [ |
|
90 |
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME], |
|
91 |
utils.RunResult(0, None, stdout2, "", "", None, None)), |
|
92 |
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME], |
|
93 |
utils.RunResult(0, None, "", "", "", None, None)), |
|
94 |
] |
|
95 |
lvmvg._RemoveMissing(self.VGNAME, _runcmd_fn=self._runCmd) |
|
96 |
self.assertEqual(self.run_history, []) |
|
97 |
# third: make sure we error out if vgs doesn't find the volume |
|
98 |
for ecode, out in [(1, ""), (0, vgs_fail)]: |
|
99 |
self.run_history = [ |
|
100 |
([self.VGREDUCE_CMD, "--removemissing", self.VGNAME], |
|
101 |
utils.RunResult(0, None, stdout1, "", "", None, None)), |
|
102 |
([self.VGREDUCE_CMD, "--removemissing", "--force", self.VGNAME], |
|
103 |
utils.RunResult(0, None, stdout2, "", "", None, None)), |
|
104 |
([self.LIST_CMD, "--noheadings", "--nosuffix", self.VGNAME], |
|
105 |
utils.RunResult(ecode, None, out, "", "", None, None)), |
|
106 |
] |
|
107 |
self.assertRaises(errors.StorageError, lvmvg._RemoveMissing, self.VGNAME, |
|
108 |
_runcmd_fn=self._runCmd) |
|
109 |
self.assertEqual(self.run_history, []) |
|
110 |
|
|
111 |
|
|
112 |
if __name__ == "__main__": |
|
113 |
testutils.GanetiTestProgram() |
Also available in: Unified diff