linspector/bin/lish

172 lines
7.1 KiB
Python
Executable file

#!/usr/bin/python3 -d
"""
This file is part of Linspector (https://linspector.org/)
Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE (MIT license).
"""
# TODO: Make use of the "rich" library to for rich text and beautiful formatting in the terminal.
import argparse
# TODO: Remove logging in the client and barf output to the terminal directly in Lish. Implement a
# verbose mode for this to suppress messages by default but create something like log levels which
# can be enabled at program start.
import logging
import logging.handlers
import os
import sys
from linspector.configuration import Configuration
from linspector.environment import Environment
from linspector.linspector import Linspector
from linspector.monitors import Monitors
logger = logging.getLogger('linspector')
# i currently only increase the 3rd number because the goal is that 0.19.* will become the first
# stable version.
__version__ = '0.0.1.dev1'
__author__ = 'Johannes Findeisen <you@hanez.org>'
# TODO: Replace all the code below! For now this is just a copy of Linspector code which makes no
# sense for a Shell style client. Best would be if Lish will become a 100% standalone program
# without making use of the daemon code and the it maybe makes sense to make an own project for
# this. This also applies to the litui client but Lish and Litui can share the same backend.
def parse_args():
parser = argparse.ArgumentParser(
description='lish is part of the linspector project and is a shell style client for '
'connecting to a linspector instance configured to load the rpc plugin for '
'remote connections.',
epilog='author: ' + __author__,
prog='lish')
parser.add_argument('host', metavar='HOST',
help='the configuration path to use')
parser.add_argument('-V', '--verbose', default=False, dest='verbose', action='store_true',
help='log in debug mode')
parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + str(__version__))
return parser.parse_args()
def main():
args = parse_args()
environment = Environment()
monitors = None
notifications = {}
plugins = {}
# the scheduler is a dict to make it possible in the future to run more than one scheduler in
# one linspector instance. need to think about it a little more...
scheduler = {}
services = {}
tasks = {}
if args.stdout:
if args.verbose:
logger.setLevel(logging.DEBUG)
else:
# setting pre initialization default log level to INFO. this changes after
# initialization of the configuration. maybe there are better solutions...?
logger.setLevel(logging.INFO)
stdout_formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s')
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setFormatter(stdout_formatter)
logger.addHandler(stdout_handler)
try:
configuration = Configuration(args.configuration_path, environment, log)
logger.debug('configuration dump: ' + configuration.dump_to_ini())
except Exception as err:
log('critical', '[linspector] configuration error: {0}'.format(err))
sys.exit(1)
if configuration.get_option('linspector', 'log_file'):
log_file = os.path.expanduser(configuration.get_option('linspector', 'log_file'))
if not os.path.exists(os.path.dirname(log_file)):
os.makedirs(os.path.dirname(log_file))
log_file_formatter = \
logging.Formatter('[%(asctime)s]:[%(levelname)s]:[%(name)s]:%(message)s')
if configuration.get_option('linspector', 'log_file_size'):
log_file_size_mb = int(configuration.get_option('linspector', 'log_file_size'))
log_file_size_bytes = int(log_file_size_mb * 1000000)
elif configuration.get_option('linspector', 'log_file_size_bytes'):
log_file_size_bytes = int(configuration.get_option('linspector',
'log_file_size_bytes'))
else:
# default log file size is 10000000 bytes (10MiB)
log_file_size_bytes = int(10000000)
if configuration.get_option('linspector', 'log_file_count'):
log_file_count = int(configuration.get_option('linspector', 'log_file_count'))
else:
# default log file count is 1.
log_file_count = 1
log_file_handler = logging.handlers.RotatingFileHandler(log_file,
maxBytes=log_file_size_bytes,
backupCount=log_file_count)
log_file_handler.setFormatter(log_file_formatter)
logger.addHandler(log_file_handler)
log_level = 'None'
# critical errors will always show up even when no log_level is set. this is most silent.
logger.setLevel(logging.CRITICAL)
if configuration.get_option('linspector', 'log_level'):
log_level = str(configuration.get_option('linspector', 'log_level'))
if log_level == "error":
logger.setLevel(logging.ERROR)
elif log_level == "warning":
logger.setLevel(logging.WARNING)
elif log_level == "info":
logger.setLevel(logging.INFO)
elif log_level == "debug":
logger.setLevel(logging.DEBUG)
# elif configuration.get_option('linspector', 'log_level') != 'error' != 'warning' \
# != 'info' != 'debug':
# logger.warning('[linspector] log level: "' + log_level + '" not found!')
try:
monitors = Monitors(configuration, environment, log, notifications, services, tasks)
except Exception as err:
log('warning', '[linspector] monitor initialization error: {0}'.format(err))
try:
linspector = Linspector(configuration, environment, log, monitors, plugins, scheduler)
# linspector.print_debug()
except Exception as err:
log('critical', '[linspector] core initialization error: {0}'.format(err))
sys.exit(1)
# daemon initialization
if args.daemon:
try:
from linspector.linspectord import Linspectord
linspectord = Linspectord(configuration, environment, linspector, log)
# do handling of restart, start and stop commands but for now "start" is enough... ;)
if args.kill:
log('info', '[linspector] stopping daemon.')
linspectord.stop()
elif args.restart:
log('info', '[linspector] restarting daemon.')
linspectord.restart()
else:
log('info', '[linspector] starting daemon.')
linspectord.start()
except Exception as err:
log('critical', '[linspector] daemon error: {0}'.format(err))
sys.exit(1)
else:
try:
while True:
pass
except KeyboardInterrupt:
log('info', '[linspector] program terminated by user!')
if __name__ == '__main__':
main()