feat(ups): unelte pentru testul de autonomie cu scoaterea din priza
set-praguri.ps1 schimba pragurile de oprire fara sa atinga parola SMTP si reporneste taskul, pentru ca ups-monitor.ps1 citeste configuratia o singura data, la pornirea buclei. trace-baterie.ps1 scrie o citire la fiecare 20 s intr-un CSV local, iar start-trace.ps1 il inregistreaza ca task programat sub SYSTEM. Local si detasat, pentru ca intr-o pana reala reteaua cade odata cu curentul daca switch-ul nu e pe UPS: sesiunea SSH devine oarba si emailurile esueaza, deci CSV-ul de pe server ramane singura sursa de date. Taskul are aceleasi AllowStartIfOnBatteries / DontStopIfGoingOnBatteries ca monitorul - fara ele Windows l-ar opri exact cand incepe ce vrem sa masuram. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RRyaDj39hPQ89SZS6URRpS
This commit is contained in:
66
scripts/ups-monitor/set-praguri.ps1
Normal file
66
scripts/ups-monitor/set-praguri.ps1
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Schimba pragurile de oprire din config.json fara sa atinga parola SMTP,
|
||||||
|
si reporneste monitorul ca sa le citeasca.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Se ruleaza PE SERVER, ridicat (Administrator).
|
||||||
|
|
||||||
|
Configuratia e citita o singura data, la pornirea buclei, deci orice modificare
|
||||||
|
cere repornirea taskului - de asta se ocupa scriptul.
|
||||||
|
|
||||||
|
Fara parametri, doar afiseaza pragurile curente.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
# praguri largite pentru un test de autonomie
|
||||||
|
powershell -ExecutionPolicy Bypass -File .\set-praguri.ps1 -Minute 60 -Procent 25
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
# inapoi la valorile de productie
|
||||||
|
powershell -ExecutionPolicy Bypass -File .\set-praguri.ps1 -Minute 10 -Procent 35
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$InstallDir = 'C:\ROMFAST\ups-monitor',
|
||||||
|
[ValidateRange(1, 1440)][int]$Minute,
|
||||||
|
[ValidateRange(1, 99)][int]$Procent,
|
||||||
|
[switch]$FaraRepornire
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version 2.0
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$path = Join-Path $InstallDir 'config.json'
|
||||||
|
$cfg = Get-Content -LiteralPath $path -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
|
|
||||||
|
Write-Host ("Praguri curente : {0} min pe baterie / {1}% incarcare" -f `
|
||||||
|
$cfg.shutdownAfterMinutesOnBattery, $cfg.shutdownAtBatteryPercent)
|
||||||
|
|
||||||
|
if (-not $Minute -and -not $Procent) {
|
||||||
|
Write-Host 'Nimic de schimbat (da -Minute si/sau -Procent).'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Minute) { $cfg.shutdownAfterMinutesOnBattery = $Minute }
|
||||||
|
if ($Procent) { $cfg.shutdownAtBatteryPercent = $Procent }
|
||||||
|
|
||||||
|
$cfg | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $path -Encoding UTF8
|
||||||
|
Write-Host ("Praguri noi : {0} min pe baterie / {1}% incarcare" -f `
|
||||||
|
$cfg.shutdownAfterMinutesOnBattery, $cfg.shutdownAtBatteryPercent)
|
||||||
|
|
||||||
|
if ($cfg.shutdownAtBatteryPercent -le 20) {
|
||||||
|
Write-Warning 'Pragul e sub cel al Windows-ului (20%): Windows va opri serverul primul, brutal, inaintea opririi curate.'
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($FaraRepornire) {
|
||||||
|
Write-Warning 'Monitorul NU a fost repornit - inca ruleaza cu pragurile vechi.'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Stop-ScheduledTask -TaskName 'ROMFAST UPS Monitor'
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
Start-ScheduledTask -TaskName 'ROMFAST UPS Monitor'
|
||||||
|
Start-Sleep -Seconds 18
|
||||||
|
|
||||||
|
$log = Join-Path $InstallDir ('log\ups-monitor-{0}.log' -f (Get-Date -Format 'yyyy-MM'))
|
||||||
|
Get-Content -LiteralPath $log -Tail 2 | ForEach-Object { " $_" }
|
||||||
69
scripts/ups-monitor/start-trace.ps1
Normal file
69
scripts/ups-monitor/start-trace.ps1
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Porneste (sau opreste) inregistrarea curbei de descarcare, ca task programat
|
||||||
|
sub SYSTEM - ca sa nu moara odata cu sesiunea SSH.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
powershell -ExecutionPolicy Bypass -File .\start-trace.ps1
|
||||||
|
powershell -ExecutionPolicy Bypass -File .\start-trace.ps1 -Stop
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$InstallDir = 'C:\ROMFAST\ups-monitor',
|
||||||
|
[ValidateRange(5, 300)][int]$IntervalSecunde = 20,
|
||||||
|
[switch]$Stop
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version 2.0
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$TaskName = 'ROMFAST UPS Trace'
|
||||||
|
$csv = Join-Path $InstallDir 'log\trace-baterie.csv'
|
||||||
|
$stopFile = Join-Path $InstallDir 'log\STOP-TRACE'
|
||||||
|
|
||||||
|
if ($Stop) {
|
||||||
|
New-Item -ItemType File -Path $stopFile -Force | Out-Null
|
||||||
|
Start-Sleep -Seconds ($IntervalSecunde + 5)
|
||||||
|
if (Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue) {
|
||||||
|
Stop-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
|
||||||
|
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
|
||||||
|
}
|
||||||
|
Remove-Item -LiteralPath $stopFile -Force -ErrorAction SilentlyContinue
|
||||||
|
Write-Host "Inregistrare oprita. Datele raman in $csv"
|
||||||
|
if (Test-Path -LiteralPath $csv) {
|
||||||
|
Write-Host ''
|
||||||
|
Get-Content -LiteralPath $csv -Tail 10 | ForEach-Object { " $_" }
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$script = Join-Path $InstallDir 'trace-baterie.ps1'
|
||||||
|
if (-not (Test-Path -LiteralPath $script)) {
|
||||||
|
throw "Lipseste $script - copiaza-l intai in $InstallDir"
|
||||||
|
}
|
||||||
|
|
||||||
|
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument (
|
||||||
|
'-NoProfile -NonInteractive -ExecutionPolicy Bypass -File "{0}" -IntervalSecunde {1}' -f $script, $IntervalSecunde)
|
||||||
|
|
||||||
|
# Aceleasi doua setari ca la monitor: fara ele, Windows opreste taskul exact cand
|
||||||
|
# serverul trece pe baterie - adica exact cand incepe ce vrem sa masuram.
|
||||||
|
$settings = New-ScheduledTaskSettingsSet `
|
||||||
|
-AllowStartIfOnBatteries `
|
||||||
|
-DontStopIfGoingOnBatteries `
|
||||||
|
-MultipleInstances IgnoreNew `
|
||||||
|
-ExecutionTimeLimit ([TimeSpan]::Zero)
|
||||||
|
|
||||||
|
$principal = New-ScheduledTaskPrincipal -UserId 'NT AUTHORITY\SYSTEM' -LogonType ServiceAccount -RunLevel Highest
|
||||||
|
|
||||||
|
if (Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue) {
|
||||||
|
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
|
||||||
|
}
|
||||||
|
Register-ScheduledTask -TaskName $TaskName -Description 'Inregistreaza curba de descarcare a UPS-ului in timpul unui test de autonomie.' `
|
||||||
|
-Action $action -Settings $settings -Principal $principal | Out-Null
|
||||||
|
|
||||||
|
Start-ScheduledTask -TaskName $TaskName
|
||||||
|
Start-Sleep -Seconds ($IntervalSecunde + 8)
|
||||||
|
|
||||||
|
Get-ScheduledTask -TaskName $TaskName | Format-Table -AutoSize TaskName, State
|
||||||
|
Write-Host "CSV: $csv"
|
||||||
|
if (Test-Path -LiteralPath $csv) { Get-Content -LiteralPath $csv -Tail 5 | ForEach-Object { " $_" } }
|
||||||
93
scripts/ups-monitor/trace-baterie.ps1
Normal file
93
scripts/ups-monitor/trace-baterie.ps1
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Inregistreaza local, in CSV, curba de descarcare a UPS-ului in timpul unui test
|
||||||
|
de autonomie cu scoaterea din priza.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Se ruleaza ca task programat, sub SYSTEM, ca sa supravietuiasca inchiderii
|
||||||
|
sesiunii SSH - exact scenariul unui test de pana, unde reteaua poate cadea odata
|
||||||
|
cu curentul daca switch-ul nu e pe UPS.
|
||||||
|
|
||||||
|
Scrie o linie la fiecare interval, indiferent de starea alimentarii, si se
|
||||||
|
opreste singur dupa MaxOre sau cand apare fisierul STOP-TRACE langa CSV.
|
||||||
|
Fisierul CSV e singura sursa sigura de date daca reteaua pica: monitorul
|
||||||
|
propriu-zis noteaza doar evenimentele, nu fiecare citire.
|
||||||
|
|
||||||
|
Se porneste cu start-trace.ps1, care inregistreaza si taskul.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
powershell -ExecutionPolicy Bypass -File .\trace-baterie.ps1 -IntervalSecunde 20
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$OutFile = 'C:\ROMFAST\ups-monitor\log\trace-baterie.csv',
|
||||||
|
[ValidateRange(5, 300)][int]$IntervalSecunde = 20,
|
||||||
|
[ValidateRange(1, 24)][int]$MaxOre = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version 2.0
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
if (-not ('TracePowerStatus' -as [type])) {
|
||||||
|
Add-Type -TypeDefinition @'
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct TRACE_POWER_STATUS {
|
||||||
|
public byte ACLineStatus;
|
||||||
|
public byte BatteryFlag;
|
||||||
|
public byte BatteryLifePercent;
|
||||||
|
public byte SystemStatusFlag;
|
||||||
|
public int BatteryLifeTime;
|
||||||
|
public int BatteryFullLifeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TracePowerStatus {
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool GetSystemPowerStatus(out TRACE_POWER_STATUS status);
|
||||||
|
}
|
||||||
|
'@
|
||||||
|
}
|
||||||
|
|
||||||
|
$dir = Split-Path -Parent $OutFile
|
||||||
|
if (-not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
|
||||||
|
|
||||||
|
$stopFile = Join-Path $dir 'STOP-TRACE'
|
||||||
|
Remove-Item -LiteralPath $stopFile -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $OutFile)) {
|
||||||
|
Set-Content -LiteralPath $OutFile -Encoding UTF8 `
|
||||||
|
-Value 'ora;sursa;procent;autonomie_sec;acLineStatus;batteryFlag'
|
||||||
|
}
|
||||||
|
Add-Content -LiteralPath $OutFile -Encoding UTF8 `
|
||||||
|
-Value ('# start {0}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'))
|
||||||
|
|
||||||
|
$pana = (Get-Date).AddHours($MaxOre)
|
||||||
|
|
||||||
|
while ((Get-Date) -lt $pana -and -not (Test-Path -LiteralPath $stopFile)) {
|
||||||
|
try {
|
||||||
|
$st = New-Object TRACE_POWER_STATUS
|
||||||
|
[void][TracePowerStatus]::GetSystemPowerStatus([ref]$st)
|
||||||
|
|
||||||
|
$sursa = switch ($st.ACLineStatus) {
|
||||||
|
0 { 'baterie' }
|
||||||
|
1 { 'retea' }
|
||||||
|
default { 'necunoscut' }
|
||||||
|
}
|
||||||
|
$procent = if ($st.BatteryLifePercent -le 100) { [int]$st.BatteryLifePercent } else { '' }
|
||||||
|
$autonomie = if ($st.BatteryLifeTime -ge 0) { [int]$st.BatteryLifeTime } else { '' }
|
||||||
|
|
||||||
|
Add-Content -LiteralPath $OutFile -Encoding UTF8 -Value (
|
||||||
|
'{0};{1};{2};{3};{4};{5}' -f (Get-Date -Format 'HH:mm:ss'), $sursa, $procent,
|
||||||
|
$autonomie, [int]$st.ACLineStatus, [int]$st.BatteryFlag)
|
||||||
|
} catch {
|
||||||
|
Add-Content -LiteralPath $OutFile -Encoding UTF8 -Value (
|
||||||
|
'{0};EROARE;;;;{1}' -f (Get-Date -Format 'HH:mm:ss'), $_.Exception.Message)
|
||||||
|
}
|
||||||
|
Start-Sleep -Seconds $IntervalSecunde
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Content -LiteralPath $OutFile -Encoding UTF8 `
|
||||||
|
-Value ('# stop {0}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'))
|
||||||
Reference in New Issue
Block a user