Merge branch 'master' of git://git.qubes-os.org/aga/qubes-manager

This commit is contained in:
Marek Marczykowski 2012-02-23 00:03:09 +01:00
commit 6213fab474
34 changed files with 4278 additions and 710 deletions

View File

@ -13,10 +13,16 @@ rpms:
rpm --addsign $(RPMS_DIR)/x86_64/qubes-manager*$(VERSION)*.rpm
res:
pyrcc4 -o qubesmanager/qrc_resources.py resources.qrc
pyrcc4 -o qubesmanager/resources_rc.py resources.qrc
pyuic4 -o qubesmanager/ui_mainwindow.py mainwindow.ui
pyuic4 -o qubesmanager/ui_newappvmdlg.py newappvmdlg.ui
pyuic4 -o qubesmanager/ui_editfwrulesdlg.py editfwrulesdlg.ui
pyuic4 -o qubesmanager/ui_newfwruledlg.py newfwruledlg.ui
pyuic4 -o qubesmanager/ui_multiselectwidget.py multiselectwidget.ui
pyuic4 -o qubesmanager/ui_settingsdlg.py settingsdlg.ui
pyuic4 -o qubesmanager/ui_restoredlg.py restoredlg.ui
pyuic4 -o qubesmanager/ui_backupdlg.py backupdlg.ui
pyuic4 -o qubesmanager/ui_globalsettingsdlg.py globalsettingsdlg.ui
update-repo-current:
ln -f $(RPMS_DIR)/x86_64/qubes-manager-*$(VERSION)*.rpm ../yum/current-release/current/dom0/rpm/

196
backupdlg.ui Normal file
View File

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Backup</class>
<widget class="QWizard" name="Backup">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>399</height>
</rect>
</property>
<property name="windowTitle">
<string>Qubes Backup VMs</string>
</property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<property name="options">
<set>QWizard::NoBackButtonOnLastPage|QWizard::NoBackButtonOnStartPage</set>
</property>
<widget class="QWizardPage" name="select_vms_page">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>Select VMs to backup:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="select_dir_page">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Backup destination directory</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Device:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="dev_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>dev1</string>
</property>
</item>
<item>
<property name="text">
<string>longdeviceblablabla</string>
</property>
</item>
<item>
<property name="text">
<string>dev2</string>
</property>
</item>
<item>
<property name="text">
<string>dev3</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Backup directory:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="dir_line_edit"/>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="select_path_button">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="confirm_page">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_6">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>You're about to perform the following actions:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="textEdit">
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;br /&gt;A lot of info&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>To continue press Next. </string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="commit_page">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_8">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>Backup in progress...</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progress_bar">
<property name="value">
<number>24</number>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

224
globalsettingsdlg.ui Normal file
View File

@ -0,0 +1,224 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GlobalSettings</class>
<widget class="QDialog" name="GlobalSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>678</width>
<height>288</height>
</rect>
</property>
<property name="windowTitle">
<string>Qubes Global Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>System defaults</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>UpdateVM:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="updateVMcombo"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>ClockVM:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="clockVMcombo"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Default netVM:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="defaultNetVMcombo"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Default template:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="defaultTemplateVMCombo"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Default memory settings</string>
</property>
<widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>11</x>
<y>26</y>
<width>134</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Minimal VM's memory:</string>
</property>
</widget>
<widget class="QLabel" name="label_7">
<property name="geometry">
<rect>
<x>11</x>
<y>57</y>
<width>139</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>dom0 memory margin:</string>
</property>
</widget>
<widget class="QSpinBox" name="minVMmem">
<property name="geometry">
<rect>
<x>156</x>
<y>26</y>
<width>121</width>
<height>25</height>
</rect>
</property>
<property name="suffix">
<string> MB</string>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
</widget>
<widget class="QSpinBox" name="dom0memMargin">
<property name="geometry">
<rect>
<x>156</x>
<y>57</y>
<width>121</width>
<height>25</height>
</rect>
</property>
<property name="suffix">
<string> MB</string>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="singleStep">
<number>50</number>
</property>
</widget>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Kernel</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Default kernel:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBox_5"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>GlobalSettings</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>GlobalSettings</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

BIN
icons/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
icons/appsprefs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
icons/edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
icons/flag-blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
icons/flag-green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
icons/flag-red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
icons/flag-yellow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
icons/mount.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
icons/newfirewall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
icons/on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
icons/pencil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
icons/redfirewall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
icons/redfirewall2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
icons/remove.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

534
mainwindow.ui Normal file
View File

@ -0,0 +1,534 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VmManagerWindow</class>
<widget class="QMainWindow" name="VmManagerWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>821</width>
<height>600</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="windowTitle">
<string>Qubes VM Manager</string>
</property>
<property name="windowIcon">
<iconset resource="resources.qrc">
<normaloff>:/qubes.png</normaloff>:/qubes.png</iconset>
</property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<widget class="QWidget" name="centralwidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QTableWidget" name="table">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>200</width>
<height>30</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<property name="gridStyle">
<enum>Qt::NoPen</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<property name="rowCount">
<number>4</number>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>150</number>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>150</number>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>Nowy wiersz</string>
</property>
</row>
<row/>
<row/>
<row/>
<column>
<property name="text">
<string>Name</string>
</property>
<property name="toolTip">
<string>VM name</string>
</property>
</column>
<column>
<property name="text">
<string>Upd</string>
</property>
<property name="toolTip">
<string>Update info</string>
</property>
</column>
<column>
<property name="text">
<string>Template</string>
</property>
<property name="toolTip">
<string>VM's template</string>
</property>
</column>
<column>
<property name="text">
<string>NetVM</string>
</property>
<property name="toolTip">
<string>VM's netVM</string>
</property>
</column>
<column>
<property name="text">
<string>CPU</string>
</property>
</column>
<column>
<property name="text">
<string>CPU Graph</string>
</property>
<property name="toolTip">
<string>CPU usage graph</string>
</property>
</column>
<column>
<property name="text">
<string>MEM</string>
</property>
</column>
<column>
<property name="text">
<string>MEM Graph</string>
</property>
<property name="toolTip">
<string>Memory usage graph</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>821</width>
<height>23</height>
</rect>
</property>
<widget class="QMenu" name="menuOptions">
<property name="title">
<string>Options</string>
</property>
<addaction name="action_global_settings"/>
<addaction name="action_backup"/>
<addaction name="action_restore"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
<addaction name="actionUpd"/>
<addaction name="actionTemplate"/>
<addaction name="actionNetVM"/>
<addaction name="actionCPU"/>
<addaction name="actionCPU_Graph"/>
<addaction name="actionMEM"/>
<addaction name="actionMEM_Graph"/>
</widget>
<addaction name="menuOptions"/>
<addaction name="menuView"/>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="allowedAreas">
<set>Qt::BottomToolBarArea|Qt::TopToolBarArea</set>
</property>
<property name="floatable">
<bool>false</bool>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="action_createvm"/>
<addaction name="action_removevm"/>
<addaction name="separator"/>
<addaction name="action_resumevm"/>
<addaction name="action_pausevm"/>
<addaction name="action_shutdownvm"/>
<addaction name="separator"/>
<addaction name="action_settings"/>
<addaction name="action_editfwrules"/>
<addaction name="action_appmenus"/>
<addaction name="action_updatevm"/>
<addaction name="separator"/>
<addaction name="action_showallvms"/>
</widget>
<action name="action_createvm">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/createvm.png</normaloff>:/createvm.png</iconset>
</property>
<property name="text">
<string>Create AppVM</string>
</property>
<property name="toolTip">
<string>Create a new AppVM</string>
</property>
</action>
<action name="action_removevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/removevm.png</normaloff>:/removevm.png</iconset>
</property>
<property name="text">
<string>remove AppVM</string>
</property>
<property name="toolTip">
<string>Remove an existing AppVM (must be stopped first)</string>
</property>
</action>
<action name="action_resumevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/resumevm.png</normaloff>:/resumevm.png</iconset>
</property>
<property name="text">
<string>Start/Resume VM</string>
</property>
<property name="toolTip">
<string>Start/Resume a VM</string>
</property>
</action>
<action name="action_pausevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/pausevm.png</normaloff>:/pausevm.png</iconset>
</property>
<property name="text">
<string>Pause VM</string>
</property>
<property name="toolTip">
<string>Pause a running VM</string>
</property>
</action>
<action name="action_shutdownvm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/shutdownvm.png</normaloff>:/shutdownvm.png</iconset>
</property>
<property name="text">
<string>Shutdown VM</string>
</property>
<property name="toolTip">
<string>Shutdown a running VM</string>
</property>
</action>
<action name="action_appmenus">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/appsprefs.png</normaloff>:/appsprefs.png</iconset>
</property>
<property name="text">
<string>Select VM applications</string>
</property>
<property name="toolTip">
<string>Select applications present in menu for this VM</string>
</property>
</action>
<action name="action_updatevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/updateable.png</normaloff>:/updateable.png</iconset>
</property>
<property name="text">
<string>Update VM</string>
</property>
<property name="toolTip">
<string>Update VM system</string>
</property>
</action>
<action name="action_showallvms">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/showallvms.png</normaloff>
<selectedoff>:/showallvms.png</selectedoff>:/showallvms.png</iconset>
</property>
<property name="text">
<string>Show/Hide inactive VMs</string>
</property>
<property name="toolTip">
<string>Show/Hide inactive VMs</string>
</property>
</action>
<action name="action_editfwrules">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/redfirewall.png</normaloff>:/redfirewall.png</iconset>
</property>
<property name="text">
<string>Edit VM Firewall rules</string>
</property>
<property name="toolTip">
<string>Edit VM Firewall rules</string>
</property>
</action>
<action name="action_showgraphs">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/showcpuload.png</normaloff>:/showcpuload.png</iconset>
</property>
<property name="text">
<string>Show graphs</string>
</property>
<property name="toolTip">
<string>Show Graphs</string>
</property>
</action>
<action name="actionOptions">
<property name="text">
<string>Options</string>
</property>
</action>
<action name="actionView">
<property name="text">
<string>View</string>
</property>
</action>
<action name="actionCPU">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>CPU</string>
</property>
</action>
<action name="actionCPU_Graph">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>CPU Graph</string>
</property>
</action>
<action name="actionMEM">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>MEM</string>
</property>
</action>
<action name="actionMEM_Graph">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>MEM Graph</string>
</property>
</action>
<action name="actionTemplate">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Template</string>
</property>
</action>
<action name="actionNetVM">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>NetVM</string>
</property>
</action>
<action name="action_settings">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/root.png</normaloff>:/root.png</iconset>
</property>
<property name="text">
<string>Settings</string>
</property>
<property name="toolTip">
<string>VM Settings</string>
</property>
</action>
<action name="action_restore">
<property name="text">
<string>Restore VMs from backup</string>
</property>
</action>
<action name="action_backup">
<property name="text">
<string>Backup VMs</string>
</property>
</action>
<action name="action_global_settings">
<property name="text">
<string>Global settings</string>
</property>
</action>
<action name="actionUpd">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Upd</string>
</property>
</action>
</widget>
<resources>
<include location="resources.qrc"/>
</resources>
<connections/>
</ui>

