Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
14 KB
Referenced Files
None
Subscribers
None
diff --git a/deployments/ansible/roles/kvm/tasks/main.yml b/deployments/ansible/roles/kvm/tasks/main.yml
index 29fae4d..cb812b0 100644
--- a/deployments/ansible/roles/kvm/tasks/main.yml
+++ b/deployments/ansible/roles/kvm/tasks/main.yml
@@ -1,240 +1,293 @@
---
- name: Validate volumes structure
ansible.builtin.assert:
that:
- volumes is defined
fail_msg: "Volumes must be a non-empty list. Current value: {{ volumes }}"
- name: Destroy
community.libvirt.virt:
name: "{{ inventory_hostname }}"
uri: "{{ qemu_uri }}"
command: destroy
ignore_errors: true
when: recreate_vm
delegate_to: 127.0.0.1
- name: Delete disk
command: virsh --connect {{ qemu_uri }} vol-delete --pool {{ vm_pool }} guest_{{ inventory_hostname }}
ignore_errors: true
when: recreate_vm
delegate_to: 127.0.0.1
- name: Undefine
community.libvirt.virt:
name: "{{ inventory_hostname }}"
uri: "{{ qemu_uri }}"
command: undefine
ignore_errors: true
when: recreate_vm
delegate_to: 127.0.0.1
- name: Prepare data volumes
vars:
_volumes: "{{ volumes | default([]) }}"
block:
- name: Check for data volume to create
command: virsh --connect {{ qemu_uri }} vol-info --pool {{ item['pool'] }} data_{{ inventory_hostname }}_{{ item['name'] }}
delegate_to: 127.0.0.1
register: _disk_info
ignore_errors: true
loop: "{{ _volumes }}"
- name: Create data volume if missing
command: virsh --connect {{ qemu_uri }} vol-create-as --pool {{ item.item['pool'] }} --name data_{{ inventory_hostname }}_{{ item.item['name'] }} --capacity {{ item.item['size'] }}
delegate_to: 127.0.0.1
when: item.rc == 1
loop: "{{ _disk_info.results | from_yaml | list}}"
- name: Get VM status
command: virsh --connect {{ qemu_uri }} domstate {{ inventory_hostname }}
ignore_errors: true
register: _vm_status
delegate_to: 127.0.0.1
- name: VM Status
debug:
msg: "VM {{ inventory_hostname }} is {{ _vm_status.stdout | default('not defined, will create it' ) }}"
# VM create block start
- name: VM create
when: _vm_status is failed
vars:
_vm_pool: "{{ vm_pool }}"
block:
- name: Upload vm image
when: not use_kickstart_file
block:
- - name: Check for kolab-minimal disk image
- command: virsh --connect {{ qemu_uri }} vol-info --pool {{ _vm_pool }} kolab-minimal
+ - name: Check for kolab disk image
+ command: virsh --connect {{ qemu_uri }} vol-info --pool {{ _vm_pool }} kolab-diskimage
delegate_to: 127.0.0.1
register: _disk_info
ignore_errors: true
- name: Download vm image
get_url:
url: "{{ disk_image }}"
- dest: "/tmp/{{ ansible_user }}"
- owner: "{{ ansible_user }}"
+ dest: "/tmp/"
register: downloaded_file
delegate_to: 127.0.0.1
- when: not disk_image_path
+ when: disk_image_path is undefined and _disk_info is failed
- ansible.builtin.set_fact:
disk_image_path: "{{ downloaded_file.dest }}"
- when: not disk_image_path
+ when: disk_image_path is undefined and _disk_info is failed
# Size according to qemu-img info --output json ../../build/packer/artifacts/qemu/kolab-minimal-0.1/kolab-minimal-0.1.qcow2 | jq -r .[\"virtual-size\"]
- - name: Create kolab-minimal Volume
- command: virsh --connect {{ qemu_uri }} vol-create-as --pool {{ _vm_pool }} --name kolab-minimal --capacity 20G --format qcow2
+ - name: Create kolab-diskimage Volume
+ command: virsh --connect {{ qemu_uri }} vol-create-as --pool {{ _vm_pool }} --name kolab-diskimage --capacity 20G --format qcow2
delegate_to: 127.0.0.1
when: _disk_info is failed
# This can fail because it's executed per host, so with multiple hosts on the same hypervisor it will be redundant
ignore_errors: true
- - name: Upload kolab-minimal image
- command: virsh --connect {{ qemu_uri }} vol-upload --pool {{ _vm_pool }} --vol kolab-minimal --file {{ disk_image_path }}
+ - name: Upload kolab image
+ command: virsh --connect {{ qemu_uri }} vol-upload --pool {{ _vm_pool }} --vol kolab-diskimage --file {{ disk_image_path }}
delegate_to: 127.0.0.1
when: _disk_info is failed
# This can fail because it's executed per host, so with multiple hosts on the same hypervisor it will be redundant
ignore_errors: true
- name: Create VM Volume
- command: virsh --connect {{ qemu_uri }} vol-clone --pool {{ _vm_pool }} --vol kolab-minimal --newname guest_{{ inventory_hostname }}
+ command: virsh --connect {{ qemu_uri }} vol-clone --pool {{ _vm_pool }} --vol kolab-diskimage --newname guest_{{ inventory_hostname }}
delegate_to: 127.0.0.1
+ - name: Prepare cloudinit file
+ when: use_cloudinit
+ block:
+ - name: Create kickstart file for VM installation
+ delegate_to: 127.0.0.1
+ template:
+ src: "cloudinit_user.j2"
+ dest: "/tmp/{{ vm_hostname | default(inventory_hostname) }}_cloudinit_user"
+ mode: '666'
+ vars:
+ _vm_root_password: "{{ vm_root_password }}"
+ root_ssh_pubkeys: "{{ vm_root_ssh_pubkeys }}"
+ _hostname: "{{ vm_hostname | default(inventory_hostname) }}"
+ _domain: "{{ domain }}"
+ register: _r_cloudinit_user
+
+ - name: Create kickstart file for VM installation
+ delegate_to: 127.0.0.1
+ template:
+ src: "cloudinit_meta.j2"
+ dest: "/tmp/{{ vm_hostname | default(inventory_hostname) }}_cloudinit_meta"
+ mode: '666'
+ vars:
+ _hostname: "{{ vm_hostname | default(inventory_hostname) }}"
+ register: _r_cloudinit_meta
+
- name: Prepare kickstart file
when: use_kickstart_file
block:
- name: Create kickstart file for VM installation
delegate_to: 127.0.0.1
template:
src: "almalinux9.ks.j2"
dest: "/tmp/{{ vm_hostname | default(inventory_hostname) }}.ks"
mode: '666'
vars:
_vm_root_password: "{{ vm_root_password }}"
root_ssh_pubkeys: "{{ vm_root_ssh_pubkeys }}"
_vm_users: "{{ vm_users }}"
_hostname: "{{ vm_hostname | default(inventory_hostname) }}"
_install_url: "{{ install_url }}"
register: _r_kickstart
- name: Check for volume
command: virsh --connect {{ qemu_uri }} vol-info --pool {{ _vm_pool }} guest_{{ inventory_hostname }}
delegate_to: 127.0.0.1
register: _disk_info
ignore_errors: true
- name: Create VM Volume
command: virsh --connect {{ qemu_uri }} vol-create-as --pool {{ _vm_pool }} --name guest_{{ inventory_hostname }} --capacity {{ vm_disk_size }}
delegate_to: 127.0.0.1
when: _disk_info is failed
- name: Create VM with virt-install
shell:
# We start off with a fixed amount of memory because the format is different.
# Also, not having enough memory results in rather cryptic installation errors (dracut: FATAL: Failed to find a root filesystem in /tmp/curl_fetch_url1/install.img).
# We also postpone attaching the data disks.
cmd: >
virt-install
--connect {{ qemu_uri }}
--name {{ vm_hostname | default(inventory_hostname) }}
--virt-type kvm
--vcpus {{ vm_cpus }}
--memory 4096
--boot hd,menu=on
+ {% if use_cloudinit %}
+ --cloud-init user-data={{ _r_cloudinit_user['dest'] }},meta-data={{ _r_cloudinit_meta['dest'] }}
+ {% endif %}
{% if use_kickstart_file %}
--initrd-inject={{ _r_kickstart['dest'] }}
--extra-args="inst.ks=file:/{{ _r_kickstart['dest'] | basename }} console=ttyS0,115200n8 ip=dhcp"
--location {{ install_url }}
{% else %}
--import
{% endif %}
--disk vol={{ _vm_pool }}/guest_{{ inventory_hostname }},bus=virtio
--network {{ vm_network | default('type=network,source=default,model=virtio') }}
--os-variant almalinux9
--noreboot
--graphics none {{ '--dry-run' if ansible_check_mode else '' }}
--console pty,target_type=serial
chdir: "{{ resources_dir }}"
delegate_to: 127.0.0.1
- name: Wait for VM installation completion
command:
cmd: >-
virsh
--connect {{ qemu_uri }}
domstate "{{ inventory_hostname }}"
check_mode: false
delay: 30
register: _vm_state
retries: 30
until: _vm_state.stdout == "shut off"
delegate_to: 127.0.0.1
+ when: not use_cloudinit
+
+ - name: Discover vm ip
+ shell: virsh --connect {{ qemu_uri }} domifaddr {{ inventory_hostname }} --source agent | grep eth0 | grep ipv4 | head -1 | tr -s ' ' | cut -d ' ' -f5 | cut -d '/' -f1
+ register: vm_ip
+ retries: 50
+ delay: 2
+ until: vm_ip.stdout != ""
+ delegate_to: 127.0.0.1
+ check_mode: false
+
+ - name: Add a host alias so we can connect to the discovered vm ip
+ ansible.builtin.add_host:
+ hostname: '{{ inventory_hostname }}'
+ ansible_host: '{{ vm_ip.stdout }}'
+
+ - name: Wait for SSH to become available
+ ansible.builtin.wait_for_connection:
+ timeout: 300
+ when: use_cloudinit
+
+ - name: Wait for cloud-init completion
+ ansible.builtin.command: cloud-init status --wait
+ changed_when: false
+ when: use_cloudinit
- name: Remove kickstart file
file:
path: "{{ _r_kickstart['dest'] }}"
state: absent
delegate_to: 127.0.0.1
when: use_kickstart_file
# VM create block end
- name: Print return information from the previous task
ansible.builtin.debug:
var: _vm_status
- name: Attach data volumes
vars:
_volumes: "{{ volumes | default([]) }}"
block:
- name: Check for data volume to attach
command: virsh --connect {{ qemu_uri }} vol-path --pool {{ item['pool'] }} data_{{ inventory_hostname }}_{{ item['name'] }}
delegate_to: 127.0.0.1
register: _disk_info
loop: "{{ _volumes }}"
- name: Check for existing devices
command: virsh --connect {{ qemu_uri }} domblklist {{ inventory_hostname }}
delegate_to: 127.0.0.1
register: _device_info
- name: Attach volume if not already attached
command: virsh --connect {{ qemu_uri }} attach-disk --domain {{ inventory_hostname }} --source {{ item.stdout }} --target {{ item.item['device'] }} --targetbus virtio --driver qemu --subdriver raw --serial {{ item.item['name'] }} --config --persistent
delegate_to: 127.0.0.1
when: _disk_info and item.stdout not in _device_info.stdout
loop: "{{ _disk_info.results }}"
- name: Set max memory
shell: virsh --connect {{ qemu_uri }} setmaxmem {{ inventory_hostname }} {{ vm_max_memory | default(vm_memory) }} --config
delegate_to: 127.0.0.1
- name: Set memory
shell: virsh --connect {{ qemu_uri }} setmem {{ inventory_hostname }} {{ vm_memory }} --config
delegate_to: 127.0.0.1
- name: Set max cpu
shell: virsh --connect {{ qemu_uri }} setvcpus {{ inventory_hostname }} {{ vm_cpus }} --maximum --config
delegate_to: 127.0.0.1
- name: Set cpu
shell: virsh --connect {{ qemu_uri }} setvcpus {{ inventory_hostname }} {{ vm_cpus }} --config
delegate_to: 127.0.0.1
- name: start vm
when: _vm_status.stdout != 'running'
community.libvirt.virt:
name: "{{ inventory_hostname }}"
state: running
uri: "{{ qemu_uri }}"
delegate_to: 127.0.0.1
- name: Discover vm ip
shell: virsh --connect {{ qemu_uri }} domifaddr {{ inventory_hostname }} --source agent | grep eth0 | grep ipv4 | head -1 | tr -s ' ' | cut -d ' ' -f5 | cut -d '/' -f1
register: vm_ip
retries: 50
delay: 2
until: vm_ip.stdout != ""
delegate_to: 127.0.0.1
check_mode: false
diff --git a/deployments/ansible/roles/kvm/templates/cloudinit_meta.j2 b/deployments/ansible/roles/kvm/templates/cloudinit_meta.j2
new file mode 100644
index 0000000..1ba5dd2
--- /dev/null
+++ b/deployments/ansible/roles/kvm/templates/cloudinit_meta.j2
@@ -0,0 +1,3 @@
+#cloud-config
+instance-id: almalinux9-vm
+local-hostname: {{ _hostname }}
diff --git a/deployments/ansible/roles/kvm/templates/cloudinit_user.j2 b/deployments/ansible/roles/kvm/templates/cloudinit_user.j2
new file mode 100644
index 0000000..30d3823
--- /dev/null
+++ b/deployments/ansible/roles/kvm/templates/cloudinit_user.j2
@@ -0,0 +1,33 @@
+#cloud-config
+hostname: "{{ _hostname }}"
+fqdn: "{{ _hostname + '.' + _domain }}"
+prefer_fqdn_over_hostname: true
+ssh_pwauth: true
+disable_root: false
+preserve_hostname: true
+packages:
+ - qemu-guest-agent
+
+users:
+ - name: root
+ ssh_pwauth: true
+{% if root_ssh_pubkeys | default( False ) %}
+ ssh_authorized_keys:
+{% for _ssh_pubkey in root_ssh_pubkeys | default( [] ) %}
+ - {{ _ssh_pubkey }}
+{% endfor %}
+{% endif %}
+
+chpasswd:
+ list: |
+ root:{{ vm_root_password }}
+ expire: false
+
+runcmd:
+ - nmcli connection migrate
+ - sysctl -w net.ipv6.conf.all.disable_ipv6=1
+ - systemctl disable cloud-init
+ - systemctl enable --now qemu-guest-agent
+ - hostnamectl set-hostname {{ _hostname }}
+output:
+ all: '| tee -a /var/log/cloud-init-output.log'
diff --git a/examples/k3s-single-node/inventory.yaml b/examples/k3s-single-node/inventory.yaml
index c5e5bc7..8863d74 100644
--- a/examples/k3s-single-node/inventory.yaml
+++ b/examples/k3s-single-node/inventory.yaml
@@ -1,38 +1,40 @@
---
all:
vars:
domain: kolab.local
admin_password: simple123
chart_url: "{{ playbook_dir }}/../../../kolab"
local_registry: false
k3s_db_password: simple123
vm_root_password: simple123
data_pool: default
data_size: 2G
# disk_image_path: ../../../kolab-kubernetes/build/packer/artifacts/qemu/kolab-minimal-0.1/kolab-minimal-0.1.qcow2
vm_memory: 4G
# Vars for the KVM role (provision_vm: true)
# Note that if provisioning is not enabledthe ip is not discovered and needs to be configured.
provision_vm: true
- use_kickstart_file: true
- install_url: "https://vault.almalinux.org/9.5/BaseOS/x86_64/os/"
+ # use_kickstart_file: true
+ use_cloudinit: true
+ # install_url: "https://vault.almalinux.org/9.5/BaseOS/x86_64/os/"
+ disk_image: https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2
hosts:
# kolab1:
# ansible_host: 192.168.122.110
localhost:
ansible_connection: local
infrastructure_nodes:
hosts:
kolab1:
worker_nodes:
hosts:
kolab1:
hypervisor_primary_group:
vars:
qemu_uri: qemu:///system
hosts:
kolab1:

File Metadata

Mime Type
text/x-diff
Expires
Sat, Apr 4, 6:47 AM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18822904
Default Alt Text
(14 KB)

Event Timeline