helpers/proxmox/Get-ProxmoxDashboard.ps1
|
<#
.SYNOPSIS Generates an interactive HTML dashboard report for Proxmox VE environments. .DESCRIPTION Orchestration script that connects to one or more Proxmox VE servers via the REST API, collects VM details (CPU, memory, disk, network, HA state), and produces a searchable, sortable Bootstrap Table HTML dashboard. Output includes both a JSON data file and a self-contained HTML report. .PARAMETER ProxmoxServers One or more Proxmox VE server URIs (e.g. https://192.168.1.100:8006). If omitted, prompts interactively. .PARAMETER Username Proxmox authentication username (e.g. root@pam). If omitted, prompts interactively. .PARAMETER Password Proxmox authentication password. If omitted, prompts interactively as a secure string. .PARAMETER SkipSSLCheck Bypass SSL certificate validation. Useful for lab environments with self-signed certificates. .EXAMPLE .\Get-ProxmoxDashboard.ps1 Prompts for Proxmox server(s) and credentials, then generates the dashboard. .EXAMPLE .\Get-ProxmoxDashboard.ps1 -ProxmoxServers "https://192.168.1.100:8006" -Username "root@pam" Generates a dashboard for a single Proxmox server (prompts for password). .EXAMPLE .\Get-ProxmoxDashboard.ps1 -ProxmoxServers "https://pve1:8006","https://pve2:8006" -SkipSSLCheck Connects to multiple Proxmox servers with SSL bypass and generates a combined dashboard. .EXAMPLE .\Get-ProxmoxDashboard.ps1 -ProxmoxServers "https://pve:8006" -Username "admin@pve" -Password "MyPass" Generates a dashboard with explicit credentials (non-interactive). .OUTPUTS System.Void Produces a JSON file (proxmox_dashboard.json) and an HTML dashboard (Proxmox-Dashboard.html) in the system temp directory, then opens the HTML in the default browser. .NOTES Author : jason@wug.ninja Version : 1.0.0 Date : 2025-07-15 Requires: PowerShell 5.1+, network access to Proxmox VE API (port 8006), ProxmoxHelpers.ps1 in the same directory. .LINK https://github.com/jayyx2/WhatsUpGoldPS #> param ( [Parameter(Mandatory = $false)] [string[]]$ProxmoxServers, [Parameter(Mandatory = $false)] [string]$Username, [Parameter(Mandatory = $false)] [string]$Password, [Parameter(Mandatory = $false)] [switch]$SkipSSLCheck ) # --- Configuration ----------------------------------------------------------- $helpersPath = Join-Path $PSScriptRoot "ProxmoxHelpers.ps1" if (Test-Path $helpersPath) { . $helpersPath } else { throw "ProxmoxHelpers.ps1 not found at $helpersPath. Ensure it is in the same directory." } if (Get-Module -ListAvailable -Name WhatsUpGoldPS) { if (-not (Get-Module -Name WhatsUpGoldPS)) { Import-Module -Name WhatsUpGoldPS } } # --- Input prompts ----------------------------------------------------------- if (-not $ProxmoxServers -or $ProxmoxServers.Count -eq 0) { $serverInput = Read-Host -Prompt "Enter Proxmox VE server(s) - e.g. https://192.168.1.100:8006 (comma-separated)" $ProxmoxServers = $serverInput -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' } } if (-not $ProxmoxServers -or $ProxmoxServers.Count -eq 0) { throw "At least one Proxmox VE server must be specified." } if (-not $Username) { $Username = Read-Host -Prompt "Enter Proxmox username (e.g. root@pam)" } if (-not $Password) { $securePassword = Read-Host -Prompt "Enter Proxmox password" -AsSecureString $Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto( [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePassword) ) } # Output paths $outputDir = if ($env:TEMP) { $env:TEMP } else { "C:\temp" } $jsonPath = Join-Path $outputDir "proxmox_dashboard.json" $htmlPath = Join-Path $outputDir "Proxmox-Dashboard.html" if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null } # --- Connect and collect data ------------------------------------------------ if ($SkipSSLCheck) { Initialize-SSLBypass } $allData = @() foreach ($server in $ProxmoxServers) { Write-Host "Connecting to $server ..." -ForegroundColor Cyan try { $cookie = Connect-ProxmoxServer -Server $server -Username $Username -Password $Password Write-Host " Authenticated to $server" -ForegroundColor Green $data = Get-ProxmoxDashboard -Server $server -Cookie $cookie if ($data) { $allData += $data } Write-Host " Collected $(@($data).Count) VM(s) from $server" -ForegroundColor Green } catch { Write-Warning "Failed to connect to ${server}: $($_.Exception.Message)" } } if (-not $allData -or $allData.Count -eq 0) { Write-Warning "No VM data collected. Exiting." return } # --- Summary ----------------------------------------------------------------- $running = @($allData | Where-Object { $_.Status -eq 'running' }).Count $stopped = @($allData | Where-Object { $_.Status -eq 'stopped' }).Count $other = $allData.Count - $running - $stopped $nodes = @($allData | Select-Object -ExpandProperty Node -Unique).Count Write-Host "`n--- Proxmox Summary ---" -ForegroundColor Yellow Write-Host " Nodes: $nodes" Write-Host " Running: $running" -ForegroundColor Green Write-Host " Stopped: $stopped" -ForegroundColor Red if ($other -gt 0) { Write-Host " Other: $other" -ForegroundColor DarkYellow } # --- Generate outputs -------------------------------------------------------- $allData | ConvertTo-Json -Depth 5 | Out-File $jsonPath -Force -Encoding UTF8 Write-Host "`nJSON data written to $jsonPath" -ForegroundColor Yellow $templatePath = Join-Path $PSScriptRoot "Proxmox-Dashboard-Template.html" Export-ProxmoxDashboardHtml -DashboardData $allData -OutputPath $htmlPath -ReportTitle "Proxmox VE Dashboard" -TemplatePath $templatePath Write-Host "HTML dashboard written to $htmlPath" -ForegroundColor Yellow # --- Optional: Open in browser ----------------------------------------------- if ($env:OS -match 'Windows') { $openBrowser = Read-Host -Prompt "Open dashboard in browser? (Y/N)" if ($openBrowser -match '^[Yy]') { Start-Process $htmlPath } } Write-Host "Done." -ForegroundColor Green # SIG # Begin signature block # MIIVlwYJKoZIhvcNAQcCoIIViDCCFYQCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAENQw+zKMFo8b4 # tVNpIlMRYKukMYYpWTt1R+AFKijcNaCCEdMwggVvMIIEV6ADAgECAhBI/JO0YFWU # jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI # DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM # EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy # dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG # EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv # IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s # hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD # J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7 # P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme # me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz # T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q # RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz # mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc # QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T # OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/ # AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID # AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD # VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV # HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE # VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v # ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE # KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI # hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF # OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC # J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ # pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl # d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH # +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYaMIIEAqADAgECAhBiHW0M # UgGeO5B5FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD # VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv # ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5 # NTlaMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzAp # BgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0G # CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjI # ztNsfvxYB5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NV # DgFigOMYzB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/3 # 6F09fy1tsB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05Zw # mRmTnAO5/arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm # +qxp4VqpB3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUe # dyz8rNyfQJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz4 # 4MPZ1f9+YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBM # dlyh2n5HirY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQY # MBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritU # pimqF6TNDDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV # HSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsG # A1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1 # YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsG # AQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2Rl # U2lnbmluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0 # aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURh # w1aVcdGRP4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0Zd # OaWTsyNyBBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajj # cw5+w/KeFvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNc # WbWDRF/3sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalO # hOfCipnx8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJs # zkyeiaerlphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z7 # 6mKnzAfZxCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5J # KdGvspbOrTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHH # j95Ejza63zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2 # Bev6SivBBOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/ # L9Uo2bC5a4CH2RwwggY+MIIEpqADAgECAhAHnODk0RR/hc05c892LTfrMA0GCSqG # SIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0 # ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYw # HhcNMjYwMjA5MDAwMDAwWhcNMjkwNDIxMjM1OTU5WjBVMQswCQYDVQQGEwJVUzEU # MBIGA1UECAwLQ29ubmVjdGljdXQxFzAVBgNVBAoMDkphc29uIEFsYmVyaW5vMRcw # FQYDVQQDDA5KYXNvbiBBbGJlcmlubzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC # AgoCggIBAPN6aN4B1yYWkI5b5TBj3I0VV/peETrHb6EY4BHGxt8Ap+eT+WpEpJyE # tRYPxEmNJL3A38Bkg7mwzPE3/1NK570ZBCuBjSAn4mSDIgIuXZnvyBO9W1OQs5d6 # 7MlJLUAEufl18tOr3ST1DeO9gSjQSAE5Nql0QDxPnm93OZBon+Fz3CmE+z3MwAe2 # h4KdtRAnCqwM+/V7iBdbw+JOxolpx+7RVjGyProTENIG3pe/hKvPb501lf8uBAAD # LdjZr5ip8vIWbf857Yw1Bu10nVI7HW3eE8Cl5//d1ribHlzTzQLfttW+k+DaFsKZ # BBL56l4YAlIVRsrOiE1kdHYYx6IGrEA809R7+TZA9DzGqyFiv9qmJAbL4fDwetDe # yIq+Oztz1LvEdy8Rcd0JBY+J4S0eDEFIA3X0N8VcLeAwabKb9AjulKXwUeqCJLvN # 79CJ90UTZb2+I+tamj0dn+IKMEsJ4v4Ggx72sxFr9+6XziodtTg5Luf2xd6+Phha # mOxF2px9LObhBLLEMyRsCHZIzVZOFKu9BpHQH7ufGB+Sa80Tli0/6LEyn9+bMYWi # 2ttn6lLOPThXMiQaooRUq6q2u3+F4SaPlxVFLI7OJVMhar6nW6joBvELTJPmANSM # jDSRFDfHRCdGbZsL/keELJNy+jZctF6VvxQEjFM8/bazu6qYhrA7AgMBAAGjggGJ # MIIBhTAfBgNVHSMEGDAWgBQPKssghyi47G9IritUpimqF6TNDDAdBgNVHQ4EFgQU # 6YF0o0D5AVhKHbVocr8GaSIBibAwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQC # MAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIB # AwIwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EM # AQQBMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2Vj # dGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3JsMHkGCCsGAQUFBwEBBG0wazBE # BggrBgEFBQcwAoY4aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGlj # Q29kZVNpZ25pbmdDQVIzNi5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNl # Y3RpZ28uY29tMA0GCSqGSIb3DQEBDAUAA4IBgQAEIsm4xnOd/tZMVrKwi3doAXvC # wOA/RYQnFJD7R/bSQRu3wXEK4o9SIefye18B/q4fhBkhNAJuEvTQAGfqbbpxow03 # J5PrDTp1WPCWbXKX8Oz9vGWJFyJxRGftkdzZ57JE00synEMS8XCwLO9P32MyR9Z9 # URrpiLPJ9rQjfHMb1BUdvaNayomm7aWLAnD+X7jm6o8sNT5An1cwEAob7obWDM6s # X93wphwJNBJAstH9Ozs6LwISOX6sKS7CKm9N3Kp8hOUue0ZHAtZdFl6o5u12wy+z # zieGEI50fKnN77FfNKFOWKlS6OJwlArcbFegB5K89LcE5iNSmaM3VMB2ADV1FEcj # GSHw4lTg1Wx+WMAMdl/7nbvfFxJ9uu5tNiT54B0s+lZO/HztwXYQUczdsFon3pjs # Nrsk9ZlalBi5SHkIu+F6g7tWiEv3rtVApmJRnLkUr2Xq2a4nbslUCt4jKs5UX4V1 # nSX8OM++AXoyVGO+iTj7z+pl6XE9Gw/Td6WKKKsxggMaMIIDFgIBATBoMFQxCzAJ # BgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNl # Y3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYCEAec4OTRFH+FzTlzz3Yt # N+swDQYJYIZIAWUDBAIBBQCggYQwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZ # BgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYB # BAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg/vOpHCHPBU+/WT+m49kO3TCmOV9LHGBQ # Pn4fweQ2p3owDQYJKoZIhvcNAQEBBQAEggIAi5ytv7ioko8+fFam0UMCYyhbYwWG # MEaDeOoPW3i2r9d7g59F+QFFfV7n9MIqwds7AbWcG00R7SYolCzkQZm0Tr8PJNj5 # 82CVoWCDuR55VwID04d5C4J/Wo+g62Gfg4d/uI+woY/e2gpWwBcwfuVd4uJw/BuT # pWAZgK9QURxJWYHxtAEYdhR/LjPd1hq5gUgeAzHj1W7p5kP47gb5X1VtmHwF3a21 # RX+K28NZQpmxYLfzIsoHkUIdY0uGX9NYHGAjKs8aIUqOorixZSh6QvPlzOuz7Vjn # qwp9SnAWObzZUtYS7ds0oBmPe0s2XNeDPj88gv5bgwxPu5ipVGIi4UEFdiX5PmEf # SsCABB8hsRiaUo74uCNEHTAF5S7fTlQHMlFk5yEiSjSjkDtaiSeP/ySnu2beo73v # XeDZAp32Sa6OU2Ojbn219JGct7X708GSlYcPjGoxk1Y1zqvHi9rrduP4sXeYxZYH # iIHckdUbNA7pcfvSkBLuZVhjwGl23KwpCvC9sg0BgMfpk/uYW9n42ByorKqA84zM # b1Q6pglq8XP4DJv4F8B10e8QgPv2yHlVpHw3EhUnZxsVgstaOdIGXjEaMWkevZm8 # XDMq5X3PswWe4ijYJx9hrQWF76bTzR3WDz0wOP+HTLQXdsqSvBvsMS74Jt5JqTwe # DGE7pbdbiTpK1Tw= # SIG # End signature block |