Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.storage.bdev_unittest.py @ cd3b4ff4

History | View | Annotate | Download (11.4 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 23d95cff Bernardo Dal Seno
class TestExclusiveStoragePvs(unittest.TestCase):
108 23d95cff Bernardo Dal Seno
  """Test cases for functions dealing with LVM PV and exclusive storage"""
109 23d95cff Bernardo Dal Seno
  # Allowance for rounding
110 23d95cff Bernardo Dal Seno
  _EPS = 1e-4
111 23d95cff Bernardo Dal Seno
  _MARGIN = constants.PART_MARGIN + constants.PART_RESERVED + _EPS
112 23d95cff Bernardo Dal Seno
113 23d95cff Bernardo Dal Seno
  @staticmethod
114 23d95cff Bernardo Dal Seno
  def _GenerateRandomPvInfo(rnd, name, vg):
115 23d95cff Bernardo Dal Seno
    # Granularity is .01 MiB
116 23d95cff Bernardo Dal Seno
    size = rnd.randint(1024 * 100, 10 * 1024 * 1024 * 100)
117 23d95cff Bernardo Dal Seno
    if rnd.choice([False, True]):
118 23d95cff Bernardo Dal Seno
      free = float(rnd.randint(0, size)) / 100.0
119 23d95cff Bernardo Dal Seno
    else:
120 23d95cff Bernardo Dal Seno
      free = float(size) / 100.0
121 23d95cff Bernardo Dal Seno
    size = float(size) / 100.0
122 23d95cff Bernardo Dal Seno
    attr = "a-"
123 23d95cff Bernardo Dal Seno
    return objects.LvmPvInfo(name=name, vg_name=vg, size=size, free=free,
124 23d95cff Bernardo Dal Seno
                             attributes=attr)
125 23d95cff Bernardo Dal Seno
126 23d95cff Bernardo Dal Seno
  def testGetStdPvSize(self):
127 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._GetStdPvSize()"""
128 23d95cff Bernardo Dal Seno
    rnd = random.Random(9517)
129 23d95cff Bernardo Dal Seno
    for _ in range(0, 50):
130 23d95cff Bernardo Dal Seno
      # Identical volumes
131 23d95cff Bernardo Dal Seno
      pvi = self._GenerateRandomPvInfo(rnd, "disk", "myvg")
132 23d95cff Bernardo Dal Seno
      onesize = bdev.LogicalVolume._GetStdPvSize([pvi])
133 23d95cff Bernardo Dal Seno
      self.assertTrue(onesize <= pvi.size)
134 23d95cff Bernardo Dal Seno
      self.assertTrue(onesize > pvi.size * (1 - self._MARGIN))
135 23d95cff Bernardo Dal Seno
      for length in range(2, 10):
136 23d95cff Bernardo Dal Seno
        n_size = bdev.LogicalVolume._GetStdPvSize([pvi] * length)
137 23d95cff Bernardo Dal Seno
        self.assertEqual(onesize, n_size)
138 23d95cff Bernardo Dal Seno
139 23d95cff Bernardo Dal Seno
      # Mixed volumes
140 23d95cff Bernardo Dal Seno
      for length in range(1, 10):
141 23d95cff Bernardo Dal Seno
        pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")
142 23d95cff Bernardo Dal Seno
                  for _ in range(0, length)]
143 23d95cff Bernardo Dal Seno
        std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
144 23d95cff Bernardo Dal Seno
        self.assertTrue(compat.all(std_size <= pvi.size for pvi in pvlist))
145 23d95cff Bernardo Dal Seno
        self.assertTrue(compat.any(std_size > pvi.size * (1 - self._MARGIN)
146 23d95cff Bernardo Dal Seno
                                   for pvi in pvlist))
147 23d95cff Bernardo Dal Seno
        pvlist.append(pvlist[0])
148 23d95cff Bernardo Dal Seno
        p1_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
149 23d95cff Bernardo Dal Seno
        self.assertEqual(std_size, p1_size)
150 23d95cff Bernardo Dal Seno
151 23d95cff Bernardo Dal Seno
  def testComputeNumPvs(self):
152 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._ComputeNumPvs()"""
153 23d95cff Bernardo Dal Seno
    rnd = random.Random(8067)
154 23d95cff Bernardo Dal Seno
    for _ in range(0, 1000):
155 23d95cff Bernardo Dal Seno
      pvlist = [self._GenerateRandomPvInfo(rnd, "disk", "myvg")]
156 23d95cff Bernardo Dal Seno
      lv_size = float(rnd.randint(10 * 100, 1024 * 1024 * 100)) / 100.0
157 23d95cff Bernardo Dal Seno
      num_pv = bdev.LogicalVolume._ComputeNumPvs(lv_size, pvlist)
158 23d95cff Bernardo Dal Seno
      std_size = bdev.LogicalVolume._GetStdPvSize(pvlist)
159 23d95cff Bernardo Dal Seno
      self.assertTrue(num_pv >= 1)
160 23d95cff Bernardo Dal Seno
      self.assertTrue(num_pv * std_size >= lv_size)
161 23d95cff Bernardo Dal Seno
      self.assertTrue((num_pv - 1) * std_size < lv_size * (1 + self._EPS))
162 23d95cff Bernardo Dal Seno
163 23d95cff Bernardo Dal Seno
  def testGetEmptyPvNames(self):
164 23d95cff Bernardo Dal Seno
    """Test cases for bdev.LogicalVolume._GetEmptyPvNames()"""
165 23d95cff Bernardo Dal Seno
    rnd = random.Random(21126)
166 23d95cff Bernardo Dal Seno
    for _ in range(0, 100):
167 23d95cff Bernardo Dal Seno
      num_pvs = rnd.randint(1, 20)
168 23d95cff Bernardo Dal Seno
      pvlist = [self._GenerateRandomPvInfo(rnd, "disk%d" % n, "myvg")
169 23d95cff Bernardo Dal Seno
                for n in range(0, num_pvs)]
170 23d95cff Bernardo Dal Seno
      for num_req in range(1, num_pvs + 2):
171 23d95cff Bernardo Dal Seno
        epvs = bdev.LogicalVolume._GetEmptyPvNames(pvlist, num_req)
172 23d95cff Bernardo Dal Seno
        epvs_set = compat.UniqueFrozenset(epvs)
173 23d95cff Bernardo Dal Seno
        if len(epvs) > 1:
174 23d95cff Bernardo Dal Seno
          self.assertEqual(len(epvs), len(epvs_set))
175 23d95cff Bernardo Dal Seno
        for pvi in pvlist:
176 23d95cff Bernardo Dal Seno
          if pvi.name in epvs_set:
177 23d95cff Bernardo Dal Seno
            self.assertEqual(pvi.size, pvi.free)
178 23d95cff Bernardo Dal Seno
          else:
179 23d95cff Bernardo Dal Seno
            # There should be no remaining empty PV when less than the
180 23d95cff Bernardo Dal Seno
            # requeste number of PVs has been returned
181 23d95cff Bernardo Dal Seno
            self.assertTrue(len(epvs) == num_req or pvi.free != pvi.size)
182 23d95cff Bernardo Dal Seno
183 23d95cff Bernardo Dal Seno
184 688b5752 Bernardo Dal Seno
class TestLogicalVolume(unittest.TestCase):
185 688b5752 Bernardo Dal Seno
  """Tests for bdev.LogicalVolume."""
186 688b5752 Bernardo Dal Seno
  def testParseLvInfoLine(self):
187 688b5752 Bernardo Dal Seno
    """Tests for LogicalVolume._ParseLvInfoLine."""
188 688b5752 Bernardo Dal Seno
    broken_lines = [
189 b5d48e87 Bernardo Dal Seno
      "  toomuch#-wi-ao#253#3#4096.00#2#/dev/abc(20)",
190 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#253#3#4096.00#/dev/abc(20)",
191 b5d48e87 Bernardo Dal Seno
      "  -wi-a#253#3#4096.00#2#/dev/abc(20)",
192 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#25.3#3#4096.00#2#/dev/abc(20)",
193 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#twenty#3#4096.00#2#/dev/abc(20)",
194 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#253#3.1#4096.00#2#/dev/abc(20)",
195 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#253#three#4096.00#2#/dev/abc(20)",
196 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#253#3#four#2#/dev/abc(20)",
197 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#253#3#4096..00#2#/dev/abc(20)",
198 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#253#3#4096.00#2.0#/dev/abc(20)",
199 b5d48e87 Bernardo Dal Seno
      "  -wi-ao#253#3#4096.00#two#/dev/abc(20)",
200 688b5752 Bernardo Dal Seno
      ]
201 688b5752 Bernardo Dal Seno
    for broken in broken_lines:
202 688b5752 Bernardo Dal Seno
      self.assertRaises(errors.BlockDeviceError,
203 688b5752 Bernardo Dal Seno
                        bdev.LogicalVolume._ParseLvInfoLine, broken, "#")
204 688b5752 Bernardo Dal Seno
205 b5d48e87 Bernardo Dal Seno
    # Examples of good lines from "lvs":
206 b5d48e87 Bernardo Dal Seno
    #  -wi-ao|253|3|4096.00|2|/dev/sdb(144),/dev/sdc(0)
207 b5d48e87 Bernardo Dal Seno
    #  -wi-a-|253|4|4096.00|1|/dev/sdb(208)
208 688b5752 Bernardo Dal Seno
    true_out = [
209 b5d48e87 Bernardo Dal Seno
      ("-wi-ao", 253, 3, 4096.00, 2, ["/dev/abc"]),
210 b5d48e87 Bernardo Dal Seno
      ("-wi-a-", 253, 7, 4096.00, 4, ["/dev/abc"]),
211 b5d48e87 Bernardo Dal Seno
      ("-ri-a-", 253, 4, 4.00, 5, ["/dev/abc", "/dev/def"]),
212 b5d48e87 Bernardo Dal Seno
      ("-wc-ao", 15, 18, 4096.00, 32, ["/dev/abc", "/dev/def", "/dev/ghi0"]),
213 688b5752 Bernardo Dal Seno
      ]
214 688b5752 Bernardo Dal Seno
    for exp in true_out:
215 b5d48e87 Bernardo Dal Seno
      for sep in "#;|":
216 b5d48e87 Bernardo Dal Seno
        pvs = ",".join("%s(%s)" % (d, i * 12) for (i, d) in enumerate(exp[-1]))
217 b5d48e87 Bernardo Dal Seno
        lvs_line = (sep.join(("  %s", "%d", "%d", "%.2f", "%d", "%s")) %
218 b5d48e87 Bernardo Dal Seno
                    (exp[0:-1] + (pvs,)))
219 688b5752 Bernardo Dal Seno
        parsed = bdev.LogicalVolume._ParseLvInfoLine(lvs_line, sep)
220 688b5752 Bernardo Dal Seno
        self.assertEqual(parsed, exp)
221 688b5752 Bernardo Dal Seno
222 688b5752 Bernardo Dal Seno
  @staticmethod
223 688b5752 Bernardo Dal Seno
  def _FakeRunCmd(success, stdout):
224 688b5752 Bernardo Dal Seno
    if success:
225 688b5752 Bernardo Dal Seno
      exit_code = 0
226 688b5752 Bernardo Dal Seno
    else:
227 688b5752 Bernardo Dal Seno
      exit_code = 1
228 688b5752 Bernardo Dal Seno
    return lambda cmd: utils.RunResult(exit_code, None, stdout, "", cmd,
229 688b5752 Bernardo Dal Seno
                                       utils.process._TIMEOUT_NONE, 5)
230 688b5752 Bernardo Dal Seno
231 688b5752 Bernardo Dal Seno
  def testGetLvInfo(self):
232 688b5752 Bernardo Dal Seno
    """Tests for LogicalVolume._GetLvInfo."""
233 688b5752 Bernardo Dal Seno
    self.assertRaises(errors.BlockDeviceError, bdev.LogicalVolume._GetLvInfo,
234 688b5752 Bernardo Dal Seno
                      "fake_path",
235 688b5752 Bernardo Dal Seno
                      _run_cmd=self._FakeRunCmd(False, "Fake error msg"))
236 688b5752 Bernardo Dal Seno
    self.assertRaises(errors.BlockDeviceError, bdev.LogicalVolume._GetLvInfo,
237 688b5752 Bernardo Dal Seno
                      "fake_path", _run_cmd=self._FakeRunCmd(True, ""))
238 688b5752 Bernardo Dal Seno
    self.assertRaises(errors.BlockDeviceError, bdev.LogicalVolume._GetLvInfo,
239 688b5752 Bernardo Dal Seno
                      "fake_path", _run_cmd=self._FakeRunCmd(True, "BadStdOut"))
240 b5d48e87 Bernardo Dal Seno
    good_line = "  -wi-ao|253|3|4096.00|2|/dev/abc(20)"
241 688b5752 Bernardo Dal Seno
    fake_cmd = self._FakeRunCmd(True, good_line)
242 688b5752 Bernardo Dal Seno
    good_res = bdev.LogicalVolume._GetLvInfo("fake_path", _run_cmd=fake_cmd)
243 b5d48e87 Bernardo Dal Seno
    # If the same line is repeated, the result should be the same
244 688b5752 Bernardo Dal Seno
    for lines in [
245 688b5752 Bernardo Dal Seno
      [good_line] * 2,
246 688b5752 Bernardo Dal Seno
      [good_line] * 3,
247 688b5752 Bernardo Dal Seno
      ]:
248 688b5752 Bernardo Dal Seno
      fake_cmd = self._FakeRunCmd(True, "\n".join(lines))
249 688b5752 Bernardo Dal Seno
      same_res = bdev.LogicalVolume._GetLvInfo("fake_path", fake_cmd)
250 688b5752 Bernardo Dal Seno
      self.assertEqual(same_res, good_res)
251 688b5752 Bernardo Dal Seno
252 b5d48e87 Bernardo Dal Seno
    # Complex multi-line examples
253 b5d48e87 Bernardo Dal Seno
    one_line = "  -wi-ao|253|3|4096.00|2|/dev/sda(20),/dev/sdb(50),/dev/sdc(0)"
254 b5d48e87 Bernardo Dal Seno
    fake_cmd = self._FakeRunCmd(True, one_line)
255 b5d48e87 Bernardo Dal Seno
    one_res = bdev.LogicalVolume._GetLvInfo("fake_path", _run_cmd=fake_cmd)
256 b5d48e87 Bernardo Dal Seno
    # These should give the same results
257 b5d48e87 Bernardo Dal Seno
    for multi_lines in [
258 b5d48e87 Bernardo Dal Seno
      ("  -wi-ao|253|3|4096.00|2|/dev/sda(30),/dev/sdb(50)\n"
259 b5d48e87 Bernardo Dal Seno
       "  -wi-ao|253|3|4096.00|2|/dev/sdb(200),/dev/sdc(300)"),
260 b5d48e87 Bernardo Dal Seno
      ("  -wi-ao|253|3|4096.00|2|/dev/sda(0)\n"
261 b5d48e87 Bernardo Dal Seno
       "  -wi-ao|253|3|4096.00|2|/dev/sdb(20)\n"
262 b5d48e87 Bernardo Dal Seno
       "  -wi-ao|253|3|4096.00|2|/dev/sdc(30)"),
263 b5d48e87 Bernardo Dal Seno
      ("  -wi-ao|253|3|4096.00|2|/dev/sda(20)\n"
264 b5d48e87 Bernardo Dal Seno
       "  -wi-ao|253|3|4096.00|2|/dev/sdb(50),/dev/sdc(0)"),
265 b5d48e87 Bernardo Dal Seno
      ]:
266 b5d48e87 Bernardo Dal Seno
      fake_cmd = self._FakeRunCmd(True, multi_lines)
267 b5d48e87 Bernardo Dal Seno
      multi_res = bdev.LogicalVolume._GetLvInfo("fake_path", _run_cmd=fake_cmd)
268 b5d48e87 Bernardo Dal Seno
      self.assertEqual(multi_res, one_res)
269 b5d48e87 Bernardo Dal Seno
270 688b5752 Bernardo Dal Seno
271 fbdac0d9 Michael Hanselmann
if __name__ == "__main__":
272 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()