Merge branch 'master' of git://git.qubes-os.org/aga/qubes-manager
This commit is contained in:
		
						commit
						33b97aa8a7
					
				
							
								
								
									
										92
									
								
								backupdlg.ui
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								backupdlg.ui
									
									
									
									
									
								
							| @ -22,20 +22,80 @@ | ||||
|   <widget class="QWizardPage" name="select_vms_page"> | ||||
|    <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|     <item> | ||||
|      <widget class="QLabel" name="label_4"> | ||||
|       <property name="font"> | ||||
|        <font> | ||||
|         <pointsize>9</pointsize> | ||||
|         <weight>50</weight> | ||||
|         <italic>false</italic> | ||||
|         <bold>false</bold> | ||||
|         <underline>false</underline> | ||||
|        </font> | ||||
|       </property> | ||||
|       <property name="text"> | ||||
|        <string>Select VMs to backup:</string> | ||||
|       </property> | ||||
|      </widget> | ||||
|      <layout class="QGridLayout" name="gridLayout_2"> | ||||
|       <item row="1" column="1"> | ||||
|        <widget class="QPushButton" name="shutdown_running_vms_button"> | ||||
|         <property name="sizePolicy"> | ||||
|          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> | ||||
|           <horstretch>0</horstretch> | ||||
|           <verstretch>0</verstretch> | ||||
|          </sizepolicy> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string>Shutdown all running selected VMs</string> | ||||
|         </property> | ||||
|         <property name="icon"> | ||||
|          <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> | ||||
|    </layout> | ||||
|   </widget> | ||||
| @ -187,6 +247,8 @@ p, li { white-space: pre-wrap; } | ||||
|    </layout> | ||||
|   </widget> | ||||
|  </widget> | ||||
|  <resources/> | ||||
|  <resources> | ||||
|   <include location="resources.qrc"/> | ||||
|  </resources> | ||||
|  <connections/> | ||||
| </ui> | ||||
|  | ||||
| @ -54,12 +54,13 @@ class BackupVMsWindow(Ui_Backup, QWizard): | ||||
| 
 | ||||
|     __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) | ||||
| 
 | ||||
|         self.app = app | ||||
|         self.qvm_collection = qvm_collection | ||||
|         self.blk_manager = blk_manager | ||||
|         self.shutdown_vm_func = shutdown_vm_func | ||||
| 
 | ||||
|         self.dev_mount_path = None | ||||
|         self.backup_dir = None | ||||
| @ -75,12 +76,16 @@ class BackupVMsWindow(Ui_Backup, QWizard): | ||||
| 
 | ||||
|         self.setupUi(self) | ||||
| 
 | ||||
|         self.show_running_vms_warning(False) | ||||
|         self.dir_line_edit.setReadOnly(True) | ||||
| 
 | ||||
|         self.select_vms_widget = MultiSelectWidget(self) | ||||
|         self.verticalLayout.insertWidget(1, self.select_vms_widget) | ||||
| 
 | ||||
|         self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed) | ||||
|         self.connect(self.select_vms_widget, SIGNAL("selected_changed()"), self.check_running) | ||||
|         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, SIGNAL("backup_progress(int)"), self.progress_bar.setValue) | ||||
| 
 | ||||
| @ -93,26 +98,92 @@ class BackupVMsWindow(Ui_Backup, QWizard): | ||||
|         self.__fill_vms_list__() | ||||
|         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): | ||||
|             super(BackupVMsWindow.VmListItem, self).__init__(vm.name) | ||||
|             self.vm = vm | ||||
| 
 | ||||
|     def __fill_vms_list__(self): | ||||
|         for vm in self.qvm_collection.values(): | ||||
|             if vm.is_running() and vm.qid != 0: | ||||
|                 self.excluded.append(vm.name) | ||||
|                 continue | ||||
|              | ||||
|             if vm.is_appvm() and vm.internal: | ||||
|                 self.excluded.append(vm.name) | ||||
|                 continue | ||||
| 
 | ||||
|             if vm.is_template() and vm.installed_by_rpm: | ||||
|                 self.excluded.append(vm.name) | ||||
|                 continue | ||||
| 
 | ||||
|             item = BackupVMsWindow.VmListItem(vm) | ||||
|             if vm.include_in_backups == True: | ||||
|                 self.select_vms_widget.selected_list.addItem(vm.name) | ||||
|                 self.select_vms_widget.selected_list.addItem(item) | ||||
|             else: | ||||
|                 self.select_vms_widget.available_list.addItem(vm.name) | ||||
|                 self.select_vms_widget.available_list.addItem(item) | ||||
|         self.check_running() | ||||
| 
 | ||||
|     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): | ||||
|         dev_combobox_activated(self, idx) | ||||
|                     | ||||
| @ -123,9 +194,16 @@ class BackupVMsWindow(Ui_Backup, QWizard): | ||||
| 
 | ||||
