Revision 873878b9 test/py/ganeti.block.bdev_unittest.py

b/test/py/ganeti.block.bdev_unittest.py
32 32
from ganeti import objects
33 33
from ganeti import utils
34 34
from ganeti.block import bdev
35
from ganeti.block import drbd
36
from ganeti.block import drbd_info
37
from ganeti.block import drbd_cmdgen
38 35

  
39 36
import testutils
40 37

  
41 38

  
42
class TestDRBD8(testutils.GanetiTestCase):
43
  def testGetVersion(self):
44
    data = [
45
      ["version: 8.0.12 (api:76/proto:86-91)"],
46
      ["version: 8.2.7 (api:88/proto:0-100)"],
47
      ["version: 8.3.7.49 (api:188/proto:13-191)"],
48
    ]
49
    result = [
50
      {
51
      "k_major": 8,
52
      "k_minor": 0,
53
      "k_point": 12,
54
      "api": 76,
55
      "proto": 86,
56
      "proto2": "91",
57
      },
58
      {
59
      "k_major": 8,
60
      "k_minor": 2,
61
      "k_point": 7,
62
      "api": 88,
63
      "proto": 0,
64
      "proto2": "100",
65
      },
66
      {
67
      "k_major": 8,
68
      "k_minor": 3,
69
      "k_point": 7,
70
      "api": 188,
71
      "proto": 13,
72
      "proto2": "191",
73
      }
74
    ]
75
    for d,r in zip(data, result):
76
      info = drbd.DRBD8Info.CreateFromLines(d)
77
      self.assertEqual(info.GetVersion(), r)
78

  
79

  
80
class TestDRBD8Runner(testutils.GanetiTestCase):
81
  """Testing case for drbd.DRBD8"""
82

  
83
  @staticmethod
84
  def _has_disk(data, dname, mname):
85
    """Check local disk corectness"""
86
    retval = (
87
      "local_dev" in data and
88
      data["local_dev"] == dname and
89
      "meta_dev" in data and
90
      data["meta_dev"] == mname and
91
      "meta_index" in data and
92
      data["meta_index"] == 0
93
      )
94
    return retval
95

  
96
  @staticmethod
97
  def _has_net(data, local, remote):
98
    """Check network connection parameters"""
99
    retval = (
100
      "local_addr" in data and
101
      data["local_addr"] == local and
102
      "remote_addr" in data and
103
      data["remote_addr"] == remote
104
      )
105
    return retval
106

  
107
  def testParser83Creation(self):
108
    """Test drbdsetup show parser creation"""
109
    drbd_info.DRBD83ShowInfo._GetShowParser()
110

  
111
  def testParser84Creation(self):
112
    """Test drbdsetup show parser creation"""
113
    drbd_info.DRBD84ShowInfo._GetShowParser()
114

  
115
  def testParser80(self):
116
    """Test drbdsetup show parser for disk and network version 8.0"""
117
    data = testutils.ReadTestData("bdev-drbd-8.0.txt")
118
    result = drbd_info.DRBD83ShowInfo.GetDevInfo(data)
119
    self.failUnless(self._has_disk(result, "/dev/xenvg/test.data",
120
                                   "/dev/xenvg/test.meta"),
121
                    "Wrong local disk info")
122
    self.failUnless(self._has_net(result, ("192.0.2.1", 11000),
123
                                  ("192.0.2.2", 11000)),
124
                    "Wrong network info (8.0.x)")
125

  
126
  def testParser83(self):
127
    """Test drbdsetup show parser for disk and network version 8.3"""
128
    data = testutils.ReadTestData("bdev-drbd-8.3.txt")
129
    result = drbd_info.DRBD83ShowInfo.GetDevInfo(data)
130
    self.failUnless(self._has_disk(result, "/dev/xenvg/test.data",
131
                                   "/dev/xenvg/test.meta"),
132
                    "Wrong local disk info")
133
    self.failUnless(self._has_net(result, ("192.0.2.1", 11000),
134
                                  ("192.0.2.2", 11000)),
135
                    "Wrong network info (8.3.x)")
136

  
137
  def testParser84(self):
138
    """Test drbdsetup show parser for disk and network version 8.4"""
139
    data = testutils.ReadTestData("bdev-drbd-8.4.txt")
