Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.bdev_unittest.py @ ef947a42

History | View | Annotate | Download (20.8 kB)

1 3840729d Iustin Pop
#!/usr/bin/python
2 3840729d Iustin Pop
#
3 3840729d Iustin Pop
4 23d95cff Bernardo Dal Seno
# Copyright (C) 2006, 2007, 2010, 2012, 2013 Google Inc.
5 3840729d Iustin Pop
#
6 3840729d Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 3840729d Iustin Pop
# it under the terms of the GNU General Public License as published by
8 3840729d Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 3840729d Iustin Pop
# (at your option) any later version.
10 3840729d Iustin Pop
#
11 3840729d Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 3840729d Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 3840729d Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3840729d Iustin Pop
# General Public License for more details.
15 3840729d Iustin Pop
#
16 3840729d Iustin Pop
# You should have received a copy of the GNU General Public License
17 3840729d Iustin Pop
# along with this program; if not, write to the Free Software
18 3840729d Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 3840729d Iustin Pop
# 02110-1301, USA.
20 3840729d Iustin Pop
21 3840729d Iustin Pop
22 3840729d Iustin Pop
"""Script for unittesting the bdev module"""
23 3840729d Iustin Pop
24 3840729d Iustin Pop
25 6634816b Iustin Pop
import os
26 23d95cff Bernardo Dal Seno
import random
27 3840729d Iustin Pop
import unittest
28 3840729d Iustin Pop
29 3840729d Iustin Pop
from ganeti import bdev
30 23d95cff Bernardo Dal Seno
from ganeti import compat
31 8a69b3a8 Andrea Spadaccini
from ganeti import constants
32 23d95cff Bernardo Dal Seno
from ganeti import errors
33 23d95cff Bernardo Dal Seno
from ganeti import objects
34 fbdac0d9 Michael Hanselmann
from ganeti import utils
35 3840729d Iustin Pop
36 25231ec5 Michael Hanselmann
import testutils
37 25231ec5 Michael Hanselmann
38 3840729d Iustin Pop
39 fcee765d Manuel Franceschini
class TestBaseDRBD(testutils.GanetiTestCase):
40 fcee765d Manuel Franceschini
  def testGetVersion(self):
41 fcee765d Manuel Franceschini
    data = [
42 fcee765d Manuel Franceschini
      ["version: 8.0.12 (api:76/proto:86-91)"],
43 fcee765d Manuel Franceschini
      ["version: 8.2.7 (api:88/proto:0-100)"],
44 fcee765d Manuel Franceschini
      ["version: 8.3.7.49 (api:188/proto:13-191)"],
45 fcee765d Manuel Franceschini
    ]
46 fcee765d Manuel Franceschini
    result = [
47 fcee765d Manuel Franceschini
      {
48 fcee765d Manuel Franceschini
      "k_major": 8,
49 fcee765d Manuel Franceschini
      "k_minor": 0,
50 fcee765d Manuel Franceschini
      "k_point": 12,
51 fcee765d Manuel Franceschini
      "api": 76,
52 fcee765d Manuel Franceschini
      "proto": 86,
53 fcee765d Manuel Franceschini
      "proto2": "91",
54 fcee765d Manuel Franceschini
      },
55 fcee765d Manuel Franceschini
      {
56 fcee765d Manuel Franceschini
      "k_major": 8,
57 fcee765d Manuel Franceschini
      "k_minor": 2,
58 fcee765d Manuel Franceschini
      "k_point": 7,
59 fcee765d Manuel Franceschini
      "api": 88,
60 fcee765d Manuel Franceschini
      "proto": 0,
61 fcee765d Manuel Franceschini
      "proto2": "100",
62 fcee765d Manuel Franceschini
      },
63 fcee765d Manuel Franceschini
      {
64 fcee765d Manuel Franceschini
      "k_major": 8,
65 fcee765d Manuel Franceschini
      "k_minor": 3,
66 fcee765d Manuel Franceschini
      "k_point": 7,
67 fcee765d Manuel Franceschini
      "api": 188,
68 fcee765d Manuel Franceschini
      "proto": 13,
69 fcee765d Manuel Franceschini
      "proto2": "191",
70 fcee765d Manuel Franceschini
      }
71 fcee765d Manuel Franceschini
    ]
72 fcee765d Manuel Franceschini
    for d,r in zip(data, result):
73 fcee765d Manuel Franceschini
      self.assertEqual(bdev.BaseDRBD._GetVersion(d), r)
74 fcee765d Manuel Franceschini
75 fcee765d Manuel Franceschini
76 149a5439 Iustin Pop
class TestDRBD8Runner(testutils.GanetiTestCase):
77 3840729d Iustin Pop
  """Testing case for DRBD8"""
78 3840729d Iustin Pop
79 3840729d Iustin Pop
  @staticmethod
80 3840729d Iustin Pop
  def _has_disk(data, dname, mname):
81 3840729d Iustin Pop
    """Check local disk corectness"""
82 3840729d Iustin Pop
    retval = (
83 3840729d Iustin Pop
      "local_dev" in data and
84 3840729d Iustin Pop
      data["local_dev"] == dname and
85 3840729d Iustin Pop
      "meta_dev" in data and
86 3840729d Iustin Pop
      data["meta_dev"] == mname and
87 3840729d Iustin Pop
      "meta_index" in data and
88 3840729d Iustin Pop
      data["meta_index"] == 0
89 3840729d Iustin Pop
      )
90 3840729d Iustin Pop
    return retval
91 3840729d Iustin Pop
92 3840729d Iustin Pop
  @staticmethod
93 3840729d Iustin Pop
  def _has_net(data, local, remote):
94 3840729d Iustin Pop
    """Check network connection parameters"""
95 3840729d Iustin Pop
    retval = (
96 3840729d Iustin Pop
      "local_addr" in data and
97 3840729d Iustin Pop
      data["local_addr"] == local and
98 3840729d Iustin Pop
      "remote_addr" in data and
99 3840729d Iustin Pop
      data["remote_addr"] == remote
100 3840729d Iustin Pop
      )
