{% extends "base.html" %} {% block title %}QuickWin #{{ run.id }}{% endblock %} {% set STEPS = [ ("draft", "Brouillon", "#94a3b8"), ("prereq", "Pr\u00e9requis", "#00d4ff"), ("snapshot", "Snapshot", "#a78bfa"), ("patching", "Patching", "#ffcc00"), ("result", "R\u00e9sultats", "#00ff88"), ("completed", "Termin\u00e9", "#10b981"), ] %} {% set current_step_idx = namespace(val=0) %} {% for s in STEPS %}{% if s[0] == run.status %}{% set current_step_idx.val = loop.index0 %}{% endif %}{% endfor %} {% set can_modify = run.status in ('draft', 'prereq') %} {% macro qs(hp=hp_page, pp=p_page) -%} ?hp_page={{ hp }}&p_page={{ pp }}&per_page={{ per_page }}&search={{ filters.search or '' }}&status={{ filters.status or '' }}&domain={{ filters.domain or '' }} {%- endmacro %} {% block content %}
← Retour campagnes

{{ run.label }}

S{{ '%02d'|format(run.week_number) }} {{ run.year }} — Créé par {{ run.created_by_name or '?' }}

Correspondance Validations Logs
{% if msg %}
{{ msg }}
{% endif %}
{% for step_id, step_label, step_color in STEPS %} {% set idx = loop.index0 %} {% set is_current = (step_id == run.status) %} {% set is_done = (idx < current_step_idx.val) %}
{% if is_done %}✓{% else %}{{ idx + 1 }}{% endif %}
{{ step_label }}
{% if not loop.last %}
{% endif %} {% endfor %}
{% if current_step_idx.val > 0 %}
{% else %}
{% endif %} {% if current_step_idx.val < 5 %}
{% else %}
{% endif %}
{{ stats.total }}
Total
{{ stats.hprod_total }}
H-Prod
{{ stats.prod_total }}
Prod
{{ stats.patched }}
Patchés
{{ stats.failed }}
KO
{{ stats.reboot_count }}
Reboot
{% if run.status == 'draft' and scope %}

Périmètre de la campagne

Cochez les domaines et zones à inclure. Les serveurs hors périmètre seront marqués « Exclu ».

DOMAINES
{% for d in scope.domains %} {% set active = scope.dom_active.get(d, 0) %} {% set total = scope.dom_counts.get(d, 0) %} {% endfor %}
ZONES
{% for z in scope.zones %} {% set active = scope.zone_active.get(z, 0) %} {% set total = scope.zone_counts.get(z, 0) %} {% endfor %}
{% endif %} {% if run.status == 'prereq' %}

Vérification des prérequis

Vérifie : résolution DNS, SSH (PSMP/Key), Satellite/YUM, espace disque (<90%)

{{ step_hp.prereq_ok }} OK {{ step_hp.prereq_ko }} KO {{ step_hp.prereq_pending }} en attente (H-Prod)
{% if prod_ok %} {% endif %}
{% endif %} {% if run.status == 'snapshot' %}

Snapshots VM

Connexion vSphere → recherche VM → snapshot automatique. Les serveurs physiques sont ignorés (vérifier backup Commvault).

