diff --git a/docs/user/backup.md b/docs/user/backup.md new file mode 100644 index 000000000..00034dd87 --- /dev/null +++ b/docs/user/backup.md @@ -0,0 +1,205 @@ +# Backup + +The `foremanctl backup` command creates an offline backup of your Foreman deployment, including databases, configuration, and optionally Pulp content. + +## Overview + +The backup process performs the following steps: + +1. **Preflight checks** - Verifies no tasks are running and database integrity +2. **Service shutdown** - Stops all Foreman services cleanly +3. **Database dumps** - Creates PostgreSQL dumps of all databases +4. **Configuration backup** - Archives foremanctl state and configuration +5. **Content backup** - Optionally backs up Pulp content directory +6. **Service restart** - Restores all services to running state + +The backup is **offline** - all Foreman services are stopped during the backup process to ensure data consistency. + +## Basic Usage + +```bash +foremanctl backup /var/backup +``` + +This creates a timestamped backup directory at `/var/backup/foreman-backup-YYYYMMDDTHHMMSS/` containing: + +- Database dumps (`.dump` files in PostgreSQL custom format) +- foremanctl state archive (`foremanctl-state.tar.gz`) +- Pulp content archive (`pulp-content.tar.gz`, unless `--skip-pulp-content`) +- Backup metadata (`metadata.yml`) + +## Options + +### Required + +| Argument | Description | +|----------|-------------| +| `BACKUP_DIR` | Directory where backup files will be stored. The backup process creates a timestamped subdirectory inside this location. | + +### Optional + +| Option | Description | +|--------|-------------| +| `--skip-pulp-content` | Skip backing up `/var/lib/pulp`. This is for debugging purposes or if you plan to copy `/var/lib/pulp` using other methods such as rsync or shared storage. **Warning:** You will not have a complete backup if you use this option. | +| `--wait-for-tasks` | Wait for running Foreman and Pulp tasks to complete instead of failing immediately. The backup will poll until all tasks finish before proceeding. | + +## Examples + +### Standard Backup + +```bash +foremanctl backup /var/backup +``` + +### Backup Without Pulp Content + +Skip Pulp content for debugging or when backing up `/var/lib/pulp` separately (e.g., via rsync or shared storage): + +```bash +foremanctl backup /var/backup --skip-pulp-content +``` + +**Note:** This will not create a complete backup. + +### Backup with Task Waiting + +Allow in-progress tasks to complete before starting backup: + +```bash +foremanctl backup /var/backup --wait-for-tasks +``` + +## Backup Contents + +### Databases + +**Base:** +- `foreman` + +**Katello (when enabled):** +- `candlepin` +- `pulp` + +**IOP (when enabled):** +- `iop_advisor` +- `iop_inventory` +- `iop_remediations` +- `iop_vmaas` +- `iop_vulnerability` + +Database dumps use PostgreSQL's custom format (`--format=c`), which provides: + +- Compression +- Selective restoration +- Parallel restoration support + +### Configuration + +- **foremanctl state** - All deployment configuration and parameters for foremanctl. + +### Pulp Content + +Unless `--skip-pulp-content` is specified, the backup includes: + +- Content repository files +- Database encryption keys +- Django secret key + +The following directories are excluded from Pulp content backups: + +- `media/exports` - Temporary export files +- `media/imports` - Temporary import files +- `media/sync_imports` - Temporary sync import files + +### Metadata + +The backup includes a `metadata.yml` file with: + +- Hostname +- OS version +- Backup timestamp +- foremanctl version +- Backup type +- Enabled features +- Database mode +- Container image list with digests +- List of backed up components + +## Preflight Checks + +Before starting the backup, the following checks are performed: + +### Running Tasks + +The backup fails if any Foreman or Pulp tasks are running (unless `--wait-for-tasks` is used). + +If `--wait-for-tasks` is specified: + +- Foreman tasks are individually waited on with a timeout of 60 minutes (3600 seconds) +- Pulp tasks are polled every 10 seconds for up to 10 minutes (600 seconds) + +### Database Integrity + +For internal databases (`--database-mode internal`), the backup verifies that all database indexes are healthy before proceeding (if PostgreSQL `amcheck` extension is available). This ensures the backup will be consistent and restorable. + +## Backup Process + +### Service Shutdown Sequence + +1. Stop `foreman.target` (all Foreman services) +2. Wait for PostgreSQL to fully stop (internal mode only) +3. Start PostgreSQL in standalone mode for dumps (internal mode only) + +### Database Dump + +Each database is dumped using `pg_dump`: + +```bash +pg_dump --host= --port= --username= --format=custom --file=/.dump +``` + +For external databases, dumps connect to the external host. For internal databases, dumps connect to the locally-running PostgreSQL instance. + +### Service Restoration + +After backup completes (or on failure): + +1. Stop PostgreSQL (if started for dumps) +2. Start `foreman.target` (restores all services) + +Services are restored even if the backup fails to avoid leaving the system in a stopped state. + +## Storage Requirements + +Plan for adequate storage in the backup directory. The following table shows compression ratios for different backup components: + +| Component | Source | Compression Ratio | Example | +|------------------|----------------------------|-------------------|-------------------| +| Database dumps | PostgreSQL data | 80-85% | 100 GB → 15-20 GB | +| foremanctl state | foremanctl state directory | ~85% | 10 MB → ~1.5 MB | +| Pulp content | `/var/lib/pulp` | Not compressed | 100 GB → 100 GB | + +`--skip-pulp-content` skips backing up `/var/lib/pulp`. This option is for debugging purposes or if you plan to copy `/var/lib/pulp` in other ways, such as rsync or shared storage. **You will not have a complete backup if you use this option.** + +## Backup Verification + +After backup completes, verify the backup: + +```bash +# Check backup directory +ls -lh /var/backup/foreman-backup-*/ + +# Review metadata +cat /var/backup/foreman-backup-*/metadata.yml + +# Verify database dumps exist +ls -lh /var/backup/foreman-backup-*/*.dump +``` + +## Retention and Rotation + +The `foremanctl backup` command does **not** automatically delete old backups. You are responsible for: + +- Implementing backup retention policies +- Rotating old backups +- Monitoring backup storage usage \ No newline at end of file diff --git a/src/playbooks/backup/backup.yaml b/src/playbooks/backup/backup.yaml new file mode 100644 index 000000000..2c0f88b4a --- /dev/null +++ b/src/playbooks/backup/backup.yaml @@ -0,0 +1,22 @@ +--- +- name: Backup Databases and configuration + hosts: quadlet + become: true + gather_facts: true + vars_files: + - "../../vars/defaults.yml" + - "../../vars/flavors/{{ flavor }}.yml" + - "../../vars/{{ certificates_source }}_certificates.yml" + - "../../vars/foreman.yml" + - "../../vars/database.yml" + - "../../vars/base.yaml" + pre_tasks: + - name: Ensure PostgreSQL client package is installed + ansible.builtin.package: + name: postgresql + state: present + roles: + - role: backup + vars: + backup_database_mode: "{{ database_mode }}" + backup_databases: "{{ all_databases }}" diff --git a/src/playbooks/backup/metadata.obsah.yaml b/src/playbooks/backup/metadata.obsah.yaml new file mode 100644 index 000000000..606f61e01 --- /dev/null +++ b/src/playbooks/backup/metadata.obsah.yaml @@ -0,0 +1,20 @@ +--- +help: | + Create offline backup of Foreman databases and configuration + +variables: + backup_dir: + parameter: backup_dir + help: Directory where backup files will be stored + type: AbsolutePath + persist: false + + skip_pulp_content: + help: Skip Pulp content directory backup + action: store_true + persist: false + + wait_for_tasks: + help: Wait for running tasks to complete instead of failing immediately + action: store_true + persist: false diff --git a/src/roles/backup/defaults/main.yaml b/src/roles/backup/defaults/main.yaml new file mode 100644 index 000000000..1e8fb7ba4 --- /dev/null +++ b/src/roles/backup/defaults/main.yaml @@ -0,0 +1,11 @@ +--- +backup_database_mode: internal +backup_task_wait_retries: 60 +backup_task_wait_delay: 10 +backup_postgresql_ready_retries: 10 +backup_postgresql_ready_delay: 2 +backup_postgresql_stop_retries: 30 +backup_postgresql_stop_delay: 1 +# State tracking variables +backup_service_stopped: false +backup_postgresql_started: false diff --git a/src/roles/backup/tasks/database_dumps.yaml b/src/roles/backup/tasks/database_dumps.yaml new file mode 100644 index 000000000..25ede0684 --- /dev/null +++ b/src/roles/backup/tasks/database_dumps.yaml @@ -0,0 +1,31 @@ +--- +- name: Dump databases + ansible.builtin.command: + cmd: > + pg_dump + --host={{ item.host }} + --port={{ item.port }} + --username={{ item.user }} + --format=custom + --file={{ backup_dir_full }}/{{ item.name }}.dump + {{ item.database }} + environment: + PGPASSWORD: "{{ item.password }}" + loop: "{{ backup_databases_config }}" + loop_control: + label: "{{ item.name }}" + changed_when: true + +- name: Gather database dump files + ansible.builtin.find: + paths: "{{ backup_dir_full }}" + patterns: "*.dump" + register: backup_files + +- name: Display backup summary + ansible.builtin.debug: + msg: | + Database dumps completed: + - Total files: {{ backup_files.matched }} + - Total size: {{ (backup_files.files | map(attribute='size') | sum) | int | human_readable }} + - Location: {{ backup_dir_full }} diff --git a/src/roles/backup/tasks/main.yaml b/src/roles/backup/tasks/main.yaml new file mode 100644 index 000000000..0f5d0e0fd --- /dev/null +++ b/src/roles/backup/tasks/main.yaml @@ -0,0 +1,171 @@ +--- +- name: Set backup timestamp + ansible.builtin.set_fact: + backup_timestamp: "{{ ansible_date_time.iso8601_basic_short }}" + +- name: Set full backup directory path + ansible.builtin.set_fact: + backup_dir_full: "{{ backup_dir }}/foreman-backup-{{ backup_timestamp }}" + +- name: Ensure backup directory exists + ansible.builtin.file: + path: "{{ backup_dir }}" + state: directory + mode: '0755' + +- name: Test write permissions + ansible.builtin.file: + path: "{{ backup_dir }}/.write_test" + state: touch + mode: '0644' + register: backup_write_test + changed_when: false + +- name: Remove write test file + ansible.builtin.file: + path: "{{ backup_dir }}/.write_test" + state: absent + when: backup_write_test is succeeded + changed_when: false + +- name: Perform backup operations + block: + - name: Run preflight checks + ansible.builtin.include_tasks: + file: preflight.yaml + + - name: Create timestamped backup directory + ansible.builtin.file: + path: "{{ backup_dir_full }}" + state: directory + mode: '0755' + + - name: Stop Foreman services + ansible.builtin.systemd: + name: foreman.target + state: stopped + + - name: Mark services as stopped + ansible.builtin.set_fact: + backup_service_stopped: true + + - name: Wait for PostgreSQL to fully stop + ansible.builtin.systemd: + name: postgresql.service + register: backup_postgres_status + until: backup_postgres_status.status.ActiveState == 'inactive' + retries: "{{ backup_postgresql_stop_retries }}" + delay: "{{ backup_postgresql_stop_delay }}" + when: backup_database_mode == 'internal' + changed_when: false + + - name: Start PostgreSQL for dumps + ansible.builtin.systemd: + name: postgresql.service + state: started + when: backup_database_mode == 'internal' + + - name: Mark PostgreSQL as started + ansible.builtin.set_fact: + backup_postgresql_started: true + when: backup_database_mode == 'internal' + + - name: Wait for PostgreSQL readiness + ansible.builtin.command: + cmd: pg_isready -h {{ database_host }} -p {{ database_port }} + register: backup_pg_ready + retries: "{{ backup_postgresql_ready_retries }}" + delay: "{{ backup_postgresql_ready_delay }}" + until: backup_pg_ready.rc == 0 + changed_when: false + + - name: Build database backup configuration + ansible.builtin.set_fact: + backup_databases_config: "{{ backup_databases_config | default([]) + [db_entry] }}" + vars: + db_entry: + name: "{{ item.name }}" + database: "{{ item.database }}" + host: "{{ database_host }}" + port: "{{ database_port }}" + user: "{{ item.user }}" + password: "{{ item.password }}" + loop: "{{ backup_databases }}" + no_log: true + + - name: Build database names list for display + ansible.builtin.set_fact: + backup_databases_to_backup: "{{ backup_databases | map(attribute='database') | list }}" + + - name: Dump databases + ansible.builtin.include_tasks: + file: database_dumps.yaml + + - name: Backup foremanctl state directory + community.general.archive: + path: "{{ obsah_state_path }}" + dest: "{{ backup_dir_full }}/foremanctl-state.tar.gz" + format: gz + mode: '0644' + + - name: Backup pulp content + ansible.builtin.include_tasks: + file: pulp_content.yaml + when: not skip_pulp_content | default(false) + + - name: Generate backup metadata + ansible.builtin.include_tasks: + file: metadata.yaml + + - name: Stop PostgreSQL + ansible.builtin.systemd: + name: postgresql.service + state: stopped + when: + - backup_database_mode == 'internal' + - backup_postgresql_started | default(false) + + - name: Mark PostgreSQL as stopped + ansible.builtin.set_fact: + backup_postgresql_started: false + when: backup_database_mode == 'internal' + + - name: Start Foreman services + ansible.builtin.systemd: + name: foreman.target + state: started + + - name: Mark services as started + ansible.builtin.set_fact: + backup_service_stopped: false + + - name: Display backup completion + ansible.builtin.debug: + msg: | + Backup completed successfully. + Location: {{ backup_dir_full }} + Databases: {{ backup_databases_to_backup | join(', ') }} + + rescue: + - name: Restore PostgreSQL on failure + ansible.builtin.systemd: + name: postgresql.service + state: stopped + when: + - backup_database_mode == 'internal' + - backup_postgresql_started | default(false) + failed_when: false + + - name: Restore Foreman services on failure + ansible.builtin.systemd: + name: foreman.target + state: started + when: backup_service_stopped | default(false) + failed_when: false + + - name: Report failure + ansible.builtin.fail: + msg: | + Backup failed: {{ ansible_failed_result.msg | default('Unknown error') }} + Services have been restarted. + Partial backup may exist at: {{ backup_dir_full }} diff --git a/src/roles/backup/tasks/metadata.yaml b/src/roles/backup/tasks/metadata.yaml new file mode 100644 index 000000000..87f14da4c --- /dev/null +++ b/src/roles/backup/tasks/metadata.yaml @@ -0,0 +1,64 @@ +--- +# Generate backup metadata before stopping services +# This metadata helps with restore operations and compatibility checking + +- name: Gather package facts + ansible.builtin.package_facts: + +- name: Query container images + containers.podman.podman_image_info: + register: backup_container_images_result + failed_when: false + +- name: Build detailed container image list + ansible.builtin.set_fact: + backup_container_images_detailed: >- + {{ + backup_container_images_detailed | default([]) + + [{ + 'name': (item.RepoTags | first) if item.RepoTags | default([]) | length > 0 else '', + 'digest': (item.RepoDigests | first) if item.RepoDigests | default([]) | length > 0 else '', + 'id': item.Id, + 'created': item.Created + }] + }} + loop: "{{ backup_container_images_result.images | default([]) }}" + when: backup_container_images_result is succeeded + no_log: true + +- name: Check if pulp content was backed up + ansible.builtin.stat: + path: "{{ backup_dir_full }}/pulp-content.tar.gz" + register: backup_pulp_content_backup_check + failed_when: false + +- name: Write metadata file + ansible.builtin.copy: + content: "{{ backup_metadata | to_nice_yaml }}" + dest: "{{ backup_dir_full }}/metadata.yml" + mode: '0644' + vars: + backup_metadata: + hostname: "{{ ansible_fqdn }}" + os_version: "{{ ansible_distribution }} {{ ansible_distribution_version }}" + foremanctl_version: "{{ ansible_facts.packages['foremanctl'][0].version | default('unknown') if 'foremanctl' in ansible_facts.packages else 'unknown' }}" + online: false + incremental: false + timestamp: "{{ backup_timestamp }}" + databases: "{{ backup_databases_to_backup }}" + iop_enabled: "{{ 'iop' in enabled_features }}" + enabled_features: "{{ enabled_features | default([]) }}" + database_mode: "{{ backup_database_mode }}" + container_images: "{{ backup_container_images_detailed | default([]) }}" + backed_up_components: >- + {{ + [ + 'databases', + 'container_images', + 'foremanctl_state' + ] + (['pulp_content'] if backup_pulp_content_backup_check.stat.exists | default(false) else []) + }} + +- name: Display metadata location + ansible.builtin.debug: + msg: "Backup metadata written to {{ backup_dir_full }}/metadata.yml" diff --git a/src/roles/backup/tasks/preflight.yaml b/src/roles/backup/tasks/preflight.yaml new file mode 100644 index 000000000..bf0e81b84 --- /dev/null +++ b/src/roles/backup/tasks/preflight.yaml @@ -0,0 +1,101 @@ +--- +# Preflight checks for backup operation +# - Check for running Foreman tasks +# - Check for running Pulp tasks +# - Run amcheck on databases (if available and local) + +- name: Check for running Foreman tasks + theforeman.foreman.resource_info: + server_url: "https://{{ ansible_fqdn }}" + oauth1_consumer_key: "{{ backup_foreman_oauth_consumer_key }}" + oauth1_consumer_secret: "{{ backup_foreman_oauth_consumer_secret }}" + ca_path: "{{ backup_foreman_ca_certificate }}" + resource: foreman_tasks + search: "state=running" + register: backup_foreman_tasks_check + failed_when: false + changed_when: false + no_log: true + +- name: Set Foreman running tasks count + ansible.builtin.set_fact: + backup_foreman_running_tasks: "{{ backup_foreman_tasks_check.resources | default([]) | length }}" + +- name: Wait for Foreman tasks to complete (if --wait-for-tasks) + theforeman.foreman.wait_for_task: + server_url: "https://{{ ansible_fqdn }}" + oauth1_consumer_key: "{{ backup_foreman_oauth_consumer_key }}" + oauth1_consumer_secret: "{{ backup_foreman_oauth_consumer_secret }}" + ca_path: "{{ backup_foreman_ca_certificate }}" + task: "{{ item }}" + timeout: "{{ task_wait_timeout | default(3600) }}" + loop: "{{ backup_foreman_tasks_check.resources | map(attribute='id') | list }}" + when: + - wait_for_tasks | default(false) + - backup_foreman_running_tasks | int > 0 + changed_when: false + no_log: true + +- name: Fail if Foreman tasks are running (without --wait-for-tasks) + ansible.builtin.fail: + msg: | + There are {{ backup_foreman_running_tasks }} running Foreman task(s). + Please wait for these to complete or use --wait-for-tasks flag. + when: + - not (wait_for_tasks | default(false)) + - backup_foreman_running_tasks | int > 0 + +- name: Check for running Pulp tasks + ansible.builtin.uri: + url: "https://{{ ansible_fqdn }}/pulp/api/v3/tasks/?state__in=running,waiting" + method: GET + client_cert: "{{ backup_foreman_client_certificate }}" + client_key: "{{ backup_foreman_client_key }}" + ca_path: "{{ backup_foreman_ca_certificate }}" + validate_certs: true + return_content: true + register: backup_pulp_tasks_check + failed_when: false + changed_when: false + no_log: true + +- name: Set Pulp running tasks count + ansible.builtin.set_fact: + backup_pulp_running_tasks: "{{ backup_pulp_tasks_check.json.count | default(0) | int }}" + when: backup_pulp_tasks_check is succeeded + +- name: Wait for Pulp tasks to complete (if --wait-for-tasks) + ansible.builtin.uri: + url: "https://{{ ansible_fqdn }}/pulp/api/v3/tasks/?state__in=running,waiting" + method: GET + client_cert: "{{ backup_foreman_client_certificate }}" + client_key: "{{ backup_foreman_client_key }}" + ca_path: "{{ backup_foreman_ca_certificate }}" + validate_certs: true + return_content: true + register: backup_pulp_tasks_wait + until: backup_pulp_tasks_wait.json.count | default(0) == 0 + retries: "{{ backup_task_wait_retries }}" + delay: "{{ backup_task_wait_delay }}" + when: + - wait_for_tasks | default(false) + - backup_pulp_running_tasks | default(0) | int > 0 + changed_when: false + no_log: true + +- name: Fail if Pulp tasks are running (without --wait-for-tasks) + ansible.builtin.fail: + msg: | + There are {{ backup_pulp_running_tasks }} running Pulp task(s). + Please wait for these to complete or use --wait-for-tasks flag. + when: + - not wait_for_tasks | default(false) + - backup_pulp_running_tasks | default(0) | int > 0 + +- name: Run database index integrity checks + ansible.builtin.include_role: + name: check_database_index + vars: + check_database_index_database: "{{ item.database }}" + loop: "{{ backup_databases }}" + when: backup_database_mode == 'internal' diff --git a/src/roles/backup/tasks/pulp_content.yaml b/src/roles/backup/tasks/pulp_content.yaml new file mode 100644 index 000000000..089d90a05 --- /dev/null +++ b/src/roles/backup/tasks/pulp_content.yaml @@ -0,0 +1,30 @@ +--- +- name: Backup pulp content + when: not skip_pulp_content | default(false) + block: + - name: Backup pulp content directory with encryption keys # noqa: command-instead-of-module + ansible.builtin.command: + cmd: > + tar -czf {{ backup_dir_full }}/pulp-content.tar.gz + -C {{ pulp_storage_path }} + --exclude=media/exports + --exclude=media/imports + --exclude=media/sync_imports + media + database_fields.symmetric.key + django_secret_key + register: backup_pulp_content_archive + changed_when: true + + - name: Get pulp content archive info + ansible.builtin.stat: + path: "{{ backup_dir_full }}/pulp-content.tar.gz" + register: backup_pulp_content_archive_stat + when: backup_pulp_content_archive is succeeded + + - name: Display pulp content backup completion + ansible.builtin.debug: + msg: >- + Pulp content backup completed: {{ backup_dir_full }}/pulp-content.tar.gz + ({{ (backup_pulp_content_archive_stat.stat.size / 1024 / 1024) | round(2) }} MB) + when: backup_pulp_content_archive_stat.stat.exists diff --git a/src/roles/check_database_index/tasks/main.yml b/src/roles/check_database_index/tasks/main.yml new file mode 100644 index 000000000..cc7900403 --- /dev/null +++ b/src/roles/check_database_index/tasks/main.yml @@ -0,0 +1,53 @@ +--- +# Check database indexes using PostgreSQL amcheck extension +# This check verifies the logical consistency of B-tree indexes to detect corruption +# Required parameters: +# check_database_index_database: database name to check + +- name: Check if amcheck extension is installed + community.postgresql.postgresql_query: + db: "{{ check_database_index_database }}" + login_host: "{{ database_host }}" + login_port: "{{ database_port }}" + login_user: postgres + login_password: "{{ postgresql_admin_password }}" + query: SELECT COUNT(*) as count FROM pg_extension WHERE extname = 'amcheck' + register: check_database_index_amcheck_installed + failed_when: false + changed_when: false + +- name: "Run amcheck on database: {{ check_database_index_database }}" + when: + - check_database_index_amcheck_installed is succeeded + - check_database_index_amcheck_installed.query_result[0].count | default(0) > 0 + block: + - name: Execute amcheck integrity check + community.postgresql.postgresql_query: + db: "{{ check_database_index_database }}" + login_host: "{{ database_host }}" + login_port: "{{ database_port }}" + login_user: postgres + login_password: "{{ postgresql_admin_password }}" + query: | + SELECT bt_index_check(index => c.oid, heapallindexed => i.indisunique), + c.relname, + c.relpages + FROM pg_index i + JOIN pg_opclass op ON i.indclass[0] = op.oid + JOIN pg_am am ON op.opcmethod = am.oid + JOIN pg_class c ON i.indexrelid = c.oid + JOIN pg_namespace n ON c.relnamespace = n.oid + WHERE am.amname = 'btree' AND n.nspname = 'public' + AND c.relpersistence != 't' + AND c.relkind = 'i' AND i.indisready AND i.indisvalid + ORDER BY c.relpages DESC; + changed_when: false + + - name: "Report database index check PASSED: {{ check_database_index_database }}" + ansible.builtin.debug: + msg: "{{ check_database_index_database }} database index check: PASSED" + + rescue: + - name: "Report database index check FAILED: {{ check_database_index_database }}" + ansible.builtin.debug: + msg: "{{ check_database_index_database }} database index check: FAILED - indexes may be corrupted" diff --git a/src/roles/checks/tasks/main.yml b/src/roles/checks/tasks/main.yml index 90dbf9e1d..1fb6f2ced 100644 --- a/src/roles/checks/tasks/main.yml +++ b/src/roles/checks/tasks/main.yml @@ -7,6 +7,14 @@ - check_database_connection - check_system_requirements +- name: Run database index integrity checks + ansible.builtin.include_role: + name: check_database_index + vars: + check_database_index_database: "{{ item.database }}" + loop: "{{ checks_databases }}" + when: database_mode == 'internal' + - name: Report status of checks ansible.builtin.fail: msg: "{{ checks_results }}" diff --git a/src/roles/pulp/defaults/main.yaml b/src/roles/pulp/defaults/main.yaml index cbffafa59..f27b74d83 100644 --- a/src/roles/pulp/defaults/main.yaml +++ b/src/roles/pulp/defaults/main.yaml @@ -11,7 +11,7 @@ pulp_api_service_worker_count: "{{ ([4, ansible_facts['processor_nproc']] | min) pulp_volumes: >- {{ - ['/var/lib/pulp:/var/lib/pulp:rw'] + + [pulp_storage_path ~ ':' ~ pulp_storage_path ~ ':rw'] + (pulp_import_paths | map('regex_replace', '^(.+)$', '\1:\1:rw') | list) + (pulp_export_paths | map('regex_replace', '^(.+)$', '\1:\1:rw') | list) }} diff --git a/src/vars/base.yaml b/src/vars/base.yaml index b85b9d02f..d39164531 100644 --- a/src/vars/base.yaml +++ b/src/vars/base.yaml @@ -31,6 +31,7 @@ httpd_server_certificate: "{{ server_certificate }}" httpd_server_key: "{{ server_key }}" httpd_enabled_pulp_snippets: "{{ ['pypi'] if 'pulp_python' in pulp_plugins else [] }}" +pulp_storage_path: /var/lib/pulp pulp_content_origin: "https://{{ ansible_facts['fqdn'] }}" pulp_pulp_url: "https://{{ ansible_facts['fqdn'] }}" pulp_plugins: "{{ enabled_features | select('contains', 'content/') | map('replace', 'content/', 'pulp_') | list }}" @@ -48,3 +49,9 @@ foreman_proxy_oauth_consumer_secret: "{{ foreman_oauth_consumer_secret }}" iop_core_foreman_url: "{{ foreman_url }}" iop_core_foreman_oauth_consumer_key: "{{ foreman_oauth_consumer_key }}" iop_core_foreman_oauth_consumer_secret: "{{ foreman_oauth_consumer_secret }}" + +backup_foreman_oauth_consumer_key: "{{ foreman_oauth_consumer_key }}" +backup_foreman_oauth_consumer_secret: "{{ foreman_oauth_consumer_secret }}" +backup_foreman_ca_certificate: "{{ foreman_ca_certificate }}" +backup_foreman_client_certificate: "{{ foreman_client_certificate }}" +backup_foreman_client_key: "{{ foreman_client_key }}"