258 lines
9.3 KiB
YAML
258 lines
9.3 KiB
YAML
---
|
|
# roles/pfsense_upgrade/tasks/upgrade.yml
|
|
# Execute the actual upgrade process with dynamic repository switching
|
|
|
|
- name: Display upgrade details
|
|
ansible.builtin.debug:
|
|
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 }}"
|
|
- "============================================================"
|
|
when: perform_upgrade | bool
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 1. Switch repository in configuration
|
|
# ---------------------------------------------------------------------------
|
|
# - name: Switch repository in config.xml
|
|
# ansible.builtin.raw: |
|
|
# 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");'
|
|
|
|
# register: _repo_switch
|
|
# timeout: "{{ upgrade_check_timeout | default(120) }}"
|
|
# changed_when: true
|
|
# when: perform_upgrade | bool
|
|
|
|
# - name: Switch repository and force synchronization (GUI Native)
|
|
# ansible.builtin.raw: |
|
|
# nohup php -r '
|
|
# require_once("/etc/inc/guiconfig.inc");
|
|
# require_once("/etc/inc/pkg-utils.inc");
|
|
# global $g;
|
|
# $target_repo = "{{ upgrade_target_repo }}";
|
|
# $repos = pkg_list_repos();
|
|
# foreach ($repos as $repo) {
|
|
# if ($repo["name"] == $target_repo) {
|
|
# config_set_path("system/pkg_repo_conf_path", $repo["path"]);
|
|
# $base_path = $g["pkg_repos_path"] ?: "/usr/local/share/pfSense/pkg/repos";
|
|
# pkg_switch_repo($base_path, $repo["name"]);
|
|
# write_config("Branch switched to " . $repo["name"] . " via Ansible");
|
|
# update_repos();
|
|
# break;
|
|
# }
|
|
# }
|
|
# ' > /dev/null 2>&1 &
|
|
# ignore_unreachable: true
|
|
# when: perform_upgrade | bool
|
|
|
|
- name: Switch repository and force synchronization (Brute Force)
|
|
ansible.builtin.raw: |
|
|
# 1. Update the XML via PHP
|
|
php -r 'require_once("config.inc"); config_set_path("system/pkg_repo_conf_path", "/usr/local/etc/pfSense/pkg/repos/pfSense-repo-{{ upgrade_target_repo }}.conf"); write_config("Ansible repo switch");'
|
|
|
|
# 2. If it is a real file and not a link, move it to a backup
|
|
if [ ! -L /usr/local/share/pfSense/pkg/repos/pfSense-repo.conf ]; then
|
|
mv /usr/local/share/pfSense/pkg/repos/pfSense-repo.conf /usr/local/share/pfSense/pkg/repos/pfSense-repo.conf.bak
|
|
fi
|
|
|
|
# 3. Create the symlink to the new target
|
|
ln -sf /usr/local/etc/pfSense/pkg/repos/pfSense-repo-{{ upgrade_target_repo }}.conf /usr/local/share/pfSense/pkg/repos/pfSense-repo.conf
|
|
|
|
# 4. Force metadata refresh
|
|
# pkg update -f
|
|
pfSense-upgrade -d -y
|
|
when: perform_upgrade | bool
|
|
|
|
- name: Wait for system to settle after repo switch
|
|
ansible.builtin.pause:
|
|
seconds: 10
|
|
when: perform_upgrade | bool
|
|
|
|
- name: Apply repository configuration via pfSense-repo-setup
|
|
ansible.builtin.raw: |
|
|
/usr/local/sbin/pfSense-repo-setup -U
|
|
register: _repo_apply
|
|
when: perform_upgrade | bool
|
|
|
|
- name: Verify repository switch took effect
|
|
ansible.builtin.raw: |
|
|
php -r '
|
|
require_once("/etc/inc/pkg-utils.inc");
|
|
foreach(pkg_list_repos() as $r)
|
|
{
|
|
if (isset($r["default"])) {
|
|
echo $r["name"];
|
|
}
|
|
}'
|
|
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:
|
|
- perform_upgrade | bool
|
|
- _verify_repo_switch.stdout | trim == upgrade_target_repo
|
|
|
|
- name: Halt if repository switch failed
|
|
ansible.builtin.fail:
|
|
msg: "Repo is still {{ _verify_repo_switch.stdout | trim }}, expected {{ upgrade_target_repo }}. Stopping to prevent false positive upgrade."
|
|
when:
|
|
- perform_upgrade | bool
|
|
- _verify_repo_switch.stdout | trim != upgrade_target_repo
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 2. Execute the upgrade (with retry for lock error RC=99)
|
|
# ---------------------------------------------------------------------------
|
|
- name: Execute pfSense upgrade command
|
|
ansible.builtin.raw: |
|
|
/usr/local/sbin/pfSense-upgrade -y -l /conf/upgrade_log.txt -p /tmp/pfSense-upgrade.sock
|
|
register: _upgrade_exec
|
|
until: _upgrade_exec.rc != 99
|
|
retries: 3
|
|
delay: 10
|
|
ignore_errors: yes
|
|
when: perform_upgrade | bool
|
|
timeout: "{{ upgrade_timeout | default(900) }}"
|
|
|
|
- name: Display upgrade command exit code
|
|
ansible.builtin.debug:
|
|
msg: "Upgrade command exit code: {{ _upgrade_exec.rc | default('TIMEOUT - upgrade may still be running') }}"
|
|
when: perform_upgrade | bool
|
|
|
|
- name: Check upgrade success from log file
|
|
ansible.builtin.raw: |
|
|
grep -q "__RC=0" /conf/upgrade_log.txt && echo "SUCCESS" || echo "FAILED"
|
|
register: _upgrade_verify
|
|
when: perform_upgrade | bool
|
|
|
|
- name: Check upgrade success from log file
|
|
ansible.builtin.raw: |
|
|
grep -q "__RC=0" /conf/upgrade_log.txt && echo "SUCCESS" || echo "FAILED"
|
|
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
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 3. Extract upgrade log summary for debugging (on failure)
|
|
# ---------------------------------------------------------------------------
|
|
- name: Get last 20 lines of upgrade log
|
|
ansible.builtin.raw: |
|
|
tail -20 /conf/upgrade_log.txt
|
|
register: _upgrade_log_tail
|
|
when:
|
|
- perform_upgrade | bool
|
|
- not upgrade_successful
|
|
|
|
- name: Display upgrade log tail (for debugging)
|
|
ansible.builtin.debug:
|
|
msg: "Upgrade log tail:\n{{ _upgrade_log_tail.stdout }}"
|
|
when:
|
|
- perform_upgrade | bool
|
|
- not upgrade_successful
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 4. Handle reboot if needed
|
|
# ---------------------------------------------------------------------------
|
|
- name: Check if reboot is required from upgrade log
|
|
ansible.builtin.raw: |
|
|
grep -q "__REBOOT_AFTER" /conf/upgrade_log.txt && echo "REBOOT_NEEDED" || echo "NO_REBOOT"
|
|
register: _reboot_check
|
|
when:
|
|
- perform_upgrade | bool
|
|
- upgrade_successful
|
|
|
|
- name: Display reboot status
|
|
ansible.builtin.debug:
|
|
msg: "Reboot required: {{ _reboot_check.stdout | trim }}"
|
|
when:
|
|
- perform_upgrade | bool
|
|
- upgrade_successful
|
|
|
|
- name: Initiate system reboot
|
|
ansible.builtin.raw: |
|
|
/sbin/reboot
|
|
async: 1 # Run task in background
|
|
poll: 0 # Do not wait for a response.
|
|
ignore_unreachable: true
|
|
ignore_errors: true
|
|
when:
|
|
- perform_upgrade | bool
|
|
- upgrade_successful | bool
|
|
- _reboot_check.stdout | trim == "REBOOT_NEEDED"
|
|
|
|
# - name: Wait for system to come back online after reboot
|
|
# ansible.builtin.wait_for_connection:
|
|
# timeout: "{{ reboot_timeout | default(600) }}"
|
|
# delay: 15
|
|
# when:
|
|
# - perform_upgrade | bool
|
|
# - upgrade_successful | bool
|
|
# - _reboot_check.stdout | trim == "REBOOT_NEEDED"
|
|
|
|
- name: Wait for system to come back online (raw ping loop)
|
|
ansible.builtin.raw: |
|
|
for i in 1 2 3 4 5 6 7 8 9 10 11 12; do
|
|
sleep 10
|
|
/sbin/ping -c 1 -t 2 8.8.8.8 > /dev/null 2>&1 && exit 0
|
|
done
|
|
exit 1
|
|
register: _wait_result
|
|
ignore_errors: true
|
|
when:
|
|
- perform_upgrade | bool
|
|
- upgrade_successful | bool
|
|
- _reboot_check.stdout | trim == "REBOOT_NEEDED"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5. Final status and failure handling
|
|
# ---------------------------------------------------------------------------
|
|
- name: Display upgrade completion message
|
|
ansible.builtin.debug:
|
|
msg:
|
|
- "============================================================"
|
|
- "✅ Upgrade completed successfully on {{ inventory_hostname }}"
|
|
- "============================================================"
|
|
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."
|
|
when:
|
|
- perform_upgrade | bool
|
|
- not upgrade_successful |