{{ step_hp.snap_ok }} fait(s) {{ step_hp.snap_pending }} en attente (H-Prod)
{% if prod_ok %} {% endif %}
Ordre vCenter : H-Prod = Senlis → Nanterre → DR | Prod = Nanterre → Senlis → DR
{% endif %} {% if run.status == 'patching' %} {% if prod_ok and stats.prod_total > 0 %} {# Alerte validations hors-prod non validées avant de patcher prod #} {% if not validations_ok %}

⚠ Validations hors-prod requises avant la production

Les non-prod suivants ne sont pas validés. Marquer leur validation dans /patching/validations avant de patcher les prods correspondants.

{% for b in validations_blockers %} {% endfor %}
ProdHors-prod bloquantStatut
{{ b.prod_hostname }} {{ b.nonprod_hostname }} {% if b.status == 'en_attente' %}En attente {% elif b.status == 'validated_ko' %}KO {% elif b.status == 'aucun_patching' %}Pas de patching {% else %}{{ b.status }}{% endif %}

{{ validations_blockers|length }} bloquant(s) — vous pouvez continuer mais il est recommandé d'obtenir les validations d'abord.

{% endif %}

Préparation Production

Avant de patcher la prod, lancez les checks prereq et snapshots sur les serveurs production.

{% endif %}

Exécution du patching

Étape 1 : Générer les commandes. Étape 2 : Vérifier. Étape 3 : Exécuter via SSH.

{% if prod_ok %}
{% endif %} {% if prod_ok %} {% endif %}
{% endif %} {% if run.status == 'result' %}

Résultats

{{ stats.patched }}
Patchés
{{ stats.failed }}
KO
{{ stats.pending }}
En attente
{{ stats.reboot_count }}
Reboot
{% endif %} {% if run.status == 'completed' %}

Campagne terminée

{{ stats.patched }} patché(s), {{ stats.failed }} KO, {{ stats.reboot_count }} reboot(s).

Télécharger le rapport
{% endif %}
{% if run.status in ('prereq','snapshot','patching','result','completed') %} {% endif %} {% if run.status in ('snapshot','patching','result','completed') %} {% endif %} {% if run.status in ('patching','result','completed') %} {% endif %} Reset
{% if not prod_ok %}

Hors-production d'abord : {{ stats.hprod_pending }} serveur(s) hprod en attente.

{% endif %} {% macro entry_table(rows, branch_label, branch_color, branch_key, page_num, total_pages, total_count) %}

{{ branch_label }} ({{ total_count }})

{{ rows|selectattr('status','eq','patched')|list|length }} OK {{ rows|selectattr('status','eq','failed')|list|length }} KO {{ rows|selectattr('status','eq','pending')|list|length }} en attente {% if can_modify %} {% endif %}
{% if can_modify %}{% endif %} {% if run.status in ('prereq','snapshot','patching','result','completed') %} {% endif %} {% if run.status in ('snapshot','patching','result','completed') %} {% endif %} {% if run.status == 'patching' %} {% endif %} {% for e in rows %} {% if can_modify %}{% endif %} {% if run.status in ('prereq','snapshot','patching','result','completed') %} {% endif %} {% if run.status in ('snapshot','patching','result','completed') %} {% endif %} {% if run.status == 'patching' %} {% endif %} {% endfor %} {% if not rows %}{% endif %}
Serveur Domaine Env StatutPrereqSnapExclusions gén. Exclusions spéc. Packages Date patch Reboot NotesAction
{{ e.hostname }} {{ e.domaine or '?' }} {{ e.environnement or '?' }} {% if e.status == 'patched' %}Patché {% elif e.status == 'failed' %}KO {% elif e.status == 'in_progress' %}En cours {% elif e.status == 'excluded' %}Exclu {% elif e.status == 'skipped' %}Ignoré {% else %}En attente{% endif %} {% if e.prereq_ok == true %} {% elif e.prereq_ok == false %} {% else %}{% endif %} {% if e.snap_done %} {% else %} {% if run.status == 'snapshot' %}
{% else %}{% endif %} {% endif %}
{{ e.general_excludes or '—' }} {{ e.specific_excludes or '—' }} {{ e.patch_packages_count or '—' }} {{ e.patch_date.strftime('%d/%m %H:%M') if e.patch_date else '—' }} {% if e.reboot_required %}OUI{% else %}—{% endif %} {{ e.notes or '—' }} {% if e.status == 'pending' and e.prereq_ok and e.snap_done %}
{% endif %}
Aucun serveur{% if filters.search or filters.status or filters.domain %} (filtre actif){% endif %}
{% if total_pages > 1 %}
Page {{ page_num }} / {{ total_pages }} — {{ total_count }} serveur(s)
{% if branch_key == 'hp' %} {% if page_num > 1 %}Préc.{% endif %} {% if page_num < total_pages %}Suiv.{% endif %} {% else %} {% if page_num > 1 %}Préc.{% endif %} {% if page_num < total_pages %}Suiv.{% endif %} {% endif %}
{% endif %}
{% endmacro %} {{ entry_table(hprod, "HORS-PRODUCTION", "#00d4ff", "hp", hp_page, hp_total_pages, hprod_total) }} {% if prod_ok %} {{ entry_table(prod, "PRODUCTION", "#ffcc00", "pr", p_page, p_total_pages, prod_total) }} {% endif %} {% if run.notes %}

NOTES

{{ run.notes }}

{% endif %} {% endblock %}