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