Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.storage.bdev_unittest.py @ 688b5752

History | View | Annotate | Download (13.7 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 cde49218 Helga Velroyen
from ganeti.storage import bdev
35 3840729d Iustin Pop
36 25231ec5 Michael Hanselmann
import testutils
37 25231ec5 Michael Hanselmann
38 3840729d Iustin Pop
39 7181fba0 Constantinos Venetsanopoulos
class TestRADOSBlockDevice(testutils.GanetiTestCase):
40 2e076ede Stratos Psomadakis
  def setUp(self):
41 2e076ede Stratos Psomadakis
    """Set up input data"""
42 2e076ede Stratos Psomadakis
    testutils.GanetiTestCase.setUp(self)
43 2e076ede Stratos Psomadakis
44 2e076ede Stratos Psomadakis
    self.plain_output_old_ok = \
45 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_old_ok.txt")
46 2e076ede Stratos Psomadakis
    self.plain_output_old_no_matches = \
47 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_old_no_matches.txt")
48 2e076ede Stratos Psomadakis
    self.plain_output_old_extra_matches = \
49 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_old_extra_matches.txt")
50 2e076ede Stratos Psomadakis
    self.plain_output_old_empty = \
51 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_old_empty.txt")
52 2e076ede Stratos Psomadakis
    self.plain_output_new_ok = \
53 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_new_ok.txt")
54 2e076ede Stratos Psomadakis
    self.plain_output_new_no_matches = \
55 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_new_no_matches.txt")
56 2e076ede Stratos Psomadakis
    self.plain_output_new_extra_matches = \
57 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/plain_output_new_extra_matches.txt")
58 2e076ede Stratos Psomadakis
    # This file is completely empty, and as such it's not shipped.
59 2e076ede Stratos Psomadakis
    self.plain_output_new_empty = ""
60 2e076ede Stratos Psomadakis
    self.json_output_ok = testutils.ReadTestData("bdev-rbd/json_output_ok.txt")
61 2e076ede Stratos Psomadakis
    self.json_output_no_matches = \
62 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/json_output_no_matches.txt")
63 2e076ede Stratos Psomadakis
    self.json_output_extra_matches = \
64 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/json_output_extra_matches.txt")
65 2e076ede Stratos Psomadakis
    self.json_output_empty = \
66 2e076ede Stratos Psomadakis
      testutils.ReadTestData("bdev-rbd/json_output_empty.txt")
67 2e076ede Stratos Psomadakis
    self.output_invalid = testutils.ReadTestData("bdev-rbd/output_invalid.txt")
68 2e076ede Stratos Psomadakis
69 2e076ede Stratos Psomadakis
    self.volume_name = "d7ab910a-4933-4ffe-88d0-faf2ce31390a.rbd.disk0"
70 2e076ede Stratos Psomadakis
71 2e076ede Stratos Psomadakis
  def test_ParseRbdShowmappedJson(self):
72 2e076ede Stratos Psomadakis
    parse_function = bdev.RADOSBlockDevice._ParseRbdShowmappedJson
73 2e076ede Stratos Psomadakis
74 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.json_output_ok, self.volume_name),
75 2e076ede Stratos Psomadakis
                     "/dev/rbd3")
76 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.json_output_empty, self.volume_name),
77 2e076ede Stratos Psomadakis
                     None)
78 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.json_output_no_matches,
79 2e076ede Stratos Psomadakis
                     self.volume_name), None)
80 7181fba0 Constantinos Venetsanopoulos
    self.assertRaises(errors.BlockDeviceError, parse_function,
81 2e076ede Stratos Psomadakis
                      self.json_output_extra_matches, self.volume_name)
82 7181fba0 Constantinos Venetsanopoulos
    self.assertRaises(errors.BlockDeviceError, parse_function,
83 2e076ede Stratos Psomadakis
                      self.output_invalid, self.volume_name)
84 2e076ede Stratos Psomadakis
85 2e076ede Stratos Psomadakis
  def test_ParseRbdShowmappedPlain(self):
