# Description: This script is used to start or stop a VM on a Proxmox server.
param(
[string]$VM_ID="101",
[ValidateSet("on", "off")] [string]$OnOrOff = "on",
[string]$Username = "root@pam",
[string]$Password = "<your_password>",
[string]$NodeName = "<your_node_name>",
[string]$ProxmoxHost = "<your_ip_here>:8006"
)
$taskTimeout = 30 # How long to wait for the task to complete, before timing out.
function ExitAndWaitForKeypress {
Write-Host "Press any key to continue..."
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
exit 1
}
$curlCommand = "curl.exe -sS -k"; # -sS is to suppress the progress bar and show errors, -k is to ignore SSL certificate errors
$proxmoxApiBaseUrl = "https://$ProxmoxHost/api2/json"
# Authenticate and get the tickets
$getTicketJson = ConvertFrom-Json (Invoke-Expression "$curlCommand -d 'username=$Username' --data-urlencode 'password=$Password' '$proxmoxApiBaseUrl/access/ticket'")
$ticket = $getTicketJson.data.ticket
$preventionToken = $getTicketJson.data.CSRFPreventionToken
if (-not $ticket -or -not $preventionToken) {
Write-Error "Failed to retrieve authentication ticket. Your login credentials may be incorrect."
ExitAndWaitforKeypress
}
$curlCommandWithTicket = "curl.exe -sS -k -H `"Cookie: PVEAuthCookie=$ticket`" -H `"CSRFPreventionToken: $preventionToken`""
# Create the task to start or stop the VM
if ($OnOrOff -eq "on") {
$curlPostTask = "$curlCommandWithTicket -X POST -i `"$proxmoxApiBaseUrl/nodes/$NodeName/qemu/$VM_ID/status/start`"" # -i to include the headers in output
} elseif ($OnOrOff -eq "off") {
$curlPostTask = "$curlCommandWithTicket -X POST -i `"$proxmoxApiBaseUrl/nodes/$NodeName/qemu/$VM_ID/status/shutdown`""
} else {
Write-Error "Invalid value for OnOrOff: $OnOrOff. OnOrOff must be 'on' or 'off'."
}
$postResponse = Invoke-Expression $curlPostTask
$responseParts = $postResponse.Split("`r`n");
$postTaskResponseStatus = $responseParts[0] # First line of the response contains the HTTP version followed by the status code and the reason phrase
$postTaskResponseJson = ConvertFrom-Json $responseParts[-1] # json body is at the end of the response
$upid = $postTaskResponseJson.data
if (-not $upid) {
Write-Error "Failed to create the task. Proxmox returned response: '$postTaskResponseStatus'."
ExitAndWaitForKeypress
}
# Wait for the task to complete, print the result.
$startTime = Get-Date
do {
$curlGetTaskStatus = "$curlCommandWithTicket -X GET `"$proxmoxApiBaseUrl/nodes/$NodeName/tasks/$upid/status`""
$taskStatusJson = ConvertFrom-Json (Invoke-Expression $curlGetTaskStatus)
if ($taskStatusJson.data.status -eq "stopped") {
Write-Host "TASK COMPLETED. | command='$($taskStatusJson.data.type)' | status='$($taskStatusJson.data.status)' | reason='$($taskStatusJson.data.exitstatus)' `r`n" -NoNewline
break
}
Write-Host "TASK RUNNING... | command='$($taskStatusJson.data.type)' | status='$($taskStatusJson.data.status)'"
$currentTime = Get-Date
$elapsedTime = ($currentTime - $startTime).TotalSeconds
if ($elapsedTime -ge $taskTimeout) {
Write-Error "Timeout: Task is still running after $taskTimeout seconds."
break
}
Start-Sleep -Milliseconds 250
} while ($true)
ExitAndWaitForKeypress