| 
									
										
										
										
											2025-08-26 23:55:54 +02:00
										 |  |  | #!/usr/bin/env python3 | 
					
						
							| 
									
										
										
										
											2016-07-07 17:25:35 +02:00
										 |  |  | # Check if all libvirt domains are prepared for TRIM/fstrim | 
					
						
							| 
									
										
										
										
											2016-12-29 14:21:38 +01:00
										 |  |  | # (for use on qcow2 images or thin provisioned volumes) | 
					
						
							| 
									
										
										
										
											2016-07-07 17:25:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | from __future__ import division, print_function | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 14:21:14 +01:00
										 |  |  | from distutils.version import LooseVersion | 
					
						
							| 
									
										
										
										
											2016-07-07 17:25:35 +02:00
										 |  |  | from lxml import objectify | 
					
						
							|  |  |  | import libvirt | 
					
						
							| 
									
										
										
										
											2016-12-29 14:21:14 +01:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2016-07-07 17:25:35 +02:00
										 |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 17:30:22 +02:00
										 |  |  | conn = libvirt.openReadOnly('qemu:///system') | 
					
						
							| 
									
										
										
										
											2016-07-07 17:25:35 +02:00
										 |  |  | if not conn: | 
					
						
							|  |  |  |     print('Failed to open connection to the hypervisor!') | 
					
						
							|  |  |  |     sys.exit(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-03 17:48:50 +02:00
										 |  |  | if not hasattr(conn, "listAllDomains"): | 
					
						
							|  |  |  |     print('connection does not have listAllDomains(), is python-libvirt too old?') | 
					
						
							|  |  |  |     sys.exit(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 17:25:35 +02:00
										 |  |  | for domain in conn.listAllDomains(): | 
					
						
							|  |  |  |     print('== {}'.format(domain.name())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     xml = domain.XMLDesc() | 
					
						
							|  |  |  |     tree = objectify.fromstring(xml) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 14:27:35 +01:00
										 |  |  |     # machine type version should be >= 2.1 if i440fx | 
					
						
							| 
									
										
										
										
											2016-07-17 17:20:14 +02:00
										 |  |  |     machine = tree.os.type.get('machine') | 
					
						
							| 
									
										
										
										
											2019-07-09 22:05:49 +02:00
										 |  |  |     matches = re.match('^pc-(?:i440fx-)?([0-9.]+)', machine) | 
					
						
							| 
									
										
										
										
											2016-12-29 14:21:14 +01:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2016-07-17 17:20:14 +02:00
										 |  |  |         # machines. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 14:27:35 +01:00
										 |  |  |     # no disks, no need to check | 
					
						
							| 
									
										
										
										
											2016-07-17 17:20:14 +02:00
										 |  |  |     if not hasattr(tree.devices, 'disk'): | 
					
						
							|  |  |  |         print('(has no disks)') | 
					
						
							|  |  |  |         continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 17:25:35 +02:00
										 |  |  |     # 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') |