|
3 | 3 | # See LICENSE file for licensing details.
|
4 | 4 |
|
5 | 5 | """Helper class used to manage cluster lifecycle."""
|
6 |
| - |
| 6 | +import glob |
7 | 7 | import logging
|
8 | 8 | import os
|
9 | 9 | import pwd
|
@@ -647,3 +647,32 @@ def update_synchronous_node_count(self, units: int = None) -> None:
|
647 | 647 | # Check whether the update was unsuccessful.
|
648 | 648 | if r.status_code != 200:
|
649 | 649 | raise UpdateSyncNodeCountError(f"received {r.status_code}")
|
| 650 | + |
| 651 | + |
| 652 | + def cluster_system_id_mismatch(self, unit_name: str) -> bool: |
| 653 | + """Check if the Patroni service is down and |
| 654 | + if there is the error storage belongs to foreign cluster in its logs.""" |
| 655 | + last_log_file = self._last_patroni_log_file() |
| 656 | + unit_name = unit_name.replace("/", "-") |
| 657 | + if f" CRITICAL: system ID mismatch, node {unit_name} belongs to a different cluster:" in last_log_file: |
| 658 | + return True |
| 659 | + return False |
| 660 | + |
| 661 | + def _last_patroni_log_file(self) -> str: |
| 662 | + """Get last log file content of Patroni service. |
| 663 | +
|
| 664 | + If there is no available log files, empty line will be returned. |
| 665 | +
|
| 666 | + Returns: |
| 667 | + Content of last log file of Patroni service. |
| 668 | + """ |
| 669 | + log_files = glob.glob(f"{PATRONI_LOGS_PATH}/*.log") |
| 670 | + if len(log_files) == 0: |
| 671 | + return "" |
| 672 | + latest_file = max(log_files, key=os.path.getmtime) |
| 673 | + try: |
| 674 | + with open(latest_file) as last_log_file: |
| 675 | + return last_log_file.read() |
| 676 | + except OSError as e: |
| 677 | + logger.exception("Failed to read last patroni log file", exc_info=e) |
| 678 | + return "" |
0 commit comments