All VMs available on backup list. One click 'shutdown running'
This commit is contained in:
parent
b616a8f536
commit
81bb0f75a6
64
backupdlg.ui
64
backupdlg.ui
@ -22,6 +22,64 @@
|
|||||||
<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>
|
||||||
|
<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">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -38,6 +96,8 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWizardPage" name="select_dir_page">
|
<widget class="QWizardPage" name="select_dir_page">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
@ -187,6 +247,8 @@ p, li { white-space: pre-wrap; }
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources>
|
||||||
|
<include location="resources.qrc"/>
|
||||||
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -54,12 +54,13 @@ 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 +76,16 @@ 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.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)
|
||||||
|
|
||||||
@ -93,24 +98,90 @@ class BackupVMsWindow(Ui_Backup, QWizard):
|
|||||||
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):
|
||||||
|
super(BackupVMsWindow.VmListItem, self).__init__(vm.name)
|
||||||
|
self.vm = vm
|
||||||
|
|
||||||
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)
|
||||||
else:
|
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):
|
def dev_combobox_activated(self, idx):
|
||||||
@ -123,9 +194,16 @@ 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 = str(self.select_vms_widget.available_list.item(i).text())
|
||||||
self.excluded.append(vmname)
|
self.excluded.append(vmname)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def gather_output(self, s):
|
def gather_output(self, s):
|
||||||
@ -152,7 +230,10 @@ 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[:]
|
||||||
|
try:
|
||||||
self.files_to_backup = qubesutils.backup_prepare(str(self.backup_dir), exclude_list = self.excluded, print_callback = self.gather_output)
|
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")
|
||||||
@ -213,8 +294,6 @@ def handle_exception( exc_type, exc_value, exc_traceback ):
|
|||||||
% ( line, filename ))
|
% ( line, filename ))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
global qubes_host
|
global qubes_host
|
||||||
|
@ -1142,6 +1142,10 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
app.processEvents()
|
app.processEvents()
|
||||||
|
|
||||||
if reply == QMessageBox.Yes:
|
if reply == QMessageBox.Yes:
|
||||||
|
self.shutdown_vm(vm)
|
||||||
|
|
||||||
|
|
||||||
|
def shutdown_vm(self, vm):
|
||||||
try:
|
try:
|
||||||
subprocess.check_call (["/usr/sbin/xl", "shutdown", vm.name])
|
subprocess.check_call (["/usr/sbin/xl", "shutdown", vm.name])
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
@ -1153,6 +1157,8 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
self.shutdown_monitor[vm.qid] = VmShutdownMonitor (vm)
|
self.shutdown_monitor[vm.qid] = VmShutdownMonitor (vm)
|
||||||
QTimer.singleShot (vm_shutdown_timeout, self.shutdown_monitor[vm.qid].check_if_vm_has_shutdown)
|
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):
|
||||||
vm = self.get_selected_vm()
|
vm = self.get_selected_vm()
|
||||||
@ -1235,7 +1241,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_()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user