86 2e076ede Stratos Psomadakis
    parse_function = bdev.RADOSBlockDevice._ParseRbdShowmappedPlain
87 2e076ede Stratos Psomadakis
88 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_new_ok,
89 2e076ede Stratos Psomadakis
                     self.volume_name), "/dev/rbd3")
90 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_old_ok,
91 2e076ede Stratos Psomadakis
                     self.volume_name), "/dev/rbd3")
92 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_new_empty,
93 2e076ede Stratos Psomadakis
                     self.volume_name), None)
94 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_old_empty,
95 2e076ede Stratos Psomadakis
                     self.volume_name), None)
96 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_new_no_matches,
97 2e076ede Stratos Psomadakis
                     self.volume_name), None)
98 2e076ede Stratos Psomadakis
    self.assertEqual(parse_function(self.plain_output_old_no_matches,
99 2e076ede Stratos Psomadakis
                     self.volume_name), None)
100 2e076ede Stratos Psomadakis
    self.assertRaises(errors.BlockDeviceError, parse_function,
101 2e076ede Stratos Psomadakis
                      self.plain_output_new_extra_matches, self.volume_name)
102 2e076ede Stratos Psomadakis
    self.assertRaises(errors.BlockDeviceError, parse_function,
103 2e076ede Stratos Psomadakis
                      self.plain_output_old_extra_matches, self.volume_name)
104 2e076ede Stratos Psomadakis
    self.assertRaises(errors.BlockDeviceError, parse_function,
105 2e076ede Stratos Psomadakis
                      self.output_invalid, self.volume_name)
106 7181fba0 Constantinos Venetsanopoulos
107 23e3c9b7 Michael Hanselmann
class TestComputeWrongFileStoragePathsInternal(unittest.TestCase):
108 23e3c9b7 Michael Hanselmann
  def testPaths(self):
109 23e3c9b7 Michael Hanselmann
    paths = bdev._GetForbiddenFileStoragePaths()
110 23e3c9b7 Michael Hanselmann
111 23e3c9b7 Michael Hanselmann
    for path in ["/bin", "/usr/local/sbin", "/lib64", "/etc", "/sys"]:
112 23e3c9b7 Michael Hanselmann
      self.assertTrue(path in paths)
113 23e3c9b7 Michael Hanselmann
114 23e3c9b7 Michael Hanselmann
    self.assertEqual(set(map(os.path.normpath, paths)), paths)
115 23e3c9b7 Michael Hanselmann
116 23e3c9b7 Michael Hanselmann
  def test(self):
117 23e3c9b7 Michael Hanselmann
    vfsp = bdev._ComputeWrongFileStoragePaths
118 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp([]), [])
119 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/tmp"]), [])
120 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/bin/ls"]), ["/bin/ls"])
121 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/bin"]), ["/bin"])
122 23e3c9b7 Michael Hanselmann
    self.assertEqual(vfsp(["/usr/sbin/vim", "/srv/file-storage"]),
123 23e3c9b7 Michael Hanselmann
                     ["/usr/sbin/vim"])
124 23e3c9b7 Michael Hanselmann
125 23e3c9b7 Michael Hanselmann
126 23e3c9b7 Michael Hanselmann
class TestComputeWrongFileStoragePaths(testutils.GanetiTestCase):
127 23e3c9b7 Michael Hanselmann
  def test(self):
128 23e3c9b7 Michael Hanselmann
    tmpfile = self._CreateTempFile()
129 23e3c9b7 Michael Hanselmann
130 23e3c9b7 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
131 23e3c9b7 Michael Hanselmann
      /tmp
132 23e3c9b7 Michael Hanselmann
      x/y///z/relative
133 23e3c9b7 Michael Hanselmann
      # This is a test file
134 23e3c9b7 Michael Hanselmann
      /srv/storage
135 23e3c9b7 Michael Hanselmann
      /bin
