diff --git a/CHANGELOG.md b/CHANGELOG.md index 5daa142..8658a8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # CHANGELOG — Set-OPS +## 2026-10-04 (74) — Un dépôt verrouillé n'est plus une panne + +**Constaté en vérifiant (73)** : lancées ensemble sur `web-dorsal-01`, la vérification du +dépôt et le contrôle de restauration se sont gênés. Le `restic check` tenait le verrou +exclusif, et la sonde a rapporté « AUCUN INSTANTANE lisible » (critique) pendant 20 s. Les +minuteurs peuvent faire de même sans personne : `Persistent=true` rattrape au démarrage tout +ce qui a été manqué, d'un coup, et le contrôle du dimanche (04:00 + jusqu'à 60 min) peut +croiser la vérification de 05:00. restic refuse aussitôt un dépôt verrouillé ; la sonde +concluait à l'absence, ou le contrôle à la corruption. + +**Fait** (`client_backup`) : les quatre scripts qui touchent au dépôt (sauvegarde, +vérification, contrôle de restauration, `setops-restaurer`) appellent restic à travers une +fonction qui ajoute `--retry-lock {{ client_backup_attente_verrou }}` (30 min par défaut ; +le plus long des occupants est le contrôle de restauration). Les unités sont `oneshot`, sans +délai d'expiration : l'attente n'est pas coupée. + +**Éprouvé** sur un dépôt jetable (`/var/tmp`, `web-dorsal-01` de Technolibre, retiré +ensuite), le verrou tenu par un vrai processus restic, scripts rendus avec le rapport +remplacé par un `echo` : + +| | sans attente | avec attente | +|---|---|---| +| contrôle de restauration face à un verrou partagé (`backup` en cours) | critique « DEPOT CORROMPU OU ILLISIBLE », 0 s | attend 17 s, puis vérifie | +| vérification du dépôt face à un verrou exclusif (`check` en cours) | critique « AUCUN INSTANTANE lisible », 1 s | attend, puis « OK », 8 s | + +Deux essais d'abord ne prouvaient rien et ont été écartés : un dépôt vide se vérifie trop vite +pour qu'un verrou dure, et `backup --dry-run` n'en pose aucun. + +**Validation** : `--syntax-check` de `client_backup.yml`, `ansible-lint` (0 violation). + ## 2026-10-04 (73) — Un instantané vide dit pourquoi **Demande de l'exploitant** : l'avertissement convient quand il n'y a rien à sauvegarder ; diff --git a/roles/client_backup/defaults/main.yml b/roles/client_backup/defaults/main.yml index 88fe549..95589b5 100644 --- a/roles/client_backup/defaults/main.yml +++ b/roles/client_backup/defaults/main.yml @@ -133,6 +133,11 @@ client_backup_restauration_part: "10%" # nouvelle, Icinga passe le service au rouge (voir `serveur_icinga_fraicheur_restauration`). client_backup_ttl_restauration: 691200 +# Combien de temps un script attend un depot verrouille par un autre (`restic --retry-lock`) +# avant d'echouer. Le plus long des occupants est le controle de restauration ; il relit +# 10 % du depot et le restaure entier. +client_backup_attente_verrou: "30m" + # --- LA RESTAURATION DANS LA RECONSTRUCTION (2026-09-30) ---------------------------- # # Jusqu'ici une reconstruction repartait d'un etat NEUF : les instantanes se restauraient diff --git a/roles/client_backup/templates/restaurer.sh.j2 b/roles/client_backup/templates/restaurer.sh.j2 index 7b01843..c67715e 100644 --- a/roles/client_backup/templates/restaurer.sh.j2 +++ b/roles/client_backup/templates/restaurer.sh.j2 @@ -39,6 +39,12 @@ set -euo pipefail export RESTIC_REPOSITORY="{{ client_backup_repo }}" export RESTIC_PASSWORD_FILE="/etc/setops/restic.pass" +# UN VERROU N'EST PAS UNE PANNE (2026-10-04). La sauvegarde, la verification du depot, le +# controle de restauration et `setops-restaurer` partagent ce depot ; leurs minuteurs peuvent +# partir ensemble (`Persistent=true` rattrape au demarrage tout ce qui a ete manque). Sans +# attente, restic refuse aussitot un depot verrouille, et une sonde concluait « aucun +# instantane » ou « depot corrompu ». On attend le verrou au lieu de conclure. +restic() { command restic --retry-lock {{ client_backup_attente_verrou }} "$@"; } MOI="{{ inventory_hostname }}" MARQUES="{{ client_backup_restauration_marques }}" MISE_DE_COTE="{{ client_backup_restauration_mise_de_cote }}" diff --git a/roles/client_backup/templates/sauvegarder.sh.j2 b/roles/client_backup/templates/sauvegarder.sh.j2 index 27f8aed..602b2b2 100644 --- a/roles/client_backup/templates/sauvegarder.sh.j2 +++ b/roles/client_backup/templates/sauvegarder.sh.j2 @@ -4,6 +4,12 @@ set -euo pipefail export RESTIC_REPOSITORY="{{ client_backup_repo }}" export RESTIC_PASSWORD_FILE="/etc/setops/restic.pass" +# UN VERROU N'EST PAS UNE PANNE (2026-10-04). La sauvegarde, la verification du depot, le +# controle de restauration et `setops-restaurer` partagent ce depot ; leurs minuteurs peuvent +# partir ensemble (`Persistent=true` rattrape au demarrage tout ce qui a ete manque). Sans +# attente, restic refuse aussitot un depot verrouille, et une sonde concluait « aucun +# instantane » ou « depot corrompu ». On attend le verrou au lieu de conclure. +restic() { command restic --retry-lock {{ client_backup_attente_verrou }} "$@"; } # 0. UN ETAT D'AVANT ATTEND-IL ? (2026-09-30) # Sur une machine reconstruite, tant que l'etat de l'incarnation precedente n'a ete ni diff --git a/roles/client_backup/templates/verifier-mon-depot.sh.j2 b/roles/client_backup/templates/verifier-mon-depot.sh.j2 index 2fe8862..16735fb 100644 --- a/roles/client_backup/templates/verifier-mon-depot.sh.j2 +++ b/roles/client_backup/templates/verifier-mon-depot.sh.j2 @@ -14,6 +14,12 @@ set -uo pipefail export RESTIC_PASSWORD_FILE="/etc/setops/restic.pass" +# UN VERROU N'EST PAS UNE PANNE (2026-10-04). La sauvegarde, la verification du depot, le +# controle de restauration et `setops-restaurer` partagent ce depot ; leurs minuteurs peuvent +# partir ensemble (`Persistent=true` rattrape au demarrage tout ce qui a ete manque). Sans +# attente, restic refuse aussitot un depot verrouille, et une sonde concluait « aucun +# instantane » ou « depot corrompu ». On attend le verrou au lieu de conclure. +restic() { command restic --retry-lock {{ client_backup_attente_verrou }} "$@"; } export RESTIC_REPOSITORY="{{ client_backup_repo }}" API="https://{{ client_backup_icinga_hote }}.{{ domaine_interne }}:5665" TTL={{ client_backup_ttl_icinga }} diff --git a/roles/client_backup/templates/verifier-restauration.sh.j2 b/roles/client_backup/templates/verifier-restauration.sh.j2 index f145d2e..8350a9f 100644 --- a/roles/client_backup/templates/verifier-restauration.sh.j2 +++ b/roles/client_backup/templates/verifier-restauration.sh.j2 @@ -19,6 +19,12 @@ set -uo pipefail export RESTIC_PASSWORD_FILE="/etc/setops/restic.pass" +# UN VERROU N'EST PAS UNE PANNE (2026-10-04). La sauvegarde, la verification du depot, le +# controle de restauration et `setops-restaurer` partagent ce depot ; leurs minuteurs peuvent +# partir ensemble (`Persistent=true` rattrape au demarrage tout ce qui a ete manque). Sans +# attente, restic refuse aussitot un depot verrouille, et une sonde concluait « aucun +# instantane » ou « depot corrompu ». On attend le verrou au lieu de conclure. +restic() { command restic --retry-lock {{ client_backup_attente_verrou }} "$@"; } export RESTIC_REPOSITORY="{{ client_backup_repo }}" API="https://{{ client_backup_icinga_hote }}.{{ domaine_interne }}:5665" TTL={{ client_backup_ttl_restauration }}