api/admin: implement *.property.GetAll methods
Allow getting all the VM properties with one call. This greatly improve performance of an applications retrieving many/all of them (qvm-ls, qubes manager etc) QubesOS/qubes-issues#5415 Fixes QubesOS/qubes-issues#3293
This commit is contained in:
parent
5d77cf2298
commit
10f99e5c4a
2
Makefile
2
Makefile
@ -35,6 +35,7 @@ ADMIN_API_METHODS_SIMPLE = \
|
|||||||
admin.pool.volume.Set.rw \
|
admin.pool.volume.Set.rw \
|
||||||
admin.pool.volume.Snapshot \
|
admin.pool.volume.Snapshot \
|
||||||
admin.property.Get \
|
admin.property.Get \
|
||||||
|
admin.property.GetAll \
|
||||||
admin.property.GetDefault \
|
admin.property.GetDefault \
|
||||||
admin.property.Help \
|
admin.property.Help \
|
||||||
admin.property.HelpRst \
|
admin.property.HelpRst \
|
||||||
@ -87,6 +88,7 @@ ADMIN_API_METHODS_SIMPLE = \
|
|||||||
admin.vm.firewall.SetPolicy \
|
admin.vm.firewall.SetPolicy \
|
||||||
admin.vm.firewall.Reload \
|
admin.vm.firewall.Reload \
|
||||||
admin.vm.property.Get \
|
admin.vm.property.Get \
|
||||||
|
admin.vm.property.GetAll \
|
||||||
admin.vm.property.GetDefault \
|
admin.vm.property.GetDefault \
|
||||||
admin.vm.property.Help \
|
admin.vm.property.Help \
|
||||||
admin.vm.property.HelpRst \
|
admin.vm.property.HelpRst \
|
||||||
|
@ -169,7 +169,11 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|||||||
|
|
||||||
self.fire_event_for_permission()
|
self.fire_event_for_permission()
|
||||||
|
|
||||||
property_def = dest.property_get_def(self.arg)
|
return self._serialize_property(dest, self.arg)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _serialize_property(dest, prop):
|
||||||
|
property_def = dest.property_get_def(prop)
|
||||||
# explicit list to be sure that it matches protocol spec
|
# explicit list to be sure that it matches protocol spec
|
||||||
if isinstance(property_def, qubes.vm.VMProperty):
|
if isinstance(property_def, qubes.vm.VMProperty):
|
||||||
property_type = 'vm'
|
property_type = 'vm'
|
||||||
@ -177,21 +181,51 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|||||||
property_type = 'int'
|
property_type = 'int'
|
||||||
elif property_def.type is bool:
|
elif property_def.type is bool:
|
||||||
property_type = 'bool'
|
property_type = 'bool'
|
||||||
elif self.arg == 'label':
|
elif prop == 'label':
|
||||||
property_type = 'label'
|
property_type = 'label'
|
||||||
else:
|
else:
|
||||||
property_type = 'str'
|
property_type = 'str'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = getattr(dest, self.arg)
|
value = getattr(dest, str(prop))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return 'default=True type={} '.format(property_type)
|
return 'default=True type={} '.format(property_type)
|
||||||
else:
|
else:
|
||||||
return 'default={} type={} {}'.format(
|
return 'default={} type={} {}'.format(
|
||||||
str(dest.property_is_default(self.arg)),
|
str(dest.property_is_default(prop)),
|
||||||
property_type,
|
property_type,
|
||||||
str(value) if value is not None else '')
|
str(value) if value is not None else '')
|
||||||
|
|
||||||
|
@qubes.api.method('admin.vm.property.GetAll', no_payload=True,
|
||||||
|
scope='local', read=True)
|
||||||
|
@asyncio.coroutine
|
||||||
|
def vm_property_get_all(self):
|
||||||
|
"""Get values of all VM properties"""
|
||||||
|
return self._property_get_all(self.dest)
|
||||||
|
|
||||||
|
@qubes.api.method('admin.property.GetAll', no_payload=True,
|
||||||
|
scope='global', read=True)
|
||||||
|
@asyncio.coroutine
|
||||||
|
def property_get_all(self):
|
||||||
|
"""Get value all global properties"""
|
||||||
|
self.enforce(self.dest.name == 'dom0')
|
||||||
|
return self._property_get_all(self.app)
|
||||||
|
|
||||||
|
def _property_get_all(self, dest):
|
||||||
|
self.enforce(not self.arg)
|
||||||
|
|
||||||
|
properties = dest.property_list()
|
||||||
|
|
||||||
|
properties = self.fire_event_for_filter(properties)
|
||||||
|
|
||||||
|
return ''.join(
|
||||||
|
'{} {}\n'.format(str(prop),
|
||||||
|
self._serialize_property(dest, prop).
|
||||||
|
replace('\\', '\\\\').replace('\n', '\\n'))
|
||||||
|
for prop in sorted(properties))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@qubes.api.method('admin.vm.property.GetDefault', no_payload=True,
|
@qubes.api.method('admin.vm.property.GetDefault', no_payload=True,
|
||||||
scope='local', read=True)
|
scope='local', read=True)
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
|
@ -180,6 +180,38 @@ class TC_00_VMs(AdminAPITestCase):
|
|||||||
b'provides_network')
|
b'provides_network')
|
||||||
self.assertEqual(value, 'type=bool False')
|
self.assertEqual(value, 'type=bool False')
|
||||||
|
|
||||||
|
def test_027_vm_property_get_all(self):
|
||||||
|
# any string property, test \n encoding
|
||||||
|
self.vm.kernelopts = 'opt1\nopt2\nopt3\\opt4'
|
||||||
|
with unittest.mock.patch.object(self.vm, 'property_list') as list_mock:
|
||||||
|
list_mock.return_value = [
|
||||||
|
self.vm.property_get_def('name'),
|
||||||
|
self.vm.property_get_def('default_user'),
|
||||||
|
self.vm.property_get_def('netvm'),
|
||||||
|
self.vm.property_get_def('klass'),
|
||||||
|
self.vm.property_get_def('debug'),
|
||||||
|
self.vm.property_get_def('label'),
|
||||||
|
self.vm.property_get_def('kernelopts'),
|
||||||
|
self.vm.property_get_def('qrexec_timeout'),
|
||||||
|
self.vm.property_get_def('qid'),
|
||||||
|
self.vm.property_get_def('updateable'),
|
||||||
|
]
|
||||||
|
value = self.call_mgmt_func(b'admin.vm.property.GetAll', b'test-vm1')
|
||||||
|
self.maxDiff = None
|
||||||
|
expected = '''debug default=True type=bool False
|
||||||
|
default_user default=True type=str user
|
||||||
|
klass default=True type=str AppVM
|
||||||
|
label default=False type=label red
|
||||||
|
name default=False type=str test-vm1
|
||||||
|
qid default=False type=int 2
|
||||||
|
qrexec_timeout default=True type=int 60
|
||||||
|
updateable default=True type=bool False
|
||||||
|
kernelopts default=False type=str opt1\\nopt2\\nopt3\\\\opt4
|
||||||
|
netvm default=True type=vm
|
||||||
|
'''
|
||||||
|
self.assertEqual(value, expected)
|
||||||
|
|
||||||
|
|
||||||
def test_030_vm_property_set_vm(self):
|
def test_030_vm_property_set_vm(self):
|
||||||
netvm = self.app.add_new_vm('AppVM', label='red', name='test-net',
|
netvm = self.app.add_new_vm('AppVM', label='red', name='test-net',
|
||||||
template='test-template', provides_network=True)
|
template='test-template', provides_network=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user