Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.block.bdev_unittest.py @ 38396ae2

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