136 23e3c9b7 Michael Hanselmann
      /usr/local/lib32/
137 23e3c9b7 Michael Hanselmann
      relative/path
138 23e3c9b7 Michael Hanselmann
      """)
139 23e3c9b7 Michael Hanselmann
140 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev.ComputeWrongFileStoragePaths(_filename=tmpfile), [
141 23e3c9b7 Michael Hanselmann
      "/bin",
142 23e3c9b7 Michael Hanselmann
      "/usr/local/lib32",
143 23e3c9b7 Michael Hanselmann
      "relative/path",
144 23e3c9b7 Michael Hanselmann
      "x/y/z/relative",
145 23e3c9b7 Michael Hanselmann
      ])
146 23e3c9b7 Michael Hanselmann
147 23e3c9b7 Michael Hanselmann
148 23e3c9b7 Michael Hanselmann
class TestCheckFileStoragePathInternal(unittest.TestCase):
149 fbdac0d9 Michael Hanselmann
  def testNonAbsolute(self):
150 fbdac0d9 Michael Hanselmann
    for i in ["", "tmp", "foo/bar/baz"]:
151 fbdac0d9 Michael Hanselmann
      self.assertRaises(errors.FileStoragePathError,
152 fbdac0d9 Michael Hanselmann
                        bdev._CheckFileStoragePath, i, ["/tmp"])
153 fbdac0d9 Michael Hanselmann
154 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
155 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp", ["tmp", "xyz"])
156 fbdac0d9 Michael Hanselmann
157 fbdac0d9 Michael Hanselmann
  def testNoAllowed(self):
158 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
159 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp", [])
160 fbdac0d9 Michael Hanselmann
161 fbdac0d9 Michael Hanselmann
  def testNoAdditionalPathComponent(self):
162 fbdac0d9 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
163 fbdac0d9 Michael Hanselmann
                      bdev._CheckFileStoragePath, "/tmp/foo", ["/tmp/foo"])
164 fbdac0d9 Michael Hanselmann
165 fbdac0d9 Michael Hanselmann
  def testAllowed(self):
166 fbdac0d9 Michael Hanselmann
    bdev._CheckFileStoragePath("/tmp/foo/a", ["/tmp/foo"])
167 fbdac0d9 Michael Hanselmann
    bdev._CheckFileStoragePath("/tmp/foo/a/x", ["/tmp/foo"])
168 fbdac0d9 Michael Hanselmann
169 fbdac0d9 Michael Hanselmann
170 23e3c9b7 Michael Hanselmann
class TestCheckFileStoragePath(testutils.GanetiTestCase):
171 23e3c9b7 Michael Hanselmann
  def testNonExistantFile(self):
172 23e3c9b7 Michael Hanselmann
    filename = "/tmp/this/file/does/not/exist"
173 23e3c9b7 Michael Hanselmann
    assert not os.path.exists(filename)
174 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
175 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/bin/", _filename=filename)
176 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
177 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/srv/file-storage",
178 23e3c9b7 Michael Hanselmann
                      _filename=filename)
179 23e3c9b7 Michael Hanselmann
180 23e3c9b7 Michael Hanselmann
  def testAllowedPath(self):
181 23e3c9b7 Michael Hanselmann
    tmpfile = self._CreateTempFile()
182 23e3c9b7 Michael Hanselmann
183 23e3c9b7 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
184 23e3c9b7 Michael Hanselmann
      /srv/storage
185 23e3c9b7 Michael Hanselmann
      """)
186 23e3c9b7 Michael Hanselmann
187 23e3c9b7 Michael Hanselmann
    bdev.CheckFileStoragePath("/srv/storage/inst1", _filename=tmpfile)
188 23e3c9b7 Michael Hanselmann
189 23e3c9b7 Michael Hanselmann
    # No additional path component
190 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
191 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/srv/storage",
192 23e3c9b7 Michael Hanselmann
                      _filename=tmpfile)
