--- - name: Synology DSM - télécharger puis installer une mise à jour via SSH (synoupgrade) hosts: synology gather_facts: false vars: # Chemin habituel sur Synology synoupgrade_bin: "/usr/syno/sbin/synoupgrade" # Temps max (en secondes) pour attendre download / reboot download_timeout: 3600 reboot_timeout: 1200 poll_delay: 20 # Certaines versions DSM n'ont pas exactement les mêmes options, # on essaie plusieurs commandes possibles pour démarrer l'upgrade. upgrade_start_cmds: - "{{ synoupgrade_bin }} --start" - "{{ synoupgrade_bin }} --upgrade" - "{{ synoupgrade_bin }} --apply" - "{{ synoupgrade_bin }} --run" - "{{ synoupgrade_bin }} --install" tasks: - name: Vérifier que synoupgrade existe ansible.builtin.raw: "test -x {{ synoupgrade_bin }} && echo OK || echo MISSING" register: synoupgrade_exists changed_when: false failed_when: "'MISSING' in synoupgrade_exists.stdout" - name: Check mise à jour disponible (synoupgrade --check) ansible.builtin.raw: "{{ synoupgrade_bin }} --check || true" register: check_out changed_when: false - name: Afficher le résultat du check ansible.builtin.debug: var: check_out.stdout_lines # Heuristique : si "no update" / "no newer version" etc, on stop proprement. - name: Stop si aucune mise à jour détectée (heuristique) ansible.builtin.meta: end_play when: > (check_out.stdout | lower) is search('no update') or (check_out.stdout | lower) is search('no newer') or (check_out.stdout | lower) is search('already up') or (check_out.stdout | lower) is search('up to date') - name: Lancer le téléchargement (synoupgrade --download) ansible.builtin.raw: "{{ synoupgrade_bin }} --download" register: download_start changed_when: true - name: Afficher retour download start ansible.builtin.debug: var: download_start.stdout_lines # Suivi du téléchargement : selon DSM, --status peut exister ou pas. # On fait un poll best-effort sur --status, sinon on se base sur le log. - name: Attendre fin du téléchargement (poll status/log) ansible.builtin.raw: | set -e if {{ synoupgrade_bin }} --status >/dev/null 2>&1; then {{ synoupgrade_bin }} --status || true else # fallback log courant (chemins variables selon DSM) (tail -n 60 /var/log/synoupgrade.log 2>/dev/null || true) (tail -n 60 /var/log/messages 2>/dev/null | grep -i synoupgrade || true) fi register: dl_poll changed_when: false until: > (dl_poll.stdout | lower) is search('downloaded') or (dl_poll.stdout | lower) is search('ready') or (dl_poll.stdout | lower) is search('finish') or (dl_poll.stdout | lower) is search('completed') or (dl_poll.stdout | lower) is search('done') retries: "{{ (download_timeout // poll_delay) | int }}" delay: "{{ poll_delay }}" - name: Afficher statut fin téléchargement ansible.builtin.debug: var: dl_poll.stdout_lines # Démarrage de l'upgrade : on teste plusieurs commandes. - name: Démarrer l'installation DSM (essais multi-commandes) ansible.builtin.raw: "{{ item }}" loop: "{{ upgrade_start_cmds }}" register: start_attempts changed_when: true failed_when: false - name: Choisir la première commande start qui a l'air OK ansible.builtin.set_fact: start_ok: >- {{ (start_attempts.results | rejectattr('stdout', 'search', '(?i)(invalid|unknown|usage|not found|error)') | list | first) | default({}) }} - name: Fail si aucune commande start ne fonctionne ansible.builtin.fail: msg: >- Impossible de démarrer l'installation via synoupgrade. Sorties: {{ start_attempts.results | map(attribute='stdout') | list }} when: start_ok | length == 0 - name: Afficher la commande start retenue ansible.builtin.debug: msg: - "Commande retenue: {{ start_ok.item }}" - "stdout: {{ start_ok.stdout | default('') }}" - "stderr: {{ start_ok.stderr | default('') }}" # Beaucoup de Synology rebootent pendant/après l’upgrade. # On attend que SSH tombe puis revienne. - name: Attendre que le NAS coupe SSH (reboot en cours) ansible.builtin.wait_for: host: "{{ inventory_hostname }}" port: 22 state: drained timeout: 300 delegate_to: localhost - name: Attendre le retour SSH (après reboot) ansible.builtin.wait_for: host: "{{ inventory_hostname }}" port: 22 state: started timeout: "{{ reboot_timeout }}" delegate_to: localhost - name: Re-check version / statut après reboot (best effort) ansible.builtin.raw: | uname -a || true cat /etc/VERSION 2>/dev/null || true {{ synoupgrade_bin }} --status 2>/dev/null || true register: post changed_when: false - name: Afficher post-check ansible.builtin.debug: var: post.stdout_lines