Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
*.py[cod]
17 changes: 17 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## [Unreleased]

### New features

- Added `exclude_tag` configuration setting to exclude hosts from Zabbix sync entirely via a ZabbixTag assigned to any object in the inheritance chain (`ZabbixTag.tag` name match)
- Added Site/SiteGroup/Region inheritance paths (appended after role/platform so upgrades do not change Role/Platform precedence); cluster site uses `cluster._site` for VM site scope
- Added NetBox Tag as an assignment target: any assignment can be pointed at a Tag; tagged Devices/VMs/VDCs inherit it at object level with automatic add/remove lifecycle (`Tag: <name>` shown as source)

### Improvements

- Plugin requires NetBox ≥4.2.6 (`PluginConfig.min_version`)
- Inherited sync status on the Zabbix tab uses a neutral indicator (distinct from a direct local assignment)

### Bug fixes

- VirtualMachines no longer inherit assignments via `device`-prefixed `inheritance_chain` paths. On NetBox 4.3+, `VirtualMachine.device` links a guest to its hosting device; skipping those paths prevents host manufacturer/role/device-type templates from leaking onto guests. Virtual Device Contexts still walk those paths

## [1.0.0] - Initial Release

- Loads of features, :)
Expand Down
54 changes: 53 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ The plugin is configuration to do exactly what you want, by means of the plugin
['cluster'],
['cluster', 'type'],
['type'],
# Hierarchy appended after device/role/platform (first-seen wins)
['device', 'site'],
['site'],
['site', 'group'],
['site', 'region'],
['cluster', '_site'],
],
'backgroundsync': {
'objects': {
Expand Down Expand Up @@ -105,10 +111,46 @@ The plugin is configuration to do exactly what you want, by means of the plugin
'objtag_type': 'nb_type',
'objtag_id': 'nb_id',
'custom_field_hostname':'',
'custom_field_display_name':''
'custom_field_display_name':'',
'exclude_tag': '',
}
```

## Inheritance Chain

The `inheritance_chain` setting defines which NetBox objects are traversed when resolving Zabbix assignments. Assignments (templates, tags, hostgroups, macros, proxy/server, interfaces, inventory, configuration groups) made on any object in the chain are inherited by the device or VM being synced, with direct assignments taking priority. Within inherited sources, **first path wins** (leaf-first order as listed).

Host interfaces are the exception: they are defined on a Device/VM directly, on a `ZabbixConfigurationGroup`, or on a NetBox Tag (as a reusable interface template), because an interface needs a per-device endpoint. To apply interfaces to a whole Site, SiteGroup or Region, assign a Configuration Group at that level — its interfaces are then cloned onto every inheriting device with that device's primary IP.

### VirtualMachine and `device`-prefixed paths

Paths that start with `device` (for example `['device']`, `['device', 'role']`, `['device', 'device_type', 'manufacturer']`) describe the associated physical device.

Virtual Device Contexts keep these paths (a VDC is part of its parent device). VirtualMachines skip them: on NetBox 4.3+, `VirtualMachine.device` links a guest to its hosting device, and walking that path would leak host hardware assignments onto the guest. VMs still inherit via cluster, site, role, platform and tag paths that apply to the VM itself.

### Site, SiteGroup, and Region Inheritance

Hierarchy paths are appended after device/role/platform/manufacturer/cluster paths so upgrading into Site inheritance does not silently override existing Role or Platform assignments. SiteGroup and Region ancestors are walked automatically when a group or region is reached.

| Path | Description |
|------|-------------|
| `['device', 'site']` | The device's site (also VDC → device → site; not walked for VirtualMachines) |
| `['site']` | Site (direct) |
| `['site', 'group']` | The site's SiteGroup (parents walked) |
| `['site', 'region']` | The site's region (parents walked) |
| `['cluster', '_site']` | The cluster's scoped site for VMs (`CachedScopeMixin._site`) |

If you previously customized `inheritance_chain` with Site paths ahead of Role/Platform, review hosts that have both a Site-level and a Role/Platform-level assignment — effective winners may change. Prefer appending hierarchy paths.

For example, assigning a `ZabbixServerAssignment` (proxy) to a `SiteGroup` means every device at every site in that SiteGroup inherits the proxy — no per-device assignment needed.

### Tag-based assignments

NetBox Tags are assignment targets: hostgroup, template, tag, macro, server, inventory, configuration group and host interface assignments can be pointed at a Tag. Every Device, VDC or VirtualMachine carrying that tag then inherits the assignment. Direct assignments on the object still take priority. Tag-targeted rows are collected before the `inheritance_chain` paths (first seen wins).

Tagging an object adds the membership on the next sync; removing the tag removes it. The inherited source is shown as `Tag: <name>`. Create Tag-targeted assignments via the API (`assigned_object_type` / `assigned_object_id`); the assignment forms expose Site hierarchy pickers but not a Tag picker.


## Configuration values

### Source of Truth
Expand Down Expand Up @@ -270,6 +312,16 @@ These tags allow you to navigate from a Zabbix host back to the corresponding N
### custom_field_hostname and custom_field_display_name
You can use these fields to map the connection between NetBox and the Zabbix hostname and display name. The device name is used as the default.

### exclude_tag

When set to a non-empty string (e.g. `'do_not_monitor'`), any `ZabbixTagAssignment` with a tag matching this name — whether assigned directly on a Device/VM or inherited from a Role, Platform, Site, SiteGroup, Region, Manufacturer, or Configuration Group — causes the host to be excluded from Zabbix sync entirely. No Zabbix host is created, and if a host was previously synced it is deleted from Zabbix.

This is useful for excluding device classes that should never be monitored (e.g. desktop PCs, VDI sessions, test lab devices) without removing their Site or Platform assignments.

The tag itself is never pushed to Zabbix — it is only used as a signal during sync resolution and is filtered out before Jinja2 rendering.

Defaults to `''` (empty string = feature disabled).

## Enabling and Disabling Synchronization

Two separate `sync_enabled` flags control whether synchronization to Zabbix is active.
Expand Down
39 changes: 16 additions & 23 deletions docs/dynamic_values.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,9 @@ For example, if a Hostgroup is given the value:
{{ object.site.name }}
```

and is applied to a `Device`, it will render as the device's `Site Name`. Here, object refers to the entity to which the assignment is made. This distinction is important: if a `Hostgroup` is assigned to a `DeviceType`, then the `DeviceType` becomes the object—even if the `Hostgroup` is later inherited by a `Device`.
and is applied to a `Device`, it will render as the device's Site name.

Therefore, using the following template:

```jinja2
{{ object.site.name }}
```

on a `DeviceType` does not make sense, because a `DeviceType` does not have a `Site` attribute.
During host synchronisation, tag, macro and host-inventory templates are rendered against the Device, VDC or VirtualMachine being synced — even when the assignment is inherited. Hostgroup templates still render with `object` as the assignment target, so hostgroup Jinja that needs host fields should be assigned where those fields exist.

## Context

Expand All @@ -38,32 +32,31 @@ Tags are rendered within a context that includes the following information:

| Key | Value | Explanation |
|-------------|-----------------------|----------------------------------------------------------------------------------------------|
| object | assigned_object | Refers to the assigned object; this could be a DeviceType, Device, VirtualMachine, etc. |
| tag | zabbixtag.tag | Contains the Zabbix Tag value that this assignment refers to |
| value | zabbixtag.value | The value of the Zabbix Tag (typically the Jinja2 template) |
| name | zabbixtag.name | The name of the Zabbix Tag |
| description | zabbixtag.description | The description of the Zabbix Tag |
| object | assigned_object | The assignment target. During host sync this is the Device/VM/VDC being synced |
| tag | zabbixtag.tag | Contains the Zabbix Tag value that this assignment refers to |
| value | zabbixtag.value | The value of the Zabbix Tag (typically the Jinja2 template) |
| name | zabbixtag.name | The name of the Zabbix Tag |
| description | zabbixtag.description | The description of the Zabbix Tag |

### Hostgroup

Just like tags, hostgroups are rendered in a context:

| Key | Value | Explanation |
|-------------|-----------------------|----------------------------------------------------------------------------------------------|
| object | assigned_object | Refers to the assigned object; this could be a DeviceType, Device, VirtualMachine, etc. |
| value | zabbixhostgroup.value | The value of the Zabbix Hostgroup (typically the Jinja2 template) |
| name | zabbixhostgroup.name | The name of the Zabbix Hostgroup |
| Key | Value | Explanation |
|-------------|-----------------------|-------------|
| object | assigned_object | The assignment target (not overridden to the synced host during host sync) |
| value | zabbixhostgroup.value | The value of the Zabbix Hostgroup (typically the Jinja2 template) |
| name | zabbixhostgroup.name | The name of the Zabbix Hostgroup |

### Host Inventory

Each field on a `ZabbixHostInventory` record is rendered individually. The context is simpler than for tags and hostgroups:

| Key | Value | Explanation |
|----------|------------------|--------------------------------------------------------------|
| `object` | assigned_object | The Device, VDC, or VirtualMachine this inventory belongs to |
| Key | Value | Explanation |
|----------|------------------|-------------|
| `object` | assigned_object | The assignment target. During host sync this is the Device/VM/VDC being synced |

Because `ZabbixHostInventory` is assigned directly to a Device, VDC, or VM (never to a DeviceType or other inheritance-chain object), `object` always
refers to the host itself. This means device attributes like `object.site.name`, `object.rack.name`, or `object.primary_ip` are always available and always resolve to the correct host.
Inventory can be assigned on hierarchy objects and inherited; during host sync `object` is the host, so fields such as `object.site.name` or `object.primary_ip` resolve correctly.

Note that each field has a maximum character length enforced at render time, values that exceed the limit are silently truncated. The `inventory_mode` field controls how Zabbix treats the inventory:
- `Manual` (the default) means Zabbix only updates inventory via the API, which is how nbxSync writes it.
Expand Down
8 changes: 7 additions & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Also, replace `netbox_secrets` with `nbxsync` obviously.
## Normal install
### Prerequisites

- NetBox >= 4.x
- NetBox >= 4.2.6
- Python >= 3.8
- Zabbix server >= 7.0

Expand Down Expand Up @@ -85,6 +85,11 @@ PLUGINS_CONFIG = {
['cluster'],
['cluster', 'type'],
['type'],
['device', 'site'],
['site'],
['site', 'group'],
['site', 'region'],
['cluster', '_site'],
],
'backgroundsync': {
'objects': {
Expand Down Expand Up @@ -112,6 +117,7 @@ PLUGINS_CONFIG = {
'objtag_id': 'nb_id',
'custom_field_hostname': '',
'custom_field_display_name': '',
'exclude_tag': '',
}
}
```
Expand Down
Loading