Browse Source

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

* origin/pr/277:
  admin: add admin.deviceclass.List
  admin: replace single quote to double for docstring
Marek Marczykowski-Górecki 4 years ago
parent
commit
5d5f102378
3 changed files with 39 additions and 22 deletions
  1. 1 0
      Makefile
  2. 35 22
      qubes/api/admin.py
  3. 3 0
      qubes/tests/api_admin.py

+ 1 - 0
Makefile

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

+ 35 - 22
qubes/api/admin.py

@@ -84,13 +84,13 @@ class QubesMgmtEventsDispatcher:
 
 
 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.
 
     .. seealso::
         https://www.qubes-os.org/doc/mgmt1/
-    '''
+    """
 
     SOCKNAME = '/var/run/qubesd.sock'
 
@@ -98,7 +98,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='global', read=True)
     @asyncio.coroutine
     def vmclass_list(self):
-        '''List all VM classes'''
+        """List all VM classes"""
         self.enforce(not self.arg)
         self.enforce(self.dest.name == 'dom0')
 
@@ -112,7 +112,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='global', read=True)
     @asyncio.coroutine
     def vm_list(self):
-        '''List all the domains'''
+        """List all the domains"""
         self.enforce(not self.arg)
 
         if self.dest.name == 'dom0':
@@ -130,14 +130,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='local', read=True)
     @asyncio.coroutine
     def vm_property_list(self):
-        '''List all properties on a qube'''
+        """List all properties on a qube"""
         return self._property_list(self.dest)
 
     @qubes.api.method('admin.property.List', no_payload=True,
         scope='global', read=True)
     @asyncio.coroutine
     def property_list(self):
-        '''List all global properties'''
+        """List all global properties"""
         self.enforce(self.dest.name == 'dom0')
         return self._property_list(self.app)
 
@@ -152,14 +152,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='local', read=True)
     @asyncio.coroutine
     def vm_property_get(self):
-        '''Get a value of one property'''
+        """Get a value of one property"""
         return self._property_get(self.dest)
 
     @qubes.api.method('admin.property.Get', no_payload=True,
         scope='global', read=True)
     @asyncio.coroutine
     def property_get(self):
-        '''Get a value of one global property'''
+        """Get a value of one global property"""
         self.enforce(self.dest.name == 'dom0')
         return self._property_get(self.app)
 
@@ -196,14 +196,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='local', read=True)
     @asyncio.coroutine
     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)
 
     @qubes.api.method('admin.property.GetDefault', no_payload=True,
         scope='global', read=True)
     @asyncio.coroutine
     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')
         return self._property_get_default(self.app)
 
@@ -239,7 +239,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='local', write=True)
     @asyncio.coroutine
     def vm_property_set(self, untrusted_payload):
-        '''Set property value'''
+        """Set property value"""
         return self._property_set(self.dest,
             untrusted_payload=untrusted_payload)
 
@@ -247,7 +247,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='global', write=True)
     @asyncio.coroutine
     def property_set(self, untrusted_payload):
-        '''Set property value'''
+        """Set property value"""
         self.enforce(self.dest.name == 'dom0')
         return self._property_set(self.app,
             untrusted_payload=untrusted_payload)
@@ -268,14 +268,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='local', read=True)
     @asyncio.coroutine
     def vm_property_help(self):
-        '''Get help for one property'''
+        """Get help for one property"""
         return self._property_help(self.dest)
 
     @qubes.api.method('admin.property.Help', no_payload=True,
         scope='global', read=True)
     @asyncio.coroutine
     def property_help(self):
-        '''Get help for one property'''
+        """Get help for one property"""
         self.enforce(self.dest.name == 'dom0')
         return self._property_help(self.app)
 
@@ -296,14 +296,14 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='local', write=True)
     @asyncio.coroutine
     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)
 
     @qubes.api.method('admin.property.Reset', no_payload=True,
         scope='global', write=True)
     @asyncio.coroutine
     def property_reset(self):
-        '''Reset a property to a default value'''
+        """Reset a property to a default value"""
         self.enforce(self.dest.name == 'dom0')
         return self._property_reset(self.app)
 
@@ -456,7 +456,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         scope='local', write=True)
     @asyncio.coroutine
     def vm_volume_import(self):
-        '''Import volume data.
+        """Import volume data.
 
         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
@@ -464,7 +464,7 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
         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
         caller.
-        '''
+        """
         self.enforce(self.arg in self.dest.volumes.keys())
 
         self.fire_event_for_permission()
@@ -1146,6 +1146,19 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
 
         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
             for ep in pkg_resources.iter_entry_points('qubes.devices')),
             no_payload=True,
@@ -1356,13 +1369,13 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
 
     @asyncio.coroutine
     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
 
         :param profile_name: name of the profile
         :param skip_passphrase: do not load passphrase - only backup summary
             can be retrieved when this option is in use
-        '''
+        """
         profile_path = os.path.join(
             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,
             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: 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
         :return: tuple(info_time, info) - new information (to be passed to
         the next iteration)
-        '''
+        """
 
         (info_time, info) = self.app.host.get_vm_stats(info_time, info,
             only_vm=only_vm)

+ 3 - 0
qubes/tests/api_admin.py

@@ -2632,6 +2632,7 @@ class TC_00_VMs(AdminAPITestCase):
 
     def test_992_dom0_unexpected_payload(self):
         methods_with_no_payload = [
+            b'admin.deviceclass.List',
             b'admin.vmclass.List',
             b'admin.vm.List',
             b'admin.label.List',
@@ -2673,6 +2674,7 @@ class TC_00_VMs(AdminAPITestCase):
 
     def test_993_dom0_unexpected_argument(self):
         methods_with_no_argument = [
+            b'admin.deviceclass.List',
             b'admin.vmclass.List',
             b'admin.vm.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
         # because of invalid destination, not invalid arguments
         methods_for_dom0_only = [
+            b'admin.deviceclass.List',
             b'admin.vmclass.List',
             b'admin.vm.Create.AppVM',
             b'admin.vm.CreateInPool.AppVM',