Revision 555b6cb1 test/ganeti.cmdlib_unittest.py

b/test/ganeti.cmdlib_unittest.py
1241 1241

  
1242 1242

  
1243 1243
class _ConfigForDiskWipe:
1244
  def __init__(self, exp_node):
1245
    self._exp_node = exp_node
1246

  
1244 1247
  def SetDiskID(self, device, node):
1245 1248
    assert isinstance(device, objects.Disk)
1246
    assert node == "node1.example.com"
1249
    assert node == self._exp_node
1247 1250

  
1248 1251

  
1249 1252
class _RpcForDiskWipe:
1250
  def __init__(self, pause_cb, wipe_cb):
1253
  def __init__(self, exp_node, pause_cb, wipe_cb):
1254
    self._exp_node = exp_node
1251 1255
    self._pause_cb = pause_cb
1252 1256
    self._wipe_cb = wipe_cb
1253 1257

  
1254 1258
  def call_blockdev_pause_resume_sync(self, node, disks, pause):
1255
    assert node == "node1.example.com"
1259
    assert node == self._exp_node
1256 1260
    return rpc.RpcResult(data=self._pause_cb(disks, pause))
1257 1261

  
1258 1262
  def call_blockdev_wipe(self, node, bdev, offset, size):
1259
    assert node == "node1.example.com"
1263
    assert node == self._exp_node
1260 1264
    return rpc.RpcResult(data=self._wipe_cb(bdev, offset, size))
1261 1265

  
1262 1266

  
......
1273 1277
    return (True, [True] * len(disks))
1274 1278

  
1275 1279

  
1280
class _DiskWipeProgressTracker:
1281
  def __init__(self, start_offset):
1282
    self._start_offset = start_offset
1283
    self.progress = {}
1284

  
1285
  def __call__(self, (disk, _), offset, size):
1286
    assert isinstance(offset, (long, int))
1287
    assert isinstance(size, (long, int))
1288

  
1289
    max_chunk_size = (disk.size / 100.0 * constants.MIN_WIPE_CHUNK_PERCENT)
1290

  
1291
    assert offset >= self._start_offset
1292
    assert (offset + size) <= disk.size
1293

  
1294
    assert size > 0
1295
    assert size <= constants.MAX_WIPE_CHUNK
1296
    assert size <= max_chunk_size
1297

  
1298
    assert offset == self._start_offset or disk.logical_id in self.progress
1299

  
1300
    # Keep track of progress
1301
    cur_progress = self.progress.setdefault(disk.logical_id, self._start_offset)
1302

  
1303
    assert cur_progress == offset
1304

  
1305
    # Record progress
1306
    self.progress[disk.logical_id] += size
1307

  
1308
    return (True, None)
1309

  
1310

  
1276 1311
class TestWipeDisks(unittest.TestCase):
1312
  def _FailingPauseCb(self, (disks, _), pause):
1313
    self.assertEqual(len(disks), 3)
1314
    self.assertTrue(pause)
1315
    # Simulate an RPC error
1316
    return (False, "error")
1317

  
1277 1318
  def testPauseFailure(self):
1278
    def _FailPause((disks, _), pause):
1279
      self.assertEqual(len(disks), 3)
1280
      self.assertTrue(pause)
1281
      return (False, "error")
1319
    node_name = "node1372.example.com"
1282 1320

  
1283
    lu = _FakeLU(rpc=_RpcForDiskWipe(_FailPause, NotImplemented),
1284
                 cfg=_ConfigForDiskWipe())
1321
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, self._FailingPauseCb,
1322
                                     NotImplemented),
1323
                 cfg=_ConfigForDiskWipe(node_name))
1285 1324

  
1286 1325
    disks = [
1287 1326
      objects.Disk(dev_type=constants.LD_LV),
......
1290 1329
      ]
1291 1330

  
1292 1331
    instance = objects.Instance(name="inst21201",
1293
                                primary_node="node1.example.com",
1332
                                primary_node=node_name,
1294 1333
                                disk_template=constants.DT_PLAIN,
1295 1334
                                disks=disks)
1296 1335

  
1297 1336
    self.assertRaises(errors.OpExecError, cmdlib._WipeDisks, lu, instance)
