qvm-ls: add filtering by domain power state
This commit is contained in:
parent
427f4587e5
commit
4cd513757b
@ -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
|
||||||
|
@ -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[
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user