Actualiser synology_upgrade_ssh.yml

This commit is contained in:
l.covela 2026-01-07 11:53:25 +01:00
parent 85ca17af4b
commit 1d9060d137
1 changed files with 93 additions and 41 deletions

View File

@ -1,34 +1,86 @@
--- ---
- name: Synology DSM - télécharger puis installer une mise à jour via SSH (synoupgrade) - name: Synology DSM - télécharger puis installer une mise à jour via SSH (auto-detect synoupgrade)
hosts: synology hosts: synology
gather_facts: false gather_facts: false
vars: vars:
# Chemin habituel sur Synology
synoupgrade_bin: "/usr/syno/sbin/synoupgrade"
# Temps max (en secondes) pour attendre download / reboot # Temps max (en secondes) pour attendre download / reboot
download_timeout: 3600 download_timeout: 3600
reboot_timeout: 1200 reboot_timeout: 1800
poll_delay: 20 poll_delay: 20
# Certaines versions DSM n'ont pas exactement les mêmes options, # Chemins probables (DSM varie selon versions/modèles)
# on essaie plusieurs commandes possibles pour démarrer l'upgrade. synoupgrade_candidates:
upgrade_start_cmds: - "/usr/syno/sbin/synoupgrade"
- "{{ synoupgrade_bin }} --start" - "/usr/syno/bin/synoupgrade"
- "{{ synoupgrade_bin }} --upgrade" - "/sbin/synoupgrade"
- "{{ synoupgrade_bin }} --apply" - "/bin/synoupgrade"
- "{{ synoupgrade_bin }} --run" - "/usr/bin/synoupgrade"
- "{{ synoupgrade_bin }} --install" - "/usr/sbin/synoupgrade"
- "/usr/syno/sbin/synoupgrade2"
- "/usr/syno/bin/synoupgrade2"
- "/usr/bin/synoupgrade2"
- "/usr/sbin/synoupgrade2"
# Commandes possibles pour lancer linstall (selon DSM)
start_subcommands:
- "--start"
- "--upgrade"
- "--apply"
- "--run"
- "--install"
tasks: tasks:
- name: Vérifier que synoupgrade existe # 0) Détecter le binaire présent
ansible.builtin.raw: "test -x {{ synoupgrade_bin }} && echo OK || echo MISSING" - name: Détecter synoupgrade (ou synoupgrade2) sur le NAS
register: synoupgrade_exists ansible.builtin.raw: |
changed_when: false set -e
failed_when: "'MISSING' in synoupgrade_exists.stdout" FOUND=""
for p in {{ synoupgrade_candidates | join(' ') }}; do
if [ -x "$p" ]; then
FOUND="$p"
break
fi
done
- name: Check mise à jour disponible (synoupgrade --check) # fallback: PATH (busybox)
if [ -z "$FOUND" ]; then
if command -v synoupgrade >/dev/null 2>&1; then
FOUND="$(command -v synoupgrade)"
elif command -v synoupgrade2 >/dev/null 2>&1; then
FOUND="$(command -v synoupgrade2)"
fi
fi
if [ -n "$FOUND" ]; then
echo "FOUND=$FOUND"
exit 0
else
echo "FOUND="
exit 0
fi
register: detect
changed_when: false
- name: Enregistrer le chemin synoupgrade détecté
ansible.builtin.set_fact:
synoupgrade_bin: "{{ (detect.stdout | regex_search('FOUND=(.*)', '\\1')) | default('') | trim }}"
changed_when: false
- name: Fail si synoupgrade introuvable
ansible.builtin.fail:
msg: >-
synoupgrade introuvable sur ce NAS (DSM/ modèle).
stdout: {{ detect.stdout | default('') }}
=> Donne-moi la sortie de : "ls -l /usr/syno/sbin /usr/syno/bin | grep -i upgrad"
when: synoupgrade_bin == ""
- name: Afficher le binaire trouvé
ansible.builtin.debug:
msg: "synoupgrade utilisé: {{ synoupgrade_bin }}"
# 1) Check mise à jour dispo
- name: Check mise à jour disponible
ansible.builtin.raw: "{{ synoupgrade_bin }} --check || true" ansible.builtin.raw: "{{ synoupgrade_bin }} --check || true"
register: check_out register: check_out
changed_when: false changed_when: false
@ -37,16 +89,17 @@
ansible.builtin.debug: ansible.builtin.debug:
var: check_out.stdout_lines var: check_out.stdout_lines
# Heuristique : si "no update" / "no newer version" etc, on stop proprement. # Heuristique : stop si rien
- name: Stop si aucune mise à jour détectée (heuristique) - name: Stop si aucune mise à jour détectée (heuristique)
ansible.builtin.meta: end_play ansible.builtin.meta: end_play
when: > when: >
(check_out.stdout | lower) is search('no update') (check_out.stdout | lower) is search('no update')
or (check_out.stdout | lower) is search('no newer') 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('already')
or (check_out.stdout | lower) is search('up to date') or (check_out.stdout | lower) is search('up to date')
- name: Lancer le téléchargement (synoupgrade --download) # 2) Download
- name: Lancer le téléchargement
ansible.builtin.raw: "{{ synoupgrade_bin }} --download" ansible.builtin.raw: "{{ synoupgrade_bin }} --download"
register: download_start register: download_start
changed_when: true changed_when: true
@ -55,17 +108,15 @@
ansible.builtin.debug: ansible.builtin.debug:
var: download_start.stdout_lines var: download_start.stdout_lines
# Suivi du téléchargement : selon DSM, --status peut exister ou pas. # 3) Attendre fin download (status ou log)
# 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) - name: Attendre fin du téléchargement (poll status/log)
ansible.builtin.raw: | ansible.builtin.raw: |
set -e set -e
if {{ synoupgrade_bin }} --status >/dev/null 2>&1; then if {{ synoupgrade_bin }} --status >/dev/null 2>&1; then
{{ synoupgrade_bin }} --status || true {{ synoupgrade_bin }} --status || true
else else
# fallback log courant (chemins variables selon DSM) (tail -n 80 /var/log/synoupgrade.log 2>/dev/null || true)
(tail -n 60 /var/log/synoupgrade.log 2>/dev/null || true) (tail -n 120 /var/log/messages 2>/dev/null | grep -i upgrad || true)
(tail -n 60 /var/log/messages 2>/dev/null | grep -i synoupgrade || true)
fi fi
register: dl_poll register: dl_poll
changed_when: false changed_when: false
@ -82,30 +133,31 @@
ansible.builtin.debug: ansible.builtin.debug:
var: dl_poll.stdout_lines var: dl_poll.stdout_lines
# Démarrage de l'upgrade : on teste plusieurs commandes. # 4) Démarrer installation (essais)
- name: Démarrer l'installation DSM (essais multi-commandes) - name: Tenter de démarrer l'installation (plusieurs sous-commandes)
ansible.builtin.raw: "{{ item }}" ansible.builtin.raw: "{{ synoupgrade_bin }} {{ item }} || true"
loop: "{{ upgrade_start_cmds }}" loop: "{{ start_subcommands }}"
register: start_attempts register: start_attempts
changed_when: true changed_when: true
failed_when: false failed_when: false
- name: Choisir la première commande start qui a l'air OK - name: Choisir la première tentative qui ne ressemble pas à une erreur
ansible.builtin.set_fact: ansible.builtin.set_fact:
start_ok: >- start_ok: >-
{{ {{
(start_attempts.results (start_attempts.results
| rejectattr('stdout', 'search', '(?i)(invalid|unknown|usage|not found|error)') | rejectattr('stdout', 'search', '(?i)(invalid|unknown|usage|not found|permission|error|failed)')
| rejectattr('stderr', 'search', '(?i)(invalid|unknown|usage|not found|permission|error|failed)')
| list | list
| first) | default({}) | first) | default({})
}} }}
- name: Fail si aucune commande start ne fonctionne - name: Fail si aucune commande de démarrage ne marche
ansible.builtin.fail: ansible.builtin.fail:
msg: >- msg: >-
Impossible de démarrer l'installation via synoupgrade. Impossible de démarrer l'installation via synoupgrade.
Sorties: stdout: {{ start_attempts.results | map(attribute='stdout') | list }}
{{ start_attempts.results | map(attribute='stdout') | list }} stderr: {{ start_attempts.results | map(attribute='stderr') | list }}
when: start_ok | length == 0 when: start_ok | length == 0
- name: Afficher la commande start retenue - name: Afficher la commande start retenue
@ -115,9 +167,8 @@
- "stdout: {{ start_ok.stdout | default('') }}" - "stdout: {{ start_ok.stdout | default('') }}"
- "stderr: {{ start_ok.stderr | default('') }}" - "stderr: {{ start_ok.stderr | default('') }}"
# Beaucoup de Synology rebootent pendant/après lupgrade. # 5) Attente reboot : le NAS peut couper SSH
# On attend que SSH tombe puis revienne. - name: Attendre que le NAS coupe SSH (reboot probable)
- name: Attendre que le NAS coupe SSH (reboot en cours)
ansible.builtin.wait_for: ansible.builtin.wait_for:
host: "{{ inventory_hostname }}" host: "{{ inventory_hostname }}"
port: 22 port: 22
@ -125,7 +176,7 @@
timeout: 300 timeout: 300
delegate_to: localhost delegate_to: localhost
- name: Attendre le retour SSH (après reboot) - name: Attendre le retour SSH
ansible.builtin.wait_for: ansible.builtin.wait_for:
host: "{{ inventory_hostname }}" host: "{{ inventory_hostname }}"
port: 22 port: 22
@ -133,7 +184,8 @@
timeout: "{{ reboot_timeout }}" timeout: "{{ reboot_timeout }}"
delegate_to: localhost delegate_to: localhost
- name: Re-check version / statut après reboot (best effort) # 6) Post-check
- name: Post-check version / statut
ansible.builtin.raw: | ansible.builtin.raw: |
uname -a || true uname -a || true
cat /etc/VERSION 2>/dev/null || true cat /etc/VERSION 2>/dev/null || true