Proxmox Inventory Plugin: Struggling to Retrieve Full OS Info via Guest Agent

I’m trying to retrieve comprehensive OS information from my Proxmox VMs using the community.proxmox.proxmox inventory plugin. My primary issue is with the os-info data.

When I manually execute qm agent get-osinfo directly on a Proxmox VE host, I successfully get all the correct operating system details for VMs that have the qemu-guest-agent installed and running. However, when I use the Ansible Proxmox inventory plugin, I’ve only been able to extract the real IP addresses of the VMs from the guest agent, but not the detailed OS information (like name, version, architecture, etc.).

My goal is to get this full OS information through the Ansible Proxmox inventory plugin.

Relevant Software Versions:

  • Ansible: 2.18.6
  • Operating System (Ansible Control Node): Ubuntu 22.04
  • Ansible Collection: community.proxmox: 1.1.0
plugin: community.proxmox.proxmox
url: https://ip:8006
user: user@domain.test
password: password
validate_certs: false

# CRUCIAL: Enable extended facts to get guest agent information
want_facts: true
qemu_extended_statuses: true
want_proxmox_nodes_ansible_host: false

# Guest agent timeout configuration
timeout: 30

keyed_groups:
  # Group by Proxmox node where the VM/LXC resides
  - prefix: proxmox_node
    key: node
  
  # Group by VM/LXC status (running, stopped)
  - prefix: proxmox_status
    key: status
  
  # Group by resource type (qemu, lxc)
  - prefix: proxmox_type
    key: type
  
  # Group by tags assigned in Proxmox
  - prefix: proxmox_tag
    key: proxmox_tags_parsed
  
  # Group by OS type defined in Proxmox
  - prefix: proxmox_ostype
    key: ostype
  
  # CORRECTED: Group by OS name reported by the guest agent
  # Trying different possible data structures
  - prefix: os_name
    key: guest_agent_osinfo.name
  
  # NEW: Group by OS version
  - prefix: os_version
    key: guest_agent_osinfo.version
  
  # NEW: Group by OS architecture
  - prefix: os_arch
    key: guest_agent_osinfo.machine
  
  # NEW: Group by OS family (linux, windows)
  - prefix: os_family
    key: guest_agent_osinfo.id