140
    result = drbd_info.DRBD84ShowInfo.GetDevInfo(data)
141
    self.failUnless(self._has_disk(result, "/dev/xenvg/test.data",
142
                                   "/dev/xenvg/test.meta"),
143
                    "Wrong local disk info")
144
    self.failUnless(self._has_net(result, ("192.0.2.1", 11000),
145
                                  ("192.0.2.2", 11000)),
146
                    "Wrong network info (8.4.x)")
147

  
148
  def testParserNetIP4(self):
149
    """Test drbdsetup show parser for IPv4 network"""
150
    data = testutils.ReadTestData("bdev-drbd-net-ip4.txt")
151
    result = drbd_info.DRBD83ShowInfo.GetDevInfo(data)
152
    self.failUnless(("local_dev" not in result and
153
                     "meta_dev" not in result and
154
                     "meta_index" not in result),
155
                    "Should not find local disk info")
156
    self.failUnless(self._has_net(result, ("192.0.2.1", 11002),
157
                                  ("192.0.2.2", 11002)),
158
                    "Wrong network info (IPv4)")
159

  
160
  def testParserNetIP6(self):
161
    """Test drbdsetup show parser for IPv6 network"""
162
    data = testutils.ReadTestData("bdev-drbd-net-ip6.txt")
163
    result = drbd_info.DRBD83ShowInfo.GetDevInfo(data)
164
    self.failUnless(("local_dev" not in result and
165
                     "meta_dev" not in result and
166
                     "meta_index" not in result),
167
                    "Should not find local disk info")
168
    self.failUnless(self._has_net(result, ("2001:db8:65::1", 11048),
169
                                  ("2001:db8:66::1", 11048)),
170
                    "Wrong network info (IPv6)")
171

  
172
  def testParserDisk(self):
173
    """Test drbdsetup show parser for disk"""
174
    data = testutils.ReadTestData("bdev-drbd-disk.txt")
175
    result = drbd_info.DRBD83ShowInfo.GetDevInfo(data)
176
    self.failUnless(self._has_disk(result, "/dev/xenvg/test.data",
177
                                   "/dev/xenvg/test.meta"),
178
                    "Wrong local disk info")
179
    self.failUnless(("local_addr" not in result and
180
                     "remote_addr" not in result),
181
                    "Should not find network info")
182

  
183
  def testBarriersOptions(self):
184
    """Test class method that generates drbdsetup options for disk barriers"""
185
    # Tests that should fail because of wrong version/options combinations
186
    should_fail = [
187
      (8, 0, 12, "bfd", True),
188
      (8, 0, 12, "fd", False),
189
      (8, 0, 12, "b", True),
190
      (8, 2, 7, "bfd", True),
191
      (8, 2, 7, "b", True)
192
    ]
193

  
194
    for vmaj, vmin, vrel, opts, meta in should_fail:
195
      self.assertRaises(errors.BlockDeviceError,
196
                        drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs,
197
                        vmaj, vmin, vrel, opts, meta)
198

  
199
    # get the valid options from the frozenset(frozenset()) in constants.
200
    valid_options = [list(x)[0] for x in constants.DRBD_VALID_BARRIER_OPT]
201

  
202
    # Versions that do not support anything
203
    for vmaj, vmin, vrel in ((8, 0, 0), (8, 0, 11), (8, 2, 6)):
204
      for opts in valid_options:
205
        self.assertRaises(
206
          errors.BlockDeviceError,
207
          drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs,
208
          vmaj, vmin, vrel, opts, True)
209

  
210
    # Versions with partial support (testing only options that are supported)
211
    tests = [
212
      (8, 0, 12, "n", False, []),
213
      (8, 0, 12, "n", True, ["--no-md-flushes"]),
214
      (8, 2, 7, "n", False, []),
215
      (8, 2, 7, "fd", False, ["--no-disk-flushes", "--no-disk-drain"]),
216
      (8, 0, 12, "n", True, ["--no-md-flushes"]),
217
      ]
218

  
219
    # Versions that support everything
220
    for vmaj, vmin, vrel in ((8, 3, 0), (8, 3, 12)):
221
      tests.append((vmaj, vmin, vrel, "bfd", True,
222
                    ["--no-disk-barrier", "--no-disk-drain",
223
                     "--no-disk-flushes", "--no-md-flushes"]))