1298 1337

  
1338
  def _FailingWipeCb(self, (disk, _), offset, size):
1339
    # This should only ever be called for the first disk
1340
    self.assertEqual(disk.logical_id, "disk0")
1341
    return (False, None)
1342

  
1299 1343
  def testFailingWipe(self):
1344
    node_name = "node13445.example.com"
1300 1345
    pt = _DiskPauseTracker()
1301 1346

  
1302
    def _WipeCb((disk, _), offset, size):
1303
      assert disk.logical_id == "disk0"
1304
      return (False, None)
1305

  
1306
    lu = _FakeLU(rpc=_RpcForDiskWipe(pt, _WipeCb),
1307
                 cfg=_ConfigForDiskWipe())
1347
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, pt, self._FailingWipeCb),
1348
                 cfg=_ConfigForDiskWipe(node_name))
1308 1349

  
1309 1350
    disks = [
1310 1351
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk0",
......
1315 1356
      ]
1316 1357

  
1317 1358
    instance = objects.Instance(name="inst562",
1318
                                primary_node="node1.example.com",
1359
                                primary_node=node_name,
1319 1360
                                disk_template=constants.DT_PLAIN,
1320 1361
                                disks=disks)
1321 1362

  
......
1326 1367
    else:
1327 1368
      self.fail("Did not raise exception")
1328 1369

  
1370
    # Check if all disks were paused and resumed
1329 1371
    self.assertEqual(pt.history, [
1330 1372
      ("disk0", 100 * 1024, True),
1331 1373
      ("disk1", 500 * 1024, True),
......
1335 1377
      ("disk2", 256, False),
1336 1378
      ])
1337 1379

  
1338
  def testNormalWipe(self):
1339
    for start_offset in [0, 280, 8895, 1563204]:
1340
      pt = _DiskPauseTracker()
1380
  def _PrepareWipeTest(self, start_offset, disks):
1381
    node_name = "node-with-offset%s.example.com" % start_offset
1382
    pauset = _DiskPauseTracker()
1383
    progresst = _DiskWipeProgressTracker(start_offset)
1341 1384

  
1342
      progress = {}
1385
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, pauset, progresst),
1386
                 cfg=_ConfigForDiskWipe(node_name))
1343 1387

  
1344
      def _WipeCb((disk, _), offset, size):
1345
        assert isinstance(offset, (long, int))
1346
        assert isinstance(size, (long, int))
1388
    instance = objects.Instance(name="inst3560",
1389
                                primary_node=node_name,
1390
                                disk_template=constants.DT_PLAIN,
1391
                                disks=disks)
1347 1392

  
1348
        max_chunk_size = (disk.size / 100.0 * constants.MIN_WIPE_CHUNK_PERCENT)
1393
    return (lu, instance, pauset, progresst)
1394

  
1395
  def testNormalWipe(self):
1396
    disks = [
1397
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk0", size=1024),
1398
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk1",
1399
                   size=500 * 1024),
1400
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk2", size=128),
1401
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk3",
1402
                   size=constants.MAX_WIPE_CHUNK),
1403
      ]
1349 1404

  
1350
        self.assertTrue(offset >= start_offset)
1351
        self.assertTrue((offset + size) <= disk.size)
1405
    (lu, instance, pauset, progresst) = self._PrepareWipeTest(0, disks)
1352 1406

  
1353
        self.assertTrue(size > 0)
1354
        self.assertTrue(size <= constants.MAX_WIPE_CHUNK)
1355
        self.assertTrue(size <= max_chunk_size)
1407
    cmdlib._WipeDisks(lu, instance)
1356 1408

  
1357
        self.assertTrue(offset == start_offset or disk.logical_id in progress)
1409
    self.assertEqual(pauset.history, [
1410
      ("disk0", 1024, True),
1411
      ("disk1", 500 * 1024, True),
1412
      ("disk2", 128, True),
1413
      ("disk3", constants.MAX_WIPE_CHUNK, True),
1414
      ("disk0", 1024, False),
1415
      ("disk1", 500 * 1024, False),
1416
      ("disk2", 128, False),
1417
      ("disk3", constants.MAX_WIPE_CHUNK, False),
1418
      ])
