feat: Add VFIO binding script and update playbook for enhanced virtualization support
This commit is contained in:
@@ -0,0 +1 @@
|
||||
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHHOPBR9p9kq5Cqzpe4cr3jHnweaYrHPXv5sXNzt+sCXP54uc5rWUBhxW2OQVvQzJ47dEVhEKi4WSC7LcuKS2G5AQDzWXNiasHvYIYQU3F/EknVCZnsiXYqXphYkJA6rJCNRnISZCIC1mocq6PB7J08ONdRFCvjfUBuVRT8BNGXNmQ/zQ==
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
DEV="$1"
|
||||
VENDOR="$2"
|
||||
DEVICE="$3"
|
||||
|
||||
if [ -z "$DEV" ] || [ -z "$VENDOR" ] || [ -z "$DEVICE" ]; then
|
||||
echo "Usage: $0 <PCI_DEVICE_ID> <VENDOR_ID> <DEVICE_ID>"
|
||||
echo "Example: $0 0000:3b:00.0 8086 1520"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait until device exists
|
||||
for i in {1..20}; do
|
||||
[ -e /sys/bus/pci/devices/$DEV ] && break
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# Unbind from current driver
|
||||
logger -t vfio-bind "Binding device $DEV (vendor: $VENDOR, device: $DEVICE) to vfio-pci"
|
||||
if [ -L /sys/bus/pci/devices/$DEV/driver ]; then
|
||||
logger -t vfio-bind "Unbinding device $DEV from current driver"
|
||||
echo "$DEV" > /sys/bus/pci/devices/$DEV/driver/unbind
|
||||
fi
|
||||
|
||||
# Tell kernel to prefer vfio-pci
|
||||
logger -t vfio-bind "Setting driver override to vfio-pci for device $DEV"
|
||||
echo vfio-pci > /sys/bus/pci/devices/$DEV/driver_override
|
||||
|
||||
# Bind to vfio-pci
|
||||
logger -t vfio-bind "Binding device $DEV to vfio-pci driver"
|
||||
echo "$DEV" > /sys/bus/pci/drivers/vfio-pci/bind
|
||||
@@ -1,6 +1,24 @@
|
||||
hostname: vh-01.lab.alexpires.me
|
||||
ansible_user: "{{ lookup('env', 'ANSIBLE_USER') }}"
|
||||
|
||||
packages_blocklist:
|
||||
- apport*
|
||||
- autofs
|
||||
- beep
|
||||
- git
|
||||
- pastebinit
|
||||
- popularity-contest
|
||||
- prelink
|
||||
- rpcbind
|
||||
- rsh*
|
||||
- talk*
|
||||
- telnet*
|
||||
- tftp*
|
||||
- whoopsie
|
||||
- xinetd
|
||||
- yp-tools
|
||||
- ypbind
|
||||
|
||||
# Users
|
||||
login_users:
|
||||
- username: "{{ ansible_user }}"
|
||||
@@ -36,7 +54,7 @@ ufw_enable: true
|
||||
fw_allowed_ports:
|
||||
- { rule: "allow", port: "22", proto: "tcp", from: "10.5.5.5/32" } # Wireguard VPN (Laptop)
|
||||
- { rule: "allow", port: "22", proto: "tcp", from: "10.19.4.0/24" } # local network
|
||||
- { rule: "allow", port: "9090", proto: "tcp" }
|
||||
- { rule: "allow", port: "9090", proto: "tcp", from: "10.19.4.0/24" } # local network
|
||||
|
||||
ufw_outgoing_traffic:
|
||||
- 22 # SSH
|
||||
@@ -53,6 +71,14 @@ ipv4_sysctl_settings:
|
||||
|
||||
disable_ipv6: true
|
||||
|
||||
# Network Bridge Configuration
|
||||
bridge_name: "br0"
|
||||
bridge_interface: "{{ ansible_default_ipv4.interface }}" # Auto-detect primary interface
|
||||
bridge_ipv4_address: "10.19.4.254/24" # Adjust to your static IP
|
||||
bridge_ipv4_gateway: "10.19.4.1"
|
||||
bridge_ipv4_dns: "10.19.4.1,1.1.1.1"
|
||||
bridge_ipv4_domain: "lab.alexpires.me"
|
||||
|
||||
# geoip will override hosts_allow and hosts_deny (so it's disabled - CIS hardening)
|
||||
custom_hosts_acls: true
|
||||
|
||||
@@ -63,31 +89,30 @@ hide_pid: 0
|
||||
install_aide: false
|
||||
|
||||
# Unattended upgrades
|
||||
unattended_reboot: true
|
||||
unattended_reboot: false
|
||||
unattended_reboot_time: "04:30"
|
||||
|
||||
# Duo Security
|
||||
duo_users: ["*", "!provision"]
|
||||
duo_api_hostname: api-7cda1654.duosecurity.com
|
||||
|
||||
# VMs reserved CPU (for gaming and AI)
|
||||
virt_vm_reserved_cpu: "1-5,7-11"
|
||||
virt_raw_block_devices:
|
||||
- "nvme0n1"
|
||||
- "nvme0n1p1"
|
||||
- "nvme0n1p2"
|
||||
# VMs reserved CPU )
|
||||
virt_vm_reserved_cpu: "1-7,9-15"
|
||||
virt_raw_block_devices: []
|
||||
|
||||
# Devices to unbind for VFIO passthrough (This are devices that will be unbound at boot with vfio-bind.sh)
|
||||
virt_vfio_devices:
|
||||
- { dev: "0000:08:00.0", vendor: "1b73", device: "1100" } # Fresco Logic FL1100 USB 3.0 Host Controller
|
||||
- { dev: "0000:05:00.0", vendor: "c0a9", device: "5415" } # Micron/Crucial Technology T500 NVMe PCIe SSD
|
||||
|
||||
virt_extra_grub_args: >
|
||||
i915.modeset=1 i915.enable_gvt=1 i915.enable_fbc=0
|
||||
initcall_blacklist=simpledrm_platform_driver_init
|
||||
rd.driver.blacklist=nouveau modprobe.blacklist=nouveau
|
||||
rd.driver.blacklist=nouveau modprobe.blacklist=nouveau ipv6.disable=1 audit=1 audit_backlog_limit=8192
|
||||
|
||||
virt_vfio_ids:
|
||||
- 10de:2482 # NVIDIA Corporation GA104 [GeForce RTX 3070 Ti]
|
||||
- 10de:228b # NVIDIA Corporation GA106 High Definition Audio Controller
|
||||
- 10de:2504 # NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
|
||||
- 10de:228e # NVIDIA Corporation GA106 High Definition Audio Controller
|
||||
- 10de:1430 # NVIDIA Corporation M2000 [Maxwell GM107GL]
|
||||
- 10de:0fba # NVIDIA Corporation M2000 High Definition Audio Controller
|
||||
- 1b73:1100 # Fresco Logic FL1100 USB 3.0 Host Controller
|
||||
- c0a9:5415 # Micron/Crucial Technology T500 NVMe PCIe SSD
|
||||
|
||||
virt_blacklist:
|
||||
- noveau
|
||||
@@ -96,15 +121,15 @@ virt_blacklist:
|
||||
- mxm_wmi
|
||||
|
||||
virt_machines:
|
||||
- name: windows-11
|
||||
title: "Microsoft Windows 11"
|
||||
- name: win10pro
|
||||
title: "Microsoft Windows 10 Pro"
|
||||
uuid: "51d5d091-67cb-4113-bd8e-817e7317e1b4"
|
||||
autostart: true
|
||||
memory: 25165824
|
||||
cores: 4
|
||||
autostart: false
|
||||
memory: 16
|
||||
cores: 5
|
||||
threads: 2
|
||||
physical_cpus: "2-8,3-9,4-10,5-11"
|
||||
reserved_cpus: "0,6"
|
||||
physical_cpus: "3-11,4-12,5-13,6-14,7-15"
|
||||
reserved_cpus: "0,8"
|
||||
enable_hyperv: true
|
||||
cdrom: true
|
||||
console: false
|
||||
@@ -112,126 +137,199 @@ virt_machines:
|
||||
secure_boot: true
|
||||
tpm: true
|
||||
tablet: true
|
||||
disk_file: "windows-11.qcow2"
|
||||
net_bridge: br0
|
||||
disk_file: "win10pro.qcow2"
|
||||
mac_address: "52:54:00:cd:dd:2d"
|
||||
block_devs:
|
||||
- block_dev: "/dev/nvme0n1"
|
||||
target_dev: "sdb"
|
||||
block_devs: []
|
||||
guest_agent: true
|
||||
host_devs:
|
||||
# Intel MDev device for GVT-g
|
||||
- type: "mdev"
|
||||
# Micron/Crucial Technology T500 NVMe PCIe SSD
|
||||
- type: "pci"
|
||||
source:
|
||||
uuid: "5abeb24f-d6f4-4666-b495-303f15b05723"
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x05"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
address:
|
||||
{
|
||||
type: "pci",
|
||||
domain: "0x0000",
|
||||
bus: "0x07",
|
||||
slot: "0x00",
|
||||
function: "0x0",
|
||||
}
|
||||
type: "pci"
|
||||
domain: "0x0000"
|
||||
bus: "0x11"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
# Fresco Logic FL1100 USB 3.0 Host Controller
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x06"
|
||||
bus: "0x08"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
address:
|
||||
{
|
||||
type: "pci",
|
||||
domain: "0x0000",
|
||||
bus: "0x10",
|
||||
slot: "0x00",
|
||||
function: "0x0",
|
||||
}
|
||||
# NVIDIA Corporation GA104 [GeForce RTX 3070 Ti]
|
||||
type: "pci"
|
||||
domain: "0x0000"
|
||||
bus: "0x10"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
# NVIDIA Corporation M2000 [Maxwell GM107GL]
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x01"
|
||||
bus: "0x03"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
address:
|
||||
{
|
||||
type: "pci",
|
||||
domain: "0x0000",
|
||||
bus: "0x0b",
|
||||
slot: "0x00",
|
||||
function: "0x0",
|
||||
}
|
||||
# NVIDIA Corporation GA106 High Definition Audio Controller
|
||||
type: "pci"
|
||||
domain: "0x0000"
|
||||
bus: "0x0b"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
# NVIDIA Corporation M2000 High Definition Audio Controller
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x01"
|
||||
bus: "0x03"
|
||||
slot: "0x00"
|
||||
function: "0x1"
|
||||
address:
|
||||
{
|
||||
type: "pci",
|
||||
domain: "0x0000",
|
||||
bus: "0x0f",
|
||||
slot: "0x00",
|
||||
function: "0x0",
|
||||
}
|
||||
type: "pci"
|
||||
domain: "0x0000"
|
||||
bus: "0x0f"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
|
||||
- name: fedora-headless
|
||||
title: "Fedora CUDA headless"
|
||||
- name: win11home
|
||||
title: "Microsoft Windows 11 Home"
|
||||
uuid: "51d5d091-67cb-4113-bd8e-817e7317e1b5"
|
||||
autostart: false
|
||||
memory: 16
|
||||
cores: 5
|
||||
threads: 2
|
||||
physical_cpus: "3-11,4-12,5-13,6-14,7-15"
|
||||
reserved_cpus: "0,8"
|
||||
enable_hyperv: true
|
||||
cdrom: true
|
||||
console: false
|
||||
audio: true
|
||||
secure_boot: true
|
||||
tpm: true
|
||||
tablet: true
|
||||
net_bridge: br0
|
||||
disk_file: "win11home.qcow2"
|
||||
mac_address: "52:54:00:cd:dd:2e"
|
||||
block_devs: []
|
||||
guest_agent: true
|
||||
host_devs:
|
||||
# Micron/Crucial Technology T500 NVMe PCIe SSD
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x05"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
address:
|
||||
type: "pci"
|
||||
domain: "0x0000"
|
||||
bus: "0x11"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
# Fresco Logic FL1100 USB 3.0 Host Controller
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x08"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
address:
|
||||
type: "pci"
|
||||
domain: "0x0000"
|
||||
bus: "0x10"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
# NVIDIA Corporation M2000 [Maxwell GM107GL]
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x03"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
address:
|
||||
type: "pci"
|
||||
domain: "0x0000"
|
||||
bus: "0x0b"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
# NVIDIA Corporation M2000 High Definition Audio Controller
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x03"
|
||||
slot: "0x00"
|
||||
function: "0x1"
|
||||
address:
|
||||
type: "pci"
|
||||
domain: "0x0000"
|
||||
bus: "0x0f"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
|
||||
- name: dev-01
|
||||
title: "Lab Kubernetes VM"
|
||||
uuid: "55feda16-51ae-446e-9c83-4c0eee1e5e00"
|
||||
cloud_image_url: "http://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
|
||||
cloud_image_sha256: "2b5f90ffe8180def601c021c874e55d8303e8bcbfc66fee2b94414f43ac5eb1f"
|
||||
disk_size: 80G
|
||||
cloud_init: true
|
||||
autostart: true
|
||||
memory: 33554432
|
||||
memory: 8
|
||||
cores: 1
|
||||
threads: 2
|
||||
physical_cpus: "1-7"
|
||||
reserved_cpus: "0,6"
|
||||
cdrom: false
|
||||
physical_cpus: "2-10"
|
||||
reserved_cpus: "0,8"
|
||||
cdrom: true
|
||||
console: true
|
||||
audio: false
|
||||
secure_boot: false
|
||||
secure_boot: true
|
||||
tpm: true
|
||||
disk_file: "fedora-headless.qcow2"
|
||||
net_bridge: br0
|
||||
disk_file: "dev-01.qcow2"
|
||||
mac_address: "52:54:00:ae:f3:d0"
|
||||
block_devs:
|
||||
- block_dev: "/dev/nvme0n1"
|
||||
target_dev: "sdb"
|
||||
host_devs:
|
||||
# NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x03"
|
||||
slot: "0x00"
|
||||
function: "0x0"
|
||||
address:
|
||||
{
|
||||
type: "pci",
|
||||
domain: "0x0000",
|
||||
bus: "0x09",
|
||||
slot: "0x00",
|
||||
function: "0x0",
|
||||
}
|
||||
# NVIDIA Corporation GA106 High Definition Audio Controller
|
||||
- type: "pci"
|
||||
source:
|
||||
address:
|
||||
domain: "0x0000"
|
||||
bus: "0x03"
|
||||
slot: "0x00"
|
||||
function: "0x1"
|
||||
address:
|
||||
{
|
||||
type: "pci",
|
||||
domain: "0x0000",
|
||||
bus: "0x0a",
|
||||
slot: "0x00",
|
||||
function: "0x0",
|
||||
}
|
||||
block_devs: []
|
||||
host_devs: []
|
||||
guest_agent: true
|
||||
virtio_fs:
|
||||
- source: "/mnt/srv"
|
||||
target: "srv"
|
||||
- source: "/mnt/storage"
|
||||
target: "storage"
|
||||
user_data: |
|
||||
#cloud-config
|
||||
hostname: dev-01
|
||||
fqdn: dev-01.lab.alexpires.me
|
||||
manage_etc_hosts: true
|
||||
users:
|
||||
- name: provision
|
||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||
shell: /bin/bash
|
||||
lock_passwd: true
|
||||
ssh_authorized_keys:
|
||||
- {{ lookup('file', 'keys/localnetwork.pub') | trim }}
|
||||
ssh_pwauth: false
|
||||
disable_root: true
|
||||
package_upgrade: true
|
||||
packages:
|
||||
- qemu-guest-agent
|
||||
runcmd:
|
||||
- systemctl enable qemu-guest-agent
|
||||
- systemctl start qemu-guest-agent
|
||||
|
||||
# Let's Encrypt / Certbot
|
||||
cloudns_auth_id: "{{ lookup('env', 'CLOUDNS_AUTH_ID') }}"
|
||||
cloudns_auth_password: "{{ lookup('env', 'CLOUDNS_PASSWORD') }}"
|
||||
cloudns_nameserver: "109.201.133.111"
|
||||
|
||||
@@ -10,6 +10,21 @@
|
||||
default_hugepagesz=1G hugepagesz=1G hugepages=8 mitigations=off loglevel=3 {{ virt_extra_grub_args | default("") | trim}}
|
||||
|
||||
tasks:
|
||||
- name: Ensure the system is Fedora
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_facts['distribution'] == "Fedora"
|
||||
fail_msg: "This playbook only supports Fedora hosts."
|
||||
|
||||
- name: Install python3-libdnf5 so Ansible DNF module works
|
||||
become: true
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
dnf install -y python3-libdnf5
|
||||
touch /etc/.python3_libdnf5_installed
|
||||
args:
|
||||
creates: /etc/.python3_libdnf5_installed
|
||||
|
||||
- name: Install required packages
|
||||
ansible.builtin.dnf:
|
||||
name:
|
||||
@@ -22,8 +37,115 @@
|
||||
- tuned
|
||||
- python3-lxml
|
||||
- python3-libvirt
|
||||
- tuned
|
||||
- cloud-utils
|
||||
- qemu-img
|
||||
state: present
|
||||
|
||||
# ===== BRIDGE CONFIGURATION TASKS =====
|
||||
|
||||
- name: Detect current network interface
|
||||
ansible.builtin.set_fact:
|
||||
primary_interface: "{{ bridge_interface }}"
|
||||
when: bridge_interface is defined
|
||||
|
||||
- name: Check if bridge already exists
|
||||
ansible.builtin.command: nmcli -t -f NAME,TYPE connection show
|
||||
register: nmcli_connections
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Set bridge existence fact
|
||||
ansible.builtin.set_fact:
|
||||
bridge_exists: "{{ (bridge_name in nmcli_connections.stdout) and ('bridge' in nmcli_connections.stdout) }}"
|
||||
|
||||
- name: Get current interface connection name
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
set -o pipefail
|
||||
nmcli -t -f NAME,DEVICE connection show --active | grep ":{{ primary_interface }}$" | cut -d: -f1 | head -n1
|
||||
executable: /bin/bash
|
||||
register: current_connection_name
|
||||
changed_when: false
|
||||
when: not bridge_exists
|
||||
|
||||
- name: Create bridge connection with static IPv4
|
||||
ansible.builtin.command: >
|
||||
nmcli connection add
|
||||
type bridge
|
||||
con-name {{ bridge_name }}
|
||||
ifname {{ bridge_name }}
|
||||
ipv4.method manual
|
||||
ipv4.addresses {{ bridge_ipv4_address }}
|
||||
ipv4.gateway {{ bridge_ipv4_gateway }}
|
||||
ipv4.dns "{{ bridge_ipv4_dns }}"
|
||||
ipv4.dns-search {{ bridge_ipv4_domain }}
|
||||
ipv6.method disabled
|
||||
connection.autoconnect yes
|
||||
bridge.stp no
|
||||
when: not bridge_exists
|
||||
changed_when: true
|
||||
register: bridge_created
|
||||
|
||||
- name: Create bridge slave connection for physical interface
|
||||
ansible.builtin.command: >
|
||||
nmcli connection add
|
||||
type ethernet
|
||||
con-name {{ bridge_name }}-slave
|
||||
ifname {{ primary_interface }}
|
||||
master {{ bridge_name }}
|
||||
slave-type bridge
|
||||
when: not bridge_exists and bridge_created is succeeded
|
||||
changed_when: true
|
||||
register: slave_created
|
||||
|
||||
- name: Deactivate old interface connection and activate bridge
|
||||
become: true
|
||||
ansible.builtin.command: >
|
||||
nmcli connection down "{{ current_connection_name.stdout }}"
|
||||
nmcli connection up {{ bridge_name }}
|
||||
when:
|
||||
- not bridge_exists
|
||||
- slave_created is succeeded
|
||||
- current_connection_name.stdout | length > 0
|
||||
register: bridge_activated
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
async: 10
|
||||
poll: 0
|
||||
|
||||
- name: Wait for network connectivity to restore # noqa: no-handler
|
||||
ansible.builtin.wait_for:
|
||||
host: "{{ bridge_ipv4_address.split('/')[0] }}"
|
||||
port: 22
|
||||
timeout: 30
|
||||
delegate_to: localhost
|
||||
when: bridge_activated is changed
|
||||
|
||||
- name: Switch ansible to connect via bridge IP # noqa: no-handler
|
||||
ansible.builtin.set_fact:
|
||||
ansible_host: "{{ bridge_ipv4_address.split('/')[0] }}"
|
||||
when: bridge_activated is changed
|
||||
|
||||
- name: Verify bridge is active # noqa: no-handler
|
||||
ansible.builtin.command: ip addr show {{ bridge_name }}
|
||||
register: bridge_status
|
||||
changed_when: false
|
||||
failed_when: "'state UP' not in bridge_status.stdout"
|
||||
when: bridge_activated is changed
|
||||
|
||||
- name: Display bridge configuration
|
||||
ansible.builtin.debug: # noqa: no-handler
|
||||
msg:
|
||||
- "Bridge {{ bridge_name }} is configured and active"
|
||||
- "IP Address: {{ bridge_ipv4_address }}"
|
||||
- "Gateway: {{ bridge_ipv4_gateway }}"
|
||||
- "DNS: {{ bridge_ipv4_dns }}"
|
||||
- "Physical interface: {{ primary_interface }}"
|
||||
when: bridge_activated is changed
|
||||
|
||||
# ===== END BRIDGE CONFIGURATION =====
|
||||
|
||||
- name: Enable and start libvirtd
|
||||
ansible.builtin.systemd:
|
||||
name: libvirtd
|
||||
@@ -38,12 +160,47 @@
|
||||
backrefs: true
|
||||
notify: Rebuild GRUB config
|
||||
|
||||
- name: Copy vfio-bind script
|
||||
ansible.builtin.copy:
|
||||
src: vfio-bind.sh
|
||||
dest: /usr/local/bin/vfio-bind.sh
|
||||
mode: '0755'
|
||||
|
||||
- name: Create systemd service for vfio-bind
|
||||
ansible.builtin.copy:
|
||||
dest: "/etc/systemd/system/vfio-{{ item.vendor }}-{{ item.device }}-bind.service"
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Bind PCI device {{ item.vendor }}:{{ item.device }} to VFIO driver
|
||||
After=systemd-udev-settle.service
|
||||
Wants=systemd-udev-settle.service
|
||||
Before=libvirtd.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/vfio-bind.sh "{{ item.dev }}" "{{ item.vendor }}" "{{ item.device }}"
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
mode: '0644'
|
||||
loop: "{{ virt_vfio_devices }}"
|
||||
|
||||
- name: Enable and start VFIO bind services
|
||||
ansible.builtin.systemd:
|
||||
name: "vfio-{{ item.vendor }}-{{ item.device }}-bind.service"
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
loop: "{{ virt_vfio_devices }}"
|
||||
|
||||
- name: Add VFIO PCI device IDs to modprobe
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/modprobe.d/vfio.conf
|
||||
content: |
|
||||
options vfio-pci ids={{ virt_vfio_ids | join(',') }}
|
||||
install snd_hda_codec_hdmi /bin/false
|
||||
softdep xhci_hcd pre: vfio-pci
|
||||
mode: '0644'
|
||||
|
||||
- name: Blacklist Nouveau and other drivers
|
||||
@@ -110,6 +267,91 @@
|
||||
- Reload udev rules
|
||||
- Trigger udev to apply changes
|
||||
|
||||
- name: Download and resize cloud image for VM
|
||||
block:
|
||||
- name: Check if local image already exists
|
||||
vars:
|
||||
vm: "{{ item }}"
|
||||
ansible.builtin.stat:
|
||||
path: "/var/lib/libvirt/images/{{ vm.disk_file }}"
|
||||
get_checksum: false
|
||||
register: cloud_image_stat
|
||||
loop: "{{ virt_machines }}"
|
||||
|
||||
- name: Download cloud image if not present
|
||||
vars:
|
||||
id: "{{ item }}"
|
||||
loop: "{{ range(virt_machines | length) }}"
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ virt_machines[id].cloud_image_url }}"
|
||||
dest: "/var/lib/libvirt/images/{{ virt_machines[id].disk_file }}"
|
||||
mode: '0644'
|
||||
checksum: "sha256:{{ virt_machines[id].cloud_image_sha256 }}"
|
||||
when:
|
||||
- not cloud_image_stat.results[id].stat.exists
|
||||
- virt_machines[id].cloud_image_url is defined
|
||||
- virt_machines[id].cloud_image_sha256 is defined
|
||||
|
||||
- name: Resize cloud image
|
||||
vars:
|
||||
id: "{{ item }}"
|
||||
loop: "{{ range(virt_machines | length) }}"
|
||||
ansible.builtin.command: >
|
||||
qemu-img resize /var/lib/libvirt/images/{{ virt_machines[id].disk_file }} {{ virt_machines[id].disk_size | default('20G') }}
|
||||
when:
|
||||
- not cloud_image_stat.results[id].stat.exists
|
||||
- virt_machines[id].disk_size is defined
|
||||
changed_when: false
|
||||
|
||||
- name: Create cloud-init ISO for VM
|
||||
block:
|
||||
- name: Create temporary cloud-init directory
|
||||
vars:
|
||||
vm: "{{ item }}"
|
||||
loop: "{{ virt_machines }}"
|
||||
ansible.builtin.file:
|
||||
path: "/var/lib/libvirt/images/{{ vm.name }}-cloudinit"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
when: vm.user_data is defined
|
||||
|
||||
- name: Create user-data file
|
||||
vars:
|
||||
vm: "{{ item }}"
|
||||
loop: "{{ virt_machines }}"
|
||||
ansible.builtin.copy:
|
||||
dest: "/var/lib/libvirt/images/{{ vm.name }}-cloudinit/user-data"
|
||||
content: |
|
||||
{{ vm.user_data }}
|
||||
mode: '0644'
|
||||
when: vm.user_data is defined
|
||||
register: user_data_created
|
||||
|
||||
- name: Create meta-data file
|
||||
vars:
|
||||
vm: "{{ item }}"
|
||||
loop: "{{ virt_machines }}"
|
||||
ansible.builtin.copy:
|
||||
dest: "/var/lib/libvirt/images/{{ vm.name }}-cloudinit/meta-data"
|
||||
content: |
|
||||
instance-id: {{ vm.name }}-{{ vm.uuid }}
|
||||
local-hostname: {{ vm.name }}
|
||||
mode: '0644'
|
||||
when: vm.user_data is defined
|
||||
|
||||
- name: Create cloud-init ISO image
|
||||
vars:
|
||||
vm: "{{ item }}"
|
||||
loop: "{{ virt_machines }}"
|
||||
ansible.builtin.command: >
|
||||
cloud-localds
|
||||
/var/lib/libvirt/images/{{ vm.name }}-cloudinit.img
|
||||
/var/lib/libvirt/images/{{ vm.name }}-cloudinit/user-data
|
||||
/var/lib/libvirt/images/{{ vm.name }}-cloudinit/meta-data
|
||||
args:
|
||||
creates: "/var/lib/libvirt/images/{{ vm.name }}-cloudinit.img"
|
||||
when: vm.user_data is defined
|
||||
|
||||
- name: Create or update virtual machine
|
||||
vars:
|
||||
vm: "{{ item }}"
|
||||
@@ -117,7 +359,6 @@
|
||||
community.libvirt.virt:
|
||||
autostart: "{{ vm.autostart | default(false) }}"
|
||||
name: "{{ vm.name }}"
|
||||
state: running
|
||||
command: define
|
||||
xml: "{{ lookup('template', 'domain.xml.j2') }}"
|
||||
|
||||
@@ -128,6 +369,7 @@
|
||||
community.libvirt.virt:
|
||||
name: "{{ vm.name }}"
|
||||
state: running
|
||||
when: vm.autostart | default(false)
|
||||
|
||||
- name: Notify user to reboot for changes
|
||||
ansible.builtin.debug:
|
||||
|
||||
@@ -135,6 +135,14 @@
|
||||
- password-auth
|
||||
- pam
|
||||
|
||||
- name: Check if sssd-shadowutils exists
|
||||
ansible.builtin.stat:
|
||||
path: /etc/pam.d/sssd-shadowutils
|
||||
register: sssd_shadowutils
|
||||
tags:
|
||||
- sssd-shadowutils
|
||||
- pam
|
||||
|
||||
- name: Remove nullok from sssd-shadowutils
|
||||
become: true
|
||||
ansible.builtin.replace:
|
||||
@@ -143,6 +151,7 @@
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
when: sssd_shadowutils.stat.exists
|
||||
tags:
|
||||
- sssd-shadowutils
|
||||
- pam
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
- name: Set ssh version as fact
|
||||
ansible.builtin.set_fact:
|
||||
ssh_installed_version: "{{ ssh_version.stderr | regex_search('^OpenSSH_([0-9+].[0-9]+)', '\\1') | join('.') | float }}" # noqa jinja[spacing]
|
||||
ssh_installed_version: "{{ ssh_version.stderr | regex_search('^OpenSSH_([0-9]+.[0-9]+).', '\\1') | join('.') | float }}" # noqa jinja[spacing]
|
||||
when: ssh_version.stderr != ""
|
||||
tags:
|
||||
- roles::cis::sshd
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
- name: CertManager | LetsEncrypt DNS-01 issuer
|
||||
ansible.builtin.include_tasks: issuers/dns-01.yml
|
||||
when: microk8s_certmgr_letsencrypt_dns01 is true
|
||||
when: microk8s_certmgr_letsencrypt_dns01
|
||||
|
||||
- name: CertManager | LetsEncrypt HTTP-01 issuer
|
||||
ansible.builtin.include_tasks: issuers/http-01.yml
|
||||
when: microk8s_certmgr_letsencrypt_http01 is true
|
||||
when: microk8s_certmgr_letsencrypt_http01
|
||||
|
||||
@@ -32,4 +32,8 @@
|
||||
state: present
|
||||
kubeconfig: "{{ k8s_kubeconfig }}"
|
||||
src: "{{ k8s_etc }}/k8s-certmanager-cloudns.yaml"
|
||||
wait: true
|
||||
|
||||
- name: CertManager | Sleep to allow webhook to be ready
|
||||
ansible.builtin.pause:
|
||||
seconds: 15
|
||||
when: microk8s_certmgr_letsencrypt_dns01
|
||||
|
||||
@@ -61,11 +61,6 @@
|
||||
- k8s::install
|
||||
- k8s::kubectl
|
||||
|
||||
- name: Setup LoadBalancer
|
||||
ansible.builtin.include_tasks: loadbalancer.yml
|
||||
tags:
|
||||
- k8s::loadbalancer
|
||||
|
||||
- name: Setup CertManager
|
||||
ansible.builtin.include_tasks: certmanager.yml
|
||||
tags:
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<name>{{ vm.name }}</name>
|
||||
<uuid>{{ vm.uuid }}</uuid>
|
||||
<title>{{ vm.title }}</title>
|
||||
<memory unit='KiB'>{{ vm.memory }}</memory>
|
||||
<currentMemory unit='KiB'>{{ vm.memory }}</currentMemory>
|
||||
<memory unit='GiB'>{{ vm.memory }}</memory>
|
||||
<currentMemory unit='GiB'>{{ vm.memory }}</currentMemory>
|
||||
<memoryBacking>
|
||||
<hugepages/>
|
||||
<source type='memfd'/>
|
||||
@@ -23,9 +23,9 @@
|
||||
<emulatorpin cpuset='{{ vm.reserved_cpus }}'/>
|
||||
</cputune>
|
||||
<os>
|
||||
<type arch='x86_64' machine='pc-q35-7.0'>hvm</type>
|
||||
<loader readonly='yes' secure='{% if vm.secure_boot %}yes{% else %}no{% endif %}' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE{% if vm.secure_boot %}.secboot{% endif %}.fd</loader>
|
||||
<nvram template='/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'>/var/lib/libvirt/qemu/nvram/{{ vm.name }}_VARS.fd</nvram>
|
||||
<type arch='x86_64' machine='pc-q35-8.2'>hvm</type>
|
||||
<loader readonly='yes' secure='{% if vm.secure_boot %}yes{% else %}no{% endif %}' type='pflash' format='qcow2'>/usr/share/edk2/ovmf/OVMF_CODE_4M{% if vm.secure_boot %}.secboot{% endif %}.qcow2</loader>
|
||||
<nvram template='/usr/share/edk2/ovmf/OVMF_VARS_4M.secboot.qcow2' templateFormat='qcow2' format='qcow2'>/var/lib/libvirt/qemu/nvram/{{ vm.name }}_VARS.fd.qcow2</nvram>
|
||||
<boot dev='hd'/>
|
||||
<bootmenu enable='no'/>
|
||||
</os>
|
||||
@@ -44,7 +44,12 @@
|
||||
{% endif %}
|
||||
<smm state='on'/>
|
||||
</features>
|
||||
{% if vm.cpu is defined %}
|
||||
<cpu mode='custom' match='exact' check='none'>
|
||||
<model fallback='allow'>{{ vm.cpu }}</model>
|
||||
{% else %}
|
||||
<cpu mode='host-passthrough' check='none' migratable='on'>
|
||||
{% endif %}
|
||||
<topology sockets='1' dies='1' cores='{{ vm.cores }}' threads='{{ vm.threads }}'/>
|
||||
</cpu>
|
||||
<clock offset='localtime'>
|
||||
@@ -81,6 +86,16 @@
|
||||
<target dev='{{ block_dev.target_dev }}' bus='virtio'/>
|
||||
</disk>
|
||||
{% endfor %}
|
||||
{% if vm.cloud_init is defined %}
|
||||
{% if vm.cloud_init | default(false) %}
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
<source file='/var/lib/libvirt/images/{{ vm.name }}-cloudinit.img'/>
|
||||
<target dev='hdb' bus='virtio'/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if vm.cdrom %}
|
||||
<disk type='file' device='cdrom'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
@@ -187,15 +202,15 @@
|
||||
<address type='usb' bus='0' port='1'/>
|
||||
</controller>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if vm.virtio_fs is defined %}
|
||||
{% if vm.virtio_fs | default(false) %}
|
||||
{% for fs in vm.virtio_fs %}
|
||||
<filesystem type='mount' accessmode='passthrough'>
|
||||
<driver type='virtiofs'/>
|
||||
<source dir='{{ vm.virtio_fs.source }}'/>
|
||||
<target dir='{{ vm.virtio_fs.target }}'/>
|
||||
<driver type='virtiofs' queue='1024'/>
|
||||
<source dir='{{ fs.source }}'/>
|
||||
<target dir='{{ fs.target }}'/>
|
||||
</filesystem>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<interface type='bridge'>
|
||||
<mac address='{{ vm.mac_address }}'/>
|
||||
@@ -221,7 +236,7 @@
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<input type='keyboard' bus='ps2'/>
|
||||
{% if vm.tpm %}
|
||||
<tpm model='tpm-tis'>
|
||||
<tpm model='tpm-crb'>
|
||||
<backend type='emulator' version='2.0'/>
|
||||
</tpm>
|
||||
{% endif %}
|
||||
@@ -248,8 +263,22 @@
|
||||
{% endif %}
|
||||
</hostdev>
|
||||
{% endfor %}
|
||||
{% if vm.guest_agent is defined %}
|
||||
{% if vm.guest_agent | default(false) %}
|
||||
<channel type='unix'>
|
||||
<source mode='bind' path='/var/lib/libvirt/qemu/{{ vm.name }}.agent'/>
|
||||
<target type='virtio' name='org.qemu.guest_agent.0' state='connected'/>
|
||||
</channel>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if vm.mem_balloon is defined %}
|
||||
{% if vm.mem_balloon | default(false) %}
|
||||
<memballoon model='virtio'>
|
||||
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
|
||||
</memballoon>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<memballoon model='none'/>
|
||||
{% endif %}
|
||||
</devices>
|
||||
</domain>
|
||||
@@ -103,12 +103,8 @@ gpu-01.lab.alexpires.me
|
||||
gpu-01.lab.alexpires.me
|
||||
|
||||
[windows]
|
||||
game-01.lab.alexpires.me
|
||||
hpz440.lab.alexpires.me
|
||||
|
||||
[windows_game]
|
||||
game-01.lab.alexpires.me
|
||||
|
||||
[prometheus_linux]
|
||||
prod-01.alexpires.me
|
||||
dev-01.lab.alexpires.me
|
||||
|
||||
@@ -14,7 +14,7 @@ locals {
|
||||
samba_shares = [
|
||||
{
|
||||
name = "Storage"
|
||||
path = "/srv/storage"
|
||||
path = "/mnt/storage"
|
||||
comment = "Main Storage"
|
||||
}
|
||||
]
|
||||
@@ -231,7 +231,7 @@ locals {
|
||||
}
|
||||
|
||||
# mstream
|
||||
mstream_music_folder = "/srv/storage/Music"
|
||||
mstream_music_folder = "/mnt/storage/Music"
|
||||
mstream_fqdn = "music.${local.lab_domain}"
|
||||
}
|
||||
|
||||
|
||||
@@ -364,7 +364,7 @@ resource "kubernetes_deployment" "proxy" {
|
||||
container {
|
||||
name = "proxy"
|
||||
image = "nginx:${var.tag}"
|
||||
image_pull_policy = "Always"
|
||||
image_pull_policy = "IfNotPresent"
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
|
||||
Reference in New Issue
Block a user