Skip to content

Instantly share code, notes, and snippets.

@timatlee
Last active March 4, 2024 17:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save timatlee/855fab414c85a6881ee7b196476a9d60 to your computer and use it in GitHub Desktop.
Save timatlee/855fab414c85a6881ee7b196476a9d60 to your computer and use it in GitHub Desktop.
---
- name: Create cloud images
# This needs to be a proxmox host, since some of the commands depend on `qm`.
hosts: proxmox1
vars_files:
# Secrets contains a variable `proxmox_api_secret`. See https://pve.proxmox.com/pve-docs/chapter-pveum.html#pveum_tokens for generating a token.
- ../../vars/secrets.yml
vars:
# Force download of the ISO. ONce this happens once, you probably don't need to do it *every* time.
- force_download: false
# Path to public keys to load into the image.
- public_keys: '/home/tim/ansible/public_keys/'
# Host to execute API calls on.
- api_host: "proxmox1"
# API user
- api_user: "root@pam"
# API token ID. SHould be the same token ID when we created `proxmox_api_secret`
- api_token_id: "fullaccess"
# Some calls need a node to do something on. Specify this here.
- node_target: "proxmox1"
# URL of the image to download. I'm using Debian here, but you could use Ubuntu.
- iso_source_url: "https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-genericcloud-amd64.qcow2"
# Where to save the ISO. This is my Synology NFS.
- iso_target_path: "/mnt/pve/synology-nfs/template/iso/debian-11-genericcloud-amd64.qcow2"
# Some calls need to know the storage 'name'. Specify that here.
- storage_target: "synology-nfs"
# A really, REALLY rudementary way to define multiple templates. We could probably do this later, but. eh.
- vm_defs:
- id: 2000
name: "cloudimage-Debian11-k3s-master"
nets:
- id: 0
bridge: "vmbr0"
- id: 2001
name: "cloudimage-Debian11-k3s-node"
nets:
- id: 0
bridge: "vmbr0"
- id: 1
bridge: "vmbr0"
tag: 100
tasks:
# PIP is required to install the proxmoxer library, needed by community.general ansible collection.
- name: Install pip
ansible.builtin.apt:
name:
- pip
state: present
- name: Install Proxmoxer on the machine
ansible.builtin.pip:
name: proxmoxer
state: present
- name: Download cloud image to NFS storage
ansible.builtin.get_url:
url: "{{ iso_source_url }}"
dest: "{{ iso_target_path }}"
force: true
mode: 0777
when: force_download
- name: Remove existing cloud image
community.general.proxmox_kvm:
api_host: "{{ api_host }}"
api_user: "{{ api_user }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ proxmox_api_secret }}"
vmid: "{{ item.id }}"
state: absent
loop: "{{ vm_defs }}"
- name: Create new cloud images
community.general.proxmox_kvm:
api_host: "{{ api_host }}"
api_user: "{{ api_user }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ proxmox_api_secret }}"
name: "{{ item.name }}"
vmid: "{{ item.id }}"
serial:
serial0: 'socket'
vga: serial0
scsihw: 'virtio-scsi-pci'
node: "{{ node_target }}"
citype: nocloud
ciuser: "ansible"
cipassword: "{{ proxmox_ci_password }}"
loop: "{{ vm_defs }}"
- name: Assign network interfaces to image
community.general.proxmox_nic:
api_host: "{{ api_host }}"
api_user: "{{ api_user }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ proxmox_api_secret }}"
vmid: "{{ item.0.id }}"
interface: "net{{ item.1.id }}"
bridge: "vmbr0"
tag: "{{ item.1.tag | default(0) }}"
loop: "{{ vm_defs | subelements('nets') }}"
# I can't get this to work. Import_from requires running as root, which I am.. but any other way the disk doesn't create.
# - name: Importing the cloud image disk
# community.general.proxmox_disk:
# api_host: "{{ api_host }}"
# api_user: "{{ api_user }}"
# api_token_id: "{{ api_token_id }}"
# api_token_secret: "{{ proxmox_api_secret }}"
# import_from: "{{ iso_target_path }}"
# vmid: " {{ item.id }}"
# storage: "{{ storage_target }}"
# disk: "scsi0"
# state: present
# # size: 5
# create: forced
# loop: "{{ vm_defs }}"
- name: Import the cloned image disk
ansible.builtin.shell:
cmd: "qm importdisk {{ item.id }} {{ iso_target_path }} {{ storage_target }}"
loop: "{{ vm_defs }}"
# Again, not sure how to do this through a playbook task..
# trying to attach the imported disk to the VM.
# - name: Set the disk image as disk 0
# community.general.proxmox_disk:
# api_host: "{{ api_host }}"
# api_user: "{{ api_user }}"
# api_token_id: "{{ api_token_id }}"
# api_token_secret: "{{ proxmox_api_secret }}"
# vmid: "{{ item.id }}"
# state: present
# disk: "unused0"
# loop: "{{ vm_defs }}"
- name: Attach the cloned disk.
ansible.builtin.shell:
cmd: "qm set {{ item.id }} --scsi0 {{ storage_target }}:{{ item.id }}/vm-{{ item.id }}-disk-0.raw"
loop: "{{ vm_defs }}"
- name: Add the CloudInit disk
ansible.builtin.shell:
cmd: "qm set {{ item.id }} --ide2 {{ storage_target }}:cloudinit"
loop: "{{ vm_defs }}"
- name: Set the boot disk
community.general.proxmox_kvm:
api_host: "{{ api_host }}"
api_user: "{{ api_user }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ proxmox_api_secret }}"
node: "{{ node_target }}"
vmid: "{{ item.id }}"
boot: "c"
bootdisk: "scsi0"
update: true
loop: "{{ vm_defs }}"
- name: Pack up local public keys into one file
delegate_to: localhost
ansible.builtin.assemble:
src: "{{ public_keys }}"
dest: "/tmp/ssh_keys_file"
mode: 0644
- name: Set SSH keys
community.general.proxmox_kvm:
api_host: "{{ api_host }}"
api_user: "{{ api_user }}"
api_token_id: "{{ api_token_id }}"
api_token_secret: "{{ proxmox_api_secret }}"
node: "{{ node_target }}"
vmid: "{{ item.id }}"
sshkeys: "{{ lookup('ansible.builtin.file', '/tmp/ssh_keys_file') }}"
update: true
loop: "{{ vm_defs }}"
- name: Convert to template
ansible.builtin.shell:
cmd: "qm template {{ item.id }}"
loop: "{{ vm_defs }}"
# - name: debug test
# ansible.builtin.debug:
# msg: "{{ item.id }}"
# loop: "{{ vm_defs }}"
@colbylol
Copy link

colbylol commented Jun 1, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment