Skip to content

Commit

Permalink
Update README, run GC every 24h
Browse files Browse the repository at this point in the history
  • Loading branch information
pederhan committed Aug 1, 2024
1 parent aeedca5 commit 95d4531
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
64 changes: 55 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ This is a crash course in how to quickly get this application up and running in
Setup a Zabbix test instance with [podman](https://podman.io/) and [podman-compose](https://github.com/containers/podman-compose/).

```bash
TAG=7.0-alpine-latest ZABBIX_PASSWORD=secret podman-compose up -d
TAG=7.0-ubuntu-latest ZABBIX_PASSWORD=secret podman-compose up -d
```

## Zabbix prerequisites
Expand All @@ -46,6 +46,8 @@ For automatic linking in templates you could create the templates:

## Database

The application requires a PostgreSQL database to store the state of the collected hosts. The database can be created with the following command:

```bash
PGPASSWORD=secret psql -h localhost -U postgres -p 5432 -U zabbix << EOF
CREATE DATABASE zac;
Expand All @@ -59,11 +61,13 @@ CREATE TABLE hosts_source (
EOF
```

Replace login credentials with your own when running against a different database. This is a one-time procedure per environment.

## Application

### Installation (production)
### Installation

For production, installing the project in a virtual environment directly with pip is the recommended way to go:
Installing the project in a virtual environment directly with pip is the recommended way to go:

```bash
python -m venv venv
Expand Down Expand Up @@ -144,7 +148,7 @@ zac

## Systemd unit

You could run this as a systemd service:
To add automatic startup of the application with systemd, create a unit file in `/etc/systemd/system/zabbix-auto-config.service`:

```ini
[Unit]
Expand All @@ -158,16 +162,24 @@ WorkingDirectory=/home/zabbix/zabbix-auto-config
Environment=PATH=/home/zabbix/zabbix-auto-config/venv/bin
ExecStart=/home/zabbix/zabbix-auto-config/venv/bin/zac
TimeoutSec=300
Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target
```

## Source collectors

ZAC relies on "Source Collectors" to fetch host data from various sources.
A source can be anything; an API, a file, a database, etc. What matters is that
the source is able to return a list of `zabbix_auto_config.models.Host` objects. ZAC uses these objects to create or update hosts in Zabbix. If a host with the same hostname is collected from multiple different sources, its information is combined into a single logical host object before being used to create/update the host in Zabbix.

### Writing a source collector

Source collectors are Python modules placed in a directory specified by the `source_collector_dir` option in the `[zac]` table of the configuration file. Zabbix-auto-config attempts to load all modules referenced by name in the configuration file from this directory. If any referenced modules cannot be found in the directory, they will be ignored.

A source collector module contains a function named `collect` that returns a list of `Host` objects. These host objects are used by Zabbix-auto-config to create or update hosts in Zabbix.
A source collector module contains a function named `collect()` that returns a list of `Host` objects. These host objects are used by Zabbix-auto-config to create or update hosts in Zabbix.

Here's an example of a source collector module that reads hosts from a file:

Expand All @@ -187,7 +199,7 @@ def collect(*args: Any, **kwargs: Any) -> List[Host]:
return [Host(**host) for host in json.load(f)]
```

A module is recognized as a source collector if it contains a `collect` function that accepts an arbitrary number of arguments and keyword arguments and returns a list of `Host` objects. Type annotations are optional but recommended.
A module is recognized as a source collector if it contains a `collect()` function that accepts an arbitrary number of arguments and keyword arguments and returns a list of `Host` objects. Type annotations are optional but recommended.

We can also provide a `if __name__ == "__main__"` block to run the collector standalone. This is useful for testing the collector module without running the entire application.

Expand All @@ -207,6 +219,7 @@ if __name__ == "__main__":
f.write(hosts_to_json(collect()))
```

### Configuration

The configuration entry for loading a source collector module, like the `load_from_json.py` module above, includes both mandatory and optional fields. Here's how it can be configured:

Expand All @@ -218,9 +231,12 @@ error_tolerance = 5
error_duration = 360
exit_on_error = false
disable_duration = 3600
# Extra keyword arguments to pass to the collect function:
filename = "hosts.json"
```

Only the extra `filename` option is passed in as a kwarg to the `collect()` function.

The following configurations options are available:

### Mandatory configuration
Expand All @@ -229,13 +245,12 @@ The following configurations options are available:
`module_name` is the name of the module to load. This is the name that will be used in the configuration file to reference the module. It must correspond with the name of the module file, without the `.py` extension.

#### update_interval
`update_interval` is the number of seconds between updates. This is the interval at which the `collect` function will be called.
`update_interval` is the number of seconds between updates. This is the interval at which the `collect()` function will be called.

### Optional configuration (error handling)

If `error_tolerance` number of errors occur within `error_duration` seconds, the collector is disabled. Source collectors do not tolerate errors by default and must opt-in to this behavior by setting `error_tolerance` and `error_duration` to non-zero values. If `exit_on_error` is set to `true`, the application will exit. Otherwise, the collector will be disabled for `disable_duration` seconds.


#### error_tolerance

`error_tolerance` (default: 0) is the maximum number of errors tolerated within `error_duration` seconds.
Expand All @@ -258,13 +273,16 @@ A useful guide is to set `error_duration` as `(error_tolerance + 1) * update_int

### Keyword arguments

Any extra config options specified in the configuration file will be passed to the `collect` function as keyword arguments. In the example above, the `filename` option is passed to the `collect` function, and then accessed via `kwargs["filename"]`.
Any extra config options specified in the configuration file will be passed to the `collect()` function as keyword arguments. In the example above, the `filename` option is passed to the `collect()` function, and then accessed via `kwargs["filename"]`.


## Host modifiers

Host modifiers are Python modules (files) that are placed in a directory defined by the option `host_modifier_dir` in the `[zac]` table of the config file. A host modifier is a module that contains a function named `modify` that takes a `Host` object as its only argument, modifies it, and returns it. Zabbix-auto-config will attempt to load all modules in the given directory.


### Writing a host modifier

A host modifier module that adds a given siteadmin to all hosts could look like this:

```py
Expand Down Expand Up @@ -292,6 +310,34 @@ Zac manages only inventory properties configured as `managed_inventory` in `conf
2. Remove the "location" property from the host in the source
3. "location=x" will remain in Zabbix

## Garbage Collection

ZAC provides an optional Zabbix garbage collection module that cleans up stale data from Zabbix that is not otherwise managed by ZAC, such as maintenances.

The garbage collector currently does the following:

- Removes disabled hosts from maintenances.
- Deletes maintenances that only contain disabled hosts.

Under normal usage, hosts are removed from maintenances when being disabled by ZAC, but if hosts are disabled outside of ZAC, they will not be removed from maintenances. The GC module will remove these hosts, and optionally delete the maintenance altogether if it only contains disabled hosts.

To enable garbage collection, add the following to your config:

```toml
[zac.process.garbage_collector]
enabled = true
delete_empty_maintenance = true
```

By default, the garbage collector runs every 24 hours. This can be adjusted with the `update_interval` option:

```toml
[zac.process.garbage_collector]
update_interval = 3600 # Run every hour
```

----

## Development

We use the project management tool [Hatch](https://hatch.pypa.io/latest/) for developing the project. The tool manages virtual environment creation, dependency installation, as well as building and publishing of the project, and more.
Expand Down
11 changes: 6 additions & 5 deletions config.sample.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ update_interval = 60
update_interval = 60

[zac.process.garbage_collector]
# Enable or disable the automatic removal of disabled hosts from maintenances and triggers
enabled = true
# Delete maintenance windows altogether if all hosts within them are disabled
delete_empty_maintenance = true
update_interval = 300
# Enable garbage collection, including:
# - Remove disabled hosts from maintenances
enabled = false
# Delete maintenances if all its hosts are disabled
delete_empty_maintenance = false
update_interval = 86400 # every 24 hours


[zabbix]
Expand Down
2 changes: 1 addition & 1 deletion zabbix_auto_config/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class ProcessesSettings(ConfigBaseModel):
hostgroup_updater: HostGroupUpdaterSettings = HostGroupUpdaterSettings()
template_updater: TemplateUpdaterSettings = TemplateUpdaterSettings()
garbage_collector: GarbageCollectorSettings = GarbageCollectorSettings(
update_interval=300
update_interval=86400 # every 24 hours
)


Expand Down

0 comments on commit 95d4531

Please sign in to comment.