Enable caching in qvm-ls and qvm-prefs
Both tools issue a large number of Admin API calls and greatly benefit from a cache filled with a single per-vm Admin API call (admin.vm.property.GetAll). In case of qvm-ls, this also saves multiple admin.vm.CurrentState calls (power state is given in the admin.vm.List response too). QubesOS/qubes-issues#3293
This commit is contained in:
parent
79c7392424
commit
c081ed8c82
@ -29,11 +29,9 @@ class TC_00_qubes_prefs(qubesadmin.tests.QubesTestCase):
|
|||||||
('dom0', 'admin.property.List', None, None)] = \
|
('dom0', 'admin.property.List', None, None)] = \
|
||||||
b'0\x00prop1\nprop2\n'
|
b'0\x00prop1\nprop2\n'
|
||||||
self.app.expected_calls[
|
self.app.expected_calls[
|
||||||
('dom0', 'admin.property.Get', 'prop1', None)] = \
|
('dom0', 'admin.property.GetAll', None, None)] = \
|
||||||
b'0\x00default=True type=str value1'
|
b'0\x00prop1 default=True type=str value1\n' \
|
||||||
self.app.expected_calls[
|
b'prop2 default=False type=str value2\n'
|
||||||
('dom0', 'admin.property.Get', 'prop2', None)] = \
|
|
||||||
b'0\x00default=False type=str value2'
|
|
||||||
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
||||||
self.assertEqual(0, qubesadmin.tools.qubes_prefs.main([], app=self.app))
|
self.assertEqual(0, qubesadmin.tools.qubes_prefs.main([], app=self.app))
|
||||||
self.assertEqual(stdout.getvalue(),
|
self.assertEqual(stdout.getvalue(),
|
||||||
|
@ -278,42 +278,34 @@ class TC_90_List_with_qubesd_calls(qubesadmin.tests.QubesTestCase):
|
|||||||
b'0\x00vm1 class=AppVM state=Running\n' \
|
b'0\x00vm1 class=AppVM state=Running\n' \
|
||||||
b'template1 class=TemplateVM state=Halted\n' \
|
b'template1 class=TemplateVM state=Halted\n' \
|
||||||
b'sys-net class=AppVM state=Running\n'
|
b'sys-net class=AppVM state=Running\n'
|
||||||
self.app.expected_calls[
|
|
||||||
('vm1', 'admin.vm.CurrentState', None, None)] = \
|
|
||||||
b'0\x00power_state=Running'
|
|
||||||
self.app.expected_calls[
|
|
||||||
('sys-net', 'admin.vm.CurrentState', None, None)] = \
|
|
||||||
b'0\x00power_state=Running'
|
|
||||||
self.app.expected_calls[
|
|
||||||
('template1', 'admin.vm.CurrentState', None, None)] = \
|
|
||||||
b'0\x00power_state=Halted'
|
|
||||||
props = {
|
props = {
|
||||||
'label': b'type=label green',
|
'label': 'type=label green',
|
||||||
'template': b'type=vm template1',
|
'template': 'type=vm template1',
|
||||||
'netvm': b'type=vm sys-net',
|
'netvm': 'type=vm sys-net',
|
||||||
# 'virt_mode': b'type=str pv',
|
# 'virt_mode': b'type=str pv',
|
||||||
}
|
}
|
||||||
for key, value in props.items():
|
|
||||||
self.app.expected_calls[
|
self.app.expected_calls[
|
||||||
('vm1', 'admin.vm.property.Get', key, None)] = \
|
('vm1', 'admin.vm.property.GetAll', None, None)] = \
|
||||||
b'0\x00default=True ' + value
|
b'0\x00' + ''.join(
|
||||||
|
'{} default=True {}\n'.format(key, value)
|
||||||
# setup template1
|
for key, value in props.items()).encode()
|
||||||
props['label'] = b'type=label black'
|
|
||||||
for key, value in props.items():
|
|
||||||
self.app.expected_calls[
|
|
||||||
('template1', 'admin.vm.property.Get', key, None)] = \
|
|
||||||
b'0\x00default=True ' + value
|
|
||||||
self.app.expected_calls[
|
|
||||||
('template1', 'admin.vm.property.Get', 'template', None)] = \
|
|
||||||
b'' # request refused - no such property
|
|
||||||
|
|
||||||
# setup sys-net
|
# setup sys-net
|
||||||
props['label'] = b'type=label red'
|
props['label'] = 'type=label red'
|
||||||
for key, value in props.items():
|
|
||||||
self.app.expected_calls[
|
self.app.expected_calls[
|
||||||
('sys-net', 'admin.vm.property.Get', key, None)] = \
|
('sys-net', 'admin.vm.property.GetAll', None, None)] = \
|
||||||
b'0\x00default=True ' + value
|
b'0\x00' + ''.join(
|
||||||
|
'{} default=True {}\n'.format(key, value)
|
||||||
|
for key, value in props.items()).encode()
|
||||||
|
|
||||||
|
# setup template1
|
||||||
|
props['label'] = 'type=label black'
|
||||||
|
del props['template']
|
||||||
|
self.app.expected_calls[
|
||||||
|
('template1', 'admin.vm.property.GetAll', None, None)] = \
|
||||||
|
b'0\x00' + ''.join(
|
||||||
|
'{} default=True {}\n'.format(key, value)
|
||||||
|
for key, value in props.items()).encode()
|
||||||
|
|
||||||
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
||||||
qubesadmin.tools.qvm_ls.main([], app=self.app)
|
qubesadmin.tools.qvm_ls.main([], app=self.app)
|
||||||
@ -337,22 +329,24 @@ class TC_90_List_with_qubesd_calls(qubesadmin.tests.QubesTestCase):
|
|||||||
('sys-net', 'admin.vm.CurrentState', None, None)] = \
|
('sys-net', 'admin.vm.CurrentState', None, None)] = \
|
||||||
b'0\x00power_state=Running'
|
b'0\x00power_state=Running'
|
||||||
props = {
|
props = {
|
||||||
'label': b'type=label green',
|
'label': 'type=label green',
|
||||||
'template': b'type=vm template1',
|
'template': 'type=vm template1',
|
||||||
'netvm': b'type=vm sys-net',
|
'netvm': 'type=vm sys-net',
|
||||||
# 'virt_mode': b'type=str pv',
|
# 'virt_mode': b'type=str pv',
|
||||||
}
|
}
|
||||||
for key, value in props.items():
|
|
||||||
self.app.expected_calls[
|
self.app.expected_calls[
|
||||||
('vm1', 'admin.vm.property.Get', key, None)] = \
|
('vm1', 'admin.vm.property.GetAll', None, None)] = \
|
||||||
b'0\x00default=True ' + value
|
b'0\x00' + ''.join(
|
||||||
|
'{} default=True {}\n'.format(key, value)
|
||||||
|
for key, value in props.items()).encode()
|
||||||
|
|
||||||
# setup sys-net
|
# setup sys-net
|
||||||
props['label'] = b'type=label red'
|
props['label'] = 'type=label red'
|
||||||
for key, value in props.items():
|
|
||||||
self.app.expected_calls[
|
self.app.expected_calls[
|
||||||
('sys-net', 'admin.vm.property.Get', key, None)] = \
|
('sys-net', 'admin.vm.property.GetAll', None, None)] = \
|
||||||
b'0\x00default=True ' + value
|
b'0\x00' + ''.join(
|
||||||
|
'{} default=True {}\n'.format(key, value)
|
||||||
|
for key, value in props.items()).encode()
|
||||||
|
|
||||||
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
||||||
qubesadmin.tools.qvm_ls.main(['vm1', 'sys-net'], app=self.app)
|
qubesadmin.tools.qvm_ls.main(['vm1', 'sys-net'], app=self.app)
|
||||||
|
@ -33,11 +33,9 @@ class TC_00_qvm_prefs(qubesadmin.tests.QubesTestCase):
|
|||||||
('dom0', 'admin.vm.property.List', None, None)] = \
|
('dom0', 'admin.vm.property.List', None, None)] = \
|
||||||
b'0\x00prop1\nprop2\n'
|
b'0\x00prop1\nprop2\n'
|
||||||
self.app.expected_calls[
|
self.app.expected_calls[
|
||||||
('dom0', 'admin.vm.property.Get', 'prop1', None)] = \
|
('dom0', 'admin.vm.property.GetAll', None, None)] = \
|
||||||
b'0\x00default=True type=str value1'
|
b'0\x00prop1 default=True type=str value1\n' \
|
||||||
self.app.expected_calls[
|
b'prop2 default=False type=str value2\n'
|
||||||
('dom0', 'admin.vm.property.Get', 'prop2', None)] = \
|
|
||||||
b'0\x00default=False type=str value2'
|
|
||||||
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
||||||
self.assertEqual(0, qubesadmin.tools.qvm_prefs.main([
|
self.assertEqual(0, qubesadmin.tools.qvm_prefs.main([
|
||||||
'dom0'], app=self.app))
|
'dom0'], app=self.app))
|
||||||
@ -46,7 +44,7 @@ class TC_00_qvm_prefs(qubesadmin.tests.QubesTestCase):
|
|||||||
'prop2 - value2\n')
|
'prop2 - value2\n')
|
||||||
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
|
||||||
self.assertEqual(0, qubesadmin.tools.qvm_prefs.main([
|
self.assertEqual(0, qubesadmin.tools.qvm_prefs.main([
|
||||||
'dom0','--hide-default'], app=self.app))
|
'dom0', '--hide-default'], app=self.app))
|
||||||
self.assertEqual(stdout.getvalue(),
|
self.assertEqual(stdout.getvalue(),
|
||||||
'prop2 - value2\n')
|
'prop2 - value2\n')
|
||||||
self.assertAllCalled()
|
self.assertAllCalled()
|
||||||
|
@ -664,6 +664,10 @@ def main(args=None, app=None):
|
|||||||
parser.print_error(str(e))
|
parser.print_error(str(e))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
# fetch all the properties with one Admin API call, instead of issuing
|
||||||
|
# one call per property
|
||||||
|
args.app.cache_enabled = True
|
||||||
|
|
||||||
if args.raw_list:
|
if args.raw_list:
|
||||||
args.raw_data = True
|
args.raw_data = True
|
||||||
args.fields = 'name'
|
args.fields = 'name'
|
||||||
|
@ -93,6 +93,9 @@ def process_actions(parser, args, target):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
if args.property is None:
|
if args.property is None:
|
||||||
|
# fetch all the properties with one Admin API call, instead of issuing
|
||||||
|
# one call per property
|
||||||
|
args.app.cache_enabled = True
|
||||||
properties = target.property_list()
|
properties = target.property_list()
|
||||||
width = max(len(prop) for prop in properties)
|
width = max(len(prop) for prop in properties)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user