Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions qubesmanager/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import signal
from qubesadmin import exc
from qubesadmin import utils as admin_utils
from qubesadmin.backup.restore \
import KNOWN_COMPRESSION_FILTERS, OPTIONAL_COMPRESSION_FILTERS

from PyQt6 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
from qubesmanager import ui_backupdlg # pylint: disable=no-name-in-module
Expand Down Expand Up @@ -129,6 +131,13 @@
self.appvm_combobox.findText("dom0"))

self.unrecognized_config_label.setVisible(False)

self.compression_combobox.addItem("Default (gzip)")
self.compression_combobox.addItems(KNOWN_COMPRESSION_FILTERS)
self.compression_combobox.addItems(
[c for c in OPTIONAL_COMPRESSION_FILTERS if shutil.which(c)]
)
self.compression_combobox.addItem("Disabled (uncompressed)")
self.load_settings()

self.show_passwd_button.pressed.connect(self.show_hide_password)
Expand Down Expand Up @@ -234,7 +243,21 @@
self.save_passphrase_checkbox.setChecked(False)

if 'compression' in profile_data:
self.compress_checkbox.setChecked(profile_data['compression'])
if isinstance(profile_data["compression"], bool):
if profile_data["compression"]:
# Technically this is necessary as the default index is -1
self.compression_combobox.setCurrentIndex(0)
else:
self.compression_combobox.setCurrentIndex(
self.compression_combobox.count() - 1
)
else:
for i in range(self.compression_combobox.count()):
if profile_data[
"compression"
] == self.compression_combobox.itemText(i):
self.compression_combobox.setCurrentIndex(i)
break

def save_settings(self, use_temp, save_passphrase=True):
"""
Expand All @@ -244,10 +267,20 @@
:param use_temp: whether to use temporary profile (True) or the default
backup profile (False)
"""
settings = {'destination_vm': self.appvm_combobox.currentText(),
'destination_path': self.dir_line_edit.text(),
'include': [vm.name for vm in self.selected_vms],
'compression': self.compress_checkbox.isChecked()}
if self.compression_combobox.currentIndex() != -1:
compression_filter = self.compression_combobox.currentText()
if compression_filter.startswith("Default"):
compression_filter = True
elif compression_filter.startswith("Disabled"):
compression_filter = False
else:
compression_filter = True

Check warning on line 277 in qubesmanager/backup.py

View check run for this annotation

Codecov / codecov/patch

qubesmanager/backup.py#L277

Added line #L277 was not covered by tests
settings = {
"destination_vm": self.appvm_combobox.currentText(),
"destination_path": self.dir_line_edit.text(),
"include": [vm.name for vm in self.selected_vms],
"compression": compression_filter
}

if save_passphrase:
settings['passphrase_text'] = self.passphrase_line_edit.text()
Expand Down
72 changes: 68 additions & 4 deletions qubesmanager/tests/test_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def test_00_load_backup(backup_dlg):


def test_01_correct_default(backup_dlg):
# backup is compressed
assert backup_dlg.compress_checkbox.isChecked()
# backup compresssion is the default (no item selected or item 0)
assert backup_dlg.compression_combobox.currentIndex() in [0, -1]

# passphrase is empty
assert backup_dlg.passphrase_line_edit.text() == "", "Password non-empty"
Expand Down Expand Up @@ -175,7 +175,10 @@ def test_10_do_backup(mock_open, backup_dlg):
backup_dlg.passphrase_line_edit_verify.setText("pass")
backup_dlg.save_profile_checkbox.setChecked(False)
backup_dlg.turn_off_checkbox.setChecked(False)
backup_dlg.compress_checkbox.setChecked(False)
backup_dlg.compression_combobox.addItem("Disabled (uncompressed")
backup_dlg.compression_combobox.setCurrentIndex(
backup_dlg.compression_combobox.count() - 1
)

