dispvm: use try/finally to make sure that qubes.xml is unlocked

Even in case of some exception (in which case theoretically it should be
unlocked at qfile-daemon-dvm exit, but the script may wait for
something).

QubesOS/qubes-issues#1636
This commit is contained in:
Marek Marczykowski-Górecki 2016-02-21 12:41:13 +01:00
parent ae848d5369
commit 5546d679c0
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -51,68 +51,67 @@ class QfileDaemonDvm:
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
tar_process = subprocess.Popen(
['bsdtar', '-C', current_savefile_vmdir,
'-xSUf', os.path.join(current_savefile_vmdir, 'saved-cows.tar')])
qvm_collection.load()
print >>sys.stderr, "time=%s, collection loaded" % (str(time.time()))
vm = qvm_collection.get_vm_by_name(self.name)
if vm is None:
sys.stderr.write('Domain ' + self.name + ' does not exist ?')
qvm_collection.unlock_db()
return None
label = vm.label
if len(sys.argv) > 4 and len(sys.argv[4]) > 0:
assert sys.argv[4] in QubesDispVmLabels.keys(), "Invalid label"
label = QubesDispVmLabels[sys.argv[4]]
disp_templ = self.get_disp_templ()
vm_disptempl = qvm_collection.get_vm_by_name(disp_templ)
if vm_disptempl is None:
sys.stderr.write('Domain ' + disp_templ + ' does not exist ?')
qvm_collection.unlock_db()
return None
dispvm = qvm_collection.add_new_vm('QubesDisposableVm',
disp_template=vm_disptempl,
label=label)
print >>sys.stderr, "time=%s, VM created" % (str(time.time()))
# By default inherit firewall rules from calling VM
disp_firewall_conf = '/var/run/qubes/%s-firewall.xml' % dispvm.name
dispvm.firewall_conf = disp_firewall_conf
if os.path.exists(vm.firewall_conf):
shutil.copy(vm.firewall_conf, disp_firewall_conf)
elif vm.qid == 0 and os.path.exists(vm_disptempl.firewall_conf):
# for DispVM called from dom0, copy use rules from DispVM template
shutil.copy(vm_disptempl.firewall_conf, disp_firewall_conf)
if len(sys.argv) > 5 and len(sys.argv[5]) > 0:
assert os.path.exists(sys.argv[5]), "Invalid firewall.conf location"
dispvm.firewall_conf = sys.argv[5]
if vm.qid != 0:
dispvm.uses_default_netvm = False
# netvm can be changed before restore,
# but cannot be enabled/disabled
if (dispvm.netvm is None) == (vm.dispvm_netvm is None):
dispvm.netvm = vm.dispvm_netvm
# Wait for tar to finish
if tar_process.wait() != 0:
sys.stderr.write('Failed to unpack saved-cows.tar')
qvm_collection.unlock_db()
return None
print >>sys.stderr, "time=%s, VM starting" % (str(time.time()))
try:
dispvm.start()
except (MemoryError, QubesException) as e:
tray_notify_error(str(e))
raise
if vm.qid != 0:
# if need to enable/disable netvm, do it while DispVM is alive
if (dispvm.netvm is None) != (vm.dispvm_netvm is None):
dispvm.netvm = vm.dispvm_netvm
print >>sys.stderr, "time=%s, VM started" % (str(time.time()))
qvm_collection.save()
qvm_collection.unlock_db()
tar_process = subprocess.Popen(
['bsdtar', '-C', current_savefile_vmdir,
'-xSUf', os.path.join(current_savefile_vmdir, 'saved-cows.tar')])
qvm_collection.load()
print >>sys.stderr, "time=%s, collection loaded" % (str(time.time()))
vm = qvm_collection.get_vm_by_name(self.name)
if vm is None:
sys.stderr.write('Domain ' + self.name + ' does not exist ?')
return None
label = vm.label
if len(sys.argv) > 4 and len(sys.argv[4]) > 0:
assert sys.argv[4] in QubesDispVmLabels.keys(), "Invalid label"
label = QubesDispVmLabels[sys.argv[4]]
disp_templ = self.get_disp_templ()
vm_disptempl = qvm_collection.get_vm_by_name(disp_templ)
if vm_disptempl is None:
sys.stderr.write('Domain ' + disp_templ + ' does not exist ?')
return None
dispvm = qvm_collection.add_new_vm('QubesDisposableVm',
disp_template=vm_disptempl,
label=label)
print >>sys.stderr, "time=%s, VM created" % (str(time.time()))
# By default inherit firewall rules from calling VM
disp_firewall_conf = '/var/run/qubes/%s-firewall.xml' % dispvm.name
dispvm.firewall_conf = disp_firewall_conf
if os.path.exists(vm.firewall_conf):
shutil.copy(vm.firewall_conf, disp_firewall_conf)
elif vm.qid == 0 and os.path.exists(vm_disptempl.firewall_conf):
# for DispVM called from dom0, copy use rules from DispVM template
shutil.copy(vm_disptempl.firewall_conf, disp_firewall_conf)
if len(sys.argv) > 5 and len(sys.argv[5]) > 0:
assert os.path.exists(sys.argv[5]), "Invalid firewall.conf location"
dispvm.firewall_conf = sys.argv[5]
if vm.qid != 0:
dispvm.uses_default_netvm = False
# netvm can be changed before restore,
# but cannot be enabled/disabled
if (dispvm.netvm is None) == (vm.dispvm_netvm is None):
dispvm.netvm = vm.dispvm_netvm
# Wait for tar to finish
if tar_process.wait() != 0:
sys.stderr.write('Failed to unpack saved-cows.tar')
return None
print >>sys.stderr, "time=%s, VM starting" % (str(time.time()))
try:
dispvm.start()
except (MemoryError, QubesException) as e:
tray_notify_error(str(e))
raise
if vm.qid != 0:
# if need to enable/disable netvm, do it while DispVM is alive
if (dispvm.netvm is None) != (vm.dispvm_netvm is None):
dispvm.netvm = vm.dispvm_netvm
print >>sys.stderr, "time=%s, VM started" % (str(time.time()))
qvm_collection.save()
finally:
qvm_collection.unlock_db()
# Reload firewall rules
print >>sys.stderr, "time=%s, reloading firewall" % (str(time.time()))
for vm in qvm_collection.values():