vdi-cloud/tools/run-single-vdi-display.py

56 lines
2.9 KiB
Python

"""Query or detach extra Windows desktop outputs in VM100's interactive session."""
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.add_argument("action", choices=["Query","Apply","Restore"])
args=parser.parse_args()
root=Path(__file__).resolve().parent
t=runpy.run_path(str(root/"pve_term_exec.py")); v=runpy.run_path(str(root/"pve_vm.py"))
ticket,csrf=t["login"]()
if v["api"]("/api2/json/nodes/starhe/qemu/100/status/current",ticket=ticket).get("status")!="running":
sys.exit("VM100 is not running; nothing changed")
payload=base64.b64encode((root/"set-single-vdi-display.ps1").read_bytes()).decode()
command=r"""
$ErrorActionPreference='Stop'
$folder='C:\ProgramData\VDI\single-display-20261103'
$task='VDISingleDisplayProbe'
if(Get-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue) { throw 'Task already exists' }
$user=(Get-CimInstance Win32_ComputerSystem).UserName
if(-not $user) { throw 'No interactive user' }
New-Item -ItemType Directory -Force $folder | Out-Null
$acl=Get-Acl $folder
$acl.SetAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($user,'Modify','ContainerInherit,ObjectInherit','None','Allow')))
Set-Acl $folder $acl
[IO.File]::WriteAllBytes("$folder\single.ps1",[Convert]::FromBase64String('__PAYLOAD__'))
Remove-Item "$folder\result.txt" -ErrorAction SilentlyContinue
$run="try { & '$folder\single.ps1' -Action __ACTION__ | Out-File -Encoding utf8 -Width 500 '$folder\result.txt' } catch { `$_ | Out-String | Out-File -Encoding utf8 -Width 500 '$folder\result.txt'; exit 1 }"
$encoded=[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($run))
$a=New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -EncodedCommand $encoded"
$p=New-ScheduledTaskPrincipal -UserId $user -LogonType Interactive -RunLevel Limited
$s=New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 2)
Register-ScheduledTask -TaskName $task -Action $a -Principal $p -Settings $s | Out-Null
try {
Start-ScheduledTask -TaskName $task
Start-Sleep -Seconds 2
for($i=0;$i-lt 30;$i++) {
if((Get-ScheduledTask -TaskName $task).State-ne 'Running') { break }
Start-Sleep -Seconds 1
}
if((Get-ScheduledTask -TaskName $task).State-eq 'Running') { throw 'Probe timed out' }
Get-Content "$folder\result.txt" -Raw
'task_result='+(Get-ScheduledTaskInfo -TaskName $task).LastTaskResult
} finally {
Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue
Unregister-ScheduledTask -TaskName $task -Confirm:$false
}
""".replace("__PAYLOAD__",payload).replace("__ACTION__",args.action)
out,err=v["agent"](ticket,csrf,["powershell.exe","-NoProfile","-Command",command])
print(out)
if err or "task_result=0" not in out:
sys.exit(err or "Display operation did not succeed")