backup: implemented restore functions using the new backup model

This commit is contained in:
Olivier MEDOC 2013-09-27 09:19:38 +02:00
parent da0d0c29b8
commit e8cec85874
3 changed files with 184 additions and 94 deletions

View File

@ -75,6 +75,20 @@ def umount_device(dev_mount_path):
if button == QMessageBox.Ok: if button == QMessageBox.Ok:
return dev_mount_path return dev_mount_path
def fill_appvms_list(dialog):
dialog.appvm_combobox.clear()
dialog.appvm_combobox.addItem("None")
dialog.appvm_combobox.setCurrentIndex(0) #current selected is null ""
for vm in dialog.qvm_collection.values():
if vm.is_appvm() and vm.internal:
continue
if vm.is_template() and vm.installed_by_rpm:
continue
if vm.is_running() and vm.qid != 0:
dialog.appvm_combobox.addItem(vm.name)
def fill_devs_list(dialog): def fill_devs_list(dialog):
dialog.dev_combobox.clear() dialog.dev_combobox.clear()
@ -157,18 +171,22 @@ def select_path_button_clicked(dialog):
file_dialog = QFileDialog() file_dialog = QFileDialog()
file_dialog.setReadOnly(True) file_dialog.setReadOnly(True)
if dialog.dev_mount_path != None: new_appvm = None
new_path = None
if dialog.appvm_combobox.currentText() != "None": #An existing appvm chosen
new_appvm = str(dialog.appvm_combobox.currentText())
elif dialog.dev_mount_path != None:
new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", dialog.dev_mount_path) new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", dialog.dev_mount_path)
else: else:
new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", "~") new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", "~")
if new_path: if new_path != None:
dialog.dir_line_edit.setText(new_path) dialog.dir_line_edit.setText(new_path)
dialog.backup_dir = new_path dialog.backup_dir = new_path
if (new_path or new_appvm) and len(dialog.backup_dir) > 0:
dialog.select_dir_page.emit(SIGNAL("completeChanged()")) dialog.select_dir_page.emit(SIGNAL("completeChanged()"))
def simulate_long_lasting_proces(period, progress_callback): def simulate_long_lasting_proces(period, progress_callback):
for i in range(period): for i in range(period):
progress_callback((i*100)/period) progress_callback((i*100)/period)

View File

@ -30,6 +30,7 @@ from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException from qubes.qubes import QubesException
from qubes.qubes import QubesDaemonPidfile from qubes.qubes import QubesDaemonPidfile
from qubes.qubes import QubesHost from qubes.qubes import QubesHost
from qubes.qubes import qubes_base_dir
import qubesmanager.resources_rc import qubesmanager.resources_rc
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
@ -50,7 +51,7 @@ from backup_utils import *
class RestoreVMsWindow(Ui_Restore, QWizard): class RestoreVMsWindow(Ui_Restore, QWizard):
__pyqtSignals__ = ("restore_progress(int)",) __pyqtSignals__ = ("restore_progress(int)","backup_progress(int)")
def __init__(self, app, qvm_collection, blk_manager, parent=None): def __init__(self, app, qvm_collection, blk_manager, parent=None):
super(RestoreVMsWindow, self).__init__(parent) super(RestoreVMsWindow, self).__init__(parent)
@ -82,6 +83,7 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed) self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed)
self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated) self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated)
self.connect(self, SIGNAL("restore_progress(QString)"), self.commit_text_edit.append) self.connect(self, SIGNAL("restore_progress(QString)"), self.commit_text_edit.append)
self.connect(self, SIGNAL("backup_progress(int)"), self.progress_bar.setValue)
self.select_dir_page.isComplete = self.has_selected_dir self.select_dir_page.isComplete = self.has_selected_dir
self.select_vms_page.isComplete = self.has_selected_vms self.select_vms_page.isComplete = self.has_selected_vms
@ -90,6 +92,7 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
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()"))
fill_devs_list(self) fill_devs_list(self)
fill_appvms_list(self)
self.__init_restore_options__() self.__init_restore_options__()
@ -118,7 +121,13 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
self.select_vms_widget.selected_list.clear() self.select_vms_widget.selected_list.clear()
self.select_vms_widget.available_list.clear() self.select_vms_widget.available_list.clear()
self.vms_to_restore = qubesutils.backup_restore_prepare(str(self.backup_dir), self.restore_options, self.qvm_collection) self.target_appvm = None
if self.appvm_combobox.currentText() != "None": #An existing appvm chosen
self.target_appvm = str(self.appvm_combobox.currentText())
self.restore_tmpdir, qubes_xml = qubesutils.backup_restore_header(str(self.backup_dir), str(self.passphrase_line_edit.text()), self.encryption_checkbox.isChecked(), appvm=self.target_appvm)
self.vms_to_restore = qubesutils.backup_restore_prepare(str(self.backup_dir),os.path.join(self.restore_tmpdir, qubes_xml), str(self.passphrase_line_edit.text()), options=self.restore_options, host_collection=self.qvm_collection, encrypt=self.encryption_checkbox.isChecked(), appvm=self.target_appvm)
for vmname in self.vms_to_restore: for vmname in self.vms_to_restore:
self.select_vms_widget.available_list.addItem(vmname) self.select_vms_widget.available_list.addItem(vmname)
@ -147,17 +156,20 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
def restore_error_output(self, s): def restore_error_output(self, s):
self.emit(SIGNAL("restore_progress(QString)"), '<font color="red">{0}</font>'.format(s)) self.emit(SIGNAL("restore_progress(QString)"), '<font color="red">{0}</font>'.format(s))
def restore_output(self, s): def restore_output(self, s):
self.emit(SIGNAL("restore_progress(QString)"),'<font color="black">{0}</font>'.format(s)) self.emit(SIGNAL("restore_progress(QString)"),'<font color="black">{0}</font>'.format(s))
def update_progress_bar(self, value):
self.emit(SIGNAL("backup_progress(int)"), value)
def __do_restore__(self, thread_monitor): def __do_restore__(self, thread_monitor):
err_msg = [] err_msg = []
self.qvm_collection.lock_db_for_writing() self.qvm_collection.lock_db_for_writing()
try: try:
qubesutils.backup_restore_do(str(self.backup_dir), self.vms_to_restore, self.qvm_collection, self.restore_output, self.restore_error_output) qubesutils.backup_restore_do(str(self.backup_dir), self.restore_tmpdir, str(self.passphrase_line_edit.text()), self.vms_to_restore, self.qvm_collection, encrypted=self.encryption_checkbox.isChecked(), appvm=self.target_appvm, print_callback=self.restore_output, error_callback=self.restore_error_output, progress_callback
=self.update_progress_bar)
except Exception as ex: except Exception as ex:
print "Exception:",ex
err_msg.append(str(ex)) err_msg.append(str(ex))
self.qvm_collection.unlock_db() self.qvm_collection.unlock_db()

