#!/usr/bin/python3 # Check if all libvirt domains are prepared for TRIM/fstrim # (for use on qcow2 images or thin provisioned volumes) from __future__ import division, print_function from distutils.version import LooseVersion from lxml import objectify import libvirt import re import sys conn = libvirt.openReadOnly('qemu:///system') if not conn: print('Failed to open connection to the hypervisor!') sys.exit(1) if not hasattr(conn, "listAllDomains"): print('connection does not have listAllDomains(), is python-libvirt too old?') sys.exit(1) for domain in conn.listAllDomains(): print('== {}'.format(domain.name())) xml = domain.XMLDesc() tree = objectify.fromstring(xml) # machine type version should be >= 2.1 if i440fx machine = tree.os.type.get('machine') matches = re.match('^pc-(?:i440fx-)?([0-9.]+)', machine) if matches: i440_version = matches.group(1) if LooseVersion(i440_version) < LooseVersion('2.1'): print('machine type (version) should be at least pc-i440fx-2.1') # Might want to check "qemu-system-x86_64 -M help" for supported # machines. # no disks, no need to check if not hasattr(tree.devices, 'disk'): print('(has no disks)') continue # every disk should be scsi + discard=unmap for disk in tree.devices.disk: if disk.get('device') != 'disk': continue disk_desc = disk.target.get('dev') if disk.target.get('bus') != 'scsi': print('{} target should be scsi'.format(disk_desc)) if disk.driver.get('discard') != 'unmap': print('{} driver should have discard=unmap'.format(disk_desc)) # every scsi controller should be model='virtio-scsi' for controller in tree.devices.controller: if controller.get('type') != 'scsi': continue if controller.get('model') != 'virtio-scsi': print('scsi controller should be a virtio model')