Merge remote-tracking branch 'origin/pr/127'
* origin/pr/127: qvm-shutdown: report errors, don't crash on DispVMs
This commit is contained in:
commit
204c33afd1
@ -293,6 +293,7 @@ class TC_00_qvm_shutdown(qubesadmin.tests.QubesTestCase):
|
|||||||
self.app.expected_calls[
|
self.app.expected_calls[
|
||||||
('sys-net', 'admin.vm.CurrentState', None, None)] = \
|
('sys-net', 'admin.vm.CurrentState', None, None)] = \
|
||||||
b'0\x00power_state=Halted'
|
b'0\x00power_state=Halted'
|
||||||
qubesadmin.tools.qvm_shutdown.main(
|
with self.assertRaisesRegexp(SystemExit, '2'):
|
||||||
['--wait', '--all', '--timeout=1'], app=self.app)
|
qubesadmin.tools.qvm_shutdown.main(
|
||||||
|
['--wait', '--all', '--timeout=1'], app=self.app)
|
||||||
self.assertAllCalled()
|
self.assertAllCalled()
|
||||||
|
@ -408,12 +408,12 @@ class QubesArgumentParser(argparse.ArgumentParser):
|
|||||||
return namespace
|
return namespace
|
||||||
|
|
||||||
|
|
||||||
def error_runtime(self, message):
|
def error_runtime(self, message, exit_code=1):
|
||||||
'''Runtime error, without showing usage.
|
'''Runtime error, without showing usage.
|
||||||
|
|
||||||
:param str message: message to show
|
:param str message: message to show
|
||||||
'''
|
'''
|
||||||
self.exit(1, '{}: error: {}\n'.format(self.prog, message))
|
self.exit(exit_code, '{}: error: {}\n'.format(self.prog, message))
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -73,7 +73,12 @@ def main(args=None, app=None): # pylint: disable=missing-docstring
|
|||||||
else:
|
else:
|
||||||
remaining_domains.add(vm)
|
remaining_domains.add(vm)
|
||||||
if not args.wait:
|
if not args.wait:
|
||||||
return len(remaining_domains)
|
if remaining_domains:
|
||||||
|
parser.error_runtime(
|
||||||
|
'Failed to shut down: ' +
|
||||||
|
', '.join(vm.name for vm in remaining_domains),
|
||||||
|
len(remaining_domains))
|
||||||
|
return
|
||||||
this_round_domains.difference_update(remaining_domains)
|
this_round_domains.difference_update(remaining_domains)
|
||||||
if not this_round_domains:
|
if not this_round_domains:
|
||||||
# no VM shutdown request succeed, no sense to try again
|
# no VM shutdown request succeed, no sense to try again
|
||||||
@ -122,8 +127,20 @@ def main(args=None, app=None): # pylint: disable=missing-docstring
|
|||||||
if args.wait:
|
if args.wait:
|
||||||
if have_events:
|
if have_events:
|
||||||
loop.close()
|
loop.close()
|
||||||
return len([vm for vm in args.domains
|
failed = []
|
||||||
if vm.get_power_state() != 'Halted'])
|
for vm in args.domains:
|
||||||
|
power_state = vm.get_power_state()
|
||||||
|
# DispVM might have been deleted before we check them,
|
||||||
|
# so NA is acceptable.
|
||||||
|
if not (power_state == 'Halted' or
|
||||||
|
(vm.klass == 'DispVM' and power_state == 'NA')):
|
||||||
|
failed.append(vm)
|
||||||
|
if failed:
|
||||||
|
parser.error_runtime(
|
||||||
|
'Failed to shut down: ' +
|
||||||
|
', '.join(vm.name for vm in failed),
|
||||||
|
len(failed))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
Loading…
Reference in New Issue
Block a user