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:
parent
5b769b104f
commit
0c77fdde97
3 changed files with 34 additions and 32 deletions
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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')
|
||||||
|
|
Loading…
Add table
Reference in a new issue