224
      tests.append((vmaj, vmin, vrel, "n", False, []))
225
      tests.append((vmaj, vmin, vrel, "b", True,
226
                    ["--no-disk-barrier", "--no-md-flushes"]))
227
      tests.append((vmaj, vmin, vrel, "fd", False,
228
                    ["--no-disk-flushes", "--no-disk-drain"]))
229
      tests.append((vmaj, vmin, vrel, "n", True, ["--no-md-flushes"]))
230

  
231
    # Test execution
232
    for test in tests:
233
      vmaj, vmin, vrel, disabled_barriers, disable_meta_flush, expected = test
234
      args = \
235
        drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs(
236
          vmaj, vmin, vrel,
237
          disabled_barriers,
238
          disable_meta_flush)
239
      self.failUnless(set(args) == set(expected),
240
                      "For test %s, got wrong results %s" % (test, args))
241

  
242
    # Unsupported or invalid versions
243
    for vmaj, vmin, vrel in ((0, 7, 25), (9, 0, 0), (7, 0, 0), (8, 4, 0)):
244
      self.assertRaises(errors.BlockDeviceError,
245
                        drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs,
246
                        vmaj, vmin, vrel, "n", True)
247

  
248
    # Invalid options
249
    for option in ("", "c", "whatever", "nbdfc", "nf"):
250
      self.assertRaises(errors.BlockDeviceError,
251
                        drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs,
252
                        8, 3, 11, option, True)
253

  
254

  
255
class TestDRBD8Status(testutils.GanetiTestCase):
256
  """Testing case for DRBD8 /proc status"""
257

  
258
  def setUp(self):
259
    """Read in txt data"""
260
    testutils.GanetiTestCase.setUp(self)
261
    proc_data = testutils.TestDataFilename("proc_drbd8.txt")
262
    proc80e_data = testutils.TestDataFilename("proc_drbd80-emptyline.txt")
263
    proc83_data = testutils.TestDataFilename("proc_drbd83.txt")
264
    proc83_sync_data = testutils.TestDataFilename("proc_drbd83_sync.txt")
265
    proc83_sync_krnl_data = \
266
      testutils.TestDataFilename("proc_drbd83_sync_krnl2.6.39.txt")
267
    proc84_data = testutils.TestDataFilename("proc_drbd84.txt")
268
    proc84_sync_data = testutils.TestDataFilename("proc_drbd84_sync.txt")
269

  
270
    self.proc80ev_data = \
271
      testutils.TestDataFilename("proc_drbd80-emptyversion.txt")
272

  
273
    self.drbd_info = drbd.DRBD8Info.CreateFromFile(filename=proc_data)
274
    self.drbd_info80e = drbd.DRBD8Info.CreateFromFile(filename=proc80e_data)
275
    self.drbd_info83 = drbd.DRBD8Info.CreateFromFile(filename=proc83_data)
276
    self.drbd_info83_sync = \
277
      drbd.DRBD8Info.CreateFromFile(filename=proc83_sync_data)
278
    self.drbd_info83_sync_krnl = \
279
      drbd.DRBD8Info.CreateFromFile(filename=proc83_sync_krnl_data)
280
    self.drbd_info84 = drbd.DRBD8Info.CreateFromFile(filename=proc84_data)
281
    self.drbd_info84_sync = \
282
      drbd.DRBD8Info.CreateFromFile(filename=proc84_sync_data)
283

  
284
  def testIOErrors(self):
285
    """Test handling of errors while reading the proc file."""
286
    temp_file = self._CreateTempFile()
287
    os.unlink(temp_file)
288
    self.failUnlessRaises(errors.BlockDeviceError,
289
                          drbd.DRBD8Info.CreateFromFile, filename=temp_file)
290

  
291
  def testHelper(self):
292
    """Test reading usermode_helper in /sys."""
293
    sys_drbd_helper = testutils.TestDataFilename("sys_drbd_usermode_helper.txt")
294
    drbd_helper = drbd.DRBD8.GetUsermodeHelper(filename=sys_drbd_helper)
295
    self.failUnlessEqual(drbd_helper, "/bin/true")
296

  
297
  def testHelperIOErrors(self):
298
    """Test handling of errors while reading usermode_helper in /sys."""
299
    temp_file = self._CreateTempFile()
