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