Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.bdev_unittest.py @ 91c17910

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 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 00ef625c Michael Hanselmann
    data = testutils.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 00ef625c Michael Hanselmann
    data = testutils.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 00ef625c Michael Hanselmann
    data = testutils.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 00ef625c Michael Hanselmann
    data = testutils.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 00ef625c Michael Hanselmann
    data = testutils.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 00ef625c Michael Hanselmann
    proc_data = testutils.TestDataFilename("proc_drbd8.txt")
241 00ef625c Michael Hanselmann
    proc80e_data = testutils.TestDataFilename("proc_drbd80-emptyline.txt")
242 00ef625c Michael Hanselmann
    proc83_data = testutils.TestDataFilename("proc_drbd83.txt")
243 00ef625c Michael Hanselmann
    proc83_sync_data = testutils.TestDataFilename("proc_drbd83_sync.txt")
244 7a380ddf Renรฉ Nussbaumer
    proc83_sync_krnl_data = \
245 00ef625c Michael Hanselmann
      testutils.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 00ef625c Michael Hanselmann
    sys_drbd_helper = testutils.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 2e076ede Stratos Psomadakis
  def setUp(self):
350 2e076ede Stratos Psomadakis
    """Set up input data"""
351 2e076ede Stratos Psomadakis
    testutils.GanetiTestCase.setUp(self)
352 2e076ede Stratos Psomadakis
353 2e076ede Stratos Psomadakis
    self.plain_output_old_ok = \
354 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_old_ok.txt")
355 2e076ede Stratos Psomadakis
    self.plain_output_old_no_matches = \
356 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_old_no_matches.txt")
357 2e076ede Stratos Psomadakis
    self.plain_output_old_extra_matches = \
358 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_old_extra_matches.txt")
359 2e076ede Stratos Psomadakis
    self.plain_output_old_empty = \
360 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_old_empty.txt")
361 2e076ede Stratos Psomadakis
    self.plain_output_new_ok = \
362 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_new_ok.txt")
363 2e076ede Stratos Psomadakis
    self.plain_output_new_no_matches = \
364 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_new_no_matches.txt")
365 2e076ede Stratos Psomadakis
    self.plain_output_new_extra_matches = \
366 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_new_extra_matches.txt")
367 2e076ede Stratos Psomadakis
    # This file is completely empty, and as such it's not shipped.
368 2e076ede Stratos Psomadakis
    self.plain_output_new_empty = ""
369 2e076ede Stratos Psomadakis
    self.json_output_ok = testutils.ReadTestData("bdev-rbd/json_output_ok.txt")
370 2e076ede Stratos Psomadakis
    self.json_output_no_matches = \
371 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/json_output_no_matches.txt")
372 2e076ede Stratos Psomadakis
    self.json_output_extra_matches = \
373 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/json_output_extra_matches.txt")
374 2e076ede Stratos Psomadakis
    self.json_output_empty = \
375 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/json_output_empty.txt")
376 2e076ede Stratos Psomadakis
    self.output_invalid = testutils.ReadTestData("bdev-rbd/output_invalid.txt")
377 2e076ede Stratos Psomadakis
378 2e076ede Stratos Psomadakis
    self.volume_name = "d7ab910a-4933-4ffe-88d0-faf2ce31390a.rbd.disk0"
379 2e076ede Stratos Psomadakis
380 2e076ede Stratos Psomadakis
  def test_ParseRbdShowmappedJson(self):
381 2e076ede Stratos Psomadakis
    parse_function = bdev.RADOSBlockDevice._ParseRbdShowmappedJson
382 2e076ede Stratos Psomadakis
383 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.json_output_ok, self.volume_name),
384 2e076ede Stratos Psomadakis
                     "/dev/rbd3")
385 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.json_output_empty, self.volume_name),
386 2e076ede Stratos Psomadakis
                     None)
387 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.json_output_no_matches,
388 2e076ede Stratos Psomadakis
                     self.volume_name), None)
389 7181fba0 Constantinos Venetsanopoulos
    self.assertRaises(errors.BlockDeviceError, parse_function,
390 2e076ede Stratos Psomadakis
                      self.json_output_extra_matches, self.volume_name)
