Merge branch 'master' of git.qubes-os.org:/var/lib/qubes/git/aga/qubes-manager
							
								
								
									
										140
									
								
								backupdlg.ui
									
									
									
									
									
								
							
							
						
						@ -22,20 +22,128 @@
 | 
				
			|||||||
  <widget class="QWizardPage" name="select_vms_page">
 | 
					  <widget class="QWizardPage" name="select_vms_page">
 | 
				
			||||||
   <layout class="QVBoxLayout" name="verticalLayout">
 | 
					   <layout class="QVBoxLayout" name="verticalLayout">
 | 
				
			||||||
    <item>
 | 
					    <item>
 | 
				
			||||||
     <widget class="QLabel" name="label_4">
 | 
					     <layout class="QGridLayout" name="gridLayout_2">
 | 
				
			||||||
      <property name="font">
 | 
					      <item row="1" column="1">
 | 
				
			||||||
       <font>
 | 
					       <widget class="QPushButton" name="shutdown_running_vms_button">
 | 
				
			||||||
        <pointsize>9</pointsize>
 | 
					        <property name="sizePolicy">
 | 
				
			||||||
        <weight>50</weight>
 | 
					         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
 | 
				
			||||||
        <italic>false</italic>
 | 
					          <horstretch>0</horstretch>
 | 
				
			||||||
        <bold>false</bold>
 | 
					          <verstretch>0</verstretch>
 | 
				
			||||||
        <underline>false</underline>
 | 
					         </sizepolicy>
 | 
				
			||||||
       </font>
 | 
					        </property>
 | 
				
			||||||
      </property>
 | 
					        <property name="text">
 | 
				
			||||||
      <property name="text">
 | 
					         <string>Shutdown all running selected VMs</string>
 | 
				
			||||||
       <string>Select VMs to backup:</string>
 | 
					        </property>
 | 
				
			||||||
      </property>
 | 
					        <property name="icon">
 | 
				
			||||||
     </widget>
 | 
					         <iconset resource="resources.qrc">
 | 
				
			||||||
 | 
					          <normaloff>:/shutdownvm.png</normaloff>:/shutdownvm.png</iconset>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item row="2" column="1">
 | 
				
			||||||
 | 
					       <widget class="QPushButton" name="refresh_button">
 | 
				
			||||||
 | 
					        <property name="sizePolicy">
 | 
				
			||||||
 | 
					         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
 | 
				
			||||||
 | 
					          <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					          <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					         </sizepolicy>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>Refresh running states.</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item row="1" column="0" rowspan="2">
 | 
				
			||||||
 | 
					       <widget class="QLabel" name="running_vms_warning">
 | 
				
			||||||
 | 
					        <property name="sizePolicy">
 | 
				
			||||||
 | 
					         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
 | 
				
			||||||
 | 
					          <horstretch>0</horstretch>
 | 
				
			||||||
 | 
					          <verstretch>0</verstretch>
 | 
				
			||||||
 | 
					         </sizepolicy>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="font">
 | 
				
			||||||
 | 
					         <font>
 | 
				
			||||||
 | 
					          <weight>75</weight>
 | 
				
			||||||
 | 
					          <italic>true</italic>
 | 
				
			||||||
 | 
					          <bold>true</bold>
 | 
				
			||||||
 | 
					         </font>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="styleSheet">
 | 
				
			||||||
 | 
					         <string notr="true">color:rgb(255, 0, 0)</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>Some of the selected VMs are running (red). Running VMs can not be backuped!</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="wordWrap">
 | 
				
			||||||
 | 
					         <bool>true</bool>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					      <item row="0" column="0">
 | 
				
			||||||
 | 
					       <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>
 | 
				
			||||||
 | 
					    </item>
 | 
				
			||||||
 | 
					    <item>
 | 
				
			||||||
 | 
					     <layout class="QGridLayout" name="gridLayout_3">
 | 
				
			||||||
 | 
					      <item row="0" column="0">
 | 
				
			||||||
 | 
					       <spacer name="horizontalSpacer_2">
 | 
				
			||||||
 | 
					        <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 row="0" column="1">
 | 
				
			||||||
 | 
					       <layout class="QHBoxLayout" name="horizontalLayout_3">
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="QLabel" name="label_3">
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string>Total size:</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <widget class="QLabel" name="total_size_label">
 | 
				
			||||||
 | 
					          <property name="text">
 | 
				
			||||||
 | 
					           <string>0</string>
 | 
				
			||||||
 | 
					          </property>
 | 
				
			||||||
 | 
					         </widget>
 | 
				
			||||||
 | 
					        </item>
 | 
				
			||||||
 | 
					        <item>
 | 
				
			||||||
 | 
					         <spacer name="horizontalSpacer">
 | 
				
			||||||
 | 
					          <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>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
    </item>
 | 
					    </item>
 | 
				
			||||||
   </layout>
 | 
					   </layout>
 | 
				
			||||||
  </widget>
 | 
					  </widget>
 | 
				
			||||||
@ -187,6 +295,8 @@ p, li { white-space: pre-wrap; }
 | 
				
			|||||||
   </layout>
 | 
					   </layout>
 | 
				
			||||||
  </widget>
 | 
					  </widget>
 | 
				
			||||||
 </widget>
 | 
					 </widget>
 | 
				
			||||||
 <resources/>
 | 
					 <resources>
 | 
				
			||||||
 | 
					  <include location="resources.qrc"/>
 | 
				
			||||||
 | 
					 </resources>
 | 
				
			||||||
 <connections/>
 | 
					 <connections/>
 | 
				
			||||||
</ui>
 | 
					</ui>
 | 
				
			||||||
 | 
				
			|||||||
@ -90,7 +90,7 @@
 | 
				
			|||||||
      <item row="0" column="0">
 | 
					      <item row="0" column="0">
 | 
				
			||||||
       <widget class="QLabel" name="label_6">
 | 
					       <widget class="QLabel" name="label_6">
 | 
				
			||||||
        <property name="enabled">
 | 
					        <property name="enabled">
 | 
				
			||||||
         <bool>false</bool>
 | 
					         <bool>true</bool>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
        <property name="text">
 | 
					        <property name="text">
 | 
				
			||||||
         <string>Minimal VM's memory:</string>
 | 
					         <string>Minimal VM's memory:</string>
 | 
				
			||||||
@ -100,36 +100,36 @@
 | 
				
			|||||||
      <item row="0" column="1">
 | 
					      <item row="0" column="1">
 | 
				
			||||||
       <widget class="QSpinBox" name="min_vm_mem">
 | 
					       <widget class="QSpinBox" name="min_vm_mem">
 | 
				
			||||||
        <property name="enabled">
 | 
					        <property name="enabled">
 | 
				
			||||||
         <bool>false</bool>
 | 
					         <bool>true</bool>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
        <property name="suffix">
 | 
					        <property name="suffix">
 | 
				
			||||||
         <string> MB</string>
 | 
					         <string> MiB</string>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
        <property name="maximum">
 | 
					        <property name="maximum">
 | 
				
			||||||
         <number>999999999</number>
 | 
					         <number>999999999</number>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
        <property name="singleStep">
 | 
					        <property name="singleStep">
 | 
				
			||||||
         <number>10</number>
 | 
					         <number>50</number>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
       </widget>
 | 
					       </widget>
 | 
				
			||||||
      </item>
 | 
					      </item>
 | 
				
			||||||
      <item row="1" column="0">
 | 
					      <item row="1" column="0">
 | 
				
			||||||
       <widget class="QLabel" name="label_7">
 | 
					       <widget class="QLabel" name="label_7">
 | 
				
			||||||
        <property name="enabled">
 | 
					        <property name="enabled">
 | 
				
			||||||
         <bool>false</bool>
 | 
					         <bool>true</bool>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
        <property name="text">
 | 
					        <property name="text">
 | 
				
			||||||
         <string>dom0 memory margin:</string>
 | 
					         <string>dom0 memory boost:</string>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
       </widget>
 | 
					       </widget>
 | 
				
			||||||
      </item>
 | 
					      </item>
 | 
				
			||||||
      <item row="1" column="1">
 | 
					      <item row="1" column="1">
 | 
				
			||||||
       <widget class="QSpinBox" name="dom0_mem_margin">
 | 
					       <widget class="QSpinBox" name="dom0_mem_boost">
 | 
				
			||||||
        <property name="enabled">
 | 
					        <property name="enabled">
 | 
				
			||||||
         <bool>false</bool>
 | 
					         <bool>true</bool>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
        <property name="suffix">
 | 
					        <property name="suffix">
 | 
				
			||||||
         <string> MB</string>
 | 
					         <string> MiB</string>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
        <property name="maximum">
 | 
					        <property name="maximum">
 | 
				
			||||||
         <number>999999999</number>
 | 
					         <number>999999999</number>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								icons/apps.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 22 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								icons/backup.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 31 KiB  | 
| 
		 Before Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								icons/global-settings.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 90 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								icons/restore.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 31 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								icons/running.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 20 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								icons/settings.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 40 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								icons/show-all-running.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 21 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								icons/wall.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 23 KiB  | 
@ -273,6 +273,10 @@
 | 
				
			|||||||
   <addaction name="action_appmenus"/>
 | 
					   <addaction name="action_appmenus"/>
 | 
				
			||||||
   <addaction name="action_updatevm"/>
 | 
					   <addaction name="action_updatevm"/>
 | 
				
			||||||
   <addaction name="separator"/>
 | 
					   <addaction name="separator"/>
 | 
				
			||||||
 | 
					   <addaction name="action_global_settings"/>
 | 
				
			||||||
 | 
					   <addaction name="action_backup"/>
 | 
				
			||||||
 | 
					   <addaction name="action_restore"/>
 | 
				
			||||||
 | 
					   <addaction name="separator"/>
 | 
				
			||||||
   <addaction name="action_showallvms"/>
 | 
					   <addaction name="action_showallvms"/>
 | 
				
			||||||
  </widget>
 | 
					  </widget>
 | 
				
			||||||
  <action name="action_createvm">
 | 
					  <action name="action_createvm">
 | 
				
			||||||