101 3840729d Iustin Pop
    return retval
102 3840729d Iustin Pop
103 3840729d Iustin Pop
  def testParserCreation(self):
104 3840729d Iustin Pop
    """Test drbdsetup show parser creation"""
105 3840729d Iustin Pop
    bdev.DRBD8._GetShowParser()
106 3840729d Iustin Pop
107 5a672c30 Manuel Franceschini
  def testParser80(self):
108 5a672c30 Manuel Franceschini
    """Test drbdsetup show parser for disk and network version 8.0"""
109 5a672c30 Manuel Franceschini
    data = self._ReadTestData("bdev-drbd-8.0.txt")
110 3840729d Iustin Pop
    result = bdev.DRBD8._GetDevInfo(data)
111 3840729d Iustin Pop
    self.failUnless(self._has_disk(result, "/dev/xenvg/test.data",
112 3840729d Iustin Pop
                                   "/dev/xenvg/test.meta"),
113 3840729d Iustin Pop
                    "Wrong local disk info")
114 926feaf1 Manuel Franceschini
    self.failUnless(self._has_net(result, ("192.0.2.1", 11000),
115 926feaf1 Manuel Franceschini
                                  ("192.0.2.2", 11000)),
116 01e2ce3a Iustin Pop
                    "Wrong network info (8.0.x)")
117 01e2ce3a Iustin Pop
118 5a672c30 Manuel Franceschini
  def testParser83(self):
119 5a672c30 Manuel Franceschini
    """Test drbdsetup show parser for disk and network version 8.3"""
120 5a672c30 Manuel Franceschini
    data = self._ReadTestData("bdev-drbd-8.3.txt")
121 01e2ce3a Iustin Pop
    result = bdev.DRBD8._GetDevInfo(data)
122 01e2ce3a Iustin Pop
    self.failUnless(self._has_disk(result, "/dev/xenvg/test.data",
123 01e2ce3a Iustin Pop
                                   "/dev/xenvg/test.meta"),
124 01e2ce3a Iustin Pop
                    "Wrong local disk info")
125 926feaf1 Manuel Franceschini
    self.failUnless(self._has_net(result, ("192.0.2.1", 11000),
126 926feaf1 Manuel Franceschini
                                  ("192.0.2.2", 11000)),
127 5a672c30 Manuel Franceschini
                    "Wrong network info (8.0.x)")
128 3840729d Iustin Pop
129 5a672c30 Manuel Franceschini
  def testParserNetIP4(self):
130 5a672c30 Manuel Franceschini
    """Test drbdsetup show parser for IPv4 network"""
131 5a672c30 Manuel Franceschini
    data = self._ReadTestData("bdev-drbd-net-ip4.txt")
132 3840729d Iustin Pop
    result = bdev.DRBD8._GetDevInfo(data)
133 3840729d Iustin Pop
    self.failUnless(("local_dev" not in result and
134 3840729d Iustin Pop
                     "meta_dev" not in result and
135 3840729d Iustin Pop
                     "meta_index" not in result),
136 3840729d Iustin Pop
                    "Should not find local disk info")
137 926feaf1 Manuel Franceschini
    self.failUnless(self._has_net(result, ("192.0.2.1", 11002),
138 926feaf1 Manuel Franceschini
                                  ("192.0.2.2", 11002)),
139 5a672c30 Manuel Franceschini
                    "Wrong network info (IPv4)")
140 5a672c30 Manuel Franceschini
141 5a672c30 Manuel Franceschini
  def testParserNetIP6(self):
142 5a672c30 Manuel Franceschini
    """Test drbdsetup show parser for IPv6 network"""
143 5a672c30 Manuel Franceschini
    data = self._ReadTestData("bdev-drbd-net-ip6.txt")
144 5a672c30 Manuel Franceschini
    result = bdev.DRBD8._GetDevInfo(data)
145 5a672c30 Manuel Franceschini
    self.failUnless(("local_dev" not in result and
146 5a672c30 Manuel Franceschini
                     "meta_dev" not in result and
147 5a672c30 Manuel Franceschini
                     "meta_index" not in result),
148 5a672c30 Manuel Franceschini
                    "Should not find local disk info")
149 5a672c30 Manuel Franceschini
    self.failUnless(self._has_net(result, ("2001:db8:65::1", 11048),
150 5a672c30 Manuel Franceschini
                                  ("2001:db8:66::1", 11048)),
151 5a672c30 Manuel Franceschini
                    "Wrong network info (IPv6)")
152 3840729d Iustin Pop
153 3840729d Iustin Pop
  def testParserDisk(self):
154 5a672c30 Manuel Franceschini
    """Test drbdsetup show parser for disk"""
155 5a672c30 Manuel Franceschini
    data = self._ReadTestData("bdev-drbd-disk.txt")
156 3840729d Iustin Pop
    result = bdev.DRBD8._GetDevInfo(data)
157 3840729d Iustin Pop
    self.failUnless(self._has_disk(result, "/dev/xenvg/test.data",
158 3840729d Iustin Pop
                                   "/dev/xenvg/test.meta"),
159 3840729d Iustin Pop
                    "Wrong local disk info")
160 3840729d Iustin Pop
    self.failUnless(("local_addr" not in result and
161 3840729d Iustin Pop
                     "remote_addr" not in result),
162 3840729d Iustin Pop
                    "Should not find network info")
163 3840729d Iustin Pop
164 8a69b3a8 Andrea Spadaccini
  def testBarriersOptions(self):
165 8a69b3a8 Andrea Spadaccini
    """Test class method that generates drbdsetup options for disk barriers"""
166 8a69b3a8 Andrea Spadaccini
    # Tests that should fail because of wrong version/options combinations
