diff --git a/qubes/api/admin.py b/qubes/api/admin.py index 8a7da0ea..13435a45 100644 --- a/qubes/api/admin.py +++ b/qubes/api/admin.py @@ -869,9 +869,9 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI): scope='local', execute=True) @asyncio.coroutine def vm_shutdown(self): - self.enforce(not self.arg) - self.fire_event_for_permission() - yield from self.dest.shutdown() + force = (self.arg == 'force') + self.fire_event_for_permission(force=force) + yield from self.dest.shutdown(force=force) @qubes.api.method('admin.vm.Pause', no_payload=True, scope='local', execute=True) diff --git a/qubes/tests/api_admin.py b/qubes/tests/api_admin.py index a756da23..7364df1f 100644 --- a/qubes/tests/api_admin.py +++ b/qubes/tests/api_admin.py @@ -1010,7 +1010,18 @@ netvm default=True type=vm \n''' self.vm.shutdown = coroutine_mock value = self.call_mgmt_func(b'admin.vm.Shutdown', b'test-vm1') self.assertIsNone(value) - func_mock.assert_called_once_with() + func_mock.assert_called_once_with(force=False) + + def test_231_shutdown_force(self): + func_mock = unittest.mock.Mock() + + @asyncio.coroutine + def coroutine_mock(*args, **kwargs): + return func_mock(*args, **kwargs) + self.vm.shutdown = coroutine_mock + value = self.call_mgmt_func(b'admin.vm.Shutdown', b'test-vm1', b'force') + self.assertIsNone(value) + func_mock.assert_called_once_with(force=True) def test_240_pause(self): func_mock = unittest.mock.Mock() @@ -2772,7 +2783,6 @@ netvm default=True type=vm \n''' b'admin.vm.firewall.Reload', b'admin.vm.volume.List', b'admin.vm.Start', - b'admin.vm.Shutdown', b'admin.vm.Pause', b'admin.vm.Unpause', b'admin.vm.Kill',