Added optional saving of default backup profile

Added checkbox for saving default backup profile. Removed useless "should I encrypt" checkbox (yes, you have to encrypt).
This commit is contained in:
Marta Marczykowska-Górecka 2017-12-10 23:17:39 +01:00
parent 9d73ceb99d
commit 7bcde2158e
No known key found for this signature in database
GPG Key ID: 9A752C30B26FD04B
4 changed files with 119 additions and 68 deletions

View File

@ -145,21 +145,20 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
self.passphrase_line_edit.setText(profile_data['passphrase_text'])
self.passphrase_line_edit_verify.setText(
profile_data['passphrase_text'])
# TODO: make a checkbox for saving the profile
# TODO: warn that unknown data will be overwritten
if 'include' in profile_data:
return profile_data['include']
return None
def save_settings(self):
def save_settings(self, use_temp):
settings = {'destination_vm': self.appvm_combobox.currentText(),
'destination_path': self.dir_line_edit.text(),
'include': [vm.name for vm in self.selected_vms],
'passphrase_text': self.passphrase_line_edit.text()}
# TODO: add compression when it is added
backup_utils.write_backup_profile(settings)
backup_utils.write_backup_profile(settings, use_temp)
class VmListItem(QtGui.QListWidgetItem):
def __init__(self, vm):
@ -267,9 +266,9 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
self.appvm_combobox.currentText()]
if not vm.is_running():
vm.start()
self.qvm_collection.qubesd_call('dom0',
'admin.backup.Execute',
'qubes-manager-backup')
self.qvm_collection.qubesd_call(
'dom0', 'admin.backup.Execute',
backup_utils.get_profile_name(True))
except exc.QubesException as err:
# TODO fixme
print('\nBackup error: {}'.format(err), file=sys.stderr)
@ -288,15 +287,20 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
old_sigchld_handler = signal.signal(signal.SIGCHLD, signal.SIG_DFL)
if self.currentPage() is self.confirm_page:
self.save_settings()
self.save_settings(True)
backup_summary = self.qvm_collection.qubesd_call(
'dom0', 'admin.backup.Info', 'qubes-manager-backup')
'dom0', 'admin.backup.Info',
backup_utils.get_profile_name(True))
self.textEdit.setReadOnly(True)
self.textEdit.setFontFamily("Monospace")
self.textEdit.setText(backup_summary.decode())
elif self.currentPage() is self.commit_page:
if self.save_profile_checkbox.isChecked():
self.save_settings(False)
self.button(self.FinishButton).setDisabled(True)
self.showFileDialog.setEnabled(
self.appvm_combobox.currentIndex() != 0)

View File

@ -30,10 +30,6 @@ import yaml
path_re = re.compile(r"[a-zA-Z0-9/:.,_+=() -]*")
path_max_len = 512
# TODO: replace it with a more dynamic approach: allowing user to turn on or off
# profile saving
backup_profile_path = '/etc/qubes/backup/qubes-manager-backup.conf'
def fill_appvms_list(dialog):
dialog.appvm_combobox.clear()
@ -90,20 +86,16 @@ def select_path_button_clicked(dialog, select_file=False):
dialog.select_dir_page.emit(QtCore.SIGNAL("completeChanged()"))
def load_backup_profile():
with open(backup_profile_path) as profile_file:
def load_backup_profile(use_temp=False):
path = get_profile_path(use_temp)
with open(path) as profile_file:
profile_data = yaml.safe_load(profile_file)
return profile_data
def write_backup_profile(args):
'''Format limited backup profile (for GUI purposes and print it to
*output_stream* (a file or stdout)
:param output_stream: file-like object ro print the profile to
:param args: dictionary with arguments
:param passphrase: passphrase to use
'''
def write_backup_profile(args, use_temp=False):
acceptable_fields = ['include', 'passphrase_text', 'compression',
'destination_vm', 'destination_path']
@ -111,6 +103,20 @@ def write_backup_profile(args):
profile_data = {key: value for key, value in args.items()
if key in acceptable_fields}
path = get_profile_path(use_temp)
# TODO add compression parameter to GUI issue#943
with open(backup_profile_path, 'w') as profile_file:
with open(path, 'w') as profile_file:
yaml.safe_dump(profile_data, profile_file)
def get_profile_name(use_temp):
backup_profile_name = 'qubes-manager-backup'
temp_backup_profile_name = 'qubes-manager-backup-tmp'
return temp_backup_profile_name if use_temp else backup_profile_name
def get_profile_path(use_temp):
path = '/etc/qubes/backup/' + get_profile_name(use_temp) + '.conf'
return path

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>650</width>
<height>399</height>
<width>737</width>
<height>420</height>
</rect>
</property>
<property name="windowTitle">
@ -137,6 +137,12 @@
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Backup destination directory</string>
</property>
@ -176,71 +182,103 @@
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Backup security</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="2" column="0">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Encryption / Verification&lt;br/&gt;passphrase:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Encrypt backup:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="encryption_checkbox">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Reenter passphrase:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="1" column="1">
<widget class="QLineEdit" name="passphrase_line_edit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="4" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Reenter passphrase:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="passphrase_line_edit_verify">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;b&gt;Note:&lt;/b&gt; Even if you choose not to encrypt your backup, a password is still required in order to provide authenticated verification of the data. See the emergency restore instructions for more info.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Save backup profile</string>
</property>
<widget class="QLabel" name="label_8">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>267</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Save settings as default backup profile:</string>
</property>
</widget>
<widget class="QCheckBox" name="save_profile_checkbox">
<property name="geometry">
<rect>
<x>270</x>
<y>30</y>
<width>539</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string> </string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<zorder>checkBox</zorder>
<zorder>groupBox_2</zorder>
<zorder>groupBox_2</zorder>
<zorder>label_8</zorder>
<zorder>save_profile_checkbox</zorder>
<zorder>groupBox_2</zorder>
<zorder>label_8</zorder>
<zorder>label_8</zorder>
<zorder>save_profile_checkbox</zorder>
<zorder>label_8</zorder>
<zorder>save_profile_checkbox</zorder>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="confirm_page">

View File

@ -147,6 +147,9 @@
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
@ -211,8 +214,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;
&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; }
&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; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Cantarell'; font-size:11pt; 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; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>