Skip to content

Data Models

netbox-packer defines five Django models. All extend NetBoxModel and support NetBox's standard features (change logging, tags, custom fields, object permissions).


PackerInstallerConfig

An OS-installer configuration file stored verbatim in the database. Used as the content source for a PackerBuild. The checksum field (SHA-256 hex digest) is computed automatically on every save() and written to PackerTemplate.installer_config_checksum_at_build at build time so staleness detection can identify out-of-date templates.

Field Type Notes
name CharField(100)
os_family CharField(20) Choices from OSFamilyChoices
installer_type CharField(20) autoinstall, kickstart, preseed, or cloud_config
content TextField Verbatim installer payload (e.g. the full #cloud-config YAML)
version CharField(40) Default "1.0.0"
checksum CharField(64) SHA-256 hex of content; auto-computed, not editable
description TextField Blank allowed

Unique constraint: (name, version).

installer_type values:

Value Label
autoinstall Cloud-init autoinstall (Ubuntu)
kickstart Anaconda kickstart (RHEL-family)
preseed d-i preseed (Debian)
cloud_config Cloud-config YAML (#cloud-config, Proxmox/generic)

Only cloud_config triggers the proxbox-api cloud-init bake path. All other types are run via packer build.


PackerTemplate

A Proxmox VM template definition with lifecycle tracking. Ties together an installer config, target node/storage, and monitoring-agent injection preferences.

Field Type Default Notes
name CharField(100)
os_family CharField(20) Choices from OSFamilyChoices
os_version CharField(40) e.g. 24.04. The web form renders this as a dropdown grouped by OS family (OS_VERSIONS_BY_FAMILY in choices.py); the model/API stay free-form so automation can send any version.
proxmox_template_id PositiveIntegerField Proxmox VMID for the resulting template
proxmox_endpoint URLField blank Proxmox API URL (used to derive SSH host)
proxmox_node CharField(100) Proxmox node name or IP
storage_pool CharField(100) blank Proxmox storage pool name (default: local)
storage_pool_type CharField(20) blank Choices from StoragePoolTypeChoices
storage_format CharField(10) blank Choices from StorageFormatChoices
cloud_init_ready BooleanField True Template supports cloud-init
min_cpu_type CharField(40) blank Minimum CPU type required
build_status CharField(20) pending pending, building, ready, failed
built_at DateTimeField null Set by PackerBuildJob on success
packer_template_ref CharField(255) blank Path/ref to the HCL2 Packer template file
max_age_days PositiveIntegerField null Trigger staleness after N days
auto_rebuild BooleanField False Auto-rebuild stale templates
description TextField blank
installer_config FK → PackerInstallerConfig null SET_NULL; drives build type
installer_config_checksum_at_build CharField(64) blank Snapshot of checksum at last successful build

Template form vs. model fields

The template add/edit form intentionally hides machine-managed lifecycle fields (built_at, packer_template_ref, and installer_config_checksum_at_build) — they are written by PackerBuildJob, not by operators. The full set of fields is still available through the REST API. The form also renders os_version as an OS-family-grouped dropdown and carries help text on the key cloud-init-template fields (os_version, proxmox_template_id, storage_pool, cloud_init_ready, installer_config).

Monitoring agent injection fields (added in migration 0008)

These fields control what PackerBuildJob._inject_monitoring_agents() adds to cloud_config content at build time. They have no effect on non-cloud_config installer types.

Field Type Default Notes
install_qemu_guest_agent BooleanField True Inject qemu-guest-agent package + systemctl enable --now runcmd into the cloud-config; skipped if qemu-guest-agent already appears in the installer config's packages list
install_zabbix_agent2 BooleanField True Inject Zabbix Agent 2 bootstrap script into write_files + runcmd; skipped entirely when "zabbix-agent2" appears anywhere in the installer config (e.g. the Zabbix server seed manages its own agent)
zabbix_server CharField(255) "zabbix.nmulti.cloud" ServerActive= value in the injected zabbix_agent2.conf; validated against hostname/IP + optional :port, comma-separated; no spaces or shell metacharacters

HCP Packer fields

hcp_bucket_name, hcp_channel_name, hcp_iteration_id, hcp_build_id, hcp_last_synced_at — store HCP Packer registry metadata. All blank by default.

Computed properties

Property Returns
age_days Days since built_at, or None when not yet built
is_stale True when age_days > max_age_days or installer_config.checksum != installer_config_checksum_at_build
derived_vms VirtualMachine queryset where custom_field_data__source_packer_template == self.pk

PackerBuild

A single build-run record for a PackerTemplate. Created by PackerTemplateViewSet.build() and executed asynchronously by PackerBuildJob.

Not a jobs-assignable object type

PackerBuild is not registered as a NetBox jobs-assignable object type. Always enqueue with PackerBuildJob.enqueue(build_id=build.pk) and never pass instance=build. Passing instance= raises "Jobs cannot be assigned to this object type" and the Build button will silently do nothing.

Field Type Default Notes
template FK → PackerTemplate CASCADE
triggered_by CharField(100) blank Username or trigger source
queued_at DateTimeField auto_now_add
started_at DateTimeField null Set when job starts running
finished_at DateTimeField null Set on success or failure
status CharField(20) queued queued, running, success, failed, cancelled
variable_overrides JSONField {} Per-build overrides (e.g. image_url, ssh_host)
log TextField blank Accumulated build output
exit_code IntegerField null Exit code from packer build or proxbox-api response
result_template_id IntegerField null Proxmox VMID of the completed template
selected_node CharField(100) blank Proxmox node selected by select_build_node()

PackerBuildTarget

A multi-cluster target entry for distributing builds across Proxmox nodes. select_build_node() iterates enabled targets in ascending priority order, skipping nodes at MAX_CONCURRENT_BUILDS_PER_NODE capacity. Falls back to the template's primary node when no targets exist or all targets are exhausted.

Field Type Default Notes
template FK → PackerTemplate CASCADE; related_name="build_targets"
proxmox_endpoint URLField blank Proxmox API URL for this target
proxmox_node CharField(100) Node name or IP
priority PositiveIntegerField 10 Lower = higher priority
enabled BooleanField True Disabled targets are skipped

Unique constraint: (template, proxmox_node).


PackerPluginSettings

Singleton settings row for the plugin. Exactly one row exists; use PackerPluginSettings.get_solo() to retrieve it.

Field Type Default Notes
singleton_key CharField(32) "default" Not editable; forced to "default" on every save()
branching_enabled BooleanField False When True, PackerStalenessCheckJob uses netbox-branching for stale updates
branch_name_prefix CharField(64) "packer-stale" Prefix for auto-created branch names
branch_on_conflict CharField(16) "fail" "fail" or "acknowledge" — behavior on branching merge conflicts
proxbox_api_url URLField blank Base URL of the proxbox-api backend; required for cloud_config builds
proxbox_api_key_encrypted CharField(512) blank Fernet-encrypted API key; not editable directly — use set_proxbox_api_key()

Key-management methods

settings_row = PackerPluginSettings.get_solo()

# Store a new API key (encrypts in-place using settings.SECRET_KEY)
settings_row.set_proxbox_api_key("my-secret-key")
settings_row.save()

# Retrieve the decrypted key at job time
api_key = settings_row.get_proxbox_api_key()

The Fernet cipher is derived from settings.SECRET_KEY (SHA-256 → base64url). There is no dependency on netbox-nms for key management.