zabbix_export:
  version: '7.0'
  template_groups:
    - uuid: a571c0d144b14fd4a87a9d9b2aa9fcd6
      name: Templates/Applications
  templates:
    - uuid: 21dff6fc1166411e9efb3b3dca9c8e44
      template: 'PBS Backup Monitoring'
      name: 'PBS Backup Monitoring'
      description: |
        Monitors Proxmox Backup Server backup groups via REST API.
        Dynamically discovers all datastores, namespaces, and backup groups.

        Setup:
          1. Deploy /usr/local/bin/pbs-backup-monitor on the PBS host
          2. Add /etc/zabbix/zabbix_agent2.d/pbs.conf on the PBS host
          3. Restart zabbix-agent2 on the PBS host
          4. Set host macro {$PBS.MAX.AGE.SECONDS} as needed

        Context macro key format: "{datastore}:{namespace}:{type}:{id}"
          Root namespace example:  "zfs-vol-02::vm:1001"
          Sub-namespace example:   "zfs-vol-02:cluster-a:vm:1001"
      groups:
        - name: Templates/Applications
      items:
        - uuid: effb30a9ab3c4046b173d0861650075a
          name: 'PBS: All backup groups'
          key: pbs.groups.all
          delay: 5m
          history: 1h
          value_type: TEXT
          trends: '0'
          description: |
            Master item. Fetches all backup groups from all datastores and namespaces via PBS REST API.
            Returns a JSON array used by dependent LLD rules and item prototypes.
          tags:
            - tag: component
              value: backup
      discovery_rules:
        - uuid: a4f9f0107cd540008cc4eff65c2b399b
          name: 'PBS backup group discovery'
          type: DEPENDENT
          key: pbs.groups.discovery
          delay: '0'
          enabled_lifetime_type: DISABLE_NEVER
          description: |
            Discovers all PBS backup groups (vm, host, ct) across all datastores and namespaces.
            Depends on master item pbs.groups.all.
          item_prototypes:
            - uuid: ca1ee8d6806d4c0b80d7038e98b99155
              name: '{#DATASTORE}:{#NAMESPACE}:{#TYPE}/{#ID}: Last backup age'
              type: DEPENDENT
              key: 'pbs.group.age[{#DATASTORE},{#NAMESPACE},{#TYPE},{#ID}]'
              delay: '0'
              history: 7d
              trends: 90d
              units: s
              description: 'Seconds elapsed since the latest backup snapshot for this group.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$[?(@.datastore=="{#DATASTORE}" && @.namespace=="{#NAMESPACE}" && @.type=="{#TYPE}" && @.id=="{#ID}")]'
                - type: JAVASCRIPT
                  parameters:
                    - |
                      var g = JSON.parse(value);
                      if (!g || g.length === 0) return -1;
                      var age = Math.floor(Date.now() / 1000) - g[0].last_backup;
                      return age < 0 ? -1 : age;
              master_item:
                key: pbs.groups.all
              tags:
                - tag: component
                  value: backup
                - tag: datastore
                  value: '{#DATASTORE}'
              trigger_prototypes:
                - uuid: cd9b4d3b4644442a84434116d4d3a945
                  expression: 'last(/PBS Backup Monitoring/pbs.group.age[{#DATASTORE},{#NAMESPACE},{#TYPE},{#ID}]) > {$PBS.MAX.AGE.SECONDS:"{#DATASTORE}:{#NAMESPACE}:{#TYPE}:{#ID}"} and last(/PBS Backup Monitoring/pbs.group.age[{#DATASTORE},{#NAMESPACE},{#TYPE},{#ID}]) >= 0'
                  name: '{#DATASTORE}:{#NAMESPACE}:{#TYPE}/{#ID}: Backup is too old'
                  event_name: '{#DATASTORE}:{#NAMESPACE}:{#TYPE}/{#ID}: Last backup older than {$PBS.MAX.AGE.SECONDS:"{#DATASTORE}:{#NAMESPACE}:{#TYPE}:{#ID}"}s'
                  opdata: 'Age: {ITEM.LASTVALUE1}'
                  priority: HIGH
                  description: |
                    The latest backup snapshot for this group is older than {$PBS.MAX.AGE.SECONDS} seconds.
                    Check if the backup job is running correctly.
                  tags:
                    - tag: scope
                      value: availability
            - uuid: a273cbe40bdd4b7cbffbd83d976ce991
              name: '{#DATASTORE}:{#NAMESPACE}:{#TYPE}/{#ID}: Snapshot count'
              type: DEPENDENT
              key: 'pbs.group.count[{#DATASTORE},{#NAMESPACE},{#TYPE},{#ID}]'
              delay: '0'
              history: 7d
              trends: 90d
              description: 'Number of backup snapshots retained for this group.'
              preprocessing:
                - type: JSONPATH
                  parameters:
                    - '$[?(@.datastore=="{#DATASTORE}" && @.namespace=="{#NAMESPACE}" && @.type=="{#TYPE}" && @.id=="{#ID}")]'
                - type: JAVASCRIPT
                  parameters:
                    - |
                      var g = JSON.parse(value);
                      return (g && g.length > 0) ? g[0].count : 0;
              master_item:
                key: pbs.groups.all
              tags:
                - tag: component
                  value: backup
                - tag: datastore
                  value: '{#DATASTORE}'
              trigger_prototypes:
                - uuid: cc9a651146c443558abf69a2f02b3bec
                  expression: 'last(/PBS Backup Monitoring/pbs.group.count[{#DATASTORE},{#NAMESPACE},{#TYPE},{#ID}]) = 0'
                  name: '{#DATASTORE}:{#NAMESPACE}:{#TYPE}/{#ID}: No backup snapshots'
                  priority: HIGH
                  description: 'This backup group has no snapshots at all.'
                  tags:
                    - tag: scope
                      value: availability
          master_item:
            key: pbs.groups.all
          lld_macro_paths:
            - lld_macro: '{#DATASTORE}'
              path: $.datastore
            - lld_macro: '{#ID}'
              path: $.id
            - lld_macro: '{#NAMESPACE}'
              path: $.namespace
            - lld_macro: '{#TYPE}'
              path: $.type
      macros:
        - macro: '{$PBS.MAX.AGE.SECONDS}'
          value: '108000'
          description: 'Alert threshold for backup age (default: 30 hours = 108000s)'
