Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.block.bdev_unittest.py @ d01e51a5

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