Pause/Unpause all running VMs on system suspend/resume

This is to fix the VM lockup problem on HT processors that
occured after S3 resume (see ticket #52).

The qvm-run command now takes additional two switches:
--pause
--unpause
This commit is contained in:
Joanna Rutkowska 2010-07-08 12:41:29 +02:00
parent 19aa54aadb
commit c8ef500588
4 changed files with 71 additions and 16 deletions

23
dom0/pm-utils/02qubes-pause-vms Executable file
View File

@ -0,0 +1,23 @@
#!/bin/sh
. "${PM_FUNCTIONS}"
pause_vms()
{
echo
qvm-run --all --pause
}
unpause_vms()
{
echo
qvm-run --all --unpause
}
case "$1" in
thaw|resume) unpause_vms ;;
suspend|hibernate) pause_vms ;;
*) exit 0 ;;
esac

View File

@ -370,6 +370,12 @@ class QubesVm(object):
else: else:
return False return False
def is_paused(self):
if self.get_power_state() == "Paused":
return True
else:
return False
def get_disk_usage(self, file_or_dir): def get_disk_usage(self, file_or_dir):
if not os.path.exists(file_or_dir): if not os.path.exists(file_or_dir):
return 0 return 0

View File

@ -53,6 +53,18 @@ def vm_run_cmd(vm, cmd, options):
subprocess.call (["/usr/sbin/xm", "shutdown", vm.name]) subprocess.call (["/usr/sbin/xm", "shutdown", vm.name])
return return
if options.pause:
if options.verbose:
print "Pausing VM: '{0}'...".format(vm.name)
subprocess.call (["/usr/sbin/xm", "pause", vm.name])
return
if options.unpause:
if options.verbose:
print "UnPausing VM: '{0}'...".format(vm.name)
subprocess.call (["/usr/sbin/xm", "unpause", vm.name])
return
if options.verbose: if options.verbose:
print "Running command on VM: '{0}'...".format(vm.name) print "Running command on VM: '{0}'...".format(vm.name)
@ -124,7 +136,7 @@ def main():
help="Use tray notifications instead of stdout" ) help="Use tray notifications instead of stdout" )
parser.add_option ("--all", action="store_true", dest="run_on_all_running", default=False, parser.add_option ("--all", action="store_true", dest="run_on_all_running", default=False,
help="Run command on all currently running VMs") help="Run command on all currently running VMs (or all paused, in case of --unpause)")
parser.add_option ("--exclude", action="append", dest="exclude_list", parser.add_option ("--exclude", action="append", dest="exclude_list",
help="When --all is used: exclude this VM name (might be repeated)") help="When --all is used: exclude this VM name (might be repeated)")
@ -135,24 +147,36 @@ def main():
parser.add_option ("--shutdown", action="store_true", dest="shutdown", default=False, parser.add_option ("--shutdown", action="store_true", dest="shutdown", default=False,
help="Do 'xm shutdown' for the VM(s) (can be combined this with --all and --wait)") help="Do 'xm shutdown' for the VM(s) (can be combined this with --all and --wait)")
parser.add_option ("--pause", action="store_true", dest="pause", default=False,
help="Do 'xm pause' for the VM(s) (can be combined this with --all and --wait)")
parser.add_option ("--unpause", action="store_true", dest="unpause", default=False,
help="Do 'xm unpause' for the VM(s) (can be combined this with --all and --wait)")
(options, args) = parser.parse_args () (options, args) = parser.parse_args ()
if options.run_on_all_running: if (options.shutdown or options.pause or options.unpause):
if len(args) < 1 and not options.shutdown: takes_cmd_argument = False
parser.error ("You must provide a command to execute on all the VMs.")
if len(args) > 1 or (options.shutdown and len(args) > 0):
parser.error ("To many arguments...")
cmdstr = args[0] if not options.shutdown else None
else: else:
if len (args) < 1 and options.shutdown: takes_cmd_argument = True
parser.error ("You must specify the VM name to shutdown.")
if len (args) < 2 and not options.shutdown: if options.run_on_all_running:
if len(args) < 1 and takes_cmd_argument:
parser.error ("You must provide a command to execute on all the VMs.")
if len(args) > 1 or ((not takes_cmd_argument) and len(args) > 0):
parser.error ("To many arguments...")
cmdstr = args[0] if takes_cmd_argument else None
else:
if len (args) < 1 and not takes_cmd_argument:
parser.error ("You must specify the VM name to shutdown/pause/unpause.")
if len (args) < 2 and takes_cmd_argument:
parser.error ("You must specify the VM name and the command to execute in the VM.") parser.error ("You must specify the VM name and the command to execute in the VM.")
if len (args) > 2 or (options.shutdown and len(args) > 1): if len (args) > 2 or ((not takes_cmd_argument) and len(args) > 1):
parser.error ("To many arguments...") parser.error ("To many arguments...")
vmname = args[0] vmname = args[0]
cmdstr = args[1] if not options.shutdown else None cmdstr = args[1] if takes_cmd_argument else None
if options.tray: if options.tray:
global notify_object global notify_object
@ -171,7 +195,7 @@ def main():
continue continue
if vm.qid == 0: if vm.qid == 0:
continue continue
if vm.is_running(): if (options.unpause and vm.is_paused()) or (not options.unpause and vm.is_running()):
vms_list.append (vm) vms_list.append (vm)
else: else:
vm = qvm_collection.get_vm_by_name(vmname) vm = qvm_collection.get_vm_by_name(vmname)
@ -180,10 +204,10 @@ def main():
exit(1) exit(1)
vms_list.append(vm) vms_list.append(vm)
if options.shutdown: if takes_cmd_argument:
cmd = None
else:
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr) cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)
else:
cmd = None
for vm in vms_list: for vm in vms_list:
vm_run_cmd(vm, cmd, options) vm_run_cmd(vm, cmd, options)

View File

@ -97,6 +97,7 @@ cp init.d/iptables $RPM_BUILD_ROOT/etc/sysconfig
mkdir -p $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d mkdir -p $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d
cp pm-utils/01qubes-sync-vms-clock $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/ cp pm-utils/01qubes-sync-vms-clock $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/
cp pm-utils/02qubes-pause-vms $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/
%post %post
@ -200,3 +201,4 @@ fi
/etc/NetworkManager/dispatcher.d/qubes_nmhook /etc/NetworkManager/dispatcher.d/qubes_nmhook
/etc/sysconfig/iptables /etc/sysconfig/iptables
/usr/lib64/pm-utils/sleep.d/01qubes-sync-vms-clock /usr/lib64/pm-utils/sleep.d/01qubes-sync-vms-clock
/usr/lib64/pm-utils/sleep.d/02qubes-pause-vms