core-admin/dispvm/qfile-daemon-dvm

160 lines
6.3 KiB
Plaintext
Raw Normal View History

#!/usr/bin/python2
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Rafal Wojtczuk <rafal@invisiblethingslab.com>
#
# 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.
#
#
import os
import subprocess
import sys
import fcntl
import shutil
2013-02-25 13:42:36 +01:00
import time
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesDispVmLabels
from qubes.notify import tray_notify,tray_notify_error,tray_notify_init
current_savefile = '/var/run/qubes/current-savefile'
current_dvm_conf = '/var/run/qubes/current-dvm.conf'
current_savefile_vmdir = '/var/lib/qubes/dvmdata/vmdir'
class QfileDaemonDvm:
def __init__(self, name):
self.name = name
def get_disp_templ(self):
vmdir = os.readlink(current_savefile_vmdir)
return vmdir.split('/')[-1]
def do_get_dvm(self):
tray_notify("red", "Starting new DispVM...")
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
tar_process = subprocess.Popen(['tar', '-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:
2011-07-09 17:56:40 +02:00
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 ' + disptempl + ' 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
if os.path.exists(vm.firewall_conf):
disp_firewall_conf = '/var/run/qubes/%s-firewall.xml' % disp_name
shutil.copy(vm.firewall_conf, disp_firewall_conf)
dispvm.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]
# 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()))
dispvm.start()
print >>sys.stderr, "time=%s, VM started" % (str(time.time()))
qvm_collection.save()
qvm_collection.unlock_db()
# Reload firewall rules
2013-02-25 06:48:29 +01:00
print >>sys.stderr, "time=%s, reloading firewall" % (str(time.time()))
for vm in qvm_collection.values():
if vm.is_proxyvm() and vm.is_running():
vm.write_iptables_xenstore_entry()
return dispvm
def dvm_setup_ok(self):
dvmdata_dir = '/var/lib/qubes/dvmdata/'
if not os.path.isfile(current_savefile):
return False
if not os.path.isfile(dvmdata_dir+'default-savefile') or not os.path.isfile(dvmdata_dir+'savefile-root'):
return False
dvm_mtime = os.stat(current_savefile).st_mtime
root_mtime = os.stat(dvmdata_dir+'savefile-root').st_mtime
if dvm_mtime < root_mtime:
template_name = os.path.basename(os.path.dirname(os.readlink(dvmdata_dir+'savefile-root')))
if subprocess.call(["xl", "domid", template_name]) == 0:
2014-07-02 02:31:05 +02:00
tray_notify("For optimum performance, you should not "
"start DispVM when its template is running.", "red")
return False
return True
def get_dvm(self):
if not self.dvm_setup_ok():
2013-03-14 15:06:19 +01:00
if os.system("/usr/lib/qubes/qubes-update-dispvm-savefile-with-progress.sh >/dev/null </dev/null" ) != 0:
tray_notify_error("DVM savefile creation failed")
return None
return self.do_get_dvm()
def remove_disposable_from_qdb(self, name):
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
vm = qvm_collection.get_vm_by_name(name)
if vm is None:
qvm_collection.unlock_db()
return False
qvm_collection.pop(vm.qid)
qvm_collection.save()
qvm_collection.unlock_db()
def main():
global notify_object
exec_index = sys.argv[1]
src_vmname = sys.argv[2]
user = sys.argv[3]
#accessed directly by get_dvm()
# sys.argv[4] - override label
# sys.argv[5] - override firewall
2013-02-25 06:48:29 +01:00
print >>sys.stderr, "time=%s, qfile-daemon-dvm init" % (str(time.time()))
tray_notify_init()
2013-02-25 06:48:29 +01:00
print >>sys.stderr, "time=%s, creating DispVM" % (str(time.time()))
qfile = QfileDaemonDvm(src_vmname)
dispvm = qfile.get_dvm()
if dispvm is not None:
2013-02-25 06:48:29 +01:00
print >>sys.stderr, "time=%s, starting VM process" % (str(time.time()))
subprocess.call(['/usr/lib/qubes/qrexec-client', '-d', dispvm.name,
user+':exec /usr/lib/qubes/qubes-rpc-multiplexer ' + exec_index + " " + src_vmname])
dispvm.force_shutdown()
qfile.remove_disposable_from_qdb(dispvm.name)
main()