Browse Source

admin: add admin.vm.Remove method

QubesOS/qubes-issues#2622
Marek Marczykowski-Górecki 7 years ago
parent
commit
f7cb8f27c5
2 changed files with 40 additions and 0 deletions
  1. 19 0
      qubes/api/admin.py
  2. 21 0
      qubes/tests/api_admin.py

+ 19 - 0
qubes/api/admin.py

@@ -712,6 +712,25 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
             raise
         self.app.save()
 
+    @qubes.api.method('admin.vm.Remove', no_payload=True)
+    @asyncio.coroutine
+    def vm_remove(self):
+        assert not self.arg
+
+        self.fire_event_for_permission()
+
+        if not self.dest.is_halted():
+            raise qubes.exc.QubesVMNotHaltedError(self.dest)
+
+        del self.app.domains[self.dest]
+        try:
+            yield from self.dest.remove_from_disk()
+        except:  # pylint: disable=bare-except
+            self.app.log.exception('Error wile removing VM \'%s\' files',
+                self.dest.name)
+
+        self.app.save()
+
     @qubes.api.method('admin.vm.Clone')
     @asyncio.coroutine
     def vm_clone(self, untrusted_payload):

+ 21 - 0
qubes/tests/api_admin.py

@@ -1550,6 +1550,27 @@ class TC_00_VMs(AdminAPITestCase):
         self.assertFalse(mock_detach.called)
         self.assertFalse(self.app.save.called)
 
+    @unittest.mock.patch('qubes.storage.Storage.remove')
+    @unittest.mock.patch('shutil.rmtree')
+    def test_500_vm_remove(self, mock_rmtree, mock_remove):
+        value = self.call_mgmt_func(b'admin.vm.Remove', b'test-vm1')
+        self.assertIsNone(value)
+        mock_rmtree.assert_called_once_with(
+            '/tmp/qubes-test-dir/appvms/test-vm1')
+        mock_remove.assert_called_once_with()
+        self.app.save.assert_called_once_with()
+
+    @unittest.mock.patch('qubes.storage.Storage.remove')
+    @unittest.mock.patch('shutil.rmtree')
+    def test_501_vm_remove_running(self, mock_rmtree, mock_remove):
+        with unittest.mock.patch.object(
+                self.vm, 'get_power_state', lambda: 'Running'):
+            with self.assertRaises(qubes.exc.QubesVMNotHaltedError):
+                self.call_mgmt_func(b'admin.vm.Remove', b'test-vm1')
+        self.assertFalse(mock_rmtree.called)
+        self.assertFalse(mock_remove.called)
+        self.assertFalse(self.app.save.called)
+
     def test_990_vm_unexpected_payload(self):
         methods_with_no_payload = [
             b'admin.vm.List',