300
    os.unlink(temp_file)
301
    self.failUnlessRaises(errors.BlockDeviceError,
302
                          drbd.DRBD8.GetUsermodeHelper, filename=temp_file)
303

  
304
  def testMinorNotFound(self):
305
    """Test not-found-minor in /proc"""
306
    self.failUnless(not self.drbd_info.HasMinorStatus(9))
307
    self.failUnless(not self.drbd_info83.HasMinorStatus(9))
308
    self.failUnless(not self.drbd_info80e.HasMinorStatus(3))
309

  
310
  def testLineNotMatch(self):
311
    """Test wrong line passed to drbd_info.DRBD8Status"""
312
    self.assertRaises(errors.BlockDeviceError, drbd_info.DRBD8Status, "foo")
313

  
314
  def testMinor0(self):
315
    """Test connected, primary device"""
316
    for info in [self.drbd_info, self.drbd_info83, self.drbd_info84]:
317
      stats = info.GetMinorStatus(0)
318
      self.failUnless(stats.is_in_use)
319
      self.failUnless(stats.is_connected and stats.is_primary and
320
                      stats.peer_secondary and stats.is_disk_uptodate)
321

  
322
  def testMinor1(self):
323
    """Test connected, secondary device"""
324
    for info in [self.drbd_info, self.drbd_info83, self.drbd_info84]:
325
      stats = info.GetMinorStatus(1)
326
      self.failUnless(stats.is_in_use)
327
      self.failUnless(stats.is_connected and stats.is_secondary and
328
                      stats.peer_primary and stats.is_disk_uptodate)
329

  
330
  def testMinor2(self):
331
    """Test unconfigured device"""
332
    for info in [self.drbd_info, self.drbd_info83,
333
                 self.drbd_info80e, self.drbd_info84]:
334
      stats = info.GetMinorStatus(2)
335
      self.failIf(stats.is_in_use)
336

  
337
  def testMinor4(self):
338
    """Test WFconn device"""
339
    for info in [self.drbd_info, self.drbd_info83, self.drbd_info84]:
340
      stats = info.GetMinorStatus(4)
341
      self.failUnless(stats.is_in_use)
342
      self.failUnless(stats.is_wfconn and stats.is_primary and
343
                      stats.rrole == "Unknown" and
344
                      stats.is_disk_uptodate)
345

  
346
  def testMinor6(self):
347
    """Test diskless device"""
348
    for info in [self.drbd_info, self.drbd_info83, self.drbd_info84]:
349
      stats = info.GetMinorStatus(6)
350
      self.failUnless(stats.is_in_use)
351
      self.failUnless(stats.is_connected and stats.is_secondary and
352
                      stats.peer_primary and stats.is_diskless)
353

  
354
  def testMinor8(self):
355
    """Test standalone device"""
356
    for info in [self.drbd_info, self.drbd_info83, self.drbd_info84]:
357
      stats = info.GetMinorStatus(8)
358
      self.failUnless(stats.is_in_use)
359
      self.failUnless(stats.is_standalone and
360
                      stats.rrole == "Unknown" and
361
                      stats.is_disk_uptodate)
362

  
363
  def testDRBD83SyncFine(self):
364
    stats = self.drbd_info83_sync.GetMinorStatus(3)
365
    self.failUnless(stats.is_in_resync)
366
    self.failUnless(stats.sync_percent is not None)
367

  
368
  def testDRBD83SyncBroken(self):
369
    stats = self.drbd_info83_sync_krnl.GetMinorStatus(3)
370
    self.failUnless(stats.is_in_resync)
371
    self.failUnless(stats.sync_percent is not None)
372

  
373
  def testDRBD84Sync(self):
374
    stats = self.drbd_info84_sync.GetMinorStatus(5)
375
    self.failUnless(stats.is_in_resync)
376
    self.failUnless(stats.sync_percent is not None)
377

  
378
  def testDRBDEmptyVersion(self):
379
    self.assertRaises(errors.BlockDeviceError,
380
                      drbd.DRBD8Info.CreateFromFile,
381
                      filename=self.proc80ev_data)
382

  
383

  
384 39
class TestRADOSBlockDevice(testutils.GanetiTestCase):
385 40
  def setUp(self):
386 41
    """Set up input data"""

Also available in: Unified diff