parent
							
								
									417cb6e912
								
							
						
					
					
						commit
						fb7bd6823a
					
				
							
								
								
									
										152
									
								
								qubes/mgmt.py
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								qubes/mgmt.py
									
									
									
									
									
								
							| @ -24,8 +24,10 @@ Qubes OS Management API | ||||
| 
 | ||||
| import asyncio | ||||
| import reprlib | ||||
| import string | ||||
| 
 | ||||
| import qubes.vm.qubesvm | ||||
| import qubes.storage | ||||
| 
 | ||||
| 
 | ||||
| class ProtocolRepr(reprlib.Repr): | ||||
| @ -194,3 +196,153 @@ class QubesMgmt(object): | ||||
|         self.fire_event_for_permission() | ||||
| 
 | ||||
|         delattr(self.dest, self.arg) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def vm_volume_list(self, untrusted_payload): | ||||
|         assert not self.arg | ||||
|         assert not untrusted_payload | ||||
|         del untrusted_payload | ||||
| 
 | ||||
|         volume_names = self.fire_event_for_filter(self.dest.volumes.keys()) | ||||
|         return ''.join('{}\n'.format(name) for name in volume_names) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def vm_volume_info(self, untrusted_payload): | ||||
|         assert self.arg in self.dest.volumes.keys() | ||||
|         assert not untrusted_payload | ||||
|         del untrusted_payload | ||||
| 
 | ||||
|         self.fire_event_for_permission() | ||||
| 
 | ||||
|         volume = self.dest.volumes[self.arg] | ||||
|         # properties defined in API | ||||
|         volume_properties = [ | ||||
|             'pool', 'vid', 'size', 'usage', 'rw', 'internal', 'source', | ||||
|             'save_on_stop', 'snap_on_start'] | ||||
|         return ''.join('{}={}\n'.format(key, getattr(volume, key)) for key in | ||||
|             volume_properties) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def vm_volume_listsnapshots(self, untrusted_payload): | ||||
|         assert self.arg in self.dest.volumes.keys() | ||||
|         assert not untrusted_payload | ||||
|         del untrusted_payload | ||||
| 
 | ||||
|         self.fire_event_for_permission() | ||||
| 
 | ||||
|         volume = self.dest.volumes[self.arg] | ||||
|         return ''.join('{}\n'.format(revision) for revision in volume.revisions) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def vm_volume_revert(self, untrusted_payload): | ||||
|         assert self.arg in self.dest.volumes.keys() | ||||
|         untrusted_revision = untrusted_payload.decode('ascii').strip() | ||||
|         del untrusted_payload | ||||
| 
 | ||||
|         volume = self.dest.volumes[self.arg] | ||||
|         snapshots = volume.revisions | ||||
|         assert untrusted_revision in snapshots | ||||
|         revision = untrusted_revision | ||||
| 
 | ||||
|         self.fire_event_for_permission(revision=revision) | ||||
| 
 | ||||
|         self.dest.storage.get_pool(volume).revert(revision) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def vm_volume_resize(self, untrusted_payload): | ||||
|         assert self.arg in self.dest.volumes.keys() | ||||
|         untrusted_size = untrusted_payload.decode('ascii').strip() | ||||
|         del untrusted_payload | ||||
|         assert untrusted_size.isdigit()  # only digits, forbid '-' too | ||||
|         assert len(untrusted_size) <= 20  # limit to about 2^64 | ||||
| 
 | ||||
|         size = int(untrusted_size) | ||||
| 
 | ||||
|         self.fire_event_for_permission(size=size) | ||||
| 
 | ||||
|         self.dest.storage.resize(self.arg, size) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def pool_list(self, untrusted_payload): | ||||
|         assert not self.arg | ||||
|         assert self.dest.name == 'dom0' | ||||
|         assert not untrusted_payload | ||||
|         del untrusted_payload | ||||
| 
 | ||||
|         pools = self.fire_event_for_filter(self.app.pools) | ||||
| 
 | ||||
|         return ''.join('{}\n'.format(pool) for pool in pools) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def pool_listdrivers(self, untrusted_payload): | ||||
|         assert self.dest.name == 'dom0' | ||||
|         assert not self.arg | ||||
|         assert not untrusted_payload | ||||
|         del untrusted_payload | ||||
| 
 | ||||