193 23e3c9b7 Michael Hanselmann
194 23e3c9b7 Michael Hanselmann
    # Forbidden path
195 23e3c9b7 Michael Hanselmann
    self.assertRaises(errors.FileStoragePathError,
196 23e3c9b7 Michael Hanselmann
                      bdev.CheckFileStoragePath, "/usr/lib64/xyz",
197 23e3c9b7 Michael Hanselmann
                      _filename=tmpfile)
198 23e3c9b7 Michael Hanselmann
199 23e3c9b7 Michael Hanselmann
200 fbdac0d9 Michael Hanselmann
class TestLoadAllowedFileStoragePaths(testutils.GanetiTestCase):
201 fbdac0d9 Michael Hanselmann
  def testDevNull(self):
202 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths("/dev/null"), [])
203 fbdac0d9 Michael Hanselmann
204 fbdac0d9 Michael Hanselmann
  def testNonExistantFile(self):
205 fbdac0d9 Michael Hanselmann
    filename = "/tmp/this/file/does/not/exist"
206 fbdac0d9 Michael Hanselmann
    assert not os.path.exists(filename)
207 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths(filename), [])
208 fbdac0d9 Michael Hanselmann
209 fbdac0d9 Michael Hanselmann
  def test(self):
210 fbdac0d9 Michael Hanselmann
    tmpfile = self._CreateTempFile()
211 fbdac0d9 Michael Hanselmann
212 fbdac0d9 Michael Hanselmann
    utils.WriteFile(tmpfile, data="""
213 fbdac0d9 Michael Hanselmann
      # This is a test file
214 fbdac0d9 Michael Hanselmann
      /tmp
215 fbdac0d9 Michael Hanselmann
      /srv/storage
216 fbdac0d9 Michael Hanselmann
      relative/path
217 fbdac0d9 Michael Hanselmann
      """)
218 fbdac0d9 Michael Hanselmann
219 23e3c9b7 Michael Hanselmann
    self.assertEqual(bdev._LoadAllowedFileStoragePaths(tmpfile), [
220 fbdac0d9 Michael Hanselmann
      "/tmp",
221 fbdac0d9 Michael Hanselmann
      "/srv/storage",
222 fbdac0d9 Michael Hanselmann
      "relative/path",
223 fbdac0d9 Michael Hanselmann
      ])
224 fbdac0d9 Michael Hanselmann
225 fbdac0d9 Michael Hanselmann
226 23d95cff Bernardo Dal Seno
class TestExclusiveStoragePvs(unittest.TestCase):
227 23d95cff Bernardo Dal Seno
  """Test cases for functions dealing with LVM PV and exclusive storage"""
228 23d95cff Bernardo Dal Seno
  # Allowance for rounding
229 23d95cff Bernardo Dal Seno
  _EPS = 1e-4
230 23d95cff Bernardo Dal Seno
  _MARGIN = constants.PART_MARGIN + constants.PART_RESERVED + _EPS
231 23d95cff Bernardo Dal Seno
232 23d95cff Bernardo Dal Seno
  @staticmethod
233 23d95cff Bernardo Dal Seno
  def _GenerateRandomPvInfo(rnd, name, vg):
234 23d95cff Bernardo Dal Seno
    # Granularity is .01 MiB
235 23d95cff Bernardo Dal Seno
    size = rnd.randint(1024 * 100, 10 * 1024 * 1024 * 100)
236 23d95cff Bernardo Dal Seno
    if rnd.choice([False, True]):
237 23d95cff Bernardo Dal Seno
      free = float(rnd.randint(0, size)) / 100.0
238 23d95cff Bernardo Dal Seno
    else:
239 23d95cff Bernardo Dal Seno
      free = float(size) / 100.0
240 23d95cff Bernardo Dal Seno
    size = float(size) / 100.0
241 23d95cff Bernardo Dal Seno
    attr = "a-"
