From 8959e5a77e6f37b1e067f31a65d4922b7c28263e Mon Sep 17 00:00:00 2001 From: Bahtiar `kalkin-` Gadimov Date: Tue, 26 Apr 2016 16:54:36 +0200 Subject: [PATCH] Implement qvm-remove - Remove old qvm-remove - Remove a log line from Storage, because it prints confusing lines, like: Removing volume kernel: /var/lib/qubes/vm-kernels/4.1.13-6/modules.img --- doc/manpages/qvm-remove.rst | 18 ++++--- qubes/storage/__init__.py | 3 -- qubes/storage/file.py | 6 +-- qubes/tools/qvm_remove.py | 52 ++++++++++++++++++ qubes/vm/qubesvm.py | 2 +- qvm-tools/qvm-remove | 103 ------------------------------------ rpm_spec/core-dom0.spec | 1 + 7 files changed, 68 insertions(+), 117 deletions(-) create mode 100644 qubes/tools/qvm_remove.py delete mode 100755 qvm-tools/qvm-remove diff --git a/doc/manpages/qvm-remove.rst b/doc/manpages/qvm-remove.rst index 84647032..56389d0e 100644 --- a/doc/manpages/qvm-remove.rst +++ b/doc/manpages/qvm-remove.rst @@ -1,15 +1,15 @@ .. program:: qvm-remove -==================================== -:program:`qvm-remove` -- Remove a VM -==================================== +:program:`qvm-remove` -- remove domain +====================================== Synopsis -======== -:command:`qvm-remove` [*options*] <*vm-name*> +-------- +:command:`qvm-remove` [-h] [--verbose] [--quiet] [--force-root] [--just-db] *VMNAME* [*VMNAME* ...] + Options -======= +------- .. option:: --help, -h @@ -28,7 +28,11 @@ Options Force to run, even with root privileges Authors -======= +------- + | Joanna Rutkowska | Rafal Wojtczuk | Marek Marczykowski +| Bahtiar `kalkin-` Gadimov + +.. vim: ts=3 sw=3 et tw=80 diff --git a/qubes/storage/__init__.py b/qubes/storage/__init__.py index 0c528a5f..ae914d29 100644 --- a/qubes/storage/__init__.py +++ b/qubes/storage/__init__.py @@ -29,7 +29,6 @@ from __future__ import absolute_import import os import os.path -import shutil import pkg_resources import qubes @@ -192,9 +191,7 @@ class Storage(object): def remove(self): for name, volume in self.vm.volumes.items(): - self.log.info('Removing volume %s: %s' % (name, volume.vid)) self.get_pool(volume).remove(volume) - shutil.rmtree(self.vm.dir_path) def start(self): ''' Execute the start method on each pool ''' diff --git a/qubes/storage/file.py b/qubes/storage/file.py index 2891cd87..a405e475 100644 --- a/qubes/storage/file.py +++ b/qubes/storage/file.py @@ -109,10 +109,10 @@ class FilePool(Pool): def remove(self, volume): if volume.volume_type in ['read-write', 'volatile']: - _remove_if_exists(volume.vid) + _remove_if_exists(volume) elif volume.volume_type == 'origin': - _remove_if_exists(volume.vid) - _remove_if_exists(volume.path_cow) + _remove_if_exists(volume) + _remove_if_exists(volume) def rename(self, volume, old_name, new_name): assert issubclass(volume.__class__, FileVolume) diff --git a/qubes/tools/qvm_remove.py b/qubes/tools/qvm_remove.py new file mode 100644 index 00000000..b20bcbaf --- /dev/null +++ b/qubes/tools/qvm_remove.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python2 +# -*- encoding: utf8 -*- +# +# The Qubes OS Project, http://www.qubes-os.org +# +# Copyright (C) 2016 Bahtiar `kalkin-` Gadimov +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +''' Remove domains from the system ''' + +from __future__ import print_function + +import sys + +from qubes.tools import QubesArgumentParser + +parser = QubesArgumentParser(description=__doc__, + want_app=True, + want_force_root=True, + vmname_nargs='+') +parser.add_argument('--just-db', + action='store_true', + help='Remove only from db, don\'t remove files') + + +def main(args=None): # pylint: disable=missing-docstring + args = parser.parse_args(args) + for vm in args.domains: + del args.app.domains[vm.qid] + args.app.save() + if not args.just_db: + vm.remove_from_disk() + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 6b5135ec..fd0f83f1 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1137,7 +1137,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): '''Remove domain remnants from disk.''' self.fire_event('domain-remove-from-disk') self.storage.remove() - shutil.rmtree(self.vm.dir_path) + shutil.rmtree(self.dir_path) def clone_disk_files(self, src): '''Clone files from other vm. diff --git a/qvm-tools/qvm-remove b/qvm-tools/qvm-remove deleted file mode 100755 index ccb10212..00000000 --- a/qvm-tools/qvm-remove +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/python2 -# -*- encoding: utf8 -*- -# -# The Qubes OS Project, http://www.qubes-os.org -# -# Copyright (C) 2010 Joanna Rutkowska -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# - -from qubes.qubes import QubesVmCollection -from optparse import OptionParser; -import os -import sys - -def main(): - usage = "usage: %prog [options] " - parser = OptionParser (usage) - parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True) - parser.add_option ("--just-db", action="store_true", dest="remove_from_db_only", default=False, - help="Remove only from the Qubes Xen DB, do not remove any files") - parser.add_option ("--force-root", action="store_true", dest="force_root", default=False, - help="Force to run, even with root privileges") - (options, args) = parser.parse_args () - if (len (args) != 1): - parser.error ("You must specify VM name!") - vmname = args[0] - - qvm_collection = QubesVmCollection() - qvm_collection.lock_db_for_writing() - qvm_collection.load() - vm = qvm_collection.get_vm_by_name(vmname) - if vm is None or vm.qid not in qvm_collection: - print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname) - exit(1) - - if hasattr(os, "geteuid") and os.geteuid() == 0 and not options.force_root: - print >> sys.stderr, "*** Running this tool as root is strongly discouraged, this will lead you in permissions problems." - print >> sys.stderr, "Retry as unprivileged user." - print >> sys.stderr, "... or use --force-root to continue anyway." - exit(1) - - if vm.is_template(): - dependent_vms = qvm_collection.get_vms_based_on(vm.qid) - if len(dependent_vms) > 0: - print >> sys.stderr, "The following AppVMs use '{0}' as a template:".format(vmname) - for vm in dependent_vms: - print >> sys.stderr, "{name:<12} (qid={qid})".format(qid=vm.qid, name=vm.name) - print >> sys.stderr, "Please remove those VMs first." - exit (1) - if qvm_collection.default_template_qid == vm.qid: - qvm_collection.default_template_qid = None - - if vm.is_netvm(): - if qvm_collection.default_netvm_qid == vm.qid: - qvm_collection.default_netvm_qid = None - - - if vm.is_running(): - print >> sys.stderr, "Cannot remove a running VM, stop it first" - exit (1) - - if vm.installed_by_rpm and not options.remove_from_db_only: - if options.verbose: - print >> sys.stderr, "This VM has been installed by RPM, use yum remove to remove it!" - exit (1) - - try: - if vm.installed_by_rpm: - if options.verbose: - print >> sys.stderr, "--> VM installed by RPM, leaving all the files on disk" - elif not options.remove_from_db_only: - if options.verbose: - print "--> Removing all the files on disk..." - #TODO: ask for confirmation, perhaps? - vm.remove_from_disk() - - - - except (IOError, OSError) as err: - print >> sys.stderr, "Warning: {0}".format(err) - # Do not exit, perhaps the VM files were somehow removed - # so just remove it from Qubes DB - - - qvm_collection.pop(vm.qid) - qvm_collection.save() - qvm_collection.unlock_db() - -main() diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index 9bedef4a..47b5301f 100644 --- a/rpm_spec/core-dom0.spec +++ b/rpm_spec/core-dom0.spec @@ -248,6 +248,7 @@ fi %{python_sitelib}/qubes/tools/qvm_ls.py* %{python_sitelib}/qubes/tools/qvm_pause.py* %{python_sitelib}/qubes/tools/qvm_prefs.py* +%{python_sitelib}/qubes/tools/qvm_remove.py* %{python_sitelib}/qubes/tools/qvm_run.py* %{python_sitelib}/qubes/tools/qvm_shutdown.py* %{python_sitelib}/qubes/tools/qvm_start.py*