|
2 | 2 | import os
|
3 | 3 | from time import sleep
|
4 | 4 | from .helpers.ptrack_helpers import ProbackupTest, ProbackupException
|
| 5 | +import shutil |
5 | 6 |
|
6 | 7 |
|
7 | 8 | module_name = 'backup'
|
@@ -1475,3 +1476,194 @@ def test_backup_with_least_privileges_role(self):
|
1475 | 1476 |
|
1476 | 1477 | # Clean after yourself
|
1477 | 1478 | self.del_test_dir(module_name, fname)
|
| 1479 | + |
| 1480 | + # @unittest.skip("skip") |
| 1481 | + def test_parent_choosing(self): |
| 1482 | + """ |
| 1483 | + PAGE3 <- RUNNING(parent should be FULL) |
| 1484 | + PAGE2 <- OK |
| 1485 | + PAGE1 <- CORRUPT |
| 1486 | + FULL |
| 1487 | + """ |
| 1488 | + fname = self.id().split('.')[3] |
| 1489 | + backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup') |
| 1490 | + node = self.make_simple_node( |
| 1491 | + base_dir=os.path.join(module_name, fname, 'node'), |
| 1492 | + set_replication=True, |
| 1493 | + initdb_params=['--data-checksums']) |
| 1494 | + |
| 1495 | + self.init_pb(backup_dir) |
| 1496 | + self.add_instance(backup_dir, 'node', node) |
| 1497 | + self.set_archiving(backup_dir, 'node', node) |
| 1498 | + node.slow_start() |
| 1499 | + |
| 1500 | + full_id = self.backup_node(backup_dir, 'node', node) |
| 1501 | + |
| 1502 | + # PAGE1 |
| 1503 | + page1_id = self.backup_node( |
| 1504 | + backup_dir, 'node', node, backup_type='page') |
| 1505 | + |
| 1506 | + # PAGE2 |
| 1507 | + page2_id = self.backup_node( |
| 1508 | + backup_dir, 'node', node, backup_type='page') |
| 1509 | + |
| 1510 | + # Change PAGE1 to ERROR |
| 1511 | + self.change_backup_status(backup_dir, 'node', page1_id, 'ERROR') |
| 1512 | + |
| 1513 | + # PAGE3 |
| 1514 | + page3_id = self.backup_node( |
| 1515 | + backup_dir, 'node', node, |
| 1516 | + backup_type='page', options=['--log-level-file=LOG']) |
| 1517 | + |
| 1518 | + log_file_path = os.path.join(backup_dir, 'log', 'pg_probackup.log') |
| 1519 | + with open(log_file_path) as f: |
| 1520 | + log_file_content = f.read() |
| 1521 | + |
| 1522 | + self.assertIn( |
| 1523 | + "WARNING: Backup {0} has invalid parent: {1}. " |
| 1524 | + "Cannot be a parent".format(page2_id, page1_id), |
| 1525 | + log_file_content) |
| 1526 | + |
| 1527 | + self.assertIn( |
| 1528 | + "WARNING: Backup {0} has status: ERROR. " |
| 1529 | + "Cannot be a parent".format(page1_id), |
| 1530 | + log_file_content) |
| 1531 | + |
| 1532 | + self.assertIn( |
| 1533 | + "Parent backup: {0}".format(full_id), |
| 1534 | + log_file_content) |
| 1535 | + |
| 1536 | + self.assertEqual( |
| 1537 | + self.show_pb( |
| 1538 | + backup_dir, 'node', backup_id=page3_id)['parent-backup-id'], |
| 1539 | + full_id) |
| 1540 | + |
| 1541 | + # Clean after yourself |
| 1542 | + self.del_test_dir(module_name, fname) |
| 1543 | + |
| 1544 | + # @unittest.skip("skip") |
| 1545 | + def test_parent_choosing_1(self): |
| 1546 | + """ |
| 1547 | + PAGE3 <- RUNNING(parent should be FULL) |
| 1548 | + PAGE2 <- OK |
| 1549 | + PAGE1 <- (missing) |
| 1550 | + FULL |
| 1551 | + """ |
| 1552 | + fname = self.id().split('.')[3] |
| 1553 | + backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup') |
| 1554 | + node = self.make_simple_node( |
| 1555 | + base_dir=os.path.join(module_name, fname, 'node'), |
| 1556 | + set_replication=True, |
| 1557 | + initdb_params=['--data-checksums']) |
| 1558 | + |
| 1559 | + self.init_pb(backup_dir) |
| 1560 | + self.add_instance(backup_dir, 'node', node) |
| 1561 | + self.set_archiving(backup_dir, 'node', node) |
| 1562 | + node.slow_start() |
| 1563 | + |
| 1564 | + full_id = self.backup_node(backup_dir, 'node', node) |
| 1565 | + |
| 1566 | + # PAGE1 |
| 1567 | + page1_id = self.backup_node( |
| 1568 | + backup_dir, 'node', node, backup_type='page') |
| 1569 | + |
| 1570 | + # PAGE2 |
| 1571 | + page2_id = self.backup_node( |
| 1572 | + backup_dir, 'node', node, backup_type='page') |
| 1573 | + |
| 1574 | + # Delete PAGE1 |
| 1575 | + shutil.rmtree( |
| 1576 | + os.path.join(backup_dir, 'backups', 'node', page1_id)) |
| 1577 | + |
| 1578 | + # PAGE3 |
| 1579 | + page3_id = self.backup_node( |
| 1580 | + backup_dir, 'node', node, |
| 1581 | + backup_type='page', options=['--log-level-file=LOG']) |
| 1582 | + |
| 1583 | + log_file_path = os.path.join(backup_dir, 'log', 'pg_probackup.log') |
| 1584 | + with open(log_file_path) as f: |
| 1585 | + log_file_content = f.read() |
| 1586 | + |
| 1587 | + self.assertIn( |
| 1588 | + "WARNING: Backup {0} has missing parent: {1}. " |
| 1589 | + "Cannot be a parent".format(page2_id, page1_id), |
| 1590 | + log_file_content) |
| 1591 | + |
| 1592 | + self.assertIn( |
| 1593 | + "Parent backup: {0}".format(full_id), |
| 1594 | + log_file_content) |
| 1595 | + |
| 1596 | + self.assertEqual( |
| 1597 | + self.show_pb( |
| 1598 | + backup_dir, 'node', backup_id=page3_id)['parent-backup-id'], |
| 1599 | + full_id) |
| 1600 | + |
| 1601 | + # Clean after yourself |
| 1602 | + self.del_test_dir(module_name, fname) |
| 1603 | + |
| 1604 | + # @unittest.skip("skip") |
| 1605 | + def test_parent_choosing_2(self): |
| 1606 | + """ |
| 1607 | + PAGE3 <- RUNNING(backup should fail) |
| 1608 | + PAGE2 <- OK |
| 1609 | + PAGE1 <- OK |
| 1610 | + FULL <- (missing) |
| 1611 | + """ |
| 1612 | + fname = self.id().split('.')[3] |
| 1613 | + backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup') |
| 1614 | + node = self.make_simple_node( |
| 1615 | + base_dir=os.path.join(module_name, fname, 'node'), |
| 1616 | + set_replication=True, |
| 1617 | + initdb_params=['--data-checksums']) |
| 1618 | + |
| 1619 | + self.init_pb(backup_dir) |
| 1620 | + self.add_instance(backup_dir, 'node', node) |
| 1621 | + self.set_archiving(backup_dir, 'node', node) |
| 1622 | + node.slow_start() |
| 1623 | + |
| 1624 | + full_id = self.backup_node(backup_dir, 'node', node) |
| 1625 | + |
| 1626 | + # PAGE1 |
| 1627 | + page1_id = self.backup_node( |
| 1628 | + backup_dir, 'node', node, backup_type='page') |
| 1629 | + |
| 1630 | + # PAGE2 |
| 1631 | + page2_id = self.backup_node( |
| 1632 | + backup_dir, 'node', node, backup_type='page') |
| 1633 | + |
| 1634 | + # Delete FULL |
| 1635 | + shutil.rmtree( |
| 1636 | + os.path.join(backup_dir, 'backups', 'node', full_id)) |
| 1637 | + |
| 1638 | + # PAGE3 |
| 1639 | + try: |
| 1640 | + self.backup_node( |
| 1641 | + backup_dir, 'node', node, |
| 1642 | + backup_type='page', options=['--log-level-file=LOG']) |
| 1643 | + # we should die here because exception is what we expect to happen |
| 1644 | + self.assertEqual( |
| 1645 | + 1, 0, |
| 1646 | + "Expecting Error because FULL backup is missing" |
| 1647 | + "\n Output: {0} \n CMD: {1}".format( |
| 1648 | + repr(self.output), self.cmd)) |
| 1649 | + except ProbackupException as e: |
| 1650 | + self.assertIn( |
| 1651 | + 'WARNING: Failed to find a valid backup chain', |
| 1652 | + e.message, |
| 1653 | + '\n Unexpected Error Message: {0}\n CMD: {1}'.format( |
| 1654 | + repr(e.message), self.cmd)) |
| 1655 | + |
| 1656 | + self.assertIn( |
| 1657 | + 'ERROR: Valid backup on current timeline is not found. ' |
| 1658 | + 'Create new FULL backup before an incremental one.', |
| 1659 | + e.message, |
| 1660 | + '\n Unexpected Error Message: {0}\n CMD: {1}'.format( |
| 1661 | + repr(e.message), self.cmd)) |
| 1662 | + |
| 1663 | + self.assertEqual( |
| 1664 | + self.show_pb( |
| 1665 | + backup_dir, 'node')[2]['status'], |
| 1666 | + 'ERROR') |
| 1667 | + |
| 1668 | + # Clean after yourself |
| 1669 | + self.del_test_dir(module_name, fname) |
0 commit comments