391 7181fba0 Constantinos Venetsanopoulos
    self.assertRaises(errors.BlockDeviceError, parse_function,
392 2e076ede Stratos Psomadakis
                      self.output_invalid, self.volume_name)
393 2e076ede Stratos Psomadakis
394 2e076ede Stratos Psomadakis
  def test_ParseRbdShowmappedPlain(self):
395 2e076ede Stratos Psomadakis
    parse_function = bdev.RADOSBlockDevice._ParseRbdShowmappedPlain
396 2e076ede Stratos Psomadakis
397 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_new_ok,
398 2e076ede Stratos Psomadakis
                     self.volume_name), "/dev/rbd3")
399 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_old_ok,
400 2e076ede Stratos Psomadakis
                     self.volume_name), "/dev/rbd3")
401 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_new_empty,
402 2e076ede Stratos Psomadakis
                     self.volume_name), None)
403 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_old_empty,
404 2e076ede Stratos Psomadakis
                     self.volume_name), None)
405 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_new_no_matches,
406 2e076ede Stratos Psomadakis
                     self.volume_name), None)
407 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_old_no_matches,
408 2e076ede Stratos Psomadakis
                     self.volume_name), None)
409 2e076ede Stratos Psomadakis
    self.assertRaises(errors.BlockDeviceError, parse_function,
410 2e076ede Stratos Psomadakis
                      self.plain_output_new_extra_matches, self.volume_name)
411 2e076ede Stratos Psomadakis
    self.assertRaises(errors.BlockDeviceError, parse_function,
412 2e076ede Stratos Psomadakis
                      self.plain_output_old_extra_matches, self.volume_name)
413 2e076ede Stratos Psomadakis
    self.assertRaises(errors.BlockDeviceError, parse_function,
414 2e076ede Stratos Psomadakis
                      self.output_invalid, self.volume_name)
415 7181fba0 Constantinos Venetsanopoulos
416 23e3c9b7 Michael Hanselmann
class TestComputeWrongFileStoragePathsInternal(unittest.TestCase):
417 23e3c9b7 Michael Hanselmann
  def testPaths(self):
418 23e3c9b7 Michael Hanselmann
    paths = bdev._GetForbiddenFileStoragePaths()
419 23e3c9b7 Michael Hanselmann
420 23e3c9b7 Michael Hanselmann
    for path in ["/bin", "/usr/local/sbin", "/lib64", "/etc", "/sys"]:
421 23e3c9b7 Michael Hanselmann
      self.assertTrue(path in paths)
422 23e3c9b7 Michael Hanselmann
423 23e3c9b7 Michael Hanselmann
    self.assertEqual(set(map(os.path.normpath, paths)), paths)
424 23e3c9b7 Michael Hanselmann
425 23e3c9b7 Michael Hanselmann
  def test(self):
426 23e3c9b7 Michael Hanselmann
    vfsp = bdev._ComputeWrongFileStoragePaths
427 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp([]), [])
428 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/tmp"]), [])
429 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/bin/ls"]), ["/bin/ls"])
430 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/bin"]), ["/bin"])
431 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/usr/sbin/vim", "/srv/file-storage"]),
432 23e3c9b7 Michael Hanselmann
                     ["/usr/sbin/vim"])
433 23e3c9b7 Michael Hanselmann
434 23e3c9b7 Michael Hanselmann
435 23e3c9b7 Michael Hanselmann
class TestComputeWrongFileStoragePaths(testutils.GanetiTestCase):
436 23e3c9b7 Michael Hanselmann
  def test(self):
437 23e3c9b7 Michael Hanselmann
    tmpfile = self._CreateTempFile()
438 23e3c9b7 Michael Hanselmann
439 23e3c9b7 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
440 23e3c9b7 Michael Hanselmann
      /tmp
441 23e3c9b7 Michael Hanselmann
      x/y///z/relative
442 23e3c9b7 Michael Hanselmann
      # This is a test file
443 23e3c9b7 Michael Hanselmann
      /srv/storage
444 23e3c9b7 Michael Hanselmann
      /bin
445 23e3c9b7 Michael Hanselmann
      /usr/local/lib32/
446 23e3c9b7 Michael Hanselmann
      relative/path
