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