193
multiselectwidget.ui Normal file
View File

@ -0,0 +1,193 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MultiSelectWidget</class>
<widget class="QWidget" name="MultiSelectWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>602</width>
<height>459</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Available</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="available_list"/>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="add_all_button">
<property name="text">
<string>&gt;&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="add_selected_button">
<property name="text">
<string>&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="remove_selected_button">
<property name="text">
<string>&lt;</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="remove_all_button">
<property name="text">
<string>&lt;&lt;</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Selected</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="selected_list"/>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -33,235 +33,87 @@ from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesHost
from qubes.qubes import qrexec_client_path
import qubesmanager.qrc_resources
import qubesmanager.resources_rc
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
import subprocess
import time
import threading
from operator import itemgetter
from thread_monitor import *
from multiselectwidget import *
whitelisted_filename = 'whitelisted-appmenus.list'
class AppRowInTable(object):
def __init__(self, filename, name, row_no, table):
class AppListWidgetItem(QListWidgetItem):
def __init__(self, name, filename, parent = None):
super(AppListWidgetItem, self).__init__(name, parent)
self.filename = filename
self.row_no = row_no
table.setRowHeight (row_no, AppmenuSelectWindow.row_height)
self.name_widget = QTableWidgetItem(name)
self.name_widget.setFlags (Qt.ItemIsSelectable | Qt.ItemIsEnabled )
table.setItem(row_no, 0, self.name_widget)
self.appvm_widget = QCheckBox()
table.setCellWidget(row_no, 1, self.appvm_widget)
class ThreadMonitor(QObject):
def __init__(self):
self.success = True
self.error_msg = None
self.event_finished = threading.Event()
def set_error_msg(self, error_msg):
self.success = False
self.error_msg = error_msg
self.set_finished()
def is_finished(self):
return self.event_finished.is_set()
def set_finished(self):
self.event_finished.set()
class AppmenuSelectWindow(QDialog):
row_height = 20
def __init__(self, vm, parent=None):
super(AppmenuSelectWindow, self).__init__(parent)
self.gridLayout = QGridLayout(self)
self.buttonBox = QDialogButtonBox(self)
self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
self.connect(self.buttonBox, SIGNAL("accepted()"), self.save_and_apply)
self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject)
self.table = QTableWidget(self)
self.table.clear()
self.table.setColumnCount(2)
self.table.setColumnWidth (0, 200)
self.table.setColumnWidth (1, 40)
self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
self.table.horizontalHeader().setResizeMode(1, QHeaderView.Fixed)
self.table.setAlternatingRowColors(True)
self.table.verticalHeader().hide()
self.table.horizontalHeader().show()
self.table.setGridStyle(Qt.NoPen)
self.table.setSortingEnabled(True)
self.table.setSelectionBehavior(QTableWidget.SelectRows)
self.table.setSelectionMode(QTableWidget.SingleSelection)
self.gridLayout.addWidget(self.table, 0, 0, 1, 1)
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1)
class AppmenuSelectManager:
def __init__(self, vm, apps_multiselect, parent=None):
self.app_list = apps_multiselect # this is a multiselect wiget
self.vm = vm
if self.vm.template_vm:
self.source_vm = self.vm.template_vm
else:
self.source_vm = self.vm
self.setWindowTitle("Qubes Appmenus for %s" % vm.name)
self.resize(250,500)
self.fill_table()
self.load_list_of_selected()
self.fill_apps_list()
def reject(self):
self.done(0)
def addActions(self, target, actions):
for action in actions:
if action is None:
target.addSeparator()
else:
target.addAction(action)
def createAction(self, text, slot=None, shortcut=None, icon=None,
tip=None, checkable=False, signal="triggered()"):
action = QAction(text, self)
if icon is not None:
action.setIcon(QIcon(":/%s.png" % icon))
if shortcut is not None:
action.setShortcut(shortcut)
if tip is not None:
action.setToolTip(tip)
action.setStatusTip(tip)
if slot is not None:
self.connect(action, SIGNAL(signal), slot)
if checkable:
action.setCheckable(True)
return action
def fill_table(self):
def fill_apps_list(self):
template_dir = self.source_vm.appmenus_templates_dir
template_file_list = os.listdir(template_dir)
self.table.clear()
self.table.setHorizontalHeaderLabels(['Name', 'VM'])
self.table.setRowCount(len(template_file_list))
whitelisted = []
if os.path.exists(self.vm.dir_path + '/' + whitelisted_filename):
f = open(self.vm.dir_path + '/' + whitelisted_filename, 'r')
whitelisted = [item.strip() for item in f]
f.close()
row_no = 0
appmenus = []
self.app_list.clear()
available_appmenus = []
for template_file in template_file_list:
desktop_template = open(template_dir + '/' + template_file, 'r')
for line in desktop_template:
if line.startswith("Name=%VMNAME%: "):
desktop_name = line.partition('Name=%VMNAME%: ')[2].strip()
row = AppRowInTable (template_file, desktop_name, row_no, self.table)
appmenus.append(row)
row_no += 1
available_appmenus.append( (template_file, desktop_name) )
break
desktop_template.close()
self.table.setRowCount(row_no)
self.appmenus = appmenus
self.table.sortItems(0)
whitelisted_appmenus = [a for a in available_appmenus if a[0] in whitelisted]
available_appmenus = [a for a in available_appmenus if a[0] not in whitelisted]
for a in available_appmenus:
self.app_list.available_list.addItem( AppListWidgetItem(a[1], a[0]))
def load_list_of_selected(self):
if not os.path.exists(self.vm.dir_path + '/' + whitelisted_filename):
# select none
for row in self.appmenus:
row.appvm_widget.setCheckState(Qt.Unchecked)
return
f = open(self.vm.dir_path + '/' + whitelisted_filename, 'r')
whitelisted = [item.strip() for item in f]
f.close()
for row in self.appmenus:
if row.filename in whitelisted:
row.appvm_widget.setCheckState(Qt.Checked)
else:
row.appvm_widget.setCheckState(Qt.Unchecked)
for a in whitelisted_appmenus:
self.app_list.selected_list.addItem( AppListWidgetItem(a[1], a[0]))
self.app_list.available_list.sortItems()
self.app_list.selected_list.sortItems()
def save_list_of_selected(self):
whitelisted = open(self.vm.dir_path + '/' + whitelisted_filename, 'w')
for row in self.appmenus:
if row.appvm_widget.checkState() == Qt.Checked:
whitelisted.write(row.filename + '\n')
whitelisted.close()
for i in range(self.app_list.selected_list.count()):
item = self.app_list.selected_list.item(i)
whitelisted.write(item.filename + '\n')
whitelisted.close()
def save_and_apply(self):
def save_appmenu_select_changes(self):
self.save_list_of_selected()
subprocess.check_call([qubes_appmenu_remove_cmd, self.vm.name])
subprocess.check_call([qubes_appmenu_create_cmd, self.source_vm.appmenus_templates_dir, self.vm.name])
self.done(0)
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception( exc_type, exc_value, exc_traceback ):
import sys
import os.path
import traceback
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
filename = os.path.basename( filename )
error = "%s: %s" % ( exc_type.__name__, exc_value )
QMessageBox.critical(None, "Houston, we have a problem...",
"Whoops. A critical error has occured. This is most likely a bug "
"in Qubes Appmenu Select application.<br><br>"
"<b><i>%s</i></b>" % error +
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% ( line, filename ))
#sys.exit(1)
def main():
global qubes_host
qubes_host = QubesHost()
global app
app = QApplication(sys.argv)
app.setOrganizationName("The Qubes Project")
app.setOrganizationDomain("http://qubes-os.org")
app.setApplicationName("Qubes Appmenu Select")
app.setWindowIcon(QIcon(":/qubes.png"))
sys.excepthook = handle_exception
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = None
if len(sys.argv) > 1:
vm = qvm_collection.get_vm_by_name(sys.argv[1])
if vm is None or vm.qid not in qvm_collection:
QMessageBox.critical(None, "Qubes Appmenu Select Error",
"A VM with the name '{0}' does not exist in the system.".format(sys.argv[1]))
sys.exit(1)
else:
vms_list = [vm.name for vm in qvm_collection.values() if (vm.is_appvm() or vm.is_template())]
vmname = QInputDialog.getItem(None, "Select VM", "Select VM:", vms_list, editable = False)
if not vmname[1]:
sys.exit(1)
vm = qvm_collection.get_vm_by_name(vmname[0])
global manager_window
select_window = AppmenuSelectWindow(vm)
select_window.show()
app.exec_()
app.exit()