447 23e3c9b7 Michael Hanselmann
      """)
448 23e3c9b7 Michael Hanselmann
449 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev.ComputeWrongFileStoragePaths(_filename=tmpfile), [
450 23e3c9b7 Michael Hanselmann
      "/bin",
451 23e3c9b7 Michael Hanselmann
      "/usr/local/lib32",
452 23e3c9b7 Michael Hanselmann
      "relative/path",
453 23e3c9b7 Michael Hanselmann
      "x/y/z/relative",
454 23e3c9b7 Michael Hanselmann
      ])
455 23e3c9b7 Michael Hanselmann
456 23e3c9b7 Michael Hanselmann
457 23e3c9b7 Michael Hanselmann
class TestCheckFileStoragePathInternal(unittest.TestCase):
458 fbdac0d9 Michael Hanselmann
  def testNonAbsolute(self):
459 fbdac0d9 Michael Hanselmann
    for i in ["", "tmp", "foo/bar/baz"]:
460 fbdac0d9 Michael Hanselmann
      self.assertRaises(errors.FileStoragePathError,
461 fbdac0d9 Michael Hanselmann
                        bdev._CheckFileStoragePath, i, ["/tmp"])
462 fbdac0d9 Michael Hanselmann
463 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
464 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp", ["tmp", "xyz"])
465 fbdac0d9 Michael Hanselmann
466 fbdac0d9 Michael Hanselmann
  def testNoAllowed(self):
467 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
468 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp", [])
469 fbdac0d9 Michael Hanselmann
470 fbdac0d9 Michael Hanselmann
  def testNoAdditionalPathComponent(self):
471 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
472 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp/foo", ["/tmp/foo"])
473 fbdac0d9 Michael Hanselmann
474 fbdac0d9 Michael Hanselmann
  def testAllowed(self):
475 fbdac0d9 Michael Hanselmann
    bdev._CheckFileStoragePath("/tmp/foo/a", ["/tmp/foo"])
476 fbdac0d9 Michael Hanselmann
    bdev._CheckFileStoragePath("/tmp/foo/a/x", ["/tmp/foo"])
477 fbdac0d9 Michael Hanselmann
478 fbdac0d9 Michael Hanselmann
479 23e3c9b7 Michael Hanselmann
class TestCheckFileStoragePath(testutils.GanetiTestCase):
480 23e3c9b7 Michael Hanselmann
  def testNonExistantFile(self):
481 23e3c9b7 Michael Hanselmann
    filename = "/tmp/this/file/does/not/exist"
482 23e3c9b7 Michael Hanselmann
    assert not os.path.exists(filename)
483 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
484 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/bin/", _filename=filename)
485 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
486 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/srv/file-storage",
487 23e3c9b7 Michael Hanselmann
                      _filename=filename)
488 23e3c9b7 Michael Hanselmann
489 23e3c9b7 Michael Hanselmann
  def testAllowedPath(self):
490 23e3c9b7 Michael Hanselmann
    tmpfile = self._CreateTempFile()
491 23e3c9b7 Michael Hanselmann
492 23e3c9b7 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
493 23e3c9b7 Michael Hanselmann
      /srv/storage
494 23e3c9b7 Michael Hanselmann
      """)
495 23e3c9b7 Michael Hanselmann
496 23e3c9b7 Michael Hanselmann
    bdev.CheckFileStoragePath("/srv/storage/inst1", _filename=tmpfile)
497 23e3c9b7 Michael Hanselmann
498 23e3c9b7 Michael Hanselmann
    # No additional path component
499 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
500 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/srv/storage",
501 23e3c9b7 Michael Hanselmann
                      _filename=tmpfile)
502 23e3c9b7 Michael Hanselmann
503 23e3c9b7 Michael Hanselmann
    # Forbidden path
504 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
505 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/usr/lib64/xyz",
506 23e3c9b7 Michael Hanselmann
                      _filename=tmpfile)
507 23e3c9b7 Michael Hanselmann
508 23e3c9b7 Michael Hanselmann
509 fbdac0d9 Michael Hanselmann
class TestLoadAllowedFileStoragePaths(testutils.GanetiTestCase):
510 fbdac0d9 Michael Hanselmann
  def testDevNull(self):
