Libvirt is a popular API/tool for managing virtual machines (KVM/Qemu, LXC etc.) and stores its configuration in XML files.
Thanks to the tool relpipe-in-xmltable
we can get aggregated overview of our virtual machines.
These XML config files contain lot of information describing given virtual machine:
<?xml version="1.0" encoding="utf8"?>
<domain type="kvm">
<name>relpipe-1</name>
<uuid>36d1e8b2-97e9-40cb-9fc2-306ebf989282</uuid>
<memory unit="KiB">1048576</memory>
<currentMemory unit="KiB">1048576</currentMemory>
<vcpu placement="static">2</vcpu>
<os>
<type arch="x86_64" machine="pc-i440fx-bionic">hvm</type>
<boot dev="hd"/>
</os>
<features>
<acpi/>
<apic/>
<vmport state="off"/>
</features>
<cpu mode="custom" match="exact" check="partial">
<model fallback="allow">Opteron_G5</model>
</cpu>
<clock offset="utc">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="no"/>
</clock>
…
<devices>
<emulator>/usr/bin/kvm-spice</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/mnt/kvm-image/relpipe-1.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<target dev='hda' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
…
<interface type='bridge'>
<mac address='52:54:e9:f2:f6:bb'/>
<source bridge='br0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
…
</devices>
</domain>
If we are interested only in certain parts, we can pick them using a command like this one:
cat /etc/libvirt/qemu/relpipe-1.xml \
| relpipe-in-xmltable \
--relation "machine" \
--records "/domain" \
--attribute "uuid" string "uuid" \
--attribute "name" string "name" \
--attribute "memory_size" integer "memory" \
--attribute "memory_unit" string "memory/@unit" \
--attribute "cpu_count" integer "vcpu" \
--relation "storage" \
--records "/domain/devices/disk" \
--attribute "machine" string "/domain/uuid" \
--attribute "type" string "@device" \
--attribute "format" string "driver/@type" \
--attribute "source" string "source/@file" \
--attribute "target_dev" string "target/@dev" \
--attribute "target_type" string "target/@bus" \
--relation "network_interface" \
--records "/domain/devices/interface" \
--attribute "machine" string "/domain/uuid" \
--attribute "mac" string "mac/@address" \
| relpipe-out-tabular
And get three relations:
machine: ╭──────────────────────────────────────┬───────────────┬───────────────────────┬──────────────────────┬─────────────────────╮ │ uuid (string) │ name (string) │ memory_size (integer) │ memory_unit (string) │ cpu_count (integer) │ ├──────────────────────────────────────┼───────────────┼───────────────────────┼──────────────────────┼─────────────────────┤ │ 36d1e8b2-97e9-40cb-9fc2-306ebf989282 │ relpipe-1 │ 1048576 │ KiB │ 2 │ ╰──────────────────────────────────────┴───────────────┴───────────────────────┴──────────────────────┴─────────────────────╯ Record count: 1 storage: ╭──────────────────────────────────────┬───────────────┬─────────────────┬─────────────────────────────────┬─────────────────────┬──────────────────────╮ │ machine (string) │ type (string) │ format (string) │ source (string) │ target_dev (string) │ target_type (string) │ ├──────────────────────────────────────┼───────────────┼─────────────────┼─────────────────────────────────┼─────────────────────┼──────────────────────┤ │ 36d1e8b2-97e9-40cb-9fc2-306ebf989282 │ disk │ qcow2 │ /mnt/kvm-image/relpipe-1.qcow2 │ vda │ virtio │ │ 36d1e8b2-97e9-40cb-9fc2-306ebf989282 │ cdrom │ raw │ │ hda │ ide │ ╰──────────────────────────────────────┴───────────────┴─────────────────┴─────────────────────────────────┴─────────────────────┴──────────────────────╯ Record count: 2 network_interface: ╭──────────────────────────────────────┬───────────────────╮ │ machine (string) │ mac (string) │ ├──────────────────────────────────────┼───────────────────┤ │ 36d1e8b2-97e9-40cb-9fc2-306ebf989282 │ 52:54:e9:f2:f6:bb │ ╰──────────────────────────────────────┴───────────────────╯ Record count: 1
Each record contain ID of the machine, thus if we collect data from several VMs,
we can JOIN relevant records together, do some aggregations or statistics.
If we are sure that the name
field is unique, we can use it as a key instead of the UUID.
Relational pipes, open standard and free software © 2018-2022 GlobalCode