Files
ROMFASTSQL/proxmox/vm109-windows-dr/scripts/check_servicing.ps1
Marius 94758421c5 fix(dr): Windows Update rebota VM 109 in mijlocul testului DR
Testul DR din 2026-08-08 a raportat "Restore failed" dupa 11 secunde, fara
niciun log RMAN. Cauza nu a fost restore-ul: KB5101001 fusese descarcat in
timpul testului din 2026-08-01 (singurul moment in care VM 109 e pornit),
a ramas staged dupa qm stop si s-a finalizat la boot-ul testului urmator.

Cronologie din Event Log-ul guest-ului:
  06:00:58  RestartManager 10010 - nu poate reporni powershell.exe (restore-ul)
  06:01:04  SCM 7034 - OpenSSH SSH Server terminat neasteptat
  06:01:06  pveelite: client_loop: send disconnect: Broken pipe -> FAILED
  06:01:38  VM-ul se reboteaza singur

Fereastra testului (Sambata 06:00) era in afara Active Hours (08:00-17:00),
deci pentru Windows era fereastra de mentenanta valida - iar VM 109 fiind
pornit doar in timpul testului, aceea era singura fereastra posibila.
Agravant: sshd nu avea acsiuni de recovery (RESET_PERIOD 0), deci dupa ce a
murit a ramas mort si au esuat si colectarea logului si shutdown-ul gratios.

Masuri:
- NoAutoUpdate=1 + AUOptions=2 pe VM 109 (aplicat direct in registry)
- actiuni de recovery pentru sshd: restart la 5s/10s/30s, reset=86400
- guard "STEP 3b: Windows servicing" inainte de restore (check_servicing.ps1):
  asteapta idle 300s, consuma controlat un reboot in asteptare, altfel
  abandoneaza cu "ABORTED - Windows servicing" in loc de un "Restore failed"
  inselator. Fail-open daca checkul lipseste - nu are voie sa pice testul.
- fereastra lunara de patching (vm109-patch-window.sh + install_updates.ps1),
  prima duminica 03:00, cu re-armare NoAutoUpdate=1 indiferent de rezultat

Adaugat si .gitattributes: cu core.autocrlf=true scripturile .sh ajungeau in
working tree cu CRLF, iar ele se deployeaza prin scp direct pe Proxmox.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BhQBTegE4PiMPPaapLHjkc
2026-08-08 16:56:24 +03:00

73 lines
2.9 KiB
PowerShell

# check_servicing.ps1 — raportează dacă stack-ul de servicing Windows este activ.
#
# De ce există: incident 2026-08-08. KB5101001 a fost descărcat în timpul testului
# DR din 2026-08-01 (singurul moment în care VM 109 este pornit), a rămas staged
# după `qm stop`, și s-a finalizat la următorul boot — adică exact la testul
# următor. RestartManager a omorât procesul powershell.exe care rula restore-ul
# (event 10010), apoi sshd (SCM 7034), iar VM-ul a rebootat la 72s după boot.
# Testul a raportat "Restore failed" fără niciun log RMAN, deși RMAN nici măcar
# nu apucase să pornească.
#
# Ieșire (o singură linie, parsabilă din bash):
# STATE=IDLE
# STATE=BUSY REBOOT_PENDING=<bool> REASONS=<listă separată prin virgulă>
#
# Cod de ieșire: 0 = IDLE, 1 = BUSY. Nu aruncă niciodată excepții — un check
# care crapă nu are voie să pice testul DR.
$ErrorActionPreference = "SilentlyContinue"
$reasons = @()
$rebootPending = $false
# 1. Component Based Servicing: update aplicat, așteaptă reboot.
if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") {
$reasons += "CBS_RebootPending"
$rebootPending = $true
}
# 2. Windows Update: reboot cerut explicit.
if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\NT\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") {
$reasons += "WU_RebootRequired"
$rebootPending = $true
}
# 3. Fișiere programate pentru redenumire la boot (semnătură clasică de servicing).
$pfro = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations).PendingFileRenameOperations
if ($pfro) {
$reasons += "PendingFileRename"
$rebootPending = $true
}
# 4. Redenumire de computer în așteptare — tot reboot cere.
if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\PostRebootReporting") {
$reasons += "PostRebootReporting"
}
# 5. TiWorker.exe = worker-ul de servicing. Prezent => CBS lucrează chiar acum.
if (Get-Process -Name "TiWorker" -ErrorAction SilentlyContinue) {
$reasons += "TiWorker_running"
}
# 6. TrustedInstaller pornit => Windows Modules Installer aplică ceva.
if ((Get-Service -Name "TrustedInstaller" -ErrorAction SilentlyContinue).Status -eq "Running") {
$reasons += "TrustedInstaller_running"
}
# 7. Update Orchestrator activ => descărcare/scheduling în curs.
if ((Get-Service -Name "UsoSvc" -ErrorAction SilentlyContinue).Status -eq "Running") {
$reasons += "UsoSvc_running"
}
# Notă: wuauserv nu este verificat intenționat — pornește și se oprește de la
# sine în mod normal (inclusiv pentru definițiile Defender) și ar produce
# fals-pozitive la fiecare rulare.
if ($reasons.Count -eq 0) {
Write-Output "STATE=IDLE"
exit 0
} else {
Write-Output ("STATE=BUSY REBOOT_PENDING=" + $rebootPending.ToString().ToLower() + " REASONS=" + ($reasons -join ","))
exit 1
}