Browse Source

Merge remote-tracking branch 'qubesos/pr/74'

* qubesos/pr/74:
  Added test for qvm-remove dependency reporting
  Better information on error in qvm-remove
Marek Marczykowski-Górecki 5 years ago
parent
commit
ed87be9303
3 changed files with 32 additions and 0 deletions
  1. 4 0
      qubesadmin/exc.py
  2. 18 0
      qubesadmin/tests/tools/qvm_remove.py
  3. 10 0
      qubesadmin/tools/qvm_remove.py

+ 4 - 0
qubesadmin/exc.py

@@ -85,6 +85,10 @@ class QubesNoTemplateError(QubesVMError):
     '''Cannot start domain, because there is no template'''
 
 
+class QubesVMInUseError(QubesVMError):
+    '''VM is in use, cannot remove.'''
+
+
 class QubesValueError(QubesException, ValueError):
     '''Cannot set some value, because it is invalid, out of bounds, etc.'''
     pass

+ 18 - 0
qubesadmin/tests/tools/qvm_remove.py

@@ -21,6 +21,7 @@
 import qubesadmin.tests
 import qubesadmin.tests.tools
 import qubesadmin.tools.qvm_remove
+import unittest.mock
 
 
 class TC_00_qvm_remove(qubesadmin.tests.QubesTestCase):
@@ -33,3 +34,20 @@ class TC_00_qvm_remove(qubesadmin.tests.QubesTestCase):
             b'0\x00\n'
         qubesadmin.tools.qvm_remove.main(['-f', 'some-vm'], app=self.app)
         self.assertAllCalled()
+
+    @unittest.mock.patch('qubesadmin.utils.vm_dependencies')
+    def test_100_dependencies(self, mock_dependencies):
+        self.app.expected_calls[
+            ('dom0', 'admin.vm.List', None, None)] = \
+            b'0\x00some-vm class=AppVM state=Running\n'
+        self.app.expected_calls[
+            ('some-vm', 'admin.vm.Remove', None, None)] = \
+            b'2\x00QubesVMInUseError\x00\x00An error occurred\x00'
+
+        mock_dependencies.return_value = \
+            [(None, 'default_template'), (self.app.domains['some-vm'], 'netvm')]
+
+        qubesadmin.tools.qvm_remove.main(['-f', 'some-vm'], app=self.app)
+
+        self.assertTrue(mock_dependencies.called,
+                        "Dependencies check not called.")

+ 10 - 0
qubesadmin/tools/qvm_remove.py

@@ -25,6 +25,7 @@ import sys
 
 import qubesadmin.exc
 from qubesadmin.tools import QubesArgumentParser
+import qubesadmin.utils
 
 parser = QubesArgumentParser(description=__doc__,
                              want_app=True,
@@ -47,6 +48,15 @@ def main(args=None, app=None):  # pylint: disable=missing-docstring
         for vm in args.domains:
             try:
                 del args.app.domains[vm.name]
+            except qubesadmin.exc.QubesVMInUseError:
+                dependencies = qubesadmin.utils.vm_dependencies(vm.app, vm)
+                print("VM {} cannot be removed. It is in use as:".format(
+                    vm.name))
+                for (holder, prop) in dependencies:
+                    if holder:
+                        print(" - {} for {}".format(prop, holder.name))
+                    else:
+                        print(" - global property {}".format(prop))
             except qubesadmin.exc.QubesException as e:
                 parser.error_runtime(e)
         retcode = 0