239
qubesmanager/backup.py Normal file
View File

@ -0,0 +1,239 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
# Copyright (C) 2012 Marek Marczykowski <marmarek@mimuw.edu.pl>
#
# 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 QubesException
from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesHost
from qubes import qubesutils
import qubesmanager.resources_rc
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
import subprocess
import time
from thread_monitor import *
from operator import itemgetter
from datetime import datetime
from string import replace
from ui_backupdlg import *
from multiselectwidget import *
from backup_utils import *
class BackupVMsWindow(Ui_Backup, QWizard):
__pyqtSignals__ = ("backup_progress(int)",)
excluded = []
to_backup = []
def __init__(self, app, qvm_collection, blk_manager, parent=None):
super(BackupVMsWindow, self).__init__(parent)
self.app = app
self.qvm_collection = qvm_collection
self.blk_manager = blk_manager
self.dev_mount_path = None
self.backup_dir = None
self.func_output = []
for vm in self.qvm_collection.values():
if vm.qid == 0:
self.vm = vm
break;
assert self.vm != None
self.setupUi(self)
self.dir_line_edit.setReadOnly(True)
self.select_vms_widget = MultiSelectWidget(self)
self.verticalLayout.insertWidget(1, self.select_vms_widget)
self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed)
self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated)
self.connect(self, SIGNAL("backup_progress(int)"), self.progress_bar.setValue)
self.select_vms_page.isComplete = self.has_selected_vms
self.select_dir_page.isComplete = self.has_selected_dir
#FIXME
#this causes to run isComplete() twice, I don't know why
self.select_vms_page.connect(self.select_vms_widget, SIGNAL("selected_changed()"), SIGNAL("completeChanged()"))
self.__fill_vms_list__()
fill_devs_list(self)
def __fill_vms_list__(self):
for vm in self.qvm_collection.values():
if vm.is_running() and vm.qid != 0:
self.excluded.append(vm.name)
continue
if vm.is_appvm() and vm.internal:
self.excluded.append(vm.name)
continue
if vm.is_template() and vm.installed_by_rpm:
self.excluded.append(vm.name)
continue
self.to_backup.append(vm.name)
self.select_vms_widget.available_list.addItem(vm.name)
def dev_combobox_activated(self, idx):
dev_combobox_activated(self, idx)
@pyqtSlot(name='on_select_path_button_clicked')
def select_path_button_clicked(self):
select_path_button_clicked(self)
def validateCurrentPage(self):
if self.currentPage() is self.select_vms_page:
for i in range(self.select_vms_widget.available_list.count()):
vmname = self.select_vms_widget.available_list.item(i).text()
self.excluded.append(vmname)
return True
def gather_output(self, s):
self.func_output.append(s)
def update_progress_bar(self, value):
self.emit(SIGNAL("backup_progress(int)"), value)
def __do_backup__(self, thread_monitor):
msg = []
try:
qubesutils.backup_do(str(self.backup_dir), self.files_to_backup, self.update_progress_bar)
#simulate_long_lasting_proces(10, self.update_progress_bar)
except Exception as ex:
msg.append(str(ex))
if len(msg) > 0 :
thread_monitor.set_error_msg('\n'.join(msg))
thread_monitor.set_finished()
def current_page_changed(self, id):
if self.currentPage() is self.confirm_page:
del self.func_output[:]
self.files_to_backup = qubesutils.backup_prepare(str(self.backup_dir), exclude_list = self.excluded, print_callback = self.gather_output)
self.textEdit.setReadOnly(True)
self.textEdit.setFontFamily("Monospace")
self.textEdit.setText("\n".join(self.func_output))
elif self.currentPage() is self.commit_page:
self.button(self.CancelButton).setDisabled(True)
self.button(self.FinishButton).setDisabled(True)
self.thread_monitor = ThreadMonitor()
thread = threading.Thread (target= self.__do_backup__ , args=(self.thread_monitor,))
thread.daemon = True
thread.start()
while not self.thread_monitor.is_finished():
self.app.processEvents()
time.sleep (0.1)
if not self.thread_monitor.success:
QMessageBox.warning (None, "Backup error!", "ERROR: {1}".format(self.vm.name, self.thread_monitor.error_msg))
umount_device(self.dev_mount_path)
self.button(self.FinishButton).setEnabled(True)
def has_selected_vms(self):
return self.select_vms_widget.selected_list.count() > 0
def has_selected_dir(self):
return self.backup_dir != None
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception( exc_type, exc_value, exc_traceback ):
import sys
import os.path
import traceback
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
filename = os.path.basename( filename )
error = "%s: %s" % ( exc_type.__name__, exc_value )
QMessageBox.critical(None, "Houston, we have a problem...",
"Whoops. A critical error has occured. This is most likely a bug "
"in Qubes Restore VMs application.<br><br>"
"<b><i>%s</i></b>" % error +
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% ( line, filename ))
def main():
global qubes_host
qubes_host = QubesHost()
global app
app = QApplication(sys.argv)
app.setOrganizationName("The Qubes Project")
app.setOrganizationDomain("http://qubes-os.org")
app.setApplicationName("Qubes Backup VMs")
sys.excepthook = handle_exception
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
global backup_window
backup_window = BackupVMsWindow()
backup_window.show()
app.exec_()
app.exit()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,159 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
#
# 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 pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
import subprocess
import time
from thread_monitor import *
from datetime import datetime
from string import replace
def check_if_mounted(dev_path):
mounts_file = open("/proc/mounts")
for m in list(mounts_file):
if m.startswith(dev_path):
return m.split(" ")[1]
return None
def mount_device(dev_path):
try:
mount_dir_name = "backup" + replace(str(datetime.now()),' ', '-').split(".")[0]
pmount_cmd = ["pmount", dev_path, mount_dir_name]
res = subprocess.check_call(pmount_cmd)
except Exception as ex:
QMessageBox.warning (None, "Error mounting selected device!", "ERROR: {0}".format(ex))
return None
if res == 0:
dev_mount_path = "/media/"+mount_dir_name
return dev_mount_path
return None
def umount_device(dev_mount_path):
try:
pumount_cmd = ["pumount", dev_mount_path]
res = subprocess.check_call(pumount_cmd)
if res == 0:
dev_mount_path = None
except Exception as ex:
QMessageBox.warning (None, "Could not unmount backup device!", "ERROR: {0}".format(ex))
return dev_mount_path
def fill_devs_list(dialog):
dialog.dev_combobox.clear()
dialog.dev_combobox.addItem("None")
for a in dialog.blk_manager.attached_devs:
if dialog.blk_manager.attached_devs[a]['attached_to']['vm'] == dialog.vm.name :
att = a + " " + unicode(dialog.blk_manager.attached_devs[a]['size']) + " " + dialog.blk_manager.attached_devs[a]['desc']
dialog.dev_combobox.addItem(att, QVariant(a))
for a in dialog.blk_manager.free_devs:
att = a + " " + unicode(dialog.blk_manager.free_devs[a]['size']) + " " + dialog.blk_manager.free_devs[a]['desc']
dialog.dev_combobox.addItem(att, QVariant(a))
dialog.dev_combobox.setCurrentIndex(0) #current selected is null ""
dialog.prev_dev_idx = 0
dialog.dir_line_edit.clear()
dialog.dir_line_edit.setEnabled(False)
dialog.select_path_button.setEnabled(False)
def enable_dir_line_edit(dialog, boolean):
dialog.dir_line_edit.setEnabled(boolean)
dialog.select_path_button.setEnabled(boolean)
def dev_combobox_activated(dialog, idx):
if idx == dialog.prev_dev_idx: #nothing has changed
return
#there was a change
dialog.dir_line_edit.setText("")
dialog.backup_dir = None
if dialog.dev_mount_path != None:
dialog.dev_mount_path = umount_device(dialog.dev_mount_path)
if dialog_dev_mount_path != None:
dialog.dev_combobox.setCurrentIndex(dialog.prev_dev_idx)
return
enable_dir_line_edit(dialog, False)
if dialog.dev_combobox.currentText() != "None": #An existing device chosen
dev_name = str(dialog.dev_combobox.itemData(idx).toString())
if dev_name in dialog.blk_manager.free_devs:
if dev_name.startswith(dialog.vm.name): # originally attached to dom0
dev_path = "/dev/"+dev_name.split(":")[1]
else: # originally attached to another domain, eg. usbvm
#attach it to dom0, then treat it as an attached device
dialog.blk_manager.attach_device(dialog.vm, dev_name)
if dev_name in dialog.blk_manager.attached_devs: #is attached to dom0
assert dialog.blk_manager.attached_devs[dev_name]['attached_to']['vm'] == dialog.vm.name
dev_path = "/dev/" + dialog.blk_manager.attached_devs[dev_name]['attached_to']['frontend']
#check if device mounted
dialog.dev_mount_path = check_if_mounted(dev_path)
if dialog.dev_mount_path != None:
enable_dir_line_edit(dialog, True)
else:
dialog.dev_mount_path = mount_device(dev_path)
if dialog.dev_mount_path != None:
enable_dir_line_edit(dialog, True)
else:
dialog.dev_combobox.setCurrentIndex(0) #if couldn't mount - set current device to "None"
dialog.prev_dev_idx = idx
dialog.select_dir_page.emit(SIGNAL("completeChanged()"))
def select_path_button_clicked(dialog):
dialog.backup_dir = dialog.dir_line_edit.text()
file_dialog = QFileDialog()
file_dialog.setReadOnly(True)
new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", dialog.dev_mount_path)
if new_path:
dialog.dir_line_edit.setText(new_path)
dialog.backup_dir = new_path
dialog.select_dir_page.emit(SIGNAL("completeChanged()"))
def simulate_long_lasting_proces(period, progress_callback):
for i in range(period):
progress_callback((i*100)/period)
time.sleep(1)
progress_callback(100)
return 0

View File

@ -31,106 +31,8 @@ from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from qubes.qubes import dry_run
import ui_editfwrulesdlg
import ui_newfwruledlg
class EditFwRulesDlg (QDialog, ui_editfwrulesdlg.Ui_EditFwRulesDlg):
def __init__(self, parent = None):
super (EditFwRulesDlg, self).__init__(parent)
self.setupUi(self)
self.newRuleButton.clicked.connect(self.new_rule_button_pressed)
self.editRuleButton.clicked.connect(self.edit_rule_button_pressed)
self.deleteRuleButton.clicked.connect(self.delete_rule_button_pressed)
self.policyAllowRadioButton.toggled.connect(self.policy_radio_toggled)
self.dnsCheckBox.toggled.connect(self.dns_checkbox_toggled)
self.icmpCheckBox.toggled.connect(self.icmp_checkbox_toggled)
def set_model(self, model):
self.__model = model
self.rulesTreeView.setModel(model)
self.rulesTreeView.header().setResizeMode(QHeaderView.ResizeToContents)
self.rulesTreeView.header().setResizeMode(0, QHeaderView.Stretch)
self.set_allow(model.allow)
self.dnsCheckBox.setChecked(model.allowDns)
self.icmpCheckBox.setChecked(model.allowIcmp)
self.setWindowTitle(model.get_vm_name() + " firewall")
def set_allow(self, allow):
self.policyAllowRadioButton.setChecked(allow)
self.policyDenyRadioButton.setChecked(not allow)
def policy_radio_toggled(self, on):
self.__model.allow = self.policyAllowRadioButton.isChecked()
def dns_checkbox_toggled(self, on):
self.__model.allowDns = on
def icmp_checkbox_toggled(self, on):
self.__model.allowIcmp = on
def new_rule_button_pressed(self):
dialog = NewFwRuleDlg()
self.run_rule_dialog(dialog)
def edit_rule_button_pressed(self):
dialog = NewFwRuleDlg()
dialog.set_ok_enabled(True)
selected = self.rulesTreeView.selectedIndexes()
if len(selected) > 0:
row = self.rulesTreeView.selectedIndexes().pop().row()
address = self.__model.get_column_string(0, row).replace(' ', '')
dialog.addressComboBox.setItemText(0, address)
dialog.addressComboBox.setCurrentIndex(0)
service = self.__model.get_column_string(1, row)
dialog.serviceComboBox.setItemText(0, service)
dialog.serviceComboBox.setCurrentIndex(0)
self.run_rule_dialog(dialog, row)
def run_rule_dialog(self, dialog, row = None):
if dialog.exec_():
address = str(dialog.addressComboBox.currentText())
service = str(dialog.serviceComboBox.currentText())
port = None
port2 = None
unmask = address.split("/", 1)
if len(unmask) == 2:
address = unmask[0]
netmask = int(unmask[1])
else:
netmask = 32
if address == "*":
address = "0.0.0.0"
netmask = 0
if service == "*":
service = "0"
try:
range = service.split("-", 1)
if len(range) == 2:
port = int(range[0])
port2 = int(range[1])
else:
port = int(service)
except (TypeError, ValueError) as ex:
port = self.__model.get_service_port(service)
if port is not None:
if port2 is not None and port2 <= port:
QMessageBox.warning(None, "Invalid service ports range", "Port {0} is lower than port {1}.".format(port2, port))
else:
item = QubesFirewallRuleItem(address, netmask, port, port2)
if row is not None:
self.__model.setChild(row, item)
else:
self.__model.appendChild(item)
else:
QMessageBox.warning(None, "Invalid service name", "Service '{0} is unknown.".format(service))
def delete_rule_button_pressed(self):
for i in set([index.row() for index in self.rulesTreeView.selectedIndexes()]):
self.__model.removeChild(i)
class QIPAddressValidator(QValidator):
def __init__(self, parent = None):
@ -397,3 +299,4 @@ class QubesFirewallRulesModel(QAbstractItemModel):
def __len__(self):
return len(self.children)

View File

