diff --git a/synology_dsm_upgrade_api.yml b/synology_dsm_upgrade_api.yml index 8ca9ab7..d130141 100644 --- a/synology_dsm_upgrade_api.yml +++ b/synology_dsm_upgrade_api.yml @@ -1,34 +1,31 @@ --- -- name: Synology DSM - déclencher une mise à jour via l'API DSM (Semaphore/legacy compatible) +- name: Synology DSM - upgrade via DSM API (Semaphore/legacy compatible) hosts: synology gather_facts: false vars: - # --- Connexion DSM --- syno_scheme: "https" syno_port: 5001 - syno_verify_ssl: false # true si certificat OK + syno_verify_ssl: false syno_user: "{{ vault_syno_user }}" syno_pass: "{{ vault_syno_pass }}" syno_session: "DSM" + uri_timeout: 60 - # --- Upgrade API --- - upgrade_check_method: "check" # parfois: "status" / "get" - upgrade_start_method: "start" - - # --- Sécurité --- refuse_if_no_upgrade_api: true - # --- Réseau --- - uri_timeout: 60 + # méthodes candidates (DSM varie) + upgrade_status_methods: + - "status" + - "get" + - "check" + upgrade_start_method: "start" tasks: - name: Construire base_url ansible.builtin.set_fact: base_url: "{{ syno_scheme }}://{{ inventory_hostname }}:{{ syno_port }}" - # 1) Découverte des APIs (paths & versions) via SYNO.API.Info - # IMPORTANT: Semaphore peut utiliser ansible.legacy.uri => pas de url_parameters. - name: Discover SYNO.API.Auth & SYNO.Core.Upgrade via SYNO.API.Info ansible.builtin.uri: url: "{{ base_url }}/webapi/entry.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth,SYNO.Core.Upgrade" @@ -49,22 +46,17 @@ ansible.builtin.fail: msg: >- L'API SYNO.Core.Upgrade n'est pas exposée sur ce NAS via /webapi. - Solution de repli: déclenchement via SSH (synoupgrade) ou mise à jour manuelle DSM. + Solution de repli: SSH (synoupgrade) ou mise à jour manuelle DSM. when: - refuse_if_no_upgrade_api | bool - (upgrade_info | length) == 0 - - name: Définir chemins et versions max + - name: Définir chemins et versions ansible.builtin.set_fact: - # Certains DSM exposent Auth via entry.cgi, d'autres via auth.cgi. - # On respecte la discovery, mais on garde des valeurs par défaut sûres. auth_path: "{{ auth_info.path | default('auth.cgi') }}" upgrade_path: "{{ upgrade_info.path | default('entry.cgi') }}" upgrade_ver: "{{ upgrade_info.maxVersion | default(1) }}" - # 2) Login -> SID - # Fix: le maxVersion retourné peut casser le login (erreur 101). - # On tente d'abord une version stable (6), puis fallback (2). - name: Login DSM API (SYNO.API.Auth) - try v6 then v2 block: - name: Login v6 @@ -81,7 +73,6 @@ - name: Set login result from v6 ansible.builtin.set_fact: login: "{{ login_v6 }}" - rescue: - name: Login v2 (fallback) ansible.builtin.uri: @@ -102,23 +93,73 @@ ansible.builtin.set_fact: sid: "{{ login.json.data.sid }}" - # 3) (Optionnel) Check update (best effort) - - name: Check DSM update readiness (best effort) + # ---- STATUS (on teste plusieurs méthodes) ---- + - name: Interroger statut upgrade (essais multiples) ansible.builtin.uri: - url: "{{ base_url }}/webapi/{{ upgrade_path }}?api=SYNO.Core.Upgrade&version={{ upgrade_ver }}&method={{ upgrade_check_method }}&_sid={{ sid }}" + url: "{{ base_url }}/webapi/{{ upgrade_path }}?api=SYNO.Core.Upgrade&version={{ upgrade_ver }}&method={{ item }}&_sid={{ sid }}" method: GET validate_certs: "{{ syno_verify_ssl }}" return_content: true status_code: 200 timeout: "{{ uri_timeout }}" - register: upgrade_check + loop: "{{ upgrade_status_methods }}" + register: upgrade_status_attempts failed_when: false - - name: Debug check result (utile pour ajuster upgrade_check_method) - ansible.builtin.debug: - var: upgrade_check.json + - name: Choisir le premier statut qui répond success=true + ansible.builtin.set_fact: + upgrade_status: >- + {{ + (upgrade_status_attempts.results + | selectattr('json', 'defined') + | selectattr('json.success', 'defined') + | selectattr('json.success', 'equalto', true) + | list + | first) | default({}) + }} + + - name: Afficher les réponses status (debug) + ansible.builtin.debug: + var: upgrade_status_attempts.results + + - name: Afficher statut retenu (debug) + ansible.builtin.debug: + var: upgrade_status.json + when: upgrade_status | length > 0 + + - name: Fail si aucune méthode status n'a fonctionné + ansible.builtin.fail: + msg: >- + Impossible de récupérer un statut upgrade via SYNO.Core.Upgrade. + Vérifie les méthodes supportées (status/get/check) sur ce DSM. + when: upgrade_status | length == 0 + + # ---- START : seulement si "ready" (on ne devine pas : on log l’état) ---- + - name: Déterminer si une mise à jour semble prête (heuristique) + ansible.builtin.set_fact: + upgrade_ready: >- + {{ + ( + (upgrade_status.json.data is defined) + and ( + (upgrade_status.json.data.ready is defined and upgrade_status.json.data.ready | bool) + or (upgrade_status.json.data.need_update is defined and upgrade_status.json.data.need_update | bool == false) + or (upgrade_status.json.data.status is defined and (upgrade_status.json.data.status|string) in ['ready','downloaded','prepared']) + ) + ) | default(false) + }} + + - name: Stop si pas prête (évite code 103) + message clair + ansible.builtin.fail: + msg: >- + DSM refuse le start (souvent code 103) car la mise à jour n’est pas "prête". + Vérifie sur DSM: Panneau de config > Mise à jour DSM : + - téléchargement terminé + - EULA/consentement accepté + - aucune upgrade en cours + Statut API (data): {{ upgrade_status.json.data | default({}) | to_nice_json }} + when: not upgrade_ready - # 4) Start upgrade - name: Start DSM upgrade (SYNO.Core.Upgrade) ansible.builtin.uri: url: "{{ base_url }}/webapi/{{ upgrade_path }}?api=SYNO.Core.Upgrade&version={{ upgrade_ver }}&method={{ upgrade_start_method }}&_sid={{ sid }}" @@ -140,7 +181,6 @@ ansible.builtin.debug: var: upgrade_start.json - # 5) Logout - name: Logout DSM API ansible.builtin.uri: url: "{{ base_url }}/webapi/{{ auth_path }}?api=SYNO.API.Auth&version=2&method=logout&session={{ syno_session | urlencode }}&_sid={{ sid }}" @@ -150,4 +190,4 @@ status_code: 200 timeout: "{{ uri_timeout }}" register: logout - failed_when: false + failed_when: false \ No newline at end of file