core-admin/qvm-tools/qvm-shutdown
M. Vefa Bicakci e499e6e88c
qvm-shutdown: Allow multiple VMs to be shut down with one invocation
Prior to this commit, qvm-shutdown had a limitation where only one
VM name could be passed in via the command line for shutting down.

This commit removes the aforementioned limitation by adapting the
code for multiple command line arguments.

Signed-off-by: M. Vefa Bicakci <m.v.b@runbox.com>
2017-03-16 12:10:58 +01:00

125 lines
4.9 KiB
Python
Executable File

#!/usr/bin/python2
# -*- encoding: utf8 -*-
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2011 Marek Marczykowski <marmarek@invisiblethingslab.com>
#
# 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,QubesException
from qubes.qubes import defaults
from optparse import OptionParser;
import sys
import time
def main():
usage = "usage: %prog [options] <vm-name> [vm-name ...]"
parser = OptionParser (usage)
parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True)
parser.add_option ("--force", action="store_true", dest="force", default=False,
help="Force operation, even if may damage other VMs (eg shutdown of NetVM)")
parser.add_option ("--wait", action="store_true", dest="wait_for_shutdown", default=False,
help="Wait for the VM(s) to shutdown")
parser.add_option("--wait-time", action="store", dest="wait_time",
default=defaults["shutdown_counter_max"],
help="Timout after which VM will be killed when --wait "
"is used")
parser.add_option ("--all", action="store_true", dest="shutdown_all", default=False,
help="Shutdown all running VMs")
parser.add_option ("--exclude", action="append", dest="exclude_list",
help="When --all is used: exclude this VM name (may be "
"repeated)")
(options, args) = parser.parse_args ()
if not options.shutdown_all and not args:
parser.error ("You must specify VM name!")
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vms_list = []
if options.shutdown_all:
all_vms = [vm for vm in qvm_collection.values()]
for vm in all_vms:
if options.exclude_list is not None and vm.name in options.exclude_list:
continue
if vm.qid == 0:
continue
if vm.is_running():
vms_list.append (vm)
else:
for vmname in args:
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None:
print >> sys.stderr, "A VM with the name '{0}' does not exist in the system!".format(vmname)
exit(1)
vms_list.append(vm)
# Check VMs network dependencies
if not options.force:
for vm in vms_list:
if vm.is_netvm():
for connected_vm in vm.connected_vms.values():
if connected_vm.is_running() and not connected_vm in vms_list:
print >> sys.stderr, "ERROR: There are other VMs connected to VM '%s'" % vm.name
exit(1)
for vm in vms_list:
try:
if options.verbose:
print >> sys.stderr, "Shutting down VM: '{0}'...".format(vm.name)
# Dependencies already checked above
vm.shutdown(force=True)
except (IOError, OSError, QubesException) as err:
print >> sys.stderr, "ERROR: {0}".format(err)
exit (1)
if options.wait_for_shutdown:
if options.verbose:
print >> sys.stderr, "Waiting for the VM(s) to shutdown..."
shutdown_counter = 0
halting_vms = []
while len (vms_list):
if options.verbose:
print >> sys.stderr, "Waiting for VMs: ", [vm.name for vm in vms_list]
for vm in vms_list:
if not vm.is_running():
vms_list.remove (vm)
continue
if vm.get_power_state() == "Halting":
if vm in halting_vms:
vm.force_shutdown()
continue
else:
halting_vms.append(vm)
if shutdown_counter > int(options.wait_time):
# kill the VM
if options.verbose:
print >> sys.stderr, "Killing the (apparently hanging) VM '{0}'...".format(vm.name)
vm.force_shutdown()
#vms_list.remove(vm)
shutdown_counter += 1
time.sleep (1)
main()