Spaces:
Paused
Paused
| import asyncio | |
| import os | |
| import shutil | |
| import sys | |
| from pathlib import Path | |
| # Add backend to path | |
| sys.path.append(os.path.join(os.getcwd(), "backend")) | |
| from app.services.infrastructure.storage.backup_service import get_backup_manager | |
| async def verify_disaster_recovery(): | |
| print("π Starting Disaster Recovery Verification...") | |
| # Set environment variables for config | |
| app_data_dir = os.path.expanduser("~/.zenith") | |
| db_path = f"{app_data_dir}/fraud_detection.db" | |
| backup_dir = os.path.join(os.getcwd(), "data/backups_verify") | |
| os.environ["BACKUP_DIR"] = backup_dir | |
| os.environ["DATABASE_PATH"] = db_path | |
| os.environ["EVIDENCE_DIR"] = os.path.join(os.getcwd(), "data/evidence_verify") | |
| os.environ["CONFIG_DIR"] = os.path.join(os.getcwd(), "data/config_verify") | |
| # Ensure app data dir exists for verification | |
| os.makedirs(app_data_dir, exist_ok=True) | |
| backup_manager = await get_backup_manager() | |
| print(f"β Backup directory: {backup_dir}") | |
| print(f"β Database path: {db_path}") | |
| # 2. Create a full backup | |
| print("\nπΎ Creating Full Backup...") | |
| try: | |
| backup_info = await backup_manager.create_full_backup(reason="DR Verification") | |
| print(f"β Backup created: {backup_info['id']}") | |
| print(f"β Size: {backup_info['size_bytes']} bytes") | |
| print(f"β Hash: {backup_info['integrity_hash']}") | |
| except Exception as e: | |
| print(f"β Backup failed: {e}") | |
| return | |
| # 3. Verify integrity | |
| print("\nπ Verifying Integrity...") | |
| verification = await backup_manager.verify_backup_integrity(backup_info["id"]) | |
| if verification["valid"]: | |
| print("β Integrity check passed!") | |
| else: | |
| print(f"β Integrity check failed: {verification.get('error')}") | |
| return | |
| # 4. Simulate disaster (move DB) | |
| print("\nπ₯ Simulating Disaster (Data Loss)...") | |
| original_db_path = Path(db_path) | |
| if not original_db_path.exists(): | |
| # Create a dummy one if it doesn't exist for the test | |
| print("β οΈ Database didn't exist, creating dummy for test...") | |
| with open(original_db_path, "w") as f: | |
| f.write("DUMMY DATA") | |
| temp_loss_path = original_db_path.with_suffix(".lost") | |
| shutil.move(original_db_path, temp_loss_path) | |
| print(f"β Original database moved to: {temp_loss_path}") | |
| print(f"β Database exists: {original_db_path.exists()}") | |
| # 5. Restore from backup | |
| print("\nπ₯ Restoring from Backup...") | |
| restore_target = os.path.join(os.getcwd(), "data/restore_verify") | |
| restore_result = await backup_manager.restore_backup( | |
| backup_info["id"], target_dir=restore_target | |
| ) | |
| if restore_result["success"]: | |
| print("β Restore operation reported success!") | |
| # BackupManager.restore_backup also copies back to original path if target_dir is None, | |
| # but since we specified target_dir, we need to check the components | |
| # Verify components were restored | |
| restored_db = Path(restore_target) / backup_info["id"] / "database.db" | |
| if restored_db.exists(): | |
| print(f"β Component verified: {restored_db}") | |
| else: | |
| print("β Restored component missing!") | |
| # The _restore_database method also attempts to restore to config["database_path"] | |
| if original_db_path.exists(): | |
| print(f"β Database restored to original location: {original_db_path}") | |
| else: | |
| print("β Database NOT restored to original location!") | |
| else: | |
| print(f"β Restore failed: {restore_result.get('error')}") | |
| # 1. Cleanup | |
| print("\nπ§Ή Cleaning Up...") | |
| if original_db_path.exists() and temp_loss_path.exists(): | |
| os.remove(temp_loss_path) | |
| print("β Simualted loss file removed.") | |
| if os.path.exists(backup_dir): | |
| shutil.rmtree(backup_dir) | |
| print("β Verification backups removed.") | |
| if os.path.exists(restore_target): | |
| shutil.rmtree(restore_target) | |
| print("β Verification restore directory removed.") | |
| print("\n⨠Disaster Recovery Verification COMPLETED SUCCESSFULLY!") | |
| if __name__ == "__main__": | |
| asyncio.run(verify_disaster_recovery()) | |