diff --git a/Makefile b/Makefile index d871570e..df64f81e 100644 --- a/Makefile +++ b/Makefile @@ -109,6 +109,7 @@ ADMIN_API_METHODS_SIMPLE = \ admin.vm.volume.Set.revisions_to_keep \ admin.vm.volume.Set.rw \ admin.vm.Stats \ + admin.vm.CurrentState \ $(null) ifeq ($(OS),Linux) diff --git a/qubes/api/admin.py b/qubes/api/admin.py index 678cb98a..17a3ecd8 100644 --- a/qubes/api/admin.py +++ b/qubes/api/admin.py @@ -1677,3 +1677,18 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI): except asyncio.CancelledError: # valid method to terminate this loop pass + + @qubes.api.method('admin.vm.CurrentState', no_payload=True, + scope='local', read=True) + @asyncio.coroutine + def vm_current_state(self): + self.enforce(not self.arg) + self.fire_event_for_permission() + + state = { + 'mem': self.dest.get_mem(), + 'mem_static_max': self.dest.get_mem_static_max(), + 'cputime': self.dest.get_cputime(), + 'power_state': self.dest.get_power_state(), + } + return ' '.join('{}={}'.format(k, v) for k, v in state.items()) diff --git a/qubes/tests/api_admin.py b/qubes/tests/api_admin.py index a35a1b64..0cd6faa2 100644 --- a/qubes/tests/api_admin.py +++ b/qubes/tests/api_admin.py @@ -2614,6 +2614,20 @@ netvm default=True type=vm value = self.call_mgmt_func(b'admin.pool.volume.List', b'dom0', b'pool1') self.assertEqual(value, 'vol1\nvol2\n') + def test_800_current_state_default(self): + value = self.call_mgmt_func(b'admin.vm.CurrentState', b'test-vm1') + self.assertEqual( + value, 'mem=0 mem_static_max=0 cputime=0 power_state=Halted') + + def test_801_current_state_changed(self): + self.vm.get_mem = lambda: 512 + self.vm.get_mem_static_max = lambda: 1024 + self.vm.get_cputime = lambda: 100 + self.vm.get_power_state = lambda: 'Running' + value = self.call_mgmt_func(b'admin.vm.CurrentState', b'test-vm1') + self.assertEqual( + value, 'mem=512 mem_static_max=1024 cputime=100 power_state=Running') + def test_990_vm_unexpected_payload(self): methods_with_no_payload = [ b'admin.vm.List',