@ -0,0 +1,107 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
# Copyright (C) 2012 Marek Marczykowski <marmarek@mimuw.edu.pl>
#
# 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 QubesException
from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesHost
import qubesmanager.resources_rc
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
import subprocess
import time
import threading
from operator import itemgetter
from ui_globalsettingsdlg import *
class GlobalSettingsWindow(Ui_GlobalSettings, QDialog):
def __init__(self, parent=None):
super(GlobalSettingsWindow, self).__init__(parent)
self.setupUi(self)
def reject(self):
self.done(0)
def save_and_apply(self):
pass
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception( exc_type, exc_value, exc_traceback ):
import sys
import os.path
import traceback
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
filename = os.path.basename( filename )
error = "%s: %s" % ( exc_type.__name__, exc_value )
QMessageBox.critical(None, "Houston, we have a problem...",
"Whoops. A critical error has occured. This is most likely a bug "
"in Qubes Global Settings application.<br><br>"
"<b><i>%s</i></b>" % error +
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% ( line, filename ))
def main():
global qubes_host
qubes_host = QubesHost()
global app
app = QApplication(sys.argv)
app.setOrganizationName("The Qubes Project")
app.setOrganizationDomain("http://qubes-os.org")
app.setApplicationName("Qubes Global Settings")
sys.excepthook = handle_exception
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
global global_window
global_window = GlobalSettingsWindow()
global_window.show()
app.exec_()
app.exit()
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from ui_multiselectwidget import *
class MultiSelectWidget(Ui_MultiSelectWidget, QWidget):
__pyqtSignals__ = ("selected_changed()",)
def __init__(self, parent=None):
super(MultiSelectWidget, self).__init__()
self.setupUi(self);
self.add_selected_button.clicked.connect(self.add_selected)
self.add_all_button.clicked.connect(self.add_all)
self.remove_selected_button.clicked.connect(self.remove_selected)
self.remove_all_button.clicked.connect(self.remove_all)
self.available_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.selected_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
def switch_selected(self, src, dst):
selected = src.selectedItems()
for s in selected:
row = src.indexFromItem(s).row()
item = src.takeItem(row)
dst.addItem(item)
dst.sortItems()
self.emit(SIGNAL("selected_changed()"))
def add_selected(self):
self.switch_selected(self.available_list, self.selected_list)
def remove_selected(self):
self.switch_selected(self.selected_list, self.available_list)
def move_all(self, src, dst):
while src.count() > 0:
item = src.takeItem(0)
dst.addItem(item)
dst.sortItems()
self.emit(SIGNAL("selected_changed()"))
def add_all(self):
self.move_all(self.available_list, self.selected_list)
def remove_all(self):
self.move_all(self.selected_list, self.available_list)
def clear(self):
self.available_list.clear()
self.selected_list.clear()

276
qubesmanager/restore.py Normal file
View File

@ -0,0 +1,276 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
# Copyright (C) 2012 Marek Marczykowski <marmarek@mimuw.edu.pl>
#
# 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 QubesException
from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesHost
from qubes.qubes import qubes_base_dir
import qubesmanager.resources_rc
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
import subprocess
import time
from operator import itemgetter
from thread_monitor import *
from qubes import qubesutils
from ui_restoredlg import *
from multiselectwidget import *
from backup_utils import *
class RestoreVMsWindow(Ui_Restore, QWizard):
__pyqtSignals__ = ("restore_progress(int)",)
def __init__(self, app, qvm_collection, blk_manager, parent=None):
super(RestoreVMsWindow, self).__init__(parent)
self.app = app
self.qvm_collection = qvm_collection
self.blk_manager = blk_manager
self.dev_mount_path = None
self.backup_dir = None
self.restore_options = None
self.backup_vms_list = None
self.func_output = []
self.excluded = {}
for vm in self.qvm_collection.values():
if vm.qid == 0:
self.vm = vm
break;
assert self.vm != None
self.setupUi(self)
self.select_vms_widget = MultiSelectWidget(self)
self.select_vms_layout.insertWidget(1, self.select_vms_widget)
self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed)
self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated)
self.connect(self, SIGNAL("restore_progress(QString)"), self.commit_text_edit.append)
self.select_dir_page.isComplete = self.has_selected_dir
self.select_vms_page.isComplete = self.has_selected_vms
#FIXME
#this causes to run isComplete() twice, I don't know why
self.select_vms_page.connect(self.select_vms_widget, SIGNAL("selected_changed()"), SIGNAL("completeChanged()"))
fill_devs_list(self)
self.__init_restore_options__()
def dev_combobox_activated(self, idx):
dev_combobox_activated(self, idx)
@pyqtSlot(name='on_select_path_button_clicked')
def select_path_button_clicked(self):
select_path_button_clicked(self)
def on_ignore_missing_toggled(self, checked):
self.restore_options['use-default-template'] = checked
self.restore_options['use-default-netvm'] = checked
def on_ignore_uname_mismatch_toggled(self, checked):
self.restore_options['ignore-username-mismatch'] = checked
def on_skip_dom0_toggled(self, checked):
self.restore_options['dom0-home'] = checked
def __fill_vms_list__(self):
if self.backup_vms_list != None:
return
self.select_vms_widget.selected_list.clear()
self.select_vms_widget.available_list.clear()
self.vms_to_restore = qubesutils.backup_restore_prepare(str(self.backup_dir), self.restore_options, self.qvm_collection)
for vmname in self.vms_to_restore:
self.select_vms_widget.available_list.addItem(vmname)
def __init_restore_options__(self):
if not self.restore_options:
self.restore_options = {}
qubesutils.backup_restore_set_defaults(self.restore_options)
if 'use-default-template' in self.restore_options and 'use-default-netvm' in self.restore_options:
val = self.restore_options['use-default-template'] and self.restore_options['use-default-netvm']
self.ignore_missing.setChecked(val)
else:
self.ignore_missing.setChecked(False)
if 'ignore-username-mismatch' in self.restore_options:
self.ignore_uname_mismatch.setChecked(self.restore_options['ignore-username-mismatch'])
if 'dom0-home' in self.restore_options:
self.skip_dom0.setChecked(self.restore_options['dom0-home'])
def gather_output(self, s):
self.func_output.append(s)
def restore_error_output(self, s):
self.emit(SIGNAL("restore_progress(QString)"), '<font color="red">{0}</font>'.format(s))
def restore_output(self, s):
self.emit(SIGNAL("restore_progress(QString)"),'<font color="black">{0}</font>'.format(s))
def __do_restore__(self, thread_monitor):
err_msg = []
self.qvm_collection.lock_db_for_writing()
try:
qubesutils.backup_restore_do(str(self.backup_dir), self.vms_to_restore, self.qvm_collection, self.restore_output, self.restore_error_output)
except Exception as ex:
err_msg.append(str(ex))
self.qvm_collection.unlock_db()
if len(err_msg) > 0 :
thread_monitor.set_error_msg('\n'.join(err_msg))
self.emit(SIGNAL("restore_progress(QString)"),'<b><font color="red">{0}</font></b>'.format("Finished with errors!"))
else:
self.emit(SIGNAL("restore_progress(QString)"),'<font color="green">{0}</font>'.format("Finished successfully!"))
thread_monitor.set_finished()
def current_page_changed(self, id):
if self.currentPage() is self.select_vms_page:
self.__fill_vms_list__()
elif self.currentPage() is self.confirm_page:
for v in self.excluded:
self.vms_to_restore[v] = self.excluded[v]
self.excluded = {}
for i in range(self.select_vms_widget.available_list.count()):
vmname = self.select_vms_widget.available_list.item(i).text()
self.excluded[str(vmname)] = self.vms_to_restore[str(vmname)]
del self.vms_to_restore[str(vmname)]
del self.func_output[:]
qubesutils.backup_restore_print_summary(self.vms_to_restore, print_callback = self.gather_output)
self.confirm_text_edit.setReadOnly(True)
self.confirm_text_edit.setFontFamily("Monospace")
self.confirm_text_edit.setText("\n".join(self.func_output))
elif self.currentPage() is self.commit_page:
self.button(self.CancelButton).setDisabled(True)
self.button(self.FinishButton).setDisabled(True)
self.thread_monitor = ThreadMonitor()
thread = threading.Thread (target= self.__do_restore__ , args=(self.thread_monitor,))
thread.daemon = True
thread.start()
while not self.thread_monitor.is_finished():
self.app.processEvents()
time.sleep (0.1)
#if not self.thread_monitor.success:
#QMessageBox.warning (None, "Backup error!", "ERROR: {1}".format(self.vm.name, self.thread_monitor.error_msg))
umount_device(self.dev_mount_path)
self.button(self.FinishButton).setEnabled(True)
def has_selected_dir(self):
return self.backup_dir != None
def has_selected_vms(self):
return self.select_vms_widget.selected_list.count() > 0
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception( exc_type, exc_value, exc_traceback ):
import sys
import os.path
import traceback
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
filename = os.path.basename( filename )
error = "%s: %s" % ( exc_type.__name__, exc_value )
QMessageBox.critical(None, "Houston, we have a problem...",
"Whoops. A critical error has occured. This is most likely a bug "
"in Qubes Restore VMs application.<br><br>"
"<b><i>%s</i></b>" % error +
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% ( line, filename ))
def main():
global qubes_host
qubes_host = QubesHost()
global app
app = QApplication(sys.argv)
app.setOrganizationName("The Qubes Project")
app.setOrganizationDomain("http://qubes-os.org")
app.setApplicationName("Qubes Restore VMs")
sys.excepthook = handle_exception
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
global restore_window
restore_window = RestoreVMsWindow()
restore_window.show()
app.exec_()
app.exit()
if __name__ == "__main__":
main()

