diff --git a/dom0/aux-tools/keep-dom0-clock-synced b/dom0/aux-tools/keep-dom0-clock-synced deleted file mode 100755 index b3c3d4e9..00000000 --- a/dom0/aux-tools/keep-dom0-clock-synced +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -# 15m -UPDATES_SLEEP=900 -UPDATES_VM=`qvm-get-updatevm` - -QREXEC_CLIENT=/usr/lib/qubes/qrexec_client - -if [ -z "$UPDATES_VM" ]; then - echo "UpdateVM not set, exiting!" >&2 - exit 1 -fi - -echo "Waiting for UpdateVM to be started" -# Intentionally used xl domid here to check if domain is running (in case of -# eg. stale qrexec socket) -while ! [ -S /var/run/qubes/qrexec.`xl domid "$UPDATES_VM" 2>/dev/null` ]; do - sleep 1 -done - -( -# Allow only one instance -flock --nonblock -s 200 || exit 1 -while true; do - qvm-sync-dom0-clock - - sleep $UPDATES_SLEEP -done - - -) 200> /var/run/qubes/clock-watch-lock diff --git a/dom0/aux-tools/qubes-sync-clock.cron b/dom0/aux-tools/qubes-sync-clock.cron new file mode 100755 index 00000000..95c9d33f --- /dev/null +++ b/dom0/aux-tools/qubes-sync-clock.cron @@ -0,0 +1 @@ +*/6 * * * * root /usr/bin/qvm-sync-clock > /dev/null 2>&1 || true diff --git a/dom0/init.d/qubes_core b/dom0/init.d/qubes_core index 08e61bb0..26ca4189 100755 --- a/dom0/init.d/qubes_core +++ b/dom0/init.d/qubes_core @@ -50,8 +50,6 @@ start() MEMINFO_DELAY_USEC=100000 /usr/lib/qubes/meminfo-writer $MEM_CHANGE_THRESHOLD_KB $MEMINFO_DELAY_USEC & - /usr/lib/qubes/keep-dom0-clock-synced > /var/log/qubes/dom0-clock-sync.log 2>&1 & - touch /var/lock/subsys/qubes_core success echo diff --git a/dom0/pm-utils/01qubes-suspend-netvm b/dom0/pm-utils/01qubes-suspend-netvm index 264c8faa..0d0f6fa7 100755 --- a/dom0/pm-utils/01qubes-suspend-netvm +++ b/dom0/pm-utils/01qubes-suspend-netvm @@ -16,7 +16,7 @@ get_running_netvms() { suspend_net() { for VM in `get_running_netvms`; do - qvm-run -u root --pass_io $VM 'service NetworkManager stop; for if in `ls /sys/class/net|grep -v "lo\|vif"`; do ip l s $if down; done; modprobe -r uhci_hcd ehci_hcd' + qvm-run -u root --pass-io $VM 'service NetworkManager stop; for if in `ls /sys/class/net|grep -v "lo\|vif"`; do ip l s $if down; done; modprobe -r uhci_hcd ehci_hcd' done # Ignore exit status from netvm... return 0 @@ -25,7 +25,7 @@ suspend_net() resume_net() { for VM in `get_running_netvms`; do - qvm-run -u root --pass_io $VM "modprobe ehci_hcd; modprobe uhci_hcd; [ -x /bin/systemctl ] && systemctl start NetworkManager.service || service qubes_core_netvm start" + qvm-run -u root --pass-io $VM "modprobe ehci_hcd; modprobe uhci_hcd; [ -x /bin/systemctl ] && systemctl start NetworkManager.service || service qubes_core_netvm start" done # Ignore exit status from netvm... return 0 diff --git a/dom0/pm-utils/01qubes-sync-vms-clock b/dom0/pm-utils/01qubes-sync-vms-clock index 0980aced..5d363387 100755 --- a/dom0/pm-utils/01qubes-sync-vms-clock +++ b/dom0/pm-utils/01qubes-sync-vms-clock @@ -4,11 +4,13 @@ sync_qubes_vms_wallclock() { -/usr/bin/qvm-sync-dom0-clock +# Sync all VMs based on dom0 clock DATE=$(date) echo echo "Syncing VMs clock to: $DATE" qvm-run --all --exclude=`qvm-get-clockvm` -u root "date -s \"$DATE\"" +# Then try to sync from the network +/usr/bin/qvm-sync-clock & } case "$1" in diff --git a/dom0/qvm-core/qubes.py b/dom0/qvm-core/qubes.py index 42b781f4..0eb6eb33 100755 --- a/dom0/qvm-core/qubes.py +++ b/dom0/qvm-core/qubes.py @@ -2546,9 +2546,9 @@ class QubesVmCollection(dict): self.clockvm_qid = clockvm.qid - # Enable ntpd in ClockVM + # Disable ntpd in ClockVM - to not conflict with ntpdate (both are using 123/udp port) if self.clockvm_qid is not None: - self[self.clockvm_qid].services['ntpd'] = True + self[self.clockvm_qid].services['ntpd'] = False return True def pop(self, qid): diff --git a/dom0/qvm-core/qubesutils.py b/dom0/qvm-core/qubesutils.py index a66fb81a..53299daa 100644 --- a/dom0/qvm-core/qubesutils.py +++ b/dom0/qvm-core/qubesutils.py @@ -229,7 +229,7 @@ def block_detach(vm, frontend = "xvdi", vm_xid = None): xl_cmd = [ '/usr/sbin/xl', 'block-detach', str(vm_xid), str(frontend)] subprocess.check_call(xl_cmd) -def run_in_vm(vm, command, verbose = True, autostart = False, notify_function = None, passio = False, localcmd = None): +def run_in_vm(vm, command, verbose = True, autostart = False, notify_function = None, passio = False, passio_popen = False, localcmd = None, wait = False): assert vm is not None if not vm.is_running(): @@ -258,7 +258,11 @@ def run_in_vm(vm, command, verbose = True, autostart = False, notify_function = if passio: os.execv(qrexec_client_path, args) exit(1) - args += ["-e"] + if passio_popen: + p = subprocess.Popen (args, stdout=subprocess.PIPE) + return p + if not wait: + args += ["-e"] return subprocess.call(args) # vim:sw=4:et: diff --git a/dom0/qvm-tools/qvm-dom0-update b/dom0/qvm-tools/qvm-dom0-update index e0da7500..c23d555b 100755 --- a/dom0/qvm-tools/qvm-dom0-update +++ b/dom0/qvm-tools/qvm-dom0-update @@ -66,7 +66,7 @@ fi # We should ensure the clocks in Dom0 and UpdateVM are in sync # becuase otherwise yum might complain about future timestamps -qvm-sync-dom0-clock +qvm-sync-clock echo "Checking for dom0 updates" >&2 @@ -75,7 +75,7 @@ qvm-run -a $UPDATEVM true || exit 1 /usr/lib/qubes/qrexec_client -d "$UPDATEVM" -l 'tar c /var/lib/rpm /etc/yum.repos.d /etc/yum.conf 2>/dev/null' 'user:tar x -C /var/lib/qubes/dom0-updates' -qvm-run --pass_io $UPDATEVM "/usr/lib/qubes/qubes_download_dom0_updates.sh --doit --nogui $ALL_OPTS" +qvm-run --pass-io $UPDATEVM "/usr/lib/qubes/qubes_download_dom0_updates.sh --doit --nogui $ALL_OPTS" RETCODE=$? if [ "$CHECK_ONLY" == "1" ]; then exit $RETCODE diff --git a/dom0/qvm-tools/qvm-grow-private b/dom0/qvm-tools/qvm-grow-private index cb6fff44..ffa114ae 100755 --- a/dom0/qvm-tools/qvm-grow-private +++ b/dom0/qvm-tools/qvm-grow-private @@ -99,7 +99,7 @@ def main(): # resize loop device retcode = subprocess.check_call(["losetup", "--set-capacity", loop_dev]) - retcode = subprocess.check_call([qvm_run_path, "-uroot", "--pass_io", 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]) diff --git a/dom0/qvm-tools/qvm-run b/dom0/qvm-tools/qvm-run index 47761495..6de98fc4 100755 --- a/dom0/qvm-tools/qvm-run +++ b/dom0/qvm-tools/qvm-run @@ -120,11 +120,11 @@ def main(): parser.add_option ("--unpause", action="store_true", dest="unpause", default=False, help="Do 'xl unpause' for the VM(s) (can be combined this with --all and --wait)") - parser.add_option ("-p", "--pass_io", action="store_true", dest="passio", default=False, + parser.add_option ("-p", "--pass-io", action="store_true", dest="passio", default=False, help="Pass stdin/stdout/stderr from remote program") parser.add_option ("--localcmd", action="store", dest="localcmd", default=None, - help="With --pass_io, pass stdin/stdout/stderr to the given program") + help="With --pass-io, pass stdin/stdout/stderr to the given program") parser.add_option ("--force", action="store_true", dest="force", default=False, help="Force operation, even if may damage other VMs (eg shutdown of NetVM)") diff --git a/dom0/qvm-tools/qvm-sync-clock b/dom0/qvm-tools/qvm-sync-clock new file mode 100755 index 00000000..99419e32 --- /dev/null +++ b/dom0/qvm-tools/qvm-sync-clock @@ -0,0 +1,95 @@ +#!/usr/bin/python2.6 +# +# The Qubes OS Project, http://www.qubes-os.org +# +# Copyright (C) 2010 Marek Marczykowski +# +# 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 qubes.qubesutils import run_in_vm +import os.path +import os +import sys +import re +import subprocess + +qvm_collection = None + +def get_netvm_of_vm(vm): + netvm = vm + while netvm.netvm_vm is not None: + netvm = netvm.netvm_vm + if netvm is None or netvm.name == 'dom0': + print >> sys.stderr, 'There seems to be no network connected to ClockVM, aborting.' + sys.exit(1) + return netvm + +def main(): + verbose = False + if len(sys.argv) > 1 and sys.argv[1] in [ '--verbose', '-v' ]: + verbose = True + + qvm_collection = QubesVmCollection() + qvm_collection.lock_db_for_reading() + qvm_collection.load() + qvm_collection.unlock_db() + + clock_vm = qvm_collection.get_clockvm_vm() + + if clock_vm is None: + print >> sys.stderr, 'There is no selected ClockVM, aborting.' + sys.exit(1) + + if not clock_vm.is_running(): + print >> sys.stderr, 'ClockVM not started, exiting!' + sys.exit(1) + + net_vm = get_netvm_of_vm(clock_vm) + if verbose: + print >> sys.stderr, '--> Waiting for network for ClockVM.' + + # Ignore retcode, try even if nm-online failed - user can setup network manually + # on-online has timeout 30sec by default + run_in_vm(net_vm, 'user:nm-online -x', verbose=verbose, wait=True) + + # Sync clock + if run_in_vm(clock_vm, 'root:/etc/init.d/ntpdate restart', verbose=verbose, wait=True) != 0: + print >> sys.stderr, 'Time sync failed, aborting!' + sys.exit(1) + + p = run_in_vm(clock_vm, 'user:date -u', verbose=verbose, passio_popen=True) + date_out = p.stdout.read(100) + if not re.match(r'^[A-Za-z]* [A-Za-z]* [ 0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [A-Z]* [0-9][0-9][0-9][0-9]$', date_out): + print >> sys.stderr, 'Invalid date output, aborting!' + sys.exit(1) + + # Sync dom0 time + if verbose: + print >> sys.stderr, '--> Syncing dom0 clock.' + + subprocess.check_call(['sudo', 'date', '-u', '-s', date_out]) + + # Sync other VMs clock + for vm in qvm_collection.values(): + if vm.is_running() and vm.qid != 0 and vm.qid != clock_vm.qid: + if verbose: + print >> sys.stderr, '--> Syncing \'%s\' clock.' % vm.name + run_in_vm(vm, 'root:date -u -s "%s"' % date_out, verbose=verbose) + +main() + diff --git a/dom0/qvm-tools/qvm-sync-dom0-clock b/dom0/qvm-tools/qvm-sync-dom0-clock deleted file mode 100755 index 2a4d09a7..00000000 --- a/dom0/qvm-tools/qvm-sync-dom0-clock +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -CLOCK_VM=`qvm-get-clockvm` - -QREXEC_CLIENT=/usr/lib/qubes/qrexec_client - -if [ -z "$CLOCK_VM" ]; then - echo "ClockVM not set, exiting!" >&2 - exit 1 -fi - -if ! xl domid "$CLOCK_VM" > /dev/null 2>&1; then - echo "ClockVM not started, exiting!" >&2 - exit 1 -fi - -# dd is supposed to not allow memory exhaustion -# grep does basic sanity checking -# there seems to be no way to pass output of date +%s.%N to date, -# so we use human-readable format - -CURRENT_TIME="$($QREXEC_CLIENT -d $CLOCK_VM 'user:date -u' | - dd count=1 2>/dev/null | - grep '^[A-Za-z]* [A-Za-z]* [ 0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [A-Z]* [0-9][0-9][0-9][0-9]$'| - head -1)" - -if [ -n "$CURRENT_TIME" ] ; then - echo Syncing Dom0 clock: setting time "$CURRENT_TIME"... - sudo date -u -s "$CURRENT_TIME" ; - echo Done. >&2 -else - echo "Error while parsing the time obtained from the ClockVM ($CLOCK_VM).." >&2 -fi - diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index 435b9513..2f2cac58 100644 --- a/rpm_spec/core-dom0.spec +++ b/rpm_spec/core-dom0.spec @@ -42,6 +42,7 @@ Conflicts: qubes-gui-dom0 < 1.1.13 Requires: xen >= 4.1.0-2 Requires: createrepo Requires: gnome-packagekit +Requires: cronie %define _builddir %(pwd)/dom0 %description @@ -105,7 +106,6 @@ cp ../qrexec/qrexec_client $RPM_BUILD_ROOT/usr/lib/qubes/ cp ../qrexec/qrexec_policy $RPM_BUILD_ROOT/usr/lib/qubes/ cp aux-tools/qfile-dom0-unpacker $RPM_BUILD_ROOT/usr/lib/qubes/ cp aux-tools/qubes-receive-updates $RPM_BUILD_ROOT/usr/lib/qubes/ -cp aux-tools/keep-dom0-clock-synced $RPM_BUILD_ROOT/usr/lib/qubes/ cp ../misc/block_add_change $RPM_BUILD_ROOT/usr/lib/qubes/ cp ../misc/block_remove $RPM_BUILD_ROOT/usr/lib/qubes/ cp ../misc/block_cleanup $RPM_BUILD_ROOT/usr/lib/qubes/ @@ -121,6 +121,7 @@ cp aux-tools/qubes.ReceiveUpdates.policy $RPM_BUILD_ROOT/etc/qubes_rpc/policy/qu cp aux-tools/qubes.ReceiveUpdates $RPM_BUILD_ROOT/etc/qubes_rpc/ install -D aux-tools/qubes-dom0.modules $RPM_BUILD_ROOT/etc/sysconfig/modules/qubes-dom0.modules install -D aux-tools/qubes-dom0-updates.cron $RPM_BUILD_ROOT/etc/cron.daily/qubes-dom0-updates.cron +install -D aux-tools/qubes-sync-clock.cron $RPM_BUILD_ROOT/etc/cron.d/qubes-sync-clock.cron cp restore/qvm-create-default-dvm $RPM_BUILD_ROOT/usr/bin cp restore/xenstore-watch $RPM_BUILD_ROOT/usr/bin/xenstore-watch-qubes @@ -328,7 +329,6 @@ fi /usr/lib/qubes/block_remove /usr/lib/qubes/block_cleanup %attr(4750,root,qubes) /usr/lib/qubes/qfile-dom0-unpacker -/usr/lib/qubes/keep-dom0-clock-synced %attr(770,root,qubes) %dir /var/lib/qubes %attr(770,root,qubes) %dir /var/lib/qubes/vm-templates %attr(770,root,qubes) %dir /var/lib/qubes/appvms @@ -381,6 +381,7 @@ fi /etc/security/limits.d/99-qubes.conf /etc/udev/rules.d/99-qubes_block.rules /etc/cron.daily/qubes-dom0-updates.cron +/etc/cron.d/qubes-sync-clock.cron /etc/dracut.conf.d/* %dir /usr/share/dracut/modules.d/90qubes-pciback /usr/share/dracut/modules.d/90qubes-pciback/*