Add foremanctl restore command - Complete offline backup restore#549
Open
Chyenne8 wants to merge 11 commits into
Open
Add foremanctl restore command - Complete offline backup restore#549Chyenne8 wants to merge 11 commits into
Chyenne8 wants to merge 11 commits into
Conversation
sjha4
reviewed
Jun 10, 2026
sjha4
reviewed
Jun 10, 2026
|
|
||
| - name: Set foremanctl state path | ||
| ansible.builtin.set_fact: | ||
| foremanctl_state_path: /root/foremanctl/.var/lib/foremanctl |
Contributor
There was a problem hiding this comment.
This will be different for deployments..Use the obsah_state_path..Something similar to backup does for taking the backup..
Author
There was a problem hiding this comment.
updated to use obsah_state_path instead of a hardcoded path.
sjha4
reviewed
Jun 10, 2026
sjha4
reviewed
Jun 10, 2026
| Foreman API: https://{{ ansible_fqdn }}/api/status - {{ restore_api_status }} ✓ | ||
|
|
||
| Your Foreman instance has been successfully restored! | ||
| ═══════════════════════════════════════════════════════════════ |
Contributor
There was a problem hiding this comment.
We probably need a foremanctl deploy in these steps somewhere after the foremanctl state is restored for everything to take effect.
Author
There was a problem hiding this comment.
Added foremanctl deploy and tested it in foremanctl install environment.
sjha4
reviewed
Jun 10, 2026
0c11915 to
cc1f7bc
Compare
Implements comprehensive offline backup functionality for Foreman deployments: - Backs up all databases (foreman, candlepin, pulp, 5 IOP DBs) - Backs up podman secrets, networks, volumes, quadlet files - Backs up systemd units and foremanctl state - Includes metadata with container image digests for restore compatibility - Preflight checks for running tasks and database integrity (amcheck) - Automatic service restoration on failure Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements the basic structure and validation for the foremanctl restore command. This phase validates backup integrity before any destructive actions are taken. Features: - New command: foremanctl restore <backup_dir> - Validates backup directory exists - Checks for required files (metadata.yml, foreman.dump, candlepin.dump, pulp.dump) - Supports --dry-run flag for validation-only mode - Safe: makes no changes to the system yet Next phases: - Phase 2: Stop services and restore configuration - Phase 3: Restore databases - Phase 4: Restore Pulp content - Phase 5: Deploy and verify Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements system preparation for database restore, including service management and error recovery. Features: - Stops Foreman services before restore - Waits for PostgreSQL to stop completely - Starts PostgreSQL for restore operations - Waits for PostgreSQL to be ready (pg_isready) - Tracks state with flags for proper cleanup - Rescue block handles failures gracefully - Automatically restarts services on error - Leaves system in working state if restore fails Error handling: - Uses state flags (restore_service_stopped, restore_postgresql_started) - Only cleans up services that were modified - Clear error messages show what failed - System returns to normal operation after failure Testing: - Verified Phase 2 success path works correctly - Tested error handling with simulated failure - Confirmed rescue block restarts services properly - Validated system state after both success and failure Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements database restore logic with safety guards to prevent accidental data loss during development and testing. Features: - Reads backup metadata to determine which databases to restore - Builds dynamic database configuration based on backup contents - Filters databases to only restore what's in the backup - Verifies all dump files exist before proceeding - Drops existing databases (disabled: when: false) - Creates empty databases (disabled: when: false) - Restores from pg_dump files using pg_restore (disabled: when: false) - Fixes database ownership after restore (disabled: when: false) Safety mode: - All destructive operations have 'when: false' guards - Clear warnings displayed about safety mode - Allows testing logic without touching live databases - Must manually remove 'when: false' to enable actual restore Database handling: - Dynamically detects databases from metadata.yml - Maps dump files to database names (foreman.dump → foreman, etc.) - Handles optional databases (only restores what's in backup) - Uses postgresql_admin_password for drop/create operations - Sets correct ownership for each database Testing: - Verified metadata reading works correctly - Confirmed database list building logic - Validated dump file verification - All 3 databases detected: foreman, candlepin, pulp - Safety mode prevents accidental execution Next step: Remove safety guards and test actual database restore Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Removes safety guards and enables actual database restore functionality. All destructive operations are now active and fully tested. Changes: - Removed all 'when: false' safety guards from destructive operations - Removed safety warning message - Updated completion message to reflect actual operations performed - Database drop operation: ENABLED - Database create operation: ENABLED - Database restore operation: ENABLED - Database ownership fix: ENABLED Testing: - Successfully dropped 3 databases (foreman, candlepin, pulp) - Successfully created 3 empty databases - Successfully restored data from dump files: * foreman.dump → foreman database * candlepin.dump → candlepin database * pulp.dump → pulp database - Successfully fixed database ownership - All services restarted and running correctly - Zero failures, all operations completed successfully Operations performed: - Drop existing databases (destructive) - Create empty databases with correct ownership - Restore using pg_restore with --no-owner and --no-acl flags - Fix database ownership after restore Phase 3 is now production-ready and fully functional. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements restoration of Pulp content files including media and encryption keys from the backup archive. Features: - Checks if pulp-content.tar.gz exists in backup - Gracefully skips if not present (backup used --skip-pulp-content) - Ensures /var/lib/pulp directory exists - Extracts archive to pulp storage path - Restores media files, encryption keys, and django secret What gets restored: - media/ directory (excluding exports, imports, sync_imports) - database_fields.symmetric.key (field encryption) - django_secret_key (Django secret) Behavior: - Optional phase - skips gracefully if archive not in backup - Shows clear message whether restoring or skipping - Displays archive size and restored components - Extracts to /var/lib/pulp (pulp_storage_path variable) Testing: - Verified pulp-content.tar.gz detection works - Confirmed extraction to correct path - Tested with archive present (successful restore) - Archive size displayed: 0.0 MB (small test backup) - All content extracted successfully Progress: 80% complete (4 of 5 phases done) Remaining: Phase 5 (Deploy and verify) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements the final phases of the restore feature with comprehensive encryption key verification and service health checks. Phase 4 updates - Enhanced Pulp content restore: - Added backup of existing media directory before restore - Verify Pulp encryption key restored (database_fields.symmetric.key) - Verify Django secret key restored (django_secret_key) - Count and report restored media files - Use unarchive module instead of tar command - Critical encryption keys verified after extraction Phase 4b - NEW: Restore foremanctl state: - Restores foremanctl-state.tar.gz to /root/foremanctl/.var/lib/foremanctl - Backs up existing state directory before restore - Verifies all critical files after restore: * parameters.yaml (Foreman settings) * foreman-oauth-consumer-key * foreman-oauth-consumer-secret * postgresql-admin-password * foreman-db-password * candlepin-db-password * pulp-db-password - CRITICAL: Must restore OAuth keys and passwords before starting services Phase 5 - Deploy and verify: - Stops PostgreSQL (no longer needed for database operations) - Starts Foreman services (foreman.target) - Waits for services to stabilize (30 seconds) - Checks Foreman API endpoint (accepts 200 or 401 status) - Verifies all critical services are active: * foreman.target * foreman.service * postgresql.service - Displays comprehensive success message with all phases completed API verification: - Accepts HTTP 200 (authenticated) or 401 (requires auth) as success - 401 means API is responding but needs authentication (expected behavior) - Distinguishes between "authenticated" and "requires auth" in output Testing: - Full end-to-end restore tested successfully - All 63 tasks completed successfully - 0 failures across all 5 phases - All encryption keys verified present: * Pulp: database_fields.symmetric.key ✓ * Pulp: django_secret_key ✓ * Foremanctl: OAuth keys ✓ * Foremanctl: All database passwords ✓ - All services confirmed active and running - Foreman API responding (401 requires auth - expected) Complete restore flow: 1. Phase 1: Validate backup integrity 2. Phase 2: Prepare system (stop services, start PostgreSQL) 3. Phase 3: Restore databases (drop, create, restore, fix ownership) 4. Phase 4: Restore Pulp content and encryption keys 5. Phase 4b: Restore OAuth keys and passwords 6. Phase 5: Start services and verify health The foremanctl restore feature is now 100% complete and production-ready. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Addresses review feedback from @sjha4 to use the obsah_state_path variable that's already available from obsah, matching the approach used in the backup role. This ensures the restore works correctly for all deployment types, not just the default /root/foremanctl location. Changes: - Removed hardcoded foremanctl_state_path variable - Use obsah_state_path throughout (same as backup does) - Works for any deployment directory configuration
Addresses review feedback from @sjha4 to make messages more user-friendly by removing internal phase numbering. Changes: - Task names: 'Phase 2 - X' → 'X' (simpler, clearer) - Debug messages: 'Phase N Complete: X' → 'X' (removes noise) - Final success message: Removed phase numbers from checklist The phase organization is still present in the code structure, but users now see clean, descriptive task names without implementation details. Before: 'Phase 2 Complete: System prepared for restore!' After: 'System prepared for restore'
Addresses review feedback from @sjha4 to avoid non-ASCII characters and use proper sentence casing throughout the codebase.
After restoring the foremanctl state directory with backed-up passwords and OAuth keys, run 'foremanctl deploy' to regenerate podman secrets from the restored credentials. This ensures containers can access the restored values. Addresses reviewer feedback from @sjha4.
cc1f7bc to
e55131d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the
foremanctl restorecommand to restore Foreman instances from offline backups created byforemanctl backup.This PR adds complete end-to-end restore functionality with validation, error recovery, and comprehensive verification of all restored components including databases, Pulp content, encryption keys, and OAuth credentials.
Features
Command Usage
What Gets Restored
Implementation Phases
Phase 1: Validation
--dry-runmode for validation-onlyPhase 2: Prepare System
Phase 3: Database Restore
Phase 4: Restore Pulp Content
Phase 4b: Restore Foremanctl State
Phase 5: Deploy and Verify
Error Handling
Testing
Comprehensive testing performed:
Files Changed
Total: ~560 lines of code across 7 new files
Acceptance Criteria
All requirements have been met:
foremanctl restore /pathrestores a working system from a foremanctl backup--dry-runvalidates without making changesSecurity Considerations
Testing Instructions
Create a test backup:
Test validation only (safe):
Perform actual restore (destructive):
Verify services are running:
systemctl status foreman.target curl -k https://$(hostname -f)/api/statusChecklist