Example #1
0
    def __init__(self, parent=None):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle('Vorta for Borg Backup')
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
        self.app = parent
        self.current_profile = BackupProfileModel.select().order_by('id').first()
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint)

        self.tests_running = False

        # Load tab models
        self.repoTab = RepoTab(self.repoTabSlot)
        self.sourceTab = SourceTab(self.sourceTabSlot)
        self.archiveTab = ArchiveTab(self.archiveTabSlot)
        self.scheduleTab = ScheduleTab(self.scheduleTabSlot)
        self.miscTab = MiscTab(self.miscTabSlot)
        self.miscTab.set_borg_details(borg_compat.version, borg_compat.path)
        self.tabWidget.setCurrentIndex(0)

        self.repoTab.repo_changed.connect(self.archiveTab.populate_from_profile)
        self.repoTab.repo_added.connect(self.archiveTab.list_action)
        self.tabWidget.currentChanged.connect(self.scheduleTab._draw_next_scheduled_backup)

        self.createStartBtn.clicked.connect(self.app.create_backup_action)
        self.cancelButton.clicked.connect(self.app.backup_cancelled_event.emit)

        QShortcut(QKeySequence("Ctrl+W"), self).activated.connect(self.on_close_window)
        QShortcut(QKeySequence("Ctrl+Q"), self).activated.connect(self.on_close_window)

        self.app.backup_started_event.connect(self.backup_started_event)
        self.app.backup_finished_event.connect(self.backup_finished_event)
        self.app.backup_log_event.connect(self.set_status)
        self.app.backup_cancelled_event.connect(self.backup_cancelled_event)

        # Init profile list
        for profile in BackupProfileModel.select():
            self.profileSelector.addItem(profile.name, profile.id)
        self.profileSelector.setCurrentIndex(0)
        self.profileSelector.currentIndexChanged.connect(self.profile_select_action)
        self.profileRenameButton.clicked.connect(self.profile_rename_action)
        self.profileDeleteButton.clicked.connect(self.profile_delete_action)
        self.profileAddButton.clicked.connect(self.profile_add_action)

        # OS-specific startup options:
        if sys.platform != 'darwin':
            # Hide Wifi-rule section in schedule tab.
            self.scheduleTab.wifiListLabel.hide()
            self.scheduleTab.wifiListWidget.hide()
            self.scheduleTab.page_2.hide()
            self.scheduleTab.toolBox.removeItem(1)

        # Connect to existing thread.
        if BorgThread.is_running():
            self.createStartBtn.setEnabled(False)
            self.cancelButton.setEnabled(True)
            self.set_status(self.tr('Backup in progress.'), progress_max=0)
Example #2
0
def test_profile_edit(qapp, qtbot):
    main = qapp.main_window
    edit_profile_window = EditProfileWindow(
        main, rename_existing_id=main.profileSelector.currentData())
    qtbot.addWidget(edit_profile_window)

    # Edit profile name
    edit_profile_window.profileNameField.setText("")
    qtbot.keyClicks(edit_profile_window.profileNameField, 'Test Profile')
    qtbot.mouseClick(
        edit_profile_window.buttonBox.button(QDialogButtonBox.Save),
        QtCore.Qt.LeftButton)
    assert BackupProfileModel.get_or_none(name='Default') is None
    assert BackupProfileModel.get_or_none(name='Test Profile') is not None
Example #3
0
def app(tmpdir, qtbot, mocker):
    tmp_db = tmpdir.join('settings.sqlite')
    mock_db = peewee.SqliteDatabase(str(tmp_db))
    vorta.models.init_db(mock_db)
    mocker.patch.object(vorta.application.VortaApp,
                        'set_borg_details_action',
                        return_value=None)

    new_repo = RepoModel(url='[email protected]:repo')
    new_repo.save()

    profile = BackupProfileModel.get(id=1)
    profile.repo = new_repo.id
    profile.save()

    test_archive = ArchiveModel(snapshot_id='99999',
                                name='test-archive',
                                time=dt(2000, 1, 1, 0, 0),
                                repo=1)
    test_archive.save()

    source_dir = SourceFileModel(dir='/tmp/another', repo=new_repo)
    source_dir.save()

    app = VortaApp([])
    app.open_main_window_action()
    qtbot.addWidget(app.main_window)
    app.main_window.tests_running = True
    return app
