feat(proxmox): automatic vm creation
Signed-off-by: Tuan-Dat Tran <tuan-dat.tran@tudattr.dev>
This commit is contained in:
@@ -4,7 +4,7 @@ Description=PostgresExporter
|
||||
[Service]
|
||||
TimeoutStartSec=0
|
||||
User={{ bin_name }}
|
||||
ExecStart={{ bin_path }} --web.listen-address={{ host.ip }}:{{ bind_port }} {{ options }}
|
||||
ExecStart={{ bin_path }} --web.listen-address={{ ansible_host }}:{{ bind_port }} {{ options }}
|
||||
Environment="DATA_SOURCE_URI=localhost:5432/postgres?sslmode=disable"
|
||||
Environment="DATA_SOURCE_USER={{ db.user }}"
|
||||
Environment="DATA_SOURCE_PASS={{ db.password }}"
|
||||
|
||||
8
roles/proxmox/tasks/00_setup_machines.yml
Normal file
8
roles/proxmox/tasks/00_setup_machines.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Prepare Localhost
|
||||
ansible.builtin.include_tasks: ./01_setup_localhost.yml
|
||||
when: is_localhost
|
||||
|
||||
- name: Prepare Localhost
|
||||
ansible.builtin.include_tasks: ./05_setup_node.yml
|
||||
when: is_proxmox_node
|
||||
7
roles/proxmox/tasks/01_setup_localhost.yml
Normal file
7
roles/proxmox/tasks/01_setup_localhost.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Install dependencies
|
||||
ansible.builtin.apt:
|
||||
name: "{{ item }}"
|
||||
update_cache: true
|
||||
state: present
|
||||
loop: "{{ proxmox_localhost_dependencies }}"
|
||||
7
roles/proxmox/tasks/05_setup_node.yml
Normal file
7
roles/proxmox/tasks/05_setup_node.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Install dependencies
|
||||
ansible.builtin.apt:
|
||||
name: "{{ item }}"
|
||||
update_cache: true
|
||||
state: present
|
||||
loop: "{{ proxmox_node_dependencies }}"
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
- name: Update Vault data
|
||||
ansible.builtin.include_tasks: 15_create_secret.yml
|
||||
loop: "{{ proxmox_vms | map(attribute='name') }}"
|
||||
loop: "{{ vms | map(attribute='name') }}"
|
||||
loop_control:
|
||||
loop_var: "vm_name"
|
||||
|
||||
|
||||
6
roles/proxmox/tasks/40_prepare_vm_creation.yml
Normal file
6
roles/proxmox/tasks/40_prepare_vm_creation.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: Download Cloud Init Isos
|
||||
ansible.builtin.include_tasks: 42_download_isos.yml
|
||||
loop: "{{ proxmox_cloud_init_images | dict2items | map(attribute='value') }}"
|
||||
loop_control:
|
||||
loop_var: distro
|
||||
12
roles/proxmox/tasks/42_download_isos.yml
Normal file
12
roles/proxmox/tasks/42_download_isos.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Check if file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ proxmox_dirs.isos }}/{{ distro.name }}"
|
||||
register: image_stat
|
||||
|
||||
- name: Download image if missing
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ distro.url }}"
|
||||
dest: "{{ proxmox_dirs.isos }}/{{ distro.name }}"
|
||||
mode: "0644"
|
||||
when: not image_stat.stat.exists
|
||||
@@ -4,8 +4,14 @@
|
||||
file: "{{ proxmox_vault_file }}"
|
||||
name: vm_secrets
|
||||
|
||||
- name: Create vms
|
||||
ansible.builtin.include_tasks: 55_create_vm.yml
|
||||
loop: "{{ proxmox_vms }}"
|
||||
- name: Destroy vms (Only during rapid testing)
|
||||
ansible.builtin.include_tasks: 54_destroy_vm.yml
|
||||
loop: "{{ vms }}"
|
||||
loop_control:
|
||||
loop_var: "vm"
|
||||
|
||||
- name: Create vms
|
||||
ansible.builtin.include_tasks: 55_create_vm.yml
|
||||
loop: "{{ vms }}"
|
||||
loop_control:
|
||||
loop_var: "vm"
|
||||
|
||||
30
roles/proxmox/tasks/54_destroy_vm.yml
Normal file
30
roles/proxmox/tasks/54_destroy_vm.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
- name: Gather info about VM
|
||||
community.general.proxmox_vm_info:
|
||||
api_user: root@pam
|
||||
api_password: "{{ vault.pve.aya01.root.sudo }}"
|
||||
api_host: "192.168.20.12"
|
||||
vmid: "{{ vm.vmid }}"
|
||||
register: vm_info
|
||||
|
||||
- name: Stop VM
|
||||
community.general.proxmox_kvm:
|
||||
api_user: root@pam
|
||||
api_password: "{{ vault.pve.aya01.root.sudo }}"
|
||||
api_host: "192.168.20.12"
|
||||
node: "{{ vm.node }}"
|
||||
vmid: "{{ vm.vmid }}"
|
||||
state: stopped
|
||||
force: true
|
||||
when: vm_info.proxmox_vms | length > 0
|
||||
|
||||
- name: Destroy VM
|
||||
community.general.proxmox_kvm:
|
||||
api_user: root@pam
|
||||
api_password: "{{ vault.pve.aya01.root.sudo }}"
|
||||
api_host: "192.168.20.12"
|
||||
node: "{{ vm.node }}"
|
||||
vmid: "{{ vm.vmid }}"
|
||||
state: absent
|
||||
force: true
|
||||
when: vm_info.proxmox_vms | length > 0
|
||||
@@ -1,34 +1,94 @@
|
||||
---
|
||||
- name: Create VM
|
||||
community.general.proxmox_kvm:
|
||||
api_user: root@pam
|
||||
api_password: "{{ vault.pve.aya01.root.sudo }}"
|
||||
api_host: "192.168.20.12"
|
||||
agent: true
|
||||
name: "{{ vm.name }}"
|
||||
vmid: "{{ vm.vmid }}"
|
||||
node: "{{ vm.node }}"
|
||||
cpu: "{{ vm.cpu }}"
|
||||
cores: "{{ vm.cores }}"
|
||||
memory: "{{ vm.memory }}"
|
||||
net: "{{ vm.net }}"
|
||||
scsi: "{{ vm.scsi }}"
|
||||
scsihw: "{{ vm.scsihw }}"
|
||||
ostype: "{{ vm.ostype }}"
|
||||
sshkeys: "{{ vm.sshkeys }}"
|
||||
scsihw: "virtio-scsi-pci"
|
||||
ostype: "l26"
|
||||
tags: "{{ proxmox_tags }}"
|
||||
description: "Created via Ansible with cloud-init"
|
||||
boot: "order=scsi0"
|
||||
cpu: "x86-64-v2-AES"
|
||||
ciuser: "{{ vm.ciuser }}"
|
||||
cipassword: "{{ vm_secrets[proxmox_secrets_prefix + '_' + vm.name.replace('-', '_')] }}"
|
||||
ide:
|
||||
ide2: "proxmox:cloudinit,format=qcow2"
|
||||
register: temp
|
||||
ipconfig:
|
||||
ipconfig0: "ip=dhcp"
|
||||
sshkeys: "{{ vm.sshkeys }}"
|
||||
register: proxmox_deploy_info
|
||||
|
||||
- name: Debug temp
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ temp }}"
|
||||
|
||||
- name: Set mac
|
||||
- name: Get MAC Address of new machine
|
||||
ansible.builtin.set_fact:
|
||||
mac: "{{ temp.mac }}"
|
||||
mac_address: "{{ proxmox_deploy_info.mac.net0 }}"
|
||||
|
||||
- name: debug mac
|
||||
- name: Import disk
|
||||
ansible.builtin.shell: |
|
||||
qm importdisk {{ vm.vmid }} {{ proxmox_dirs.isos }}/{{ vm.boot_image }} {{ proxmox_storage }}
|
||||
delegate_to: "{{ vm.node }}"
|
||||
|
||||
- name: Attach disk and cloud-init
|
||||
ansible.builtin.shell: |
|
||||
qm set {{ vm.vmid }} --scsi0 {{ proxmox_storage }}:{{ vm.vmid }}/vm-{{ vm.vmid }}-disk-0.raw --ide2 {{ proxmox_storage }}:cloudinit --boot order=scsi0
|
||||
delegate_to: "{{ vm.node }}"
|
||||
|
||||
- name: Resize scsi0 disk if needed
|
||||
ansible.builtin.shell: |
|
||||
qm resize {{ vm.vmid }} scsi0 {{ vm.disk_size }}G
|
||||
delegate_to: "{{ vm.node }}"
|
||||
|
||||
- name: Start VM
|
||||
community.general.proxmox_kvm:
|
||||
api_user: root@pam
|
||||
api_password: "{{ vault.pve.aya01.root.sudo }}"
|
||||
api_host: "192.168.20.12"
|
||||
node: "{{ vm.node }}"
|
||||
vmid: "{{ vm.vmid }}"
|
||||
state: started
|
||||
|
||||
- name: Wait for VM to appear on network
|
||||
ansible.builtin.shell: |
|
||||
nmap -sn -n -PR 192.168.20.0/24 | grep -B2 "{{ mac_address }}" | grep "Nmap scan report for"
|
||||
register: vm_nmap_scan
|
||||
retries: 30
|
||||
delay: 5
|
||||
until: vm_nmap_scan.stdout != ""
|
||||
delegate_to: "{{ vm.node }}"
|
||||
|
||||
- name: Extract the IP address from Nmap output
|
||||
ansible.builtin.set_fact:
|
||||
vm_found_ip: "{{ vm_nmap_scan.stdout | regex_search('Nmap scan report for ([0-9\\.]+)', '\\1') | first }}"
|
||||
|
||||
- name: Debug IP address
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ mac }}"
|
||||
msg: "Found VM IP address: {{ vm_found_ip }}"
|
||||
|
||||
- name: Define SSH config block
|
||||
ansible.builtin.set_fact:
|
||||
ssh_entry: |
|
||||
Host {{ vm.name }}
|
||||
HostName {{ vm_found_ip }}
|
||||
Port 22
|
||||
User tudattr
|
||||
IdentityFile /media/veracrypt1/genesis
|
||||
ProxyJump {{ vm.node }}
|
||||
|
||||
- name: Append new VM to SSH config
|
||||
ansible.builtin.blockinfile:
|
||||
path: "{{ ansible_env.HOME }}/.ssh/config_homelab"
|
||||
marker: "# {mark} HOMELAB VMS BLOCK"
|
||||
block: |
|
||||
{{ ssh_entry }}
|
||||
|
||||
- name: Add the new VM to the proxmox_nodes group in production.ini
|
||||
ansible.builtin.lineinfile:
|
||||
path: "../inventory.ini"
|
||||
line: "{{ proxmox_inventory_entry }}"
|
||||
insertafter: "[proxmox_nodes]"
|
||||
state: present
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
|
||||
- name: Create vms
|
||||
ansible.builtin.include_tasks: 65_create_container.yml
|
||||
loop: "{{ proxmox_lxcs }}"
|
||||
loop: "{{ lxcs }}"
|
||||
loop_control:
|
||||
loop_var: "container"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
- name: Download Debian Image
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ proxmox_debian_image_url }}"
|
||||
dest: "{{ proxmox_image_path }}"
|
||||
mode: "0644"
|
||||
@@ -1,12 +1,18 @@
|
||||
---
|
||||
- name: Setup user
|
||||
ansible.builtin.include_tasks: 01_setup_user.yml
|
||||
- name: Prepare Machines
|
||||
ansible.builtin.include_tasks: 00_setup_machines.yml
|
||||
|
||||
- name: Create VM vault
|
||||
ansible.builtin.include_tasks: 10_create_secrets.yml
|
||||
when: is_localhost
|
||||
|
||||
- name: Prime node for VM
|
||||
ansible.builtin.include_tasks: 40_prepare_vm_creation.yml
|
||||
when: is_proxmox_node
|
||||
|
||||
- name: Create VMs
|
||||
ansible.builtin.include_tasks: 50_create_vms.yml
|
||||
|
||||
when: is_localhost
|
||||
- name: Create LXC containers
|
||||
ansible.builtin.include_tasks: 60_create_containers.yml
|
||||
when: is_localhost
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
author: tuan-dat.tran@tudattr.dev
|
||||
creator: ansible
|
||||
proxmox_author: tuan-dat.tran@tudattr.dev
|
||||
proxmox_creator: ansible
|
||||
|
||||
proxmox_storage: proxmox
|
||||
|
||||
proxmox_vault_file: ../group_vars/proxmox/secrets_vm.yml
|
||||
proxmox_secrets_prefix: secrets_vm
|
||||
proxmox_debian_image_url: https://cdimage.debian.org/images/cloud/bookworm/20250316-2053/debian-12-genericcloud-amd64-20250316-2053.qcow2
|
||||
proxmox_image_path: /opt/template/iso/
|
||||
proxmox_cloud_init_images:
|
||||
debian:
|
||||
name: debian-12-genericcloud-amd64.qcow2
|
||||
url: https://cdimage.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2
|
||||
ubuntu:
|
||||
name: noble-server-cloudimg-amd64.img
|
||||
url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
|
||||
proxmox_dirs:
|
||||
isos: /opt/proxmox/template/iso/
|
||||
|
||||
proxmox_tags:
|
||||
- "{{ creator }}"
|
||||
- "{{ proxmox_creator }}"
|
||||
|
||||
proxmox_node_dependencies:
|
||||
- libguestfs-tools
|
||||
- nmap
|
||||
|
||||
proxmox_localhost_dependencies: []
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{% if http_port %}
|
||||
{{ service.name }}.{{ domain }} {
|
||||
{% for vm in service.vm %}
|
||||
reverse_proxy {{ hostvars[vm].host.ip }}:{{ http_port[0] }}
|
||||
reverse_proxy {{ hostvars[vm].ansible_host }}:{{ http_port[0] }}
|
||||
{% endfor %}
|
||||
log {
|
||||
output file /var/log/caddy/{{ service.name }}.log
|
||||
|
||||
Reference in New Issue
Block a user