Proxmox ve rest api update - #805
Open
Garfieldttt wants to merge 21 commits into
Open
Conversation
…tus endpoint and item error handling
Updated the Zabbix template documentation for Proxmox VE REST API to include additional details on monitoring capabilities, requirements, and installation steps.
…d rebuilt dashboard
Updated the Zabbix template for Proxmox VE REST API with community additions, corrected URLs, and rebuilt the dashboard. Added new macros, discovery rules, and triggers for enhanced monitoring.
This Zabbix template enables full monitoring of a Proxmox VE environment via the official REST API. It includes metrics for hosts, clusters, VMs, containers, backup jobs, and more, with a rebuilt dashboard and corrected URLs.
Updated README to reflect community template modifications and added detailed instructions for rebuilding and API token creation.
This Zabbix template enables full monitoring of a Proxmox VE environment via the official REST API, collecting various metrics without requiring a Zabbix agent. It includes updated URLs, a rebuilt dashboard, and new discovery rules for enhanced functionality.
- guest stopped triggers used min(...,24h)=1 and could never fire
- task and backup alerts never cleared; bounded by new *.ALERT.WINDOW
macros, with the Proxmox error text in the event name
- undefined {#NODE_ID}, missing =1 in the backup trigger, byte/bytes
mismatch in the task status regex, unresolved macro in a trigger name
- dropped vm.balloonmin, it reads a field the API never returns
- disk temperature for ATA and NVMe, health as a dependent item,
missing-disk trigger, dashboard cell
- README macro tables now match the template
… coverage
Adds nine endpoints that the template did not cover yet. All of them are read
with the permissions PVEAuditor already grants, except where noted.
/nodes/{node}/services PVE services, LLD with SubState
/nodes/{node}/replication ZFS replication jobs, LLD
/nodes/{node}/disks/zfs ZFS pools, LLD
/nodes/{node}/certificates/info certificate expiry, LLD
/cluster/backup-info/not-backed-up guests without a backup job
/nodes/{node}/apt/repositories broken repository files, warnings
/nodes/{node}/apt/versions pve-manager version, running kernel
/nodes/{node}/subscription subscription status
/nodes/{node}/apt/update pending updates, DISABLED by default
/apt/update is the only endpoint requiring Sys.Modify instead of Sys.Audit,
which PVEAuditor does not grant. Its items ship disabled and the repository
state is monitored through /apt/repositories instead.
Totals: 9 master items, 9 dependent items, 4 discovery rules, 18 item
prototypes, 10 triggers, 11 macros. No JavaScript preprocessing is used;
JSONPath, .length() and one calculated item are enough, since PVE already
returns last_sync and notafter as Unix epochs. Existing UUIDs are unchanged,
so importing with "Update existing" keeps the history.
Three corrections to existing objects:
- "PVE API not reachable" raised from Average to High. When the API is gone it
is the cause of every other failure, so it should outrank them.
- "High CPU usage" had the threshold 90 hardcoded in the expression while the
rest of the template uses macros. Now {$NODE.CPU.UTIL.MAX}.
- 14 numeric performance and capacity items had trends disabled and therefore
kept no data beyond the history retention: pve.cpu.utilization, the three
load average items, pve.memory.*, pve.rootfs.*, pve.swap.* and disk.wearout.
Now 365d. Timestamp items keep trends off on purpose.
Field names and required privileges were taken from the official API schema
(pve-docs/api-viewer/apidoc.js) and verified against a PVE 9.2.10 node.
Zabbix validates the UUID version on import and rejects anything else with "Invalid parameter ...: UUIDv4 is expected". The 50 UUIDs of the new objects were derived with uuid5 and therefore carried version 5. The derivation stays deterministic, the version and variant bits of a v4 are now stamped onto the digest. All 254 UUIDs in the template are version 4 and unique.
zfs.health was a text item, so it could not be graphed or shown on a dashboard
and the trigger had to compare strings. It is now UNSIGNED with a value map:
0 ONLINE, 1 DEGRADED, 2 FAULTED, 3 OFFLINE, 4 REMOVED, 5 UNAVAIL, 6 SUSPENDED.
The mapping uses a chain of STR_REPLACE preprocessing steps, not a script. The
seven state names share no substring, so step order does not matter. A state
outside the list leaves text in place and the item turns visibly unsupported
instead of reporting a wrong number.
Three triggers were missing:
- ZFS pool fragmentation above {$ZFS.FRAG.WARN}. The macro was documented with
a default of 60 but no trigger used it, so it did nothing.
- APT repository configuration has warnings, Info severity. This is the common
case of the enterprise repository being enabled without a subscription. A
host on the no-subscription repository reports one warning permanently, hence
{$PVE.APT.REPO.WARN.MAX} to raise the tolerance there.
- Package updates pending, Info severity and disabled by default, matching the
item it depends on.
The replication failure trigger now carries the error message PVE reported in
its event name, so the reason is visible without opening the item.
Verified: no threshold macro is left without a trigger using it.
The subscription due date was only available as text, without any alert.
- New item pve.subscription.nextduedate.epoch carrying the due date as a Unix
timestamp
- Trigger "expires in less than {$PVE.SUBSCRIPTION.EXPIRE.DAYS}", Warning,
lead time 30 days by default
- Trigger "has expired", Average, once the date has passed
Neither needs an enable macro: a host without a subscription reports no due
date, so the item stays empty and the triggers cannot fire.
{$PVE.SUBSCRIPTION.ALERT} still governs only the status trigger for notfound,
invalid and suspended.
Both the advance warning and the status trigger depend on the expired trigger,
so a lapsed subscription raises one problem instead of three.
This is the one place where JavaScript preprocessing is unavoidable.
/nodes/{node}/subscription reports nextduedate as a plain date string, unlike
the certificate endpoint which already delivers an epoch, and Zabbix has no
preprocessing step that parses a date. "Already expired" could be done with
date(), "expires in N days" cannot. One line, with a format check: an
unexpected format throws so the item turns visibly unsupported instead of
yielding a wrong date.
Garfieldttt
marked this pull request as ready for review
August 20, 2026 14:06
added 4 commits
August 21, 2026 09:18
Backup jobs from /cluster/backup. The template watched the backup runs only, so
a job that was disabled or is no longer advanced by the scheduler started no run,
reported no failure and stayed invisible. Adds a master item, a job counter, a
discovery rule with enabled and next run prototypes, and three triggers.
Running backups from /nodes/{node}/tasks with source=active and typefilter=vzdump.
The task list defaults to source=archive, where a task appears only once it has
finished, so a backup that never finishes produced no signal at all and the status
item kept reporting the previous successful run. Adds a master item, a running
counter, the real start time and a stuck backup trigger, plus a calculated
duration prototype for the last finished run.
Preprocessing: six JavaScript steps replaced by native JSONPath filters using &&,
|| and parentheses, twelve steps down to six. The unused {#HA_TYPE} macro is
removed together with the script that produced it.
New macros: PVE.BACKUP.JOBS.MIN, PVE.BACKUP.JOB.STALE, PVE.BACKUP.JOB.ALERT and
PVE.BACKUP.RUN.MAX.
Not yet verified against a running Zabbix server: the import itself, and whether
the engine accepts the filter expressions.
Cluster nodes total ran a script that returned the nodes field of the type=cluster entry and counted the type=node entries when that entry was missing. Both branches produce the same number: /cluster/status lists one entry per cluster member, offline ones included, and a host that is not in a cluster has no cluster entry at all and exactly one node entry. A single JSONPath filter with .length() covers both cases, the same pattern the neighbouring Cluster nodes online item already uses. Verified against a standalone node, where old and new both report 1. The item had no description and now has one. PVE disks raw ran a script that was only a guard: it passed the payload through when data was an array and returned an empty list otherwise, so a broken response produced an empty discovery instead of an error. The guard now sits where it belongs, as a custom value error handler on the discovery rule's JSONPath step. The item prototypes below it already handle their own errors. Four scripts remain, all for cases native preprocessing cannot express. PVE backup raw and PVE tasks raw deduplicate to the most recent run: the task list is sorted by pstart, which resets at every reboot, so a filter with .first() would not reliably hit the newest entry, and .max() would yield the timestamp without the status of that run. Disk temperature reads two different SMART shapes, numbered attribute 194 or 190 for ATA and SAS and the composite temperature line for NVMe, and a preprocessing pipeline cannot branch. Subscription expiry converts a date string to a Unix timestamp, for which Zabbix has no preprocessing step.
The screenshots showed Proxmox VE 8.4.6 on a light theme, captured in August 2025, with the old dashboard layout of eight pages named PVE, Storage, QEMU/KVM-VMs, LXC - Container, Backup, Nodes, Tasks and Network. The template ships five pages named Overview, Virtual machines, LXC containers, Storage and disks, and Nodes and HA, so the images no longer matched what a user gets after the import. Replaced with current captures of those five pages. The file is now identical to the README of the upstream repository.
Severities. A guest at 99% CPU for five minutes was High, which claims an
outage where there is only work: a compile, a transcode or the guest backup
itself reaches that. Lowered to Average, and the second level of the same
pair from Average to Warning, for both QEMU and LXC. High memory usage on
the node was Average although the ZFS ARC counts towards used memory, so a
ZFS host sits high permanently without being short of memory; now Warning.
High CPU average compares the load against the number of cores, which
describes a busy machine rather than an overloaded one; now Warning. The
interface down trigger went the other way, from Warning to Average: it only
fires for an interface with autostart set that was up before, so a bridge
or bond member has actually gone.
ZFS pool health was one High trigger for every state other than ONLINE.
DEGRADED means the pool lost redundancy but keeps serving, the other states
mean it does not, and the item is numeric with a value map, so the two are
now separate triggers: DEGRADED at Average, everything from FAULTED upwards
at High.
ZFS fragmentation warned on the fragmentation value alone. That value
describes the free space, not the stored data, and on a pool with room left
it costs nothing. It only starts to hurt once the pool is also filling up,
because the allocator has to work from ever smaller free segments. The
trigger now requires the usage to exceed the new macro
{$ZFS.FRAG.UTIL.MIN}, default 70, deliberately below the 80 of the usage
warning so it arrives first.
An expired certificate stayed at Warning forever, since the advance warning
keeps matching once the date has passed. Added a separate trigger for the
expired state at Average, with the advance warning depending on it, the
same pattern the subscription triggers already use.
User expiry used fuzzytime, which compares symmetrically: the problem
closed itself two days after the account had expired. Replaced with the
now() comparison used for certificates and the subscription, guarded with
a check for a non-zero timestamp so accounts that never expire, which
report 0, are excluded.
Trigger names carried macros without their context while the expression
resolved one per pool, storage or disk. A per-entity value made the alert
text wrong. The names now use the same context form as the expression.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.