511 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths("/dev/null"), [])
512 fbdac0d9 Michael Hanselmann
513 fbdac0d9 Michael Hanselmann
  def testNonExistantFile(self):
514 fbdac0d9 Michael Hanselmann
    filename = "/tmp/this/file/does/not/exist"
515 fbdac0d9 Michael Hanselmann
    assert not os.path.exists(filename)
516 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths(filename), [])
517 fbdac0d9 Michael Hanselmann
518 fbdac0d9 Michael Hanselmann
  def test(self):
519 fbdac0d9 Michael Hanselmann
    tmpfile = self._CreateTempFile()
520 fbdac0d9 Michael Hanselmann
521 fbdac0d9 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
522 fbdac0d9 Michael Hanselmann
      # This is a test file
523 fbdac0d9 Michael Hanselmann
      /tmp
524 fbdac0d9 Michael Hanselmann
      /srv/storage
525 fbdac0d9 Michael Hanselmann
      relative/path
526 fbdac0d9 Michael Hanselmann
      """)
527 fbdac0d9 Michael Hanselmann
528 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths(tmpfile), [
529 fbdac0d9 Michael Hanselmann
      "/tmp",
530 fbdac0d9 Michael Hanselmann
      "/srv/storage",
531 fbdac0d9 Michael Hanselmann
      "relative/path",
532 fbdac0d9 Michael Hanselmann
      ])
533 fbdac0d9 Michael Hanselmann
534 fbdac0d9 Michael Hanselmann
535 23d95cff Bernardo Dal Seno
class TestExclusiveStoragePvs(unittest.TestCase):
536 23d95cff Bernardo Dal Seno
  """Test cases for functions dealing with LVM PV and exclusive storage"""
537 23d95cff Bernardo Dal Seno
  # Allowance for rounding
538 23d95cff Bernardo Dal Seno
  _EPS = 1e-4
539 23d95cff Bernardo Dal Seno
  _MARGIN = constants.PART_MARGIN + constants.PART_RESERVED + _EPS
540 23d95cff Bernardo Dal Seno
541 23d95cff Bernardo Dal Seno
  @staticmethod
542 23d95cff Bernardo Dal Seno
  def _GenerateRandomPvInfo(rnd, name, vg):
543 23d95cff Bernardo Dal Seno
    # Granularity is .01 MiB
544 23d95cff Bernardo Dal Seno
    size = rnd.randint(1024 * 100, 10 * 1024 * 1024 * 100)
545 23d95cff Bernardo Dal Seno
    if rnd.choice([False, True]):
546 23d95cff Bernardo Dal Seno
      free = float(rnd.randint(0, size)) / 100.0
547 23d95cff Bernardo Dal Seno
    else:
548 23d95cff Bernardo Dal Seno
      free = float(size) / 100.0
549 23d95cff Bernardo Dal Seno
    size = float(size) / 100.0
550 23d95cff Bernardo Dal Seno
    attr = "a-"
551 23d95cff Bernardo Dal Seno
    return objects.LvmPvInfo(name=name, vg_name=vg, size=size, free=free,
552 23d95cff Bernardo Dal Seno
                             attributes=attr)
553 23d95cff Bernardo Dal Seno
554 23d95cff Bernardo Dal Seno
  def testGetStdPvSize(self):
555 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._GetStdPvSize()"""
556 23d95cff Bernardo Dal Seno
    rnd = random.Random(9517)
557 23d95cff Bernardo Dal Seno
    for _ in range(0, 50):
558 23d95cff Bernardo Dal Seno
      # Identical volumes
559 23d95cff Bernardo Dal Seno
      pvi = self._GenerateRandomPvInfo(rnd, "disk", "myvg")
560 23d95cff Bernardo Dal Seno
      onesize = bdev.LogicalVolume._GetStdPvSize([pvi])
561 23d95cff Bernardo Dal Seno
      self.assertTrue(onesize <= pvi.size)
562 23d95cff Bernardo Dal Seno
      self.assertTrue(onesize > pvi.size * (1 - self._MARGIN))
563 23d95cff Bernardo Dal Seno
      for length in range(2, 10):
564 23d95cff Bernardo Dal Seno
        n_size = bdev.LogicalVolume._GetStdPvSize([pvi] * length)
