1
0
Fork 0
mirror of https://github.com/borgbase/vorta synced 2025-03-12 07:09:37 +00:00

Address DB Locking issues (#1109)

This commit is contained in:
Manu 2021-11-16 10:32:40 +04:00 committed by GitHub
parent 5b769b104f
commit 0c77fdde97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 32 deletions

View file

@ -2,7 +2,7 @@ import os
import signal import signal
import sys import sys
import peewee from peewee import SqliteDatabase
from vorta._version import __version__ from vorta._version import __version__
from vorta.i18n import trans_late, translate from vorta.i18n import trans_late, translate
from vorta.config import SETTINGS_DIR from vorta.config import SETTINGS_DIR
@ -50,7 +50,7 @@ def main():
init_logger(background=want_background) init_logger(background=want_background)
# Init database # Init database
sqlite_db = peewee.SqliteDatabase(os.path.join(SETTINGS_DIR, 'settings.db'), pragmas={'journal_mode': 'wal', }) sqlite_db = SqliteDatabase(os.path.join(SETTINGS_DIR, 'settings.db'), pragmas={'journal_mode': 'wal', })
init_db(sqlite_db) init_db(sqlite_db)
# Init app after database is available # Init app after database is available

View file

@ -21,7 +21,8 @@ from vorta.utils import borg_compat, pretty_bytes
from vorta.keyring.abc import VortaKeyring from vorta.keyring.abc import VortaKeyring
from vorta.keyring.db import VortaDBKeyring from vorta.keyring.db import VortaDBKeyring
temp_mutex = Lock() keyring_lock = Lock()
db_lock = Lock()
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
FakeRepo = namedtuple('Repo', ['url', 'id', 'extra_borg_arguments', 'encryption']) FakeRepo = namedtuple('Repo', ['url', 'id', 'extra_borg_arguments', 'encryption'])
@ -144,27 +145,26 @@ class BorgJob(JobInterface, BackupProfileMixin):
return ret return ret
# Try to get password from chosen keyring backend. # Try to get password from chosen keyring backend.
temp_mutex.acquire() with keyring_lock:
cls.keyring = VortaKeyring.get_keyring() cls.keyring = VortaKeyring.get_keyring()
logger.debug("Using %s keyring to store passwords.", cls.keyring.__class__.__name__) logger.debug("Using %s keyring to store passwords.", cls.keyring.__class__.__name__)
ret['password'] = cls.keyring.get_password('vorta-repo', profile.repo.url) ret['password'] = cls.keyring.get_password('vorta-repo', profile.repo.url)
# Check if keyring is locked # Check if keyring is locked
if profile.repo.encryption != 'none' and not cls.keyring.is_unlocked: if profile.repo.encryption != 'none' and not cls.keyring.is_unlocked:
ret['message'] = trans_late('messages', ret['message'] = trans_late('messages',
'Please unlock your system password manager or disable it under Misc') 'Please unlock your system password manager or disable it under Misc')
return ret return ret
# Try to fall back to DB Keyring, if we use the system keychain. # Try to fall back to DB Keyring, if we use the system keychain.
if ret['password'] is None and cls.keyring.is_system: if ret['password'] is None and cls.keyring.is_system:
logger.debug('Password not found in primary keyring. Falling back to VortaDBKeyring.') logger.debug('Password not found in primary keyring. Falling back to VortaDBKeyring.')
ret['password'] = VortaDBKeyring().get_password('vorta-repo', profile.repo.url) ret['password'] = VortaDBKeyring().get_password('vorta-repo', profile.repo.url)
# Give warning and continue if password is found there. # Give warning and continue if password is found there.
if ret['password'] is not None: if ret['password'] is not None:
logger.warning('Found password in database, but secure storage was available. ' logger.warning('Found password in database, but secure storage was available. '
'Consider re-adding the repo to use it.') 'Consider re-adding the repo to use it.')
temp_mutex.release()
# Password is required for encryption, cannot continue # Password is required for encryption, cannot continue
if ret['password'] is None and not isinstance(profile.repo, FakeRepo) and profile.repo.encryption != 'none': if ret['password'] is None and not isinstance(profile.repo, FakeRepo) and profile.repo.encryption != 'none':
@ -204,12 +204,13 @@ class BorgJob(JobInterface, BackupProfileMixin):
def run(self): def run(self):
self.started_event() self.started_event()
log_entry = EventLogModel(category=self.params.get('category', 'user'), with db_lock:
subcommand=self.cmd[1], log_entry = EventLogModel(category=self.params.get('category', 'user'),
profile=self.params.get('profile_id', None) subcommand=self.cmd[1],
) profile=self.params.get('profile_id', None)
log_entry.save() )
logger.info('Running command %s', ' '.join(self.cmd)) log_entry.save()
logger.info('Running command %s', ' '.join(self.cmd))
p = Popen(self.cmd, stdout=PIPE, stderr=PIPE, bufsize=1, universal_newlines=True, p = Popen(self.cmd, stdout=PIPE, stderr=PIPE, bufsize=1, universal_newlines=True,
env=self.env, cwd=self.cwd, start_new_session=True) env=self.env, cwd=self.cwd, start_new_session=True)
@ -285,9 +286,10 @@ class BorgJob(JobInterface, BackupProfileMixin):
log_entry.returncode = p.returncode log_entry.returncode = p.returncode
log_entry.repo_url = self.params.get('repo_url', None) log_entry.repo_url = self.params.get('repo_url', None)
log_entry.end_time = dt.now() log_entry.end_time = dt.now()
log_entry.save() with db_lock:
log_entry.save()
self.process_result(result)
self.process_result(result)
self.finished_event(result) self.finished_event(result)
def process_result(self, result): def process_result(self, result):

View file

@ -1,5 +1,5 @@
import os import os
import peewee from peewee import SqliteDatabase
import pytest import pytest
import sys import sys
from datetime import datetime as dt from datetime import datetime as dt
@ -26,7 +26,7 @@ def pytest_configure(config):
def qapp(tmpdir_factory): def qapp(tmpdir_factory):
# DB is required to init QApplication. New DB used for every test. # DB is required to init QApplication. New DB used for every test.
tmp_db = tmpdir_factory.mktemp('Vorta').join('settings.sqlite') tmp_db = tmpdir_factory.mktemp('Vorta').join('settings.sqlite')
mock_db = peewee.SqliteDatabase(str(tmp_db)) mock_db = SqliteDatabase(str(tmp_db))
vorta.models.init_db(mock_db) vorta.models.init_db(mock_db)
from vorta.application import VortaApp from vorta.application import VortaApp
@ -43,7 +43,7 @@ def qapp(tmpdir_factory):
@pytest.fixture(scope='function', autouse=True) @pytest.fixture(scope='function', autouse=True)
def init_db(qapp, qtbot, tmpdir_factory): def init_db(qapp, qtbot, tmpdir_factory):
tmp_db = tmpdir_factory.mktemp('Vorta').join('settings.sqlite') tmp_db = tmpdir_factory.mktemp('Vorta').join('settings.sqlite')
mock_db = peewee.SqliteDatabase(str(tmp_db), pragmas={'journal_mode': 'wal', }) mock_db = SqliteDatabase(str(tmp_db), pragmas={'journal_mode': 'wal', })
vorta.models.init_db(mock_db) vorta.models.init_db(mock_db)
default_profile = BackupProfileModel(name='Default') default_profile = BackupProfileModel(name='Default')