@ -353,7 +357,7 @@
 | 
				
			|||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
   <property name="icon">
 | 
					   <property name="icon">
 | 
				
			||||||
    <iconset resource="resources.qrc">
 | 
					    <iconset resource="resources.qrc">
 | 
				
			||||||
     <normaloff>:/appsprefs.png</normaloff>:/appsprefs.png</iconset>
 | 
					     <normaloff>:/apps.png</normaloff>:/apps.png</iconset>
 | 
				
			||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
   <property name="text">
 | 
					   <property name="text">
 | 
				
			||||||
    <string>Select VM applications</string>
 | 
					    <string>Select VM applications</string>
 | 
				
			||||||
@ -386,8 +390,8 @@
 | 
				
			|||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
   <property name="icon">
 | 
					   <property name="icon">
 | 
				
			||||||
    <iconset resource="resources.qrc">
 | 
					    <iconset resource="resources.qrc">
 | 
				
			||||||
     <normaloff>:/showallvms.png</normaloff>
 | 
					     <normaloff>:/show-all-running.png</normaloff>
 | 
				
			||||||
     <selectedoff>:/showallvms.png</selectedoff>:/showallvms.png</iconset>
 | 
					     <selectedoff>:/showallvms.png</selectedoff>:/show-all-running.png</iconset>
 | 
				
			||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
   <property name="text">
 | 
					   <property name="text">
 | 
				
			||||||
    <string>Show/Hide inactive VMs</string>
 | 
					    <string>Show/Hide inactive VMs</string>
 | 
				
			||||||
@ -399,7 +403,7 @@
 | 
				
			|||||||
  <action name="action_editfwrules">
 | 
					  <action name="action_editfwrules">
 | 
				
			||||||
   <property name="icon">
 | 
					   <property name="icon">
 | 
				
			||||||
    <iconset resource="resources.qrc">
 | 
					    <iconset resource="resources.qrc">
 | 
				
			||||||
     <normaloff>:/redfirewall.png</normaloff>:/redfirewall.png</iconset>
 | 
					     <normaloff>:/firewall.png</normaloff>:/firewall.png</iconset>
 | 
				
			||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
   <property name="text">
 | 
					   <property name="text">
 | 
				
			||||||
    <string>Edit VM Firewall rules</string>
 | 
					    <string>Edit VM Firewall rules</string>
 | 
				
			||||||
@ -502,7 +506,7 @@
 | 
				
			|||||||
  <action name="action_settings">
 | 
					  <action name="action_settings">
 | 
				
			||||||
   <property name="icon">
 | 
					   <property name="icon">
 | 
				
			||||||
    <iconset resource="resources.qrc">
 | 
					    <iconset resource="resources.qrc">
 | 
				
			||||||
     <normaloff>:/root.png</normaloff>:/root.png</iconset>
 | 
					     <normaloff>:/settings.png</normaloff>:/settings.png</iconset>
 | 
				
			||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
   <property name="text">
 | 
					   <property name="text">
 | 
				
			||||||
    <string>Settings</string>
 | 
					    <string>Settings</string>
 | 
				
			||||||
@ -512,16 +516,28 @@
 | 
				
			|||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
  </action>
 | 
					  </action>
 | 
				
			||||||
  <action name="action_restore">
 | 
					  <action name="action_restore">
 | 
				
			||||||
 | 
					   <property name="icon">
 | 
				
			||||||
 | 
					    <iconset resource="resources.qrc">
 | 
				
			||||||
 | 
					     <normaloff>:/restore.png</normaloff>:/restore.png</iconset>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
   <property name="text">
 | 
					   <property name="text">
 | 
				
			||||||
    <string>Restore VMs from backup</string>
 | 
					    <string>Restore VMs from backup</string>
 | 
				
			||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
  </action>
 | 
					  </action>
 | 
				
			||||||
  <action name="action_backup">
 | 
					  <action name="action_backup">
 | 
				
			||||||
 | 
					   <property name="icon">
 | 
				
			||||||
 | 
					    <iconset resource="resources.qrc">
 | 
				
			||||||
 | 
					     <normaloff>:/backup.png</normaloff>:/backup.png</iconset>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
   <property name="text">
 | 
					   <property name="text">
 | 
				
			||||||
    <string>Backup VMs</string>
 | 
					    <string>Backup VMs</string>
 | 
				
			||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
  </action>
 | 
					  </action>
 | 
				
			||||||
  <action name="action_global_settings">
 | 
					  <action name="action_global_settings">
 | 
				
			||||||
 | 
					   <property name="icon">
 | 
				
			||||||
 | 
					    <iconset resource="resources.qrc">
 | 
				
			||||||
 | 
					     <normaloff>:/global-settings.png</normaloff>:/global-settings.png</iconset>
 | 
				
			||||||
 | 
					   </property>
 | 
				
			||||||
   <property name="text">
 | 
					   <property name="text">
 | 
				
			||||||
    <string>Global settings</string>
 | 
					    <string>Global settings</string>
 | 
				
			||||||
   </property>
 | 
					   </property>
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import signal
 | 
				
			||||||
from PyQt4.QtCore import *
 | 
					from PyQt4.QtCore import *
 | 
				
			||||||
from PyQt4.QtGui import *
 | 
					from PyQt4.QtGui import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,18 +49,20 @@ from ui_backupdlg import *
 | 
				
			|||||||
