Revision 3840729d
b/lib/bdev.py | ||
---|---|---|
1737 | 1737 |
return bnf |
1738 | 1738 |
|
1739 | 1739 |
@classmethod |
1740 |
def _GetDevInfo(cls, minor): |
|
1741 |
"""Get details about a given DRBD minor. |
|
1742 |
|
|
1743 |
This return, if available, the local backing device (as a path) |
|
1744 |
and the local and remote (ip, port) information. |
|
1740 |
def _GetShowData(cls, minor): |
|
1741 |
"""Return the `drbdsetup show` data for a minor. |
|
1745 | 1742 |
|
1746 | 1743 |
""" |
1747 |
data = {} |
|
1748 | 1744 |
result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "show"]) |
1749 | 1745 |
if result.failed: |
1750 | 1746 |
logger.Error("Can't display the drbd config: %s" % result.fail_reason) |
1751 |
return data |
|
1752 |
out = result.stdout |
|
1747 |
return None |
|
1748 |
return result.stdout |
|
1749 |
|
|
1750 |
@classmethod |
|
1751 |
def _GetDevInfo(cls, out): |
|
1752 |
"""Parse details about a given DRBD minor. |
|
1753 |
|
|
1754 |
This return, if available, the local backing device (as a path) |
|
1755 |
and the local and remote (ip, port) information from a string |
|
1756 |
containing the output of the `drbdsetup show` command as returned |
|
1757 |
by _GetShowData. |
|
1758 |
|
|
1759 |
""" |
|
1760 |
data = {} |
|
1753 | 1761 |
if not out: |
1754 | 1762 |
return data |
1755 | 1763 |
|
... | ... | |
1881 | 1889 |
timeout = time.time() + 10 |
1882 | 1890 |
ok = False |
1883 | 1891 |
while time.time() < timeout: |
1884 |
info = cls._GetDevInfo(minor)
|
|
1892 |
info = cls._GetDevInfo(cls._GetShowData(minor))
|
|
1885 | 1893 |
if not "local_addr" in info or not "remote_addr" in info: |
1886 | 1894 |
time.sleep(1) |
1887 | 1895 |
continue |
... | ... | |
1904 | 1912 |
raise errors.BlockDeviceError("Can't attach to dbrd8 during AddChildren") |
1905 | 1913 |
if len(devices) != 2: |
1906 | 1914 |
raise errors.BlockDeviceError("Need two devices for AddChildren") |
1907 |
info = self._GetDevInfo(self.minor)
|
|
1915 |
info = self._GetDevInfo(self._GetShowData(self.minor))
|
|
1908 | 1916 |
if "local_dev" in info: |
1909 | 1917 |
raise errors.BlockDeviceError("DRBD8 already attached to a local disk") |
1910 | 1918 |
backend, meta = devices |
... | ... | |
1930 | 1938 |
raise errors.BlockDeviceError("Can't attach to drbd8 during" |
1931 | 1939 |
" RemoveChildren") |
1932 | 1940 |
# early return if we don't actually have backing storage |
1933 |
info = self._GetDevInfo(self.minor)
|
|
1941 |
info = self._GetDevInfo(self._GetShowData(self.minor))
|
|
1934 | 1942 |
if "local_dev" not in info: |
1935 | 1943 |
return |
1936 | 1944 |
if len(self._children) != 2: |
... | ... | |
2083 | 2091 |
|
2084 | 2092 |
""" |
2085 | 2093 |
for minor in self._GetUsedDevs(): |
2086 |
info = self._GetDevInfo(minor)
|
|
2094 |
info = self._GetDevInfo(self._GetShowData(minor))
|
|
2087 | 2095 |
match_l = self._MatchesLocal(info) |
2088 | 2096 |
match_r = self._MatchesNet(info) |
2089 | 2097 |
if match_l and match_r: |
... | ... | |
2093 | 2101 |
(self._lhost, self._lport, |
2094 | 2102 |
self._rhost, self._rport), |
2095 | 2103 |
"C") |
2096 |
if res_r and self._MatchesNet(self._GetDevInfo(minor)): |
|
2097 |
break |
|
2104 |
if res_r: |
|
2105 |
if self._MatchesNet(self._GetDevInfo(self._GetShowData(minor))): |
|
2106 |
break |
|
2098 | 2107 |
# the weakest case: we find something that is only net attached |
2099 | 2108 |
# even though we were passed some children at init time |
2100 | 2109 |
if match_r and "local_dev" not in info: |
... | ... | |
2114 | 2123 |
# None) |
2115 | 2124 |
if (self._AssembleNet(minor, (self._lhost, self._lport, |
2116 | 2125 |
self._rhost, self._rport), "C") and |
2117 |
self._MatchesNet(self._GetDevInfo(minor))):
|
|
2126 |
self._MatchesNet(self._GetDevInfo(self._GetShowData(minor)))):
|
|
2118 | 2127 |
break |
2119 | 2128 |
|
2120 | 2129 |
else: |
b/test/Makefile.am | ||
---|---|---|
1 | 1 |
TESTS = \ |
2 | 2 |
ganeti.config_unittest.py \ |
3 | 3 |
ganeti.hooks_unittest.py \ |
4 |
ganeti.utils_unittest.py |
|
4 |
ganeti.utils_unittest.py \ |
|
5 |
ganeti.bdev_unittest.py |
|
6 |
|
|
5 | 7 |
TESTS_ENVIRONMENT = PYTHONPATH=.:$(top_builddir) |
6 | 8 |
|
7 | 9 |
check-am: do-pre-check |
b/test/data/bdev-both.txt | ||
---|---|---|
1 |
disk { |
|
2 |
size 0s _is_default; # bytes |
|
3 |
on-io-error detach; |
|
4 |
fencing dont-care _is_default; |
|
5 |
} |
|
6 |
net { |
|
7 |
timeout 60 _is_default; # 1/10 seconds |
|
8 |
max-epoch-size 16384; |
|
9 |
max-buffers 16384; |
|
10 |
unplug-watermark 128 _is_default; |
|
11 |
connect-int 10 _is_default; # seconds |
|
12 |
ping-int 10 _is_default; # seconds |
|
13 |
sndbuf-size 8388608; # bytes |
|
14 |
ko-count 0 _is_default; |
|
15 |
after-sb-0pri disconnect _is_default; |
|
16 |
after-sb-1pri disconnect _is_default; |
|
17 |
after-sb-2pri disconnect _is_default; |
|
18 |
rr-conflict disconnect _is_default; |
|
19 |
ping-timeout 5 _is_default; # 1/10 seconds |
|
20 |
} |
|
21 |
syncer { |
|
22 |
rate 30720k; # bytes/second |
|
23 |
after -1 _is_default; |
|
24 |
al-extents 257; |
|
25 |
} |
|
26 |
protocol A; |
|
27 |
_this_host { |
|
28 |
device "/dev/drbd63"; |
|
29 |
disk "/dev/xenvg/test.data"; |
|
30 |
meta-disk "/dev/xenvg/test.meta" [ 0 ]; |
|
31 |
address 192.168.1.1:11000; |
|
32 |
} |
|
33 |
_remote_host { |
|
34 |
address 192.168.1.2:11000; |
|
35 |
} |
b/test/data/bdev-disk.txt | ||
---|---|---|
1 |
disk { |
|
2 |
size 0s _is_default; # bytes |
|
3 |
on-io-error detach; |
|
4 |
fencing dont-care _is_default; |
|
5 |
} |
|
6 |
syncer { |
|
7 |
rate 250k _is_default; # bytes/second |
|
8 |
after -1 _is_default; |
|
9 |
al-extents 257; |
|
10 |
} |
|
11 |
_this_host { |
|
12 |
device "/dev/drbd58"; |
|
13 |
disk "/dev/xenvg/test.data"; |
|
14 |
meta-disk "/dev/xenvg/test.meta" [ 0 ]; |
|
15 |
} |
b/test/data/bdev-net.txt | ||
---|---|---|
1 |
net { |
|
2 |
timeout 60 _is_default; # 1/10 seconds |
|
3 |
max-epoch-size 2048 _is_default; |
|
4 |
max-buffers 2048 _is_default; |
|
5 |
unplug-watermark 128 _is_default; |
|
6 |
connect-int 10 _is_default; # seconds |
|
7 |
ping-int 10 _is_default; # seconds |
|
8 |
sndbuf-size 131070 _is_default; # bytes |
|
9 |
ko-count 0 _is_default; |
|
10 |
after-sb-0pri disconnect _is_default; |
|
11 |
after-sb-1pri disconnect _is_default; |
|
12 |
after-sb-2pri disconnect _is_default; |
|
13 |
rr-conflict disconnect _is_default; |
|
14 |
ping-timeout 5 _is_default; # 1/10 seconds |
|
15 |
} |
|
16 |
syncer { |
|
17 |
rate 250k _is_default; # bytes/second |
|
18 |
after -1 _is_default; |
|
19 |
al-extents 127 _is_default; |
|
20 |
} |
|
21 |
protocol C; |
|
22 |
_this_host { |
|
23 |
device "/dev/drbd59"; |
|
24 |
address 192.168.1.1:11002; |
|
25 |
} |
|
26 |
_remote_host { |
|
27 |
address 192.168.1.2:11002; |
|
28 |
} |
b/test/ganeti.bdev_unittest.py | ||
---|---|---|
1 |
#!/usr/bin/python |
|
2 |
# |
|
3 |
|
|
4 |
# Copyright (C) 2006, 2007 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 unittesting the bdev module""" |
|
23 |
|
|
24 |
|
|
25 |
import unittest |
|
26 |
|
|
27 |
from ganeti import bdev |
|
28 |
|
|
29 |
|
|
30 |
class TestDRBD8Runner(unittest.TestCase): |
|
31 |
"""Testing case for DRBD8""" |
|
32 |
|
|
33 |
@staticmethod |
|
34 |
def _has_disk(data, dname, mname): |
|
35 |
"""Check local disk corectness""" |
|
36 |
retval = ( |
|
37 |
"local_dev" in data and |
|
38 |
data["local_dev"] == dname and |
|
39 |
"meta_dev" in data and |
|
40 |
data["meta_dev"] == mname and |
|
41 |
"meta_index" in data and |
|
42 |
data["meta_index"] == 0 |
|
43 |
) |
|
44 |
return retval |
|
45 |
|
|
46 |
@staticmethod |
|
47 |
def _has_net(data, local, remote): |
|
48 |
"""Check network connection parameters""" |
|
49 |
retval = ( |
|
50 |
"local_addr" in data and |
|
51 |
data["local_addr"] == local and |
|
52 |
"remote_addr" in data and |
|
53 |
data["remote_addr"] == remote |
|
54 |
) |
|
55 |
return retval |
|
56 |
|
|
57 |
def testParserCreation(self): |
|
58 |
"""Test drbdsetup show parser creation""" |
|
59 |
bdev.DRBD8._GetShowParser() |
|
60 |
|
|
61 |
def testParserBoth(self): |
|
62 |
"""Test drbdsetup show parser for disk and network""" |
|
63 |
data = open("data/bdev-both.txt").read() |
|
64 |
result = bdev.DRBD8._GetDevInfo(data) |
|
65 |
self.failUnless(self._has_disk(result, "/dev/xenvg/test.data", |
|
66 |
"/dev/xenvg/test.meta"), |
|
67 |
"Wrong local disk info") |
|
68 |
self.failUnless(self._has_net(result, ("192.168.1.1", 11000), |
|
69 |
("192.168.1.2", 11000)), |
|
70 |
"Wrong network info") |
|
71 |
|
|
72 |
def testParserNet(self): |
|
73 |
"""Test drbdsetup show parser for disk and network""" |
|
74 |
data = open("data/bdev-net.txt").read() |
|
75 |
result = bdev.DRBD8._GetDevInfo(data) |
|
76 |
self.failUnless(("local_dev" not in result and |
|
77 |
"meta_dev" not in result and |
|
78 |
"meta_index" not in result), |
|
79 |
"Should not find local disk info") |
|
80 |
self.failUnless(self._has_net(result, ("192.168.1.1", 11002), |
|
81 |
("192.168.1.2", 11002)), |
|
82 |
"Wrong network info") |
|
83 |
|
|
84 |
def testParserDisk(self): |
|
85 |
"""Test drbdsetup show parser for disk and network""" |
|
86 |
data = open("data/bdev-disk.txt").read() |
|
87 |
result = bdev.DRBD8._GetDevInfo(data) |
|
88 |
self.failUnless(self._has_disk(result, "/dev/xenvg/test.data", |
|
89 |
"/dev/xenvg/test.meta"), |
|
90 |
"Wrong local disk info") |
|
91 |
self.failUnless(("local_addr" not in result and |
|
92 |
"remote_addr" not in result), |
|
93 |
"Should not find network info") |
|
94 |
|
|
95 |
if __name__ == '__main__': |
|
96 |
unittest.main() |
Also available in: Unified diff