Proxmox Virtual Environment (PVE) is a virtualization platform that supports virtual machines (QEMU), containers, templates, snapshots, per VM firewall, web-based management interface, etc. Proxmox runs on Debian Linux, and supports local command line tools for automation. So what do I do if I want to automate Proxmox from Windows PowerShell? Use the Proxmox API of course.
I wrote this script as a proof of concept to demonstrate how to use an API in PowerShell, and specifically how to consume the Proxmox API from PowerShell.
What does this script do?
This script will return the name, status, and uptime for a specific VM in a nicely formatted table. This is an example of the output:
Name Status UpDays UpHours UpMinutes UpSeconds
---- ------ ------ ------- --------- ---------
highcastle--debian running 9 17 1 46
How does this script work?
This script follows this common pattern: Set up, execute, output.
Set up
If you don’t already have an API token in Proxmox, see these instructions.
For the “prepare variables” section, you’ll need to customize these values to match how your Proxmox environment is set up. $tokenUser is in the format “username@pam!tokenname” and $tokenSecret is the value assigned when initially creating the token. $vmid is the VM’s ID number. $node is the PVE node name as listed under Datacenter. $pveserver can be the node’s IP address, or hostname. $pveport is the API port, keep the default of 8006, unless you have changed this in PVE.
Please note that the “token secret” should not be in plain text in a live system. It is plain text here for demonstration purposes only. In later iterations of this script, I’ll show how this can be encrypted.
$url is the API URL is the path to get the virtual machine status. The API Viewer documentation helped me to get the exact path needed.
$pveheader is the Authorization header that gets sent with the API call.
Execute
This is just the one line, using the command Invoke-RestMethod. It uses all the values we prepared in the Set up region. This is the command that actually connects to the Proxmox API. The results of this command are put in the variable $result.
If Proxmox is using a self-signed SSL certificate (the default behavior), PowerShell may refuse to connect. There are two solutions to this. 1) The preferred method is to obtain a CA signed certificate for your Proxmox node, more info here. Or option 2) Tell PowerShell to skip checking the certificate by using the code snippet in this StackOverflow answer.
Output
Here is an example of the data returned by the API call:
PS C:\code> $result.data
diskread : 190837326
ha : @{managed=0}
maxdisk : 21474836480
netout : 1919738
proxmox-support : @{pbs-library-version=1.4.1 (UNKNOWN); pbs-masterkey=True; backup-max-workers=True; query-bitmap-info=True; pbs-dirty-bitmap-savevm=True; pbs-dirty-bitmap=True;
backup-fleecing=True; pbs-dirty-bitmap-migration=True}
spice : 1
maxmem : 2147483648
clipboard :
pid : 2210159
blockstat : @{scsi0=; ide2=}
diskwrite : 755953664
name : highcastle--debian
mem : 355270656
cpus : 1
freemem : 1707507712
uptime : 872718
netin : 354281367
nics : @{tap100i0=}
disk : 0
ballooninfo : @{max_mem=2147483648; free_mem=1707507712; mem_swapped_in=0; mem_swapped_out=0; total_mem=2062778368; last_update=1719800413; actual=2147483648;
minor_page_faults=807811; major_page_faults=492}
running-machine : pc-i440fx-8.1+pve0
status : running
vmid : 100
cpu : 0.00591751100250928
running-qemu : 8.1.5
qmpstatus : running
balloon : 2147483648
agent : 1
That’s a lot to sift through, isn’t it? Remember that this script will return just the name, status, and uptime. To make this script useful, and so it doesn’t overwhelm us with this wall of text, I will narrow down the output into a PS Custom Object and format the results. The VM name and status are simple to pull out of the data properties of the same names. The uptime value returned is in seconds, so to make that useful, I convert it to a TimeSpan. In the PS Custom Object, I output that TimeSpan as days, hours, minutes and seconds to make it more easily understood.
To format the PS Custom Object, it is piped into Format-Table, so it displays as a horizontal table.
The script
#region SET UP
# prepare variables
$tokenUser = "username@pam!tokenname" # example: "username@pam!tokenname"
$tokenSecret = "11111111-2222-3333-4444-555555555555" # example: "11111111-2222-3333-4444-555555555555"
$vmid = "100" # ID of VM
$node = "pve" # PVE node name, default is "pve"
$pveserver = "192.168.1.123" # PVE node IP Address or if using SSL certificate, then use name as in certificate
$pveport = "8006" # default port is "8006"
# form URL
$url = "https://${pveserver}:$pveport/api2/json/nodes/$node/qemu/$vmid/status/current"
# set up authorization header to use token values
$pveheader = @{Authorization = "PVEAPIToken=$tokenUser=$tokenSecret"}
#endregion
#region EXCUTE
# send the API request to PVE
$result = Invoke-RestMethod -Headers $pveheader -Method Get -Uri $url
#endregion
#region OUTPUT
# format the result
$uptimeSeconds = New-TimeSpan -Seconds $result.data.uptime
[pscustomobject]@{
Name = $result.data.name
Status = $result.data.status
UpDays = $uptimeSeconds.Days
UpHours = $uptimeSeconds.Hours
UpMinutes = $uptimeSeconds.Minutes
UpSeconds = $uptimeSeconds.Seconds
} | Format-Table
#endregion
Conclusion
This is a demo of using PowerShell to connect to the Proxmox API. In part 2, I will refine the script and turn it into a flexible function that you can use day to day.