167 8a69b3a8 Andrea Spadaccini
    should_fail = [
168 8a69b3a8 Andrea Spadaccini
      (8, 0, 12, "bfd", True),
169 8a69b3a8 Andrea Spadaccini
      (8, 0, 12, "fd", False),
170 8a69b3a8 Andrea Spadaccini
      (8, 0, 12, "b", True),
171 8a69b3a8 Andrea Spadaccini
      (8, 2, 7, "bfd", True),
172 8a69b3a8 Andrea Spadaccini
      (8, 2, 7, "b", True)
173 8a69b3a8 Andrea Spadaccini
    ]
174 8a69b3a8 Andrea Spadaccini
175 8a69b3a8 Andrea Spadaccini
    for vmaj, vmin, vrel, opts, meta in should_fail:
176 8a69b3a8 Andrea Spadaccini
      self.assertRaises(errors.BlockDeviceError,
177 8a69b3a8 Andrea Spadaccini
                        bdev.DRBD8._ComputeDiskBarrierArgs,
178 8a69b3a8 Andrea Spadaccini
                        vmaj, vmin, vrel, opts, meta)
179 8a69b3a8 Andrea Spadaccini
180 8a69b3a8 Andrea Spadaccini
    # get the valid options from the frozenset(frozenset()) in constants.
181 8a69b3a8 Andrea Spadaccini
    valid_options = [list(x)[0] for x in constants.DRBD_VALID_BARRIER_OPT]
182 8a69b3a8 Andrea Spadaccini
183 8a69b3a8 Andrea Spadaccini
    # Versions that do not support anything
184 8a69b3a8 Andrea Spadaccini
    for vmaj, vmin, vrel in ((8, 0, 0), (8, 0, 11), (8, 2, 6)):
185 8a69b3a8 Andrea Spadaccini
      for opts in valid_options:
186 8a69b3a8 Andrea Spadaccini
        self.assertRaises(errors.BlockDeviceError,
187 8a69b3a8 Andrea Spadaccini
                          bdev.DRBD8._ComputeDiskBarrierArgs,
188 8a69b3a8 Andrea Spadaccini
                          vmaj, vmin, vrel, opts, True)
189 8a69b3a8 Andrea Spadaccini
190 8a69b3a8 Andrea Spadaccini
    # Versions with partial support (testing only options that are supported)
191 8a69b3a8 Andrea Spadaccini
    tests = [
192 8a69b3a8 Andrea Spadaccini
      (8, 0, 12, "n", False, []),
193 8a69b3a8 Andrea Spadaccini
      (8, 0, 12, "n", True, ["--no-md-flushes"]),
194 8a69b3a8 Andrea Spadaccini
      (8, 2, 7, "n", False, []),
195 8a69b3a8 Andrea Spadaccini
      (8, 2, 7, "fd", False, ["--no-disk-flushes", "--no-disk-drain"]),
196 8a69b3a8 Andrea Spadaccini
      (8, 0, 12, "n", True, ["--no-md-flushes"]),
197 8a69b3a8 Andrea Spadaccini
      ]
198 8a69b3a8 Andrea Spadaccini
199 8a69b3a8 Andrea Spadaccini
    # Versions that support everything
200 8a69b3a8 Andrea Spadaccini
    for vmaj, vmin, vrel in ((8, 3, 0), (8, 3, 12)):
201 8a69b3a8 Andrea Spadaccini
      tests.append((vmaj, vmin, vrel, "bfd", True,
202 8a69b3a8 Andrea Spadaccini
                    ["--no-disk-barrier", "--no-disk-drain",
203 8a69b3a8 Andrea Spadaccini
                     "--no-disk-flushes", "--no-md-flushes"]))
204 8a69b3a8 Andrea Spadaccini
      tests.append((vmaj, vmin, vrel, "n", False, []))
205 8a69b3a8 Andrea Spadaccini
      tests.append((vmaj, vmin, vrel, "b", True,
206 8a69b3a8 Andrea Spadaccini
                    ["--no-disk-barrier", "--no-md-flushes"]))
207 8a69b3a8 Andrea Spadaccini
      tests.append((vmaj, vmin, vrel, "fd", False,
208 8a69b3a8 Andrea Spadaccini
                    ["--no-disk-flushes", "--no-disk-drain"]))
209 8a69b3a8 Andrea Spadaccini
      tests.append((vmaj, vmin, vrel, "n", True, ["--no-md-flushes"]))
210 8a69b3a8 Andrea Spadaccini
211 8a69b3a8 Andrea Spadaccini
    # Test execution
212 8a69b3a8 Andrea Spadaccini
    for test in tests:
213 8a69b3a8 Andrea Spadaccini
      vmaj, vmin, vrel, disabled_barriers, disable_meta_flush, expected = test
214 8a69b3a8 Andrea Spadaccini
      args = \
215 8a69b3a8 Andrea Spadaccini
        bdev.DRBD8._ComputeDiskBarrierArgs(vmaj, vmin, vrel,
216 8a69b3a8 Andrea Spadaccini
                                           disabled_barriers,
217 8a69b3a8 Andrea Spadaccini
                                           disable_meta_flush)
218 8a69b3a8 Andrea Spadaccini
      self.failUnless(set(args) == set(expected),
219 8a69b3a8 Andrea Spadaccini
                      "For test %s, got wrong results %s" % (test, args))
220 8a69b3a8 Andrea Spadaccini
221 8a69b3a8 Andrea Spadaccini
    # Unsupported or invalid versions
222 8a69b3a8 Andrea Spadaccini
    for vmaj, vmin, vrel in ((0, 7, 25), (9, 0, 0), (7, 0, 0), (8, 4, 0)):
223 8a69b3a8 Andrea Spadaccini
      self.assertRaises(errors.BlockDeviceError,
224 8a69b3a8 Andrea Spadaccini
                        bdev.DRBD8._ComputeDiskBarrierArgs,
225 8a69b3a8 Andrea Spadaccini
                        vmaj, vmin, vrel, "n", True)
