Module proxmox

Proxmox adapter

  • License: Inmanta EULA

  • Version: 0.0.1

Entities

entity proxmox::Credentials

Parents: std::Entity

Credentials used to communicate with a Proxmox VE instance.

attribute string url

Base URL to the Proxmox VE instance (e.g. https://pve-host:8006)

attribute string api_token_id

API token identifier in the format USER@REALM!TOKENID

attribute string api_token_secret

API token secret (UUID)

attribute bool verify=false

Whether to verify the SSL certificate

attribute bool agent_autostart=true

Configure default local agent for resources using these credentials

attribute string? agent_name=null

Name of the agent for the resources using these credentials

attribute string resolved_agent_name

The following implementations are defined for this entity:

The following implements statements select implementations for this entity:

entity proxmox::NodeScopedResource

Parents: proxmox::Resource

Base for resources scoped to a specific PVE node.

attribute string node
entity proxmox::Resource

Parents: std::PurgeableResource, std::ManagedResource

Base entity for all Proxmox resources.

attribute bool send_event=true
relation proxmox::Credentials credentials [1]
entity proxmox::resources::ACL

Parents: proxmox::Resource

A single ACL grant on a PVE path. Exactly one of userid or group must be set.

PVE has no per-entry ACL endpoint — ACL writes go through the bulk PUT /access/acl (with delete=1 to revoke). This resource models one (path, user_or_group, role) grant; multi-user or multi-role grants must be expressed as multiple resources.

attribute string path

ACL object path (e.g. / or /storage/local-lvm).

attribute string? userid=null

Grantee user (e.g. admin@pve). Set this or group, not both.

attribute string? group=null

Grantee group. Set this or userid, not both.

attribute string role

Role to grant (e.g. Administrator, PVEAdmin).

attribute bool? propagate=null

Whether the grant propagates to children. PVE defaults to true.

The following implements statements select implementations for this entity:

entity proxmox::resources::APIToken

Parents: proxmox::Resource

API token for a PVE user.

The token secret is generated by PVE on creation and is returned only once. It cannot be retrieved later. The handler captures the secret via ctx.set_fact("token_secret", ...) so it can be obtained from the Inmanta facts store after the create deploy. The model does NOT have a secret attribute and the secret is not round-tripped through PVE.

attribute string userid

Owning user, e.g. root@pam.

attribute string tokenid

Token identifier under the user, e.g. inmanta. The full PVE token id is <userid>!<tokenid>.

attribute string? comment=null

Optional comment.

attribute bool? privsep=null

Privilege separation. PVE defaults to true; set to false to make the token inherit the owning user’s full ACL.

attribute string? expire=null

Token expiration as an epoch timestamp; 0 means never.

The following implements statements select implementations for this entity:

entity proxmox::resources::BondInterface

Parents: proxmox::NodeScopedResource

Proxmox bond network interface.

Network changes on a PVE node are staged in /etc/network/interfaces.new and only become active after a NetworkApply resource is applied.

attribute string iface

The bond interface name (e.g. bond0)

attribute string? slaves=null

Bond member interfaces, space-separated (e.g. “eth0 eth1”)

attribute string? bond_mode=null

Bonding mode (e.g. “802.3ad”, “active-backup”, “balance-rr”)

attribute string? bond_xmit_hash_policy=null

Transmit hash policy for 802.3ad/balance-xor (e.g. “layer2+3”)

attribute string? cidr=null

IPv4 address with prefix (e.g. “10.0.0.1/24”)

attribute string? gateway=null

Default gateway IPv4 address

attribute bool? autostart=null

Bring the interface up automatically at boot

attribute int? mtu=null

Maximum transmission unit

attribute string? comments=null

Free-form comments on the interface

The following implements statements select implementations for this entity:

entity proxmox::resources::ConfigDriveISO

Parents: proxmox::NodeScopedResource

A small ISO built by the Inmanta agent from a set of in-memory files and uploaded to a PVE node storage (web UI: Storage > ISO Images) via POST /nodes/{node}/storage/{storage}/upload. Attach it to a VM as a CD-ROM (QemuVM.ide2 = "{storage}:iso/{filename},media=cdrom") to deliver a cloud-init / OpenStack config-2 config-drive — e.g. a FortiGate user_data blob. This is the Proxmox analogue of vcenter::CreateISO.

The ISO content and volume_label are create-only inputs; PVE does not echo them back and the diff ignores them. A change requires purge + re-create.

attribute string storage

target storage id (e.g. local). Must support the iso content type.

attribute string filename

ISO filename to write into the storage (must end in .iso, e.g. cloudinit-5001.iso).

attribute dict content

map of in-ISO absolute file path -> file content, e.g. {"/openstack/latest/user_data": "..."}.

attribute string volume_label='config-2'

ISO9660 volume id. Defaults to config-2, the OpenStack config-drive label cloud-init looks for.

The following implements statements select implementations for this entity:

entity proxmox::resources::DownloadedImage

Parents: proxmox::NodeScopedResource

A file fetched by the PVE node from an HTTP(S) URL into one of its storages, via the per-node Storage.Download.URL API endpoint (web UI: Storage > Download from URL). Use this to land a vendor qcow2, ISO, or LXC template directly without staging the file on the host running the Inmanta agent — the PVE node fetches it.

The download parameters (url, checksum, compression, verify_certificates) are inputs to create only; PVE does not echo them back and the diff ignores them. Change requires purge + re-create.

attribute string storage

target storage id (e.g. local). Must support the requested content type.

attribute string filename

filename to write into the storage. PVE normalises this — pick something sane (alphanumerics, dashes, dots).

attribute string url

HTTP(S) source URL. Fetched by the PVE node.

attribute string content='import'

PVE content type — import (VM disk images), iso (ISO images), or vztmpl (LXC templates).

attribute string? checksum=null

optional checksum to verify against after download

attribute string? checksum_algorithm=null

algorithm matching checksum (md5|sha1|sha224|sha256|sha384|sha512)

attribute string? compression=null

optional decompression algorithm (e.g. gz)

attribute bool verify_certificates=true

verify TLS certs on the source URL

The following implements statements select implementations for this entity:

entity proxmox::resources::LinuxBridge

Parents: proxmox::NodeScopedResource

Proxmox Linux bridge network interface.

Network changes on a PVE node are staged in /etc/network/interfaces.new and only become active after a NetworkApply resource is applied.

attribute string iface

The bridge interface name (e.g. vmbr0, vmbr1)

attribute string? bridge_ports=null

Bridge member ports, space-separated (e.g. “eth0”, “none”)

attribute bool? bridge_vlan_aware=null

Enable VLAN awareness on the bridge

attribute string? cidr=null

IPv4 address with prefix (e.g. “10.0.0.1/24”)

attribute string? gateway=null

Default gateway IPv4 address

attribute string? comments=null

Free-form comments on the interface

attribute bool? autostart=null

Bring the interface up automatically at boot

attribute int? mtu=null

Maximum transmission unit

The following implements statements select implementations for this entity:

entity proxmox::resources::LxcContainer

Parents: proxmox::NodeScopedResource

Proxmox LXC container.

attribute int vmid

The unique container ID

attribute string? ostemplate=null

OS template (e.g. local:vztmpl/debian-12-standard_12.2-1_amd64.tar.zst)

attribute string? hostname=null

Container hostname

attribute int? memory=null

Memory in MB

attribute int? swap=null

Swap in MB

attribute int? cores=null

Number of CPU cores

attribute string? rootfs=null

Root filesystem specification (e.g. local-lvm:8)

attribute bool? onboot=null

Start at boot

attribute bool? unprivileged=null

Create an unprivileged container

attribute string? description=null

Container description

attribute string? tags=null

Tags (semicolon-separated)

attribute bool? protection=null

Protection flag

attribute string? net0=null

Network device 0 specification (name=eth0,bridge=vmbr0,ip=dhcp)

attribute string? net1=null

Network device 1 specification

attribute string? nameserver=null

DNS server

attribute string? searchdomain=null

DNS search domain

attribute string? features=null

Container features (e.g. nesting=1,keyctl=1)

attribute bool? start=null

Start after creation

The following implements statements select implementations for this entity:

entity proxmox::resources::NetworkApply

Parents: proxmox::NodeScopedResource

Applies pending network changes on a PVE node.

PVE stages interface edits in /etc/network/interfaces.new; nothing takes effect until the network configuration is reloaded. This resource maps to PUT /api2/json/nodes/{node}/network which commits the pending state. It is an action rather than a configuration object: the handler always treats the resource as drifted and re-applies on every deploy.

purged=true is not supported and will raise at deploy time. Order this resource after the LinuxBridge/BondInterface resources whose changes you want to commit.

The following implements statements select implementations for this entity:

entity proxmox::resources::NodeDns

Parents: proxmox::NodeScopedResource

DNS resolver configuration of a PVE node – the node analogue of an ESXi host DNS config. Maps to PUT /api2/json/nodes/{node}/dns, which rewrites the node’s /etc/resolv.conf.

A node needs this to resolve names itself, e.g. the image-download host of a DownloadedImage (the node fetches the image directly).

Idempotent: the handler reads the current resolver config and only rewrites it on drift. purged=true is not supported (a node always has a resolver config and there is no meaningful inverse), so keep it out of owned_resources.

attribute string search

DNS search domain (PVE requires one when setting the resolver).

attribute string[] nameservers=List()

Resolver IP addresses. PVE stores at most three (dns1/dns2/dns3); any beyond the first three are ignored.

The following implements statements select implementations for this entity:

entity proxmox::resources::Pool

Parents: proxmox::Resource

Proxmox resource pool.

attribute string poolid

The pool identifier

attribute string? comment=null

Pool description/comment

The following implements statements select implementations for this entity:

entity proxmox::resources::QemuVM

Parents: proxmox::NodeScopedResource

Proxmox QEMU virtual machine.

attribute int vmid

The unique VM ID

attribute string? name=null

VM name

attribute int? memory=null

Memory in MB

attribute int? cores=null

Number of CPU cores per socket

attribute int? sockets=null

Number of CPU sockets

attribute string? cpu=null

CPU type (e.g. host, kvm64, x86-64-v2-AES)

attribute string? ostype=null

OS type (l26, win11, win10, other, etc.)

attribute string? boot=null

Boot order (e.g. order=scsi0;ide2;net0)

attribute string? scsihw=null

SCSI controller type (virtio-scsi-pci, virtio-scsi-single, lsi, etc.)

attribute string? bios=null

BIOS type (seabios, ovmf)

attribute string? machine=null

Machine type (pc, q35)

attribute string? agent=null

QEMU guest agent settings (e.g. enabled=1)

attribute bool? onboot=null

Start at boot

attribute string? description=null

VM description

attribute string? tags=null

Tags (semicolon-separated)

attribute bool? protection=null

Protection flag

attribute int? balloon=null

Minimum memory for ballooning (0 to disable)

attribute bool? numa=null

Enable NUMA

attribute bool? acpi=null

Enable ACPI

attribute bool? kvm=null

Enable KVM virtualization

attribute string? scsi0=null

SCSI disk 0 specification

attribute string? scsi1=null

SCSI disk 1 specification

attribute string? virtio0=null

VirtIO disk 0 specification

attribute string? ide2=null

IDE device 2 (typically CD-ROM)

attribute string? efidisk0=null

EFI disk specification

attribute string? net0=null

Network device 0 specification

attribute string? net1=null

Network device 1 specification

attribute string? net2=null

Network device 2 specification

attribute string? net3=null

Network device 3 specification

attribute string? net4=null

Network device 4 specification

attribute string? net5=null

Network device 5 specification

attribute string? net6=null

Network device 6 specification

attribute string? net7=null

Network device 7 specification

attribute string? net8=null

Network device 8 specification

attribute string? net9=null

Network device 9 specification

attribute string? net10=null

Network device 10 specification

attribute string? net11=null

Network device 11 specification

attribute string? net12=null

Network device 12 specification

attribute string? net13=null

Network device 13 specification

attribute string? net14=null

Network device 14 specification

attribute string? net15=null

Network device 15 specification

attribute string? ipconfig0=null

Cloud-init IP configuration for net0

attribute string? ipconfig1=null

Cloud-init IP configuration for net1

attribute string? ciuser=null

Cloud-init user

attribute string? cipassword=null

Cloud-init password

attribute string? sshkeys=null

Cloud-init SSH public keys (URL-encoded)

attribute string? serial0=null

Serial device 0

attribute string? vga=null

VGA type

attribute string? affinity=null

CPU pin set, comma-separated core ids (e.g. “0,10,11,12,…,23”). Critical for UPF performance.

attribute string? cicustom=null

Custom cloud-init snippet reference (e.g. “user=local:snippets/ncm.yaml”)

attribute string? smbios1=null

SMBIOS identity (e.g. “uuid=cf7f5e4b-9cdb-4cac-bc7a-af02044ae94a”). Preserves VM identity across recreations.

attribute string? vmgenid=null

VM Generation ID (UUID)

attribute string? hostpci0=null

PCI passthrough device 0 (e.g. “0000:9f:00,pcie=on”)

attribute string? hostpci1=null

PCI passthrough device 1

attribute string? hostpci2=null

PCI passthrough device 2

attribute string? hostpci3=null

PCI passthrough device 3

attribute string? hostpci4=null

PCI passthrough device 4

attribute string? hostpci5=null

PCI passthrough device 5

attribute string? hostpci6=null

PCI passthrough device 6

attribute string? hostpci7=null

PCI passthrough device 7

attribute bool running=false

The following implements statements select implementations for this entity:

entity proxmox::resources::Storage

Parents: proxmox::Resource

Proxmox storage configuration.

attribute string storage

The storage identifier

attribute string type

Storage type (dir, nfs, cifs, lvm, lvmthin, zfspool, rbd, cephfs, iscsi, pbs)

attribute string? path=null

File system path (for dir type)

attribute string? content=null

Allowed content types (comma-separated: images, rootdir, iso, vztmpl, backup, snippets)

attribute string? nodes=null

Restrict storage to specific nodes (comma-separated)

attribute bool? shared=null

Mark storage as shared between nodes

attribute bool? disable=null

Disable the storage

attribute string? server=null
attribute string? export=null
attribute string? pool=null
attribute string? vgname=null
attribute string? thinpool=null
attribute string? datastore=null
attribute string? username=null
attribute string? fingerprint=null

The following implements statements select implementations for this entity:

entity proxmox::resources::User

Parents: proxmox::Resource

Proxmox VE user account in a given realm (e.g. pve or pam).

Note: this resource creates/updates/deletes the user account itself. It does NOT set the user’s password. PVE’s password endpoint (PUT /access/password) has peculiar semantics (it requires the OLD password when changing your own, and PAM-realm users need shell access anyway), so password management is intentionally left out of scope for this resource. Use pveum passwd over SSH or PVE’s UI for initial password provisioning.

attribute string userid

User identifier in the form <name>@<realm> (e.g. admin@pve or root@pam).

attribute string? comment=null

Optional comment.

attribute string? email=null

Optional e-mail address.

attribute bool? enable=null

Enable the account. PVE defaults to true when unset.

attribute string? expire=null

Account expiration as an epoch timestamp; 0 means never.

attribute string? firstname=null

Optional first name.

attribute string? lastname=null

Optional last name.

attribute string? groups=null

Comma-separated list of groups the user belongs to.

attribute string? keys=null

2FA keys.

The following implements statements select implementations for this entity:

Implementations

implementation proxmox::proxmox_agent_autostart
implementation proxmox::resolve_agent_name

Resources

class proxmox.resources.ACLResource

A single ACL grant. PVE only exposes a bulk GET /access/acl and PUT /access/acl; the handler composes the appropriate PUT bodies. Read pulls the full list and selects the matching entry.

class proxmox.resources.APITokenResource

Resource for /access/users/{userid}/token/{tokenid}.

The PVE API generates the token secret on POST and only returns it once. APITokenHandler.create_resource parses it from the create response and stores it via ctx.set_fact("token_secret", ...). The model does NOT have a secret attribute; the secret is not round-tripped.

class proxmox.resources.BondInterfaceResource
class proxmox.resources.ConfigDriveISOResource

Builds a config-drive ISO from content and uploads it to a PVE storage. Identity is (node, storage, filename), serialised as the PVE volid {storage}:iso/{filename}. content and volume_label are create-only inputs consumed by the handler; _build_body is empty so the base calculate_diff never flags drift — only purge-transitions deploy.

class proxmox.resources.DownloadedImageResource

Wraps PVE’s per-node Storage.Download.URL API (POST /nodes/{node}/storage/{storage}/download-url).

The download parameters (source_url, checksum, checksum_algorithm, compression, verify_certificates) are inputs to create only — PVE doesn’t echo them back and the diff ignores changes. Identity is (node, storage, filename, content), serialised as the PVE volid {storage}:{content}/{filename}.

class proxmox.resources.LinuxBridgeResource
class proxmox.resources.LxcContainerResource
class proxmox.resources.NetworkApplyResource

Commits pending network changes via PUT /api2/json/nodes/{node}/network.

Idempotent: read_resource queries the node-level network endpoint and only drifts when PVE reports pending interface changes (the envelope changes field is non-empty — i.e. /etc/network/interfaces.new exists). On drift, create_resource issues the PUT that commits the staged config; PVE returns a UPID, the handler waits on it.

class proxmox.resources.NodeDnsResource
class proxmox.resources.PoolResource
class proxmox.resources.QemuVMResource
class proxmox.resources.StorageResource
class proxmox.resources.UserResource

Handlers

class proxmox.resources.StorageHandler
class proxmox.resources.PoolHandler
class proxmox.resources.QemuVMHandler

QemuVM handler with VM-lifecycle support on top of /config CRUD.

The PVE API splits a VM’s reality into two endpoints:
/config

— declarative config (what the VM IS)

/status/current — runtime state (whether the VM is RUNNING)

and transitions go through /status/start, /status/shutdown, /status/stop.

We model both in a single QemuVM resource. The running attribute is read from /status/current, kept in the body so the diff can compare desired vs current, then stripped before any /config PUT and applied via /status/* as a side effect of create/update.

class proxmox.resources.LxcContainerHandler
class proxmox.resources.DownloadedImageHandler

download-url isn’t a standard CRUD endpoint, so we override the four methods directly:

read GET /nodes/{node}/storage/{storage}/content/{volid} create POST /nodes/{node}/storage/{storage}/download-url + UPID wait update re-download (delete + create) — only create-only fields

can change, so any change implies the file has to be redrawn from the new URL.

delete DELETE /nodes/{node}/storage/{storage}/content/{volid}

class proxmox.resources.ConfigDriveISOHandler

Builds a config-drive ISO and uploads it to PVE storage. Like DownloadedImage this isn’t a standard CRUD endpoint:

read GET /nodes/{node}/storage/{storage}/content/{volid} create build ISO (pycdlib) + POST …/upload (multipart) + UPID wait update rebuild (delete + create) — content/label are create-only delete DELETE /nodes/{node}/storage/{storage}/content/{volid}

class proxmox.resources.UserHandler
class proxmox.resources.APITokenHandler

Handler for API tokens.

The token secret is generated server-side and only returned on create. We surface it back to the model via Inmanta facts (token_secret); it is NOT stored in any model attribute.

class proxmox.resources.ACLHandler

Handler for ACL grants.

PVE’s ACL endpoint is bulk-only:

  • GET /access/acl returns the full list of grants; we pick out ours by matching (path, userid|group, roleid).

  • PUT /access/acl adds OR removes a grant depending on the delete flag.

Create and update share the same PUT body — PVE upserts by (path, principal, role).

class proxmox.resources.LinuxBridgeHandler
class proxmox.resources.BondInterfaceHandler
class proxmox.resources.NetworkApplyHandler

Idempotent handler: only triggers the PUT when PVE’s GET /nodes/{node}/network envelope carries a non-empty changes field. When no changes are pending, read_resource sets an empty body so the diff is empty and no action runs.

class proxmox.resources.NodeDnsHandler

GET /nodes/{node}/dns always returns the resolver object, so the resource never reads as purged and the generic lifecycle is update-only.