|     def validateCurrentPage(self): | ||||
|         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()): | ||||
|                 vmname =  self.select_vms_widget.available_list.item(i).text() | ||||
|                 vmname =  str(self.select_vms_widget.available_list.item(i).text()) | ||||
|                 self.excluded.append(vmname) | ||||
|                  | ||||
|         return True | ||||
| 
 | ||||
|     def gather_output(self, s): | ||||
| @ -152,7 +230,10 @@ class BackupVMsWindow(Ui_Backup, QWizard): | ||||
|     def current_page_changed(self, id): | ||||
|         if self.currentPage() is self.confirm_page: | ||||
|             del self.func_output[:] | ||||
|             self.files_to_backup = qubesutils.backup_prepare(str(self.backup_dir), exclude_list = self.excluded, print_callback = self.gather_output) | ||||
|             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.setFontFamily("Monospace") | ||||
| @ -213,8 +294,6 @@ def handle_exception( exc_type, exc_value, exc_traceback ): | ||||
|                          % ( line, filename )) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
| 
 | ||||
|     global qubes_host | ||||
|  | ||||
| @ -1142,16 +1142,22 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow): | ||||
|         app.processEvents() | ||||
| 
 | ||||
|         if reply == QMessageBox.Yes: | ||||
|             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 | ||||
|             self.shutdown_vm(vm) | ||||
| 
 | ||||
| 
 | ||||
|     def shutdown_vm(self, vm): | ||||
|         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') | ||||
|     def action_settings_triggered(self): | ||||
| @ -1235,7 +1241,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow): | ||||
| 
 | ||||
|     @pyqtSlot(name='on_action_backup_triggered') | ||||
|     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_() | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -358,7 +358,7 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog): | ||||
|         self.vcpus.setMaximum(QubesHost().no_cpus) | ||||
|         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 | ||||
|         if self.vm.template is not None: | ||||
| @ -415,10 +415,8 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog): | ||||
|             self.vm.vcpus = self.vcpus.value()  | ||||
|             self.anything_changed = True | ||||
| 
 | ||||
|         balancing_was_checked = ('meminfo-writer' in self.vm.services and self.vm.services['meminfo-writer']==True) | ||||
|         if self.include_in_balancing.isChecked() != balancing_was_checked: | ||||
|             self.new_srv_dict['meminfo-writer'] = self.include_in_balancing.isChecked() | ||||
|             self.anything_changed = True | ||||
|         #include_in_memory_balancing applied in services tab | ||||
| 
 | ||||
| 
 | ||||
|         #kernel changed | ||||
|         if self.kernel.currentIndex() != self.kernel_idx: | ||||
| @ -489,6 +487,12 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog): | ||||
|             self.anything_changed = True | ||||
| 
 | ||||
|     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 state == QtCore.Qt.Checked: | ||||
|                 self.dmm_warning_adv.show() | ||||
| @ -496,6 +500,7 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog): | ||||
|             else: | ||||
|                 self.dmm_warning_adv.hide() | ||||
|                 self.dmm_warning_dev.hide() | ||||
| 
 | ||||
|     def devices_selection_changed(self): | ||||
|         if self.include_in_balancing.isChecked(): | ||||
|             if self.dev_list.selected_list.count() > 0 : | ||||
| @ -515,28 +520,54 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog): | ||||
|             else: | ||||
|                 item.setCheckState(QtCore.Qt.Unchecked) | ||||
|             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) | ||||
| 
 | ||||
|     def __add_service__(self): | ||||
|         srv = str(self.service_line_edit.text()).strip() | ||||
|         if srv != "" and srv not in self.new_srv_dict: | ||||
|             item = QListWidgetItem(srv) | ||||
|             item.setCheckState(QtCore.Qt.Checked) | ||||
|             self.services_list.addItem(item) | ||||
|             self.new_srv_dict[srv] = True | ||||
|         if srv != "": | ||||
|             if srv in self.new_srv_dict: | ||||
|                 QMessageBox.information(None, "", "Service already on the list!") | ||||
|             else: | ||||
|                 item = QListWidgetItem(srv) | ||||
|                 item.setCheckState(QtCore.Qt.Checked) | ||||
|                 self.services_list.addItem(item) | ||||
|                 self.new_srv_dict[srv] = True | ||||
| 
 | ||||
|     def __remove_service__(self): | ||||
|         row = self.services_list.currentRow() | ||||
|         if row: | ||||
|         item = self.services_list.currentItem() | ||||
|         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) | ||||
|             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): | ||||
|         new_dict = {} | ||||
|         for r in range (self.services_list.count()): | ||||
|             item = self.services_list.item(r) | ||||
|             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: | ||||
|             self.vm.services = self.new_srv_dict | ||||
|             self.anything_changed = True | ||||
|  | ||||
| @ -11,7 +11,7 @@ Group:		Qubes | ||||
| Vendor:		Invisible Things Lab | ||||
| License:	GPL | ||||
| 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 | ||||
| BuildRequires:	PyQt4-devel | ||||
| AutoReq:	0 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Marek Marczykowski
						Marek Marczykowski