226 8a69b3a8 Andrea Spadaccini
227 8a69b3a8 Andrea Spadaccini
    # Invalid options
228 8a69b3a8 Andrea Spadaccini
    for option in ("", "c", "whatever", "nbdfc", "nf"):
229 8a69b3a8 Andrea Spadaccini
      self.assertRaises(errors.BlockDeviceError,
230 8a69b3a8 Andrea Spadaccini
                        bdev.DRBD8._ComputeDiskBarrierArgs,
231 8a69b3a8 Andrea Spadaccini
                        8, 3, 11, option, True)
232 8a69b3a8 Andrea Spadaccini
233 6b90c22e Iustin Pop
234 149a5439 Iustin Pop
class TestDRBD8Status(testutils.GanetiTestCase):
235 6b90c22e Iustin Pop
  """Testing case for DRBD8 /proc status"""
236 6b90c22e Iustin Pop
237 6b90c22e Iustin Pop
  def setUp(self):
238 6b90c22e Iustin Pop
    """Read in txt data"""
239 51596eb2 Iustin Pop
    testutils.GanetiTestCase.setUp(self)
240 149a5439 Iustin Pop
    proc_data = self._TestDataFilename("proc_drbd8.txt")
241 67d101d4 Iustin Pop
    proc80e_data = self._TestDataFilename("proc_drbd80-emptyline.txt")
242 01e2ce3a Iustin Pop
    proc83_data = self._TestDataFilename("proc_drbd83.txt")
243 7a380ddf René Nussbaumer
    proc83_sync_data = self._TestDataFilename("proc_drbd83_sync.txt")
244 7a380ddf René Nussbaumer
    proc83_sync_krnl_data = \
245 7a380ddf René Nussbaumer
      self._TestDataFilename("proc_drbd83_sync_krnl2.6.39.txt")
246 ae9da390 Iustin Pop
    self.proc_data = bdev.DRBD8._GetProcData(filename=proc_data)
247 67d101d4 Iustin Pop
    self.proc80e_data = bdev.DRBD8._GetProcData(filename=proc80e_data)
248 01e2ce3a Iustin Pop
    self.proc83_data = bdev.DRBD8._GetProcData(filename=proc83_data)
249 7a380ddf René Nussbaumer
    self.proc83_sync_data = bdev.DRBD8._GetProcData(filename=proc83_sync_data)
250 7a380ddf René Nussbaumer
    self.proc83_sync_krnl_data = \
251 7a380ddf René Nussbaumer
      bdev.DRBD8._GetProcData(filename=proc83_sync_krnl_data)
252 6b90c22e Iustin Pop
    self.mass_data = bdev.DRBD8._MassageProcData(self.proc_data)
253 67d101d4 Iustin Pop
    self.mass80e_data = bdev.DRBD8._MassageProcData(self.proc80e_data)
254 01e2ce3a Iustin Pop
    self.mass83_data = bdev.DRBD8._MassageProcData(self.proc83_data)
255 7a380ddf René Nussbaumer
    self.mass83_sync_data = bdev.DRBD8._MassageProcData(self.proc83_sync_data)
256 7a380ddf René Nussbaumer
    self.mass83_sync_krnl_data = \
257 7a380ddf René Nussbaumer
      bdev.DRBD8._MassageProcData(self.proc83_sync_krnl_data)
258 6b90c22e Iustin Pop
259 f6eaed12 Iustin Pop
  def testIOErrors(self):
260 f6eaed12 Iustin Pop
    """Test handling of errors while reading the proc file."""
261 f6eaed12 Iustin Pop
    temp_file = self._CreateTempFile()
262 f6eaed12 Iustin Pop
    os.unlink(temp_file)
263 f6eaed12 Iustin Pop
    self.failUnlessRaises(errors.BlockDeviceError,
264 f6eaed12 Iustin Pop
                          bdev.DRBD8._GetProcData, filename=temp_file)
265 f6eaed12 Iustin Pop
266 549071a0 Luca Bigliardi
  def testHelper(self):
267 549071a0 Luca Bigliardi
    """Test reading usermode_helper in /sys."""
268 549071a0 Luca Bigliardi
    sys_drbd_helper = self._TestDataFilename("sys_drbd_usermode_helper.txt")
269 549071a0 Luca Bigliardi
    drbd_helper = bdev.DRBD8.GetUsermodeHelper(filename=sys_drbd_helper)
270 549071a0 Luca Bigliardi
    self.failUnlessEqual(drbd_helper, "/bin/true")
271 549071a0 Luca Bigliardi
272 549071a0 Luca Bigliardi
  def testHelperIOErrors(self):
273 549071a0 Luca Bigliardi
    """Test handling of errors while reading usermode_helper in /sys."""
274 549071a0 Luca Bigliardi
    temp_file = self._CreateTempFile()
275 549071a0 Luca Bigliardi
    os.unlink(temp_file)
276 549071a0 Luca Bigliardi
    self.failUnlessRaises(errors.BlockDeviceError,
277 549071a0 Luca Bigliardi
                          bdev.DRBD8.GetUsermodeHelper, filename=temp_file)
278 549071a0 Luca Bigliardi
279 6b90c22e Iustin Pop
  def testMinorNotFound(self):
280 6b90c22e Iustin Pop
    """Test not-found-minor in /proc"""
281 6b90c22e Iustin Pop
    self.failUnless(9 not in self.mass_data)
282 01e2ce3a Iustin Pop
    self.failUnless(9 not in self.mass83_data)
283 67d101d4 Iustin Pop
    self.failUnless(3 not in self.mass80e_data)
284 6b90c22e Iustin Pop
285 6b90c22e Iustin Pop
  def testLineNotMatch(self):
286 6b90c22e Iustin Pop
    """Test wrong line passed to DRBD8Status"""
287 6b90c22e Iustin Pop
    self.assertRaises(errors.BlockDeviceError, bdev.DRBD8Status, "foo")
288 6b90c22e Iustin Pop
289 6b90c22e Iustin Pop
  def testMinor0(self):
290 6b90c22e Iustin Pop
    """Test connected, primary device"""
291 01e2ce3a Iustin Pop
    for data in [self.mass_data, self.mass83_data]:
292 01e2ce3a Iustin Pop
      stats = bdev.DRBD8Status(data[0])
293 01e2ce3a Iustin Pop
      self.failUnless(stats.is_in_use)
294 01e2ce3a Iustin Pop
      self.failUnless(stats.is_connected and stats.is_primary and
295 01e2ce3a Iustin Pop
                      stats.peer_secondary and stats.is_disk_uptodate)
296 6b90c22e Iustin Pop
297 6b90c22e Iustin Pop
  def testMinor1(self):
298 6b90c22e Iustin Pop
    """Test connected, secondary device"""
299 01e2ce3a Iustin Pop
    for data in [self.mass_data, self.mass83_data]:
300 01e2ce3a Iustin Pop
      stats = bdev.DRBD8Status(data[1])
301 01e2ce3a Iustin Pop
      self.failUnless(stats.is_in_use)
302 01e2ce3a Iustin Pop
      self.failUnless(stats.is_connected and stats.is_secondary and
303 01e2ce3a Iustin Pop
                      stats.peer_primary and stats.is_disk_uptodate)
304 6b90c22e Iustin Pop
305 767d52d3 Iustin Pop
  def testMinor2(self):
306 767d52d3 Iustin Pop
    """Test unconfigured device"""
307 67d101d4 Iustin Pop
    for data in [self.mass_data, self.mass83_data, self.mass80e_data]:
308 01e2ce3a Iustin Pop
      stats = bdev.DRBD8Status(data[2])
309 01e2ce3a Iustin Pop
      self.failIf(stats.is_in_use)
310 767d52d3 Iustin Pop
311 6b90c22e Iustin Pop
  def testMinor4(self):
312 6b90c22e Iustin Pop
    """Test WFconn device"""
313 01e2ce3a Iustin Pop
    for data in [self.mass_data, self.mass83_data]:
314 01e2ce3a Iustin Pop
      stats = bdev.DRBD8Status(data[4])
315 01e2ce3a Iustin Pop
      self.failUnless(stats.is_in_use)
316 01e2ce3a Iustin Pop
      self.failUnless(stats.is_wfconn and stats.is_primary and
317 8c114acd Michael Hanselmann
                      stats.rrole == "Unknown" and
318 01e2ce3a Iustin Pop
                      stats.is_disk_uptodate)
319 6b90c22e Iustin Pop
320 6b90c22e Iustin Pop
  def testMinor6(self):
321 6b90c22e Iustin Pop
    """Test diskless device"""
322 01e2ce3a Iustin Pop
    for data in [self.mass_data, self.mass83_data]:
323 01e2ce3a Iustin Pop
      stats = bdev.DRBD8Status(data[6])
324 01e2ce3a Iustin Pop
      self.failUnless(stats.is_in_use)
325 01e2ce3a Iustin Pop
      self.failUnless(stats.is_connected and stats.is_secondary and
326 01e2ce3a Iustin Pop
                      stats.peer_primary and stats.is_diskless)
327 6b90c22e Iustin Pop
328 6b90c22e Iustin Pop
  def testMinor8(self):
329 6b90c22e Iustin Pop
    """Test standalone device"""
330 01e2ce3a Iustin Pop
    for data in [self.mass_data, self.mass83_data]:
331 01e2ce3a Iustin Pop
      stats = bdev.DRBD8Status(data[8])
332 01e2ce3a Iustin Pop
      self.failUnless(stats.is_in_use)
333 01e2ce3a Iustin Pop
      self.failUnless(stats.is_standalone and
334 8c114acd Michael Hanselmann
                      stats.rrole == "Unknown" and
335 01e2ce3a Iustin Pop
                      stats.is_disk_uptodate)
336 6b90c22e Iustin Pop
337 7a380ddf René Nussbaumer
  def testDRBD83SyncFine(self):
338 7a380ddf René Nussbaumer
    stats = bdev.DRBD8Status(self.mass83_sync_data[3])
339 7a380ddf René Nussbaumer
    self.failUnless(stats.is_in_resync)
340 7a380ddf René Nussbaumer
    self.failUnless(stats.sync_percent is not None)
341 7a380ddf René Nussbaumer
342 7a380ddf René Nussbaumer
  def testDRBD83SyncBroken(self):
343 7a380ddf René Nussbaumer
    stats = bdev.DRBD8Status(self.mass83_sync_krnl_data[3])
344 7a380ddf René Nussbaumer
    self.failUnless(stats.is_in_resync)
345 7a380ddf René Nussbaumer
    self.failUnless(stats.sync_percent is not None)
346 7a380ddf René Nussbaumer
347 7181fba0 Constantinos Venetsanopoulos
348 7181fba0 Constantinos Venetsanopoulos
class TestRADOSBlockDevice(testutils.GanetiTestCase):
349 7181fba0 Constantinos Venetsanopoulos
  def test_ParseRbdShowmappedOutput(self):
350 7181fba0 Constantinos Venetsanopoulos
    volume_name = "abc9778-8e8ace5b.rbd.disk0"
351 7181fba0 Constantinos Venetsanopoulos
    output_ok = \
352 7181fba0 Constantinos Venetsanopoulos
      ("0\trbd\te69f28e5-9817.rbd.disk0\t-\t/dev/rbd0\n"
353 7181fba0 Constantinos Venetsanopoulos
       "1\t/dev/rbd0\tabc9778-8e8ace5b.rbd.disk0\t-\t/dev/rbd16\n"
354 7181fba0 Constantinos Venetsanopoulos
       "line\twith\tfewer\tfields\n"
355 7181fba0 Constantinos Venetsanopoulos
       "")
