d5cf6f656e
Previously the community.proxmox.proxmox / proxmox_vm_info module_defaults were defined inline on the outer block in main.yml. Invoking individual task files via 'tasks_from: stop' (or delete/convert/etc.) bypassed main.yml, leaving the API parameters unset and producing 'missing required arguments: api_host, api_user' errors. The README worked around this by telling callers to repeat the module_defaults block at the play level — easy to forget, and duplicated config. Extract the defaults dict into _proxmox_module_defaults in defaults/main.yml (using a YAML anchor to share between the two modules), and wrap every task file that calls a Proxmox module in a block that references it. Callers only need the proxmox_* connection vars in scope (typically group_vars/all/) — both 'roles:' and 'tasks_from:' invocations now configure the API consistently. Files wrapped: check-exists, create, clone, update, start, stop, delete, convert. wait/post-clone/edit-config don't call Proxmox modules and are unchanged. main.yml's now-redundant outer module_defaults is removed. README updated to drop the 'Using Standalone Tasks' workaround boilerplate.
186 lines
7.8 KiB
Markdown
Executable File
186 lines
7.8 KiB
Markdown
Executable File
# Ansible Role: proxmox_lxc_provision
|
|
|
|
## Description
|
|
|
|
This Ansible role manages the provision of LXC containers and templates on a Proxmox host. By default the role will create and start an LXC container. It allows creating a new container from a [container image](https://pve.proxmox.com/wiki/Linux_Container#pct_container_images) or cloning an existing container or template container.
|
|
|
|
It also includes tasks which may be used individually:
|
|
- `clone.yml`: Creates a new LXC container by cloning another container or template
|
|
- `convert.yml`: Converts an LXC container to a template
|
|
- `create.yml`: Creates a new LXC container
|
|
- `delete.yml`: Deletes an LXC container given its vmid or hostname
|
|
- `start.yml`: Starts an LXC container
|
|
- `stop.yml`: Stops an LXC container
|
|
- `update.yml`: Updates an existing LXC container
|
|
- `wait.yml`: Waits for SSH to be available on the container
|
|
- `check-exists.yml`: Checks if an LXC exists by `lxc_vmid` or `lxc_hostname`
|
|
- `post-clone.yml`: Post-clone configuration (passwords, SSH host key regeneration). Runs against the new container; depends on the `system_setup` role.
|
|
- `edit-config.yml`: Edits `/etc/pve/lxc/<vmid>.conf` directly to add ID mappings and NVIDIA GPU passthrough entries. Must be delegated to the Proxmox host.
|
|
|
|
## Requirements
|
|
|
|
- Ansible 2.12 or higher
|
|
- Python 3.6 or higher
|
|
- requests
|
|
- proxmoxer
|
|
- passlib
|
|
|
|
## Role Variables
|
|
|
|
### Required Proxmox API Variables
|
|
|
|
| Variable | Description | Example |
|
|
|----------|-------------|---------|
|
|
| `proxmox_api_host` | The IP address or hostname of the Proxmox server | `192.168.1.10` |
|
|
| `proxmox_api_user` | The username for Proxmox authentication, typically in format `username@realm` | `ansible@pve` |
|
|
| `proxmox_api_token_id` | The API token ID used for authentication | `token` |
|
|
| `proxmox_api_token_secret` | The secret key associated with the API token | `xxx-yyy-zzz` |
|
|
| `proxmox_node` | The name of the Proxmox node to target | `pve01` |
|
|
|
|
### Optional Proxmox API Variables
|
|
|
|
| Variable | Description | Default |
|
|
|----------|-------------|---------|
|
|
| `proxmox_api_port` | The port on which the Proxmox API is listening | `8006` |
|
|
| `proxmox_api_validate_certs` | Whether to validate SSL certificates | `false` |
|
|
| `proxmox_delegate_host` | Inventory hostname for delegated tasks (pct commands). Use this to inherit `ansible_become_password` from inventory. | `{{ proxmox_api_host }}` |
|
|
|
|
### Required Container Variables
|
|
|
|
| Variable | Description | Example |
|
|
|----------|-------------|---------|
|
|
| `lxc_template` | The OS template to create the LXC from. Mutually exclusive with `lxc_clone_from` | `local:vztmpl/debian-12_amd64.tar.zst` |
|
|
| `lxc_clone_from` | The vmid of the container or template to clone. Mutually exclusive with `lxc_template` | `201` |
|
|
| `lxc_hostname` | The hostname for the container | `my-container` |
|
|
| `lxc_vmid` | The VM ID for the container | `100` |
|
|
|
|
### Optional Container Variables
|
|
|
|
| Variable | Description | Default |
|
|
|----------|-------------|---------|
|
|
| `lxc_clone_type` | Clone type when using `lxc_clone_from` | `full` |
|
|
| `lxc_storage` | Target storage for the container | `local-zfs` |
|
|
| `lxc_size` | Disk size in GB | `16` |
|
|
| `lxc_disk` | The target storage and storage size | `local-zfs:16` |
|
|
| `lxc_root_password` | Password for the root account. On creates from `lxc_template` it is set via the Proxmox API; on clones it is applied inside the container by `post-clone.yml`. | - |
|
|
| `lxc_user_name` | Name of an additional non-root user to manage in `post-clone.yml` (clone path only). | `admin` |
|
|
| `lxc_user_password` | Password for `lxc_user_name`. Only applied on the clone path via `post-clone.yml`. The user must already exist in the source template. | - |
|
|
| `lxc_cores` | The number of CPU cores | `4` |
|
|
| `lxc_memory` | Memory size in MB | `2048` |
|
|
| `lxc_swap` | Swap memory size in MB | `2048` |
|
|
| `lxc_ipv4` | The IPv4 address | `dhcp` |
|
|
| `lxc_ipv6` | The IPv6 address | `auto` |
|
|
| `lxc_gateway` | The default gateway | `10.0.0.1` |
|
|
| `lxc_nameserver` | DNS nameserver | `10.0.0.7` |
|
|
| `lxc_bridge` | Linux bridge on the Proxmox host to attach the container to | `vmbr0` |
|
|
| `lxc_iface_name` | Interface name inside the container | `eth0` |
|
|
| `lxc_vlan_tag` | 802.1Q VLAN tag (integer 1-4094). Omitted from netif when unset. | - |
|
|
| `lxc_pubkey_file` | Path to SSH public key file | `~/.ssh/id_ed25519.pub` |
|
|
| `lxc_features` | List of container features | `["nesting=1"]` |
|
|
| `lxc_tags` | Tags for the container | `["ansible-managed"]` |
|
|
| `lxc_start` | Start container after creation | `true` |
|
|
| `lxc_unprivileged` | Create as an unprivileged container | `true` |
|
|
| `lxc_mounts` | Dict of additional bind mounts (e.g. `{ mp0: "/srv/data,mp=/data" }`) | - |
|
|
| `lxc_onboot` | Start container on Proxmox host boot | `false` |
|
|
| `lxc_startup` | Startup order string passed to Proxmox (e.g. `order=1,up=30`) | - |
|
|
| `lxc_timezone` | Timezone inside the container (e.g. `Europe/Berlin`) | - |
|
|
| `lxc_nvidia_gpu_mount` | Add NVIDIA GPU passthrough entries via `edit-config.yml` | `false` |
|
|
| `gpu_device_id` | Major device number for `/dev/nvidia*` (required when `lxc_nvidia_gpu_mount` is true) | - |
|
|
| `uvm_device_id` | Major device number for `/dev/nvidia-uvm*` (required when `lxc_nvidia_gpu_mount` is true) | - |
|
|
| `lxc_id_mappings` | Multi-line `lxc.idmap:` block written into the container config by `edit-config.yml` | - |
|
|
|
|
|
|
## Example Playbook
|
|
|
|
### Prerequisites
|
|
|
|
Set up your Proxmox API connection variables in group vars:
|
|
|
|
```yaml
|
|
# group_vars/all.yml
|
|
proxmox_api_host: "10.0.1.1"
|
|
proxmox_api_port: 8006
|
|
proxmox_api_user: "automation@pve"
|
|
proxmox_api_token_id: "mytoken"
|
|
proxmox_api_token_secret: "{{ vault_proxmox_token }}"
|
|
proxmox_api_validate_certs: false
|
|
proxmox_node: "pve01"
|
|
proxmox_delegate_host: "proxmox_server" # inventory hostname for become_password
|
|
```
|
|
|
|
### Creating a new LXC from template
|
|
|
|
```yaml
|
|
- name: Create and start an LXC container
|
|
hosts: localhost
|
|
connection: local
|
|
vars:
|
|
lxc_vmid: 100
|
|
lxc_hostname: new-debian-container
|
|
lxc_template: "local:vztmpl/debian-12_amd64.tar.zst"
|
|
lxc_ipv4: "10.0.0.99/24"
|
|
roles:
|
|
- role: proxmox_lxc_provision
|
|
```
|
|
|
|
### Creating a new LXC by cloning an existing container
|
|
|
|
```yaml
|
|
- name: Clone an LXC container
|
|
hosts: localhost
|
|
connection: local
|
|
vars:
|
|
lxc_vmid: 101
|
|
lxc_hostname: cloned-container
|
|
lxc_clone_from: 200
|
|
lxc_ipv4: "10.0.0.100/24"
|
|
roles:
|
|
- role: proxmox_lxc_provision
|
|
```
|
|
|
|
### Idempotent Behavior
|
|
|
|
The role includes idempotency checking. If a container with the specified `lxc_vmid` or `lxc_hostname` already exists, the role will skip provisioning and exit gracefully. Sets `lxc_exists` fact for use in subsequent tasks.
|
|
|
|
### Using Standalone Tasks
|
|
|
|
Individual task files (`stop`, `start`, `delete`, `convert`, etc.) can be invoked via `tasks_from` directly — each task file wraps its work in a block with the role's shared `module_defaults`, so the Proxmox API connection is configured automatically as long as the `proxmox_*` connection variables are in scope (typically from `group_vars/all/`).
|
|
|
|
```yaml
|
|
- name: Convert container to a template
|
|
hosts: localhost
|
|
tasks:
|
|
- include_role:
|
|
name: proxmox_lxc_provision
|
|
tasks_from: convert
|
|
vars:
|
|
lxc_hostname: my-container
|
|
```
|
|
|
|
### Creating an LXC Container and Converting it to a Template
|
|
|
|
```yaml
|
|
---
|
|
- name: Create and start an LXC container
|
|
hosts: localhost
|
|
connection: local
|
|
vars:
|
|
lxc_vmid: "{{ lxc_vmid }}"
|
|
lxc_hostname: "{{ lxc_hostname }}"
|
|
lxc_template: "local:vztmpl/debian-12_amd64.tar.zst"
|
|
lxc_ipv4: "10.0.0.99/24"
|
|
roles:
|
|
- role: proxmox_lxc_provision
|
|
|
|
# Run configuration tasks on the container...
|
|
|
|
- name: Convert the created container to a template
|
|
hosts: localhost
|
|
tasks:
|
|
- include_role:
|
|
name: proxmox_lxc_provision
|
|
tasks_from: convert
|
|
vars:
|
|
lxc_hostname: "{{ lxc_hostname }}"
|
|
```
|