1358 1419

  
1359
        # Keep track of progress
1360
        cur_progress = progress.setdefault(disk.logical_id, start_offset)
1361
        self.assertEqual(cur_progress, offset)
1420
    # Ensure the complete disk has been wiped
1421
    self.assertEqual(progresst.progress,
1422
                     dict((i.logical_id, i.size) for i in disks))
1362 1423

  
1363
        progress[disk.logical_id] += size
1424
  def testWipeWithStartOffset(self):
1425
    for start_offset in [0, 280, 8895, 1563204]:
1426
      disks = [
1427
        objects.Disk(dev_type=constants.LD_LV, logical_id="disk0",
1428
                     size=128),
1429
        objects.Disk(dev_type=constants.LD_LV, logical_id="disk1",
1430
                     size=start_offset + (100 * 1024)),
1431
        ]
1364 1432

  
1365
        return (True, None)
1433
      (lu, instance, pauset, progresst) = \
1434
        self._PrepareWipeTest(start_offset, disks)
1366 1435

  
1367
      lu = _FakeLU(rpc=_RpcForDiskWipe(pt, _WipeCb),
1368
                   cfg=_ConfigForDiskWipe())
1436
      # Test start offset with only one disk
1437
      cmdlib._WipeDisks(lu, instance,
1438
                        disks=[(1, disks[1], start_offset)])
1369 1439

  
1370
      if start_offset > 0:
1371
        disks = [
1372
          objects.Disk(dev_type=constants.LD_LV, logical_id="disk0",
1373
                       size=128),
1374
          objects.Disk(dev_type=constants.LD_LV, logical_id="disk1",
1375
                       size=start_offset + (100 * 1024)),
1376
          ]
1377
      else:
1378
        disks = [
1379
          objects.Disk(dev_type=constants.LD_LV, logical_id="disk0", size=1024),
1380
          objects.Disk(dev_type=constants.LD_LV, logical_id="disk1",
1381
                       size=500 * 1024),
1382
          objects.Disk(dev_type=constants.LD_LV, logical_id="disk2", size=128),
1383
          objects.Disk(dev_type=constants.LD_LV, logical_id="disk3",
1384
                       size=constants.MAX_WIPE_CHUNK),
1385
          ]
1386

  
1387
      instance = objects.Instance(name="inst3560",
1388
                                  primary_node="node1.example.com",
1389
                                  disk_template=constants.DT_PLAIN,
1390
                                  disks=disks)
1391

  
1392
      if start_offset > 0:
1393
        # Test start offset with only one disk
1394
        cmdlib._WipeDisks(lu, instance,
1395
                          disks=[(1, disks[1], start_offset)])
1396
        self.assertEqual(pt.history, [
1397
          ("disk1", start_offset + (100 * 1024), True),
1398
          ("disk1", start_offset + (100 * 1024), False),
1399
          ])
1400
        self.assertEqual(progress, {
1401
          "disk1": disks[1].size,
1402
          })
1403
      else:
1404
        cmdlib._WipeDisks(lu, instance)
1405

  
1406
        self.assertEqual(pt.history, [
1407
          ("disk0", 1024, True),
1408
          ("disk1", 500 * 1024, True),
1409
          ("disk2", 128, True),
1410
          ("disk3", constants.MAX_WIPE_CHUNK, True),
1411
          ("disk0", 1024, False),
1412
          ("disk1", 500 * 1024, False),
1413
          ("disk2", 128, False),
1414
          ("disk3", constants.MAX_WIPE_CHUNK, False),
1415
          ])
1416

  
1417
        # Ensure the complete disk has been wiped
1418
        self.assertEqual(progress, dict((i.logical_id, i.size) for i in disks))
1440
      # Only the second disk may have been paused and wiped
1441
      self.assertEqual(pauset.history, [
1442
        ("disk1", start_offset + (100 * 1024), True),
1443
        ("disk1", start_offset + (100 * 1024), False),
1444
        ])
1445
      self.assertEqual(progresst.progress, {
1446
        "disk1": disks[1].size,
1447
        })
1419 1448

  
1420 1449

  
1421 1450
class TestDiskSizeInBytesToMebibytes(unittest.TestCase):

Also available in: Unified diff