356 7181fba0 Constantinos Venetsanopoulos
    output_empty = ""
357 7181fba0 Constantinos Venetsanopoulos
    output_no_matches = \
358 7181fba0 Constantinos Venetsanopoulos
      ("0\trbd\te69f28e5-9817.rbd.disk0\t-\t/dev/rbd0\n"
359 7181fba0 Constantinos Venetsanopoulos
       "1\trbd\tabcdef01-9817.rbd.disk0\t-\t/dev/rbd10\n"
360 7181fba0 Constantinos Venetsanopoulos
       "2\trbd\tcdef0123-9817.rbd.disk0\t-\t/dev/rbd12\n"
361 7181fba0 Constantinos Venetsanopoulos
       "something\twith\tfewer\tfields"
362 7181fba0 Constantinos Venetsanopoulos
       "")
363 7181fba0 Constantinos Venetsanopoulos
    output_extra_matches = \
364 7181fba0 Constantinos Venetsanopoulos
      ("0\t/dev/rbd0\tabc9778-8e8ace5b.rbd.disk0\t-\t/dev/rbd11\n"
365 7181fba0 Constantinos Venetsanopoulos
       "1\trbd\te69f28e5-9817.rbd.disk0\t-\t/dev/rbd0\n"
366 7181fba0 Constantinos Venetsanopoulos
       "2\t/dev/rbd0\tabc9778-8e8ace5b.rbd.disk0\t-\t/dev/rbd16\n"
367 7181fba0 Constantinos Venetsanopoulos
       "something\twith\tfewer\tfields"
368 7181fba0 Constantinos Venetsanopoulos
       "")
369 7181fba0 Constantinos Venetsanopoulos
370 7181fba0 Constantinos Venetsanopoulos
    parse_function = bdev.RADOSBlockDevice._ParseRbdShowmappedOutput
371 7181fba0 Constantinos Venetsanopoulos
    self.assertEqual(parse_function(output_ok, volume_name), "/dev/rbd16")
372 7181fba0 Constantinos Venetsanopoulos
    self.assertRaises(errors.BlockDeviceError, parse_function,
373 7181fba0 Constantinos Venetsanopoulos
                      output_empty, volume_name)
374 7181fba0 Constantinos Venetsanopoulos
    self.assertEqual(parse_function(output_no_matches, volume_name), None)
375 7181fba0 Constantinos Venetsanopoulos
    self.assertRaises(errors.BlockDeviceError, parse_function,
376 7181fba0 Constantinos Venetsanopoulos
                      output_extra_matches, volume_name)
377 7181fba0 Constantinos Venetsanopoulos
378 7181fba0 Constantinos Venetsanopoulos
379 23e3c9b7 Michael Hanselmann
class TestComputeWrongFileStoragePathsInternal(unittest.TestCase):
380 23e3c9b7 Michael Hanselmann
  def testPaths(self):
381 23e3c9b7 Michael Hanselmann
    paths = bdev._GetForbiddenFileStoragePaths()
382 23e3c9b7 Michael Hanselmann
383 23e3c9b7 Michael Hanselmann
    for path in ["/bin", "/usr/local/sbin", "/lib64", "/etc", "/sys"]:
384 23e3c9b7 Michael Hanselmann
      self.assertTrue(path in paths)
385 23e3c9b7 Michael Hanselmann
386 23e3c9b7 Michael Hanselmann
    self.assertEqual(set(map(os.path.normpath, paths)), paths)
387 23e3c9b7 Michael Hanselmann
388 23e3c9b7 Michael Hanselmann
  def test(self):
389 23e3c9b7 Michael Hanselmann
    vfsp = bdev._ComputeWrongFileStoragePaths
390 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp([]), [])
391 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/tmp"]), [])
392 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/bin/ls"]), ["/bin/ls"])
393 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/bin"]), ["/bin"])
394 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/usr/sbin/vim", "/srv/file-storage"]),
395 23e3c9b7 Michael Hanselmann
                     ["/usr/sbin/vim"])
396 23e3c9b7 Michael Hanselmann
397 23e3c9b7 Michael Hanselmann
398 23e3c9b7 Michael Hanselmann
class TestComputeWrongFileStoragePaths(testutils.GanetiTestCase):
399 23e3c9b7 Michael Hanselmann
  def test(self):
400 23e3c9b7 Michael Hanselmann
    tmpfile = self._CreateTempFile()
401 23e3c9b7 Michael Hanselmann
402 23e3c9b7 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
403 23e3c9b7 Michael Hanselmann
      /tmp
404 23e3c9b7 Michael Hanselmann
      x/y///z/relative
405 23e3c9b7 Michael Hanselmann
      # This is a test file
406 23e3c9b7 Michael Hanselmann
      /srv/storage
407 23e3c9b7 Michael Hanselmann
      /bin
408 23e3c9b7 Michael Hanselmann
      /usr/local/lib32/
409 23e3c9b7 Michael Hanselmann
      relative/path