Example #4
0
    def on_user_click(self):
        """Build system tray menu based on current state."""

        menu = self.contextMenu()
        menu.clear()

        open_action = menu.addAction(self.tr('Vorta for Borg Backup'))
        open_action.triggered.connect(self.app.open_main_window_action)

        menu.addSeparator()

        status = menu.addAction(self.app.scheduler.next_job)
        status.setEnabled(False)

        if BorgThread.is_running():
            status.setText(self.tr('Backup in Progress'))
            cancel_action = menu.addAction(self.tr('Cancel Backup'))
            cancel_action.triggered.connect(self.app.backup_cancelled_event.emit)
        else:
            status.setText(self.tr('Next Task: %s') % self.app.scheduler.next_job)
            profiles = BackupProfileModel.select()
            if profiles.count() > 1:
                profile_menu = menu.addMenu(self.tr('Backup Now'))
                for profile in profiles:
                    new_item = profile_menu.addAction(profile.name)
                    new_item.triggered.connect(lambda state, i=profile.id: self.app.create_backup_action(i))
            else:
                profile = profiles.first()
                profile_menu = menu.addAction(self.tr('Backup Now'))
                profile_menu.triggered.connect(lambda state, i=profile.id: self.app.create_backup_action(i))

        menu.addSeparator()

        exit_action = menu.addAction(self.tr('Quit'))
        exit_action.triggered.connect(self.app.quit)
Example #5
0
def app(tmpdir, qtbot):
    tmp_db = tmpdir.join('settings.sqlite')
    mock_db = peewee.SqliteDatabase(str(tmp_db))
    vorta.models.init_db(mock_db)

    new_repo = RepoModel(url='[email protected]:repo')
    new_repo.save()

    profile = BackupProfileModel.get(id=1)
    profile.repo = new_repo.id
    profile.save()

    test_archive = ArchiveModel(snapshot_id='99999',
                                name='test-archive',
                                time=dt(2000, 1, 1, 0, 0),
                                repo=1)
    test_archive.save()

    source_dir = SourceFileModel(dir='/tmp/another', repo=new_repo)
    source_dir.save()

    app = VortaApp([])
    app.main_window.show()
    qtbot.addWidget(app.main_window)
    return app
Example #6
0
def init_db(qapp):
    vorta.models.db.drop_tables(models)
    vorta.models.init_db()

    new_repo = RepoModel(url='[email protected]:repo')
    new_repo.encryption = 'none'
    new_repo.save()

    profile = BackupProfileModel.get(id=1)
    profile.repo = new_repo.id
    profile.dont_run_on_metered_networks = False
    profile.save()

    test_archive = ArchiveModel(snapshot_id='99999',
                                name='test-archive',
                                time=dt(2000, 1, 1, 0, 0),
                                repo=1)
    test_archive.save()

    test_archive1 = ArchiveModel(snapshot_id='99998',
                                 name='test-archive1',
                                 time=dt(2000, 1, 1, 0, 0),
                                 repo=1)
    test_archive1.save()

    source_dir = SourceFileModel(dir='/tmp/another',
                                 repo=new_repo,
                                 dir_size=100,
                                 dir_files_count=18,
                                 path_isdir=True)
    source_dir.save()

    qapp.main_window = MainWindow(
        qapp)  # Re-open main window to apply mock data in UI
Example #7
0
    def create_backup(self, profile_id):
        notifier = VortaNotifications.pick()
        profile = BackupProfileModel.get(id=profile_id)

        logger.info('Starting background backup for %s', profile.name)
        notifier.deliver(self.tr('Vorta Backup'),
                         self.tr('Starting background backup for %s.') % profile.name,
                         level='info')

        msg = BorgCreateThread.prepare(profile)
        if msg['ok']:
            logger.info('Preparation for backup successful.')
            thread = BorgCreateThread(msg['cmd'], msg)
            thread.start()
            thread.wait()
            if thread.process.returncode in [0, 1]:
                notifier.deliver(self.tr('Vorta Backup'),
                                 self.tr('Backup successful for %s.') % profile.name,
                                 level='info')
                logger.info('Backup creation successful.')
                self.post_backup_tasks(profile_id)
            else:
                notifier.deliver(self.tr('Vorta Backup'), self.tr('Error during backup creation.'), level='error')
                logger.error('Error during backup creation.')
        else:
            logger.error('Conditions for backup not met. Aborting.')
            logger.error(msg['message'])
            notifier.deliver(self.tr('Vorta Backup'), translate('messages', msg['message']), level='error')
Example #8
0
    def profile_delete_action(self):
        if self.profileSelector.count() > 1:
            to_delete = BackupProfileModel.get(
                id=self.profileSelector.currentData())

            # Remove pending background jobs
            to_delete_id = str(to_delete.id)
            msg = self.tr(
                "Are you sure you want to delete profile '{}'?".format(
                    to_delete.name))
            reply = QMessageBox.question(self, self.tr("Confirm deletion"),
                                         msg, QMessageBox.Yes | QMessageBox.No,
                                         QMessageBox.No)

            if reply == QMessageBox.Yes:
                if self.app.scheduler.get_job(to_delete_id):
                    self.app.scheduler.remove_job(to_delete_id)
                to_delete.delete_instance(recursive=True)
                self.profileSelector.removeItem(
                    self.profileSelector.currentIndex())
                self.profile_select_action(0)

        else:
            warn = self.tr("Can't delete the last profile.")
            point = QPoint(0, self.profileDeleteButton.size().height() / 2)
            QToolTip.showText(self.profileDeleteButton.mapToGlobal(point),
                              warn)
Example #9
0
def init_db(qapp):
    vorta.models.db.drop_tables(models)
    vorta.models.init_db()

    new_repo = RepoModel(url='[email protected]:repo')
    new_repo.save()

    profile = BackupProfileModel.get(id=1)
    profile.repo = new_repo.id
    profile.save()

    test_archive = ArchiveModel(snapshot_id='99999',
                                name='test-archive',
                                time=dt(2000, 1, 1, 0, 0),
                                repo=1)
    test_archive.save()

    test_archive1 = ArchiveModel(snapshot_id='99998',
                                 name='test-archive1',
                                 time=dt(2000, 1, 1, 0, 0),
                                 repo=1)
    test_archive1.save()

    source_dir = SourceFileModel(dir='/tmp/another', repo=new_repo)
    source_dir.save()

    qapp.open_main_window_action()
Example #10
0
 def profile_select_action(self, index):
     self.current_profile = BackupProfileModel.get(
         id=self.profileSelector.currentData())
     self.archiveTab.populate_from_profile()
     self.repoTab.populate_from_profile()
     self.sourceTab.populate_from_profile()
     self.scheduleTab.populate_from_profile()
Example #11
0
 def populate_profile_selector(self):
     self.profileSelector.clear()
     for profile in BackupProfileModel.select().order_by(
             BackupProfileModel.name):
         self.profileSelector.addItem(profile.name, profile.id)
     current_profile_index = self.profileSelector.findData(
         self.current_profile.id)
     self.profileSelector.setCurrentIndex(current_profile_index)
