1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/ait/poc/scanner/create_dvm.py Sat May 04 12:17:31 2013 -0400
1.3 @@ -0,0 +1,280 @@
1.4 +#!/bin/python
1.5 +import os
1.6 +import time
1.7 +import dbus
1.8 +import sys
1.9 +import subprocess
1.10 +from qubes.qubes import QubesVmCollection
1.11 +from qubes.qubes import QubesDispVmLabels
1.12 +from qubes.qubes import QubesException
1.13 +from qubes.qubes import QubesVmLabels
1.14 +from qubes.qmemman_client import QMemmanClient
1.15 +from qubes.qubesutils import block_list,block_attach,block_detach,block_detach_all,block_check_attached
1.16 +from qubes.qubesutils import kbytes_to_kmg, bytes_to_kmg
1.17 +
1.18 +
1.19 +notify_object = None
1.20 +current_savefile = '/var/run/qubes/current_savefile'
1.21 +current_dvm_conf = '/var/run/qubes/current_dvm.conf'
1.22 +avir_appvm_template = 'avir-template'
1.23 +avir_dvm_template = 'avir-template-dvm'
1.24 +
1.25 +def get_vm_collection():
1.26 + vm_collection = QubesVmCollection()
1.27 + vm_collection.lock_db_for_reading()
1.28 + vm_collection.load()
1.29 + vm_collection.unlock_db()
1.30 + return vm_collection
1.31 +
1.32 +def get_vm_by_name(vmname):
1.33 + return get_vm_collection().get_vm_by_name(vmname)
1.34 +
1.35 +def gen_scanner_name():
1.36 + vm_collection = get_vm_collection()
1.37 + vms = [vm for vm in vm_collection.values()]
1.38 + vm_names = []
1.39 + for vm in vms:
1.40 + if vm.is_appvm() and vm.template.name == avir_appvm_template:
1.41 + vm_names.append (vm.name)
1.42 + print vm_names
1.43 +
1.44 + ids = range(100)
1.45 + for id in ids:
1.46 + if "scanner"+str(id) not in vm_names:
1.47 + return "scanner"+str(id)
1.48 + print >> sys.stderr, "Unable to generate new scanner vm name"
1.49 + exit(1)
1.50 +
1.51 +class VMFactory:
1.52 + def __init__(self):
1.53 + self.tray_notify(str="Initialized")
1.54 +
1.55 + def tray_notify(self, str, timeout = 3000):
1.56 + notify_object.Notify("Qubes", 0, "red", "Qubes", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
1.57 +
1.58 + def tray_notify_error(self, str, timeout = 3000):
1.59 + notify_object.Notify("Qubes", 0, "dialog-error", "Qubes", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
1.60 +
1.61 + def create_appvm(self):
1.62 + #generate new avir-scanner name
1.63 + scanner_vmname = gen_scanner_name()
1.64 + print "Generating new scanner vm %s " % scanner_vmname
1.65 +
1.66 + #create new vscanner virtual machine from template "avir-template"
1.67 + qvm_collection = QubesVmCollection()
1.68 + qvm_collection.lock_db_for_writing()
1.69 + qvm_collection.load()
1.70 + avir_template = qvm_collection.get_vm_by_name(avir_appvm_template)
1.71 + if not avir_template.is_template():
1.72 + print >> sys.stderr, "VM '{0}' is not a TemplateVM".format(avir_template)
1.73 + exit (1)
1.74 + vmtype = "QubesAppVm"
1.75 +
1.76 + try:
1.77 + scanner_vm = qvm_collection.add_new_vm(vmtype, name=scanner_vmname, template=avir_template, label = QubesVmLabels["orange"])
1.78 + except QubesException as err:
1.79 + print >> sys.stderr, "ERROR: {0}".format(err)
1.80 + exit (1)
1.81 +
1.82 + scanner_vm.memory = 512
1.83 + scanner_vm.vcpus = 2
1.84 + try:
1.85 + scanner_vm.create_on_disk(verbose=True, source_template=avir_template)
1.86 + #if options.root:
1.87 + # os.unlink(vm.root_img)
1.88 + # os.rename(options.root, vm.root_img)
1.89 + except (IOError, OSError) as err:
1.90 + print >> sys.stderr, "ERROR: {0}".format(err)
1.91 + exit (1)
1.92 +
1.93 + qvm_collection.save()
1.94 + qvm_collection.unlock_db()
1.95 + return scanner_vmname
1.96 +
1.97 + def start_vm(self, vmname):
1.98 + vm = get_vm_by_name(vmname)
1.99 + if vm is None or vm.qid not in get_vm_collection():
1.100 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
1.101 + exit(1)
1.102 + try:
1.103 + vm.verify_files()
1.104 + xid = vm.start(verbose=True, preparing_dvm=False, start_guid=True, notify_function=None)
1.105 + except (IOError, OSError, QubesException, MemoryError) as err:
1.106 + #if options.tray:
1.107 + # tray_notify_error(str(err))
1.108 + #else:
1.109 + print >> sys.stderr, "ERROR: {0}".format(err)
1.110 + exit (1)
1.111 +
1.112 + def create_dvm(self):
1.113 + qmemman_client = QMemmanClient()
1.114 + if not qmemman_client.request_memory(400*1024*1024):
1.115 + qmemman_client.close()
1.116 + errmsg = 'Not enough memory to create DVM. '
1.117 + errmsg +='Terminate some appVM and retry.'
1.118 + if os.path.exists('/usr/bin/kdialog'):
1.119 + subprocess.call(['/usr/bin/kdialog', '--sorry', errmsg])
1.120 + else:
1.121 + subprocess.call(['/usr/bin/zenity', '--warning', errmsg])
1.122 + return None
1.123 + self.tray_notify("Starting new DispVM...")
1.124 +
1.125 + qvm_collection = QubesVmCollection()
1.126 + qvm_collection.lock_db_for_writing()
1.127 + qvm_collection.load()
1.128 + avir_template = qvm_collection.get_vm_by_name(avir_dvm_template)
1.129 + if avir_template is None:
1.130 + sys.stderr.write( 'Domain ' + avir_dvm_template + ' does not exist ?')
1.131 + qvm_collection.unlock_db()
1.132 + qmemman_client.close()
1.133 + return None
1.134 + label = avir_template.label
1.135 + retcode = subprocess.call(['/usr/lib/qubes/qubes_restore',
1.136 + current_savefile,
1.137 + current_dvm_conf,
1.138 + '-u', str(avir_template.default_user),
1.139 + '-c', label.color,
1.140 + '-i', label.icon_path,
1.141 + '-l', str(label.index)])
1.142 + qmemman_client.close()
1.143 + if retcode != 0:
1.144 + if os.path.exists('/usr/bin/kdialog'):
1.145 + subprocess.call(['/usr/bin/kdialog', '--sorry', 'DisposableVM creation failed, see qubes_restore.log'])
1.146 + else:
1.147 + subprocess.call(['/usr/bin/zenity', '--warning', 'DisposableVM creation failed, see qubes_restore.log'])
1.148 + qvm_collection.unlock_db()
1.149 + return None
1.150 +
1.151 + f = open('/var/run/qubes/dispVM_xid', 'r');
1.152 + disp_xid = f.readline().rstrip('\n')
1.153 + disp_name = f.readline().rstrip('\n')
1.154 + disptempl = f.readline().rstrip('\n')
1.155 + f.close()
1.156 +
1.157 + print >>sys.stderr, "getting vm %s" % disptempl
1.158 + avir_disptempl = qvm_collection.get_vm_by_name(disptempl);
1.159 + if avir_disptempl is None:
1.160 + sys.stderr.write( 'Domain ' + disptempl + ' does not exist ?')
1.161 + qvm_collection.unlock_db()
1.162 + return None
1.163 +
1.164 + dispid = int(disp_name[4:])
1.165 + dispvm = qvm_collection.add_new_disposablevm(disp_name, avir_disptempl.template, label=label, dispid=dispid, netvm=avir_disptempl.netvm)
1.166 + print >> sys.stderr, "Waiting for the VM %s to startup...", dispvm.name
1.167 + startup_counter = 0
1.168 + startup_counter_max = 60
1.169 + while startup_counter < startup_counter_max:
1.170 + if dispvm.is_running():
1.171 + break
1.172 + shutdown_counter += 1
1.173 + time.sleep (1)
1.174 +
1.175 + qvm_collection.save()
1.176 + qvm_collection.unlock_db()
1.177 + return dispvm.name
1.178 +
1.179 + def stop_vm(self, vmname):
1.180 + vm = get_vm_by_name(vmname)
1.181 + if vm is None or vm.qid not in get_vm_collection():
1.182 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
1.183 + exit(1)
1.184 + vm.shutdown(force=True)
1.185 + print >> sys.stderr, "Waiting for the VM %s to shutdown...", vmname
1.186 + shutdown_counter = 0
1.187 + shutdown_counter_max = 60
1.188 + while shutdown_counter < shutdown_counter_max:
1.189 + if not vm.is_running():
1.190 + return
1.191 + shutdown_counter += 1
1.192 + time.sleep (1)
1.193 +
1.194 + def remove_vm(self, vmname):
1.195 + qvm_collection = QubesVmCollection()
1.196 + qvm_collection.lock_db_for_writing()
1.197 + qvm_collection.load()
1.198 + vm = qvm_collection.get_vm_by_name(vmname)
1.199 +
1.200 + if vm is None or vm.qid not in qvm_collection:
1.201 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
1.202 + exit(1)
1.203 +
1.204 + if vm.is_running():
1.205 + print >> sys.stderr, "Cannot remove a running VM, stop it first"
1.206 + exit (1)
1.207 +
1.208 + if vm.is_template():
1.209 + dependent_vms = qvm_collection.get_vms_based_on(vm.qid)
1.210 + if len(dependent_vms) > 0:
1.211 + print >> sys.stderr, "The following AppVMs use '{0}' as a template:".format(vmname)
1.212 + for vm in dependent_vms:
1.213 + print >> sys.stderr, "{name:<12} (qid={qid})".format(qid=vm.qid, name=vm.name)
1.214 + print >> sys.stderr, "Please remove those VMs first."
1.215 + exit (1)
1.216 + if qvm_collection.default_template_qid == vm.qid:
1.217 + qvm_collection.default_template_qid = None
1.218 +
1.219 + try:
1.220 + vm.remove_from_disk()
1.221 + except (IOError, OSError) as err:
1.222 + print >> sys.stderr, "Warning: {0}".format(err)
1.223 +
1.224 + # Do not exit, perhaps the VM files were somehow removed
1.225 + # so just remove it from Qubes DB
1.226 + qvm_collection.pop(vm.qid)
1.227 + qvm_collection.save()
1.228 + qvm_collection.unlock_db()
1.229 +
1.230 + def attach_dev(self, vmname, devname):
1.231 + vm = get_vm_by_name(vmname)
1.232 + if vm is None or vm.qid not in get_vm_collection():
1.233 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
1.234 + exit(1)
1.235 + print "Attaching %s to vm - %s" % (devname, vm.name)
1.236 + kwargs = {}
1.237 + kwargs['auto_detach'] = True
1.238 + try:
1.239 + backend_vm = get_vm_by_name("dom0")
1.240 + block_attach(vm, backend_vm, devname, **kwargs)
1.241 + except QubesException as e:
1.242 + print >> sys.stderr, "ERROR: %s" % str(e)
1.243 + exit(1)
1.244 +
1.245 + def detach_dev(self, vmname, devname):
1.246 + vm = get_vm_by_name(vmname)
1.247 + if vm is None or vm.qid not in get_vm_collection():
1.248 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
1.249 + exit(1)
1.250 + print "Detaching %s from vm - %s" % (devname, vmname)
1.251 + kwargs = {}
1.252 + #kwargs['frontend'] = "to_scan"
1.253 + try:
1.254 + block_detach(vm, **kwargs)
1.255 + except QubesException as e:
1.256 + print >> sys.stderr, "ERROR: %s" % str(e)
1.257 + sys.exit(1)
1.258 +
1.259 + def scan(self, vmname):
1.260 + vm = get_vm_by_name(vmname)
1.261 + if vm is None or vm.qid not in get_vm_collection():
1.262 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
1.263 + exit(1)
1.264 + subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:mount /dev/xvdi /mnt/removable'])
1.265 + #subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:clamscan /mnt/removable'])
1.266 + subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:umount /mnt/removable'])
1.267 +
1.268 +
1.269 +def main():
1.270 + global notify_object
1.271 + print >>sys.stderr, "time=%s, qfile-daemon-dvm init" % (str(time.time()))
1.272 + notify_object = dbus.SessionBus().get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
1.273 + vm_factory = VMFactory()
1.274 + #vmname = vm_factory.create_dvm()
1.275 + vmname = vm_factory.create_appvm()
1.276 + vm_factory.start_vm(vmname)
1.277 + vm_factory.attach_dev(vmname, "sdb")
1.278 + vm_factory.scan(vmname)
1.279 + vm_factory.detach_dev(vmname, "sdb")
1.280 + #vm_factory.stop_vm(vmname)
1.281 + #vm_factory.remove_vm(vmname)
1.282 +
1.283 +main()