From 2bcbc1742ea68dae5b55d7e5cdb3b65a0befae4a Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Tue, 29 Mar 2011 12:20:50 +0200 Subject: [PATCH 1/7] Run pm-utils scripts in netvm on suspend (#146) --- dom0/pm-utils/01qubes-suspend-netvm | 28 +++++++++++++++++ dom0/pm-utils/01qubes-swap-pci-devs | 48 ----------------------------- 2 files changed, 28 insertions(+), 48 deletions(-) create mode 100755 dom0/pm-utils/01qubes-suspend-netvm delete mode 100755 dom0/pm-utils/01qubes-swap-pci-devs diff --git a/dom0/pm-utils/01qubes-suspend-netvm b/dom0/pm-utils/01qubes-suspend-netvm new file mode 100755 index 00000000..1491bb47 --- /dev/null +++ b/dom0/pm-utils/01qubes-suspend-netvm @@ -0,0 +1,28 @@ +#!/bin/sh + +. "${PM_FUNCTIONS}" + +suspend_net() +{ + NETVM=$(qvm-get-default-netvm) + if [ "X"$NETVM = "X""dom0" -o "X"$NETVM = "X" -o "X"$NETVM = "X""none"] ; then + exit 0 + fi + qvm-run -u root --pass_io $NETVM "source /usr/lib64/pm-utils/pm-functions; run_hooks sleep suspend suspend" +} + +resume_net() +{ + NETVM=$(qvm-get-default-netvm) + if [ "X"$NETVM = "X""dom0" -o "X"$NETVM = "X" -o "X"$NETVM = "X""none"] ; then + exit 0 + fi + qvm-run -u root --pass_io $NETVM "source /usr/lib64/pm-utils/pm-functions; run_hooks sleep resume suspend reverse" +} + + +case "$1" in + resume) resume_net ;; + suspend) suspend_net ;; + *) exit 0 ;; +esac diff --git a/dom0/pm-utils/01qubes-swap-pci-devs b/dom0/pm-utils/01qubes-swap-pci-devs deleted file mode 100755 index 2922c5b8..00000000 --- a/dom0/pm-utils/01qubes-swap-pci-devs +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -. "${PM_FUNCTIONS}" - -get_domain_pci_devs() -{ - VM=$1 - TMPFILE=$(mktemp -p /var/run/qubes/) - xm pci-list $VM > $TMPFILE - if grep -i -q vslt $TMPFILE ; then - slt=valid_identifier - else - slt="" - fi - cat $TMPFILE | grep -v domain | sed 's/0x//g'| \ - while read $slt a b c d; do echo $a:$b:$c.$d ; done > /var/run/qubes/$VM.pcidevs - rm -f $TMPFILE -} - -detach_pcis() -{ - NETVM=$(qvm-get-default-netvm) - if [ "X"$NETVM = "X""dom0" -o "X"$NETVM = "X" -o "X"$NETVM = "X""none"] ; then - exit 0 - fi - get_domain_pci_devs $NETVM - for dev in $(cat /var/run/qubes/$NETVM.pcidevs) ; do - xm pci-detach $NETVM $dev - done -} - -attach_pcis() -{ - NETVM=$(qvm-get-default-netvm) - if [ "X"$NETVM = "X""dom0" -o "X"$NETVM = "X" -o "X"$NETVM = "X""none"] ; then - exit 0 - fi - for dev in $(cat /var/run/qubes/$NETVM.pcidevs) ; do - xm pci-attach $NETVM $dev - done -} - - -case "$1" in - resume) attach_pcis ;; - suspend) detach_pcis ;; - *) exit 0 ;; -esac From 464337a24e1279b99dec2abfe6cd90d69ceeddcf Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Tue, 29 Mar 2011 12:22:31 +0200 Subject: [PATCH 2/7] Ignore exit status from netvm pm-scripts (#146) --- dom0/pm-utils/01qubes-suspend-netvm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dom0/pm-utils/01qubes-suspend-netvm b/dom0/pm-utils/01qubes-suspend-netvm index 1491bb47..a0e2f447 100755 --- a/dom0/pm-utils/01qubes-suspend-netvm +++ b/dom0/pm-utils/01qubes-suspend-netvm @@ -9,6 +9,8 @@ suspend_net() exit 0 fi qvm-run -u root --pass_io $NETVM "source /usr/lib64/pm-utils/pm-functions; run_hooks sleep suspend suspend" + # Ignore exit status from netvm... + return 0 } resume_net() @@ -18,6 +20,8 @@ resume_net() exit 0 fi qvm-run -u root --pass_io $NETVM "source /usr/lib64/pm-utils/pm-functions; run_hooks sleep resume suspend reverse" + # Ignore exit status from netvm... + return 0 } From c2e0a84c222be070449c6d679ed43d0f0f48759e Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Tue, 29 Mar 2011 12:39:01 +0200 Subject: [PATCH 3/7] Add 01qubes-suspend-netvm to rpm (#146) --- rpm_spec/core-dom0.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index fcb5be8c..0fc1ab47 100644 --- a/rpm_spec/core-dom0.spec +++ b/rpm_spec/core-dom0.spec @@ -126,7 +126,7 @@ cp ../common/iptables $RPM_BUILD_ROOT/etc/sysconfig 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-swap-pci-devs $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/ +cp pm-utils/01qubes-suspend-netvm $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/ cp pm-utils/02qubes-pause-vms $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/ mkdir -p $RPM_BUILD_ROOT/var/log/qubes @@ -306,7 +306,7 @@ fi /etc/NetworkManager/dispatcher.d/qubes_nmhook /etc/sysconfig/iptables /usr/lib64/pm-utils/sleep.d/01qubes-sync-vms-clock -/usr/lib64/pm-utils/sleep.d/01qubes-swap-pci-devs +/usr/lib64/pm-utils/sleep.d/01qubes-suspend-netvm /usr/lib64/pm-utils/sleep.d/02qubes-pause-vms /usr/bin/xenstore-watch /usr/lib/qubes/qubes_restore From 212fd13957fff8eac1d39dc610cbda4575e58826 Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Wed, 30 Mar 2011 22:29:57 +0200 Subject: [PATCH 4/7] Stop only NM on suspend. (#146) Also remove ip_forward setting from sysctl, so NM will not reset it on restart --- dom0/pm-utils/01qubes-suspend-netvm | 27 +++++++++++++++++---------- rpm_spec/core-netvm.spec | 3 +++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/dom0/pm-utils/01qubes-suspend-netvm b/dom0/pm-utils/01qubes-suspend-netvm index a0e2f447..cf635ae6 100755 --- a/dom0/pm-utils/01qubes-suspend-netvm +++ b/dom0/pm-utils/01qubes-suspend-netvm @@ -2,24 +2,31 @@ . "${PM_FUNCTIONS}" +get_running_netvms() { + # Actually get running VMs with PCI devices attached + RUNNING_VMS=`xm list --state=Running | tail -n +3 | cut -f 1 -d " "` + RUNNING_NETVMS="" + for VM in $RUNNING_VMS; do + if [ -n "`xm pci-list $VM`" ]; then + echo "$VM" + fi + done +} + suspend_net() { - NETVM=$(qvm-get-default-netvm) - if [ "X"$NETVM = "X""dom0" -o "X"$NETVM = "X" -o "X"$NETVM = "X""none"] ; then - exit 0 - fi - qvm-run -u root --pass_io $NETVM "source /usr/lib64/pm-utils/pm-functions; run_hooks sleep suspend suspend" + for VM in `get_running_netvms`; do + qvm-run -u root --pass_io $VM "service NetworkManager stop" + done # Ignore exit status from netvm... return 0 } resume_net() { - NETVM=$(qvm-get-default-netvm) - if [ "X"$NETVM = "X""dom0" -o "X"$NETVM = "X" -o "X"$NETVM = "X""none"] ; then - exit 0 - fi - qvm-run -u root --pass_io $NETVM "source /usr/lib64/pm-utils/pm-functions; run_hooks sleep resume suspend reverse" + for VM in `get_running_netvms`; do + qvm-run -u root --pass_io $VM "service NetworkManager start" + done # Ignore exit status from netvm... return 0 } diff --git a/rpm_spec/core-netvm.spec b/rpm_spec/core-netvm.spec index b4f1eb34..d09139b0 100644 --- a/rpm_spec/core-netvm.spec +++ b/rpm_spec/core-netvm.spec @@ -73,6 +73,9 @@ cp ../common/vif-route-qubes $RPM_BUILD_ROOT/etc/xen/scripts chkconfig --add qubes_core_netvm || echo "WARNING: Cannot add service qubes_core!" chkconfig qubes_core_netvm on || echo "WARNING: Cannot enable service qubes_core!" +# Remove ip_forward setting from sysctl, so NM will not reset it +sed 's/^net.ipv4.ip_forward.*/#\0/' -i /etc/sysctl.conf + %preun if [ "$1" = 0 ] ; then # no more packages left From 01ef2aff9ed26389e88f9c1a86a74c7c38bfd5ee Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Thu, 31 Mar 2011 00:44:58 +0200 Subject: [PATCH 5/7] Wait for device size change, before resize2fs (#5) --- dom0/qvm-tools/qvm-grow-private | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom0/qvm-tools/qvm-grow-private b/dom0/qvm-tools/qvm-grow-private index e14802b6..7ca50d2e 100755 --- a/dom0/qvm-tools/qvm-grow-private +++ b/dom0/qvm-tools/qvm-grow-private @@ -99,7 +99,7 @@ def main(): retcode = subprocess.check_call(["losetup", "--set-capacity", loop_dev]) retcode = subprocess.check_call([qvm_run_path, "-uroot", vmname, - "resize2fs /dev/xvdb" ]) + "while [ \"`blockdev --getsize64 /dev/xvdb`\" -lt {0} ]; do sleep 0.2; done; resize2fs /dev/xvdb".format(size_bytes) ]) else: retcode = subprocess.check_call(["resize2fs", "-f", vm.private_img]) From 6273c42faff0cd749dee49a6bbce5cea5eb5fcf4 Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Thu, 31 Mar 2011 01:58:45 +0200 Subject: [PATCH 6/7] Recursive stop VMs, when stopping NetVM (#172) Dependency resolving in qvm-core, recursive stopping only in qvm-run for now. --- dom0/init.d/qubes_netvm | 17 +++++++++++++++-- dom0/qvm-core/qubes.py | 19 +++++++++++++++++++ dom0/qvm-tools/qvm-run | 5 +++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/dom0/init.d/qubes_netvm b/dom0/init.d/qubes_netvm index bfc0f0c6..2d27fdd8 100755 --- a/dom0/init.d/qubes_netvm +++ b/dom0/init.d/qubes_netvm @@ -20,6 +20,17 @@ NETVM=$(qvm-get-default-netvm) +get_running_netvms() { + # Actually get running VMs with PCI devices attached + RUNNING_VMS=`xm list --state=Running | tail -n +3 | cut -f 1 -d " "` + RUNNING_NETVMS="" + for VM in $RUNNING_VMS; do + if [ -n "`xm pci-list $VM`" ]; then + echo "$VM" + fi + done +} + start() { if [ x$NETVM = x ] ; then @@ -59,8 +70,10 @@ stop() echo -n $"Stopping Qubes networking in Dom0:" else - echo -n $"Stopping default NetVM:" - qvm-run -q --shutdown --wait $NETVM + echo -n $"Stopping NetVMs:" + for VM in `get_running_netvms`; do + qvm-run -q --shutdown --wait $VM + done fi rm -f /var/lock/subsys/qubes_netvm diff --git a/dom0/qvm-core/qubes.py b/dom0/qvm-core/qubes.py index 11fc1870..8ce6897b 100755 --- a/dom0/qvm-core/qubes.py +++ b/dom0/qvm-core/qubes.py @@ -1773,6 +1773,25 @@ class QubesVmCollection(dict): if (vm.is_appvm() and vm.template_vm.qid == template_qid)]) return vms + def get_vms_connected_to(self, netvm_qid): + new_vms = [ netvm_qid ] + dependend_vms_qid = [] + + # Dependency resolving only makes sense on NetVM (or derivative) + if not self[netvm_qid].is_netvm(): + return set([]) + + while len(new_vms) > 0: + cur_vm = new_vms.pop() + for vm in self.values(): + if vm.netvm_vm and vm.netvm_vm.qid == cur_vm and vm.qid not in dependend_vms_qid: + dependend_vms_qid.append(vm.qid) + if vm.is_netvm(): + new_vms.append(vm.qid) + + vms = [vm for vm in self.values() if vm.qid in dependend_vms_qid] + return vms + def verify_new_vm(self, new_vm): # Verify that qid is unique diff --git a/dom0/qvm-tools/qvm-run b/dom0/qvm-tools/qvm-run index 3f801e2c..fe2ca357 100755 --- a/dom0/qvm-tools/qvm-run +++ b/dom0/qvm-tools/qvm-run @@ -219,6 +219,11 @@ def main(): print "A VM with the name '{0}' does not exist in the system!".format(vmname) exit(1) vms_list.append(vm) + + # If stopping NetVM - stop connected VMs too + if options.shutdown and vm.is_netvm(): + vms_list += [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()] + vms_list.reverse() if takes_cmd_argument: cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr) From ece8cfa9f0292197a6fb0c280439c24852665bd6 Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Thu, 31 Mar 2011 02:40:45 +0200 Subject: [PATCH 7/7] Show output from resize2fs, when running it in AppVM (#5) --- dom0/qvm-tools/qvm-grow-private | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom0/qvm-tools/qvm-grow-private b/dom0/qvm-tools/qvm-grow-private index 7ca50d2e..57c61060 100755 --- a/dom0/qvm-tools/qvm-grow-private +++ b/dom0/qvm-tools/qvm-grow-private @@ -98,7 +98,7 @@ def main(): # resize loop device retcode = subprocess.check_call(["losetup", "--set-capacity", loop_dev]) - retcode = subprocess.check_call([qvm_run_path, "-uroot", vmname, + retcode = subprocess.check_call([qvm_run_path, "-uroot", "--pass_io", vmname, "while [ \"`blockdev --getsize64 /dev/xvdb`\" -lt {0} ]; do sleep 0.2; done; resize2fs /dev/xvdb".format(size_bytes) ]) else: retcode = subprocess.check_call(["resize2fs", "-f", vm.private_img])