Example #12
0
def test_import_bootstrap_success(qapp, mocker):
    mocked_unlink = mocker.MagicMock()
    mocker.patch.object(Path, 'unlink', mocked_unlink)
    qapp.bootstrap_profile(Path(VALID_IMPORT_FILE))

    assert mocked_unlink.called

    restored_profile = BackupProfileModel.get_or_none(
        name="Test Profile Restoration")
    assert restored_profile is not None

    restored_repo = restored_profile.repo
    assert restored_repo is not None

    assert len(SourceFileModel.select().where(
        SourceFileModel.profile == restored_profile)) == 3
    assert BackupProfileModel.select().count() == 2
Example #13
0
 def profile_select_action(self, index):
     self.current_profile = BackupProfileModel.get(id=self.profileSelector.currentData())
     self.archiveTab.populate_from_profile()
     self.repoTab.populate_from_profile()
     self.sourceTab.populate_from_profile()
     self.scheduleTab.populate_from_profile()
     SettingsModel.update({SettingsModel.str_value: self.current_profile.id})\
         .where(SettingsModel.key == 'previous_profile_id')\
         .execute()
Example #14
0
def test_profile_edit(qapp, qtbot):
    main = qapp.main_window
    qtbot.mouseClick(main.profileRenameButton, QtCore.Qt.LeftButton)

    edit_profile_window = main.window
    qtbot.addWidget(edit_profile_window)
    qtbot.waitUntil(lambda: edit_profile_window == qapp.activeWindow(),
                    timeout=5000)

    edit_profile_window.profileNameField.setText("")
    qtbot.keyClicks(edit_profile_window.profileNameField, 'Test Profile')
    qtbot.mouseClick(
        edit_profile_window.buttonBox.button(QDialogButtonBox.Save),
        QtCore.Qt.LeftButton)

    assert BackupProfileModel.get_or_none(name='Default') is None
    assert BackupProfileModel.get_or_none(name='Test Profile') is not None
    assert main.profileSelector.currentText() == 'Test Profile'
Example #15
0
def delete_current_profile(qapp):
    ''' Delete current profile for cleanup '''
    main = qapp.main_window
    target = BackupProfileModel.get(id=main.profileSelector.currentData())
    if qapp.scheduler.get_job(target.id):
        qapp.scheduler.remove_job(target.id)
    target.delete_instance(recursive=True)
    main.profileSelector.removeItem(main.profileSelector.currentIndex())
    main.profile_select_action(0)
Example #16
0
 def bootstrap_profile(self, bootstrap_file=PROFILE_BOOTSTRAP_FILE):
     """
     Make sure there is at least one profile when first starting Vorta.
     Will either import a profile placed in ~/.vorta-init.json
     or add an empty "Default" profile.
     """
     if bootstrap_file.is_file():
         profile_export = ProfileExport.from_json(bootstrap_file)
         profile = profile_export.to_db(overwrite_profile=True,
                                        overwrite_settings=True)
         bootstrap_file.unlink()
         notifier = VortaNotifications.pick()
         notifier.deliver(self.tr('Profile import successful!'),
                          self.tr('Profile {} imported.').format(
                              profile.name),
                          level='info')
         logger.info('Profile {} imported.'.format(profile.name))
     if BackupProfileModel.select().count() == 0:
         default_profile = BackupProfileModel(name='Default')
         default_profile.save()
Example #17
0
 def init_overwrite_profile_checkbox(self):
     """Disable the overwrite profile checkbox if no profile with that name currently exists."""
     existing_backup_profile = BackupProfileModel.get_or_none(
         BackupProfileModel.name == self.profile_export.name)
     if not existing_backup_profile:
         self.overwriteExistingProfile.setChecked(False)
         self.overwriteExistingProfile.setEnabled(False)
         self.overwriteExistingProfile.setToolTip(
             self.
             tr('A profile with the name {} does not exist. Nothing to overwrite.'
                .format(self.profile_export.name)))
