The Veeam, MARS, WSB and VB365 collectors each carried identical copies of logging, ISO time conversion, property lookup, posting to the API, config loading, TLS setup, the sent-runs state file and the 401 check, and their installers repeated the same key prompt, locked-down config, file copy and scheduled-task registration. These now live in collectors/common/BackupDashboard.Collector.psm1: - Initialize-Collector / Test-RunSent / Send-JobReport / Test-AuthRejected / Complete-Collector for collector runs - Write-Log, Get-ErrorText, ConvertTo-IsoTime, Get-FirstValue - Install-CollectorTask for the shared half of each installer Collectors find the module next to themselves (installed) or in ..\common (repo); installers copy it into Program Files beside the collector. The diagnostic scripts stay standalone single files. No behavior change: a harness ran each collector against its mock (12 scenarios: dry run, two real runs against a stub API, state file, logs, exit codes, rejected key, en-GB, backfill) before and after, and all 84 outputs are identical. Installers, run with stand-ins for the Windows-only commands, write identical configs and tasks; the only differences are the module being copied and the summary line naming the shell's path. Co-Authored-By: Claude Opus 5.5 <[email protected]>
84 lines
4.5 KiB
Markdown
84 lines
4.5 KiB
Markdown
# Veeam Backup & Replication collector
|
|
|
|
A PowerShell script that runs on each client's VBR server and reports job results to the dashboard.
|
|
It covers jobs returned by `Get-VBRJob`: VM backup, replication and backup copy jobs.
|
|
|
|
## Install (on the VBR server, as an administrator)
|
|
|
|
Requires PowerShell 7 installed machine-wide (`winget install Microsoft.PowerShell` or the MSI),
|
|
which VBR 13's Veeam module expects. The Microsoft Store version won't work, because the SYSTEM
|
|
account can't run it. The installer checks for this before changing anything.
|
|
|
|
1. On the dashboard host, create a key for this server:
|
|
```bash
|
|
python manage.py create-key veeam-acme
|
|
```
|
|
2. Copy the whole `collectors` folder to the VBR server (the installer needs `common`
|
|
as well as this folder), then from `collectors\veeam` run, from PowerShell 7 (`pwsh`):
|
|
```powershell
|
|
.\Install-VeeamCollector.ps1 -ApiUrl https://backups.example.com -Tenant "Acme Corp"
|
|
```
|
|
It prompts for the key, then:
|
|
- writes `C:\ProgramData\BackupDashboard\veeam-collector.json` (readable only by SYSTEM and Administrators)
|
|
- copies the script to `C:\Program Files\BackupDashboard\`
|
|
- registers the scheduled task **Backup Dashboard - Veeam collector** (SYSTEM, every 60 minutes,
|
|
run by `C:\Program Files\PowerShell\7\pwsh.exe`; use `-PwshPath` if it's installed elsewhere)
|
|
3. Preview the payloads, then backfill 30 days so the history view is populated straight away
|
|
(from `pwsh`):
|
|
```powershell
|
|
& 'C:\Program Files\BackupDashboard\Send-VeeamBackupStatus.ps1' -DryRun
|
|
& 'C:\Program Files\BackupDashboard\Send-VeeamBackupStatus.ps1' -LookbackHours 720
|
|
```
|
|
|
|
Re-run the installer to change settings or update the script. It also installs
|
|
`BackupDashboard.Collector.psm1`, the code shared by all collectors, next to the script. To remove the collector,
|
|
delete the scheduled task and both `BackupDashboard` folders.
|
|
|
|
## What it sends
|
|
|
|
| Dashboard | Veeam |
|
|
|---|---|
|
|
| Company | `Tenant` from the config |
|
|
| Job | Job name. The job's GUID is the ID, so renaming a job in Veeam doesn't duplicate it |
|
|
| Status | Session result (Success / Warning / Failed). Any state other than Stopped is **Running**. A session that stopped with no result (e.g. cancelled) is reported as **Warning** |
|
|
| Started / finished | Session `CreationTime` / `EndTime` |
|
|
| Next scheduled | Job's next run, from the live schedule (`GetScheduleOptions()`). Sent as empty, so never flagged Overdue, for disabled jobs, chained ("run after") jobs, and immediate-mode backup copy jobs, which run whenever their source does |
|
|
| Message | Session reason, each VM or object that didn't succeed, and warning/error lines from the session log |
|
|
| Size | `BackupStats.BackupSize` |
|
|
|
|
**Backup copy jobs (VBR 12+):** Veeam records their sessions under hidden per-source "worker" jobs.
|
|
The collector files each worker session under its copy job (via the worker's `PolicyJobId`), so a
|
|
copy job gets one run per source job it copies, with the source in `copied_from`.
|
|
|
|
Each run covers the last 48 hours (`LookbackHours`), so a few missed runs (server rebooting, API
|
|
down) fill in automatically. Sessions already delivered are recorded in
|
|
`veeam-collector.state.json`. Running sessions are re-sent until they finish.
|
|
|
|
## Troubleshooting
|
|
|
|
- Log: `C:\ProgramData\BackupDashboard\veeam-collector.log` (rotates at 5 MB).
|
|
- Exit codes: `0` OK, `1` some jobs failed to send (they're retried next run), `2` setup failed
|
|
(config, Veeam module, or Veeam connection).
|
|
- `API key rejected`: the key was revoked or mistyped. Re-run the installer with a new key.
|
|
- A job shows **Unknown** on the dashboard: the collector sent the job but matched no sessions to it.
|
|
Run `.\Get-VeeamCollectorDiagnostics.ps1` (read-only). It lists sessions whose job ID matches no
|
|
job, plus the type and link properties of the jobs left without sessions.
|
|
- `Get-VBRBackupSession` loads every session in the VBR database. On a server with years of history,
|
|
this can make each run take a minute or more. The task's 30-minute limit and "don't start if
|
|
already running" setting keep that safe.
|
|
|
|
## Testing without Veeam
|
|
|
|
`tests/MockVeeam.ps1` defines stand-in `Get-VBRJob` / `Get-VBRBackupSession` cmdlets with a mix of
|
|
success, warning, failed, running and disabled jobs:
|
|
|
|
```powershell
|
|
. ./tests/MockVeeam.ps1
|
|
./Send-VeeamBackupStatus.ps1 -ConfigPath ./my-test-config.json -DryRun
|
|
```
|
|
|
|
## Not covered yet
|
|
|
|
- Veeam Agent jobs managed by VBR (`Get-VBRComputerBackupJob`), tape jobs, and SureBackup.
|
|
- Veeam Backup for Microsoft 365, which has its own PowerShell module.
|