mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-11 07:46:07 -07:00
Add fucntion to import a config file
This commit is contained in:
parent
beff5caaac
commit
06665fdd06
2 changed files with 115 additions and 3 deletions
|
@ -190,6 +190,56 @@ _CONFIG_DEFINITIONS = {
|
||||||
_BLACKLIST_KEYS = ['_APITOKEN', '_TOKEN', '_KEY', '_SECRET', '_PASSWORD', '_APIKEY', '_ID', '_HOOK']
|
_BLACKLIST_KEYS = ['_APITOKEN', '_TOKEN', '_KEY', '_SECRET', '_PASSWORD', '_APIKEY', '_ID', '_HOOK']
|
||||||
_WHITELIST_KEYS = ['HTTPS_KEY']
|
_WHITELIST_KEYS = ['HTTPS_KEY']
|
||||||
|
|
||||||
|
_DO_NOT_IMPORT_KEYS = [
|
||||||
|
'FIRST_RUN_COMPLETE', 'GET_FILE_SIZES_HOLD', 'GIT_PATH',
|
||||||
|
'BACKUP_DIR', 'CACHE_DIR', 'LOG_DIR', 'NEWSLETTER_DIR', 'NEWSLETTER_CUSTOM_DIR',
|
||||||
|
'HTTP_HOST', 'HTTP_PORT', 'HTTP_ROOT',
|
||||||
|
'HTTP_USERNAME', 'HTTP_PASSWORD', 'HTTP_HASH_PASSWORD', 'HTTP_HASHED_PASSWORD',
|
||||||
|
'ENABLE_HTTPS', 'HTTPS_CREATE_CERT', 'HTTPS_CERT', 'HTTPS_CERT_CHAIN', 'HTTPS_KEY'
|
||||||
|
]
|
||||||
|
_DO_NOT_IMPORT_KEYS_DOCKER = [
|
||||||
|
'PLEXPY_AUTO_UPDATE', 'GIT_REMOTE', 'GIT_BRANCH'
|
||||||
|
]
|
||||||
|
|
||||||
|
IS_IMPORTING = False
|
||||||
|
|
||||||
|
|
||||||
|
def set_is_importing(value):
|
||||||
|
global IS_IMPORTING
|
||||||
|
IS_IMPORTING = value
|
||||||
|
|
||||||
|
|
||||||
|
def import_tautulli_config(config=None, backup=False):
|
||||||
|
if backup:
|
||||||
|
# Make a backup of the current config first
|
||||||
|
logger.info("Tautulli Config :: Creating a config backup before importing.")
|
||||||
|
if not make_backup():
|
||||||
|
logger.error("Tautulli Config :: Failed to import Tautulli config: failed to create config backup")
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.info("Tautulli Config :: Importing Tautulli config '%s'...", config)
|
||||||
|
set_is_importing(True)
|
||||||
|
|
||||||
|
# Create a new Config object with the imported config file
|
||||||
|
imported_config = Config(config, is_import=True)
|
||||||
|
|
||||||
|
# Remove keys that should not be imported
|
||||||
|
for key in _DO_NOT_IMPORT_KEYS:
|
||||||
|
delattr(imported_config, key)
|
||||||
|
if plexpy.DOCKER:
|
||||||
|
for key in _DO_NOT_IMPORT_KEYS_DOCKER:
|
||||||
|
delattr(imported_config, key)
|
||||||
|
|
||||||
|
# Merge the imported config file into the current config file
|
||||||
|
plexpy.CONFIG._config.merge(imported_config._config)
|
||||||
|
plexpy.CONFIG.write()
|
||||||
|
|
||||||
|
logger.info("Tautulli Config :: Tautulli config import complete.")
|
||||||
|
set_is_importing(False)
|
||||||
|
|
||||||
|
# Restart to apply changes
|
||||||
|
plexpy.SIGNAL = 'restart'
|
||||||
|
|
||||||
|
|
||||||
def make_backup(cleanup=False, scheduler=False):
|
def make_backup(cleanup=False, scheduler=False):
|
||||||
""" Makes a backup of config file, removes all but the last 5 backups """
|
""" Makes a backup of config file, removes all but the last 5 backups """
|
||||||
|
@ -233,12 +283,13 @@ def make_backup(cleanup=False, scheduler=False):
|
||||||
class Config(object):
|
class Config(object):
|
||||||
""" Wraps access to particular values in a config file """
|
""" Wraps access to particular values in a config file """
|
||||||
|
|
||||||
def __init__(self, config_file):
|
def __init__(self, config_file, is_import=False):
|
||||||
""" Initialize the config with values from a file """
|
""" Initialize the config with values from a file """
|
||||||
self._config_file = config_file
|
self._config_file = config_file
|
||||||
self._config = ConfigObj(self._config_file, encoding='utf-8')
|
self._config = ConfigObj(self._config_file, encoding='utf-8')
|
||||||
for key in _CONFIG_DEFINITIONS:
|
for key in _CONFIG_DEFINITIONS:
|
||||||
self.check_setting(key)
|
self.check_setting(key)
|
||||||
|
if not is_import:
|
||||||
self._upgrade()
|
self._upgrade()
|
||||||
self._blacklist()
|
self._blacklist()
|
||||||
|
|
||||||
|
@ -337,6 +388,16 @@ class Config(object):
|
||||||
self._config[section][ini_key] = definition_type(value)
|
self._config[section][ini_key] = definition_type(value)
|
||||||
return self._config[section][ini_key]
|
return self._config[section][ini_key]
|
||||||
|
|
||||||
|
def __delattr__(self, name):
|
||||||
|
"""
|
||||||
|
Deletes a key from the configuration object.
|
||||||
|
"""
|
||||||
|
if not re.match(r'[A-Z_]+$', name):
|
||||||
|
return super(Config, self).__delattr__(name)
|
||||||
|
else:
|
||||||
|
key, definition_type, section, ini_key, default = self._define(name)
|
||||||
|
del self._config[section][ini_key]
|
||||||
|
|
||||||
def process_kwargs(self, kwargs):
|
def process_kwargs(self, kwargs):
|
||||||
"""
|
"""
|
||||||
Given a big bunch of key value pairs, apply them to the ini.
|
Given a big bunch of key value pairs, apply them to the ini.
|
||||||
|
|
|
@ -3832,6 +3832,57 @@ class WebInterface(object):
|
||||||
else:
|
else:
|
||||||
return {'result': 'error', 'message': 'App not recognized for import'}
|
return {'result': 'error', 'message': 'App not recognized for import'}
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
@cherrypy.tools.json_out()
|
||||||
|
@requireAuth(member_of("admin"))
|
||||||
|
@addtoapi()
|
||||||
|
def import_config(self, config_file=None, config_path=None, backup=False, **kwargs):
|
||||||
|
""" Import a Tautulli config file.
|
||||||
|
|
||||||
|
```
|
||||||
|
Required parameters:
|
||||||
|
config_file (file): The config file to import (multipart/form-data)
|
||||||
|
or
|
||||||
|
config_path (str): The full path to the config file to import
|
||||||
|
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
backup (bool): true or false whether to backup
|
||||||
|
the current config before importing
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
json:
|
||||||
|
{"result": "success",
|
||||||
|
"message": "Config import has started. Check the logs to monitor any problems. "
|
||||||
|
"Tautulli will restart automatically."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
if database.IS_IMPORTING:
|
||||||
|
return {'result': 'error',
|
||||||
|
'message': 'Database import is in progress. Please wait until it is finished to import a config.'}
|
||||||
|
|
||||||
|
if config_file:
|
||||||
|
config_path = os.path.join(plexpy.CONFIG.CACHE_DIR, config_file.filename + '.import.ini')
|
||||||
|
logger.info("Received config file '%s' for import. Saving to cache '%s'.",
|
||||||
|
config_file.filename, config_path)
|
||||||
|
with open(config_path, 'wb') as f:
|
||||||
|
while True:
|
||||||
|
data = config_file.file.read(8192)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
f.write(data)
|
||||||
|
|
||||||
|
if not config_path:
|
||||||
|
return {'result': 'error', 'message': 'No config specified for import'}
|
||||||
|
|
||||||
|
threading.Thread(target=config.import_tautulli_config,
|
||||||
|
kwargs={'config': config_path,
|
||||||
|
'backup': helpers.bool_true(backup)}).start()
|
||||||
|
return {'result': 'success',
|
||||||
|
'message': 'Config import has started. Check the logs to monitor any problems. '
|
||||||
|
'Tautulli will restart automatically.'}
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@requireAuth(member_of("admin"))
|
@requireAuth(member_of("admin"))
|
||||||
def import_database_tool(self, app=None, **kwargs):
|
def import_database_tool(self, app=None, **kwargs):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue