From ed11346977851712c1ab5187e06b60a93d4ad5b6 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Fri, 29 Dec 2017 14:17:30 -0500 Subject: [PATCH 1/9] Add --yes option and confirm prompt. --- qubesadmin/tools/qvm_remove.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/qubesadmin/tools/qvm_remove.py b/qubesadmin/tools/qvm_remove.py index b5a3ad0..0e9ddb0 100644 --- a/qubesadmin/tools/qvm_remove.py +++ b/qubesadmin/tools/qvm_remove.py @@ -28,14 +28,26 @@ from qubesadmin.tools import QubesArgumentParser parser = QubesArgumentParser(description=__doc__, want_app=True, vmname_nargs='+') +parser.add_argument("--yes", action="store_true", dest="no_confirm", + default=False, help="Do not prompt for confirmation") + def main(args=None, app=None): # pylint: disable=missing-docstring args = parser.parse_args(args, app=app) - for vm in args.domains: - del args.app.domains[vm.name] + go_ahead = "" + if not args.no_confirm: + print("This will completely remove the selected VM(s)...") + go_ahead = input("Are you sure? [y/N] ").upper() + + if args.no_confirm or go_ahead == "Y": + for vm in args.domains: + del args.app.domains[vm.name] + return 0 + else: + print("Remove cancelled.") + return 1 - return 0 if __name__ == '__main__': From ac7461d1e8560ebcdbe3bafb6b065d24dbf32a09 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 2 Jan 2018 00:42:47 -0500 Subject: [PATCH 2/9] Fix error message grammar --- qubesadmin/tools/qvm_template_postprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qubesadmin/tools/qvm_template_postprocess.py b/qubesadmin/tools/qvm_template_postprocess.py index f5e1642..54e5b6b 100644 --- a/qubesadmin/tools/qvm_template_postprocess.py +++ b/qubesadmin/tools/qvm_template_postprocess.py @@ -222,9 +222,9 @@ def pre_remove(args): try: tpl = app.domains[args.name] except KeyError: - parser.error('Qube with this name do not exist') + parser.error('No Qube with this name exists') for appvm in tpl.appvms: - parser.error('Qube {} use this template'.format(appvm.name)) + parser.error('Qube {} uses this template'.format(appvm.name)) del app.domains[args.name] return 0 From f7d27cdcdc9f2c69425542cab9c2667fe9b55acf Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 2 Jan 2018 01:19:06 -0500 Subject: [PATCH 3/9] Toggle installed_by_rpm in template tool --- qubesadmin/tools/qvm_template_postprocess.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qubesadmin/tools/qvm_template_postprocess.py b/qubesadmin/tools/qvm_template_postprocess.py index 54e5b6b..ccfce88 100644 --- a/qubesadmin/tools/qvm_template_postprocess.py +++ b/qubesadmin/tools/qvm_template_postprocess.py @@ -205,6 +205,7 @@ def post_install(args): # if data import fails, remove half-created VM del app.domains[vm.name] raise + vm.installed_by_rpm = True import_appmenus(vm, args.dir) if not args.skip_start: @@ -226,6 +227,7 @@ def pre_remove(args): for appvm in tpl.appvms: parser.error('Qube {} uses this template'.format(appvm.name)) + tpl.installed_by_rpm = False del app.domains[args.name] return 0 From 91928ae0c6d213c8761cddcac8c1854167c68823 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 2 Jan 2018 01:33:20 -0500 Subject: [PATCH 4/9] Use --force instead of --yes --- qubesadmin/tools/qvm_remove.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qubesadmin/tools/qvm_remove.py b/qubesadmin/tools/qvm_remove.py index 0e9ddb0..ac0c488 100644 --- a/qubesadmin/tools/qvm_remove.py +++ b/qubesadmin/tools/qvm_remove.py @@ -28,7 +28,7 @@ from qubesadmin.tools import QubesArgumentParser parser = QubesArgumentParser(description=__doc__, want_app=True, vmname_nargs='+') -parser.add_argument("--yes", action="store_true", dest="no_confirm", +parser.add_argument("--force", "-f", action="store_true", dest="no_confirm", default=False, help="Do not prompt for confirmation") From 8b03c9cc9cc2eb1de508ada88653353d513c87e0 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Tue, 2 Jan 2018 01:51:01 -0500 Subject: [PATCH 5/9] Print vm list before prompt --- qubesadmin/tools/qvm_remove.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qubesadmin/tools/qvm_remove.py b/qubesadmin/tools/qvm_remove.py index ac0c488..0df0b93 100644 --- a/qubesadmin/tools/qvm_remove.py +++ b/qubesadmin/tools/qvm_remove.py @@ -38,6 +38,8 @@ def main(args=None, app=None): # pylint: disable=missing-docstring go_ahead = "" if not args.no_confirm: print("This will completely remove the selected VM(s)...") + for vm in args.domains: + print(" ", vm.name) go_ahead = input("Are you sure? [y/N] ").upper() if args.no_confirm or go_ahead == "Y": From 7a9b0c232c12db96828496fb7376985c72179489 Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Wed, 3 Jan 2018 05:07:57 -0500 Subject: [PATCH 6/9] Avoid cloning installed_by_rpm --- qubesadmin/app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qubesadmin/app.py b/qubesadmin/app.py index 52d54a5..52c01ac 100644 --- a/qubesadmin/app.py +++ b/qubesadmin/app.py @@ -334,7 +334,8 @@ class QubesBase(qubesadmin.base.PropertyHolder): assert isinstance(dst_vm, qubesadmin.vm.QubesVM) for prop in src_vm.property_list(): # handled by admin.vm.Create call - if prop in ('name', 'qid', 'template', 'label', 'uuid'): + if prop in ('name', 'qid', 'template', 'label', 'uuid', \ + 'installed_by_rpm'): continue if src_vm.property_is_default(prop): continue From 7a948c7f19fb92914678a18f0cbad22e9591a75a Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Fri, 5 Jan 2018 18:05:17 -0500 Subject: [PATCH 7/9] Add --force to manpage. --- doc/manpages/qvm-remove.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/manpages/qvm-remove.rst b/doc/manpages/qvm-remove.rst index 945a1c3..ae3b662 100644 --- a/doc/manpages/qvm-remove.rst +++ b/doc/manpages/qvm-remove.rst @@ -14,7 +14,7 @@ Synopsis -------- -:command:`qvm-remove` [-h] [--verbose] [--quiet] [--force-root] [--all] [--exclude *EXCLUDE*] [--just-db] [*VMNAME* [*VMNAME* ...]] +:command:`qvm-remove` [-h] [--verbose] [--quiet] [--force] [--force-root] [--all] [--exclude *EXCLUDE*] [--just-db] [*VMNAME* [*VMNAME* ...]] Options ------- @@ -28,6 +28,10 @@ Options Exclude the qube from :option:`--all`. +.. option:: --force, -f + + Do not prompt for confirmation; assume 'yes'. + .. option:: --help, -h Show this help message and exit From 75a433f07a81e8811e2a58059ed48cb27ac28be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 6 Jan 2018 03:40:51 +0100 Subject: [PATCH 8/9] tests: update qvm-template-process and qvm-remove tests --- qubesadmin/tests/tools/qvm_remove.py | 2 +- qubesadmin/tests/tools/qvm_template_postprocess.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/qubesadmin/tests/tools/qvm_remove.py b/qubesadmin/tests/tools/qvm_remove.py index 5a6b58d..38995b3 100644 --- a/qubesadmin/tests/tools/qvm_remove.py +++ b/qubesadmin/tests/tools/qvm_remove.py @@ -31,5 +31,5 @@ class TC_00_qvm_remove(qubesadmin.tests.QubesTestCase): self.app.expected_calls[ ('some-vm', 'admin.vm.Remove', None, None)] = \ b'0\x00\n' - qubesadmin.tools.qvm_remove.main(['some-vm'], app=self.app) + qubesadmin.tools.qvm_remove.main(['-f', 'some-vm'], app=self.app) self.assertAllCalled() diff --git a/qubesadmin/tests/tools/qvm_template_postprocess.py b/qubesadmin/tests/tools/qvm_template_postprocess.py index e2d74c9..585f637 100644 --- a/qubesadmin/tests/tools/qvm_template_postprocess.py +++ b/qubesadmin/tests/tools/qvm_template_postprocess.py @@ -240,6 +240,9 @@ class TC_00_qvm_template_postprocess(qubesadmin.tests.QubesTestCase): self.app.expected_calls[ ('test-vm', 'admin.vm.property.Set', 'netvm', b'')] = b'0\0' + self.app.expected_calls[ + ('test-vm', 'admin.vm.property.Set', 'installed_by_rpm', b'True')] \ + = b'0\0' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Reset', 'netvm', None)] = b'0\0' self.app.expected_calls[ @@ -290,6 +293,9 @@ class TC_00_qvm_template_postprocess(qubesadmin.tests.QubesTestCase): self.app.expected_calls[ ('test-vm', 'admin.vm.property.Set', 'netvm', b'')] = b'0\0' + self.app.expected_calls[ + ('test-vm', 'admin.vm.property.Set', 'installed_by_rpm', b'True')] \ + = b'0\0' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Reset', 'netvm', None)] = b'0\0' self.app.expected_calls[ @@ -335,6 +341,9 @@ class TC_00_qvm_template_postprocess(qubesadmin.tests.QubesTestCase): mock_import_appmenus): self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \ b'0\0test-vm class=TemplateVM state=Halted\n' + self.app.expected_calls[ + ('test-vm', 'admin.vm.property.Set', 'installed_by_rpm', b'True')] \ + = b'0\0' self.app.add_new_vm = mock.Mock() if qubesadmin.tools.qvm_template_postprocess.have_events: @@ -365,6 +374,9 @@ class TC_00_qvm_template_postprocess(qubesadmin.tests.QubesTestCase): b'0\0test-vm class=TemplateVM state=Halted\n' self.app.expected_calls[('test-vm', 'admin.vm.Remove', None, None)] = \ b'0\0' + self.app.expected_calls[ + ('test-vm', 'admin.vm.property.Set', 'installed_by_rpm', b'False')]\ + = b'0\0' self.app.expected_calls[ ('test-vm', 'admin.vm.property.Get', 'template', None)] = \ b'2\0QubesNoSuchPropertyError\0\0invalid property \'template\' of ' \ From acd5f2e524274467987bd8db6c9335301e157b3d Mon Sep 17 00:00:00 2001 From: Christopher Laprise Date: Fri, 5 Jan 2018 23:13:24 -0500 Subject: [PATCH 9/9] Fix style else-return --- qubesadmin/tools/qvm_remove.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qubesadmin/tools/qvm_remove.py b/qubesadmin/tools/qvm_remove.py index 0df0b93..cd99e52 100644 --- a/qubesadmin/tools/qvm_remove.py +++ b/qubesadmin/tools/qvm_remove.py @@ -45,10 +45,11 @@ def main(args=None, app=None): # pylint: disable=missing-docstring if args.no_confirm or go_ahead == "Y": for vm in args.domains: del args.app.domains[vm.name] - return 0 + retcode = 0 else: print("Remove cancelled.") - return 1 + retcode = 1 + return retcode