Heres my Powershell 5.1 version with improved error handling. Might be useful to someone out there..
If you want to use it, make sure to set default values in the param() block at the top of the script unless you want to specify arguments manually every time.
Examples of how to call the script, supplying arguments manually:
Or just right-click and "Run with PowerShell" (given you have hardcoded default params that work)
Written in Powershell 5.1 using Proxmox 8.1
If you want to use it, make sure to set default values in the param() block at the top of the script unless you want to specify arguments manually every time.
Examples of how to call the script, supplying arguments manually:
.\VMControl.ps1 123 on
.\VMControl.ps1 123 off root@pam password nodename 192.168.1.10:8006
.\VMControl.ps1 -VM_ID "123" -OnOrOff "on" -Username "root@pam" -Password "password" -NodeName "nodename" -ProxmoxHost "192.168.1.10:8006"
Or just right-click and "Run with PowerShell" (given you have hardcoded default params that work)
Written in Powershell 5.1 using Proxmox 8.1
Code:
# 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 = "<your_user>",
[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
Last edited: