diff --git a/mainwindow.ui b/mainwindow.ui
index 3c1cd34..6dd730b 100644
--- a/mainwindow.ui
+++ b/mainwindow.ui
@@ -810,6 +810,21 @@
Show/Hide internal VMs
+
+
+ false
+
+
+
+ :/resumevm.png:/resumevm.png
+
+
+ Start VM for Window Tools installation
+
+
+ Start VM for Window Tools installation
+
+
diff --git a/qubesmanager/main.py b/qubesmanager/main.py
index 15a3d42..7983e9e 100755
--- a/qubesmanager/main.py
+++ b/qubesmanager/main.py
@@ -39,6 +39,10 @@ from qubes.qubes import QubesVmLabels
from qubes.qubes import dry_run
from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesHost
+try:
+ from qubes.qubes import QubesHVm
+except ImportError:
+ pass
from qubes import qubes
from qubes import qubesutils
@@ -861,6 +865,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
self.context_menu.addAction(self.action_updatevm)
self.context_menu.addAction(self.action_run_command_in_vm)
self.context_menu.addAction(self.action_resumevm)
+ self.context_menu.addAction(self.action_startvm_tools_install)
self.context_menu.addAction(self.action_pausevm)
self.context_menu.addAction(self.action_shutdownvm)
self.context_menu.addAction(self.action_killvm)
@@ -1246,6 +1251,13 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
self.action_removevm.setEnabled(not vm.installed_by_rpm and not (vm.last_running))
self.action_clonevm.setEnabled(not (vm.last_running) and not vm.is_netvm())
self.action_resumevm.setEnabled(not vm.last_running)
+ try:
+ self.action_startvm_tools_install.setVisible(isinstance(vm,
+ QubesHVm))
+ except NameError:
+ # ignore non existing QubesHVm
+ pass
+ self.action_startvm_tools_install.setEnabled(not vm.last_running)
self.action_pausevm.setEnabled(vm.last_running and vm.qid != 0)
self.action_shutdownvm.setEnabled(vm.last_running and vm.qid != 0)
self.action_killvm.setEnabled((vm.last_running or vm.last_power_state == "Paused") and vm.qid != 0)
@@ -1258,6 +1270,8 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
else:
self.action_settings.setEnabled(False)
self.action_removevm.setEnabled(False)
+ self.action_startvm_tools_install.setVisible(False)
+ self.action_startvm_tools_install.setEnabled(False)
self.action_clonevm.setEnabled(False)
self.action_resumevm.setEnabled(False)
self.action_pausevm.setEnabled(False)
@@ -1489,6 +1503,46 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
thread_monitor.set_finished()
+ @pyqtSlot(name='on_action_startvm_tools_install_triggered')
+ def action_startvm_tools_install_triggered(self):
+ vm = self.get_selected_vm()
+ assert not vm.is_running()
+
+ thread_monitor = ThreadMonitor()
+ thread = threading.Thread (target=self.do_start_vm_tools_install,
+ args=(vm, thread_monitor))
+ thread.daemon = True
+ thread.start()
+
+ trayIcon.showMessage ("Starting '{0}'...".format(vm.name), msecs=3000)
+
+ while not thread_monitor.is_finished():
+ app.processEvents()
+ time.sleep (0.1)
+
+ if thread_monitor.success:
+ trayIcon.showMessage ("VM '{0}' has been started. Start Qubes "
+ "Tools installation from attached CD"
+ .format(vm.name), msecs=3000)
+ else:
+ trayIcon.showMessage ("Error starting VM '{0}': {1}".format(vm.name, thread_monitor.error_msg ), msecs=3000)
+ self.set_error(vm.qid, "Error starting VM: %s" % thread_monitor.error_msg)
+
+ def do_start_vm_tools_install(self, vm, thread_monitor):
+ prev_drive = vm.drive
+ try:
+ vm.verify_files()
+ vm.drive = 'cdrom:dom0:/usr/lib/qubes/qubes-windows-tools.iso'
+ xid = vm.start()
+ except Exception as ex:
+ thread_monitor.set_error_msg(str(ex))
+ thread_monitor.set_finished()
+ return
+ finally:
+ vm.drive = prev_drive
+
+ thread_monitor.set_finished()
+
@pyqtSlot(name='on_action_pausevm_triggered')
def action_pausevm_triggered(self):
vm = self.get_selected_vm()