A web-based operations dashboard for VMware vSphere estates. It connects to one or more vCenter Servers, collects cluster, host, virtual machine, datastore and version data through VMware PowerCLI, and presents it as a single interactive dashboard covering capacity, redundancy, health, VM placement and ESXi version consistency across every site.
The repository also contains a companion PowerShell automation that emails a formatted daily health report and registers it as a scheduled task.
The system is designed to run inside an air-gapped environment. The web server has no internet access, so all front-end libraries are served locally and the dashboard makes no external requests.
- Components
- Architecture and Data Flow
- Dashboard Features
- Cluster Metrics Reference
- Repository Structure
- Technology Stack
- Prerequisites
- Credentials File
- Installation
- Configuration
- Backend API
- Daily Health Report
- Security Notes
- Troubleshooting
- License
This repository contains two related but independent components.
index.html- dashboard markup and navigationcompute.js- all front-end logic and renderingstyle.css- dashboard styling, including dark moderun_compute.php- backend endpoint that runs the collector and returns JSONComputeAnalysis.ps1- PowerCLI collector that gathers all metrics from a vCenterassets/- vendored third-party libraries (see Installation)
The user opens the dashboard in a browser, it requests data for each configured vCenter through the PHP endpoint, and it renders the results. Nothing is stored in a database; each refresh reflects the live state of the vCenter, subject to a short server-side cache.
Send-HealthReport.ps1- collects the estate state and emails an HTML reportSetup-HealthReportTask.ps1- registers the report as a daily scheduled task
This component runs headless on a schedule. It does not depend on the web application and produces its own self-contained HTML email.
The dashboard has three layers: a browser front end, a PHP orchestration layer, and a PowerShell collector that talks to vCenter.
Browser (index.html + compute.js)
|
| POST run_compute.php { vcenter, forceRefresh }
v
PHP (run_compute.php)
| - checks a 5-minute file cache
| - shells out to PowerShell when the cache is cold
v
PowerShell (ComputeAnalysis.ps1)
| - reads credentials from vcenter.csv
| - connects with VMware PowerCLI
| - collects clusters, hosts, VMs, datastores, versions
| - emits a single JSON document on stdout
v
PHP returns the JSON to the browser, which renders the dashboard.
Sequence for a full refresh:
- On load,
compute.jsiterates the configured vCenter sites and issues one request per site torun_compute.php. run_compute.phpreturns a cached response if one exists and is younger than five minutes; otherwise it executesComputeAnalysis.ps1for that vCenter.ComputeAnalysis.ps1connects to vCenter, collects all metrics, and prints a JSON document.run_compute.phpvalidates the JSON, caches it, and returns it.compute.jsaggregates the responses from all sites and renders the Overview, Health, ESXi and Analysis views.
The list of vCenter sites is defined in compute.js:
| URL | Name |
|---|---|
| vcenter1.example.com | Site A |
| vcenter2.example.com | Site B |
| vcenter3.example.com | Site C |
| vcenter4.example.com | Site D |
The dashboard is organized into views reachable from the top navigation bar.
A multi-site summary that aggregates every configured vCenter into one picture: cluster hotspots, host health issues, snapshot pressure and a searchable VM index built from all collected inventory.
A morning-checklist view that evaluates the whole estate against a set of pass, warning and fail conditions, grouped into three categories:
- Availability and Protection: host connectivity, hardware status, HA enabled, active red alarms.
- Capacity and Performance: N+1 redundancy, host CPU and memory pressure, datastore capacity.
- Maintenance and Hygiene: host uptime, stale snapshots, VMware Tools status, connected installation media.
It also renders a compact host status grid per cluster showing state, CPU, memory, uptime and hardware health at a glance.
A dedicated view whose purpose is to bring every host in the estate onto a single current ESXi version.
- It determines the estate target, defined as the newest ESXi version and build present on any host anywhere in the estate. Build numbers increase with each release, so the highest build is the most recent.
- It shows an estate-wide version distribution, with the target build highlighted and older builds listed below it.
- It reports, per cluster, how many hosts are behind the estate target and which ones, so upgrade work can be planned cluster by cluster.
- A cluster is only marked as on target when every one of its hosts is on the newest build; a cluster that is internally uniform but running an older build is correctly flagged as behind.
The manual entry point: a card per configured vCenter. Selecting a site runs a detailed analysis for that vCenter and jumps to the Analysis view.
The per-cluster deep dive. For the selected vCenter it renders one card per cluster containing:
- A composite health score and CPU, memory and capacity metrics.
- N+1 redundancy status with the projected worst-case load after a single host failure.
- HA and DRS configuration, DRS automation level and active alarm count.
- Top resource-consuming VMs and a list of powered-off VMs with their allocated resources and virtual hardware version.
- VM health issues: outdated or missing VMware Tools, legacy virtual hardware versions, connected CD/DVD media, and disabled CPU or memory hot-add.
- Datastore capacity, sorted by usage.
- Per-host details, including a cross-cluster migration suggestion for hosts under memory pressure. The suggestion verifies that the target host can accept the VM by checking resource headroom, shared networks, shared datastores and CPU family compatibility (EVC) before recommending a destination.
Export of the current analysis to CSV in several shapes (cluster and host
metrics, full VM inventory, health issues). PDF export is present but disabled by
default; because the server is offline, it requires the jsPDF and
html2canvas libraries to be saved locally and referenced from index.html. The
dashboard explains this when PDF export is selected.
A light and dark theme toggle, persisted in the browser.
The following fields are the most significant ones produced per cluster by
ComputeAnalysis.ps1 and consumed by the dashboard.
| Field | Meaning |
|---|---|
| HealthScore | Composite 0-100 score derived from memory pressure, snapshots, N+1 status and VM health issues. |
| CpuUsage, MemUsage | Cluster-wide CPU and memory utilization as a percentage. |
| vCpuRatio | Provisioned virtual CPUs per physical core. |
| NPlus1Status | Whether the cluster can survive one host failure: Safe, At Risk or Insufficient. |
| NPlus1Detail | Projected worst-case memory and CPU percentage after removing the single most impactful host. |
| TotalPhysicalCores, TotalLogicalThreads | Physical cores and logical threads across connected hosts. |
| SnapshotCount, OldSnapshotCount | Total snapshots and those older than the configured age threshold. |
| PoweredOffCount, PoweredOffVMs | Powered-off VMs and a sample of the largest by allocated memory. |
| ToolsIssues, HWIssues, MediaMounted, HotAddIssues | VM-level hygiene findings. |
| Datastores | Per-datastore capacity and usage. |
| EsxiVersion | Per-cluster ESXi version data: each host's version and build, the cluster baseline, and per-host upgrade flags. |
| Hosts | Per-host CPU, memory, core count, uptime, hardware status and migration suggestion. |
| HAEnabled, DRSEnabled, DRSMode, RedAlarmCount | Cluster protection and alarm state. |
Utilization is color-coded throughout the dashboard using these thresholds:
- Green: healthy, below 75 percent.
- Yellow: warning, from 75 up to 85 percent.
- Red: critical, at or above 85 percent.
compute/
├── index.html Dashboard markup and navigation
├── compute.js Front-end logic, rendering and export
├── style.css Dashboard styling and dark mode
├── run_compute.php Backend endpoint: cache and PowerShell orchestration
├── ComputeAnalysis.ps1 PowerCLI collector, emits JSON
├── Send-HealthReport.ps1 Daily HTML health report over email
├── Setup-HealthReportTask.ps1 Registers the daily scheduled task
├── README.md This document
├── .gitignore Excludes the assets directory
└── assets/ Vendored libraries, not tracked in git
├── css/ Bootstrap and Font Awesome styles
├── js/ Bootstrap and SweetAlert2
└── webfonts/ Font Awesome web fonts
The assets/ directory is intentionally excluded from version control by
.gitignore. It holds third-party libraries and must be restored separately on
a fresh checkout (see Installation).
Front end:
- HTML5 and CSS3
- JavaScript (ES6+), no build step
- Bootstrap 5, Font Awesome and SweetAlert2, served locally
Backend:
- PHP for request handling, caching and process orchestration
- Windows PowerShell 5.1
- VMware PowerCLI for vCenter connectivity
The reference deployment uses XAMPP on Windows to serve the PHP application.
- Windows Server, or Windows 10 or 11, with Windows PowerShell 5.1
- VMware PowerCLI installed for the account that runs the collector
- PHP 7.4 or later (for example via XAMPP)
- Network reachability and credentials for each vCenter Server
- The
assets/libraries restored into the project (see Installation)
Both the dashboard collector and the health report read vCenter credentials from a CSV file. The file maps a vCenter address to a username and password.
Format:
viserver,username,password
vcenter1.example.com,administrator@vsphere.local,ExamplePassword1
vcenter2.example.com,administrator@vsphere.local,ExamplePassword2
vcenter3.example.com,administrator@vsphere.local,ExamplePassword3
vcenter4.example.com,administrator@vsphere.local,ExamplePassword4The viserver column must match the site URL configured in the application.
ComputeAnalysis.ps1 searches for the file in this order and uses the first that
exists:
vcenter.csvin the script directory%USERPROFILE%\Desktop\vcenter.csv
Send-HealthReport.ps1 uses its own list of candidate paths, configurable near
the top of the script.
This file contains plaintext credentials. It must never be committed to version control and should be readable only by the account that runs the collector.
-
Clone the repository into the web root. For the reference XAMPP layout:
C:\xampp\htdocs\powershell-app\compute\ -
Restore the
assets/directory. Because the server is offline andassets/is not tracked in git, copy the Bootstrap, Font Awesome and SweetAlert2 files intoassets/css,assets/jsandassets/webfontsas referenced byindex.html. -
Install VMware PowerCLI for the account that will run the collector:
Install-Module -Name VMware.PowerCLI -Scope AllUsers -Force
-
Create the credentials file (see Credentials File) in one of the searched locations.
-
Confirm the site list in
compute.jsmatches your environment and theviservervalues in the credentials file. -
Start the web server. With XAMPP, start Apache and browse to the application, for example:
http://localhost/powershell-app/compute/For a quick local test without XAMPP, PHP's built-in server can be used from the project directory:
php -S localhost:8000
The dashboard loads all configured sites on startup. Because the account that Apache runs under is the identity that PowerCLI authenticates with for local resources, ensure that account has the access it needs.
Collector thresholds are defined near the top of ComputeAnalysis.ps1:
| Variable | Default | Purpose |
|---|---|---|
| SnapshotAgeDays | 30 | Snapshots older than this are flagged as stale. |
| MigrationMemThreshold | 80 | Host memory percentage above which a migration is suggested. |
| MigrationTargetCap | 85 | A migration target host is never pushed above this percentage. |
| AssumedVmCpuUtilization | 0.20 | Assumed average fraction of a VM's vCPUs actually in use, for target sizing. |
| NPlus1SafePct | 85 | After one host failure, survivors should stay below this percentage. |
| OldHWVersionNum | 14 | Virtual hardware at or below this version is treated as legacy. |
| HWUpgradeVersionNum | 19 | Virtual hardware below this version is treated as upgradeable. |
| ExcludeClusters | empty | Names of clusters to skip entirely. |
Backend behavior is defined in run_compute.php:
- Responses are cached per vCenter for five minutes in a
cache/directory. - A request may set
forceRefreshto bypass the cache. - Diagnostic output is written to
compute_debug.log.
Request body (JSON):
{
"vcenter": "vcenter1.example.com",
"forceRefresh": false
}Response (JSON, abbreviated):
{
"success": true,
"vCenter": "vcenter1.example.com",
"generatedAt": "2026-01-01 09:00:00",
"cached": false,
"Clusters": [
{
"Name": "Cluster-01",
"HealthScore": 92,
"CpuUsage": 41.3,
"MemUsage": 68.0,
"vCpuRatio": 4.17,
"NPlus1Status": "Safe",
"HostCount": 3,
"VmCount": 90,
"SnapshotCount": 12,
"EsxiVersion": {
"BaseDisplay": "8.0.3 (build 25429389)",
"Consistent": false,
"UpgradeCount": 1,
"HostCount": 3,
"Hosts": [
{
"HostName": "esx-01.example.com",
"Version": "8.0.3",
"Build": "25429389",
"Display": "8.0.3 (build 25429389)",
"NeedsUpgrade": false
}
],
"Recommendation": "..."
},
"Hosts": [
{
"HostName": "esx-01.example.com",
"ConnectionState": "Connected",
"CpuUsage": 65.0,
"MemUsage": 72.0,
"CoreCount": 32
}
]
}
],
"Errors": []
}On failure the endpoint returns {"success": false, "message": "..."}. A single
failing cluster does not abort the whole run; its error is recorded in the
Errors array and the remaining clusters are still returned.
Send-HealthReport.ps1 is a standalone automation that produces a formatted HTML
health report for the whole estate and emails it once per day. It is independent
of the web dashboard.
What it does:
- Connects to each configured vCenter with PowerCLI.
- Evaluates the same classes of checks as the dashboard Health view: host connectivity and hardware, HA, active alarms, N+1 redundancy, host CPU and memory pressure, host uptime, stale snapshots, VMware Tools status and connected media.
- Builds a single self-contained HTML email using inline styles only, so it renders correctly in email clients without external resources.
- Sends the report by SMTP and also writes a timestamped copy, plus a
latest.html, to an output directory, keeping the most recent copies.
Key configuration, near the top of the script:
| Setting | Default |
|---|---|
| From address | vcenter-health@example.com |
| To address | it-team@example.com |
| SMTP server and port | smtp.example.com, port 25 |
| Snapshot age threshold | 7 days |
| CPU and memory thresholds | warning at 75 percent, critical at 85 percent |
| HTML output directory | health-report-html under the web application |
The subject line is prefixed with the overall status, one of [OK],
[WARNING] or [CRITICAL].
Setup-HealthReportTask.ps1 registers the report as a Windows scheduled task.
Run it once from an elevated PowerShell session:
powershell.exe -ExecutionPolicy Bypass -File "Setup-HealthReportTask.ps1"Defaults:
- Task name:
vCenter-HealthReport, in the task folder\IT Operations - Trigger: daily at 09:00
- Runs whether or not a user is logged on, with the highest privileges
To run it immediately for testing, or to inspect the last result:
Start-ScheduledTask -TaskName 'vCenter-HealthReport' -TaskPath '\IT Operations'
Get-ScheduledTaskInfo -TaskName 'vCenter-HealthReport' -TaskPath '\IT Operations'To remove the task:
Unregister-ScheduledTask -TaskName 'vCenter-HealthReport' -Confirm:$false- The credentials file holds plaintext vCenter passwords. Keep it outside the web root, restrict its file permissions, and never commit it.
- The dashboard performs read-only collection. It does not power VMs on or off, migrate them, or change any vCenter configuration. Migration entries are recommendations for an operator to act on, not automated actions.
- The application is intended for an internal, trusted network. It has no built-in authentication; place it behind existing network controls or add a web-server access control layer if wider exposure is a concern.
- The SMTP settings in the health report default to an unauthenticated relay on port 25. Adjust them to match your mail environment.
- Credentials file not found: confirm the CSV exists in one of the searched locations and that the account running the collector can read it.
- A site shows a connection error: verify network reachability to that vCenter,
and that the
viservervalue in the CSV exactly matches the configured URL. - Empty or partial data: check
compute_debug.login the application directory for the PowerShell output captured by the backend. - Styling or icons missing: the
assets/directory has not been restored, or the files referenced byindex.htmlare not present. - PDF export unavailable: expected by default; save
jsPDFandhtml2canvaslocally and reference them fromindex.htmlas the dashboard describes. - A host shows an unknown ESXi version: the host was likely disconnected or its product information was unavailable at collection time.
Proprietary. Intended for internal infrastructure use only.