Example #18
0
 def create_backups_cmdline(self, profile_name):
     profile = BackupProfileModel.get_or_none(name=profile_name)
     if profile is not None:
         if profile.repo is None:
             logger.warning(f"Add a repository to {profile_name}")
         # Wait a bit in case something is running
         while BorgThread.is_running():
             time.sleep(0.1)
         self.create_backup_action(profile_id=profile.id)
     else:
         logger.warning(f"Invalid profile name {profile_name}")
Example #19
0
def test_prune_intervals(qapp, qtbot):
    prune_intervals = ['hour', 'day', 'week', 'month', 'year']
    main = qapp.main_window
    tab = main.archiveTab
    profile = BackupProfileModel.get(id=1)

    for i in prune_intervals:
        getattr(tab, f'prune_{i}').setValue(9)
        tab.save_prune_setting(None)
        profile = profile.refresh()
        assert getattr(profile, f'prune_{i}') == 9
Example #20
0
def test_profile_add(qapp, qtbot):
    main = qapp.main_window
    add_profile_window = AddProfileWindow(main)
    qtbot.addWidget(add_profile_window)

    # Add a new profile
    qtbot.keyClicks(add_profile_window.profileNameField, 'Test Profile')
    qtbot.mouseClick(
        add_profile_window.buttonBox.button(QDialogButtonBox.Save),
        QtCore.Qt.LeftButton)
    assert BackupProfileModel.get_or_none(name='Test Profile') is not None
Example #21
0
    def profile_delete_action(self):
        if self.profileSelector.count() > 1:
            to_delete = BackupProfileModel.get(id=self.profileSelector.currentData())

            # Remove pending background jobs
            to_delete_id = str(to_delete.id)
            if self.app.scheduler.get_job(to_delete_id):
                self.app.scheduler.remove_job(to_delete_id)

            to_delete.delete_instance(recursive=True)
            self.profileSelector.removeItem(self.profileSelector.currentIndex())
            self.profile_select_action(0)
Example #22
0
    def create_backup_action(self, profile_id=None):
        if not profile_id:
            profile_id = self.main_window.current_profile.id

        profile = BackupProfileModel.get(id=profile_id)
        msg = BorgCreateThread.prepare(profile)
        if msg['ok']:
            thread = BorgCreateThread(msg['cmd'], msg, parent=self)
            thread.start()
        else:
            notifier = VortaNotifications.pick()
            notifier.deliver(self.tr('Vorta Backup'), translate('messages', msg['message']), level='error')
            self.backup_log_event.emit(translate('messages', msg['message']))
Example #23
0
    def next_job(self):
        self.wakeup()
        self._process_jobs()
        jobs = []
        for job in self.get_jobs():
            jobs.append((job.next_run_time, job.id))

        if jobs:
            jobs.sort(key=lambda job: job[0])
            profile = BackupProfileModel.get(id=int(jobs[0][1]))
            return f"{jobs[0][0].strftime('%H:%M')} ({profile.name})"
        else:
            return self.tr('None scheduled')
Example #24
0
def init_db(qapp, qtbot, tmpdir_factory):
    tmp_db = tmpdir_factory.mktemp('Vorta').join('settings.sqlite')
    mock_db = peewee.SqliteDatabase(str(tmp_db),
                                    pragmas={
                                        'journal_mode': 'wal',
                                    })
    vorta.models.init_db(mock_db)

    default_profile = BackupProfileModel(name='Default')
    default_profile.save()

    new_repo = RepoModel(url='[email protected]:repo')
    new_repo.encryption = 'none'
    new_repo.save()

    default_profile.repo = new_repo.id
    default_profile.dont_run_on_metered_networks = False
    default_profile.save()

    test_archive = ArchiveModel(snapshot_id='99999',
                                name='test-archive',
                                time=dt(2000, 1, 1, 0, 0),
                                repo=1)
    test_archive.save()

    test_archive1 = ArchiveModel(snapshot_id='99998',
                                 name='test-archive1',
                                 time=dt(2000, 1, 1, 0, 0),
                                 repo=1)
    test_archive1.save()

    source_dir = SourceFileModel(dir='/tmp/another',
                                 repo=new_repo,
                                 dir_size=100,
                                 dir_files_count=18,
                                 path_isdir=True)
    source_dir.save()

    qapp.main_window.deleteLater()
    del qapp.main_window
    qapp.main_window = MainWindow(
        qapp)  # Re-open main window to apply mock data in UI

    yield
    qapp.backup_cancelled_event.emit()
    qtbot.waitUntil(lambda: not vorta.borg.borg_thread.BorgThread.is_running())
    mock_db.close()
