Merge commit '7228a3968ef3c220ddf09eeb390bb467be4e5616'

* commit '7228a3968ef3c220ddf09eeb390bb467be4e5616':
  fwvm -> proxyvm once again
  Tray notify after comit template changes.
  Template changes commit confirmation
  Toggle manager window visibility on icon click
  Git ignores
  Delete AppVM after failed create only if it was (partially) created.
  Add firewall files to rpm
  Remove generated files (ui)
  Fix typo 'templete'
  Add UI python files to gitignore
  Add compiled python scripts to rpm
  Enable pause button
  Implement pause button
  Implement start button action
  Suport for commit template changes
This commit is contained in:
Tomasz Sterna 2011-03-14 20:14:34 +01:00
commit 52741c369a
7 changed files with 88 additions and 154 deletions

3
.gitignore vendored
View File

@ -1 +1,4 @@
*.pyc
*.pyo
*~
rpm/

View File

@ -1,2 +1,4 @@
qrc_resources.py
ui_newappvmdlg.py
ui_editfwrulesdlg.py
ui_newfwruledlg.py

View File

@ -260,7 +260,7 @@ class QubesFirewallRulesModel(QAbstractItemModel):
qvm_collection.unlock_db()
for vm in qvm_collection.values():
if vm.is_fwvm():
if vm.is_proxyvm():
vm.write_iptables_xenstore_entry()
def index(self, row, column, parent=QModelIndex()):

View File

