initial commit

This commit is contained in:
hiperman
2026-01-30 20:13:58 -05:00
commit a28fcbd942
31 changed files with 1022 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
---
- name: Create a full clone of the container
community.general.proxmox:
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
api_host: "{{ proxmox_api_host }}"
node: "{{ proxmox_node }}"
vmid: "{{ container_vmid | default(0) }}"
clone: "{{ clone_from }}"
clone_type: "{{ clone_type }}"
hostname: "{{ container_hostname }}"
storage: "{{ container_storage }}"
register: clone_result
- name: Debug container_mounts
ansible.builtin.debug:
msg:
- "container_mounts: {{ container_mounts }}"
- "Type: {{ container_mounts | type_debug }}"
- "Defined: {{ container_mounts is defined }}"
- "Length: {{ container_mounts | length }}"
- name: Add bind mounts via pct
become: yes
ansible.builtin.shell: |
pct set {{ clone_result.vmid | default(container_vmid) }} {% for key, value in container_mounts.items() %}-{{ key }} {{ value }} {% endfor %}
delegate_to: "{{ proxmox_api_host }}"
when: container_mounts is defined
- name: Resize rootfs after clone
ansible.builtin.command:
cmd: "pct resize {{ clone_result.vmid }} rootfs {{ container_size }}G"
delegate_to: "{{ proxmox_api_host }}"
become: yes
register: resize_result
changed_when: resize_result.rc == 0 and 'already at specified size' not in resize_result.stderr
failed_when:
- resize_result.rc != 0
- "'already at specified size' not in resize_result.stderr"
when: container_size is defined

View File

@@ -0,0 +1,12 @@
---
- ansible.builtin.include_tasks: stop.yaml
- name: Convert container to template
community.general.proxmox:
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
api_host: "{{ proxmox_api_host }}"
node: server
state: template
hostname: "{{ container_hostname }}"

View File

@@ -0,0 +1,32 @@
---
- name: Create an LXC container
community.general.proxmox:
api_host: "{{ proxmox_api_host }}"
api_port: "{{ proxmox_api_port }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
validate_certs: "{{ proxmox_api_validate_certs }}"
node: "{{ proxmox_node }}"
vmid: "{{ container_vmid | default(omit) }}"
hostname: "{{ container_hostname }}"
password: "{{ container_password }}"
ostemplate: "{{ container_template }}"
cores: "{{ container_cores }}"
memory: "{{ container_memory }}"
swap: "{{ container_swap }}"
disk: "{{ container_disk }}"
mounts: "{{ container_mounts | default(omit) }}"
netif: >
{"net0": "name=eth0,gw={{ container_gateway }},ip={{ container_ipv4 }},ip6={{ container_ipv6 | default(omit) }},bridge=vmbr0"}
pubkey: "{{ lookup('file', container_pubkey_file) | default(omit) }}"
onboot: "{{ container_onboot | default(false) }}"
startup: "{{ container_startup | default(omit) }}"
unprivileged: "{{ container_unprivileged | default(true) }}"
features: "{{ container_features | default(omit) }}"
timezone: "{{ container_timezone | default(omit) }}"
nameserver: "{{ container_nameserver | default(omit) }}"
state: present
tags: "{{ container_tags | default(omit) }}"
register: container_result

View File

@@ -0,0 +1,18 @@
---
- ansible.builtin.include_tasks: stop.yaml
- name: Delete a container
community.general.proxmox:
api_host: "{{ proxmox_api_host }}"
api_port: "{{ proxmox_api_port }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
validate_certs: "{{ proxmox_api_validate_certs }}"
vmid: "{{ container_vmid | default(omit) }}"
hostname: "{{ container_hostname | default(omit) }}"
state: absent
register: delete_result
failed_when: |
delete_result.failed and
('does not exist' not in delete_result.msg)

View File

@@ -0,0 +1,43 @@
---
- name: Remove all existing ID mappings
lineinfile:
path: "/etc/pve/lxc/{{ container_vmid }}.conf"
regexp: '^lxc\.idmap:'
state: absent
when: container_id_mappings is defined
- name: Add ID mappings
blockinfile:
path: "/etc/pve/lxc/{{ container_vmid }}.conf"
block: "{{ container_id_mappings }}"
insertafter: EOF
when: container_id_mappings is defined
- name: Remove existing GPU configuration
lineinfile:
path: "/etc/pve/lxc/{{ container_vmid }}.conf"
regexp: "{{ item }}"
state: absent
loop:
- '^lxc\.cgroup2\.devices\.allow: c {{ gpu_device_id }}:\* rwm'
- '^lxc\.cgroup2\.devices\.allow: c {{ uvm_device_id }}:\* rwm'
- '^lxc\.mount\.entry: /dev/nvidia0'
- '^lxc\.mount\.entry: /dev/nvidiactl'
- '^lxc\.mount\.entry: /dev/nvidia-uvm '
- '^lxc\.mount\.entry: /dev/nvidia-uvm-tools'
when: container_nvidia_gpu_mount
- name: Add GPU device for passthrough
blockinfile:
path: /etc/pve/lxc/{{ container_vmid }}.conf
block: |
lxc.cgroup2.devices.allow: c {{ gpu_device_id }}:* rwm
lxc.cgroup2.devices.allow: c {{ uvm_device_id }}:* rwm
lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-uvm-tools none bind,optional,create=file
when: container_nvidia_gpu_mount

View File

@@ -0,0 +1,38 @@
---
- name: Container source must be defined (clone_from or container_template)
ansible.builtin.fail:
msg: "Neither clone_from or container_template are defined"
when: clone_from is undefined and container_template is undefined
- name: Clone container from another container or template, then update
when: clone_from is defined
block:
- name: Clone from template
ansible.builtin.include_tasks: clone.yaml
register: clone_result
- name: Update container
ansible.builtin.include_tasks: update.yaml
vars:
container_vmid: "{{ clone_result.vmid }}"
register: container_result
- name: Create the new container
ansible.builtin.include_tasks: create.yaml
when: container_template is defined and clone_from is undefined
- name: Start the created container and wait for ssh
vars:
container_vmid: "{{ container_result.vmid }}"
ansible.builtin.include_tasks: "{{ item }}"
loop:
- start.yaml
- wait.yaml
when: container_start
- name: Post clone updates
when: clone_from is defined
delegate_to: "{{ container_hostname }}"
block:
- name: Include post-clone tasks
ansible.builtin.include_tasks: post-clone.yaml

View File

@@ -0,0 +1,27 @@
---
- name: Change root password
ansible.builtin.user:
name: root
password: "{{ container_password | password_hash('sha512') }}"
update_password: always
when: container_password is defined
- name: Change admin password
ansible.builtin.user:
name: admin
password: "{{ password | password_hash('sha512') }}"
update_password: always
when: password is defined
- name: Regenerate SSH host keys
ansible.builtin.include_role:
name: system-setup
tasks_from: ssh
vars:
regenerate_ssh_keys: true
- name: Remove previous entry from known hosts
ansible.builtin.known_hosts:
name: "{{ hostvars[container_hostname]['ansible_host'] }}"
state: absent
delegate_to: localhost

View File

@@ -0,0 +1,17 @@
---
- name: Start the LXC container
community.general.proxmox:
api_host: "{{ proxmox_api_host }}"
api_port: "{{ proxmox_api_port }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
validate_certs: "{{ proxmox_api_validate_certs }}"
vmid: "{{ container_result.vmid }}"
state: started
register: start_result
retries: 3
delay: 5
until: start_result is success
failed_when: start_result.failed and ('already running' not in start_result.msg)

View File

@@ -0,0 +1,16 @@
---
- name: Stop container if it is running
community.general.proxmox:
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
api_host: "{{ proxmox_api_host }}"
vmid: "{{ container_vmid | default(omit) }}"
hostname: "{{ container_hostname | default(omit) }}"
state: "stopped"
register: stop_result
failed_when: |-
stop_result.failed and
('not running' not in stop_result.msg) and
('does not exist' not in stop_result.msg)

View File

@@ -0,0 +1,29 @@
---
- name: Update an LXC container
community.general.proxmox:
api_host: "{{ proxmox_api_host }}"
api_port: "{{ proxmox_api_port }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
validate_certs: "{{ proxmox_api_validate_certs }}"
node: "{{ proxmox_node }}"
vmid: "{{ container_vmid }}"
hostname: "{{ container_hostname }}"
password: "{{ container_password | default(omit) }}" # Updating password does not work
cores: "{{ container_cores }}"
memory: "{{ container_memory }}"
swap: "{{ container_swap }}"
disk: "{{ container_disk }}"
netif: '{"net0": "name=eth0,gw={{ container_gateway }},ip={{ container_ipv4 }},ip6={{ container_ipv6 | default(omit) }},bridge=vmbr0"}'
pubkey: "{{ lookup('file', container_pubkey_file) | default(omit) }}"
onboot: "{{ container_onboot | default(false) }}"
startup: "{{ container_startup | default(omit) }}"
features: "{{ container_features | default(omit) }}"
timezone: "{{ container_timezone | default(omit) }}"
nameserver: "{{ container_nameserver | default(omit) }}"
state: present
tags: "{{ container_tags | default(omit) }}"
update: true
register: container_result

View File

@@ -0,0 +1,20 @@
---
- ansible.builtin.meta: refresh_inventory
- name: Wait a moment for container to be available in inventory
ansible.builtin.pause:
seconds: 2
- name: Debug - Check if container is in inventory
ansible.builtin.debug:
msg: "Container {{ container_hostname }} found with IP: {{ hostvars[container_hostname]['ansible_host'] | default('NOT FOUND') }}"
- name: Wait for SSH to become available
ansible.builtin.wait_for:
host: "{{ hostvars[container_hostname]['ansible_host'] }}"
port: 22
delay: 3
state: started
register: ssh_wait_result
until: ssh_wait_result is not failed