qvm-ls: add filtering by domain power state

This commit is contained in:
Patrik Hagara 2018-10-10 19:58:32 +02:00
parent 427f4587e5
commit 4cd513757b
No known key found for this signature in database
GPG Key ID: 5C1E71DF031F9AE5
3 changed files with 64 additions and 1 deletions

View File

@ -6,7 +6,7 @@
Synopsis Synopsis
-------- --------
:command:`qvm-ls` [-h] [--verbose] [--quiet] [--help-columns] [--help-formats] [--format *FORMAT* | --fields *FIELD*,...] [--tags *TAG* [*TAG* ...]] :command:`qvm-ls` [-h] [--verbose] [--quiet] [--help-columns] [--help-formats] [--format *FORMAT* | --fields *FIELD*,...] [--tags *TAG* [*TAG* ...]] [--running] [--paused] [--halted]
Options Options
------- -------
@ -47,6 +47,11 @@ Options
Shows only VMs having specific tag(s). Shows only VMs having specific tag(s).
.. option:: --running, --paused, --halted
Shows only VMs matching the specified power state(s). When none of these
options is used (default), all VMs are shown.
.. option:: --raw-data .. option:: --raw-data
Output data in easy to parse format. Table header is skipped and columns are Output data in easy to parse format. Table header is skipped and columns are

View File

@ -175,6 +175,42 @@ class TC_70_Tags(qubesadmin.tests.QubesTestCase):
'NAME STATE CLASS LABEL TEMPLATE NETVM\n') 'NAME STATE CLASS LABEL TEMPLATE NETVM\n')
class TC_80_Power_state_filters(qubesadmin.tests.QubesTestCase):
def setUp(self):
self.app = TestApp()
self.app.domains = TestVMCollection(
[
('a', TestVM('a', power_state='Halted')),
('b', TestVM('b', power_state='Transient')),
('c', TestVM('c', power_state='Running'))
]
)
def test_100_nofilter(self):
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
qubesadmin.tools.qvm_ls.main([], app=self.app)
self.assertEqual(stdout.getvalue(),
'NAME STATE CLASS LABEL TEMPLATE NETVM\n'
'a Halted TestVM - - -\n'
'b Transient TestVM - - -\n'
'c Running TestVM - - -\n')
def test_100_running(self):
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
qubesadmin.tools.qvm_ls.main(['--running'], app=self.app)
self.assertEqual(stdout.getvalue(),
'NAME STATE CLASS LABEL TEMPLATE NETVM\n'
'c Running TestVM - - -\n')
def test_100_running_or_halted(self):
with qubesadmin.tests.tools.StdoutBuffer() as stdout:
qubesadmin.tools.qvm_ls.main(['--running', '--halted'], app=self.app)
self.assertEqual(stdout.getvalue(),
'NAME STATE CLASS LABEL TEMPLATE NETVM\n'
'a Halted TestVM - - -\n'
'c Running TestVM - - -\n')
class TC_90_List_with_qubesd_calls(qubesadmin.tests.QubesTestCase): class TC_90_List_with_qubesd_calls(qubesadmin.tests.QubesTestCase):
def test_100_list_with_status(self): def test_100_list_with_status(self):
self.app.expected_calls[ self.app.expected_calls[

View File

@ -494,6 +494,21 @@ class _HelpFormatsAction(argparse.Action):
parser.exit(message=text) parser.exit(message=text)
# common VM power states for easy command-line filtering
DOMAIN_POWER_STATES = ['running', 'paused', 'halted']
def matches_power_states(domain, **states):
'''Filter domains by their power state'''
# if all values are False (default) => return match on every VM
if not states or set(states.values()) == {False}:
return True
# otherwise => only VMs matching True states
requested_states = [state for state, active in states.items() if active]
return domain.get_power_state().lower() in requested_states
def get_parser(): def get_parser():
'''Create :py:class:`argparse.ArgumentParser` suitable for '''Create :py:class:`argparse.ArgumentParser` suitable for
:program:`qvm-ls`. :program:`qvm-ls`.
@ -531,6 +546,10 @@ def get_parser():
parser.add_argument('--tags', nargs='+', metavar='TAG', parser.add_argument('--tags', nargs='+', metavar='TAG',
help='show only VMs having specific tag(s)') help='show only VMs having specific tag(s)')
for pwrstate in DOMAIN_POWER_STATES:
parser.add_argument('--{}'.format(pwrstate), action='store_true',
help='show {} VMs'.format(pwrstate))
parser.add_argument('--raw-data', action='store_true', parser.add_argument('--raw-data', action='store_true',
help='Display specify data of specified VMs. Intended for ' help='Display specify data of specified VMs. Intended for '
'bash-parsing.') 'bash-parsing.')
@ -614,6 +633,9 @@ def main(args=None, app=None):
domains = [dom for dom in domains domains = [dom for dom in domains
if set(dom.tags).intersection(set(args.tags))] if set(dom.tags).intersection(set(args.tags))]
pwrstates = {state: getattr(args, state) for state in DOMAIN_POWER_STATES}
domains = filter(lambda x: matches_power_states(x, **pwrstates), domains)
table = Table(domains, columns, spinner, args.raw_data) table = Table(domains, columns, spinner, args.raw_data)
table.write_table(sys.stdout) table.write_table(sys.stdout)