expected_call = ('dom0', 'admin.backup.Info', 'qubes-manager-backup-tmp',
None)
Expand Down Expand Up @@ -233,7 +236,7 @@ def test_20_loading_settings(mock_load, test_qubes_app, qapp):
"Passphrase not loaded"
assert backup_dlg.passphrase_line_edit_verify.text() == "longerPassPhrase" \
, "Passphrase verify not loaded"
assert backup_dlg.compress_checkbox.isChecked()
assert backup_dlg.compression_combobox.currentIndex() == 0

# check that 'include' vms were not pre-selected
include_in_backups_no = len(
Expand All @@ -247,6 +250,67 @@ def test_20_loading_settings(mock_load, test_qubes_app, qapp):
assert not backup_dlg.unrecognized_config_label.isVisible()


@mock.patch('qubesmanager.backup_utils.load_backup_profile')
def test_20_loading_settings_nocomp(mock_load, test_qubes_app, qapp):

mock_load.return_value = {
'destination_vm': 'test-blue',
'destination_path': "/home",
'include': ['dom0', 'test-red', 'sys-net'],
'passphrase_text': "longerPassPhrase",
'compression': False
}

dispatcher = MockAsyncDispatcher(test_qubes_app)
backup_dlg = backup.BackupVMsWindow(qapp, test_qubes_app, dispatcher)
# needed because otherwise the wizard will not test correctly
backup_dlg.show()

# check if last compression filter (Disabled) is selected
assert backup_dlg.compression_combobox.currentIndex() == \
backup_dlg.compression_combobox.count() - 1


@mock.patch('qubesmanager.backup_utils.load_backup_profile')
def test_20_loading_settings_bzip2(mock_load, test_qubes_app, qapp):

mock_load.return_value = {
'destination_vm': 'test-blue',
'destination_path': "/home",
'include': ['dom0', 'test-red', 'sys-net'],
'passphrase_text': "longerPassPhrase",
'compression': "bzip2"
}

dispatcher = MockAsyncDispatcher(test_qubes_app)
backup_dlg = backup.BackupVMsWindow(qapp, test_qubes_app, dispatcher)
# needed because otherwise the wizard will not test correctly
backup_dlg.show()

# check if the right compression filter is selected
assert backup_dlg.compression_combobox.currentText() == "bzip2"


@mock.patch('qubesmanager.backup_utils.load_backup_profile')
def test_20_loading_settings_pkzip(mock_load, test_qubes_app, qapp):

mock_load.return_value = {
'destination_vm': 'test-blue',
'destination_path': "/home",
'include': ['dom0', 'test-red', 'sys-net'],
'passphrase_text': "longerPassPhrase",
'compression': "pkzip"
}

dispatcher = MockAsyncDispatcher(test_qubes_app)
backup_dlg = backup.BackupVMsWindow(qapp, test_qubes_app, dispatcher)
# needed because otherwise the wizard will not test correctly
backup_dlg.show()

# check if the compression filter reverts to the default
assert backup_dlg.compression_combobox.currentIndex() == 0


@mock.patch('qubesmanager.backup_utils.load_backup_profile')
def test_21_loading_settings_error(mock_load, test_qubes_app, qapp):
mock_load.return_value = {
Expand Down
39 changes: 30 additions & 9 deletions ui/backupdlg.ui
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,35 @@
</layout>
</item>
<item>
<widget class="QCheckBox" name="compress_checkbox">
<property name="text">
<string>Compress backup</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<layout class="QGridLayout" name="gridLayout_compression">
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_compression">
<item>
<widget class="QLabel" name="label_compression">
<property name="text">
<string>Compression filter:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="compression_combobox"/>
</item>
<item>
<spacer name="horizontalSpacer_compression">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="metadata_warning_label">
Expand Down Expand Up @@ -452,7 +473,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
</widget>
</widget>
<tabstops>
<tabstop>compress_checkbox</tabstop>
<tabstop>compression_combobox</tabstop>
<tabstop>appvm_combobox</tabstop>
<tabstop>dir_line_edit</tabstop>
<tabstop>select_path_button</tabstop>
Expand Down