Hi there
I'm usig Proxmox VE now for about 4 years on my Lab and had a step learning curve. Now after all VMware Broadcom story - I'm in to do some PoC to convince my Boss to migrate from ESXi to Proxmox. For this I had to fullfill few demonstrations to show that Proxmox is realy capable to cover our needs. As we patch our Customers VMs over Ivanti there was the Poit to make some easy tool to take and delete snapshots before and after patching. As I profited allready a lot of the proxmox i decided to share these three Powershellscripts. Maybe the could serve / help someone out there. Thanks to the well documented API of Proxmox that was quiet simple. (I know there are PS Modules out there ;-))
Script to take snapshots on VM with defined Tag:
Here the Script to Delete the automated taken snapshots
Kind regards tscret
I'm usig Proxmox VE now for about 4 years on my Lab and had a step learning curve. Now after all VMware Broadcom story - I'm in to do some PoC to convince my Boss to migrate from ESXi to Proxmox. For this I had to fullfill few demonstrations to show that Proxmox is realy capable to cover our needs. As we patch our Customers VMs over Ivanti there was the Poit to make some easy tool to take and delete snapshots before and after patching. As I profited allready a lot of the proxmox i decided to share these three Powershellscripts. Maybe the could serve / help someone out there. Thanks to the well documented API of Proxmox that was quiet simple. (I know there are PS Modules out there ;-))
Script to take snapshots on VM with defined Tag:
code_language.shell:
<#
Proxmox API Snapshot Creator by TAG
Description: Das Script greift per API auf den Proxmox Cluster zu und erstellt bei jeder VM mit dem definierten $SearchTag einen Snapshot.
Die Ausführung des Snapshost wird mittels Task-API Kontrolle überwacht.
#>
# Proxmox API Details
$ProxmoxAPIURL = "https://<FQDN>:8006/api2/json"
$APITokenID = "<API-Token-Secret>"
$APITokenSecret = "<API-Token-Secret>"
$SearchTag = "<YourTag>"
# Log-Datei definieren
$LogFilePath = "C:\temp\ProxmoxSnapshotLog_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
# Funktion zum Schreiben in die Log-Datei
function Write-Log {
param (
[string]$Message
)
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "$Timestamp - $Message"
Write-Output $LogMessage
Add-Content -Path $LogFilePath -Value $LogMessage
}
# Funktion zur Abfrage aller Nodes im Cluster
function Get-AllNodes {
Invoke-RestMethod -Uri "$ProxmoxAPIURL/nodes" -Method Get -Headers $Headers
}
# Funktion zur Abfrage von VMs mit einem bestimmten Tag auf einer Node
function Get-VMsByTag {
param (
[string]$NodeName,
[string]$Tag
)
$VMs = Invoke-RestMethod -Uri "$ProxmoxAPIURL/nodes/$NodeName/qemu" -Method Get -Headers $Headers
return $VMs.data | Where-Object { $_.tags -Like $Tag }
}
# Funktion zur Erstellung eines Snapshots
function Create-Snapshot {
param (
[string]$NodeName,
[string]$VMID,
[string]$SnapshotName
)
$Uri = "$ProxmoxAPIURL/nodes/$NodeName/qemu/$VMID/snapshot"
$Body = @{
snapname = $SnapshotName
vmstate = "0" # Setze auf 1, um den RAM-Zustand zu speichern
description = "Auto Snapshot für Tag $SearchTag"
}
$Response = Invoke-RestMethod -Uri $Uri -Method Post -Body $Body -Headers $Headers -ContentType "application/x-www-form-urlencoded"
return $Response.data
}
# Funktion zur Überprüfung des Task-Status
function Wait-ForTaskCompletion {
param (
[string]$NodeName,
[string]$TaskID
)
Write-Log "Überprüfe Snapshot-Task $VMID auf Node $NodeName..."
while ($true) {
$TaskStatus = Invoke-RestMethod -Uri "$ProxmoxAPIURL/nodes/$NodeName/tasks/$TaskID/status" -Method Get -Headers $Headers
if ($TaskStatus.data.status -eq "stopped") {
if ($TaskStatus.data.exitstatus -eq "OK") {
Write-Log "Snapshot-Task $VMID erfolgreich abgeschlossen."
break
} else {
Write-Log "Snapshot-Task $VMID ist fehlgeschlagen: $($TaskStatus.data.exitstatus)"
throw "Snapshot-Task fehlgeschlagen."
}
}
Start-Sleep -Milliseconds 500
}
}
# Hauptskript
try {
$Counter = 0
Write-Log "Konfiguriere API-Header..."
$Headers = @{
Authorization = "PVEAPIToken=$APITokenID=$APITokenSecret"
}
# Alle Nodes im Cluster abrufen
Write-Log "Hole alle Nodes im Cluster..."
$Nodes = Get-AllNodes
# Über alle Nodes iterieren
foreach ($Node in $Nodes.data) {
$NodeName = $Node.node
Write-Log "Verarbeite Node: $NodeName"
# VMs mit Tag 'IVANTI' auf dieser Node abrufen
Write-Log "Suche nach VMs mit dem Tag $SearchTag auf Node $NodeName..."
$TaggedVMs = Get-VMsByTag -NodeName $NodeName -Tag $SearchTag
if ($TaggedVMs.Count -eq 0) {
Write-Log "Keine VMs mit dem Tag $SearchTag auf Node $NodeName gefunden."
} else {
# Snapshot erstellen
foreach ($VM in $TaggedVMs) {
$VMID = $VM.vmid
$SnapshotName = "$($SearchTag)_Auto_Snapshot_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
Write-Log "Erstelle Snapshot '$SnapshotName' für VMID $VMID auf Node $NodeName..."
$Counter = $Counter+1
$TaskData = Create-Snapshot -NodeName $NodeName -VMID $VMID -SnapshotName $SnapshotName
Wait-ForTaskCompletion -NodeName $NodeName -TaskID $TaskData
}
}
}
Write-Log "Snapshots für alle Nodes abgeschlossen. Anzahl Snapshots $Counter erstellt."
}
catch {
Write-Log "Ein Fehler ist aufgetreten: $_"
throw
}
Here the Script to Delete the automated taken snapshots
code_language.shell:
<#
Proxmox API Snapshot Creator by TAG
Datimo IT Solutions Winterthur
Autor: Reto Tschopp
Created: 31.12.2024
Description: Das Script greift per API auf den Proxmox Cluster zu und löscht bei jeder VM Snapshot die mit dem $SearchTag Wert beginnen.
Die Ausführung des Snapshost wird mittels Task-API Kontrolle überwacht.
#>
# Proxmox API Details
$ProxmoxAPIURL = "https://<FQDN>:8006/api2/json"
$APITokenID = "<API-Token-Secret>"
$APITokenSecret = "<API-Token-Secret>"
$SearchTag = "<YourTag>"
# Log-Datei definieren
$LogFilePath = "C:\temp\ProxmoxSnapshotLog_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
# Funktion zum Schreiben in die Log-Datei
function Write-Log {
param (
[string]$Message
)
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogMessage = "$Timestamp - $Message"
Write-Output $LogMessage
Add-Content -Path $LogFilePath -Value $LogMessage
}
# Header mit Authentifizierung
Write-Log "Konfiguriere API-Header..."
$headers = @{
Authorization = "PVEAPIToken=$APITokenID=$APITokenSecret"
}
# Funktion zum Abrufen der VMIDs
function Get-VMList {
$vmListUrl = "$ProxmoxApiUrl/nodes/$NodeName/qemu"
$response = Invoke-RestMethod -Uri $vmListUrl -Headers $headers -Method Get
return $response.data.vmid
}
# Funktion zum Abrufen der Snapshots einer VM
function Get-Snapshots {
param (
[string]$vmid,
[string]$snapnameStart
)
$snapshotUrl = "$ProxmoxApiUrl/nodes/$NodeName/qemu/$vmid/snapshot"
$response = Invoke-RestMethod -Uri $snapshotUrl -Headers $headers -Method Get
$response.data | Where-Object { $_.name -Match $snapnameStart }
}
# Funktion zum Löschen eines Snapshots
function Delete-Snapshot {
param (
[string]$vmid,
[string]$snapshotName
)
$deleteSnapshotUrl = "$ProxmoxApiUrl/nodes/$NodeName/qemu/$vmid/snapshot/$snapshotName"
$Response = Invoke-RestMethod -Uri $deleteSnapshotUrl -Headers $headers -Method Delete
return $Response.data
}
# Funktion zum holen aller Nodes im Cluster
function Get-AllNodes {
Invoke-RestMethod -Uri "$ProxmoxAPIURL/nodes" -Method Get -Headers $headers
}
# Funktion zur Überprüfung des Task-Status
function Wait-ForTaskCompletion {
param (
[string]$NodeName,
[string]$TaskID
)
Write-Log "Überprüfe Snapshot-Task $VMID auf Node $NodeName..."
while ($true) {
$TaskStatus = Invoke-RestMethod -Uri "$ProxmoxAPIURL/nodes/$NodeName/tasks/$TaskID/status" -Method Get -Headers $headers
if ($TaskStatus.data.status -eq "stopped") {
if ($TaskStatus.data.exitstatus -eq "OK") {
Write-Log "Task für VM $VMID erfolgreich abgeschlossen."
break
} else {
Write-Log "Task für VM $VMID ist fehlgeschlagen: $($TaskStatus.data.exitstatus)"
throw "Snapshot-Task fehlgeschlagen."
}
}
Start-Sleep -Milliseconds 500
}
}
#Hauptscript
try {
$Counter = 0
# Abrufen aller Nodes
$Nodes = Get-AllNodes
foreach ($Node in $Nodes.data) {
$NodeName = $Node.node
Write-Log "Verarbeite Node: $NodeName"
# Abrufen der VMIDs
$vmList = Get-VMList
# Iterieren über jede VM
foreach ($vmid in $vmList) {
# Abrufen der Snapshots für die VM
$snapshots = Get-Snapshots -vmid $vmid -snapnameStart "$($SearchTag)*"
# Wenn Snapshots vorhanden sind, lösche sie
foreach ($snapshot in $snapshots) {
Write-Log "Lösche Snapshot $($snapshot.name) für VMID $vmid..."
$Counter = $Counter+1
$TaskData = Delete-Snapshot -vmid $vmid -snapshotName $snapshot.name
Write-Log "Snapshot $snapshotName für VMID $vmid gelöscht."
Wait-ForTaskCompletion -NodeName $NodeName -TaskID $TaskData
}
}
}
Write-Log "Snapshot-Löschung abgeschlossen. Anzahl gelöschte Snapshots $Counter"
} catch {
Write-Log "Ein Fehler ist aufgetreten: $_"
throw
}
Kind regards tscret