242 23d95cff Bernardo Dal Seno
    return objects.LvmPvInfo(name=name, vg_name=vg, size=size, free=free,
243 23d95cff Bernardo Dal Seno
                             attributes=attr)
244 23d95cff Bernardo Dal Seno
245 23d95cff Bernardo Dal Seno
  def testGetStdPvSize(self):
246 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._GetStdPvSize()"""
247 23d95cff Bernardo Dal Seno
    rnd = random.Random(9517)
248 23d95cff Bernardo Dal Seno
    for _ in range(0, 50):
249 23d95cff Bernardo Dal Seno
      # Identical volumes
250 23d95cff Bernardo Dal Seno
      pvi = self._GenerateRandomPvInfo(rnd, "disk", "myvg")
251 23d95cff Bernardo Dal Seno
      onesize = bdev.LogicalVolume._GetStdPvSize([pvi])
252 23d95cff Bernardo Dal Seno
      self.assertTrue(onesize <= pvi.size)
253 23d95cff Bernardo Dal Seno
      self.assertTrue(onesize > pvi.size * (1 - self._MARGIN))
254 23d95cff Bernardo Dal Seno
      for length in range(2, 10):
255 23d95cff Bernardo Dal Seno
        n_size = bdev.LogicalVolume._GetStdPvSize([pvi] * length)
256 23d95cff Bernardo Dal Seno
        self.assertEqual(onesize, n_size)
257 23d95cff Bernardo Dal Seno
258 23d95cff Bernardo Dal Seno
      # Mixed volumes
259 23d95cff Bernardo Dal Seno
      for length in range(1, 10):
260 23d95cff Bernardo Dal Seno
        pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")
261 23d95cff Bernardo Dal Seno
                  for _ in range(0, length)]
262 23d95cff Bernardo Dal Seno
        std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
263 23d95cff Bernardo Dal Seno
        self.assertTrue(compat.all(std_size <= pvi.size for pvi in pvlist))
264 23d95cff Bernardo Dal Seno
        self.assertTrue(compat.any(std_size > pvi.size * (1 - self._MARGIN)
265 23d95cff Bernardo Dal Seno
                                   for pvi in pvlist))
266 23d95cff Bernardo Dal Seno
        pvlist.append(pvlist[0])
267 23d95cff Bernardo Dal Seno
        p1_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
268 23d95cff Bernardo Dal Seno
        self.assertEqual(std_size, p1_size)
269 23d95cff Bernardo Dal Seno
270 23d95cff Bernardo Dal Seno
  def testComputeNumPvs(self):
271 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._ComputeNumPvs()"""
272 23d95cff Bernardo Dal Seno
    rnd = random.Random(8067)
273 23d95cff Bernardo Dal Seno
    for _ in range(0, 1000):
274 23d95cff Bernardo Dal Seno
      pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")]
275 23d95cff Bernardo Dal Seno
      lv_size = float(rnd.randint(10 * 100, 1024 * 1024 * 100)) / 100.0
276 23d95cff Bernardo Dal Seno
      num_pv = bdev.LogicalVolume._ComputeNumPvs(lv_size, pvlist)
277 23d95cff Bernardo Dal Seno
      std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
278 23d95cff Bernardo Dal Seno
      self.assertTrue(num_pv >= 1)
279 23d95cff Bernardo Dal Seno
      self.assertTrue(num_pv * std_size >= lv_size)
280 23d95cff Bernardo Dal Seno
      self.assertTrue((num_pv - 1) * std_size < lv_size * (1 + self._EPS))
281 23d95cff Bernardo Dal Seno
282 23d95cff Bernardo Dal Seno
  def testGetEmptyPvNames(self):
