vdi-cloud/tools/deploy-vdi-display-refresh.py

76 lines
3.6 KiB
Python
Raw Normal View History

"""Back up and deploy the VDD login refresh script in VM100, without rebooting."""
import argparse
import base64
from pathlib import Path
import runpy
import sys
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
parser = argparse.ArgumentParser(description=__doc__)
parser.parse_args()
root = Path(__file__).resolve().parent
term = runpy.run_path(str(root / "pve_term_exec.py"))
vm = runpy.run_path(str(root / "pve_vm.py"))
ticket, csrf = term["login"]()
state = vm["api"]("/api2/json/nodes/starhe/qemu/100/status/current", ticket=ticket)
if state.get("status") != "running":
sys.exit("VM100 is not running; nothing changed")
payload = base64.b64encode((root / "set-2k-display.ps1").read_bytes()).decode()
command = r"""
$ErrorActionPreference='Stop'
$target='C:\ProgramData\VDI\set-2k-display.ps1'
$task='VDISet2KDisplay'
$entry=Get-ScheduledTask -TaskName $task
if($entry.State -eq 'Running') { throw 'Display task is already running; inspect before deployment' }
if(-not (Test-Path -LiteralPath $target)) { throw 'Original display script is missing' }
if(($entry.Actions | Select-Object -First 1).Arguments -notlike '*set-2k-display.ps1*') {
throw 'Unexpected display task action; do not change it'
}
$backup='C:\ProgramData\VDI\backups\display-refresh-'+(Get-Date -Format 'yyyyMMdd-HHmmss')
New-Item -ItemType Directory -Path $backup | Out-Null
Copy-Item -LiteralPath $target -Destination "$backup\set-2k-display.ps1"
Export-ScheduledTask -TaskName $task | Set-Content -Encoding UTF8 "$backup\VDISet2KDisplay.xml"
if(Test-Path 'C:\ProgramData\VDI\set-2k-result.txt') {
Copy-Item 'C:\ProgramData\VDI\set-2k-result.txt' "$backup\previous-result.txt"
}
$temporary=$target+'.new'
try {
[IO.File]::WriteAllBytes($temporary,[Convert]::FromBase64String('__PAYLOAD__'))
Move-Item -LiteralPath $temporary -Destination $target -Force
# Prove freshness by a newly created result file; scheduler LastRunTime can
# lag wall-clock time after VM clock correction and is not a reliable token.
Remove-Item -LiteralPath 'C:\ProgramData\VDI\set-2k-result.txt' -ErrorAction SilentlyContinue
Start-ScheduledTask -TaskName $task
Start-Sleep -Seconds 2
for($i=0;$i -lt 20;$i++) {
if((Get-ScheduledTask -TaskName $task).State -ne 'Running') { break }
Start-Sleep -Seconds 1
}
$info=Get-ScheduledTaskInfo -TaskName $task
if((Get-ScheduledTask -TaskName $task).State -eq 'Running' -or
$info.LastTaskResult -ne 0) {
throw 'New display task did not complete successfully'
}
$log=Get-Content 'C:\ProgramData\VDI\set-2k-result.txt' -Raw
if($log -notmatch 'result=0 mode=2560x1440@60') { throw '60Hz read-back missing in display task log' }
@{backup=$backup; task_result=$info.LastTaskResult; result=$log.Trim()} | ConvertTo-Json -Compress
} catch {
if(Test-Path 'C:\ProgramData\VDI\set-2k-result.txt') {
Copy-Item 'C:\ProgramData\VDI\set-2k-result.txt' "$backup\failed-result.txt"
Get-Content "$backup\failed-result.txt"
}
if($info) { $info | Select-Object LastTaskResult,LastRunTime | ConvertTo-Json -Compress }
Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue
Copy-Item -LiteralPath "$backup\set-2k-display.ps1" -Destination $target -Force
Start-ScheduledTask -TaskName $task
throw
} finally {
Remove-Item -LiteralPath $temporary -ErrorAction SilentlyContinue
}
""".replace("__PAYLOAD__", payload)
out, error = vm["agent"](ticket, csrf, ["powershell.exe", "-NoProfile", "-Command", command])
print(out)
if error or '"task_result":0' not in out:
print(error, file=sys.stderr)
sys.exit(1)