Updated to use native php/pfsense commands.

This commit is contained in:
2026-04-27 19:05:06 -07:00
parent f732662bae
commit a98573da02

View File

@@ -1,100 +1,207 @@
--- ---
# roles/pfsense_upgrade/tasks/upgrade.yml # roles/pfsense_upgrade/tasks/upgrade.yml
# Applies the upgrade after safety checks pass. # Execute the actual upgrade process with dynamic repository switching
# Only runs when perform_upgrade=true.
- name: Abort if no upgrade is available (nothing to do) - name: Fail if upgrade target not detected
ansible.builtin.debug:
msg: >
No in-branch upgrade is available for {{ inventory_hostname }}.
Current version {{ pfsense_current_version }} is already the latest on branch {{ pfsense_major_minor }}.
Skipping upgrade.
when:
- not (upgrade_available | bool)
- not (new_major_release_available | bool and allow_major_upgrade | bool)
- name: End play for this host if nothing to upgrade
ansible.builtin.meta: end_host
when:
- not (upgrade_available | bool)
- not (new_major_release_available | bool and allow_major_upgrade | bool)
# ---------------------------------------------------------------------------
# Branch-crossing guard
# ---------------------------------------------------------------------------
- name: Abort if major upgrade is available but not explicitly allowed
ansible.builtin.fail: ansible.builtin.fail:
msg: > msg: "No upgrade target repository detected. Cannot proceed."
A new pfSense branch is available ({{ upstream_version }}) but allow_major_upgrade=false.
Review the release notes for {{ upstream_version }} before upgrading across branches.
Re-run with -e "allow_major_upgrade=true" when ready.
when: when:
- new_major_release_available | bool - perform_upgrade | bool
- not (allow_major_upgrade | bool) - not upgrade_available | bool
- not (upgrade_available | bool)
# --------------------------------------------------------------------------- - name: Display upgrade details
# Pre-upgrade config backup
# ---------------------------------------------------------------------------
- name: Trigger config backup via PHP (writes to /cf/conf/backup/)
ansible.builtin.raw: >
sudo php -r "require_once('/etc/inc/config.inc');
require_once('/etc/inc/util.inc');
backup_config();"
register: _backup_result
changed_when: false
when: not (skip_backup_check | bool)
- name: Confirm backup file was created
ansible.builtin.raw: >
ls -t {{ pfsense_config_backup_path }}/config-*.xml 2>/dev/null | head -1
register: _backup_file
changed_when: false
when: not (skip_backup_check | bool)
- name: Display backup file path
ansible.builtin.debug: ansible.builtin.debug:
msg: "Config backup written to: {{ _backup_file.stdout | trim }}" msg:
- "============================================================"
- "Starting upgrade process on {{ inventory_hostname }}"
- "============================================================"
- " Current version : {{ pfsense_current_version }}"
- " Current repo : {{ current_repo }}"
- " Target repo : {{ upgrade_target_repo }}"
- " Target description : {{ upgrade_target_description }}"
- "============================================================"
# ---------------------------------------------------------------------------
# 1. Backup current configuration before any changes
# ---------------------------------------------------------------------------
- name: Create backup of current config.xml
ansible.builtin.raw:
cmd: cp /conf/config.xml /conf/config.xml.pre_upgrade_{{ ansible_date_time.epoch }}
become: yes
register: _config_backup
when: perform_upgrade | bool
- name: Verify config backup was created
ansible.builtin.raw:
cmd: test -f /conf/config.xml.pre_upgrade_*
become: yes
register: _backup_verified
failed_when: false
when: perform_upgrade | bool
# ---------------------------------------------------------------------------
# 2. Switch repository in configuration
# ---------------------------------------------------------------------------
- name: Switch repository in config.xml
ansible.builtin.raw:
cmd: php -r 'require_once("/etc/inc/config.inc"); require_once("/etc/inc/pkg-utils.inc"); config_set_path("system/pkg_repo_conf_path", "{{ upgrade_target_repo }}"); write_config("Switched to {{ upgrade_target_repo }} for upgrade");'
become: yes
register: _repo_switch
changed_when: true
when: perform_upgrade | bool
- name: Apply repository configuration via pfSense-repo-setup
ansible.builtin.raw:
cmd: /usr/local/sbin/pfSense-repo-setup -U
become: yes
register: _repo_apply
when: perform_upgrade | bool
- name: Verify repository switch took effect
ansible.builtin.raw:
cmd: php -r 'require_once("/etc/inc/pkg-utils.inc"); foreach(pkg_list_repos() as $r) { if (isset($r["default"])) { echo $r["name"]; } }'
become: yes
register: _verify_repo_switch
when: perform_upgrade | bool
- name: Display new default repository
ansible.builtin.debug:
msg: "Repository switched to: {{ _verify_repo_switch.stdout | trim }}"
when: when:
- not (skip_backup_check | bool) - perform_upgrade | bool
- _backup_file.stdout | trim | length > 0 - _verify_repo_switch.stdout | trim == upgrade_target_repo
- name: Warn if no backup file found # ---------------------------------------------------------------------------
# 3. Execute the upgrade (with retry for lock error RC=99)
# ---------------------------------------------------------------------------
- name: Execute pfSense upgrade command
ansible.builtin.raw:
cmd: /usr/local/sbin/pfSense-upgrade -y -l /conf/upgrade_log.txt -p /tmp/pfSense-upgrade.sock
become: yes
register: _upgrade_exec
until: _upgrade_exec.rc != 99
retries: 3
delay: 10
ignore_errors: yes
when: perform_upgrade | bool
timeout: "{{ upgrade_check_timeout | default(120) }}"
- name: Display upgrade command exit code
ansible.builtin.debug: ansible.builtin.debug:
msg: > msg: "Upgrade command exit code: {{ _upgrade_exec.rc }}"
WARNING: Could not confirm config backup was written. when: perform_upgrade | bool
Check {{ pfsense_config_backup_path }} manually before proceeding.
- name: Check upgrade success from log file
ansible.builtin.raw:
cmd: grep -q "__RC=0" /conf/upgrade_log.txt && echo "SUCCESS" || echo "FAILED"
become: yes
register: _upgrade_verify
when: perform_upgrade | bool
- name: Parse upgrade verification result
ansible.builtin.set_fact:
upgrade_successful: "{{ _upgrade_verify.stdout | trim == 'SUCCESS' }}"
upgrade_exit_code: "{{ _upgrade_exec.rc }}"
when: perform_upgrade | bool
- name: Display upgrade verification result
ansible.builtin.debug:
msg:
- "Upgrade verification: {{ _upgrade_verify.stdout | trim }}"
- "Exit code from log: {{ upgrade_exit_code }}"
when: perform_upgrade | bool
# ---------------------------------------------------------------------------
# 4. Extract upgrade log summary for debugging
# ---------------------------------------------------------------------------
- name: Get last 20 lines of upgrade log
ansible.builtin.raw:
cmd: tail -20 /conf/upgrade_log.txt
become: yes
register: _upgrade_log_tail
when: perform_upgrade | bool
- name: Display upgrade log tail (for debugging)
ansible.builtin.debug:
msg: "Upgrade log tail:\n{{ _upgrade_log_tail.stdout }}"
when: when:
- not (skip_backup_check | bool) - perform_upgrade | bool
- _backup_file.stdout | trim | length == 0 - not upgrade_successful
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Execute the upgrade # 5. Handle reboot if needed
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
- name: "UPGRADE — Running pfSense-upgrade on {{ inventory_hostname }}" - name: Check if reboot is required from upgrade log
ansible.builtin.raw: > ansible.builtin.raw:
sudo {{ pfsense_upgrade_bin }} -d -y 2>&1 cmd: grep -q "__REBOOT_AFTER" /conf/upgrade_log.txt && echo "REBOOT_NEEDED" || echo "NO_REBOOT"
register: _upgrade_result become: yes
async: 600 # pfSense upgrades can take several minutes register: _reboot_check
poll: 10 when:
timeout: 620 - perform_upgrade | bool
# The upgrade reboots the host — the connection will drop. That is expected. - upgrade_successful
failed_when: >
_upgrade_result.rc is defined and
_upgrade_result.rc != 0 and
'reboot' not in _upgrade_result.stdout | lower and
'Restarting' not in _upgrade_result.stdout
- name: Display upgrade output - name: Display reboot status
ansible.builtin.debug: ansible.builtin.debug:
msg: "{{ _upgrade_result.stdout_lines | default(['(no output captured — likely rebooted mid-stream)']) }}" msg: "Reboot required: {{ _reboot_check.stdout | trim }}"
when:
- perform_upgrade | bool
- upgrade_successful
# --------------------------------------------------------------------------- - name: Initiate system reboot
# Wait for host to come back after reboot ansible.builtin.raw:
# --------------------------------------------------------------------------- cmd: /sbin/reboot
- name: Wait for pfSense to reboot and become reachable become: yes
when:
- perform_upgrade | bool
- upgrade_successful
- _reboot_check.stdout | trim == "REBOOT_NEEDED"
- name: Wait for system to come back online after reboot
ansible.builtin.wait_for_connection: ansible.builtin.wait_for_connection:
delay: 30 timeout: "{{ reboot_timeout | default(300) }}"
timeout: "{{ reboot_timeout }}" delay: 15
sleep: 10 when:
when: auto_reboot | bool - perform_upgrade | bool
- upgrade_successful
- _reboot_check.stdout | trim == "REBOOT_NEEDED"
- name: Additional delay for services to stabilize
ansible.builtin.pause:
seconds: 30
when:
- perform_upgrade | bool
- upgrade_successful
- _reboot_check.stdout | trim == "REBOOT_NEEDED"
# ---------------------------------------------------------------------------
# 6. Final status and failure handling
# ---------------------------------------------------------------------------
- name: Display upgrade completion message
ansible.builtin.debug:
msg:
- "============================================================"
- "✅ Upgrade completed successfully on {{ inventory_hostname }}"
- " New version should be available after reboot"
- "============================================================"
when:
- perform_upgrade | bool
- upgrade_successful
- name: Display upgrade failure message
ansible.builtin.debug:
msg:
- "============================================================"
- "❌ Upgrade FAILED on {{ inventory_hostname }}"
- " Exit code: {{ upgrade_exit_code }}"
- " Check /conf/upgrade_log.txt on the target system"
- "============================================================"
when:
- perform_upgrade | bool
- not upgrade_successful
- name: Fail playbook if upgrade unsuccessful
ansible.builtin.fail:
msg: "Upgrade failed on {{ inventory_hostname }}. Manual intervention required. SSH to the system and check /conf/upgrade_log.txt"
when:
- perform_upgrade | bool
- not upgrade_successful