410 23e3c9b7 Michael Hanselmann
      """)
411 23e3c9b7 Michael Hanselmann
412 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev.ComputeWrongFileStoragePaths(_filename=tmpfile), [
413 23e3c9b7 Michael Hanselmann
      "/bin",
414 23e3c9b7 Michael Hanselmann
      "/usr/local/lib32",
415 23e3c9b7 Michael Hanselmann
      "relative/path",
416 23e3c9b7 Michael Hanselmann
      "x/y/z/relative",
417 23e3c9b7 Michael Hanselmann
      ])
418 23e3c9b7 Michael Hanselmann
419 23e3c9b7 Michael Hanselmann
420 23e3c9b7 Michael Hanselmann
class TestCheckFileStoragePathInternal(unittest.TestCase):
421 fbdac0d9 Michael Hanselmann
  def testNonAbsolute(self):
422 fbdac0d9 Michael Hanselmann
    for i in ["", "tmp", "foo/bar/baz"]:
423 fbdac0d9 Michael Hanselmann
      self.assertRaises(errors.FileStoragePathError,
424 fbdac0d9 Michael Hanselmann
                        bdev._CheckFileStoragePath, i, ["/tmp"])
425 fbdac0d9 Michael Hanselmann
426 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
427 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp", ["tmp", "xyz"])
428 fbdac0d9 Michael Hanselmann
429 fbdac0d9 Michael Hanselmann
  def testNoAllowed(self):
430 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
431 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp", [])
432 fbdac0d9 Michael Hanselmann
433 fbdac0d9 Michael Hanselmann
  def testNoAdditionalPathComponent(self):
434 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
435 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp/foo", ["/tmp/foo"])
436 fbdac0d9 Michael Hanselmann
437 fbdac0d9 Michael Hanselmann
  def testAllowed(self):
438 fbdac0d9 Michael Hanselmann
    bdev._CheckFileStoragePath("/tmp/foo/a", ["/tmp/foo"])
439 fbdac0d9 Michael Hanselmann
    bdev._CheckFileStoragePath("/tmp/foo/a/x", ["/tmp/foo"])
440 fbdac0d9 Michael Hanselmann
441 fbdac0d9 Michael Hanselmann
442 23e3c9b7 Michael Hanselmann
class TestCheckFileStoragePath(testutils.GanetiTestCase):
443 23e3c9b7 Michael Hanselmann
  def testNonExistantFile(self):
444 23e3c9b7 Michael Hanselmann
    filename = "/tmp/this/file/does/not/exist"
445 23e3c9b7 Michael Hanselmann
    assert not os.path.exists(filename)
446 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
447 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/bin/", _filename=filename)
448 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
449 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/srv/file-storage",
450 23e3c9b7 Michael Hanselmann
                      _filename=filename)
451 23e3c9b7 Michael Hanselmann
452 23e3c9b7 Michael Hanselmann
  def testAllowedPath(self):
453 23e3c9b7 Michael Hanselmann
    tmpfile = self._CreateTempFile()
454 23e3c9b7 Michael Hanselmann
455 23e3c9b7 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
456 23e3c9b7 Michael Hanselmann
      /srv/storage
457 23e3c9b7 Michael Hanselmann
      """)
458 23e3c9b7 Michael Hanselmann
459 23e3c9b7 Michael Hanselmann
    bdev.CheckFileStoragePath("/srv/storage/inst1", _filename=tmpfile)
460 23e3c9b7 Michael Hanselmann
461 23e3c9b7 Michael Hanselmann
    # No additional path component
462 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
463 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/srv/storage",
464 23e3c9b7 Michael Hanselmann
                      _filename=tmpfile)
465 23e3c9b7 Michael Hanselmann
466 23e3c9b7 Michael Hanselmann
    # Forbidden path
467 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
468 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/usr/lib64/xyz",
469 23e3c9b7 Michael Hanselmann
                      _filename=tmpfile)
470 23e3c9b7 Michael Hanselmann
471 23e3c9b7 Michael Hanselmann
472 fbdac0d9 Michael Hanselmann
class TestLoadAllowedFileStoragePaths(testutils.GanetiTestCase):
473 fbdac0d9 Michael Hanselmann
  def testDevNull(self):
474 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths("/dev/null"), [])
475 fbdac0d9 Michael Hanselmann
476 fbdac0d9 Michael Hanselmann
  def testNonExistantFile(self):
477 fbdac0d9 Michael Hanselmann
    filename = "/tmp/this/file/does/not/exist"
478 fbdac0d9 Michael Hanselmann
    assert not os.path.exists(filename)
479 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths(filename), [])
480 fbdac0d9 Michael Hanselmann
481 fbdac0d9 Michael Hanselmann
  def test(self):
482 fbdac0d9 Michael Hanselmann
    tmpfile = self._CreateTempFile()
483 fbdac0d9 Michael Hanselmann
484 fbdac0d9 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
485 fbdac0d9 Michael Hanselmann
      # This is a test file
486 fbdac0d9 Michael Hanselmann
      /tmp
487 fbdac0d9 Michael Hanselmann
      /srv/storage
488 fbdac0d9 Michael Hanselmann
      relative/path
489 fbdac0d9 Michael Hanselmann
      """)
490 fbdac0d9 Michael Hanselmann
491 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths(tmpfile), [
492 fbdac0d9 Michael Hanselmann
      "/tmp",
493 fbdac0d9 Michael Hanselmann
      "/srv/storage",
494 fbdac0d9 Michael Hanselmann
      "relative/path",
495 fbdac0d9 Michael Hanselmann
      ])
496 fbdac0d9 Michael Hanselmann
497 fbdac0d9 Michael Hanselmann
498 23d95cff Bernardo Dal Seno
class TestExclusiveStoragePvs(unittest.TestCase):
499 23d95cff Bernardo Dal Seno
  """Test cases for functions dealing with LVM PV and exclusive storage"""
500 23d95cff Bernardo Dal Seno
  # Allowance for rounding
501 23d95cff Bernardo Dal Seno
  _EPS = 1e-4
502 23d95cff Bernardo Dal Seno
  _MARGIN = constants.PART_MARGIN + constants.PART_RESERVED + _EPS
503 23d95cff Bernardo Dal Seno
504 23d95cff Bernardo Dal Seno
  @staticmethod
505 23d95cff Bernardo Dal Seno
  def _GenerateRandomPvInfo(rnd, name, vg):
506 23d95cff Bernardo Dal Seno
    # Granularity is .01 MiB
507 23d95cff Bernardo Dal Seno
    size = rnd.randint(1024 * 100, 10 * 1024 * 1024 * 100)
508 23d95cff Bernardo Dal Seno
    if rnd.choice([False, True]):
509 23d95cff Bernardo Dal Seno
      free = float(rnd.randint(0, size)) / 100.0
510 23d95cff Bernardo Dal Seno
    else:
511 23d95cff Bernardo Dal Seno
      free = float(size) / 100.0
512 23d95cff Bernardo Dal Seno
    size = float(size) / 100.0
513 23d95cff Bernardo Dal Seno
    attr = "a-"
514 23d95cff Bernardo Dal Seno
    return objects.LvmPvInfo(name=name, vg_name=vg, size=size, free=free,
515 23d95cff Bernardo Dal Seno
                             attributes=attr)
516 23d95cff Bernardo Dal Seno
517 23d95cff Bernardo Dal Seno
  def testGetStdPvSize(self):
518 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._GetStdPvSize()"""
519 23d95cff Bernardo Dal Seno
    rnd = random.Random(9517)