@ -44,6 +44,8 @@ import subprocess
import time
import threading
qubes_guid_path = '/usr/bin/qubes_guid'
class QubesConfigFileWatcher(ProcessEvent):
def __init__ (self, update_func):
self.update_func = update_func
@ -73,7 +75,7 @@ class VmStatusIcon(QLabel):
icon = QIcon (":/dom0.png")
elif vm.is_appvm():
icon = QIcon (vm.label.icon_path)
elif vm.is_templete():
elif vm.is_template():
icon = QIcon (":/templatevm.png")
elif vm.is_netvm():
icon = QIcon (":/netvm.png")
@ -105,7 +107,7 @@ class VmInfoWidget (QWidget):
if vm.is_appvm() or vm.is_disposablevm():
label_tmpl = QLabel ("<i><font color=\"gray\">" + vm.template_vm.name + "</i></font>")
elif vm.is_templete():
elif vm.is_template():
label_tmpl = QLabel ("<i><font color=\"gray\">TemplateVM</i></font>")
elif vm.qid == 0:
label_tmpl = QLabel ("<i><font color=\"gray\">AdminVM</i></font>")
@ -371,8 +373,8 @@ class VmManagerWindow(QMainWindow):
self.action_shutdownvm = self.createAction ("Shutdown VM", slot=self.shutdown_vm,
icon="shutdownvm", tip="Shutdown a running VM")
self.action_updatevm = self.createAction ("Update VM", slot=None,
icon="updateable", tip="Update VM (only for 'updateable' VMs, e.g. templates)")
self.action_updatevm = self.createAction ("Commit VM changes", slot=self.update_vm,
icon="updateable", tip="Commit changes to template (only for 'updateable' template VMs); VM must be stopped")
self.action_showallvms = self.createAction ("Show/Hide Inactive VMs", slot=None, checkable=True,
icon="showallvms", tip="Show/Hide Inactive VMs")
@ -491,7 +493,7 @@ class VmManagerWindow(QMainWindow):
# Now, the templates...
for tvm in vms_list:
if tvm.is_templete():
if tvm.is_template():
vms_to_display.append (tvm)
label_list = QubesVmLabels.values()
@ -552,9 +554,10 @@ class VmManagerWindow(QMainWindow):
# Update available actions:
self.action_removevm.setEnabled(not vm.installed_by_rpm and not vm.is_running())
#self.action_resumevm.setEnabled(not vm.is_running())
#self.action_pausevm.setEnabled(vm.is_running() and vm.qid != 0)
self.action_resumevm.setEnabled(not vm.is_running())
self.action_pausevm.setEnabled(vm.is_running() and vm.qid != 0)
self.action_shutdownvm.setEnabled(vm.is_running() and vm.qid != 0)
self.action_updatevm.setEnabled(vm.is_updateable() and not vm.is_running())
self.action_editfwrules.setEnabled(vm.is_networked() and (vm.is_appvm() or vm.is_disposablevm()))
def get_minimum_table_width(self):
@ -587,7 +590,7 @@ class VmManagerWindow(QMainWindow):
dialog.vmlabel.insertItem(i, label.name)
dialog.vmlabel.setItemIcon (i, QIcon(label.icon_path))
template_vm_list = [vm for vm in self.qvm_collection.values() if vm.is_templete()]
template_vm_list = [vm for vm in self.qvm_collection.values() if vm.is_template()]
default_index = 0
for (i, vm) in enumerate(template_vm_list):
@ -633,6 +636,7 @@ class VmManagerWindow(QMainWindow):
def do_create_appvm (self, vmname, label, template_vm, thread_monitor):
vm = None
try:
self.qvm_collection.lock_db_for_writing()
self.qvm_collection.load()
@ -643,7 +647,8 @@ class VmManagerWindow(QMainWindow):
self.qvm_collection.save()
except Exception as ex:
thread_monitor.set_error_msg (str(ex))
vm.remove_from_disk()
if vm:
vm.remove_from_disk()
finally:
self.qvm_collection.unlock_db()
@ -664,8 +669,8 @@ class VmManagerWindow(QMainWindow):
self.qvm_collection.lock_db_for_reading()
self.qvm_collection.load()
self.qvm_collection.unlock_db()
if vm.is_templete():
if vm.is_template():
dependent_vms = self.qvm_collection.get_vms_based_on(vm.qid)
if len(dependent_vms) > 0:
QMessageBox.warning (None, "Warning!",
@ -710,7 +715,7 @@ class VmManagerWindow(QMainWindow):
self.qvm_collection.load()
#TODO: the following two conditions should really be checked by qvm_collection.pop() overload...
if vm.is_templete() and qvm_collection.default_template_qid == vm.qid:
if vm.is_template() and qvm_collection.default_template_qid == vm.qid:
qvm_collection.default_template_qid = None
if vm.is_netvm() and qvm_collection.default_netvm_qid == vm.qid:
qvm_collection.default_netvm_qid = None
@ -727,10 +732,29 @@ class VmManagerWindow(QMainWindow):
thread_monitor.set_finished()
def resume_vm(self):
pass
vm = self.get_selected_vm()
assert not vm.is_running()
try:
vm.verify_files()
xid = vm.start()
except (IOError, OSError, QubesException) as err:
QMessageBox.warning (None, "Error starting VM!", "ERROR: {0}".format(err))
return
retcode = subprocess.call ([qubes_guid_path, "-d", str(xid), "-c", vm.label.color, "-i", vm.label.icon, "-l", str(vm.label.index)])
if (retcode != 0):
QMessageBox.warning (None, "Error starting VM!", "ERROR: Cannot start qubes_guid!")
return
def pause_vm(self):
pass
vm = self.get_selected_vm()
assert vm.is_running()
try:
subprocess.check_call (["/usr/sbin/xm", "pause", vm.name])
except Exception as ex:
QMessageBox.warning (None, "Error pausing VM!", "ERROR: {0}".format(ex))
return
def shutdown_vm(self):
vm = self.get_selected_vm()
@ -754,6 +778,25 @@ class VmManagerWindow(QMainWindow):
self.shutdown_monitor[vm.qid] = VmShutdownMonitor (vm)
QTimer.singleShot (vm_shutdown_timeout, self.shutdown_monitor[vm.qid].check_if_vm_has_shutdown)
def update_vm(self):
vm = self.get_selected_vm()
assert not vm.is_running()
reply = QMessageBox.question(None, "VM Update Confirmation",
"Are you sure you want to commit template <b>'{0}'</b> changes?<br>"
"<small>AppVMs will see the changes after restart.</small>".format(vm.name),
QMessageBox.Yes | QMessageBox.Cancel)
app.processEvents()
if reply == QMessageBox.Yes:
try:
vm.commit_changes();
except Exception as ex:
QMessageBox.warning (None, "Error commiting changes!", "ERROR: {0}".format(ex))
return
trayIcon.showMessage ("Qubes Manager", "Changes to template '{0}' commited.".format(vm.name), msecs=3000)
def showcpuload(self):
self.__cpugraphs = self.action_showcpuload.isChecked()
self.update_table_columns()
@ -775,7 +818,7 @@ class VmManagerWindow(QMainWindow):
qvm_collection.unlock_db()
for vm in qvm_collection.values():
if vm.is_fwvm():
if vm.is_proxyvm():
error_file = "/local/domain/{0}/qubes_iptables_error".format(vm.get_xid())
error = subprocess.Popen(
@ -824,7 +867,7 @@ class QubesTrayIcon(QSystemTrayIcon):
# Handle the right click normally, i.e. display the context menu
return
else:
show_manager()
toggle_manager()
def addActions(self, target, actions):
for action in actions:
@ -854,6 +897,11 @@ class QubesTrayIcon(QSystemTrayIcon):
def show_manager():
manager_window.show()
def toggle_manager():
if manager_window.isVisible():
manager_window.hide()
else:
manager_window.show()
def exit_app():
notifier.stop()

View File

@ -1,85 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'editfwrulesdlg.ui'
#
# Created: Thu Mar 3 17:36:19 2011
# by: PyQt4 UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
class Ui_EditFwRulesDlg(object):
def setupUi(self, EditFwRulesDlg):
EditFwRulesDlg.setObjectName("EditFwRulesDlg")
EditFwRulesDlg.resize(500, 335)
self.verticalLayout_3 = QtGui.QVBoxLayout(EditFwRulesDlg)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.policyAllowRadioButton = QtGui.QRadioButton(EditFwRulesDlg)
self.policyAllowRadioButton.setObjectName("policyAllowRadioButton")
self.verticalLayout_3.addWidget(self.policyAllowRadioButton)
self.policyDenyRadioButton = QtGui.QRadioButton(EditFwRulesDlg)
self.policyDenyRadioButton.setObjectName("policyDenyRadioButton")
self.verticalLayout_3.addWidget(self.policyDenyRadioButton)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setSizeConstraint(QtGui.QLayout.SetMaximumSize)
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout_2 = QtGui.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.rulesTreeView = QtGui.QTreeView(EditFwRulesDlg)
self.rulesTreeView.setRootIsDecorated(False)
self.rulesTreeView.setUniformRowHeights(False)
self.rulesTreeView.setItemsExpandable(False)
self.rulesTreeView.setAllColumnsShowFocus(True)
self.rulesTreeView.setExpandsOnDoubleClick(True)
self.rulesTreeView.setObjectName("rulesTreeView")
self.rulesTreeView.header().setDefaultSectionSize(40)
self.rulesTreeView.header().setStretchLastSection(False)
self.verticalLayout_2.addWidget(self.rulesTreeView)
self.dnsCheckBox = QtGui.QCheckBox(EditFwRulesDlg)
self.dnsCheckBox.setChecked(True)
self.dnsCheckBox.setObjectName("dnsCheckBox")
self.verticalLayout_2.addWidget(self.dnsCheckBox)
self.horizontalLayout.addLayout(self.verticalLayout_2)
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.newRuleButton = QtGui.QPushButton(EditFwRulesDlg)
self.newRuleButton.setObjectName("newRuleButton")
self.verticalLayout.addWidget(self.newRuleButton)
self.editRuleButton = QtGui.QPushButton(EditFwRulesDlg)
self.editRuleButton.setObjectName("editRuleButton")
self.verticalLayout.addWidget(self.editRuleButton)
self.deleteRuleButton = QtGui.QPushButton(EditFwRulesDlg)
self.deleteRuleButton.setObjectName("deleteRuleButton")
self.verticalLayout.addWidget(self.deleteRuleButton)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.horizontalLayout.addLayout(self.verticalLayout)
self.verticalLayout_3.addLayout(self.horizontalLayout)
self.buttonBox = QtGui.QDialogButtonBox(EditFwRulesDlg)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout_3.addWidget(self.buttonBox)
self.retranslateUi(EditFwRulesDlg)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), EditFwRulesDlg.reject)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), EditFwRulesDlg.accept)
QtCore.QMetaObject.connectSlotsByName(EditFwRulesDlg)
EditFwRulesDlg.setTabOrder(self.policyAllowRadioButton, self.policyDenyRadioButton)
EditFwRulesDlg.setTabOrder(self.policyDenyRadioButton, self.dnsCheckBox)
EditFwRulesDlg.setTabOrder(self.dnsCheckBox, self.rulesTreeView)
EditFwRulesDlg.setTabOrder(self.rulesTreeView, self.newRuleButton)
EditFwRulesDlg.setTabOrder(self.newRuleButton, self.editRuleButton)
EditFwRulesDlg.setTabOrder(self.editRuleButton, self.deleteRuleButton)
EditFwRulesDlg.setTabOrder(self.deleteRuleButton, self.buttonBox)
def retranslateUi(self, EditFwRulesDlg):
EditFwRulesDlg.setWindowTitle(QtGui.QApplication.translate("EditFwRulesDlg", "VM Firewall", None, QtGui.QApplication.UnicodeUTF8))
self.policyAllowRadioButton.setText(QtGui.QApplication.translate("EditFwRulesDlg", "Allow network access except...", None, QtGui.QApplication.UnicodeUTF8))
self.policyDenyRadioButton.setText(QtGui.QApplication.translate("EditFwRulesDlg", "Deny network access except...", None, QtGui.QApplication.UnicodeUTF8))
self.dnsCheckBox.setText(QtGui.QApplication.translate("EditFwRulesDlg", "Allow DNS queries", None, QtGui.QApplication.UnicodeUTF8))
self.newRuleButton.setText(QtGui.QApplication.translate("EditFwRulesDlg", "&New", None, QtGui.QApplication.UnicodeUTF8))
self.editRuleButton.setText(QtGui.QApplication.translate("EditFwRulesDlg", "&Edit", None, QtGui.QApplication.UnicodeUTF8))
self.deleteRuleButton.setText(QtGui.QApplication.translate("EditFwRulesDlg", "&Delete", None, QtGui.QApplication.UnicodeUTF8))

