Merge remote-tracking branch 'origin/pr/277'

* origin/pr/277:
  admin: add admin.deviceclass.List
  admin: replace single quote to double for docstring
This commit is contained in:
Marek Marczykowski-Górecki 2019-08-08 14:05:00 +02:00
commit 5d5f102378
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
3 changed files with 39 additions and 22 deletions

View File

@ -8,6 +8,7 @@ OS ?= Linux
PYTHON ?= python3 PYTHON ?= python3
ADMIN_API_METHODS_SIMPLE = \ ADMIN_API_METHODS_SIMPLE = \
admin.deviceclass.List \
admin.vmclass.List \ admin.vmclass.List \
admin.Events \ admin.Events \
admin.backup.Execute \ admin.backup.Execute \

View File

@ -84,13 +84,13 @@ class QubesMgmtEventsDispatcher:
class QubesAdminAPI(qubes.api.AbstractQubesAPI): class QubesAdminAPI(qubes.api.AbstractQubesAPI):
'''Implementation of Qubes Management API calls """Implementation of Qubes Management API calls
This class contains all the methods available in the main API. This class contains all the methods available in the main API.
.. seealso:: .. seealso::
https://www.qubes-os.org/doc/mgmt1/ https://www.qubes-os.org/doc/mgmt1/
''' """
SOCKNAME = '/var/run/qubesd.sock' SOCKNAME = '/var/run/qubesd.sock'
@ -98,7 +98,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='global', read=True) scope='global', read=True)
@asyncio.coroutine @asyncio.coroutine
def vmclass_list(self): def vmclass_list(self):
'''List all VM classes''' """List all VM classes"""
self.enforce(not self.arg) self.enforce(not self.arg)
self.enforce(self.dest.name == 'dom0') self.enforce(self.dest.name == 'dom0')
@ -112,7 +112,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='global', read=True) scope='global', read=True)
@asyncio.coroutine @asyncio.coroutine
def vm_list(self): def vm_list(self):
'''List all the domains''' """List all the domains"""
self.enforce(not self.arg) self.enforce(not self.arg)
if self.dest.name == 'dom0': if self.dest.name == 'dom0':
@ -130,14 +130,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='local', read=True) scope='local', read=True)
@asyncio.coroutine @asyncio.coroutine
def vm_property_list(self): def vm_property_list(self):
'''List all properties on a qube''' """List all properties on a qube"""
return self._property_list(self.dest) return self._property_list(self.dest)
@qubes.api.method('admin.property.List', no_payload=True, @qubes.api.method('admin.property.List', no_payload=True,
scope='global', read=True) scope='global', read=True)
@asyncio.coroutine @asyncio.coroutine
def property_list(self): def property_list(self):
'''List all global properties''' """List all global properties"""
self.enforce(self.dest.name == 'dom0') self.enforce(self.dest.name == 'dom0')
return self._property_list(self.app) return self._property_list(self.app)
@ -152,14 +152,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='local', read=True) scope='local', read=True)
@asyncio.coroutine @asyncio.coroutine
def vm_property_get(self): def vm_property_get(self):
'''Get a value of one property''' """Get a value of one property"""
return self._property_get(self.dest) return self._property_get(self.dest)
@qubes.api.method('admin.property.Get', no_payload=True, @qubes.api.method('admin.property.Get', no_payload=True,
scope='global', read=True) scope='global', read=True)
@asyncio.coroutine @asyncio.coroutine
def property_get(self): def property_get(self):
'''Get a value of one global property''' """Get a value of one global property"""
self.enforce(self.dest.name == 'dom0') self.enforce(self.dest.name == 'dom0')
return self._property_get(self.app) return self._property_get(self.app)
@ -196,14 +196,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='local', read=True) scope='local', read=True)
@asyncio.coroutine @asyncio.coroutine
def vm_property_get_default(self): def vm_property_get_default(self):
'''Get a value of one property''' """Get a value of one property"""
return self._property_get_default(self.dest) return self._property_get_default(self.dest)
@qubes.api.method('admin.property.GetDefault', no_payload=True, @qubes.api.method('admin.property.GetDefault', no_payload=True,
scope='global', read=True) scope='global', read=True)
@asyncio.coroutine @asyncio.coroutine
def property_get_default(self): def property_get_default(self):
'''Get a value of one global property''' """Get a value of one global property"""
self.enforce(self.dest.name == 'dom0') self.enforce(self.dest.name == 'dom0')
return self._property_get_default(self.app) return self._property_get_default(self.app)
@ -239,7 +239,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='local', write=True) scope='local', write=True)
@asyncio.coroutine @asyncio.coroutine
def vm_property_set(self, untrusted_payload): def vm_property_set(self, untrusted_payload):
'''Set property value''' """Set property value"""
return self._property_set(self.dest, return self._property_set(self.dest,
untrusted_payload=untrusted_payload) untrusted_payload=untrusted_payload)
@ -247,7 +247,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='global', write=True) scope='global', write=True)
@asyncio.coroutine @asyncio.coroutine
def property_set(self, untrusted_payload): def property_set(self, untrusted_payload):
'''Set property value''' """Set property value"""
self.enforce(self.dest.name == 'dom0') self.enforce(self.dest.name == 'dom0')
return self._property_set(self.app, return self._property_set(self.app,
untrusted_payload=untrusted_payload) untrusted_payload=untrusted_payload)
@ -268,14 +268,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='local', read=True) scope='local', read=True)
@asyncio.coroutine @asyncio.coroutine
def vm_property_help(self): def vm_property_help(self):
'''Get help for one property''' """Get help for one property"""
return self._property_help(self.dest) return self._property_help(self.dest)
@qubes.api.method('admin.property.Help', no_payload=True, @qubes.api.method('admin.property.Help', no_payload=True,
scope='global', read=True) scope='global', read=True)
@asyncio.coroutine @asyncio.coroutine
def property_help(self): def property_help(self):
'''Get help for one property''' """Get help for one property"""
self.enforce(self.dest.name == 'dom0') self.enforce(self.dest.name == 'dom0')
return self._property_help(self.app) return self._property_help(self.app)
@ -296,14 +296,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='local', write=True) scope='local', write=True)
@asyncio.coroutine @asyncio.coroutine
def vm_property_reset(self): def vm_property_reset(self):
'''Reset a property to a default value''' """Reset a property to a default value"""
return self._property_reset(self.dest) return self._property_reset(self.dest)
@qubes.api.method('admin.property.Reset', no_payload=True, @qubes.api.method('admin.property.Reset', no_payload=True,
scope='global', write=True) scope='global', write=True)
@asyncio.coroutine @asyncio.coroutine
def property_reset(self): def property_reset(self):
'''Reset a property to a default value''' """Reset a property to a default value"""
self.enforce(self.dest.name == 'dom0') self.enforce(self.dest.name == 'dom0')
return self._property_reset(self.app) return self._property_reset(self.app)
@ -456,7 +456,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
scope='local', write=True) scope='local', write=True)
@asyncio.coroutine @asyncio.coroutine
def vm_volume_import(self): def vm_volume_import(self):
'''Import volume data. """Import volume data.
Note that this function only returns a path to where data should be Note that this function only returns a path to where data should be
written, actual importing is done by a script in /etc/qubes-rpc written, actual importing is done by a script in /etc/qubes-rpc
@ -464,7 +464,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
internal.vm.volume.ImportEnd (with either b'ok' or b'fail' as a internal.vm.volume.ImportEnd (with either b'ok' or b'fail' as a
payload) and response from that call will be actually send to the payload) and response from that call will be actually send to the
caller. caller.
''' """
self.enforce(self.arg in self.dest.volumes.keys()) self.enforce(self.arg in self.dest.volumes.keys())
self.fire_event_for_permission() self.fire_event_for_permission()
@ -1146,6 +1146,19 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
self.app.save() self.app.save()
@qubes.api.method('admin.deviceclass.List', no_payload=True,
scope='global', read=True)
@asyncio.coroutine
def deviceclass_list(self):
"""List all DEVICES classes"""
self.enforce(not self.arg)
self.enforce(self.dest.name == 'dom0')
entrypoints = self.fire_event_for_filter(
pkg_resources.iter_entry_points('qubes.devices'))
return ''.join('{}\n'.format(ep.name) for ep in entrypoints)
@qubes.api.method('admin.vm.device.{endpoint}.Available', endpoints=(ep.name @qubes.api.method('admin.vm.device.{endpoint}.Available', endpoints=(ep.name
for ep in pkg_resources.iter_entry_points('qubes.devices')), for ep in pkg_resources.iter_entry_points('qubes.devices')),
no_payload=True, no_payload=True,
@ -1356,13 +1369,13 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
@asyncio.coroutine @asyncio.coroutine
def _load_backup_profile(self, profile_name, skip_passphrase=False): def _load_backup_profile(self, profile_name, skip_passphrase=False):
'''Load backup profile and return :py:class:`qubes.backup.Backup` """Load backup profile and return :py:class:`qubes.backup.Backup`
instance instance
:param profile_name: name of the profile :param profile_name: name of the profile
:param skip_passphrase: do not load passphrase - only backup summary :param skip_passphrase: do not load passphrase - only backup summary
can be retrieved when this option is in use can be retrieved when this option is in use
''' """
profile_path = os.path.join( profile_path = os.path.join(
qubes.config.backup_profile_dir, profile_name + '.conf') qubes.config.backup_profile_dir, profile_name + '.conf')
@ -1523,7 +1536,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
def _send_stats_single(self, info_time, info, only_vm, filters, def _send_stats_single(self, info_time, info, only_vm, filters,
id_to_name_map): id_to_name_map):
'''A single iteration of sending VM stats """A single iteration of sending VM stats
:param info_time: time of previous iteration :param info_time: time of previous iteration
:param info: information retrieved in previous iteration :param info: information retrieved in previous iteration
@ -1532,7 +1545,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
:param id_to_name_map: ID->VM name map, may be modified :param id_to_name_map: ID->VM name map, may be modified
:return: tuple(info_time, info) - new information (to be passed to :return: tuple(info_time, info) - new information (to be passed to
the next iteration) the next iteration)
''' """
(info_time, info) = self.app.host.get_vm_stats(info_time, info, (info_time, info) = self.app.host.get_vm_stats(info_time, info,
only_vm=only_vm) only_vm=only_vm)

View File

@ -2632,6 +2632,7 @@ class TC_00_VMs(AdminAPITestCase):
def test_992_dom0_unexpected_payload(self): def test_992_dom0_unexpected_payload(self):
methods_with_no_payload = [ methods_with_no_payload = [
b'admin.deviceclass.List',
b'admin.vmclass.List', b'admin.vmclass.List',
b'admin.vm.List', b'admin.vm.List',
b'admin.label.List', b'admin.label.List',
@ -2673,6 +2674,7 @@ class TC_00_VMs(AdminAPITestCase):
def test_993_dom0_unexpected_argument(self): def test_993_dom0_unexpected_argument(self):
methods_with_no_argument = [ methods_with_no_argument = [
b'admin.deviceclass.List',
b'admin.vmclass.List', b'admin.vmclass.List',
b'admin.vm.List', b'admin.vm.List',
b'admin.label.List', b'admin.label.List',
@ -2708,6 +2710,7 @@ class TC_00_VMs(AdminAPITestCase):
# TODO set some better arguments, to make sure the call was rejected # TODO set some better arguments, to make sure the call was rejected
# because of invalid destination, not invalid arguments # because of invalid destination, not invalid arguments
methods_for_dom0_only = [ methods_for_dom0_only = [
b'admin.deviceclass.List',
b'admin.vmclass.List', b'admin.vmclass.List',
b'admin.vm.Create.AppVM', b'admin.vm.Create.AppVM',
b'admin.vm.CreateInPool.AppVM', b'admin.vm.CreateInPool.AppVM',