520 23d95cff Bernardo Dal Seno
    for _ in range(0, 50):
521 23d95cff Bernardo Dal Seno
      # Identical volumes
522 23d95cff Bernardo Dal Seno
      pvi = self._GenerateRandomPvInfo(rnd, "disk", "myvg")
523 23d95cff Bernardo Dal Seno
      onesize = bdev.LogicalVolume._GetStdPvSize([pvi])
524 23d95cff Bernardo Dal Seno
      self.assertTrue(onesize <= pvi.size)
525 23d95cff Bernardo Dal Seno
      self.assertTrue(onesize > pvi.size * (1 - self._MARGIN))
526 23d95cff Bernardo Dal Seno
      for length in range(2, 10):
527 23d95cff Bernardo Dal Seno
        n_size = bdev.LogicalVolume._GetStdPvSize([pvi] * length)
528 23d95cff Bernardo Dal Seno
        self.assertEqual(onesize, n_size)
529 23d95cff Bernardo Dal Seno
530 23d95cff Bernardo Dal Seno
      # Mixed volumes
531 23d95cff Bernardo Dal Seno
      for length in range(1, 10):
532 23d95cff Bernardo Dal Seno
        pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")
533 23d95cff Bernardo Dal Seno
                  for _ in range(0, length)]
534 23d95cff Bernardo Dal Seno
        std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
535 23d95cff Bernardo Dal Seno
        self.assertTrue(compat.all(std_size <= pvi.size for pvi in pvlist))
536 23d95cff Bernardo Dal Seno
        self.assertTrue(compat.any(std_size > pvi.size * (1 - self._MARGIN)
537 23d95cff Bernardo Dal Seno
                                   for pvi in pvlist))
538 23d95cff Bernardo Dal Seno
        pvlist.append(pvlist[0])
539 23d95cff Bernardo Dal Seno
        p1_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
540 23d95cff Bernardo Dal Seno
        self.assertEqual(std_size, p1_size)
541 23d95cff Bernardo Dal Seno
542 23d95cff Bernardo Dal Seno
  def testComputeNumPvs(self):
543 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._ComputeNumPvs()"""
544 23d95cff Bernardo Dal Seno
    rnd = random.Random(8067)
545 23d95cff Bernardo Dal Seno
    for _ in range(0, 1000):
546 23d95cff Bernardo Dal Seno
      pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")]
547 23d95cff Bernardo Dal Seno
      lv_size = float(rnd.randint(10 * 100, 1024 * 1024 * 100)) / 100.0
548 23d95cff Bernardo Dal Seno
      num_pv = bdev.LogicalVolume._ComputeNumPvs(lv_size, pvlist)
549 23d95cff Bernardo Dal Seno
      std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
550 23d95cff Bernardo Dal Seno
      self.assertTrue(num_pv >= 1)
551 23d95cff Bernardo Dal Seno
      self.assertTrue(num_pv * std_size >= lv_size)
552 23d95cff Bernardo Dal Seno
      self.assertTrue((num_pv - 1) * std_size < lv_size * (1 + self._EPS))
553 23d95cff Bernardo Dal Seno
554 23d95cff Bernardo Dal Seno
  def testGetEmptyPvNames(self):
555 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._GetEmptyPvNames()"""
556 23d95cff Bernardo Dal Seno
    rnd = random.Random(21126)
557 23d95cff Bernardo Dal Seno
    for _ in range(0, 100):
558 23d95cff Bernardo Dal Seno
      num_pvs = rnd.randint(1, 20)
559 23d95cff Bernardo Dal Seno
      pvlist = [self._GenerateRandomPvInfo(rnd, "disk%d" % n, "myvg")
560 23d95cff Bernardo Dal Seno
                for n in range(0, num_pvs)]
561 23d95cff Bernardo Dal Seno
      for num_req in range(1, num_pvs + 2):
562 23d95cff Bernardo Dal Seno
        epvs = bdev.LogicalVolume._GetEmptyPvNames(pvlist, num_req)
563 23d95cff Bernardo Dal Seno
        epvs_set = compat.UniqueFrozenset(epvs)
564 23d95cff Bernardo Dal Seno
        if len(epvs) > 1:
565 23d95cff Bernardo Dal Seno
          self.assertEqual(len(epvs), len(epvs_set))
566 23d95cff Bernardo Dal Seno
        for pvi in pvlist:
567 23d95cff Bernardo Dal Seno
          if pvi.name in epvs_set:
568 23d95cff Bernardo Dal Seno
            self.assertEqual(pvi.size, pvi.free)
569 23d95cff Bernardo Dal Seno
          else:
570 23d95cff Bernardo Dal Seno
            # There should be no remaining empty PV when less than the
571 23d95cff Bernardo Dal Seno
            # requeste number of PVs has been returned
572 23d95cff Bernardo Dal Seno
            self.assertTrue(len(epvs) == num_req or pvi.free != pvi.size)
573 23d95cff Bernardo Dal Seno
574 23d95cff Bernardo Dal Seno
575 fbdac0d9 Michael Hanselmann
if __name__ == "__main__":
576 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()