--- # ============================================================================= # Install QEMU Guest Agent on KVM Virtual Machines # ============================================================================= # This playbook installs and configures qemu-guest-agent on all KVM guest VMs, # enabling better VM management from the hypervisor. # # Benefits of QEMU Guest Agent: # - Accurate IP address discovery from hypervisor # - Filesystem quiescing for consistent snapshots # - Graceful shutdown/reboot from hypervisor # - VM state monitoring and management # # Usage: # ansible-playbook playbooks/install_qemu_agent.yml # ansible-playbook playbooks/install_qemu_agent.yml --limit pihole # # Note: After installation, the VM needs a virtio-serial channel configured # in the libvirt domain XML. This playbook installs the guest-side component. # # To add the channel (run on hypervisor): # virsh attach-device --config --file channel.xml # # Where channel.xml contains: # # # # # Tags: # - install: Package installation tasks # - config: Service configuration tasks # - validate: Validation tasks only # ============================================================================= - name: Install and Configure QEMU Guest Agent hosts: all become: yes gather_facts: yes tasks: - name: Display QEMU Guest Agent installation information debug: msg: - "=== Installing QEMU Guest Agent ===" - "Host: {{ inventory_hostname }}" - "OS Family: {{ ansible_os_family }}" - "Distribution: {{ ansible_distribution }} {{ ansible_distribution_version }}" tags: [always] - name: Check if QEMU Guest Agent is already installed command: which qemu-ga register: qemu_ga_installed changed_when: false failed_when: false tags: [install, validate] - name: Display current installation status debug: msg: "QEMU Guest Agent {{ 'is already installed' if qemu_ga_installed.rc == 0 else 'is NOT installed' }}" tags: [install, validate] - name: Install QEMU Guest Agent - Debian/Ubuntu apt: name: qemu-guest-agent state: present update_cache: yes when: ansible_os_family == "Debian" register: debian_install tags: [install] - name: Install QEMU Guest Agent - RHEL/Rocky/AlmaLinux/CentOS yum: name: qemu-guest-agent state: present when: ansible_os_family == "RedHat" register: rhel_install tags: [install] - name: Install QEMU Guest Agent - SUSE/openSUSE zypper: name: qemu-guest-agent state: present when: ansible_os_family == "Suse" register: suse_install tags: [install] - name: Verify package installation command: which qemu-ga register: qemu_ga_post_install changed_when: false tags: [install, validate] - name: Get QEMU Guest Agent version command: qemu-ga --version register: qemu_ga_version changed_when: false tags: [install, validate] - name: Display installed version debug: msg: "QEMU Guest Agent version: {{ qemu_ga_version.stdout }}" tags: [install, validate] - name: Enable QEMU Guest Agent service systemd: name: qemu-guest-agent enabled: yes state: started register: service_status tags: [config] - name: Wait for service to be fully started wait_for: timeout: 3 when: service_status is changed tags: [config] - name: Verify service is running systemd: name: qemu-guest-agent register: service_check tags: [config, validate] - name: Check if virtio-serial device exists stat: path: /dev/virtio-ports/org.qemu.guest_agent.0 register: virtio_serial tags: [validate] - name: Check for alternative virtio device paths shell: ls -la /dev/vport* 2>/dev/null || echo "No virtio ports found" register: virtio_ports changed_when: false failed_when: false tags: [validate] - name: Display service and channel status debug: msg: - "=== QEMU Guest Agent Status ===" - "Service status: {{ service_check.status.ActiveState }}" - "Service enabled: {{ service_check.status.UnitFileState }}" - "Virtio serial channel: {{ 'CONFIGURED' if virtio_serial.stat.exists else 'NOT CONFIGURED' }}" - "Available virtio ports:" - "{{ virtio_ports.stdout_lines }}" tags: [validate] - name: Display warning if channel not configured debug: msg: - "" - "WARNING: Virtio serial channel is not configured!" - "The guest agent is running but cannot communicate with the hypervisor." - "" - "To fix this, run on the HYPERVISOR:" - " 1. Shutdown the VM: virsh shutdown {{ inventory_hostname }}" - " 2. Add the channel:" - " virsh attach-device {{ inventory_hostname }} --config \\" - " <(echo '')" - " 3. Start the VM: virsh start {{ inventory_hostname }}" when: not virtio_serial.stat.exists tags: [validate] - name: Test QEMU Guest Agent functionality block: - name: Try to ping QEMU Guest Agent command: qemu-ga-client ping register: agent_ping changed_when: false failed_when: false tags: [validate] - name: Display agent connectivity debug: msg: "Agent connectivity: {{ 'SUCCESS' if agent_ping.rc == 0 else 'FAILED - Channel not configured' }}" tags: [validate] when: virtio_serial.stat.exists - name: Create documentation file for manual steps copy: dest: /root/qemu-guest-agent-setup.txt content: | QEMU Guest Agent Installation Summary ====================================== Date: {{ ansible_date_time.iso8601 }} Host: {{ inventory_hostname }} Status: Agent installed and running Virtio Serial Channel Status: {{ 'CONFIGURED' if virtio_serial.stat.exists else 'NOT CONFIGURED' }} {% if not virtio_serial.stat.exists %} MANUAL CONFIGURATION REQUIRED ============================= The QEMU guest agent is installed and running inside this VM, but it cannot communicate with the hypervisor because the virtio-serial channel is not configured. To complete the setup, execute these commands ON THE HYPERVISOR: 1. Shutdown this VM: virsh shutdown {{ inventory_hostname }} 2. Create channel configuration file: cat > /tmp/{{ inventory_hostname }}-channel.xml << 'EOF' EOF 3. Attach the channel to the VM: virsh attach-device {{ inventory_hostname }} \ --config --file /tmp/{{ inventory_hostname }}-channel.xml 4. Start the VM: virsh start {{ inventory_hostname }} 5. Verify the agent is working: virsh qemu-agent-command {{ inventory_hostname }} '{"execute":"guest-ping"}' Alternatively, you can edit the XML directly: virsh edit {{ inventory_hostname }} And add this section inside : {% else %} CONFIGURATION COMPLETE ====================== The QEMU guest agent is fully configured and can communicate with the hypervisor. Test from hypervisor: virsh qemu-agent-command {{ inventory_hostname }} '{"execute":"guest-ping"}' virsh qemu-agent-command {{ inventory_hostname }} '{"execute":"guest-info"}' {% endif %} mode: '0644' tags: [config] - name: Display installation summary debug: msg: - "====================================" - "QEMU Guest Agent Installation Complete" - "====================================" - "Host: {{ inventory_hostname }}" - "Package: {{ 'Installed' if debian_install is changed or rhel_install is changed or suse_install is changed else 'Already installed' }}" - "Service: {{ service_check.status.ActiveState }} ({{ service_check.status.UnitFileState }})" - "Version: {{ qemu_ga_version.stdout }}" - "Virtio Channel: {{ 'Configured' if virtio_serial.stat.exists else 'Requires hypervisor configuration' }}" - "" tags: [always] - name: Display action required message debug: msg: - "ACTION REQUIRED:" - " See /root/qemu-guest-agent-setup.txt for hypervisor configuration steps" when: not virtio_serial.stat.exists tags: [always] - name: Display operational status debug: msg: "Status: Fully operational" when: virtio_serial.stat.exists tags: [always]