diff --git a/CHANGES.md b/CHANGES.md index dc3afd9..fe2ff33 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ ### 0.23.0 (2019-xx-xx xx:xx:xx UTC) +* Add db backup to the scheduled daily update +* Add display "Database backups" location at config/about if feature available +* Add option "Backup database plan" to config/general/advanced if feature available +* Add py7zr to recommended.txt for optional 7z compression +* Add `backup_db_path` setting to config.ini to customise backup db location +* Add `backup_db_max_count` to config.ini with range 0-90 where 0 = disable backup, 14 = default * Change improve list performance for file/directory browser * Change improve import shows listing performance * Change improve performance during show rescan process diff --git a/gui/slick/interfaces/default/config.tmpl b/gui/slick/interfaces/default/config.tmpl index ed83147..85c7784 100644 --- a/gui/slick/interfaces/default/config.tmpl +++ b/gui/slick/interfaces/default/config.tmpl @@ -31,6 +31,9 @@ Config file:$sg_str('CONFIG_FILE') Database file:$db.dbFilename() +#if $db.db_supports_backup + Database backups:$backup_db_path +#end if Cache Dir:$sg_str('CACHE_DIR') Arguments:#echo $sg_var('MY_ARGS') or 'None used'# Web Root:$sg_str('WEB_ROOT') diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl index 87f2ebf..16f48f4 100644 --- a/gui/slick/interfaces/default/config_general.tmpl +++ b/gui/slick/interfaces/default/config_general.tmpl @@ -5,6 +5,7 @@ #from sickbeard import config, metadata #from sickbeard.metadata.generic import GenericMetadata #from sickbeard.common import * +#from sickbeard.db import db_supports_backup #from sickbeard.helpers import anon_url, maybe_plural #from sickbeard.logger import reverseNames as file_logging_presets #from sickbeard.sgdatetime import * @@ -796,6 +797,17 @@ +#if $db_supports_backup +
+ +
+#end if diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 1b4fb30..66d6f21 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -545,9 +545,10 @@ SUBTITLES_FINDER_FREQUENCY = 1 USE_FAILED_DOWNLOADS = False DELETE_FAILED = False -MAX_DB_BACKUP_COUNT = 14 -DEFAULT_DB_BACKUP_COUNT = 14 -DB_BACKUP_PATH = '' +BACKUP_DB_PATH = '' +BACKUP_DB_ONEDAY = False +BACKUP_DB_MAX_COUNT = 14 +BACKUP_DB_DEFAULT_COUNT = 14 EXTRA_SCRIPTS = [] SG_EXTRA_SCRIPTS = [] @@ -748,7 +749,7 @@ def init_stage_1(console_logging): # Anime Settings global ANIME_TREAT_AS_HDTV, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST # db backup settings - global MAX_DB_BACKUP_COUNT, DEFAULT_DB_BACKUP_COUNT, DB_BACKUP_PATH + global BACKUP_DB_PATH, BACKUP_DB_ONEDAY, BACKUP_DB_MAX_COUNT, BACKUP_DB_DEFAULT_COUNT for stanza in ('General', 'Blackhole', 'SABnzbd', 'NZBGet', 'Emby', 'Kodi', 'XBMC', 'PLEX', 'Growl', 'Prowl', 'Slack', 'Discord', 'Boxcar2', 'NMJ', 'NMJv2', @@ -1312,10 +1313,10 @@ def init_stage_1(console_logging): if not isinstance(BROWSELIST_MRU, dict): BROWSELIST_MRU = {} - MAX_DB_BACKUP_COUNT = minimax(check_setting_int(CFG, 'Backup', 'max_db_backup_count', DEFAULT_DB_BACKUP_COUNT), - DEFAULT_DB_BACKUP_COUNT, 0, 90) - - DB_BACKUP_PATH = check_setting_str(CFG, 'Backup', 'db_backup_path', '') + BACKUP_DB_PATH = check_setting_str(CFG, 'Backup', 'backup_db_path', '') + BACKUP_DB_ONEDAY = bool(check_setting_int(CFG, 'Backup', 'backup_db_oneday', 0)) + use_count = (1, BACKUP_DB_DEFAULT_COUNT)[not BACKUP_DB_ONEDAY] + BACKUP_DB_MAX_COUNT = minimax(check_setting_int(CFG, 'Backup', 'backup_db_max_count', use_count), use_count, 0, 90) sg_helpers.db = db sg_helpers.DOMAIN_FAILURES.load_from_db() @@ -1885,9 +1886,12 @@ def save_config(): new_config['General']['ignore_words'] = helpers.generate_word_str(IGNORE_WORDS, IGNORE_WORDS_REGEX) new_config['General']['require_words'] = helpers.generate_word_str(REQUIRE_WORDS, REQUIRE_WORDS_REGEX) new_config['General']['calendar_unprotected'] = int(CALENDAR_UNPROTECTED) - new_config['Backup']['max_db_backup_count'] = MAX_DB_BACKUP_COUNT - if DB_BACKUP_PATH: - new_config['Backup']['db_backup_path'] = DB_BACKUP_PATH + + new_config['Backup'] = {} + if BACKUP_DB_PATH: + new_config['Backup']['backup_db_path'] = BACKUP_DB_PATH + new_config['Backup']['backup_db_oneday'] = int(BACKUP_DB_ONEDAY) + new_config['Backup']['backup_db_max_count'] = BACKUP_DB_MAX_COUNT default_not_zero = ('enable_recentsearch', 'enable_backlog', 'enable_scheduled_backlog', 'use_after_get_data') for src in filter_iter(lambda px: GenericProvider.TORRENT == px.providerType, providers.sortedProviderList()): diff --git a/sickbeard/db.py b/sickbeard/db.py index db2ade9..9b07fa8 100644 --- a/sickbeard/db.py +++ b/sickbeard/db.py @@ -776,7 +776,7 @@ def get_rollback_module(): def delete_old_db_backups(target): # type: (AnyStr) -> None """ - remove old db backups (> MAX_DB_BACKUP_COUNT) + remove old db backups (> BACKUP_DB_MAX_COUNT) :param target: backup folder to check """ @@ -786,9 +786,9 @@ def delete_old_db_backups(target): file_list = [f for f in ek.ek(scandir, target) if f.is_file()] for filename in ['sickbeard', 'cache', 'failed']: tb = filter_list(lambda fn: fn.is_file() and filename in fn.name, file_list) - if sickbeard.MAX_DB_BACKUP_COUNT < len(tb): + if sickbeard.BACKUP_DB_MAX_COUNT < len(tb): tb.sort(key=lambda f: f.stat(follow_symlinks=False).st_mtime, reverse=True) - for t in tb[sickbeard.MAX_DB_BACKUP_COUNT:]: + for t in tb[sickbeard.BACKUP_DB_MAX_COUNT:]: try: ek.ek(os.unlink, t.path) except (BaseException, Exception): @@ -810,12 +810,10 @@ def backup_all_dbs(target, compress=True, prefer_7z=True): :param prefer_7z: prefer 7z compression if available :return: success, message """ - if not ek.ek(os.path.isdir, target): - make_dirs(target) - if not ek.ek(os.path.isdir, target): + if not make_dirs(target): logger.log('Failed to create db backup dir', logger.ERROR) return False, 'Failed to create db backup dir' - my_db = DBConnection() + my_db = DBConnection('cache.db') last_backup = my_db.select('SELECT time FROM lastUpdate WHERE provider = ?', ['sickgear_db_backup']) if last_backup: now_stamp = int(timestamp_near(datetime.datetime.now())) @@ -823,10 +821,10 @@ def backup_all_dbs(target, compress=True, prefer_7z=True): # only backup every 23 hours if now_stamp - the_time < 60 * 60 * 23: return False, 'Too early to backup db again' - now = datetime.datetime.now() - d = sgdatetime.SGDatetime.sbfdate(now, d_preset='%d-%m-%Y') + now = sgdatetime.SGDatetime.now() + d = sgdatetime.SGDatetime.sbfdate(now, d_preset='%Y-%m-%d') t = sgdatetime.SGDatetime.sbftime(now, t_preset='%H-%M') - ds = '%s_%s' % (t, d) + ds = '%s_%s' % (d, t) for c in ['sickbeard', 'cache', 'failed']: cur_db = DBConnection('%s.db' % c) b_name = '%s_%s.db' % (c, ds) diff --git a/sickbeard/show_updater.py b/sickbeard/show_updater.py index c469518..bfc6da7 100644 --- a/sickbeard/show_updater.py +++ b/sickbeard/show_updater.py @@ -71,13 +71,13 @@ class ShowUpdater(object): update_date = update_datetime.date() # backup db's - if sickbeard.db.db_supports_backup and 0 < sickbeard.MAX_DB_BACKUP_COUNT: + if sickbeard.db.db_supports_backup and 0 < sickbeard.BACKUP_DB_MAX_COUNT: logger.log('backing up all db\'s') try: - sickbeard.db.backup_all_dbs(sickbeard.DB_BACKUP_PATH or + sickbeard.db.backup_all_dbs(sickbeard.BACKUP_DB_PATH or ek.ek(os.path.join, sickbeard.DATA_DIR, 'backup')) except (BaseException, Exception): - logger.log('DB backup error', logger.ERROR) + logger.log('backup db error', logger.ERROR) # refresh network timezones try: diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 3e17a40..379ccb6 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -6730,6 +6730,9 @@ class Config(MainHandler): except (BaseException, Exception): t.version = '' + t.backup_db_path = sickbeard.BACKUP_DB_MAX_COUNT and \ + (sickbeard.BACKUP_DB_PATH or ek.ek(os.path.join, sickbeard.DATA_DIR, 'backup')) or 'Disabled' + return t.respond() @@ -6957,7 +6960,7 @@ class ConfigGeneral(Config): handle_reverse_proxy=None, send_security_headers=None, allowed_hosts=None, allow_anyip=None, git_remote=None, git_path=None, cpu_preset=None, anon_redirect=None, encryption_version=None, - proxy_setting=None, proxy_indexers=None, file_logging_preset=None): + proxy_setting=None, proxy_indexers=None, file_logging_preset=None, backup_db_oneday=None): results = [] @@ -7067,6 +7070,7 @@ class ConfigGeneral(Config): sickbeard.PROXY_INDEXERS = config.checkbox_to_value(proxy_indexers) sickbeard.FILE_LOGGING_PRESET = file_logging_preset # sickbeard.LOG_DIR is set in config.change_log_dir() + sickbeard.BACKUP_DB_ONEDAY = config.checkbox_to_value(backup_db_oneday) logger.log_set_level()