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
--------
: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
-------
@ -47,6 +47,11 @@ Options
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
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')
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):
def test_100_list_with_status(self):
self.app.expected_calls[

View File

@ -494,6 +494,21 @@ class _HelpFormatsAction(argparse.Action):
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():
'''Create :py:class:`argparse.ArgumentParser` suitable for
:program:`qvm-ls`.
@ -531,6 +546,10 @@ def get_parser():
parser.add_argument('--tags', nargs='+', metavar='TAG',
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',
help='Display specify data of specified VMs. Intended for '
'bash-parsing.')
@ -614,6 +633,9 @@ def main(args=None, app=None):
domains = [dom for dom in domains
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.write_table(sys.stdout)