Example #25
0
    def profile_delete_action(self):
        if self.profileSelector.count() > 1:
            to_delete = BackupProfileModel.get(id=self.profileSelector.currentData())

            # Remove pending background jobs
            to_delete_id = str(to_delete.id)
            msg = self.tr("Are you sure you want to delete profile '{}'?".format(to_delete.name))
            reply = QMessageBox.question(self, self.tr("Confirm deletion"),
                                         msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

            if reply == QMessageBox.Yes:
                if self.app.scheduler.get_job(to_delete_id):
                    self.app.scheduler.remove_job(to_delete_id)
                to_delete.delete_instance(recursive=True)
                self.profileSelector.removeItem(self.profileSelector.currentIndex())
                self.profile_select_action(0)
Example #26
0
def test_profile_add(qapp, qtbot):
    main = qapp.main_window
    qtbot.mouseClick(main.profileAddButton, QtCore.Qt.LeftButton)

    add_profile_window = main.window
    qtbot.addWidget(add_profile_window)
    qtbot.waitUntil(lambda: add_profile_window == qapp.activeWindow(),
                    **pytest._wait_defaults)

    qtbot.keyClicks(add_profile_window.profileNameField, 'Test Profile')
    qtbot.mouseClick(
        add_profile_window.buttonBox.button(QDialogButtonBox.Save),
        QtCore.Qt.LeftButton)

    assert BackupProfileModel.get_or_none(name='Test Profile') is not None
    assert main.profileSelector.currentText() == 'Test Profile'
Example #27
0
    def reload(self):
        for profile in BackupProfileModel.select():
            trigger = None
            job_id = f'{profile.id}'
            if profile.schedule_mode == 'interval':
                if profile.schedule_interval_hours >= 24:
                    days = profile.schedule_interval_hours // 24
                    leftover_hours = profile.schedule_interval_hours % 24

                    if leftover_hours == 0:
                        cron_hours = '1'
                    else:
                        cron_hours = f'*/{leftover_hours}'

                    trigger = cron.CronTrigger(day=f'*/{days}',
                                               hour=cron_hours,
                                               minute=profile.schedule_interval_minutes)
                else:
                    trigger = cron.CronTrigger(hour=f'*/{profile.schedule_interval_hours}',
                                               minute=profile.schedule_interval_minutes)
            elif profile.schedule_mode == 'fixed':
                trigger = cron.CronTrigger(hour=profile.schedule_fixed_hour,
                                           minute=profile.schedule_fixed_minute)
            if self.get_job(job_id) is not None and trigger is not None:
                self.reschedule_job(job_id, trigger=trigger)
                notifier = VortaNotifications.pick()
                notifier.deliver(self.tr('Vorta Scheduler'), self.tr('Background scheduler was changed.'))
                logger.debug('Job for profile %s was rescheduled.', profile.name)
            elif trigger is not None:
                self.add_job(
                    func=self.create_backup,
                    args=[profile.id],
                    trigger=trigger,
                    id=job_id,
                    misfire_grace_time=180
                )
                logger.debug('New job for profile %s was added.', profile.name)
            elif self.get_job(job_id) is not None and trigger is None:
                self.remove_job(job_id)
                logger.debug('Job for profile %s was removed.', profile.name)
Example #28
0
def test_import_success(qapp, qtbot, rootdir, monkeypatch):
    monkeypatch.setattr(QFileDialog, "getOpenFileName",
                        lambda *args: [VALID_IMPORT_FILE])
    monkeypatch.setattr(QMessageBox, 'information', lambda *args: None)

    main = qapp.main_window
    main.profile_import_action()
    import_dialog: ImportWindow = main.window
    import_dialog.overwriteExistingSettings.setChecked(True)

    qtbot.mouseClick(import_dialog.buttonBox.button(QDialogButtonBox.Ok),
                     QtCore.Qt.LeftButton)
    qtbot.waitSignal(import_dialog.profile_imported, **pytest._wait_defaults)

    restored_profile = BackupProfileModel.get_or_none(
        name="Test Profile Restoration")
    assert restored_profile is not None

    restored_repo = restored_profile.repo
    assert restored_repo is not None
    assert len(SourceFileModel.select().where(
        SourceFileModel.profile == restored_profile)) == 3
Example #29
0
    def post_backup_tasks(self, profile_id):
        """
        Pruning and checking after successful backup.
        """
        profile = BackupProfileModel.get(id=profile_id)
        logger.info('Doing post-backup jobs for %s', profile.name)
        if profile.prune_on:
            msg = BorgPruneThread.prepare(profile)
            if msg['ok']:
                prune_thread = BorgPruneThread(msg['cmd'], msg)
                prune_thread.start()
                prune_thread.wait()

                # Refresh archives
                msg = BorgListRepoThread.prepare(profile)
                if msg['ok']:
                    list_thread = BorgListRepoThread(msg['cmd'], msg)
                    list_thread.start()
                    list_thread.wait()

        validation_cutoff = date.today() - timedelta(days=7 * profile.validation_weeks)
        recent_validations = EventLogModel.select().where(
            (
                EventLogModel.subcommand == 'check'
            ) & (
                EventLogModel.start_time > validation_cutoff
            ) & (
                EventLogModel.repo_url == profile.repo.url
            )
        ).count()
        if profile.validation_on and recent_validations == 0:
            msg = BorgCheckThread.prepare(profile)
            if msg['ok']:
                check_thread = BorgCheckThread(msg['cmd'], msg)
                check_thread.start()
                check_thread.wait()

        logger.info('Finished background task for profile %s', profile.name)
Example #30
0
 def react_to_log(self, mgs, context):
     """
     Trigger Vorta actions based on Borg logs. E.g. repo lock.
     """
     msgid = context.get('msgid')
     if msgid == 'LockTimeout':
         profile = BackupProfileModel.get(name=context['profile_name'])
         repo_url = context.get('repo_url')
         msg = QMessageBox()
         msg.setWindowTitle(self.tr("Repository In Use"))
         msg.setIcon(QMessageBox.Critical)
         abortButton = msg.addButton(self.tr("Abort"),
                                     QMessageBox.RejectRole)
         msg.addButton(self.tr("Continue"), QMessageBox.AcceptRole)
         msg.setDefaultButton(abortButton)
         msg.setText(
             self.
             tr(f"The repository at {repo_url} might be in use elsewhere."))
         msg.setInformativeText(
             self.
             tr("Only break the lock if you are certain no other Borg process "
                "on any machine is accessing the repository. Abort or break the lock?"
                ))
         msg.accepted.connect(lambda: self.break_lock(profile))
         self._msg = msg
         msg.show()
     elif msgid == 'LockFailed':
         repo_url = context.get('repo_url')
         msg = QMessageBox()
         msg.setText(
             self.
             tr(f"You do not have permission to access the repository at {repo_url}. Gain access and try again."
                ))  # noqa: E501
         msg.setWindowTitle(self.tr("No Repository Permissions"))
         self._msg = msg
         msg.show()