|         drivers = self.fire_event_for_filter(qubes.storage.pool_drivers()) | ||||
| 
 | ||||
|         return ''.join('{} {}\n'.format( | ||||
|             driver, | ||||
|             ' '.join(qubes.storage.driver_parameters(driver))) | ||||
|             for driver in drivers) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def pool_info(self, untrusted_payload): | ||||
|         assert self.dest.name == 'dom0' | ||||
|         assert self.arg in self.app.pools.keys() | ||||
|         assert not untrusted_payload | ||||
|         del untrusted_payload | ||||
| 
 | ||||
|         pool = self.app.pools[self.arg] | ||||
| 
 | ||||
|         self.fire_event_for_permission(pool=pool) | ||||
| 
 | ||||
|         return ''.join('{}={}\n'.format(prop, val) | ||||
|             for prop, val in sorted(pool.config.items())) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def pool_add(self, untrusted_payload): | ||||
|         assert self.dest.name == 'dom0' | ||||
|         drivers = qubes.storage.pool_drivers() | ||||
|         assert self.arg in drivers | ||||
|         untrusted_pool_config = untrusted_payload.decode('ascii').splitlines() | ||||
|         del untrusted_payload | ||||
|         assert all(('=' in line) for line in untrusted_pool_config) | ||||
|         # pairs of (option, value) | ||||
|         untrusted_pool_config = [line.split('=', 1) | ||||
|             for line in untrusted_pool_config] | ||||
|         # reject duplicated options | ||||
|         assert len(set(x[0] for x in untrusted_pool_config)) == \ | ||||
|                len([x[0] for x in untrusted_pool_config]) | ||||
|         # and convert to dict | ||||
|         untrusted_pool_config = dict(untrusted_pool_config) | ||||
| 
 | ||||
|         assert 'name' in untrusted_pool_config | ||||
|         untrusted_pool_name = untrusted_pool_config.pop('name') | ||||
|         allowed_chars = string.ascii_letters + string.digits + '-_.' | ||||
|         assert all(c in allowed_chars for c in untrusted_pool_name) | ||||
|         pool_name = untrusted_pool_name | ||||
|         assert pool_name not in self.app.pools | ||||
| 
 | ||||
|         driver_parameters = qubes.storage.driver_parameters(self.arg) | ||||
|         assert all(key in driver_parameters for key in untrusted_pool_config) | ||||
| 
 | ||||
|         # option names validated, validation of option values is delegated to | ||||
|         #  extension (through events mechanism) | ||||
|         self.fire_event_for_permission(name=pool_name, | ||||
|             untrusted_pool_config=untrusted_pool_config) | ||||
|         pool_config = untrusted_pool_config | ||||
| 
 | ||||
|         self.app.add_pool(name=pool_name, driver=self.arg, **pool_config) | ||||
| 
 | ||||
|     @asyncio.coroutine | ||||
|     def pool_remove(self, untrusted_payload): | ||||
|         assert self.dest.name == 'dom0' | ||||
|         assert self.arg in self.app.pools.keys() | ||||
|         assert not untrusted_payload | ||||
|         del untrusted_payload | ||||
| 
 | ||||
|         self.fire_event_for_permission() | ||||
| 
 | ||||
|         self.app.remove_pool(self.arg) | ||||
| @ -635,6 +635,15 @@ def pool_drivers(): | ||||
|             for ep in pkg_resources.iter_entry_points(STORAGE_ENTRY_POINT)] | ||||
| 
 | ||||
| 
 | ||||
| def driver_parameters(name): | ||||
|     ''' Get __init__ parameters from a driver with out `self` & `name`. ''' | ||||
|     init_function = qubes.utils.get_entry_point_one( | ||||
|         qubes.storage.STORAGE_ENTRY_POINT, name).__init__ | ||||
|     params = init_function.func_code.co_varnames | ||||
|     ignored_params = ['self', 'name'] | ||||
|     return [p for p in params if p not in ignored_params] | ||||
| 
 | ||||
| 
 | ||||
| def isodate(seconds=time.time()): | ||||
|     ''' Helper method which returns an iso date ''' | ||||
|     return datetime.utcfromtimestamp(seconds).isoformat("T") | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Marek Marczykowski-Górecki
						Marek Marczykowski-Górecki