565 23d95cff Bernardo Dal Seno
        self.assertEqual(onesize, n_size)
566 23d95cff Bernardo Dal Seno
567 23d95cff Bernardo Dal Seno
      # Mixed volumes
568 23d95cff Bernardo Dal Seno
      for length in range(1, 10):
569 23d95cff Bernardo Dal Seno
        pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")
570 23d95cff Bernardo Dal Seno
                  for _ in range(0, length)]
571 23d95cff Bernardo Dal Seno
        std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
572 23d95cff Bernardo Dal Seno
        self.assertTrue(compat.all(std_size <= pvi.size for pvi in pvlist))
573 23d95cff Bernardo Dal Seno
        self.assertTrue(compat.any(std_size > pvi.size * (1 - self._MARGIN)
574 23d95cff Bernardo Dal Seno
                                   for pvi in pvlist))
575 23d95cff Bernardo Dal Seno
        pvlist.append(pvlist[0])
576 23d95cff Bernardo Dal Seno
        p1_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
577 23d95cff Bernardo Dal Seno
        self.assertEqual(std_size, p1_size)
578 23d95cff Bernardo Dal Seno
579 23d95cff Bernardo Dal Seno
  def testComputeNumPvs(self):
580 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._ComputeNumPvs()"""
581 23d95cff Bernardo Dal Seno
    rnd = random.Random(8067)
582 23d95cff Bernardo Dal Seno
    for _ in range(0, 1000):
583 23d95cff Bernardo Dal Seno
      pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")]
584 23d95cff Bernardo Dal Seno
      lv_size = float(rnd.randint(10 * 100, 1024 * 1024 * 100)) / 100.0
585 23d95cff Bernardo Dal Seno
      num_pv = bdev.LogicalVolume._ComputeNumPvs(lv_size, pvlist)
586 23d95cff Bernardo Dal Seno
      std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
587 23d95cff Bernardo Dal Seno
      self.assertTrue(num_pv >= 1)
588 23d95cff Bernardo Dal Seno
      self.assertTrue(num_pv * std_size >= lv_size)
589 23d95cff Bernardo Dal Seno
      self.assertTrue((num_pv - 1) * std_size < lv_size * (1 + self._EPS))
590 23d95cff Bernardo Dal Seno
591 23d95cff Bernardo Dal Seno
  def testGetEmptyPvNames(self):
592 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._GetEmptyPvNames()"""
593 23d95cff Bernardo Dal Seno
    rnd = random.Random(21126)
594 23d95cff Bernardo Dal Seno
    for _ in range(0, 100):
595 23d95cff Bernardo Dal Seno
      num_pvs = rnd.randint(1, 20)
596 23d95cff Bernardo Dal Seno
      pvlist = [self._GenerateRandomPvInfo(rnd, "disk%d" % n, "myvg")
597 23d95cff Bernardo Dal Seno
                for n in range(0, num_pvs)]
598 23d95cff Bernardo Dal Seno
      for num_req in range(1, num_pvs + 2):
599 23d95cff Bernardo Dal Seno
        epvs = bdev.LogicalVolume._GetEmptyPvNames(pvlist, num_req)
600 23d95cff Bernardo Dal Seno
        epvs_set = compat.UniqueFrozenset(epvs)
601 23d95cff Bernardo Dal Seno
        if len(epvs) > 1:
602 23d95cff Bernardo Dal Seno
          self.assertEqual(len(epvs), len(epvs_set))
603 23d95cff Bernardo Dal Seno
        for pvi in pvlist:
604 23d95cff Bernardo Dal Seno
          if pvi.name in epvs_set:
605 23d95cff Bernardo Dal Seno
            self.assertEqual(pvi.size, pvi.free)
606 23d95cff Bernardo Dal Seno
          else:
607 23d95cff Bernardo Dal Seno
            # There should be no remaining empty PV when less than the
608 23d95cff Bernardo Dal Seno
            # requeste number of PVs has been returned
609 23d95cff Bernardo Dal Seno
            self.assertTrue(len(epvs) == num_req or pvi.free != pvi.size)
610 23d95cff Bernardo Dal Seno
611 23d95cff Bernardo Dal Seno
612 fbdac0d9 Michael Hanselmann
if __name__ == "__main__":
613 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()