283 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._GetEmptyPvNames()"""
284 23d95cff Bernardo Dal Seno
    rnd = random.Random(21126)
285 23d95cff Bernardo Dal Seno
    for _ in range(0, 100):
286 23d95cff Bernardo Dal Seno
      num_pvs = rnd.randint(1, 20)
287 23d95cff Bernardo Dal Seno
      pvlist = [self._GenerateRandomPvInfo(rnd, "disk%d" % n, "myvg")
288 23d95cff Bernardo Dal Seno
                for n in range(0, num_pvs)]
289 23d95cff Bernardo Dal Seno
      for num_req in range(1, num_pvs + 2):
290 23d95cff Bernardo Dal Seno
        epvs = bdev.LogicalVolume._GetEmptyPvNames(pvlist, num_req)
291 23d95cff Bernardo Dal Seno
        epvs_set = compat.UniqueFrozenset(epvs)
292 23d95cff Bernardo Dal Seno
        if len(epvs) > 1:
293 23d95cff Bernardo Dal Seno
          self.assertEqual(len(epvs), len(epvs_set))
294 23d95cff Bernardo Dal Seno
        for pvi in pvlist:
295 23d95cff Bernardo Dal Seno
          if pvi.name in epvs_set:
296 23d95cff Bernardo Dal Seno
            self.assertEqual(pvi.size, pvi.free)
297 23d95cff Bernardo Dal Seno
          else:
298 23d95cff Bernardo Dal Seno
            # There should be no remaining empty PV when less than the
299 23d95cff Bernardo Dal Seno
            # requeste number of PVs has been returned
300 23d95cff Bernardo Dal Seno
            self.assertTrue(len(epvs) == num_req or pvi.free != pvi.size)
301 23d95cff Bernardo Dal Seno
302 23d95cff Bernardo Dal Seno
303 688b5752 Bernardo Dal Seno
class TestLogicalVolume(unittest.TestCase):
304 688b5752 Bernardo Dal Seno
  """Tests for bdev.LogicalVolume."""
305 688b5752 Bernardo Dal Seno
  def testParseLvInfoLine(self):
306 688b5752 Bernardo Dal Seno
    """Tests for LogicalVolume._ParseLvInfoLine."""
307 688b5752 Bernardo Dal Seno
    broken_lines = [
308 688b5752 Bernardo Dal Seno
      "  toomuch#-wi-ao#253#3#4096.00#2",
309 688b5752 Bernardo Dal Seno
      "  -wi-ao#253#3#4096.00",
310 688b5752 Bernardo Dal Seno
      "  -wi-a#253#3#4096.00#2",
311 688b5752 Bernardo Dal Seno
      "  -wi-ao#25.3#3#4096.00#2",
312 688b5752 Bernardo Dal Seno
      "  -wi-ao#twenty#3#4096.00#2",
313 688b5752 Bernardo Dal Seno
      "  -wi-ao#253#3.1#4096.00#2",
314 688b5752 Bernardo Dal Seno
      "  -wi-ao#253#three#4096.00#2",
315 688b5752 Bernardo Dal Seno
      "  -wi-ao#253#3#four#2",
316 688b5752 Bernardo Dal Seno
      "  -wi-ao#253#3#4096..00#2",
317 688b5752 Bernardo Dal Seno
      "  -wi-ao#253#3#4096.00#2.0",
318 688b5752 Bernardo Dal Seno
      "  -wi-ao#253#3#4096.00#two",
319 688b5752 Bernardo Dal Seno
      ]
320 688b5752 Bernardo Dal Seno
    for broken in broken_lines:
321 688b5752 Bernardo Dal Seno
      self.assertRaises(errors.BlockDeviceError,
322 688b5752 Bernardo Dal Seno
                        bdev.LogicalVolume._ParseLvInfoLine, broken, "#")
323 688b5752 Bernardo Dal Seno
324 688b5752 Bernardo Dal Seno
    true_out = [
325 688b5752 Bernardo Dal Seno
      ("-wi-ao", 253, 3, 4096.00, 2),
326 688b5752 Bernardo Dal Seno
      ("-wi-a-", 253, 7, 4096.00, 4),
327 688b5752 Bernardo Dal Seno
      ("-ri-a-", 253, 4, 4.00, 5),
328 688b5752 Bernardo Dal Seno
      ("-wc-ao", 15, 18, 4096.00, 32),
329 688b5752 Bernardo Dal Seno
      ]
330 688b5752 Bernardo Dal Seno
    for exp in true_out:
331 688b5752 Bernardo Dal Seno
      for sep in "#;|,":
332 688b5752 Bernardo Dal Seno
        lvs_line = sep.join(("  %s", "%d", "%d", "%.2f", "%d")) % exp
333 688b5752 Bernardo Dal Seno
        parsed = bdev.LogicalVolume._ParseLvInfoLine(lvs_line, sep)
334 688b5752 Bernardo Dal Seno
        self.assertEqual(parsed, exp)
335 688b5752 Bernardo Dal Seno
336 688b5752 Bernardo Dal Seno
  @staticmethod
337 688b5752 Bernardo Dal Seno
  def _FakeRunCmd(success, stdout):
338 688b5752 Bernardo Dal Seno
    if success:
339 688b5752 Bernardo Dal Seno
      exit_code = 0
340 688b5752 Bernardo Dal Seno
    else:
341 688b5752 Bernardo Dal Seno
      exit_code = 1
342 688b5752 Bernardo Dal Seno
    return lambda cmd: utils.RunResult(exit_code, None, stdout, "", cmd,
343 688b5752 Bernardo Dal Seno
                                       utils.process._TIMEOUT_NONE, 5)
344 688b5752 Bernardo Dal Seno
345 688b5752 Bernardo Dal Seno
  def testGetLvInfo(self):
346 688b5752 Bernardo Dal Seno
    """Tests for LogicalVolume._GetLvInfo."""
347 688b5752 Bernardo Dal Seno
    self.assertRaises(errors.BlockDeviceError, bdev.LogicalVolume._GetLvInfo,
348 688b5752 Bernardo Dal Seno
                      "fake_path",
349 688b5752 Bernardo Dal Seno
                      _run_cmd=self._FakeRunCmd(False, "Fake error msg"))
350 688b5752 Bernardo Dal Seno
    self.assertRaises(errors.BlockDeviceError, bdev.LogicalVolume._GetLvInfo,
351 688b5752 Bernardo Dal Seno
                      "fake_path", _run_cmd=self._FakeRunCmd(True, ""))
352 688b5752 Bernardo Dal Seno
    self.assertRaises(errors.BlockDeviceError, bdev.LogicalVolume._GetLvInfo,
353 688b5752 Bernardo Dal Seno
                      "fake_path", _run_cmd=self._FakeRunCmd(True, "BadStdOut"))
354 688b5752 Bernardo Dal Seno
    good_line = "  -wi-ao,253,3,4096.00,2"
355 688b5752 Bernardo Dal Seno
    fake_cmd = self._FakeRunCmd(True, good_line)
356 688b5752 Bernardo Dal Seno
    good_res = bdev.LogicalVolume._GetLvInfo("fake_path", _run_cmd=fake_cmd)
357 688b5752 Bernardo Dal Seno
    # Only the last line should be parsed and taken into account
358 688b5752 Bernardo Dal Seno
    for lines in [
359 688b5752 Bernardo Dal Seno
      [good_line] * 2,
360 688b5752 Bernardo Dal Seno
      [good_line] * 3,
361 688b5752 Bernardo Dal Seno
      ["bad line", good_line],
362 688b5752 Bernardo Dal Seno
      ]:
363 688b5752 Bernardo Dal Seno
      fake_cmd = self._FakeRunCmd(True, "\n".join(lines))
364 688b5752 Bernardo Dal Seno
      same_res = bdev.LogicalVolume._GetLvInfo("fake_path", fake_cmd)
365 688b5752 Bernardo Dal Seno
      self.assertEqual(same_res, good_res)
366 688b5752 Bernardo Dal Seno
367 688b5752 Bernardo Dal Seno
368 fbdac0d9 Michael Hanselmann
if __name__ == "__main__":
369 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()