Replaced python threading with QThreads
This commit is contained in:
parent
693f3e411c
commit
afcdba3029
@ -28,7 +28,6 @@ import subprocess
|
|||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import traceback
|
import traceback
|
||||||
import threading
|
|
||||||
import quamash
|
import quamash
|
||||||
import asyncio
|
import asyncio
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
@ -44,7 +43,6 @@ from PyQt4 import QtCore # pylint: disable=import-error
|
|||||||
from qubesmanager.about import AboutDialog
|
from qubesmanager.about import AboutDialog
|
||||||
|
|
||||||
from . import ui_qubemanager # pylint: disable=no-name-in-module
|
from . import ui_qubemanager # pylint: disable=no-name-in-module
|
||||||
from . import thread_monitor
|
|
||||||
from . import table_widgets
|
from . import table_widgets
|
||||||
from . import settings
|
from . import settings
|
||||||
from . import global_settings
|
from . import global_settings
|
||||||
@ -238,6 +236,81 @@ class VmShutdownMonitor(QtCore.QObject):
|
|||||||
self.restart_vm_if_needed()
|
self.restart_vm_if_needed()
|
||||||
|
|
||||||
|
|
||||||
|
class StartVMThread(QtCore.QThread):
|
||||||
|
def __init__(self, vm):
|
||||||
|
QtCore.QThread.__init__(self)
|
||||||
|
self.vm = vm
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.vm.start()
|
||||||
|
except exc.QubesException as ex:
|
||||||
|
self.emit(QtCore.SIGNAL('show_error(QString, QString)'),\
|
||||||
|
"Error starting Qube!", str(ex))
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveVMThread(QtCore.QThread):
|
||||||
|
def __init__(self, vm, qubes_app):
|
||||||
|
QtCore.QThread.__init__(self)
|
||||||
|
self.vm = vm
|
||||||
|
self.qubes_app = qubes_app
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
del self.qubes_app.domains[self.vm.name]
|
||||||
|
except exc.QubesException as ex:
|
||||||
|
self.emit(QtCore.SIGNAL('show_error(QString, QString)'),\
|
||||||
|
"Error removing Qube!", str(ex))
|
||||||
|
|
||||||
|
class UpdateVMThread(QtCore.QThread):
|
||||||
|
def __init__(self, vm):
|
||||||
|
QtCore.QThread.__init__(self)
|
||||||
|
self.vm = vm
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
if self.vm.qid == 0:
|
||||||
|
subprocess.check_call(
|
||||||
|
["/usr/bin/qubes-dom0-update", "--clean", "--gui"])
|
||||||
|
else:
|
||||||
|
if not self.vm.is_running():
|
||||||
|
self.vm.start()
|
||||||
|
self.vm.run_service("qubes.InstallUpdatesGUI",\
|
||||||
|
user="root", wait=False)
|
||||||
|
except (ChildProcessError, exc.QubesException) as ex:
|
||||||
|
self.emit(QtCore.SIGNAL('show_error(QString, QString)'),\
|
||||||
|
"Error on Qube update!", str(ex))
|
||||||
|
|
||||||
|
|
||||||
|
class CloneVMThread(QtCore.QThread):
|
||||||
|
def __init__(self, src_vm, qubes_app, dst_name):
|
||||||
|
QtCore.QThread.__init__(self)
|
||||||
|
self.src_vm = src_vm
|
||||||
|
self.qubes_app = qubes_app
|
||||||
|
self.dst_name = dst_name
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
dst_vm = self.qubes_app.clone_vm(self.src_vm, self.dst_name)
|
||||||
|
except exc.QubesException as ex:
|
||||||
|
self.emit(QtCore.SIGNAL('show_error(QString, QString)'),\
|
||||||
|
"Error while cloning Qube!", str(ex))
|
||||||
|
|
||||||
|
|
||||||
|
class RunCommandThread(QtCore.QThread):
|
||||||
|
def __init__(self, vm, command_to_run):
|
||||||
|
QtCore.QThread.__init__(self)
|
||||||
|
self.vm = vm
|
||||||
|
self.command_to_run = command_to_run
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.vm.run(self.command_to_run)
|
||||||
|
except (ChildProcessError, exc.QubesException) as ex:
|
||||||
|
self.emit(QtCore.SIGNAL('show_error(QString, QString)'),\
|
||||||
|
"Error while running command!", str(ex))
|
||||||
|
|
||||||
|
|
||||||
class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
row_height = 30
|
row_height = 30
|
||||||
@ -410,6 +483,9 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
dispatcher.add_handler('property-load',
|
dispatcher.add_handler('property-load',
|
||||||
self.on_domain_changed)
|
self.on_domain_changed)
|
||||||
|
|
||||||
|
# It needs to store threads until they finish
|
||||||
|
self.threads_list = []
|
||||||
|
|
||||||
# Check Updates Timer
|
# Check Updates Timer
|
||||||
timer = QtCore.QTimer(self)
|
timer = QtCore.QTimer(self)
|
||||||
timer.timeout.connect(self.check_updates)
|
timer.timeout.connect(self.check_updates)
|
||||||
@ -585,7 +661,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
vm = self.get_selected_vm()
|
vm = self.get_selected_vm()
|
||||||
|
|
||||||
if vm is not None and vm in self.qubes_app.domains:
|
if vm is not None and vm in self.qubes_app.domains:
|
||||||
|
|
||||||
# TODO: add boot from device to menu and add windows tools there
|
# TODO: add boot from device to menu and add windows tools there
|
||||||
# Update available actions:
|
# Update available actions:
|
||||||
self.action_settings.setEnabled(vm.klass != 'AdminVM')
|
self.action_settings.setEnabled(vm.klass != 'AdminVM')
|
||||||
@ -705,43 +780,16 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
# remove the VM
|
# remove the VM
|
||||||
t_monitor = thread_monitor.ThreadMonitor()
|
thread = RemoveVMThread(vm, self.qubes_app)
|
||||||
thread = threading.Thread(target=self.do_remove_vm,
|
self.threads_list.append(thread)
|
||||||
args=(vm, self.qubes_app, t_monitor))
|
self.connect(thread, QtCore.SIGNAL("show_error(QString, QString)"), self.show_error)
|
||||||
thread.daemon = True
|
thread.finished.connect(self.clear_threads)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
progress = QtGui.QProgressDialog(
|
def clear_threads(self):
|
||||||
self.tr(
|
for thread in self.threads_list:
|
||||||
"Removing Qube: <b>{0}</b>...").format(vm.name), "", 0, 0)
|
if thread.isFinished():
|
||||||
progress.setWindowFlags(QtCore.Qt.Window |
|
self.threads_list.remove(thread)
|
||||||
QtCore.Qt.WindowTitleHint |
|
|
||||||
QtCore.Qt.CustomizeWindowHint)
|
|
||||||
progress.setCancelButton(None)
|
|
||||||
progress.setModal(True)
|
|
||||||
progress.show()
|
|
||||||
|
|
||||||
while not t_monitor.is_finished():
|
|
||||||
self.qt_app.processEvents()
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
progress.hide()
|
|
||||||
|
|
||||||
if t_monitor.success:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
QtGui.QMessageBox.warning(None, self.tr("Error removing Qube!"),
|
|
||||||
self.tr("ERROR: {0}").format(
|
|
||||||
t_monitor.error_msg))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def do_remove_vm(vm, qubes_app, t_monitor):
|
|
||||||
try:
|
|
||||||
del qubes_app.domains[vm.name]
|
|
||||||
except exc.QubesException as ex:
|
|
||||||
t_monitor.set_error_msg(str(ex))
|
|
||||||
|
|
||||||
t_monitor.set_finished()
|
|
||||||
|
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
@QtCore.pyqtSlot(name='on_action_clonevm_triggered')
|
@QtCore.pyqtSlot(name='on_action_clonevm_triggered')
|
||||||
@ -760,12 +808,9 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
if not ok or clone_name == "":
|
if not ok or clone_name == "":
|
||||||
return
|
return
|
||||||
|
|
||||||
t_monitor = thread_monitor.ThreadMonitor()
|
self.thread = CloneVMThread(vm, self.qubes_app, clone_name)
|
||||||
thread = threading.Thread(target=self.do_clone_vm,
|
self.thread.start()
|
||||||
args=(vm, self.qubes_app,
|
return
|
||||||
clone_name, t_monitor))
|
|
||||||
thread.daemon = True
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
progress = QtGui.QProgressDialog(
|
progress = QtGui.QProgressDialog(
|
||||||
self.tr("Cloning Qube <b>{0}</b> to <b>{1}</b>...").format(
|
self.tr("Cloning Qube <b>{0}</b> to <b>{1}</b>...").format(
|
||||||
@ -777,31 +822,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
progress.setModal(True)
|
progress.setModal(True)
|
||||||
progress.show()
|
progress.show()
|
||||||
|
|
||||||
while not t_monitor.is_finished():
|
|
||||||
self.qt_app.processEvents()
|
|
||||||
time.sleep(0.2)
|
|
||||||
|
|
||||||
progress.hide()
|
|
||||||
|
|
||||||
if not t_monitor.success:
|
|
||||||
QtGui.QMessageBox.warning(
|
|
||||||
None,
|
|
||||||
self.tr("Error while cloning Qube"),
|
|
||||||
self.tr("Exception while cloning:<br>{0}").format(
|
|
||||||
t_monitor.error_msg))
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def do_clone_vm(src_vm, qubes_app, dst_name, t_monitor):
|
|
||||||
dst_vm = None
|
|
||||||
try:
|
|
||||||
dst_vm = qubes_app.clone_vm(src_vm, dst_name)
|
|
||||||
except exc.QubesException as ex:
|
|
||||||
t_monitor.set_error_msg(str(ex))
|
|
||||||
if dst_vm:
|
|
||||||
pass
|
|
||||||
t_monitor.set_finished()
|
|
||||||
|
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
@QtCore.pyqtSlot(name='on_action_resumevm_triggered')
|
@QtCore.pyqtSlot(name='on_action_resumevm_triggered')
|
||||||
def action_resumevm_triggered(self):
|
def action_resumevm_triggered(self):
|
||||||
@ -823,33 +843,18 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
def start_vm(self, vm):
|
def start_vm(self, vm):
|
||||||
if vm.is_running():
|
if vm.is_running():
|
||||||
return
|
return
|
||||||
t_monitor = thread_monitor.ThreadMonitor()
|
|
||||||
thread = threading.Thread(target=self.do_start_vm,
|
thread = StartVMThread(vm)
|
||||||
args=(vm, t_monitor))
|
self.threads_list.append(thread)
|
||||||
thread.daemon = True
|
self.connect(thread, QtCore.SIGNAL("show_error(QString, QString)"), self.show_error)
|
||||||
|
thread.finished.connect(self.clear_threads)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
while not t_monitor.is_finished():
|
def show_error(self, error, error_msg):
|
||||||
self.qt_app.processEvents()
|
QtGui.QMessageBox.warning(
|
||||||
time.sleep(0.1)
|
None,
|
||||||
|
self.tr(error),
|
||||||
if not t_monitor.success:
|
self.tr("ERROR: {0}").format(error_msg))
|
||||||
QtGui.QMessageBox.warning(
|
|
||||||
None,
|
|
||||||
self.tr("Error starting Qube!"),
|
|
||||||
self.tr("ERROR: {0}").format(t_monitor.error_msg))
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def do_start_vm(vm, t_monitor):
|
|
||||||
try:
|
|
||||||
vm.start()
|
|
||||||
except exc.QubesException as ex:
|
|
||||||
t_monitor.set_error_msg(str(ex))
|
|
||||||
t_monitor.set_finished()
|
|
||||||
return
|
|
||||||
|
|
||||||
t_monitor.set_finished()
|
|
||||||
|
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
@QtCore.pyqtSlot(name='on_action_startvm_tools_install_triggered')
|
@QtCore.pyqtSlot(name='on_action_startvm_tools_install_triggered')
|
||||||
@ -1014,55 +1019,12 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
if reply != QtGui.QMessageBox.Yes:
|
if reply != QtGui.QMessageBox.Yes:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.qt_app.processEvents()
|
thread = UpdateVMThread(vm)
|
||||||
|
self.threads_list.append(thread)
|
||||||
t_monitor = thread_monitor.ThreadMonitor()
|
self.connect(thread, QtCore.SIGNAL("show_error(QString, QString)"), self.show_error)
|
||||||
thread = threading.Thread(target=self.do_update_vm,
|
thread.finished.connect(self.clear_threads)
|
||||||
args=(vm, t_monitor))
|
|
||||||
thread.daemon = True
|
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
progress = QtGui.QProgressDialog(
|
|
||||||
self.tr(
|
|
||||||
"<b>{0}</b><br>Please wait for the updater to "
|
|
||||||
"launch...").format(vm.name), "", 0, 0)
|
|
||||||
progress.setWindowFlags(QtCore.Qt.Window |
|
|
||||||
QtCore.Qt.WindowTitleHint |
|
|
||||||
QtCore.Qt.CustomizeWindowHint)
|
|
||||||
progress.setCancelButton(None)
|
|
||||||
progress.setModal(True)
|
|
||||||
progress.show()
|
|
||||||
|
|
||||||
while not t_monitor.is_finished():
|
|
||||||
self.qt_app.processEvents()
|
|
||||||
time.sleep(0.2)
|
|
||||||
|
|
||||||
progress.hide()
|
|
||||||
|
|
||||||
if vm.qid != 0:
|
|
||||||
if not t_monitor.success:
|
|
||||||
QtGui.QMessageBox.warning(
|
|
||||||
None,
|
|
||||||
self.tr("Error on Qube update!"),
|
|
||||||
self.tr("ERROR: {0}").format(t_monitor.error_msg))
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def do_update_vm(vm, t_monitor):
|
|
||||||
try:
|
|
||||||
if vm.qid == 0:
|
|
||||||
subprocess.check_call(
|
|
||||||
["/usr/bin/qubes-dom0-update", "--clean", "--gui"])
|
|
||||||
else:
|
|
||||||
if not vm.is_running():
|
|
||||||
vm.start()
|
|
||||||
vm.run_service("qubes.InstallUpdatesGUI",
|
|
||||||
user="root", wait=False)
|
|
||||||
except (ChildProcessError, exc.QubesException) as ex:
|
|
||||||
t_monitor.set_error_msg(str(ex))
|
|
||||||
t_monitor.set_finished()
|
|
||||||
return
|
|
||||||
t_monitor.set_finished()
|
|
||||||
|
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
@QtCore.pyqtSlot(name='on_action_run_command_in_vm_triggered')
|
@QtCore.pyqtSlot(name='on_action_run_command_in_vm_triggered')
|
||||||
@ -1075,29 +1037,13 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
self.tr('Run command in <b>{}</b>:').format(vm.name))
|
self.tr('Run command in <b>{}</b>:').format(vm.name))
|
||||||
if not ok or command_to_run == "":
|
if not ok or command_to_run == "":
|
||||||
return
|
return
|
||||||
t_monitor = thread_monitor.ThreadMonitor()
|
|
||||||
thread = threading.Thread(target=self.do_run_command_in_vm, args=(
|
thread = RunCommandThread(vm, command_to_run)
|
||||||
vm, command_to_run, t_monitor))
|
self.threads_list.append(thread)
|
||||||
thread.daemon = True
|
self.connect(thread, QtCore.SIGNAL("show_error(QString, QString)"), self.show_error)
|
||||||
|
thread.finished.connect(self.clear_threads)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
while not t_monitor.is_finished():
|
|
||||||
self.qt_app.processEvents()
|
|
||||||
time.sleep(0.2)
|
|
||||||
|
|
||||||
if not t_monitor.success:
|
|
||||||
QtGui.QMessageBox.warning(
|
|
||||||
None, self.tr("Error while running command"),
|
|
||||||
self.tr("Exception while running command:<br>{0}").format(
|
|
||||||
t_monitor.error_msg))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def do_run_command_in_vm(vm, command_to_run, t_monitor):
|
|
||||||
try:
|
|
||||||
vm.run(command_to_run)
|
|
||||||
except (ChildProcessError, exc.QubesException) as ex:
|
|
||||||
t_monitor.set_error_msg(str(ex))
|
|
||||||
t_monitor.set_finished()
|
|
||||||
|
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
@QtCore.pyqtSlot(name='on_action_set_keyboard_layout_triggered')
|
@QtCore.pyqtSlot(name='on_action_set_keyboard_layout_triggered')
|
||||||
|
Loading…
Reference in New Issue
Block a user