Skip to content

Commit 2c6c766

Browse files
committed
Merge branch '20171107-tests-backup-api-misc'
* 20171107-tests-backup-api-misc: test: make race condition on xterm close less likely tests/backupcompatibility: fix handling 'internal' property backup: fix handling target write error (like no disk space) tests/backupcompatibility: drop R1 format tests backup: use offline_mode for backup collection qubespolicy: fix handling '$adminvm' target with ask action app: drop reference to libvirt object after undefining it vm: always log startup fail api: do not log handled errors sent to a client tests/backups: convert to new restore handling - using qubesadmin module app: clarify error message on failed domain remove (used somewhere) Fix qubes-core.service ordering
2 parents 9519f15 + 45af091 commit 2c6c766

File tree

10 files changed

+356
-347
lines changed

10 files changed

+356
-347
lines changed

linux/systemd/qubes-core.service

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[Unit]
22
Description=Qubes Dom0 startup setup
3-
After=qubes-db-dom0.service libvirtd.service xenconsoled.service
3+
After=qubes-db-dom0.service libvirtd.service xenconsoled.service qubesd.service qubes-qmemman.service
44
# Cover legacy init.d script
55

66
[Service]

qubes/api/__init__.py

-3
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,6 @@ def respond(self, src, meth, dest, arg, *, untrusted_payload):
285285
if self.debug:
286286
self.app.log.exception(msg,
287287
err, src, meth, dest, arg, len(untrusted_payload))
288-
else:
289-
self.app.log.info(msg,
290-
err, src, meth, dest, arg, len(untrusted_payload))
291288
if self.transport is not None:
292289
self.send_exception(err)
293290
self.transport.write_eof()

qubes/app.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,8 @@ def __delitem__(self, key):
484484
self.app.fire_event('domain-pre-delete', pre_event=True, vm=vm)
485485
try:
486486
vm.libvirt_domain.undefine()
487+
# pylint: disable=protected-access
488+
vm._libvirt_domain = None
487489
except libvirt.libvirtError as e:
488490
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
489491
# already undefined
@@ -1196,7 +1198,9 @@ def on_domain_pre_deleted(self, event, vm):
11961198
self.log.error(
11971199
'Cannot remove %s, used by %s.%s',
11981200
vm, obj, prop.__name__)
1199-
raise qubes.exc.QubesVMInUseError(vm)
1201+
raise qubes.exc.QubesVMInUseError(vm,
1202+
'Domain is in use: {!r}; details in system log'
1203+
.format(vm.name))
12001204
except AttributeError:
12011205
pass
12021206

qubes/backup.py

+20-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import itertools
2424
import logging
2525
import functools
26+
import string
2627
import termios
2728

2829
import asyncio
@@ -665,6 +666,13 @@ def _monitor_process(proc, error_message):
665666
raise
666667

667668
if proc.returncode:
669+
if proc.stderr is not None:
670+
proc_stderr = (yield from proc.stderr.read())
671+
proc_stderr = proc_stderr.decode('ascii', errors='ignore')
672+
proc_stderr = ''.join(
673+
c for c in proc_stderr if c in string.printable and
674+
c not in '\r\n%{}')
675+
error_message += ': ' + proc_stderr
668676
raise qubes.exc.QubesException(error_message)
669677

670678
@staticmethod
@@ -694,7 +702,7 @@ def backup_do(self):
694702
self.tmpdir = tempfile.mkdtemp()
695703
shutil.copy(qubes_xml, os.path.join(self.tmpdir, 'qubes.xml'))
696704
qubes_xml = os.path.join(self.tmpdir, 'qubes.xml')
697-
backup_app = qubes.Qubes(qubes_xml)
705+
backup_app = qubes.Qubes(qubes_xml, offline_mode=True)
698706
backup_app.events_enabled = False
699707

700708
files_to_backup = self._files_to_backup
@@ -709,14 +717,17 @@ def backup_do(self):
709717
backup_app.domains[qid].features['backup-path'] = vm_info.subdir
710718
backup_app.domains[qid].features['backup-size'] = vm_info.size
711719
backup_app.save()
720+
del backup_app
712721

713722
vmproc = None
714723
if self.target_vm is not None:
715724
# Prepare the backup target (Qubes service call)
716725
# If APPVM, STDOUT is a PIPE
717726
read_fd, write_fd = os.pipe()
718727
vmproc = yield from self.target_vm.run_service('qubes.Backup',
719-
stdin=read_fd, stderr=subprocess.PIPE)
728+
stdin=read_fd,
729+
stderr=subprocess.PIPE,
730+
stdout=subprocess.DEVNULL)
720731
os.close(read_fd)
721732
os.write(write_fd, (self.target_dir.
722733
replace("\r", "").replace("\n", "") + "\n").encode())
@@ -754,11 +765,12 @@ def backup_do(self):
754765

755766
vmproc_task = None
756767
if vmproc is not None:
757-
vmproc_task = asyncio.ensure_future(self._cancel_on_error(
768+
vmproc_task = asyncio.ensure_future(
758769
self._monitor_process(vmproc,
759770
'Writing backup to VM {} failed'.format(
760-
self.target_vm.name)),
761-
send_task))
771+
self.target_vm.name)))
772+
asyncio.ensure_future(self._cancel_on_error(
773+
vmproc_task, send_task))
762774

763775
for file_name in header_files:
764776
yield from to_send.put(file_name)
@@ -782,10 +794,12 @@ def backup_do(self):
782794
except:
783795
yield from to_send.put(QUEUE_ERROR)
784796
# in fact we may be handling CancelledError, induced by
785-
# exception in send_task (and propagated by
797+
# exception in send_task or vmproc_task (and propagated by
786798
# self._cancel_on_error call above); in such a case this
787799
# yield from will raise exception, covering CancelledError -
788800
# this is intended behaviour
801+
if vmproc_task:
802+
yield from vmproc_task
789803
yield from send_task
790804
raise
791805

0 commit comments

Comments
 (0)