storage: add Pool.included_in() method for checking nested pools
It may happen that one pool is inside a volume of other pool. This is the case for example for varlibqubes pool (file driver, dir_path=/var/lib/qubes) and default lvm pool (lvm_thin driver). The latter include whole root filesystem, so /var/lib/qubes too. This is relevant for proper disk space calculation - to not count some space twice. QubesOS/qubes-issues#3240 QubesOS/qubes-issues#3241
This commit is contained in:
		
							parent
							
								
									99f430511a
								
							
						
					
					
						commit
						d40fae9756
					
				| @ -815,6 +815,17 @@ class Pool(object): | ||||
|         ''' | ||||
|         raise self._not_implemented("get_volume") | ||||
| 
 | ||||
|     def included_in(self, app): | ||||
|         ''' Check if this pool is physically included in another one | ||||
| 
 | ||||
|         This works on best-effort basis, because one pool driver may not know | ||||
|         all the other drivers. | ||||
| 
 | ||||
|         :param app: Qubes() object to lookup other pools in | ||||
|         :returns pool or None | ||||
|         ''' | ||||
|         pass | ||||
| 
 | ||||
|     @property | ||||
|     def size(self): | ||||
|         ''' Storage pool size in bytes ''' | ||||
| @ -865,6 +876,27 @@ def isodate(seconds=time.time()): | ||||
|     ''' Helper method which returns an iso date ''' | ||||
|     return datetime.utcfromtimestamp(seconds).isoformat("T") | ||||
| 
 | ||||
| def search_pool_containing_dir(pools, dir_path): | ||||
|     ''' Helper function looking for a pool containing given directory. | ||||
| 
 | ||||
|     This is useful for implementing Pool.included_in method | ||||
|     ''' | ||||
| 
 | ||||
|     # prefer filesystem pools | ||||
|     for pool in pools: | ||||
|         if hasattr(pool, 'dir_path'): | ||||
|             if dir_path.startswith(pool.dir_path): | ||||
|                 return pool | ||||
| 
 | ||||
|     # then look for lvm | ||||
|     for pool in pools: | ||||
|         if hasattr(pool, 'thin_pool') and hasattr(pool, 'volume_group'): | ||||
|             if (pool.volume_group, pool.thin_pool) == \ | ||||
|                     DirectoryThinPool.thin_pool(dir_path): | ||||
|                 return pool | ||||
| 
 | ||||
|     return None | ||||
| 
 | ||||
| 
 | ||||
| class VmCreationManager(object): | ||||
|     ''' A `ContextManager` which cleans up if volume creation fails. | ||||
|  | ||||
| @ -163,6 +163,12 @@ class FilePool(qubes.storage.Pool): | ||||
|         statvfs = os.statvfs(self.dir_path) | ||||
|         return statvfs.f_frsize * (statvfs.f_blocks - statvfs.f_bfree) | ||||
| 
 | ||||
|     def included_in(self, app): | ||||
|         ''' Check if there is pool containing this one - either as a | ||||
|         filesystem or its LVM volume''' | ||||
|         return qubes.storage.search_pool_containing_dir( | ||||
|             [pool for pool in app.pools.values() if pool is not self], | ||||
|             self.dir_path) | ||||
| 
 | ||||
| class FileVolume(qubes.storage.Volume): | ||||
|     ''' Parent class for the xen volumes implementation which expects a | ||||
|  | ||||
| @ -24,6 +24,7 @@ | ||||
| import os | ||||
| 
 | ||||
| import qubes.exc | ||||
| import qubes.storage | ||||
| from qubes.storage import Pool, StoragePoolException, Volume | ||||
| 
 | ||||
| 
 | ||||
| @ -202,6 +203,12 @@ class LinuxKernel(Pool): | ||||
|             raise qubes.exc.QubesValueError( | ||||
|                 'LinuxModules supports only revisions_to_keep=0') | ||||
| 
 | ||||
|     def included_in(self, app): | ||||
|         ''' Check if there is pool containing /var/lib/qubes/vm-kernels ''' | ||||
|         return qubes.storage.search_pool_containing_dir( | ||||
|             [pool for pool in app.pools.values() if pool is not self], | ||||
|             self.dir_path) | ||||
| 
 | ||||
|     @property | ||||
|     def volumes(self): | ||||
|         ''' Return all known kernel volumes ''' | ||||
|  | ||||
| @ -108,6 +108,12 @@ class ReflinkPool(qubes.storage.Pool): | ||||
|         statvfs = os.statvfs(self.dir_path) | ||||
|         return statvfs.f_frsize * (statvfs.f_blocks - statvfs.f_bfree) | ||||
| 
 | ||||
|     def included_in(self, app): | ||||
|         ''' Check if there is pool containing this one - either as a | ||||
|         filesystem or its LVM volume''' | ||||
|         return qubes.storage.search_pool_containing_dir( | ||||
|             [pool for pool in app.pools.values() if pool is not self], | ||||
|             self.dir_path) | ||||
| 
 | ||||
| class ReflinkVolume(qubes.storage.Volume): | ||||
|     def create(self): | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Marek Marczykowski-Górecki
						Marek Marczykowski-Górecki