View File

@ -20,83 +20,21 @@
<set>QWizard::NoBackButtonOnLastPage|QWizard::NoBackButtonOnStartPage</set> <set>QWizard::NoBackButtonOnLastPage|QWizard::NoBackButtonOnStartPage</set>
</property> </property>
<widget class="QWizardPage" name="select_dir_page"> <widget class="QWizardPage" name="select_dir_page">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QGridLayout" name="gridLayout_3">
<item> <item row="3" column="0">
<widget class="QGroupBox" name="groupBox_2"> <spacer name="verticalSpacer">
<property name="font"> <property name="orientation">
<font> <enum>Qt::Vertical</enum>
<weight>50</weight>
<bold>false</bold>
</font>
</property> </property>
<property name="title"> <property name="sizeHint" stdset="0">
<string>Backup source location</string> <size>
<width>20</width>
<height>215</height>
</size>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> </spacer>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Device</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="dev_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>dev1</string>
</property>
</item>
<item>
<property name="text">
<string>longdeviceblablabla</string>
</property>
</item>
<item>
<property name="text">
<string>dev2</string>
</property>
</item>
<item>
<property name="text">
<string>dev3</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Backup directory:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="dir_line_edit"/>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="select_path_button">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item> </item>
<item> <item row="1" column="0">
<widget class="QGroupBox" name="options_groupbox"> <widget class="QGroupBox" name="options_groupbox">
<property name="font"> <property name="font">
<font> <font>
@ -138,18 +76,127 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item> <item row="0" column="0">
<spacer name="verticalSpacer"> <widget class="QGroupBox" name="groupBox_2">
<property name="orientation"> <property name="font">
<enum>Qt::Vertical</enum> <font>
<weight>50</weight>
<bold>false</bold>
</font>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="title">
<size> <string>Backup source location</string>
<width>20</width>
<height>215</height>
</size>
</property> </property>
</spacer> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QComboBox" name="dev_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>dev1</string>
</property>
</item>
<item>
<property name="text">
<string>longdeviceblablabla</string>
</property>
</item>
<item>
<property name="text">
<string>dev2</string>
</property>
</item>
<item>
<property name="text">
<string>dev3</string>
</property>
</item>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="dir_line_edit"/>
</item>
<item row="6" column="2">
<widget class="QToolButton" name="select_path_button">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Backup directory:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Device:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="appvm_combobox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>AppVM:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Security options</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="1">
<widget class="QCheckBox" name="encryption_checkbox">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Encrypted backup:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Decryption / Verification&lt;br/&gt;passphrase:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="passphrase_line_edit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -189,8 +236,8 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -217,6 +264,19 @@ p, li { white-space: pre-wrap; }
<item> <item>
<widget class="QTextEdit" name="commit_text_edit"/> <widget class="QTextEdit" name="commit_text_edit"/>
</item> </item>
<item>
<widget class="QProgressBar" name="progress_bar">
<property name="value">
<number>0</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
<property name="format">
<string/>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>