|
1 | 1 | import os
|
2 | 2 | import unittest
|
3 | 3 | from datetime import datetime, timedelta
|
4 |
| -from .helpers.ptrack_helpers import ProbackupTest |
| 4 | +from .helpers.ptrack_helpers import ProbackupTest, ProbackupException |
5 | 5 | from time import sleep
|
6 | 6 |
|
7 | 7 |
|
@@ -1264,16 +1264,156 @@ def test_window_error_backups(self):
|
1264 | 1264 | self.set_archiving(backup_dir, 'node', node)
|
1265 | 1265 | node.slow_start()
|
1266 | 1266 |
|
1267 |
| - node.pgbench_init(scale=3) |
1268 |
| - |
1269 | 1267 | # Take FULL BACKUPs
|
1270 | 1268 | backup_id_a1 = self.backup_node(backup_dir, 'node', node)
|
1271 |
| - page_id_a2 = self.backup_node( |
| 1269 | + gdb = self.backup_node( |
| 1270 | + backup_dir, 'node', node, backup_type='page', gdb=True) |
| 1271 | + |
| 1272 | + page_id_a3 = self.backup_node( |
1272 | 1273 | backup_dir, 'node', node, backup_type='page')
|
1273 | 1274 |
|
1274 | 1275 | # Change FULLb backup status to ERROR
|
1275 | 1276 | self.change_backup_status(backup_dir, 'node', backup_id_b, 'ERROR')
|
1276 | 1277 |
|
| 1278 | + # Clean after yourself |
| 1279 | + self.del_test_dir(module_name, fname) |
| 1280 | + |
| 1281 | + # @unittest.skip("skip") |
| 1282 | + def test_window_error_backups_1(self): |
| 1283 | + """ |
| 1284 | + DELTA |
| 1285 | + PAGE ERROR |
| 1286 | + FULL |
| 1287 | + -------window |
| 1288 | + """ |
| 1289 | + fname = self.id().split('.')[3] |
| 1290 | + node = self.make_simple_node( |
| 1291 | + base_dir=os.path.join(module_name, fname, 'node'), |
| 1292 | + initdb_params=['--data-checksums']) |
| 1293 | + |
| 1294 | + backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup') |
| 1295 | + self.init_pb(backup_dir) |
| 1296 | + self.add_instance(backup_dir, 'node', node) |
| 1297 | + self.set_archiving(backup_dir, 'node', node) |
| 1298 | + node.slow_start() |
| 1299 | + |
| 1300 | + # Take FULL BACKUP |
| 1301 | + full_id = self.backup_node(backup_dir, 'node', node) |
| 1302 | + |
| 1303 | + # Take PAGE BACKUP |
| 1304 | + gdb = self.backup_node( |
| 1305 | + backup_dir, 'node', node, backup_type='page', gdb=True) |
| 1306 | + |
| 1307 | + gdb.set_breakpoint('pg_stop_backup') |
| 1308 | + gdb.run_until_break() |
| 1309 | + gdb.remove_all_breakpoints() |
| 1310 | + gdb._execute('signal SIGINT') |
| 1311 | + gdb.continue_execution_until_error() |
| 1312 | + |
| 1313 | + page_id = self.show_pb(backup_dir, 'node')[1]['id'] |
| 1314 | + |
| 1315 | + # Take DELTA backup |
| 1316 | + delta_id = self.backup_node( |
| 1317 | + backup_dir, 'node', node, backup_type='delta', |
| 1318 | + options=['--retention-window=2', '--delete-expired']) |
| 1319 | + |
| 1320 | + # Take FULL BACKUP |
| 1321 | + full2_id = self.backup_node(backup_dir, 'node', node) |
| 1322 | + |
| 1323 | + self.assertEqual(len(self.show_pb(backup_dir, 'node')), 4) |
| 1324 | + |
| 1325 | + # Clean after yourself |
| 1326 | + self.del_test_dir(module_name, fname) |
| 1327 | + |
| 1328 | + # @unittest.skip("skip") |
| 1329 | + def test_window_error_backups_2(self): |
| 1330 | + """ |
| 1331 | + DELTA |
| 1332 | + PAGE ERROR |
| 1333 | + FULL |
| 1334 | + -------window |
| 1335 | + """ |
| 1336 | + fname = self.id().split('.')[3] |
| 1337 | + node = self.make_simple_node( |
| 1338 | + base_dir=os.path.join(module_name, fname, 'node'), |
| 1339 | + initdb_params=['--data-checksums']) |
| 1340 | + |
| 1341 | + backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup') |
| 1342 | + self.init_pb(backup_dir) |
| 1343 | + self.add_instance(backup_dir, 'node', node) |
| 1344 | + self.set_archiving(backup_dir, 'node', node) |
| 1345 | + node.slow_start() |
| 1346 | + |
| 1347 | + # Take FULL BACKUP |
| 1348 | + full_id = self.backup_node(backup_dir, 'node', node) |
| 1349 | + |
| 1350 | + # Take PAGE BACKUP |
| 1351 | + gdb = self.backup_node( |
| 1352 | + backup_dir, 'node', node, backup_type='page', gdb=True) |
| 1353 | + |
| 1354 | + gdb.set_breakpoint('pg_stop_backup') |
| 1355 | + gdb.run_until_break() |
| 1356 | + gdb._execute('signal SIGTERM') |
| 1357 | + gdb.continue_execution_until_error() |
| 1358 | + |
| 1359 | + page_id = self.show_pb(backup_dir, 'node')[1]['id'] |
| 1360 | + |
| 1361 | + # Take DELTA backup |
| 1362 | + delta_id = self.backup_node( |
| 1363 | + backup_dir, 'node', node, backup_type='delta', |
| 1364 | + options=['--retention-window=2', '--delete-expired']) |
| 1365 | + |
| 1366 | + self.assertEqual(len(self.show_pb(backup_dir, 'node')), 3) |
| 1367 | + |
| 1368 | + # Clean after yourself |
| 1369 | + # self.del_test_dir(module_name, fname) |
| 1370 | + |
| 1371 | + def test_retention_redundancy_overlapping_chains(self): |
| 1372 | + """""" |
| 1373 | + fname = self.id().split('.')[3] |
| 1374 | + node = self.make_simple_node( |
| 1375 | + base_dir=os.path.join(module_name, fname, 'node'), |
| 1376 | + initdb_params=['--data-checksums']) |
| 1377 | + |
| 1378 | + if self.get_version(node) < 90600: |
| 1379 | + self.del_test_dir(module_name, fname) |
| 1380 | + return unittest.skip('Skipped because ptrack support is disabled') |
| 1381 | + |
| 1382 | + backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup') |
| 1383 | + self.init_pb(backup_dir) |
| 1384 | + self.add_instance(backup_dir, 'node', node) |
| 1385 | + self.set_archiving(backup_dir, 'node', node) |
| 1386 | + node.slow_start() |
| 1387 | + |
| 1388 | + self.set_config( |
| 1389 | + backup_dir, 'node', options=['--retention-redundancy=1']) |
| 1390 | + |
| 1391 | + # Make backups to be purged |
| 1392 | + self.backup_node(backup_dir, 'node', node) |
| 1393 | + self.backup_node(backup_dir, 'node', node, backup_type="page") |
| 1394 | + |
| 1395 | + # Make backups to be keeped |
| 1396 | + gdb = self.backup_node(backup_dir, 'node', node, gdb=True) |
| 1397 | + gdb.set_breakpoint('backup_files') |
| 1398 | + gdb.run_until_break() |
| 1399 | + |
| 1400 | + sleep(1) |
| 1401 | + |
| 1402 | + self.backup_node(backup_dir, 'node', node, backup_type="page") |
| 1403 | + |
| 1404 | + gdb.remove_all_breakpoints() |
| 1405 | + gdb.continue_execution_until_exit() |
| 1406 | + |
| 1407 | + self.backup_node(backup_dir, 'node', node, backup_type="page") |
| 1408 | + |
| 1409 | + # Purge backups |
| 1410 | + log = self.delete_expired( |
| 1411 | + backup_dir, 'node', options=['--expired', '--wal']) |
| 1412 | + self.assertEqual(len(self.show_pb(backup_dir, 'node')), 2) |
| 1413 | + |
| 1414 | + # Clean after yourself |
| 1415 | + self.del_test_dir(module_name, fname) |
| 1416 | + |
1277 | 1417 | def test_retention_redundancy_overlapping_chains(self):
|
1278 | 1418 | """"""
|
1279 | 1419 | fname = self.id().split('.')[3]
|
@@ -1319,3 +1459,49 @@ def test_retention_redundancy_overlapping_chains(self):
|
1319 | 1459 |
|
1320 | 1460 | # Clean after yourself
|
1321 | 1461 | self.del_test_dir(module_name, fname)
|
| 1462 | + |
| 1463 | + def test_agressive_retention_window_purge(self): |
| 1464 | + """ |
| 1465 | + https://github.com/postgrespro/pg_probackup/issues/106 |
| 1466 | + """ |
| 1467 | + fname = self.id().split('.')[3] |
| 1468 | + node = self.make_simple_node( |
| 1469 | + base_dir=os.path.join(module_name, fname, 'node'), |
| 1470 | + initdb_params=['--data-checksums']) |
| 1471 | + |
| 1472 | + backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup') |
| 1473 | + self.init_pb(backup_dir) |
| 1474 | + self.add_instance(backup_dir, 'node', node) |
| 1475 | + node.slow_start() |
| 1476 | + |
| 1477 | + # Make ERROR incremental backup |
| 1478 | + try: |
| 1479 | + self.backup_node(backup_dir, 'node', node, backup_type='page') |
| 1480 | + # we should die here because exception is what we expect to happen |
| 1481 | + self.assertEqual( |
| 1482 | + 1, 0, |
| 1483 | + "Expecting Error because page backup should not be possible " |
| 1484 | + "without valid full backup.\n Output: {0} \n CMD: {1}".format( |
| 1485 | + repr(self.output), self.cmd)) |
| 1486 | + except ProbackupException as e: |
| 1487 | + self.assertIn( |
| 1488 | + "ERROR: Valid backup on current timeline 1 is not found. " |
| 1489 | + "Create new FULL backup before an incremental one.", |
| 1490 | + e.message, |
| 1491 | + "\n Unexpected Error Message: {0}\n CMD: {1}".format( |
| 1492 | + repr(e.message), self.cmd)) |
| 1493 | + |
| 1494 | + page_id = self.show_pb(backup_dir, 'node')[0]['id'] |
| 1495 | + |
| 1496 | + sleep(1) |
| 1497 | + |
| 1498 | + # Make FULL backup |
| 1499 | + self.backup_node( |
| 1500 | + backup_dir, 'node', node, |
| 1501 | + options=['--delete-expired', '--retention-window=1', '--stream']) |
| 1502 | + |
| 1503 | + # Check number of backups |
| 1504 | + self.assertEqual(len(self.show_pb(backup_dir, 'node')), 2) |
| 1505 | + |
| 1506 | + # Clean after yourself |
| 1507 | + self.del_test_dir(module_name, fname) |
0 commit comments