#!/usr/bin/python2 # # The Qubes OS Project, http://www.qubes-os.org # # Copyright (C) 2012 Agnieszka Kostrzewa # Copyright (C) 2012 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. # # import sys import os from PyQt4.QtCore import * from PyQt4.QtGui import * from qubes.qubes import QubesVmCollection from qubes.qubes import QubesVmLabels from qubes.qubes import QubesException from qubes.qubes import QubesVm,QubesHVm import qubesmanager.resources_rc from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent import subprocess import time import threading from ui_newappvmdlg import * from thread_monitor import * class NewVmDlg (QDialog, Ui_NewVMDlg): def __init__(self, app, qvm_collection, trayIcon, parent = None): super (NewVmDlg, self).__init__(parent) self.setupUi(self) self.app = app self.trayIcon = trayIcon self.qvm_collection = qvm_collection # Theoretically we should be locking for writing here and unlock # only after the VM creation finished. But the code would be more messy... # Instead we lock for writing in the actual worker thread try: from qubes.qubes import QubesHVm except ImportError: pass else: self.hvm_radio.setEnabled(True) self.qvm_collection.lock_db_for_reading() self.qvm_collection.load() self.qvm_collection.unlock_db() self.label_list = QubesVmLabels.values() self.label_list.sort(key=lambda l: l.index) for (i, label) in enumerate(self.label_list): self.vmlabel.insertItem(i, label.name) self.vmlabel.setItemIcon (i, QIcon(label.icon_path)) self.fill_template_list() self.vmname.setValidator(QRegExpValidator(QRegExp("[a-zA-Z0-9-]*", Qt.CaseInsensitive), None)) self.vmname.selectAll() self.vmname.setFocus() self.hvmtemplatewarningbox.hide() def fill_template_list(self): def filter_template(vm): if vm.internal: return False if not vm.is_template(): return False if self.hvm_radio.isChecked(): return QubesHVm.is_template_compatible(vm) else: return QubesVm.is_template_compatible(vm) self.template_vm_list = filter(filter_template, self.qvm_collection.values()) self.template_name.clear() default_index = 0 for (i, vm) in enumerate(self.template_vm_list): if vm is self.qvm_collection.get_default_template(): default_index = i self.template_name.insertItem(i, vm.name + " (default)") else: self.template_name.insertItem(i, vm.name) self.template_name.setCurrentIndex(default_index) def on_appvm_radio_toggled(self, checked): if checked: self.template_name.setEnabled(True) self.allow_networking.setEnabled(True) def on_netvm_radio_toggled(self, checked): if checked: self.template_name.setEnabled(True) self.allow_networking.setEnabled(False) def on_proxyvm_radio_toggled(self, checked): if checked: self.template_name.setEnabled(True) self.allow_networking.setEnabled(True) def on_hvm_radio_toggled(self, checked): if checked: self.standalone.setChecked(True) self.allow_networking.setEnabled(True) else: self.standalone.setChecked(False) self.fill_template_list() def on_standalone_toggled(self, checked): if checked and self.hvm_radio.isChecked(): self.template_name.setEnabled(False) else: self.template_name.setEnabled(True) if not checked and self.hvm_radio.isChecked(): self.hvmtemplatewarningbox.show() else: self.hvmtemplatewarningbox.hide() def reject(self): self.done(0) def accept(self): vmname = str(self.vmname.text()) if self.qvm_collection.get_vm_by_name(vmname) is not None: QMessageBox.warning (None, "Incorrect AppVM Name!", "A VM with the name {0} already exists in the system!".format(vmname)) return label = self.label_list[self.vmlabel.currentIndex()] template_vm = None if self.template_name.isEnabled(): template_vm = self.template_vm_list[self.template_name.currentIndex()] standalone = self.standalone.isChecked() allow_networking = None if self.allow_networking.isEnabled(): allow_networking = self.allow_networking.isChecked() if self.appvm_radio.isChecked(): createvm_method = self.qvm_collection.add_new_appvm vmtype = "AppVM" elif self.netvm_radio.isChecked(): createvm_method = self.qvm_collection.add_new_netvm vmtype = "NetVM" elif self.proxyvm_radio.isChecked(): createvm_method = self.qvm_collection.add_new_proxyvm vmtype = "ProxyVM" else: #hvm_radio.isChecked() createvm_method = self.qvm_collection.add_new_hvm vmtype = "HVM" vmclass = "Qubes" + vmtype.replace("VM", "Vm") thread_monitor = ThreadMonitor() thread = threading.Thread (target=self.do_create_vm, args=(vmclass, vmname, label, template_vm, standalone, allow_networking, thread_monitor)) thread.daemon = True thread.start() progress = QProgressDialog ("Creating new {0} {1}...".format(vmtype, vmname), "", 0, 0) progress.setCancelButton(None) progress.setModal(True) progress.show() while not thread_monitor.is_finished(): self.app.processEvents() time.sleep (0.1) progress.hide() if thread_monitor.success: self.trayIcon.showMessage ("VM '{0}' has been created.".format(vmname), msecs=3000) else: QMessageBox.warning (None, "Error creating AppVM!", "ERROR: {0}".format(thread_monitor.error_msg)) self.done(0) def do_create_vm (self, vmclass, vmname, label, template_vm, standalone, allow_networking, thread_monitor): vm = None try: self.qvm_collection.lock_db_for_writing() self.qvm_collection.load() if not standalone: vm = self.qvm_collection.add_new_vm(vmclass, name=vmname, template=template_vm, label=label) else: vm = self.qvm_collection.add_new_vm(vmclass, name=vmname, template=None, label=label) vm.create_on_disk(verbose=False, source_template = template_vm) if allow_networking == False: vm.uses_default_netvm = False vm.netvm = None self.qvm_collection.save() except Exception as ex: thread_monitor.set_error_msg (str(ex)) if vm: vm.remove_from_disk() finally: self.qvm_collection.unlock_db() thread_monitor.set_finished()