# Variables we want to expose directly in the inventory for each host
compose:
  # PRIORITY 1: Try to use the first IP reported by the QEMU Guest Agent
  ansible_host: >-
    {% if guest_agent_ipaddresses is defined and guest_agent_ipaddresses | length > 0 %}
    {{ guest_agent_ipaddresses[0] }}
    {% elif guest_agent.ipaddresses is defined and guest_agent.ipaddresses | length > 0 %}
    {{ guest_agent.ipaddresses[0] }}
    {% elif proxmox_net0.ip is defined %}
    {{ proxmox_net0.ip }}
    {% else %}
    {{ inventory_hostname }}
    {% endif %}
  
  # Basic Proxmox variables
  proxmox_vmid: vmid
  proxmox_node: node
  proxmox_name: name
  proxmox_status: status
  proxmox_type: type
  proxmox_ostype: ostype
  
  # --- CORRECTED OS VARIABLES ---
  # Trying different possible data structures from the guest agent
  
  ansible_os_family: >-
    {% if guest_agent_osinfo.id is defined %}
    {{ guest_agent_osinfo.id }}
    {% elif guest_agent.osinfo.id is defined %}
    {{ guest_agent.osinfo.id }}
    {% else %}
    {{ ostype | default('unknown') }}
    {% endif %}
  
  ansible_distribution: >-
    {% if guest_agent_osinfo.name is defined %}
    {{ guest_agent_osinfo.name }}
    {% elif guest_agent.osinfo.name is defined %}
    {{ guest_agent.osinfo.name }}
    {% else %}
    {{ ostype | default('unknown') }}
    {% endif %}
  
  ansible_distribution_version: >-
    {% if guest_agent_osinfo.version is defined %}
    {{ guest_agent_osinfo.version }}
    {% elif guest_agent.osinfo.version is defined %}
    {{ guest_agent.osinfo.version }}
    {% else %}
    'unknown'
    {% endif %}
  
  ansible_distribution_release: >-
    {% if guest_agent_osinfo['pretty-name'] is defined %}
    {{ guest_agent_osinfo['pretty-name'] }}
    {% elif guest_agent.osinfo['pretty-name'] is defined %}
    {{ guest_agent.osinfo['pretty-name'] }}
    {% else %}
    'unknown'
    {% endif %}
  
  ansible_architecture: >-
    {% if guest_agent_osinfo.machine is defined %}
    {{ guest_agent_osinfo.machine }}
    {% elif guest_agent.osinfo.machine is defined %}
    {{ guest_agent.osinfo.machine }}
    {% elif guest_agent_osinfo.arch is defined %}
    {{ guest_agent_osinfo.arch }}
    {% elif guest_agent.osinfo.arch is defined %}
    {{ guest_agent.osinfo.arch }}
    {% else %}
    'unknown'
    {% endif %}
  
  # Specific OS variables for playbook use
  os_id: >-
    {% if guest_agent_osinfo.id is defined %}
    {{ guest_agent_osinfo.id }}
    {% elif guest_agent.osinfo.id is defined %}
    {{ guest_agent.osinfo.id }}
    {% else %}
    'unknown'
    {% endif %}
  
  os_name: >-
    {% if guest_agent_osinfo.name is defined %}
    {{ guest_agent_osinfo.name }}
    {% elif guest_agent.osinfo.name is defined %}
    {{ guest_agent.osinfo.name }}
    {% else %}
    'unknown'
    {% endif %}
  
  os_pretty_name: >-
    {% if guest_agent_osinfo['pretty-name'] is defined %}
    {{ guest_agent_osinfo['pretty-name'] }}
    {% elif guest_agent.osinfo['pretty-name'] is defined %}
    {{ guest_agent.osinfo['pretty-name'] }}
    {% else %}
    'unknown'
    {% endif %}
  
  os_version: >-
    {% if guest_agent_osinfo.version is defined %}
    {{ guest_agent_osinfo.version }}
    {% elif guest_agent.osinfo.version is defined %}
    {{ guest_agent.osinfo.version }}
    {% else %}
    'unknown'
    {% endif %}
  
  os_version_id: >-
    {% if guest_agent_osinfo['version-id'] is defined %}
    {{ guest_agent_osinfo['version-id'] }}
    {% elif guest_agent.osinfo['version-id'] is defined %}
    {{ guest_agent.osinfo['version-id'] }}
    {% else %}
    'unknown'
    {% endif %}
  
  os_kernel: >-
    {% if guest_agent_osinfo['kernel-release'] is defined %}
    {{ guest_agent_osinfo['kernel-release'] }}
    {% elif guest_agent.osinfo['kernel-release'] is defined %}
    {{ guest_agent.osinfo['kernel-release'] }}
    {% else %}
    'unknown'
    {% endif %}
  
  os_kernel_version: >-
    {% if guest_agent_osinfo['kernel-version'] is defined %}
    {{ guest_agent_osinfo['kernel-version'] }}
    {% elif guest_agent.osinfo['kernel-version'] is defined %}
    {{ guest_agent.osinfo['kernel-version'] }}
    {% else %}
    'unknown'
    {% endif %}
  
  os_arch: >-
    {% if guest_agent_osinfo.machine is defined %}
    {{ guest_agent_osinfo.machine }}
    {% elif guest_agent.osinfo.machine is defined %}
    {{ guest_agent.osinfo.machine }}
    {% else %}
    'unknown'
    {% endif %}
  
  # Guest agent status
  guest_agent_enabled: >-
    {% if guest_agent_ipaddresses is defined or guest_agent.ipaddresses is defined %}
    true
    {% else %}
    false
    {% endif %}
  
  # Guest agent network information
  guest_agent_ips: >-
    {% if guest_agent_ipaddresses is defined %}
    {{ guest_agent_ipaddresses }}
    {% elif guest_agent.ipaddresses is defined %}
    {{ guest_agent.ipaddresses }}
    {% else %}
    []
    {% endif %}
  
  # Useful additional information
  vm_uptime: uptime
  vm_cpu_usage: cpu
  vm_memory_usage: mem
  vm_disk_usage: disk

# Filters
filters:
  # Exclude VMs with the tag 'NoArrancar'
  - proxmox_tags_parsed is not defined or 'NoArrancar' not in proxmox_tags_parsed

Hi there,

I don’t think this is possible. The inventory plugin only communicates with the PVE API and I don’t think the PVE API has all of the information you need available. And the command you mention is not something that is done by the API itself, it only retrieves the IP information of the host.

Unless I’m mistaken, but it might help to browse around in the API output at https://pve:8006/api2/json and see if it does provide the information you seek somewhere. If it does, it should be possible to add it to the plugin.

Cheers!

1 Like

Hi,

Thank you very much for helping me. I’ve decided to clone the plugin’s repository and take a look at it. Indeed, it doesn’t retrieve that information. Regarding the QEMU Guest Agent, it only accesses the API section where the machine’s interfaces are shown. Since I needed to extract information about the operating system, I decided to modify the inventory plugin and was able to get that information through the API.

Best regards

1 Like