View File

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'newfwruledlg.ui'
#
# Created: Thu Mar 3 17:36:19 2011
# by: PyQt4 UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
class Ui_NewFwRuleDlg(object):
def setupUi(self, NewFwRuleDlg):
NewFwRuleDlg.setObjectName("NewFwRuleDlg")
NewFwRuleDlg.setWindowModality(QtCore.Qt.NonModal)
NewFwRuleDlg.resize(381, 121)
NewFwRuleDlg.setModal(True)
self.buttonBox = QtGui.QDialogButtonBox(NewFwRuleDlg)
self.buttonBox.setGeometry(QtCore.QRect(10, 80, 361, 32))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.label_2 = QtGui.QLabel(NewFwRuleDlg)
self.label_2.setGeometry(QtCore.QRect(10, 14, 62, 17))
self.label_2.setObjectName("label_2")
self.addressEdit = QtGui.QLineEdit(NewFwRuleDlg)
self.addressEdit.setGeometry(QtCore.QRect(70, 10, 301, 27))
self.addressEdit.setObjectName("addressEdit")
self.label_4 = QtGui.QLabel(NewFwRuleDlg)
self.label_4.setGeometry(QtCore.QRect(10, 44, 61, 21))
self.label_4.setObjectName("label_4")
self.serviceComboBox = QtGui.QComboBox(NewFwRuleDlg)
self.serviceComboBox.setGeometry(QtCore.QRect(70, 40, 301, 27))
self.serviceComboBox.setEditable(True)
self.serviceComboBox.setObjectName("serviceComboBox")
self.retranslateUi(NewFwRuleDlg)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), NewFwRuleDlg.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), NewFwRuleDlg.reject)
QtCore.QMetaObject.connectSlotsByName(NewFwRuleDlg)
NewFwRuleDlg.setTabOrder(self.addressEdit, self.serviceComboBox)
NewFwRuleDlg.setTabOrder(self.serviceComboBox, self.buttonBox)
def retranslateUi(self, NewFwRuleDlg):
NewFwRuleDlg.setWindowTitle(QtGui.QApplication.translate("NewFwRuleDlg", "New Address", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("NewFwRuleDlg", "Address", None, QtGui.QApplication.UnicodeUTF8))
self.label_4.setText(QtGui.QApplication.translate("NewFwRuleDlg", "Service", None, QtGui.QApplication.UnicodeUTF8))

View File

@ -22,16 +22,21 @@ The Graphical Qubes VM Manager.
%build
make res
python -m compileall qubesmanager
python -O -m compileall qubesmanager
%install
mkdir -p $RPM_BUILD_ROOT/usr/bin/
cp qubes-manager $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager/
cp qubesmanager/main.py $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/qrc_resources.py $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/__init__.py $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_newappvmdlg.py $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/main.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/firewall.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/qrc_resources.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/__init__.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_newappvmdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_newfwruledlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_editfwrulesdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
mkdir -p $RPM_BUILD_ROOT/usr/share/applications
cp qubes-manager.desktop $RPM_BUILD_ROOT/usr/share/applications
@ -56,12 +61,21 @@ rm -rf $RPM_BUILD_ROOT
%{python_sitearch}/qubesmanager/main.py
%{python_sitearch}/qubesmanager/main.pyc
%{python_sitearch}/qubesmanager/main.pyo
%{python_sitearch}/qubesmanager/firewall.py
%{python_sitearch}/qubesmanager/firewall.pyc
%{python_sitearch}/qubesmanager/firewall.pyo
%{python_sitearch}/qubesmanager/qrc_resources.py
%{python_sitearch}/qubesmanager/qrc_resources.pyc
%{python_sitearch}/qubesmanager/qrc_resources.pyo
%{python_sitearch}/qubesmanager/ui_newappvmdlg.py
%{python_sitearch}/qubesmanager/ui_newappvmdlg.pyc
%{python_sitearch}/qubesmanager/ui_newappvmdlg.pyo
%{python_sitearch}/qubesmanager/ui_newfwruledlg.py
%{python_sitearch}/qubesmanager/ui_newfwruledlg.pyc
%{python_sitearch}/qubesmanager/ui_newfwruledlg.pyo
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.py
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.pyc
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.pyo
/usr/share/applications/qubes-manager.desktop