该模块对软件的配置等进行了一系列设置。
log.py
目录结构
class LogConfigurator
def __init__
def _rotating_config
def _basic_config
def add_syslog_handler
def _get_log_level
init
def __init__(self,level,logfile)
self._level=self._get_log_level(level)
self._logfile=logfile
if logfile is None:
self._basic_config()
else:
self._rotating_config()
从函数中,我们可以看到调用了_get_log_level方法,_basic方法,_rotating_config方法
def _get_log_level(self, level):
if level == 'debug':
return logging.DEBUG
elif level == 'info':
return logging.INFO
else:
return logging.WARNING
可以看出该方法的主要目的是设置logging的等级。
def _basic_config(self):
'''Log to stdout. Mainly for development.'''
kw = {
'format': '[%(asctime)s] [%(levelname)s] %(message)s',
'datefmt': '%m/%d/%Y %H:%M:%S',
'level': self._level,
'stream': sys.stdout
}
logging.basicConfig(**kw)
该方法设置基础配置,kw设置了一些列关于logging的参数
def _rotating_config(self):
'''Rotating log'''
handler = logging.handlers.TimedRotatingFileHandler(self._logfile, when='W0', interval=1)
handler.setLevel(self._level)
formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s')
handler.setFormatter(formatter)
logging.root.setLevel(self._level)
logging.root.addHandler(handler)
该方法与上面方法的区别在于通过设置handler进行logging配置。按日期进行切割
logging.handlers.TimedRotatingFileHandler:按日期对日志进行切割
def add_syslog_handler(self):
handler = logging.handlers.SysLogHandler(address='/dev/log')
handler.setLevel(self._level)
formatter = logging.Formatter('seafevents[%(process)d]: %(message)s')
handler.setFormatter(formatter)
logging.root.addHandler(handler)
该方法设置SysLogHandler。
config.py
class AppConfig(object):
def __init__(self):
pass
def set(self, key, value):
self.key = value
def get(self, key):
if hasattr(self, key):
return self.__dict__[key]
else:
return ''
配置的对象类,用于封装信息
def exception_catch(conf_module):
def func_wrapper(func):
def wrapper(*args, **kwargs):
try:
func(*args, **kwargs)
except Exception as e:
logger.info('%s module configuration loading failed: %s' % (conf_module, e))
return wrapper
return func_wrapper
该方法捕捉函数的异常并进行抓捕。
logger.info('%s module configuration loading failed: %s' % (conf_module, e))
def load_config(config_file):
# seafevent config file
appconfig.session_cls = init_db_session_class(config_file)
config = get_config(config_file)
load_env_config()
appconfig.seaf_session_cls = init_db_session_class(appconfig.seaf_conf_path, db = 'seafile')
load_publish_config(config)
load_statistics_config(config)
load_file_history_config(config)
load_collab_server_config(config)
该方法加载配置。init_db_session_class方法在db文件中定义,我们在之前已经介绍过。
load_env_config()
load_publish_config(config)
load_statistics_config(config)
load_file_history_config(config)
load_collab_server_config(config)
这里调用的函数是该文件剩余的函数,可以看出是从不同的类型加载配置。
def load_env_config():
# get central config dir
appconfig.central_confdir = ""
if 'SEAFILE_CENTRAL_CONF_DIR' in os.environ:
appconfig.central_confdir = os.environ['SEAFILE_CENTRAL_CONF_DIR']
# get seafile config path
appconfig.seaf_conf_path = ""
if appconfig.central_confdir:
appconfig.seaf_conf_path = os.path.join(appconfig.central_confdir, 'seafile.conf')
elif 'SEAFILE_CONF_DIR' in os.environ:
appconfig.seaf_conf_path = os.path.join(os.environ['SEAFILE_CONF_DIR'], 'seafile.conf')
# get ccnet config path
appconfig.ccnet_conf_path = ""
if appconfig.central_confdir:
appconfig.ccnet_conf_path = os.path.join(appconfig.central_confdir, 'ccnet.conf')
elif 'CCNET_CONF_DIR' in os.environ:
appconfig.ccnet_conf_path = os.path.join(os.environ['CCNET_CONF_DIR'], 'ccnet.conf')
分别对seafile的central config dir,conf_path,ccnet_conf_path进行配置,基本逻辑为,通过os.environ查看是否系统是否有配置,然后分情况进行设置。
def load_publish_config(config):
appconfig.publish_enabled = False
try:
appconfig.publish_enabled = config.getboolean('EVENTS PUBLISH', 'enabled')
except Exception as e:
# prevent hasn't EVENTS PUBLISH section.
pass
if appconfig.publish_enabled:
try:
appconfig.publish_mq_type = config.get('EVENTS PUBLISH', 'mq_type').upper()
if appconfig.publish_mq_type != 'REDIS':
logger.error("Unknown database backend: %s" % config['publish_mq_type'])
raise RuntimeError("Unknown database backend: %s" % config['publish_mq_type'])
appconfig.publish_mq_server = config.get(appconfig.publish_mq_type,
'server')
appconfig.publish_mq_port = config.getint(appconfig.publish_mq_type,
'port')
# prevent needn't password
appconfig.publish_mq_password = ""
if config.has_option(appconfig.publish_mq_type, 'password'):
appconfig.publish_mq_password = config.get(appconfig.publish_mq_type,
'password')
except Exception as e:
appconfig.publish_enabled = False
该方法配置publish版,会先检查config中的publish_enabled的配置,然后进行配置,同时设置数据库类型,server和port还有密码
if config.has_option(appconfig.publish_mq_type, 'password'):
appconfig.publish_mq_password = config.get(appconfig.publish_mq_type,
'password')
def load_statistics_config(config):
appconfig.enable_statistics = False
try:
if config.has_option('STATISTICS', 'enabled'):
appconfig.enable_statistics = config.getboolean('STATISTICS', 'enabled')
except Exception as e:
logger.info(e)
该函数比较直观,根据config中的STATISTICS对enabled进行设置
def load_file_history_config(config):
appconfig.fh = AppConfig()
if config.has_option('FILE HISTORY', 'enabled'):
appconfig.fh.enabled = config.getboolean('FILE HISTORY', 'enabled')
if appconfig.fh.enabled:
appconfig.fh.threshold = int(get_opt_from_conf_or_env(config, 'FILE HISTORY', 'threshold', default=5))
default_suffix = 'md,txt,doc,docx,xls,xlsx,ppt,pptx'
appconfig.fh.suffix = get_opt_from_conf_or_env(config, 'FILE HISTORY', 'suffix', default=default_suffix)
suffix = appconfig.fh.suffix.strip(',')
appconfig.fh.suffix_list = suffix.split(',') if suffix else []
logger.info('The file with the following suffix will be recorded into the file history: %s' % suffix)
else:
logger.info('Disable File History Features.')
else:
appconfig.fh.enabled = True
appconfig.fh.threshold = 5
suffix = 'md,txt,doc,docx,xls,xlsx,ppt,pptx'
appconfig.fh.suffix_list = suffix.split(',')
logger.info('The file with the following suffix will be recorded into the file history: %s' % suffix)
配置FILE HISTORY 关于enabled属性的配置。
配置一系列属性。
def load_collab_server_config(config):
appconfig.enable_collab_server = False
if not config.has_option('COLLAB_SERVER', 'enabled'):
return
appconfig.enable_collab_server = config.getboolean('COLLAB_SERVER', 'enabled')
if appconfig.enable_collab_server:
appconfig.collab_server = config.get('COLLAB_SERVER', 'server_url')
appconfig.collab_key = config.get('COLLAB_SERVER', 'key')
配置collab_server
上面的配置大多数是根据enabled属性进行配置。
signal_hangler.py
该文件非常简单
def sigint_handler(*args):
dummy = args
do_exit(0)
def sigchild_handler(*args):
dummy = args
try:
os.wait3(os.WNOHANG)
except:
pass
do_exit为util下的方法
def do_exit(code=0):
logging.info('exit with code %s', code)
# os._exit: Exit the process with status n, without calling cleanup handlers, flushing stdio buffers, etc
# sys.exit: This is implemented by raising the SystemExit exception. So only kill the current thread.
# we need to make sure that the process exits.
os._exit(code)
mq_handler.py
class MessageHandler
def add_handler:添加事件和处理函数到handler中
def handle_message:对于func中的函数,进行执行
def get_channels:得到handler中的msg
def add_handler(self, msg_type, func):
if msg_type in self._handlers:
funcs = self._handlers[msg_type]
else:
funcs = []
self._handlers[msg_type] = funcs
if func not in funcs:
funcs.append(func)
def handle_message(self, session, channel, msg):
pos = msg['content'].find('\t')
if pos == -1:
logger.warning("invalid message format: %s", msg)
return
msg_type = channel + ':' + msg['content'][:pos]
if msg_type not in self._handlers:
return
funcs = self._handlers.get(msg_type)
for func in funcs:
try:
func(session, msg)
except Exception as e:
logger.exception("error when handle msg: %s", e)
def get_channels(self):
channels = set()
for msg_type in self._handlers:
pos = msg_type.find(':')
channels.add(msg_type[:pos])
return channels
class EventsHander:
def handle_event:进行事件处理
def start:对于channel中的事件进行处理
App.py:app主类,进行一系列设置
BackgroundTasks的start方法进行一系列功能的启动
logging.info('Starting background tasks.')
self._file_updates_sender.start()
if self._work_weixin_notice_sender.is_enabled():
self._work_weixin_notice_sender.start()
else:
logging.info('work weixin notice sender is disabled')
if self._index_updater.is_enabled():
self._index_updater.start()
else:
logging.info('search indexer is disabled')
if self._seahub_email_sender.is_enabled():
self._seahub_email_sender.start()
else:
logging.info('seahub email sender is disabled')
if self._ldap_syncer.enable_sync():
self._ldap_syncer.start()
else:
logging.info('ldap sync is disabled')
if self._virus_scanner.is_enabled():
self._virus_scanner.start()
else:
logging.info('virus scan is disabled')
if self._statistics.is_enabled():
self._statistics.start()
else:
logging.info('data statistics is disabled')
if self._content_scanner.is_enabled():
self._content_scanner.start()
else:
logging.info('content scan is disabled')
if self._office_converter and self._office_converter.is_enabled():
self._office_converter.start()
else:
logging.info('office converter is disabled')
if self._repo_old_file_auto_del_scanner.is_enabled():
self._repo_old_file_auto_del_scanner.start()
else:
logging.info('repo old file auto del scanner disabled')
if self._offline_downloader.is_enabled():
self._offline_downloader.start()
else:
logging.info('offline downloader disabled')
App类则启动一系列主要功能
def __init__(self, args, events_handler_enabled=True, background_tasks_enabled=True):
self._central_config_dir = os.environ.get('SEAFILE_CENTRAL_CONF_DIR')
self._args = args
self._events_handler_enabled = events_handler_enabled
self._bg_tasks_enabled = background_tasks_enabled
try:
load_config(args.config_file)
except Exception as e:
logging.error('Error loading seafevents config. Detail: %s' % e)
raise RuntimeError("Error loading seafevents config. Detail: %s" % e)
self._events_handler = None
if self._events_handler_enabled:
self._events_handler = EventsHandler(self._args.config_file)
if appconfig.publish_enabled:
events_publisher.init()
else:
logging.info("Events publish to redis is disabled.")
self._bg_tasks = None
if self._bg_tasks_enabled:
self._bg_tasks = BackgroundTasks(args.config_file)
if appconfig.enable_statistics:
self.update_login_record_task = CountUserActivity()
self.count_traffic_task = CountTrafficInfo()
def serve_forever(self):
if self._events_handler:
self._events_handler.start()
else:
logging.info("Event listener is disabled.")
if self._bg_tasks:
self._bg_tasks.start()
else:
logging.info("Background task is disabled.")
if appconfig.enable_statistics:
self.update_login_record_task.start()
self.count_traffic_task.start()
else:
logging.info("User login statistics is disabled.")
logging.info("Traffic statistics is disabled.")
该模块主要定义了配置文件的处理与系统各种功能的启动与检查。
|