403
qubesmanager/settings.py Normal file
View File

@ -0,0 +1,403 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
# Copyright (C) 2012 Marek Marczykowski <marmarek@mimuw.edu.pl>
#
# 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 qubes_appmenu_create_cmd
from qubes.qubes import qubes_appmenu_remove_cmd
from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesHost
from qubes.qubes import qrexec_client_path
import qubesmanager.resources_rc
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
import subprocess
import time
import threading
from operator import itemgetter
from ui_settingsdlg import *
from multiselectwidget import *
from appmenu_select import *
from firewall import *
class VMSettingsWindow(Ui_SettingsDialog, QDialog):
tabs_indices = {"basic": 0,
"advanced": 1,
"firewall": 2,
"devices": 3,
"applications": 4,
"services": 5,}
def __init__(self, vm, app, qvm_collection, init_page="basic", parent=None):
super(VMSettingsWindow, self).__init__(parent)
self.app = app
self.qvm_collection = qvm_collection
self.vm = vm
if self.vm.template_vm:
self.source_vm = self.vm.template_vm
else:
self.source_vm = self.vm
self.setupUi(self)
if init_page in self.tabs_indices:
idx = self.tabs_indices[init_page]
assert (idx in range(self.tabWidget.count()))
self.tabWidget.setCurrentIndex(idx)
self.connect(self.buttonBox, SIGNAL("accepted()"), self.save_and_apply)
self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject)
self.tabWidget.currentChanged.connect(self.current_tab_changed)
###### basic tab
self.__init_basic_tab__()
###### firewall tab
model = QubesFirewallRulesModel()
model.set_vm(vm)
self.set_fw_model(model)
self.newRuleButton.clicked.connect(self.new_rule_button_pressed)
self.editRuleButton.clicked.connect(self.edit_rule_button_pressed)
self.deleteRuleButton.clicked.connect(self.delete_rule_button_pressed)
self.policyAllowRadioButton.toggled.connect(self.policy_radio_toggled)
self.dnsCheckBox.toggled.connect(self.dns_checkbox_toggled)
self.icmpCheckBox.toggled.connect(self.icmp_checkbox_toggled)
####### devices tab
self.dev_list = MultiSelectWidget(self)
self.devices_layout.addWidget(self.dev_list)
####### apps tab
if not vm.is_netvm():
self.app_list = MultiSelectWidget(self)
self.apps_layout.addWidget(self.app_list)
self.AppListManager = AppmenuSelectManager(self.vm, self.app_list)
else:
self.tabWidget.setTabEnabled(self.tabs_indices["applications"], False)
def reject(self):
self.done(0)
#needed not to close the dialog before applying changes
def accept(self):
pass
def save_and_apply(self):
thread_monitor = ThreadMonitor()
thread = threading.Thread (target=self.__save_changes__, args=(thread_monitor,))
thread.daemon = True
thread.start()
progress = QProgressDialog ("Applying settings to <b>{0}</b>...".format(self.vm.name), "", 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 not thread_monitor.success:
QMessageBox.warning (None, "Error while changing settings for {0}!", "ERROR: {1}".format(self.vm.name, thread_monitor.error_msg))
self.done(0)
def __save_changes__(self, thread_monitor):
ret = self.__apply_basic_tab__()
if len(ret) > 0 :
thread_monitor.set_error_msg('\n'.join(ret))
thread_monitor.set_finished()
return
#self.fw_model.apply_rules()
self.AppListManager.save_appmenu_select_changes()
thread_monitor.set_finished()
def current_tab_changed(self, idx):
if idx == self.tabs_indices["firewall"]:
if self.vm.netvm_vm is not None and not self.vm.netvm_vm.is_proxyvm():
QMessageBox.warning (None, "VM configuration problem!", "The '{0}' AppVM is not network connected to a FirewallVM!<p>".format(self.vm.name) +\
"You may edit the '{0}' VM firewall rules, but these will not take any effect until you connect it to a working Firewall VM.".format(self.vm.name))
######### basic tab
def __init_basic_tab__(self):
self.vmname.setText(self.vm.name)
#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)
self.label_idx = 0
for (i, label) in enumerate(self.label_list):
if label == self.vm.label:
self.label_idx = i
self.vmlabel.insertItem(i, label.name)
self.vmlabel.setItemIcon (i, QIcon(label.icon_path))
self.vmlabel.setCurrentIndex(self.label_idx)
if not self.vm.is_template() and self.vm.template_vm is not None:
template_vm_list = [vm for vm in self.qvm_collection.values() if not vm.internal and vm.is_template()]
self.template_idx = 0
for (i, vm) in enumerate(template_vm_list):
text = vm.name
if vm is self.qvm_collection.get_default_template_vm():
text += " (default)"
if vm.qid == self.vm.template_vm.qid:
self.template_idx = i
text += " (current)"
self.template_name.insertItem(i, text)
self.template_name.setCurrentIndex(self.template_idx)
else:
self.template_name.setEnabled(False)
if not self.vm.is_netvm():
netvm_list = [vm for vm in self.qvm_collection.values() if not vm.internal and vm.is_netvm()]
self.netvm_idx = 0
for (i, vm) in enumerate(netvm_list):
text = vm.name
if vm is self.qvm_collection.get_default_netvm_vm():
text += " (default)"
if vm.qid == self.vm.netvm_vm.qid:
self.netvm_idx = i
text += " (current)"
self.netVM.insertItem(i, text)
self.netVM.setCurrentIndex(self.netvm_idx)
else:
self.netVM.setEnabled(False)
#self.vmname.selectAll()
#self.vmname.setFocus()
def __apply_basic_tab__(self):
msg = []
if self.vm.is_running():
msg.append("Can't change settings of a running VM.")
msg.append("telemele")
return msg
# vmname changed
vmname = str(self.vmname.text())
if self.vm.name != vmname:
if self.qvm_collection.get_vm_by_name(vmname) is not None:
msg.append("A VM named <b>{0}</b> already exists in the system!".format(vmname))
else:
oldname = self.vm.name
try:
self.qvm_collection.lock_db_for_writing()
self.vm.pre_rename(vmname)
self.vm.set_name(vmname)
self.vm.post_rename(oldname)
self.qvm_collection.save()
except Exception as ex:
msg.append(str(ex))
finally:
self.qvm_collection.unlock_db()
#vm label changed
if self.vmlabel.currentIndex() != self.label_idx:
label = self.label_list[self.vmlabel.currentIndex()]
self.qvm_collection.lock_db_for_writing()
self.vm.label = label
self.qvm_collection.save()
self.qvm_collection.unlock_db()
return msg
# template_vm = template_vm_list[dialog.template_name.currentIndex()]
# allow_networking = dialog.allow_networking.isChecked()
######### firewall tab related
def set_fw_model(self, model):
self.fw_model = model
self.rulesTreeView.setModel(model)
self.rulesTreeView.header().setResizeMode(QHeaderView.ResizeToContents)
self.rulesTreeView.header().setResizeMode(0, QHeaderView.Stretch)
self.set_allow(model.allow)
self.dnsCheckBox.setChecked(model.allowDns)
self.icmpCheckBox.setChecked(model.allowIcmp)
def set_allow(self, allow):
self.policyAllowRadioButton.setChecked(allow)
self.policyDenyRadioButton.setChecked(not allow)
def policy_radio_toggled(self, on):
self.fw_model.allow = self.policyAllowRadioButton.isChecked()
def dns_checkbox_toggled(self, on):
self.fw_model.allowDns = on
def icmp_checkbox_toggled(self, on):
self.fw_model.allowIcmp = on
def new_rule_button_pressed(self):
dialog = NewFwRuleDlg()
self.run_rule_dialog(dialog)
def edit_rule_button_pressed(self):
dialog = NewFwRuleDlg()
dialog.set_ok_enabled(True)
selected = self.rulesTreeView.selectedIndexes()
if len(selected) > 0:
row = self.rulesTreeView.selectedIndexes().pop().row()
address = self.fw_model.get_column_string(0, row).replace(' ', '')
dialog.addressComboBox.setItemText(0, address)
dialog.addressComboBox.setCurrentIndex(0)
service = self.fw_model.get_column_string(1, row)
dialog.serviceComboBox.setItemText(0, service)
dialog.serviceComboBox.setCurrentIndex(0)
self.run_rule_dialog(dialog, row)
def delete_rule_button_pressed(self):
for i in set([index.row() for index in self.rulesTreeView.selectedIndexes()]):
self.fw_model.removeChild(i)
def run_rule_dialog(self, dialog, row = None):
if dialog.exec_():
address = str(dialog.addressComboBox.currentText())
service = str(dialog.serviceComboBox.currentText())
port = None
port2 = None
unmask = address.split("/", 1)
if len(unmask) == 2:
address = unmask[0]
netmask = int(unmask[1])
else:
netmask = 32
if address == "*":
address = "0.0.0.0"
netmask = 0
if service == "*":
service = "0"
try:
range = service.split("-", 1)
if len(range) == 2:
port = int(range[0])
port2 = int(range[1])
else:
port = int(service)
except (TypeError, ValueError) as ex:
port = self.fw_model.get_service_port(service)
if port is not None:
if port2 is not None and port2 <= port:
QMessageBox.warning(None, "Invalid service ports range", "Port {0} is lower than port {1}.".format(port2, port))
else:
item = QubesFirewallRuleItem(address, netmask, port, port2)
if row is not None:
self.fw_model.setChild(row, item)
else:
self.fw_model.appendChild(item)
else:
QMessageBox.warning(None, "Invalid service name", "Service '{0} is unknown.".format(service))
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception( exc_type, exc_value, exc_traceback ):
import sys
import os.path
import traceback
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
filename = os.path.basename( filename )
error = "%s: %s" % ( exc_type.__name__, exc_value )
QMessageBox.critical(None, "Houston, we have a problem...",
"Whoops. A critical error has occured. This is most likely a bug "
"in Qubes VM Settings application.<br><br>"
"<b><i>%s</i></b>" % error +
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% ( line, filename ))
def main():
global qubes_host
qubes_host = QubesHost()
global app
app = QApplication(sys.argv)
app.setOrganizationName("The Qubes Project")
app.setOrganizationDomain("http://qubes-os.org")
app.setApplicationName("Qubes VM Settings")
sys.excepthook = handle_exception
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = None
if len(sys.argv) > 1:
vm = qvm_collection.get_vm_by_name(sys.argv[1])
if vm is None or vm.qid not in qvm_collection:
QMessageBox.critical(None, "Qubes VM Settings Error",
"A VM with the name '{0}' does not exist in the system.".format(sys.argv[1]))
sys.exit(1)
else:
vms_list = [vm.name for vm in qvm_collection.values() if (vm.is_appvm() or vm.is_template())]
vmname = QInputDialog.getItem(None, "Select VM", "Select VM:", vms_list, editable = False)
if not vmname[1]:
sys.exit(1)
vm = qvm_collection.get_vm_by_name(vmname[0])
global settings_window
settings_window = VMSettingsWindow(vm, app, qvm_collection, "basic")
settings_window.show()
app.exec_()
app.exit()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,44 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2011 Marek Marczykowski <marmarek@mimuw.edu.pl>
#
# 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.
#
#
from PyQt4.QtCore import *
import threading
class ThreadMonitor(QObject):
def __init__(self):
self.success = True
self.error_msg = None
self.event_finished = threading.Event()
def set_error_msg(self, error_msg):
self.success = False
self.error_msg = error_msg
self.set_finished()
def is_finished(self):
return self.event_finished.is_set()
def set_finished(self):
self.event_finished.set()

View File

@ -1,22 +1,35 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file alias="qubes.png">icons/qubes.png</file>
<file alias="appvm.png">icons/appvm.png</file>
<file alias="netvm.png">icons/netvm.png</file>
<file alias="networking.png">icons/networking.png</file>
<file alias="dom0.png">icons/dom0.png</file>
<file alias="storagevm.png">icons/storagevm.png</file>
<file alias="templatevm.png">icons/templatevm.png</file>
<file alias="updateable.png">icons/updateable.png</file>
<file alias="home.png">icons/home.png</file>
<file alias="root.png">icons/root.png</file>
<file alias="createvm.png">icons/createvm.png</file>
<file alias="removevm.png">icons/removevm.png</file>
<file alias="shutdownvm.png">icons/shutdownvm.png</file>
<file alias="resumevm.png">icons/resumevm.png</file>
<file alias="pausevm.png">icons/pausevm.png</file>
<file alias="showallvms.png">icons/showallvms.png</file>
<file alias="showcpuload.png">icons/showcpuload.png</file>
<file alias="firewall.png">icons/firewall.png</file>
</qresource>
<RCC>
<qresource>
<file alias="mount.png">icons/mount.png</file>
<file alias="pencil.png">icons/pencil.png</file>
<file alias="redfirewall.png">icons/redfirewall.png</file>
<file alias="edit.png">icons/edit.png</file>
<file alias="add.png">icons/add.png</file>
<file alias="flag-blue.png">icons/flag-blue.png</file>
<file alias="flag-green.png">icons/flag-green.png</file>
<file alias="flag-red.png">icons/flag-red.png</file>
<file alias="flag-yellow.png">icons/flag-yellow.png</file>
<file alias="remove.png">icons/remove.png</file>
<file alias="on.png">icons/on.png</file>
<file alias="appsprefs.png">icons/appsprefs.png</file>
<file alias="newfirewall.png">icons/newfirewall.png</file>
<file alias="qubes.png">icons/qubes.png</file>
<file alias="appvm.png">icons/appvm.png</file>
<file alias="netvm.png">icons/netvm.png</file>
<file alias="networking.png">icons/networking.png</file>
<file alias="dom0.png">icons/dom0.png</file>
<file alias="storagevm.png">icons/storagevm.png</file>
<file alias="templatevm.png">icons/templatevm.png</file>
<file alias="updateable.png">icons/updateable.png</file>
<file alias="home.png">icons/home.png</file>
<file alias="root.png">icons/root.png</file>
<file alias="createvm.png">icons/createvm.png</file>
<file alias="removevm.png">icons/removevm.png</file>
<file alias="shutdownvm.png">icons/shutdownvm.png</file>
<file alias="resumevm.png">icons/resumevm.png</file>
<file alias="pausevm.png">icons/pausevm.png</file>
<file alias="showallvms.png">icons/showallvms.png</file>
<file alias="showcpuload.png">icons/showcpuload.png</file>
<file alias="firewall.png">icons/firewall.png</file>
</qresource>
</RCC>

229
restoredlg.ui Normal file
View File

@ -0,0 +1,229 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Restore</class>
<widget class="QWizard" name="Restore">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>399</height>
</rect>
</property>
<property name="windowTitle">
<string>Qubes Restore VMs</string>
</property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<property name="options">
<set>QWizard::NoBackButtonOnLastPage|QWizard::NoBackButtonOnStartPage</set>
</property>
<widget class="QWizardPage" name="select_dir_page">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="title">
<string>Backup source location</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Device</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="dev_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>dev1</string>
</property>
</item>
<item>
<property name="text">
<string>longdeviceblablabla</string>
</property>
</item>
<item>
<property name="text">
<string>dev2</string>
</property>
</item>
<item>
<property name="text">
<string>dev3</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Backup directory:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="dir_line_edit"/>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="select_path_button">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="options_groupbox">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="title">
<string>Restore options</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QCheckBox" name="ignore_missing">
<property name="toolTip">
<string>Ignore missing templates or netvms, restore VMs anyway.</string>
</property>
<property name="text">
<string>ignore missing</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="skip_dom0">
<property name="text">
<string>skip dom0</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="ignore_uname_mismatch">
<property name="toolTip">
<string>Ignore dom0 username mismatch while restoring homedir.</string>
</property>
<property name="text">
<string>ignore username mismatch</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>215</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="select_vms_page">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="select_vms_groupbox">
<property name="title">
<string>VMs to restore</string>
</property>
<layout class="QVBoxLayout" name="select_vms_layout"/>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="confirm_page">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_6">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>You're about to perform the following actions:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="confirm_text_edit">
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info&lt;br /&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info&lt;br /&gt;A lot of info&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>To continue press Next. </string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="commit_page">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTextEdit" name="commit_text_edit"/>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -33,12 +33,25 @@ cp qubes-appmenu-select $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager/
cp qubesmanager/main.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/appmenu_select.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/backup.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/backup_utils.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/global_settings.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/multiselectwidget.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/restore.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/settings.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/thread_monitor.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/resources_rc.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/__init__.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_backupdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_editfwrulesdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_globalsettingsdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_mainwindow.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_multiselectwidget.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
cp qubesmanager/ui_restoredlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
cp qubesmanager/ui_settingsdlg.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
@ -67,21 +80,60 @@ rm -rf $RPM_BUILD_ROOT
%{python_sitearch}/qubesmanager/appmenu_select.py
%{python_sitearch}/qubesmanager/appmenu_select.pyc
%{python_sitearch}/qubesmanager/appmenu_select.pyo
%{python_sitearch}/qubesmanager/backup.py
%{python_sitearch}/qubesmanager/backup.pyc
%{python_sitearch}/qubesmanager/backup.pyo
%{python_sitearch}/qubesmanager/backup_utils.py
%{python_sitearch}/qubesmanager/backup_utils.pyc
%{python_sitearch}/qubesmanager/backup_utils.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/global_settings.py
%{python_sitearch}/qubesmanager/global_settings.pyc
%{python_sitearch}/qubesmanager/global_settings.pyo
%{python_sitearch}/qubesmanager/multiselectwidget.py
%{python_sitearch}/qubesmanager/multiselectwidget.pyc
%{python_sitearch}/qubesmanager/multiselectwidget.pyo
%{python_sitearch}/qubesmanager/restore.py
%{python_sitearch}/qubesmanager/restore.pyc
%{python_sitearch}/qubesmanager/restore.pyo
%{python_sitearch}/qubesmanager/settings.py
%{python_sitearch}/qubesmanager/settings.pyc
%{python_sitearch}/qubesmanager/settings.pyo
%{python_sitearch}/qubesmanager/thread_monitor.py
%{python_sitearch}/qubesmanager/thread_monitor.pyc
%{python_sitearch}/qubesmanager/thread_monitor.pyo
%{python_sitearch}/qubesmanager/resources_rc.py
%{python_sitearch}/qubesmanager/resources_rc.pyc
%{python_sitearch}/qubesmanager/resources_rc.pyo
%{python_sitearch}/qubesmanager/ui_backupdlg.py
%{python_sitearch}/qubesmanager/ui_backupdlg.pyc
%{python_sitearch}/qubesmanager/ui_backupdlg.pyo
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.py
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.pyc
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.pyo
%{python_sitearch}/qubesmanager/ui_globalsettingsdlg.py
%{python_sitearch}/qubesmanager/ui_globalsettingsdlg.pyc
%{python_sitearch}/qubesmanager/ui_globalsettingsdlg.pyo
%{python_sitearch}/qubesmanager/ui_mainwindow.py
%{python_sitearch}/qubesmanager/ui_mainwindow.pyc
%{python_sitearch}/qubesmanager/ui_mainwindow.pyo
%{python_sitearch}/qubesmanager/ui_multiselectwidget.py
%{python_sitearch}/qubesmanager/ui_multiselectwidget.pyc
%{python_sitearch}/qubesmanager/ui_multiselectwidget.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
%{python_sitearch}/qubesmanager/ui_restoredlg.py
%{python_sitearch}/qubesmanager/ui_restoredlg.pyc
%{python_sitearch}/qubesmanager/ui_restoredlg.pyo
%{python_sitearch}/qubesmanager/ui_settingsdlg.py
%{python_sitearch}/qubesmanager/ui_settingsdlg.pyc
%{python_sitearch}/qubesmanager/ui_settingsdlg.pyo
/usr/share/applications/qubes-manager.desktop

807
settingsdlg.ui Normal file
View File

@ -0,0 +1,807 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsDialog</class>
<widget class="QDialog" name="SettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>694</width>
<height>483</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<property name="windowIcon">
<iconset resource="resources.qrc">
<normaloff>:/root.png</normaloff>:/root.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<property name="currentIndex">
<number>5</number>
</property>
<widget class="QWidget" name="basic_tab">
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<attribute name="title">
<string>Basic</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name &amp; label:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="vmname">
<property name="text">
<string>myappvm</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="vmlabel">
<property name="frame">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Template:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="template_name"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>NetVM:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="netVM"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Include in backups by default</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Info</string>
</property>
<layout class="QFormLayout" name="formLayout_4">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="type_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>AppVM</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Installed by RPM:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="rpm_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>No</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Disk storage</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="1">
<widget class="QSpinBox" name="priv_size">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>GB</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Private storage max. size:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>73</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="advanced_tab">
<property name="enabled">
<bool>false</bool>
</property>
<attribute name="title">
<string>Advanced</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Memory/CPU</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Initial memory:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="mem_size">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>xx</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_16">
<property name="text">
<string>MB</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Max memory:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="max_mem_size">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>400</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>MB</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>VCPUs no.:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="vcpus">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="include_in_balancing">
<property name="text">
<string>Include in memory balancing</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_10">
<property name="title">
<string>Kernel</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Kernel:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="kernel"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Kernel opts:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="kernel_opts">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>[]</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_11">
<property name="title">
<string>Paths</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>dir:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="dir_path">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>dir_path</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>config:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="config_path">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>config_path</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>root img:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="root_img_path">
<property name="text">
<string>root_img_path</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>root volatile img:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="volatile_img_path">
<property name="text">
<string>volatile_path</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>private img:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="private_img_path">
<property name="text">
<string>private_path</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>88</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="firewall_tab">
<attribute name="title">
<string>Firewall rules</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QRadioButton" name="policyAllowRadioButton">
<property name="text">
<string>Allow network access except...</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="policyDenyRadioButton">
<property name="text">
<string>Deny network access except...</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QTreeView" name="rulesTreeView">
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>false</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>true</bool>
</property>
<attribute name="headerDefaultSectionSize">
<number>40</number>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QCheckBox" name="icmpCheckBox">
<property name="text">
<string>Allow ICMP traffic</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="dnsCheckBox">
<property name="text">
<string>Allow DNS queries</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QPushButton" name="newRuleButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/add.png</normaloff>:/add.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="editRuleButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/pencil.png</normaloff>:/pencil.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deleteRuleButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/remove.png</normaloff>:/remove.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="devices_tab">
<property name="enabled">
<bool>false</bool>
</property>
<attribute name="title">
<string>Devices</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<layout class="QVBoxLayout" name="devices_layout"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="apps_tab">
<attribute name="icon">
<iconset resource="resources.qrc">
<normaloff>:/appsprefs.png</normaloff>:/appsprefs.png</iconset>
</attribute>
<attribute name="title">
<string>Applications</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<layout class="QVBoxLayout" name="apps_layout"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="services_tab">
<property name="enabled">
<bool>false</bool>
</property>
<attribute name="title">
<string>Services</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QLineEdit" name="service_lineEdit"/>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="add_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/add.png</normaloff>:/add.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="4" column="0" rowspan="2">
<widget class="QListWidget" name="services_list">
<item>
<property name="text">
<string>ntpd</string>
</property>
<property name="checkState">
<enum>Checked</enum>
</property>
</item>
<item>
<property name="text">
<string>cupsd</string>
</property>
<property name="checkState">
<enum>Checked</enum>
</property>
</item>
<item>
<property name="text">
<string>meminfo</string>
</property>
<property name="checkState">
<enum>Checked</enum>
</property>
</item>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Checked services will be turned on.</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Unchecked services will be turned off.</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Unlisted services will follow default VM's settings.</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="remove_button">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/remove.png</normaloff>:/remove.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="5" column="1">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1 +1 @@
1.1.6
1.2.0