from multiselectwidget import *
 | 
					from multiselectwidget import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backup_utils import *
 | 
					from backup_utils import *
 | 
				
			||||||
 | 
					import grp,pwd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BackupVMsWindow(Ui_Backup, QWizard):
 | 
					class BackupVMsWindow(Ui_Backup, QWizard):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    __pyqtSignals__ = ("backup_progress(int)",)
 | 
					    __pyqtSignals__ = ("backup_progress(int)",)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, app, qvm_collection, blk_manager, parent=None):
 | 
					    def __init__(self, app, qvm_collection, blk_manager, shutdown_vm_func, parent=None):
 | 
				
			||||||
        super(BackupVMsWindow, self).__init__(parent)
 | 
					        super(BackupVMsWindow, self).__init__(parent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.app = app
 | 
					        self.app = app
 | 
				
			||||||
        self.qvm_collection = qvm_collection
 | 
					        self.qvm_collection = qvm_collection
 | 
				
			||||||
        self.blk_manager = blk_manager
 | 
					        self.blk_manager = blk_manager
 | 
				
			||||||
 | 
					        self.shutdown_vm_func = shutdown_vm_func
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.dev_mount_path = None
 | 
					        self.dev_mount_path = None
 | 
				
			||||||
        self.backup_dir = None
 | 
					        self.backup_dir = None
 | 
				
			||||||
@ -75,12 +78,18 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.setupUi(self)
 | 
					        self.setupUi(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.show_running_vms_warning(False)
 | 
				
			||||||
        self.dir_line_edit.setReadOnly(True)
 | 
					        self.dir_line_edit.setReadOnly(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.select_vms_widget = MultiSelectWidget(self)
 | 
					        self.select_vms_widget = MultiSelectWidget(self)
 | 
				
			||||||
        self.verticalLayout.insertWidget(1, self.select_vms_widget)
 | 
					        self.verticalLayout.insertWidget(1, self.select_vms_widget)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed)
 | 
					        self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed)
 | 
				
			||||||
 | 
					        self.connect(self.select_vms_widget, SIGNAL("selected_changed()"), self.check_running)
 | 
				
			||||||
 | 
					        self.connect(self.select_vms_widget, SIGNAL("items_removed(list)"), self.vms_removed)
 | 
				
			||||||
 | 
					        self.connect(self.select_vms_widget, SIGNAL("items_added(list)"), self.vms_added)
 | 
				
			||||||
 | 
					        self.refresh_button.clicked.connect(self.check_running)
 | 
				
			||||||
 | 
					        self.shutdown_running_vms_button.clicked.connect(self.shutdown_all_running_selected)
 | 
				
			||||||
        self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated)
 | 
					        self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated)
 | 
				
			||||||
        self.connect(self, SIGNAL("backup_progress(int)"), self.progress_bar.setValue)
 | 
					        self.connect(self, SIGNAL("backup_progress(int)"), self.progress_bar.setValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -89,30 +98,126 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
				
			|||||||
        #FIXME
 | 
					        #FIXME
 | 
				
			||||||
        #this causes to run isComplete() twice, I don't know why
 | 
					        #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.select_vms_page.connect(self.select_vms_widget, SIGNAL("selected_changed()"), SIGNAL("completeChanged()")) 
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        self.total_size = 0
 | 
				
			||||||
        self.__fill_vms_list__()
 | 
					        self.__fill_vms_list__()
 | 
				
			||||||
        fill_devs_list(self)
 | 
					        fill_devs_list(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def show_running_vms_warning(self, show):
 | 
				
			||||||
 | 
					        self.running_vms_warning.setVisible(show)
 | 
				
			||||||
 | 
					        self.shutdown_running_vms_button.setVisible(show)
 | 
				
			||||||
 | 
					        self.refresh_button.setVisible(show)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class VmListItem(QListWidgetItem):
 | 
				
			||||||
 | 
					        def __init__(self, vm):
 | 
				
			||||||
 | 
					            self.vm = vm
 | 
				
			||||||
 | 
					            if vm.qid == 0:
 | 
				
			||||||
 | 
					                local_user = grp.getgrnam('qubes').gr_mem[0]
 | 
				
			||||||
 | 
					                home_dir = pwd.getpwnam(local_user).pw_dir
 | 
				
			||||||
 | 
					                self.size = qubesutils.get_disk_usage(home_dir)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                self.size = self.get_vm_size(vm) 
 | 
				
			||||||
 | 
					            super(BackupVMsWindow.VmListItem, self).__init__(vm.name+ " (" + qubesutils.size_to_human(self.size) + ")")
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        def get_vm_size(self, vm):
 | 
				
			||||||
 | 
					            size = 0
 | 
				
			||||||
 | 
					            if vm.private_img is not None:
 | 
				
			||||||
 | 
					                size += vm.get_disk_usage (vm.private_img)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if vm.updateable:
 | 
				
			||||||
 | 
					                size += vm.get_disk_usage(vm.root_img)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __fill_vms_list__(self):
 | 
					    def __fill_vms_list__(self):
 | 
				
			||||||
        for vm in self.qvm_collection.values():
 | 
					        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:
 | 
					            if vm.is_appvm() and vm.internal:
 | 
				
			||||||
                self.excluded.append(vm.name)
 | 
					 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if vm.is_template() and vm.installed_by_rpm:
 | 
					            if vm.is_template() and vm.installed_by_rpm:
 | 
				
			||||||
                self.excluded.append(vm.name)
 | 
					 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            item = BackupVMsWindow.VmListItem(vm)
 | 
				
			||||||
            if vm.include_in_backups == True:
 | 
					            if vm.include_in_backups == True:
 | 
				
			||||||
                self.select_vms_widget.selected_list.addItem(vm.name)
 | 
					                self.select_vms_widget.selected_list.addItem(item)
 | 
				
			||||||
 | 
					                self.total_size += item.size
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                self.select_vms_widget.available_list.addItem(vm.name)
 | 
					                self.select_vms_widget.available_list.addItem(item)
 | 
				
			||||||
 | 
					        self.check_running()
 | 
				
			||||||
 | 
					        self.total_size_label.setText(qubesutils.size_to_human(self.total_size))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def vms_added(self, items):
 | 
				
			||||||
 | 
					        for i in items:
 | 
				
			||||||
 | 
					            self.total_size += i.size
 | 
				
			||||||
 | 
					        self.total_size_label.setText(qubesutils.size_to_human(self.total_size))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def vms_removed(self, items):
 | 
				
			||||||
 | 
					        for i in items:
 | 
				
			||||||
 | 
					            self.total_size -= i.size
 | 
				
			||||||
 | 
					        self.total_size_label.setText(qubesutils.size_to_human(self.total_size))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def check_running(self):
 | 
				
			||||||
 | 
					        some_selected_vms_running = False
 | 
				
			||||||
 | 
					        for i in range(self.select_vms_widget.selected_list.count()):
 | 
				
			||||||
 | 
					            item = self.select_vms_widget.selected_list.item(i)
 | 
				
			||||||
 | 
					            if item.vm.is_running() and item.vm.qid != 0:
 | 
				
			||||||
 | 
					                item.setForeground(QBrush(QColor(255, 0, 0)))
 | 
				
			||||||
 | 
					                some_selected_vms_running = True
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                item.setForeground(QBrush(QColor(0, 0, 0)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.show_running_vms_warning(some_selected_vms_running)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        for i in range(self.select_vms_widget.available_list.count()):
 | 
				
			||||||
 | 
					            item =  self.select_vms_widget.available_list.item(i)
 | 
				
			||||||
 | 
					            if item.vm.is_running() and item.vm.qid != 0:
 | 
				
			||||||
 | 
					                item.setForeground(QBrush(QColor(255, 0, 0)))
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                item.setForeground(QBrush(QColor(0, 0, 0)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return some_selected_vms_running
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def shutdown_all_running_selected(self):
 | 
				
			||||||
 | 
					        names = []
 | 
				
			||||||
 | 
					        vms = []
 | 
				
			||||||
 | 
					        for i in range(self.select_vms_widget.selected_list.count()):
 | 
				
			||||||
 | 
					            item = self.select_vms_widget.selected_list.item(i)
 | 
				
			||||||
 | 
					            if item.vm.is_running() and item.vm.qid != 0:
 | 
				
			||||||
 | 
					                names.append(item.vm.name)
 | 
				
			||||||
 | 
					                vms.append(item.vm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if len(vms) == 0:
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        reply = QMessageBox.question(None, "VM Shutdown Confirmation",
 | 
				
			||||||
 | 
					                                     "Are you sure you want to power down the following VMs: <b>{0}</b>?<br>"
 | 
				
			||||||
 | 
					                                     "<small>This will shutdown all the running applications within them.</small>".format(', '.join(names)),
 | 
				
			||||||
 | 
					                                     QMessageBox.Yes | QMessageBox.Cancel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.app.processEvents()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if reply == QMessageBox.Yes:
 | 
				
			||||||
 | 
					            for vm in vms:
 | 
				
			||||||
 | 
					                self.shutdown_vm_func(vm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            progress = QProgressDialog ("Shutting down VMs <b>{0}</b>...".format(', '.join(names)), "", 0, 0)
 | 
				
			||||||
 | 
					            progress.setModal(True)
 | 
				
			||||||
 | 
					            progress.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            wait_time = 15.0
 | 
				
			||||||
 | 
					            wait_for = wait_time
 | 
				
			||||||
 | 
					            while self.check_running() and wait_for > 0:
 | 
				
			||||||
 | 
					                self.app.processEvents()
 | 
				
			||||||
 | 
					                time.sleep (0.1)
 | 
				
			||||||
 | 
					                wait_for -= 0.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            progress.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if self.check_running():
 | 
				
			||||||
 | 
					                QMessageBox.information(None, "Strange", "Could not power down the VMs in {0} seconds...".format(wait_time))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
					 | 
				
			||||||
    def dev_combobox_activated(self, idx):
 | 
					    def dev_combobox_activated(self, idx):
 | 
				
			||||||
        dev_combobox_activated(self, idx)
 | 
					        dev_combobox_activated(self, idx)
 | 
				
			||||||
                   
 | 
					                   
 | 
				
			||||||
@ -123,17 +228,30 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def validateCurrentPage(self):
 | 
					    def validateCurrentPage(self):
 | 
				
			||||||
        if self.currentPage() is self.select_vms_page:
 | 
					        if self.currentPage() is self.select_vms_page:
 | 
				
			||||||
 | 
					            for i in range(self.select_vms_widget.selected_list.count()):
 | 
				
			||||||
 | 
					                if self.check_running() == True:
 | 
				
			||||||
 | 
					                    QMessageBox.information(None, "Wait!", "Some selected VMs are running. Running VMs can not be backuped. Please shut them down or remove them from the list.")
 | 
				
			||||||
 | 
					                    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            del self.excluded[:]
 | 
				
			||||||
            for i in range(self.select_vms_widget.available_list.count()):
 | 
					            for i in range(self.select_vms_widget.available_list.count()):
 | 
				
			||||||
                vmname =  self.select_vms_widget.available_list.item(i).text()
 | 
					                vmname =  self.select_vms_widget.available_list.item(i).vm.name
 | 
				
			||||||
                self.excluded.append(vmname)
 | 
					                self.excluded.append(vmname)
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def gather_output(self, s):
 | 
					    def gather_output(self, s):
 | 
				
			||||||
        self.func_output.append(s)
 | 
					        self.func_output.append(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_progress_bar(self, value):
 | 
					    def update_progress_bar(self, value):
 | 
				
			||||||
        self.emit(SIGNAL("backup_progress(int)"), value)
 | 
					        if value == 100:
 | 
				
			||||||
 | 
					            self.emit(SIGNAL("backup_progress(int)"), value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def check_backup_progress(self, initial_usage, total_backup_size):
 | 
				
			||||||
 | 
					        du = qubesutils.get_disk_usage(self.backup_dir)
 | 
				
			||||||
 | 
					        done = du - initial_usage
 | 
				
			||||||
 | 
					        percent = int((float(done)/total_backup_size)*100)
 | 
				
			||||||
 | 
					        return percent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __do_backup__(self, thread_monitor):
 | 
					    def __do_backup__(self, thread_monitor):
 | 
				
			||||||
        msg = []
 | 
					        msg = []
 | 
				
			||||||
@ -152,23 +270,34 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
				
			|||||||
    def current_page_changed(self, id):
 | 
					    def current_page_changed(self, id):
 | 
				
			||||||
        if self.currentPage() is self.confirm_page:
 | 
					        if self.currentPage() is self.confirm_page:
 | 
				
			||||||
            del self.func_output[:]
 | 
					            del self.func_output[:]
 | 
				
			||||||
            self.files_to_backup = qubesutils.backup_prepare(str(self.backup_dir), exclude_list = self.excluded, print_callback = self.gather_output)
 | 
					            try:
 | 
				
			||||||
 | 
					                self.files_to_backup = qubesutils.backup_prepare(str(self.backup_dir), exclude_list = self.excluded, print_callback = self.gather_output)
 | 
				
			||||||
 | 
					            except Exception as ex:
 | 
				
			||||||
 | 
					                QMessageBox.critical(None, "Error while prepering backup.", "ERROR: {0}".format(ex))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.textEdit.setReadOnly(True)
 | 
					            self.textEdit.setReadOnly(True)
 | 
				
			||||||
            self.textEdit.setFontFamily("Monospace")
 | 
					            self.textEdit.setFontFamily("Monospace")
 | 
				
			||||||
            self.textEdit.setText("\n".join(self.func_output))
 | 
					            self.textEdit.setText("\n".join(self.func_output))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elif self.currentPage() is self.commit_page:
 | 
					        elif self.currentPage() is self.commit_page:
 | 
				
			||||||
            self.button(self.CancelButton).setDisabled(True)
 | 
					 | 
				
			||||||
            self.button(self.FinishButton).setDisabled(True)
 | 
					            self.button(self.FinishButton).setDisabled(True)
 | 
				
			||||||
 | 
					            self.button(self.CancelButton).setDisabled(True)
 | 
				
			||||||
            self.thread_monitor = ThreadMonitor()
 | 
					            self.thread_monitor = ThreadMonitor()
 | 
				
			||||||
 | 
					            initial_usage = qubesutils.get_disk_usage(self.backup_dir)
 | 
				
			||||||
            thread = threading.Thread (target= self.__do_backup__ , args=(self.thread_monitor,))
 | 
					            thread = threading.Thread (target= self.__do_backup__ , args=(self.thread_monitor,))
 | 
				
			||||||
            thread.daemon = True
 | 
					            thread.daemon = True
 | 
				
			||||||
            thread.start()
 | 
					            thread.start()
 | 
				
			||||||
 | 
					            self.button(self.CancelButton).setDisabled(False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            counter = 0
 | 
				
			||||||
            while not self.thread_monitor.is_finished():
 | 
					            while not self.thread_monitor.is_finished():
 | 
				
			||||||
                self.app.processEvents()
 | 
					                self.app.processEvents()
 | 
				
			||||||
                time.sleep (0.1)
 | 
					                time.sleep (0.1)
 | 
				
			||||||
 | 
					                counter += 1
 | 
				
			||||||
 | 
					                if counter == 20:
 | 
				
			||||||
 | 
					                    progress = self.check_backup_progress(initial_usage, self.total_size)
 | 
				
			||||||
 | 
					                    self.progress_bar.setValue(progress)
 | 
				
			||||||
 | 
					                    counter = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if not self.thread_monitor.success:
 | 
					            if not self.thread_monitor.success:
 | 
				
			||||||
                QMessageBox.warning (None, "Backup error!", "ERROR: {1}".format(self.vm.name, self.thread_monitor.error_msg))
 | 
					                QMessageBox.warning (None, "Backup error!", "ERROR: {1}".format(self.vm.name, self.thread_monitor.error_msg))
 | 
				
			||||||
@ -179,6 +308,25 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
				
			|||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reject(self):
 | 
					    def reject(self):
 | 
				
			||||||
 | 
					        #cancell clicked while the backup is in progress.
 | 
				
			||||||
 | 
					        #calling kill on cp.
 | 
				
			||||||
 | 
					        if self.currentPage() is self.commit_page:
 | 
				
			||||||
 | 
					            manager_pid = os.getpid()
 | 
				
			||||||
 | 
					            cp_pid_cmd = ["ps" ,"--ppid", str(manager_pid)]
 | 
				
			||||||
 | 
					            pid = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            while not self.thread_monitor.is_finished():
 | 
				
			||||||
 | 
					                cp_pid = subprocess.Popen(cp_pid_cmd, stdout = subprocess.PIPE)
 | 
				
			||||||
 | 
					                output = cp_pid.stdout.read().split("\n")
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                for l in output:
 | 
				
			||||||
 | 
					                    if l.endswith("cp"):
 | 
				
			||||||
 | 
					                        pid = l.split(" ")[1]
 | 
				
			||||||
 | 
					                        break
 | 
				
			||||||
 | 
					                if pid != None:
 | 
				
			||||||
 | 
					                    os.kill(int(pid), signal.SIGTERM)
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.dev_mount_path != None:
 | 
					        if self.dev_mount_path != None:
 | 
				
			||||||
            umount_device(self.dev_mount_path)
 | 
					            umount_device(self.dev_mount_path)
 | 
				
			||||||
        self.done(0)
 | 
					        self.done(0)
 | 
				
			||||||
@ -213,8 +361,6 @@ def handle_exception( exc_type, exc_value, exc_traceback ):
 | 
				
			|||||||
                         % ( line, filename ))
 | 
					                         % ( line, filename ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def main():
 | 
					def main():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    global qubes_host
 | 
					    global qubes_host
 | 
				
			||||||
 | 
				
			|||||||
@ -72,6 +72,8 @@ def umount_device(dev_mount_path):
 | 
				
			|||||||
def fill_devs_list(dialog):
 | 
					def fill_devs_list(dialog):
 | 
				
			||||||
    dialog.dev_combobox.clear()
 | 
					    dialog.dev_combobox.clear()
 | 
				
			||||||
    dialog.dev_combobox.addItem("None")
 | 
					    dialog.dev_combobox.addItem("None")
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    dialog.blk_manager.blk_lock.acquire()
 | 
				
			||||||
    for a in dialog.blk_manager.attached_devs:
 | 
					    for a in dialog.blk_manager.attached_devs:
 | 
				
			||||||
        if dialog.blk_manager.attached_devs[a]['attached_to']['vm'] == dialog.vm.name :
 | 
					        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']
 | 
					            att = a + " " + unicode(dialog.blk_manager.attached_devs[a]['size']) + " " + dialog.blk_manager.attached_devs[a]['desc']
 | 
				
			||||||
@ -79,6 +81,8 @@ def fill_devs_list(dialog):
 | 
				
			|||||||
    for a in dialog.blk_manager.free_devs:
 | 
					    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']
 | 
					        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.addItem(att, QVariant(a))
 | 
				
			||||||
 | 
					    dialog.blk_manager.blk_lock.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dialog.dev_combobox.setCurrentIndex(0) #current selected is null ""
 | 
					    dialog.dev_combobox.setCurrentIndex(0) #current selected is null ""
 | 
				
			||||||
    dialog.prev_dev_idx = 0
 | 
					    dialog.prev_dev_idx = 0
 | 
				
			||||||
    dialog.dir_line_edit.clear()
 | 
					    dialog.dir_line_edit.clear()
 | 
				
			||||||
@ -107,6 +111,7 @@ def dev_combobox_activated(dialog, idx):
 | 
				
			|||||||
    if dialog.dev_combobox.currentText() != "None":   #An existing device chosen 
 | 
					    if dialog.dev_combobox.currentText() != "None":   #An existing device chosen 
 | 
				
			||||||
        dev_name = str(dialog.dev_combobox.itemData(idx).toString())
 | 
					        dev_name = str(dialog.dev_combobox.itemData(idx).toString())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dialog.blk_manager.blk_lock.acquire()
 | 
				
			||||||
        if dev_name in dialog.blk_manager.free_devs:
 | 
					        if dev_name in dialog.blk_manager.free_devs:
 | 
				
			||||||
            if dev_name.startswith(dialog.vm.name):       # originally attached to dom0
 | 
					            if dev_name.startswith(dialog.vm.name):       # originally attached to dom0
 | 
				
			||||||
                dev_path = "/dev/"+dev_name.split(":")[1]
 | 
					                dev_path = "/dev/"+dev_name.split(":")[1]
 | 
				
			||||||
@ -118,6 +123,7 @@ def dev_combobox_activated(dialog, idx):
 | 
				
			|||||||
        if dev_name in dialog.blk_manager.attached_devs:       #is attached to dom0
 | 
					        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
 | 
					            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']
 | 
					            dev_path = "/dev/" + dialog.blk_manager.attached_devs[dev_name]['attached_to']['frontend']
 | 
				
			||||||
 | 
					        dialog.blk_manager.blk_lock.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #check if device mounted
 | 
					        #check if device mounted
 | 
				
			||||||
        dialog.dev_mount_path = check_if_mounted(dev_path)
 | 
					        dialog.dev_mount_path = check_if_mounted(dev_path)
 | 
				
			||||||
 | 
				
			|||||||
@ -43,7 +43,12 @@ from operator import itemgetter
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from ui_globalsettingsdlg import *
 | 
					from ui_globalsettingsdlg import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ConfigParser import SafeConfigParser
 | 
				
			||||||
 | 
					from qubes.qubesutils import parse_size
 | 
				
			||||||
 | 
					from qubes import qmemman_algo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dont_keep_dvm_in_memory_path = '/var/lib/qubes/dvmdata/dont_use_shm'
 | 
					dont_keep_dvm_in_memory_path = '/var/lib/qubes/dvmdata/dont_use_shm'
 | 
				
			||||||
 | 
					qmemman_config_path = '/etc/qubes/qmemman.conf'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GlobalSettingsWindow(Ui_GlobalSettings, QDialog):
 | 
					class GlobalSettingsWindow(Ui_GlobalSettings, QDialog):
 | 
				
			||||||
@ -187,13 +192,80 @@ class GlobalSettingsWindow(Ui_GlobalSettings, QDialog):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    def __init_mem_defaults__(self):
 | 
					    def __init_mem_defaults__(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #qmemman settings
 | 
				
			||||||
 | 
					        self.qmemman_config = SafeConfigParser()
 | 
				
			||||||
 | 
					        self.vm_min_mem_val =  str(qmemman_algo.MIN_PREFMEM)
 | 
				
			||||||
 | 
					        self.dom0_mem_boost_val = str(qmemman_algo.DOM0_MEM_BOOST)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        self.qmemman_config.read(qmemman_config_path)
 | 
				
			||||||
 | 
					        if self.qmemman_config.has_section('global'):
 | 
				
			||||||
 | 
					            self.vm_min_mem_val = self.qmemman_config.get('global', 'vm-min-mem')
 | 
				
			||||||
 | 
					            self.dom0_mem_boost_val = self.qmemman_config.get('global', 'dom0-mem-boost')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.vm_min_mem_val = parse_size(self.vm_min_mem_val)
 | 
				
			||||||
 | 
					        self.dom0_mem_boost_val = parse_size(self.dom0_mem_boost_val)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.min_vm_mem.setValue(self.vm_min_mem_val/1024/1024)
 | 
				
			||||||
 | 
					        self.dom0_mem_boost.setValue(self.dom0_mem_boost_val/1024/1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #keep dispvm in memory
 | 
					        #keep dispvm in memory
 | 
				
			||||||
        exists = os.path.exists(dont_keep_dvm_in_memory_path)
 | 
					        exists = os.path.exists(dont_keep_dvm_in_memory_path)
 | 
				
			||||||
        self.dispvm_in_memory.setChecked( not exists)
 | 
					        self.dispvm_in_memory.setChecked( not exists)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def __apply_mem_defaults__(self):
 | 
					    def __apply_mem_defaults__(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #qmemman settings
 | 
				
			||||||
 | 
					        current_min_vm_mem = self.min_vm_mem.value()
 | 
				
			||||||
 | 
					        current_dom0_mem_boost = self.dom0_mem_boost.value()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if current_min_vm_mem*1024*1024 != self.vm_min_mem_val or current_dom0_mem_boost*1024*1024 != self.dom0_mem_boost_val:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            current_min_vm_mem = str(current_min_vm_mem)+'M'
 | 
				
			||||||
 | 
					            current_dom0_mem_boost = str(current_dom0_mem_boost)+'M'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if not self.qmemman_config.has_section('global'):
 | 
				
			||||||
 | 
					                #add the whole section
 | 
				
			||||||
 | 
					                self.qmemman_config.add_section('global')
 | 
				
			||||||
 | 
					                self.qmemman_config.set('global', 'vm-min-mem', current_min_vm_mem)
 | 
				
			||||||
 | 
					                self.qmemman_config.set('global', 'dom0-mem-boost', current_dom0_mem_boost)
 | 
				
			||||||
 | 
					                self.qmemman_config.set('global', 'cache-margin-factor', str(qmemman_algo.CACHE_FACTOR))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                qmemman_config_file = open(qmemman_config_path, 'a')
 | 
				
			||||||
 | 
					                self.qmemman_config.write(qmemman_config_file)
 | 
				
			||||||
 | 
					                qmemman_config_file.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                #If there already is a 'global' section, we don't use SafeConfigParser.write() - it would get rid of all the comments...
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                lines_to_add = {}
 | 
				
			||||||
 | 
					                lines_to_add['vm-min-mem'] = "vm-min-mem = " + current_min_vm_mem + "\n"
 | 
				
			||||||
 | 
					                lines_to_add['dom0-mem-boost'] = "dom0-mem-boost = " + current_dom0_mem_boost +"\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                config_lines = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                qmemman_config_file = open(qmemman_config_path, 'r')
 | 
				
			||||||
 | 
					                for l in qmemman_config_file:
 | 
				
			||||||
 | 
					                    if l.strip().startswith('vm-min-mem'):
 | 
				
			||||||
 | 
					                        config_lines.append(lines_to_add['vm-min-mem'])
 | 
				
			||||||
 | 
					                        del lines_to_add['vm-min-mem']
 | 
				
			||||||
 | 
					                    elif l.strip().startswith('dom0-mem-boost'):
 | 
				
			||||||
 | 
					                        config_lines.append(lines_to_add['dom0-mem-boost'])
 | 
				
			||||||
 | 
					                        del lines_to_add['dom0-mem-boost']
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        config_lines.append(l)
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                qmemman_config_file.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for l in lines_to_add:
 | 
				
			||||||
 | 
					                    config_lines.append(l)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                qmemman_config_file = open(qmemman_config_path, 'w')
 | 
				
			||||||
 | 
					                qmemman_config_file.writelines(config_lines)
 | 
				
			||||||
 | 
					                qmemman_config_file.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.anything_changed = True
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        #keep dispvm in memory
 | 
					        #keep dispvm in memory
 | 
				
			||||||
        was_checked = not os.path.exists(dont_keep_dvm_in_memory_path)
 | 
					        was_checked = not os.path.exists(dont_keep_dvm_in_memory_path)
 | 
				
			||||||
@ -206,6 +278,7 @@ class GlobalSettingsWindow(Ui_GlobalSettings, QDialog):
 | 
				
			|||||||
                os.remove(dont_keep_dvm_in_memory_path)
 | 
					                os.remove(dont_keep_dvm_in_memory_path)
 | 
				
			||||||
            self.anything_changed = True
 | 
					            self.anything_changed = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reject(self):
 | 
					    def reject(self):
 | 
				
			||||||
        self.done(0)
 | 
					        self.done(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -557,9 +557,14 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 | 
				
			|||||||
        self.setupUi(self)
 | 
					        self.setupUi(self)
 | 
				
			||||||
        self.toolbar = self.toolBar
 | 
					        self.toolbar = self.toolBar
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        self.qubes_watch = qubesutils.QubesWatch()
 | 
				
			||||||
        self.qvm_collection = QubesVmCollection()
 | 
					        self.qvm_collection = QubesVmCollection()
 | 
				
			||||||
        self.blk_manager = QubesBlockDevicesManager(self.qvm_collection)
 | 
					        self.blk_manager = QubesBlockDevicesManager(self.qvm_collection)
 | 
				
			||||||
        
 | 
					        self.qubes_watch.setup_block_watch(self.blk_manager.block_devs_event)
 | 
				
			||||||
 | 
					        self.blk_watch_thread = threading.Thread(target=self.qubes_watch.watch_loop)
 | 
				
			||||||
 | 
					        self.blk_watch_thread.daemon = True
 | 
				
			||||||
 | 
					        self.blk_watch_thread.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.connect(self.table, SIGNAL("itemSelectionChanged()"), self.table_selection_changed)
 | 
					        self.connect(self.table, SIGNAL("itemSelectionChanged()"), self.table_selection_changed)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        self.table.setColumnWidth(0, self.column_width)
 | 
					        self.table.setColumnWidth(0, self.column_width)
 | 
				
			||||||
@ -794,8 +799,10 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 | 
				
			|||||||
            rows_with_blk = None
 | 
					            rows_with_blk = None
 | 
				
			||||||
            if update_devs == True:
 | 
					            if update_devs == True:
 | 
				
			||||||
                rows_with_blk = []
 | 
					                rows_with_blk = []
 | 
				
			||||||
 | 
					                self.blk_manager.blk_lock.acquire()
 | 
				
			||||||
                for d in self.blk_manager.attached_devs:
 | 
					                for d in self.blk_manager.attached_devs:
 | 
				
			||||||
                    rows_with_blk.append( self.blk_manager.attached_devs[d]['attached_to']['vm'])
 | 
					                    rows_with_blk.append( self.blk_manager.attached_devs[d]['attached_to']['vm'])
 | 
				
			||||||
 | 
					                self.blk_manager.blk_lock.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self.counter % 3 == 0 or out_of_schedule:
 | 
					            if self.counter % 3 == 0 or out_of_schedule:
 | 
				
			||||||
                (self.last_measure_time, self.last_measure_results) = \
 | 
					                (self.last_measure_time, self.last_measure_results) = \
 | 
				
			||||||
@ -843,7 +850,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
    def update_block_devices(self):
 | 
					    def update_block_devices(self):
 | 
				
			||||||
        res, msg = self.blk_manager.update()
 | 
					        res, msg = self.blk_manager.check_for_updates()
 | 
				
			||||||
        if msg != None and len(msg) > 0:
 | 
					        if msg != None and len(msg) > 0:
 | 
				
			||||||
            str = "\n".join(msg)
 | 
					            str = "\n".join(msg)
 | 
				
			||||||
            trayIcon.showMessage ("Qubes Manager", str, msecs=5000)
 | 
					            trayIcon.showMessage ("Qubes Manager", str, msecs=5000)
 | 
				
			||||||
@ -1142,16 +1149,22 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 | 
				
			|||||||
        app.processEvents()
 | 
					        app.processEvents()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if reply == QMessageBox.Yes:
 | 
					        if reply == QMessageBox.Yes:
 | 
				
			||||||
            try:
 | 
					            self.shutdown_vm(vm)
 | 
				
			||||||
                subprocess.check_call (["/usr/sbin/xl", "shutdown", vm.name])
 | 
					
 | 
				
			||||||
            except Exception as ex:
 | 
					
 | 
				
			||||||
                QMessageBox.warning (None, "Error shutting down VM!", "ERROR: {0}".format(ex))
 | 
					    def shutdown_vm(self, vm):
 | 
				
			||||||
                return
 | 
					        try:
 | 
				
			||||||
 | 
					            subprocess.check_call (["/usr/sbin/xl", "shutdown", vm.name])
 | 
				
			||||||
 | 
					        except Exception as ex:
 | 
				
			||||||
 | 
					            QMessageBox.warning (None, "Error shutting down VM!", "ERROR: {0}".format(ex))
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        trayIcon.showMessage ("Qubes Manager", "VM '{0}' is shutting down...".format(vm.name), msecs=3000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.shutdown_monitor[vm.qid] = VmShutdownMonitor (vm)
 | 
				
			||||||
 | 
					        QTimer.singleShot (vm_shutdown_timeout, self.shutdown_monitor[vm.qid].check_if_vm_has_shutdown)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            trayIcon.showMessage ("Qubes Manager", "VM '{0}' is shutting down...".format(vm.name), msecs=3000)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.shutdown_monitor[vm.qid] = VmShutdownMonitor (vm)
 | 
					 | 
				
			||||||
            QTimer.singleShot (vm_shutdown_timeout, self.shutdown_monitor[vm.qid].check_if_vm_has_shutdown)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pyqtSlot(name='on_action_settings_triggered')
 | 
					    @pyqtSlot(name='on_action_settings_triggered')
 | 
				
			||||||
    def action_settings_triggered(self):
 | 
					    def action_settings_triggered(self):
 | 
				
			||||||
@ -1235,7 +1248,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @pyqtSlot(name='on_action_backup_triggered')
 | 
					    @pyqtSlot(name='on_action_backup_triggered')
 | 
				
			||||||
    def action_backup_triggered(self):
 | 
					    def action_backup_triggered(self):
 | 
				
			||||||
        backup_window = BackupVMsWindow(app, self.qvm_collection, self.blk_manager)
 | 
					        backup_window = BackupVMsWindow(app, self.qvm_collection, self.blk_manager, self.shutdown_vm)
 | 
				
			||||||
        backup_window.exec_()
 | 
					        backup_window.exec_()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1298,6 +1311,8 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.blk_menu.clear()
 | 
					            self.blk_menu.clear()
 | 
				
			||||||
            self.blk_menu.setEnabled(True)
 | 
					            self.blk_menu.setEnabled(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.blk_manager.blk_lock.acquire()
 | 
				
			||||||
            if len(self.blk_manager.attached_devs) > 0 :
 | 
					            if len(self.blk_manager.attached_devs) > 0 :
 | 
				
			||||||
                for d in self.blk_manager.attached_devs:
 | 
					                for d in self.blk_manager.attached_devs:
 | 
				
			||||||
                    if self.blk_manager.attached_devs[d]['attached_to']['vm'] == vm.name:
 | 
					                    if self.blk_manager.attached_devs[d]['attached_to']['vm'] == vm.name:
 | 
				
			||||||
@ -1313,6 +1328,8 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 | 
				
			|||||||
                    action = self.blk_menu.addAction(QIcon(":/add.png"), str)
 | 
					                    action = self.blk_menu.addAction(QIcon(":/add.png"), str)
 | 
				
			||||||
                    action.setData(QVariant(d))
 | 
					                    action.setData(QVariant(d))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.blk_manager.blk_lock.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self.blk_menu.isEmpty():
 | 
					            if self.blk_menu.isEmpty():
 | 
				
			||||||
                self.blk_menu.setEnabled(False)
 | 
					                self.blk_menu.setEnabled(False)
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
@ -1322,10 +1339,13 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
 | 
				
			|||||||
    def attach_dettach_device_triggered(self, action):
 | 
					    def attach_dettach_device_triggered(self, action):
 | 
				
			||||||
        dev = str(action.data().toString())
 | 
					        dev = str(action.data().toString())
 | 
				
			||||||
        vm = self.get_selected_vm()
 | 
					        vm = self.get_selected_vm()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.blk_manager.blk_lock.acquire()
 | 
				
			||||||
        if dev in self.blk_manager.attached_devs:
 | 
					        if dev in self.blk_manager.attached_devs:
 | 
				
			||||||
            self.blk_manager.detach_device(vm, dev)
 | 
					            self.blk_manager.detach_device(vm, dev)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.blk_manager.attach_device(vm, dev)
 | 
					            self.blk_manager.attach_device(vm, dev)
 | 
				
			||||||
 | 
					        self.blk_manager.blk_lock.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class QubesBlockDevicesManager():
 | 
					class QubesBlockDevicesManager():
 | 
				
			||||||
@ -1338,43 +1358,75 @@ class QubesBlockDevicesManager():
 | 
				
			|||||||
        self.current_attached = {}
 | 
					        self.current_attached = {}
 | 
				
			||||||
        self.devs_changed = False
 | 
					        self.devs_changed = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.last_update_time = time.time()
 | 
				
			||||||
 | 
					        self.blk_state_changed = True
 | 
				
			||||||
 | 
					        self.msg = []
 | 
				
			||||||
 | 
					        self.check_counter = 0
 | 
				
			||||||
 | 
					        self.blk_lock = threading.Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def block_devs_event(self, xid):
 | 
				
			||||||
 | 
					        now = time.time()
 | 
				
			||||||
 | 
					        #don't update more often than 1/10 s
 | 
				
			||||||
 | 
					        if now - self.last_update_time >= 0.1:
 | 
				
			||||||
 | 
					            self.last_update_time = now
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.blk_lock.acquire()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.blk_state_changed = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.blk_lock.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def check_for_updates(self):
 | 
				
			||||||
 | 
					        self.blk_lock.acquire()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ret = (self.blk_state_changed, self.msg)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if self.blk_state_changed == True:
 | 
				
			||||||
 | 
					            self.check_counter += 1
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            self.update()
 | 
				
			||||||
 | 
					            ret = (self.blk_state_changed, self.msg)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            #let the update last for 3 manager-update cycles
 | 
				
			||||||
 | 
					            if self.check_counter == 3:
 | 
				
			||||||
 | 
					                self.check_counter = 0
 | 
				
			||||||
 | 
					                self.blk_state_changed = False
 | 
				
			||||||
 | 
					        self.msg = []            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.blk_lock.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ret
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
    def update(self):
 | 
					    def update(self):
 | 
				
			||||||
        blk = qubesutils.block_list()
 | 
					        blk = qubesutils.block_list()
 | 
				
			||||||
        msg = []
 | 
					 | 
				
			||||||
        for b in blk:
 | 
					        for b in blk:
 | 
				
			||||||
            att = qubesutils.block_check_attached(None, blk[b]['device'], backend_xid = blk[b]['xid'])
 | 
					            att = qubesutils.block_check_attached(None, blk[b]['device'], backend_xid = blk[b]['xid'])
 | 
				
			||||||
            if b in self.current_blk:
 | 
					            if b in self.current_blk:
 | 
				
			||||||
                if blk[b] == self.current_blk[b]:
 | 
					                if blk[b] == self.current_blk[b]:
 | 
				
			||||||
                    if self.current_attached[b] != att: #devices the same, sth with attaching changed
 | 
					                    if self.current_attached[b] != att: #devices the same, sth with attaching changed
 | 
				
			||||||
                        self.current_attached[b] = att
 | 
					                        self.current_attached[b] = att
 | 
				
			||||||
                        self.devs_changed = True
 | 
					 | 
				
			||||||
                else:   #device changed ?!
 | 
					                else:   #device changed ?!
 | 
				
			||||||
                    self.current_blk[b] = blk[b]
 | 
					                    self.current_blk[b] = blk[b]
 | 
				
			||||||
                    self.current_attached[b] = att
 | 
					                    self.current_attached[b] = att
 | 
				
			||||||
                    self.devs_changed = True
 | 
					 | 
				
			||||||
            else: #new device
 | 
					            else: #new device
 | 
				
			||||||
                self.current_blk[b] = blk[b]
 | 
					                self.current_blk[b] = blk[b]
 | 
				
			||||||
                self.current_attached[b] = att
 | 
					                self.current_attached[b] = att
 | 
				
			||||||
                self.devs_changed = True
 | 
					                self.msg.append("Attached new device: {0}".format(blk[b]['device']))
 | 
				
			||||||
                msg.append("Attached new device: {0}".format(blk[b]['device']))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        to_delete = []
 | 
					        to_delete = []
 | 
				
			||||||
        for b in self.current_blk: #remove devices that are not there anymore
 | 
					        for b in self.current_blk: #remove devices that are not there anymore
 | 
				
			||||||
            if b not in blk:
 | 
					            if b not in blk:
 | 
				
			||||||
                to_delete.append(b)
 | 
					                to_delete.append(b)
 | 
				
			||||||
                self.devs_changed = True
 | 
					                self.msg.append("Detached device: {0}".format(self.current_blk[b]['device']))
 | 
				
			||||||
                msg.append("Detached device: {0}".format(self.current_blk[b]['device']))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for d in to_delete:
 | 
					        for d in to_delete:
 | 
				
			||||||
            del self.current_blk[d]
 | 
					            del self.current_blk[d]
 | 
				
			||||||
            del self.current_attached[d]
 | 
					            del self.current_attached[d]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.devs_changed == True:
 | 
					        self.__update_blk_entries__()
 | 
				
			||||||
            self.devs_changed = False
 | 
					 | 
				
			||||||
            self.__update_blk_entries__()
 | 
					 | 
				
			||||||
            return True, msg
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return False, None
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __update_blk_entries__(self):
 | 
					    def __update_blk_entries__(self):
 | 
				
			||||||
@ -1402,16 +1454,12 @@ class QubesBlockDevicesManager():
 | 
				
			|||||||
        backend_vm = self.qvm_collection.get_vm_by_name(backend_vm_name)
 | 
					        backend_vm = self.qvm_collection.get_vm_by_name(backend_vm_name)
 | 
				
			||||||
        trayIcon.showMessage ("Qubes Manager", "{0} - attaching {1}".format(vm.name, dev), msecs=3000)
 | 
					        trayIcon.showMessage ("Qubes Manager", "{0} - attaching {1}".format(vm.name, dev), msecs=3000)
 | 
				
			||||||
        qubesutils.block_attach(vm, backend_vm, dev_id)
 | 
					        qubesutils.block_attach(vm, backend_vm, dev_id)
 | 
				
			||||||
        self.devs_changed = True
 | 
					 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
    def detach_device(self, vm, dev_name):
 | 
					    def detach_device(self, vm, dev_name):
 | 
				
			||||||
        dev_id = self.attached_devs[dev_name]['attached_to']['devid']
 | 
					        dev_id = self.attached_devs[dev_name]['attached_to']['devid']
 | 
				
			||||||
        vm_xid = self.attached_devs[dev_name]['attached_to']['xid']
 | 
					        vm_xid = self.attached_devs[dev_name]['attached_to']['xid']
 | 
				
			||||||
        trayIcon.showMessage ("Qubes Manager", "{0} - detaching {1}".format(vm.name, dev_name), msecs=3000)
 | 
					        trayIcon.showMessage ("Qubes Manager", "{0} - detaching {1}".format(vm.name, dev_name), msecs=3000)
 | 
				
			||||||
        qubesutils.block_detach(None, dev_id, vm_xid)
 | 
					        qubesutils.block_detach(None, dev_id, vm_xid)
 | 
				
			||||||
        self.devs_changed = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class QubesTrayIcon(QSystemTrayIcon):
 | 
					class QubesTrayIcon(QSystemTrayIcon):
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,8 @@ from ui_multiselectwidget import *
 | 
				
			|||||||
class MultiSelectWidget(Ui_MultiSelectWidget, QWidget):
 | 
					class MultiSelectWidget(Ui_MultiSelectWidget, QWidget):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    __pyqtSignals__ = ("selected_changed()",)
 | 
					    __pyqtSignals__ = ("selected_changed()",)
 | 
				
			||||||
 | 
					    __pyqtSignals__ = ("items_added(list)",)
 | 
				
			||||||
 | 
					    __pyqtSignals__ = ("items_removed(list)",)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, parent=None):
 | 
					    def __init__(self, parent=None):
 | 
				
			||||||
        super(MultiSelectWidget, self).__init__()
 | 
					        super(MultiSelectWidget, self).__init__()
 | 
				
			||||||
@ -19,13 +21,19 @@ class MultiSelectWidget(Ui_MultiSelectWidget, QWidget):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def switch_selected(self, src, dst):
 | 
					    def switch_selected(self, src, dst):
 | 
				
			||||||
        selected = src.selectedItems()
 | 
					        selected = src.selectedItems()
 | 
				
			||||||
 | 
					        items = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for s in selected:
 | 
					        for s in selected:
 | 
				
			||||||
            row = src.indexFromItem(s).row()
 | 
					            row = src.indexFromItem(s).row()
 | 
				
			||||||
            item = src.takeItem(row)
 | 
					            item = src.takeItem(row)
 | 
				
			||||||
            dst.addItem(item)
 | 
					            dst.addItem(item)
 | 
				
			||||||
 | 
					            items.append(item)
 | 
				
			||||||
        dst.sortItems()
 | 
					        dst.sortItems()
 | 
				
			||||||
        self.emit(SIGNAL("selected_changed()"))
 | 
					        self.emit(SIGNAL("selected_changed()"))
 | 
				
			||||||
 | 
					        if src is self.selected_list:    
 | 
				
			||||||
 | 
					            self.emit(SIGNAL("items_removed(list)"), items)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.emit(SIGNAL("items_added(list)"), items)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_selected(self):
 | 
					    def add_selected(self):
 | 
				
			||||||
        self.switch_selected(self.available_list, self.selected_list)
 | 
					        self.switch_selected(self.available_list, self.selected_list)
 | 
				
			||||||
@ -34,11 +42,18 @@ class MultiSelectWidget(Ui_MultiSelectWidget, QWidget):
 | 
				
			|||||||
        self.switch_selected(self.selected_list, self.available_list)    
 | 
					        self.switch_selected(self.selected_list, self.available_list)    
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
    def move_all(self, src, dst):
 | 
					    def move_all(self, src, dst):
 | 
				
			||||||
 | 
					        items = []
 | 
				
			||||||
        while src.count() > 0:
 | 
					        while src.count() > 0:
 | 
				
			||||||
            item = src.takeItem(0)
 | 
					            item = src.takeItem(0)
 | 
				
			||||||
            dst.addItem(item)
 | 
					            dst.addItem(item)
 | 
				
			||||||
 | 
					            items.append(item)
 | 
				
			||||||
        dst.sortItems()
 | 
					        dst.sortItems()
 | 
				
			||||||
        self.emit(SIGNAL("selected_changed()"))
 | 
					        self.emit(SIGNAL("selected_changed()"))
 | 
				
			||||||
 | 
					        if src is self.selected_list:    
 | 
				
			||||||
 | 
					            self.emit(SIGNAL("items_removed(list)"), items)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.emit(SIGNAL("items_added(list)"), items)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_all(self):
 | 
					    def add_all(self):
 | 
				
			||||||
        self.move_all(self.available_list, self.selected_list)
 | 
					        self.move_all(self.available_list, self.selected_list)
 | 
				
			||||||
 | 
				
			|||||||
@ -358,7 +358,7 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
 | 
				
			|||||||
        self.vcpus.setMaximum(QubesHost().no_cpus)
 | 
					        self.vcpus.setMaximum(QubesHost().no_cpus)
 | 
				
			||||||
        self.vcpus.setValue(int(self.vm.vcpus))
 | 
					        self.vcpus.setValue(int(self.vm.vcpus))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.include_in_balancing.setChecked('meminfo-writer' in self.vm.services and self.vm.services['meminfo-writer']==True)
 | 
					        self.include_in_balancing.setChecked(self.vm.services['meminfo-writer']==True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #kernel
 | 
					        #kernel
 | 
				
			||||||
        if self.vm.template is not None:
 | 
					        if self.vm.template is not None:
 | 
				
			||||||
@ -415,10 +415,8 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
 | 
				
			|||||||
            self.vm.vcpus = self.vcpus.value() 
 | 
					            self.vm.vcpus = self.vcpus.value() 
 | 
				
			||||||
            self.anything_changed = True
 | 
					            self.anything_changed = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        balancing_was_checked = ('meminfo-writer' in self.vm.services and self.vm.services['meminfo-writer']==True)
 | 
					        #include_in_memory_balancing applied in services tab
 | 
				
			||||||
        if self.include_in_balancing.isChecked() != balancing_was_checked:
 | 
					
 | 
				
			||||||
            self.new_srv_dict['meminfo-writer'] = self.include_in_balancing.isChecked()
 | 
					 | 
				
			||||||
            self.anything_changed = True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #kernel changed
 | 
					        #kernel changed
 | 
				
			||||||
        if self.kernel.currentIndex() != self.kernel_idx:
 | 
					        if self.kernel.currentIndex() != self.kernel_idx:
 | 
				
			||||||
@ -489,6 +487,12 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
 | 
				
			|||||||
            self.anything_changed = True
 | 
					            self.anything_changed = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def include_in_balancing_state_changed(self, state):
 | 
					    def include_in_balancing_state_changed(self, state):
 | 
				
			||||||
 | 
					        for r in range (self.services_list.count()):
 | 
				
			||||||
 | 
					            item = self.services_list.item(r)
 | 
				
			||||||
 | 
					            if str(item.text()) == 'meminfo-writer':
 | 
				
			||||||
 | 
					                item.setCheckState(state)
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.dev_list.selected_list.count() > 0:
 | 
					        if self.dev_list.selected_list.count() > 0:
 | 
				
			||||||
            if state == QtCore.Qt.Checked:
 | 
					            if state == QtCore.Qt.Checked:
 | 
				
			||||||
                self.dmm_warning_adv.show()
 | 
					                self.dmm_warning_adv.show()
 | 
				
			||||||
@ -496,6 +500,7 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
 | 
				
			|||||||
            else:
 | 
					            else:
 | 
				
			||||||
                self.dmm_warning_adv.hide()
 | 
					                self.dmm_warning_adv.hide()
 | 
				
			||||||
                self.dmm_warning_dev.hide()
 | 
					                self.dmm_warning_dev.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def devices_selection_changed(self):
 | 
					    def devices_selection_changed(self):
 | 
				
			||||||
        if self.include_in_balancing.isChecked():
 | 
					        if self.include_in_balancing.isChecked():
 | 
				
			||||||
            if self.dev_list.selected_list.count() > 0 :
 | 
					            if self.dev_list.selected_list.count() > 0 :
 | 
				
			||||||
@ -515,28 +520,54 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
 | 
				
			|||||||
            else:
 | 
					            else:
 | 
				
			||||||
                item.setCheckState(QtCore.Qt.Unchecked)
 | 
					                item.setCheckState(QtCore.Qt.Unchecked)
 | 
				
			||||||
            self.services_list.addItem(item)
 | 
					            self.services_list.addItem(item)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        self.connect(self.services_list, SIGNAL("itemClicked(QListWidgetItem *)"), self.services_item_clicked)
 | 
				
			||||||
        self.new_srv_dict = copy(self.vm.services)
 | 
					        self.new_srv_dict = copy(self.vm.services)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __add_service__(self):
 | 
					    def __add_service__(self):
 | 
				
			||||||
        srv = str(self.service_line_edit.text()).strip()
 | 
					        srv = str(self.service_line_edit.text()).strip()
 | 
				
			||||||
        if srv != "" and srv not in self.new_srv_dict:
 | 
					        if srv != "":
 | 
				
			||||||
            item = QListWidgetItem(srv)
 | 
					            if srv in self.new_srv_dict:
 | 
				
			||||||
            item.setCheckState(QtCore.Qt.Checked)
 | 
					                QMessageBox.information(None, "", "Service already on the list!")
 | 
				
			||||||
            self.services_list.addItem(item)
 | 
					            else:
 | 
				
			||||||
            self.new_srv_dict[srv] = True
 | 
					                item = QListWidgetItem(srv)
 | 
				
			||||||
 | 
					                item.setCheckState(QtCore.Qt.Checked)
 | 
				
			||||||
 | 
					                self.services_list.addItem(item)
 | 
				
			||||||
 | 
					                self.new_srv_dict[srv] = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __remove_service__(self):
 | 
					    def __remove_service__(self):
 | 
				
			||||||
        row = self.services_list.currentRow()
 | 
					        item = self.services_list.currentItem()
 | 
				
			||||||
        if row:
 | 
					        if str(item.text()) == 'meminfo-writer':    
 | 
				
			||||||
 | 
					                    QMessageBox.information(None, "Service can not be removed", "Service meminfo-writer can not be removed from the list.")
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            row = self.services_list.currentRow()
 | 
				
			||||||
            item = self.services_list.takeItem(row)
 | 
					            item = self.services_list.takeItem(row)
 | 
				
			||||||
            del self.new_srv_dict[str(item.text())]
 | 
					            del self.new_srv_dict[str(item.text())]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def services_item_clicked(self, item):
 | 
				
			||||||
 | 
					        if str(item.text()) == 'meminfo-writer':
 | 
				
			||||||
 | 
					            if item.checkState() == QtCore.Qt.Checked:
 | 
				
			||||||
 | 
					                if not self.include_in_balancing.isChecked():
 | 
				
			||||||
 | 
					                    self.include_in_balancing.setChecked(True)
 | 
				
			||||||
 | 
					            elif item.checkState() == QtCore.Qt.Unchecked:
 | 
				
			||||||
 | 
					                if self.include_in_balancing.isChecked():
 | 
				
			||||||
 | 
					                    self.include_in_balancing.setChecked(False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __apply_services_tab__(self):
 | 
					    def __apply_services_tab__(self):
 | 
				
			||||||
        new_dict = {}
 | 
					 | 
				
			||||||
        for r in range (self.services_list.count()):
 | 
					        for r in range (self.services_list.count()):
 | 
				
			||||||
            item = self.services_list.item(r)
 | 
					            item = self.services_list.item(r)
 | 
				
			||||||
            self.new_srv_dict[str(item.text())] = (item.checkState() == QtCore.Qt.Checked)
 | 
					            self.new_srv_dict[str(item.text())] = (item.checkState() == QtCore.Qt.Checked)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        balancing_was_checked = (self.vm.services['meminfo-writer']==True)
 | 
				
			||||||
 | 
					        balancing_is_checked =  self.include_in_balancing.isChecked()
 | 
				
			||||||
 | 
					        meminfo_writer_checked = (self.new_srv_dict['meminfo-writer'] == True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if balancing_is_checked != meminfo_writer_checked:
 | 
				
			||||||
 | 
					            if balancing_is_checked != balancing_was_checked:
 | 
				
			||||||
 | 
					                self.new_srv_dict['meminfo-writer'] = balancing_is_checked
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.new_srv_dict != self.vm.services:
 | 
					        if self.new_srv_dict != self.vm.services:
 | 
				
			||||||
            self.vm.services = self.new_srv_dict
 | 
					            self.vm.services = self.new_srv_dict
 | 
				
			||||||
            self.anything_changed = True
 | 
					            self.anything_changed = True
 | 
				
			||||||
 | 
				
			|||||||
@ -1,19 +1,26 @@
 | 
				
			|||||||
<RCC>
 | 
					<RCC>
 | 
				
			||||||
  <qresource>
 | 
					  <qresource>
 | 
				
			||||||
 | 
					    <file alias="apps.png">icons/apps.png</file>
 | 
				
			||||||
 | 
					    <file alias="settings.png">icons/settings.png</file>
 | 
				
			||||||
 | 
					    <file alias="firewall.png">icons/wall.png</file>
 | 
				
			||||||
 | 
					    <file alias="restore.png">icons/restore.png</file>
 | 
				
			||||||
 | 
					    <file alias="backup.png">icons/backup.png</file>
 | 
				
			||||||
 | 
					    <file alias="global-settings.png">icons/global-settings.png</file>
 | 
				
			||||||
    <file alias="off.png">icons/on-icon/off.png</file>
 | 
					    <file alias="off.png">icons/on-icon/off.png</file>
 | 
				
			||||||
    <file alias="on.png">icons/on-icon/on.png</file>
 | 
					    <file alias="on-old.png">icons/on-icon/on.png</file>
 | 
				
			||||||
 | 
					    <file alias="show-all-running.png">icons/on-icon/show-all-running.png</file>
 | 
				
			||||||
    <file alias="mount.png">icons/mount.png</file>
 | 
					    <file alias="mount.png">icons/mount.png</file>
 | 
				
			||||||
    <file alias="pencil.png">icons/pencil.png</file>
 | 
					    <file alias="pencil.png">icons/pencil.png</file>
 | 
				
			||||||
    <file alias="redfirewall.png">icons/redfirewall.png</file>
 | 
					    <file alias="redfirewall.png">icons/redfirewall.png</file>
 | 
				
			||||||
    <file alias="edit.png">icons/edit.png</file>
 | 
					    <file alias="edit.png">icons/edit.png</file>
 | 
				
			||||||
    <file alias="add.png">icons/add.png</file>
 | 
					    <file alias="add.png">icons/add.png</file>
 | 
				
			||||||
    <file alias="flag-blue.png">icons/flag-blue.png</file>
 | 
					    <file alias="flag-blue.png">icons/flag-blue.png</file>
 | 
				
			||||||
 | 
					    <file alias="on.png">icons/running.png</file>
 | 
				
			||||||
    <file alias="flag-green.png">icons/flag-green.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-red.png">icons/flag-red.png</file>
 | 
				
			||||||
    <file alias="flag-yellow.png">icons/flag-yellow.png</file>
 | 
					    <file alias="flag-yellow.png">icons/flag-yellow.png</file>
 | 
				
			||||||
    <file alias="remove.png">icons/remove.png</file>
 | 
					    <file alias="remove.png">icons/remove.png</file>
 | 
				
			||||||
    <file alias="appsprefs.png">icons/appsprefs.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="qubes.png">icons/qubes.png</file>
 | 
				
			||||||
    <file alias="appvm.png">icons/appvm.png</file>
 | 
					    <file alias="appvm.png">icons/appvm.png</file>
 | 
				
			||||||
    <file alias="netvm.png">icons/netvm.png</file>
 | 
					    <file alias="netvm.png">icons/netvm.png</file>
 | 
				
			||||||
@ -31,6 +38,6 @@
 | 
				
			|||||||
    <file alias="pausevm.png">icons/pausevm.png</file>
 | 
					    <file alias="pausevm.png">icons/pausevm.png</file>
 | 
				
			||||||
    <file alias="showallvms.png">icons/showallvms.png</file>
 | 
					    <file alias="showallvms.png">icons/showallvms.png</file>
 | 
				
			||||||
    <file alias="showcpuload.png">icons/showcpuload.png</file>
 | 
					    <file alias="showcpuload.png">icons/showcpuload.png</file>
 | 
				
			||||||
    <file alias="firewall.png">icons/firewall.png</file>
 | 
					 | 
				
			||||||
  </qresource>
 | 
					  </qresource>
 | 
				
			||||||
 | 
					  <qresource/>
 | 
				
			||||||
</RCC>
 | 
					</RCC>
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ Group:		Qubes
 | 
				
			|||||||
Vendor:		Invisible Things Lab
 | 
					Vendor:		Invisible Things Lab
 | 
				
			||||||
License:	GPL
 | 
					License:	GPL
 | 
				
			||||||
URL:		http://fixme
 | 
					URL:		http://fixme
 | 
				
			||||||
Requires:	python, PyQt4, qubes-core-dom0 >= 1.7.15, kdebase
 | 
					Requires:	python, PyQt4, qubes-core-dom0 > 1.7.17, kdebase
 | 
				
			||||||
Requires:	pmount, cryptsetup
 | 
					Requires:	pmount, cryptsetup
 | 
				
			||||||
BuildRequires:	PyQt4-devel
 | 
					BuildRequires:	PyQt4-devel
 | 
				
			||||||
AutoReq:	0
 | 
					AutoReq:	0
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@
 | 
				
			|||||||
        <locale language="English" country="UnitedStates"/>
 | 
					        <locale language="English" country="UnitedStates"/>
 | 
				
			||||||
       </property>
 | 
					       </property>
 | 
				
			||||||
       <property name="currentIndex">
 | 
					       <property name="currentIndex">
 | 
				
			||||||
        <number>1</number>
 | 
					        <number>4</number>
 | 
				
			||||||
       </property>
 | 
					       </property>
 | 
				
			||||||
       <widget class="QWidget" name="basic_tab">
 | 
					       <widget class="QWidget" name="basic_tab">
 | 
				
			||||||
        <property name="locale">
 | 
					        <property name="locale">
 | 
				
			||||||
@ -586,6 +586,10 @@
 | 
				
			|||||||
        </layout>
 | 
					        </layout>
 | 
				
			||||||
       </widget>
 | 
					       </widget>
 | 
				
			||||||
       <widget class="QWidget" name="firewall_tab">
 | 
					       <widget class="QWidget" name="firewall_tab">
 | 
				
			||||||
 | 
					        <attribute name="icon">
 | 
				
			||||||
 | 
					         <iconset resource="resources.qrc">
 | 
				
			||||||
 | 
					          <normaloff>:/firewall.png</normaloff>:/firewall.png</iconset>
 | 
				
			||||||
 | 
					        </attribute>
 | 
				
			||||||
        <attribute name="title">
 | 
					        <attribute name="title">
 | 
				
			||||||
         <string>Firewall rules</string>
 | 
					         <string>Firewall rules</string>
 | 
				
			||||||
        </attribute>
 | 
					        </attribute>
 | 
				
			||||||
@ -746,6 +750,10 @@
 | 
				
			|||||||
        <property name="enabled">
 | 
					        <property name="enabled">
 | 
				
			||||||
         <bool>true</bool>
 | 
					         <bool>true</bool>
 | 
				
			||||||
        </property>
 | 
					        </property>
 | 
				
			||||||
 | 
					        <attribute name="icon">
 | 
				
			||||||
 | 
					         <iconset resource="resources.qrc">
 | 
				
			||||||
 | 
					          <normaloff>:/storagevm.png</normaloff>:/storagevm.png</iconset>
 | 
				
			||||||
 | 
					        </attribute>
 | 
				
			||||||
        <attribute name="title">
 | 
					        <attribute name="title">
 | 
				
			||||||
         <string>Devices</string>
 | 
					         <string>Devices</string>
 | 
				
			||||||
        </attribute>
 | 
					        </attribute>
 | 
				
			||||||
@ -776,7 +784,7 @@
 | 
				
			|||||||
       <widget class="QWidget" name="apps_tab">
 | 
					       <widget class="QWidget" name="apps_tab">
 | 
				
			||||||
        <attribute name="icon">
 | 
					        <attribute name="icon">
 | 
				
			||||||
         <iconset resource="resources.qrc">
 | 
					         <iconset resource="resources.qrc">
 | 
				
			||||||
          <normaloff>:/appsprefs.png</normaloff>:/appsprefs.png</iconset>
 | 
					          <normaloff>:/apps.png</normaloff>:/apps.png</iconset>
 | 
				
			||||||
        </attribute>
 | 
					        </attribute>
 | 
				
			||||||
        <attribute name="title">
 | 
					        <attribute name="title">
 | 
				
			||||||
         <string>Applications</string>
 | 
					         <string>Applications</string>
 | 
				
			||||||
 | 
				
			|||||||