diff --git a/mikrotikbackup_clean.yml b/mikrotikbackup_clean.yml index c5781fd..6ade657 100644 --- a/mikrotikbackup_clean.yml +++ b/mikrotikbackup_clean.yml @@ -1,7 +1,7 @@ --- - name: Backup and/or Upgrade MikroTik hosts: mikrotik_routers - gather_facts: false + gather_facts: no serial: 10 vars: @@ -10,19 +10,19 @@ checkmk_service_description: "MikroTik Backup/Upgrade" tasks: + # ---------------------------- # Always: identity + timestamp # ---------------------------- - name: Get router identity community.routeros.command: - commands: - - /system identity print + commands: /system identity print register: identity_raw tags: always - name: Parse router name ansible.builtin.set_fact: - router_name: "{{ identity_raw.stdout[0].split(': ', 1)[1] | trim }}" + router_name: "{{ identity_raw.stdout[0].split(': ')[1] | trim }}" tags: always - name: Get timestamp @@ -38,7 +38,7 @@ tags: always # ---------------------------- - # Backup + # Backup (tag: backup) # ---------------------------- - name: Ensure local backup directory exists ansible.builtin.file: @@ -50,8 +50,7 @@ - name: Export router config community.routeros.command: - commands: - - /export terse show-sensitive + commands: /export terse show-sensitive register: export_cfg tags: backup @@ -70,52 +69,57 @@ tags: backup # ---------------------------- - # Upgrade + # Upgrade (tag: upgrade) # ---------------------------- - name: Trigger update check community.routeros.command: - commands: - - /system package update check-for-updates once - register: update_trigger + commands: /system package update check-for-updates once tags: upgrade - - name: Poll update status until ready + - name: Wait before reading update info + ansible.builtin.pause: + seconds: 5 + tags: upgrade + + - name: Get update info (plain) community.routeros.command: - commands: - - /system package update print as-value + commands: /system package update print register: update_info - retries: 10 - delay: 3 - until: > - update_info.stdout is defined and - update_info.stdout | length > 0 and - update_info.stdout[0] is mapping and - update_info.stdout[0].get('status', '') != '' and - 'finding out latest version' not in (update_info.stdout[0].get('status', '') | lower) tags: upgrade - - name: Debug update info - ansible.builtin.debug: - var: update_info.stdout[0] - tags: upgrade - - - name: Parse versions + # ---------------------------- + # Parse versions (robust) + # ---------------------------- + - name: Parse installed and latest versions ansible.builtin.set_fact: - installed_version: "{{ update_info.stdout[0].get('installed-version', 'unknown') }}" - latest_version: "{{ update_info.stdout[0].get('latest-version', 'unknown') }}" - update_status: "{{ update_info.stdout[0].get('status', 'unknown') }}" - update_channel: "{{ update_info.stdout[0].get('channel', 'unknown') }}" + installed_version: "{{ update_info.stdout[0] | regex_search('installed-version: ([^\\s]+)', '\\1') | default('unknown', true) }}" + latest_version: "{{ update_info.stdout[0] | regex_search('latest-version: ([^\\s]+)', '\\1') | default('unknown', true) }}" + update_status: "{{ update_info.stdout[0] | regex_search('status: (.+)', '\\1') | default('unknown', true) }}" + update_channel: "{{ update_info.stdout[0] | regex_search('channel: ([^\\s]+)', '\\1') | default('unknown', true) }}" tags: upgrade + - name: Debug parsed update info + ansible.builtin.debug: + msg: "Router={{ router_name }} channel={{ update_channel }} installed={{ installed_version }} latest={{ latest_version }} status={{ update_status }}" + tags: upgrade + + # ---------------------------- + # Detect problems + # ---------------------------- - name: Detect update failure ansible.builtin.set_fact: - update_failed: >- - {{ - 'error' in (update_status | lower) or - 'failed' in (update_status | lower) - }} + update_failed: "{{ 'error' in update_status | lower or 'failed' in update_status | lower }}" tags: upgrade + - name: Warn if update failed + ansible.builtin.debug: + msg: "WARNING: Update check failed on {{ router_name }} (status={{ update_status }})" + when: update_failed + tags: upgrade + + # ---------------------------- + # Decide upgrade + # ---------------------------- - name: Set upgrade-needed fact ansible.builtin.set_fact: upgrade_needed: >- @@ -129,38 +133,26 @@ - name: Show decision ansible.builtin.debug: - msg: >- - Router={{ router_name }} - channel={{ update_channel }} - installed={{ installed_version }} - latest={{ latest_version }} - status={{ update_status }} - upgrade_needed={{ upgrade_needed }} - tags: upgrade - - - name: Warn if update check failed - ansible.builtin.debug: - msg: "WARNING: Update check failed on {{ router_name }} (status={{ update_status }})" - when: update_failed + msg: "Router={{ router_name }} installed={{ installed_version }} latest={{ latest_version }} upgrade_needed={{ upgrade_needed }}" tags: upgrade - name: Skip upgrade if already latest ansible.builtin.debug: - msg: "Router {{ router_name }} is already up to date ({{ installed_version }})" - when: - - not update_failed - - not upgrade_needed + msg: "Router {{ router_name }} is already on latest version {{ installed_version }}" + when: not upgrade_needed tags: upgrade - - name: Trigger package install + # ---------------------------- + # Perform upgrade + # ---------------------------- + - name: Trigger package download and install community.routeros.command: - commands: - - /system package update install + commands: /system package update install register: upgrade_result when: upgrade_needed tags: upgrade - - name: Wait for router to come back + - name: Wait for router to come back online after reboot ansible.builtin.wait_for_connection: delay: 180 timeout: 600 @@ -172,42 +164,36 @@ - name: Confirm upgraded version community.routeros.command: - commands: - - /system resource print + commands: /system resource print register: post_upgrade_info when: upgrade_needed tags: upgrade - name: Parse post-upgrade version ansible.builtin.set_fact: - post_upgrade_version: >- - {{ - post_upgrade_info.stdout[0] - | regex_search('version: ([^\\s]+)', '\\1') - | default('unknown', true) - }} + post_upgrade_version: "{{ post_upgrade_info.stdout[0] | regex_search('version: ([^\\s]+)', '\\1') | default('unknown', true) }}" when: upgrade_needed tags: upgrade - - name: Show post-upgrade version + - name: Show post-upgrade RouterOS version ansible.builtin.debug: - msg: "Router {{ router_name }} upgraded to {{ post_upgrade_version }}" + msg: "Router {{ router_name }} upgraded to version {{ post_upgrade_version }}" when: upgrade_needed tags: upgrade # ---------------------------- - # Build Checkmk result + # Build Checkmk status # ---------------------------- - name: Build Checkmk result when no upgrade was needed ansible.builtin.set_fact: cmk_state: "{{ 2 if update_failed else 0 }}" cmk_output: >- - {{ 'CRIT' if update_failed else 'OK' }} - router={{ router_name }} + {{ 'CRIT' if update_failed else 'OK' }} - + router={{ router_name }} backup=ok - channel={{ update_channel }} installed={{ installed_version }} latest={{ latest_version }} - status="{{ update_status }}" + status={{ update_status }} upgrade_needed=no backup_file={{ backup_file | default('n/a') }} backup_ts={{ ts }} @@ -218,12 +204,12 @@ ansible.builtin.set_fact: cmk_state: "{{ 0 if post_upgrade_version == latest_version else 2 }}" cmk_output: >- - {{ 'OK' if post_upgrade_version == latest_version else 'CRIT' }} - router={{ router_name }} + {{ 'OK' if post_upgrade_version == latest_version else 'CRIT' }} - + router={{ router_name }} backup=ok - channel={{ update_channel }} installed_before={{ installed_version }} latest={{ latest_version }} - status="{{ update_status }}" + status={{ update_status }} upgrade_needed=yes upgraded_to={{ post_upgrade_version }} backup_file={{ backup_file | default('n/a') }} @@ -232,7 +218,7 @@ tags: always # ---------------------------- - # Send to Checkmk + # Push result to Checkmk # ---------------------------- - name: Send result to Checkmk delegate_to: localhost