Update mikrotikbackup_clean.yml

This commit is contained in:
2026-09-24 17:55:18 +00:00
parent 87150f8cd9
commit 00b56a7c06
+120 -76
View File
@@ -1,151 +1,195 @@
---
- name: Backup and/or Upgrade MikroTik
hosts: mikrotik_routers
gather_facts: no
gather_facts: false
vars:
backup_dir: /opt/mikrotik_backups/
ansible_connection: ansible.netcommon.network_cli
ansible_network_os: community.routeros.routeros
ansible_connect_timeout: 60
ansible_command_timeout: 60
upgrade_command_timeout: 600
upgrade_reconnect_timeout: 600
upgrade_verify_retries: 40
upgrade_verify_delay: 15
tasks:
# ----------------------------
# Always: identity + timestamp
# ----------------------------
- name: Get router identity
community.routeros.command:
commands: /system identity print
register: identity_raw
changed_when: false
tags: always
- name: Parse router name
set_fact:
router_name: "{{ identity_raw.stdout[0].split(': ')[1] | trim }}"
ansible.builtin.set_fact:
router_name: "{{ identity_raw.stdout[0].split(': ', 1)[1] | trim }}"
tags: always
- name: Get timestamp
ansible.builtin.command: date +%Y-%m-%d_%H-%M-%S
register: date_out
delegate_to: localhost
vars:
ansible_connection: local
changed_when: false
tags: always
- name: Set timestamp fact
set_fact:
ansible.builtin.set_fact:
ts: "{{ date_out.stdout }}"
tags: always
# ----------------------------
# Backup (tag: backup)
# ----------------------------
- name: Back up router configuration
tags: [backup, never]
block:
- name: Ensure local backup directory exists
ansible.builtin.file:
path: "{{ backup_dir }}"
state: directory
mode: "0755"
delegate_to: localhost
tags: [backup, never]
vars:
ansible_connection: local
- name: Export router config
community.routeros.command:
commands: /export terse show-sensitive
register: export_cfg
tags: [backup, never]
changed_when: false
no_log: true
- name: Save export locally
ansible.builtin.copy:
content: "{{ export_cfg.stdout[0] }}"
dest: "{{ backup_dir }}/{{ router_name }}-{{ ts }}.rsc"
mode: "0600"
delegate_to: localhost
tags: [backup, never]
vars:
ansible_connection: local
no_log: true
# ----------------------------
# Upgrade (tag: upgrade)
# ----------------------------
- name: Check and upgrade RouterOS packages
tags: [upgrade, never]
when: not ansible_check_mode
block:
- name: Check current and latest available package versions
community.routeros.command:
commands: /system package update check-for-updates
register: update_check
tags: [upgrade, never]
changed_when: false
- name: Normalize update output
set_fact:
ansible.builtin.set_fact:
_update_text: "{{ update_check.stdout[0] | replace('\r', '') }}"
tags: [upgrade, never]
- name: Debug raw update output
ansible.builtin.debug:
msg: "{{ _update_text }}"
tags: [upgrade, never]
- name: Parse installed and latest versions
set_fact:
ansible.builtin.set_fact:
installed_version: >-
{{
(_update_text | regex_findall('(?:installed|current)-version:[ ]*([0-9A-Za-z.]+)'))[0]
if (_update_text | regex_findall('(?:installed|current)-version:[ ]*([0-9A-Za-z.]+)'))
else 'unknown'
}}
{{ (_update_text | regex_findall('(?:installed|current)-version:[ \t]*([0-9][0-9A-Za-z.-]*)')
| first) | default('unknown') }}
latest_version: >-
{{
(_update_text | regex_findall('(?:latest|newest)-version:[ ]*([0-9A-Za-z.]+)'))[0]
if (_update_text | regex_findall('(?:latest|newest)-version:[ ]*([0-9A-Za-z.]+)'))
else 'unknown'
}}
tags: [upgrade, never]
{{ (_update_text | regex_findall('(?:latest|newest)-version:[ \t]*([0-9][0-9A-Za-z.-]*)')
| first) | default('unknown') }}
- name: Fail if versions could not be parsed
ansible.builtin.fail:
msg: >
Could not parse versions from update output.
Raw text was: {{ _update_text }}
when: installed_version == 'unknown' or latest_version == 'unknown'
tags: [upgrade, never]
- name: Require valid versions before attempting an upgrade
ansible.builtin.assert:
that:
- installed_version != 'unknown'
- latest_version != 'unknown'
fail_msg: "Could not parse versions from update output: {{ _update_text }}"
- name: Debug parsed versions
- name: Show installed and available versions
ansible.builtin.debug:
msg:
- "Installed: {{ installed_version }}"
- "Latest: {{ latest_version }}"
tags: [upgrade, never]
msg: "{{ router_name }}: installed={{ installed_version }}, available={{ latest_version }}"
- name: Skip upgrade if already on latest
ansible.builtin.debug:
msg: "Router {{ router_name }} is already on latest version {{ installed_version }}. Skipping upgrade."
msg: "{{ router_name }} is already on {{ installed_version }}. Skipping upgrade."
when: installed_version == latest_version
tags: [upgrade, never]
- name: Install and verify the available version
when: installed_version != latest_version
block:
- name: Reset persistent connection before installation
ansible.builtin.meta: reset_connection
- name: Request package installation
block:
- name: Trigger package download and install
community.routeros.command:
commands: /system package update install
vars:
ansible_command_timeout: 60
when: installed_version != latest_version
ignore_errors: true
tags: [upgrade, never]
ansible_command_timeout: "{{ upgrade_command_timeout }}"
register: install_result
- name: Wait before reconnecting after reboot
ansible.builtin.pause:
seconds: 30
when: installed_version != latest_version
tags: [upgrade, never]
rescue:
# A reboot can interrupt the command response. This is NOT
# success: the mandatory version check below decides the result.
- name: Record installation error for final verification
ansible.builtin.debug:
msg: >-
Installation returned an error: {{ install_result.msg | default('Unknown error') }}.
The command may or may not have reached the router.
Continuing only to verify the actual installed version.
- name: Wait for router to come back online after reboot
community.routeros.command:
commands: /system resource print
register: reboot_wait
until: reboot_wait is succeeded
retries: 20
delay: 15
when: installed_version != latest_version
tags: [upgrade, never]
always:
- name: Discard the installation connection
ansible.builtin.meta: reset_connection
- name: Confirm upgraded version
# This readiness check does not claim that a reboot occurred.
# The exact version comparison below is the success criterion.
- name: Wait for SSH availability from Semaphore
ansible.builtin.wait_for:
host: >-
{{ hostvars[inventory_hostname].ansible_host
| default(hostvars[inventory_hostname].ansible_ssh_host)
| default(inventory_hostname) }}
port: >-
{{ hostvars[inventory_hostname].ansible_port
| default(hostvars[inventory_hostname].ansible_ssh_port)
| default(22) }}
state: started
search_regex: SSH-
delay: 30
sleep: 5
connect_timeout: 5
timeout: "{{ upgrade_reconnect_timeout }}"
delegate_to: localhost
vars:
ansible_connection: local
changed_when: false
- name: Reset persistent connection before verification
ansible.builtin.meta: reset_connection
- name: Verify the installed version
block:
- name: Wait until the router reports the expected version
community.routeros.command:
commands: /system resource print
register: post_upgrade_info
when: installed_version != latest_version
tags: [upgrade, never]
changed_when: false
until:
- post_upgrade_info is succeeded
- >-
((post_upgrade_info.stdout | default(['']) | first
| regex_findall('(?m)^\s*version:[ \t]*([0-9][0-9A-Za-z.-]*)')
| first) | default('unknown')) == latest_version
retries: "{{ upgrade_verify_retries }}"
delay: "{{ upgrade_verify_delay }}"
- name: Show post-upgrade RouterOS version
rescue:
- name: Fail if the expected RouterOS version could not be verified
ansible.builtin.fail:
msg: >-
Upgrade NOT verified for {{ router_name }}.
Previous={{ installed_version }}; expected={{ latest_version }}.
Last router response={{ post_upgrade_info.stdout | default([]) }}.
Verification error={{ post_upgrade_info.msg | default('Version mismatch') }}.
Install error={{ install_result.msg | default('No module error reported') }}.
- name: Report verified upgrade
ansible.builtin.debug:
msg: "{{ post_upgrade_info.stdout[0] | regex_search('version: .+') }}"
when: installed_version != latest_version
tags: [upgrade, never]
msg: "{{ router_name }}: verified RouterOS {{ installed_version }} -> {{ latest_version }}."