mirror of
https://github.com/Telecominfraproject/openafc_final.git
synced 2025-11-02 02:57:58 +00:00
238 lines
7.2 KiB
Python
Executable File
238 lines
7.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Copyright (C) 2021 Broadcom. All rights reserved. The term "Broadcom"
|
|
# refers solely to the Broadcom Inc. corporate affiliate that owns
|
|
# the software below. This work is licensed under the OpenAFC Project License,
|
|
# a copy of which is included with this software program
|
|
#
|
|
|
|
"""
|
|
Description
|
|
|
|
The acceptor client (aka consumer) registeres own queue within broker
|
|
application (aka rabbitmq). Such queue used as a channel for control commands.
|
|
"""
|
|
|
|
from appcfg import BrokerConfigurator, ObjstConfig
|
|
import os
|
|
import sys
|
|
from sys import stdout
|
|
import logging
|
|
from logging.config import dictConfig
|
|
import argparse
|
|
import inspect
|
|
import gevent
|
|
import subprocess
|
|
import shutil
|
|
from ncli import MsgAcceptor
|
|
from hchecks import MsghndHealthcheck, ObjstHealthcheck
|
|
from fst import DataIf
|
|
|
|
dictConfig({
|
|
'version': 1,
|
|
'disable_existing_loggers': False,
|
|
'formatters': {
|
|
'standard': {
|
|
'format': '%(asctime)s - [%(levelname)s] %(name)s [%(module)s.%(funcName)s:%(lineno)d]: %(message)s',
|
|
'datefmt': '%Y-%m-%d %H:%M:%S',
|
|
}
|
|
},
|
|
'handlers': {
|
|
'console': {
|
|
'level': 'DEBUG',
|
|
'class': 'logging.StreamHandler',
|
|
'formatter': 'standard',
|
|
}
|
|
},
|
|
'root': {
|
|
'level': 'INFO',
|
|
'handlers': ['console']
|
|
},
|
|
})
|
|
app_log = logging.getLogger()
|
|
|
|
|
|
class Configurator(dict):
|
|
__instance = None
|
|
|
|
def __new__(cls):
|
|
if cls.__instance is None:
|
|
cls.__instance = dict.__new__(cls)
|
|
return cls.__instance
|
|
|
|
def __init__(self):
|
|
dict.__init__(self)
|
|
self.update(BrokerConfigurator().__dict__.items())
|
|
self.update(ObjstConfig().__dict__.items())
|
|
self['OBJST_CERT_CLI_BUNDLE'] = \
|
|
'certificate/client.bundle.pem'
|
|
self['DISPAT_CERT_CLI_BUNDLE'] = \
|
|
'/etc/nginx/certs/client.bundle.pem'
|
|
self['DISPAT_CERT_CLI_BUNDLE_DFLT'] = \
|
|
'/etc/nginx/certs/client.bundle.pem_dflt'
|
|
|
|
|
|
log_level_map = {
|
|
'debug': logging.DEBUG, # 10
|
|
'info': logging.INFO, # 20
|
|
'warn': logging.WARNING, # 30
|
|
'err': logging.ERROR, # 40
|
|
'crit': logging.CRITICAL, # 50
|
|
}
|
|
|
|
|
|
def set_log_level(opt) -> int:
|
|
app_log.info(f"({os.getpid()}) {inspect.stack()[0][3]}() "
|
|
f"{app_log.getEffectiveLevel()}")
|
|
app_log.setLevel(log_level_map[opt])
|
|
return log_level_map[opt]
|
|
|
|
|
|
def readiness_check(cfg):
|
|
"""Provide readiness check by calling for response preconfigured
|
|
list of subjects (containers)
|
|
"""
|
|
app_log.debug(f"({os.getpid()}) {inspect.stack()[0][3]}()")
|
|
objst_chk = ObjstHealthcheck(cfg)
|
|
msghnd_chk = MsghndHealthcheck.from_hcheck_if()
|
|
checks = [gevent.spawn(objst_chk.healthcheck),
|
|
gevent.spawn(msghnd_chk.healthcheck)]
|
|
gevent.joinall(checks)
|
|
for i in checks:
|
|
if i.value != 0:
|
|
return i.value
|
|
return 0
|
|
|
|
|
|
def run_restart(cfg):
|
|
"""Get messages"""
|
|
app_log.debug(f"({os.getpid()}) {inspect.stack()[0][3]}()")
|
|
with DataIf().open(cfg['OBJST_CERT_CLI_BUNDLE']) as hfile:
|
|
if hfile.head():
|
|
app_log.debug(f"Found cert bundle file.")
|
|
with open(cfg['DISPAT_CERT_CLI_BUNDLE'], 'w') as ofile:
|
|
ofile.write(hfile.read().decode('utf-8'))
|
|
app_log.info(f"{os.path.getctime(cfg['DISPAT_CERT_CLI_BUNDLE'])}, "
|
|
f"{os.path.getsize(cfg['DISPAT_CERT_CLI_BUNDLE'])}")
|
|
else:
|
|
app_log.debug(f"({os.getpid()}) {inspect.stack()[0][3]}()")
|
|
# use default certificate (placeholder)
|
|
# in any case of missing file, no more certificates included
|
|
app_log.info(f"Misssing certificate file "
|
|
f"{cfg['OBJST_CERT_CLI_BUNDLE']}, back to default "
|
|
f"{cfg['DISPAT_CERT_CLI_BUNDLE_DFLT']}")
|
|
shutil.copy2(cfg['DISPAT_CERT_CLI_BUNDLE_DFLT'],
|
|
cfg['DISPAT_CERT_CLI_BUNDLE'])
|
|
p = subprocess.Popen("nginx -s reload",
|
|
stdout=subprocess.PIPE, shell=True)
|
|
app_log.info(f"{p.communicate()}")
|
|
|
|
|
|
def run_remove(cfg):
|
|
"""Get messages"""
|
|
app_log.debug(f"({os.getpid()}) {inspect.stack()[0][3]}() "
|
|
f"{cfg['DISPAT_CERT_CLI_BUNDLE']}")
|
|
os.unlink(cfg['DISPAT_CERT_CLI_BUNDLE'])
|
|
# restore builtin certifiicate from backup
|
|
app_log.debug(f"({os.getpid()}) {inspect.stack()[0][3]}() "
|
|
f"restore default certificate "
|
|
f"{cfg['DISPAT_CERT_CLI_BUNDLE_DFLT']}")
|
|
shutil.copy2(cfg['DISPAT_CERT_CLI_BUNDLE_DFLT'],
|
|
cfg['DISPAT_CERT_CLI_BUNDLE'])
|
|
p = subprocess.Popen("nginx -s reload",
|
|
stdout=subprocess.PIPE, shell=True)
|
|
app_log.info(f"{p.communicate()}")
|
|
|
|
|
|
commands_map = {
|
|
'cmd_restart': run_restart,
|
|
'cmd_remove': run_remove,
|
|
}
|
|
|
|
|
|
def get_commands(cfg, msg):
|
|
"""Get messages"""
|
|
app_log.debug(f"({os.getpid()}) {inspect.stack()[0][3]}()")
|
|
commands_map[msg](cfg)
|
|
|
|
|
|
def run_it(cfg):
|
|
"""Execute command line run command"""
|
|
app_log.debug(f"({os.getpid()}) {inspect.stack()[0][3]}()")
|
|
|
|
# backup builtin certifiicate as a default one
|
|
shutil.copy2(cfg['DISPAT_CERT_CLI_BUNDLE'],
|
|
cfg['DISPAT_CERT_CLI_BUNDLE_DFLT'])
|
|
# check if lucky to find new certificate bundle already
|
|
run_restart(cfg)
|
|
|
|
maker = MsgAcceptor(cfg['BROKER_URL'], cfg['BROKER_EXCH_DISPAT'],
|
|
msg_handler=get_commands, handler_params=cfg)
|
|
app_log.info(f"({os.getpid()}) Connected to {cfg['BROKER_URL']}")
|
|
maker.run()
|
|
|
|
|
|
# available commands to execute in alphabetical order
|
|
execution_map = {
|
|
'run': run_it,
|
|
'check': readiness_check,
|
|
}
|
|
|
|
|
|
def make_arg_parser():
|
|
"""Define command line options"""
|
|
args_parser = argparse.ArgumentParser(
|
|
epilog=__doc__.strip(),
|
|
formatter_class=argparse.RawTextHelpFormatter)
|
|
args_parser.add_argument('--log', type=set_log_level,
|
|
default='info', dest='log_level',
|
|
help="<info|debug|warn|err|crit> - set "
|
|
"logging level (default=info).\n")
|
|
args_parser.add_argument('--cmd', choices=execution_map.keys(),
|
|
nargs='?',
|
|
help="run - start accepting commands.\n"
|
|
"check - run readiness check.\n")
|
|
|
|
return args_parser
|
|
|
|
|
|
def prepare_args(parser, cfg):
|
|
"""Prepare required parameters"""
|
|
app_log.debug(f"{inspect.stack()[0][3]}() {parser.parse_args()}")
|
|
cfg.update(vars(parser.parse_args()))
|
|
|
|
|
|
def main():
|
|
"""Main function of the utility"""
|
|
res = 0
|
|
parser = make_arg_parser()
|
|
config = Configurator()
|
|
|
|
if prepare_args(parser, config) == 1:
|
|
# error in preparing arguments
|
|
res = 1
|
|
else:
|
|
if isinstance(config['cmd'], type(None)):
|
|
parser.print_help()
|
|
|
|
if res == 0:
|
|
app_log.debug(f"{inspect.stack()[0][3]}() {config}")
|
|
res = execution_map[config['cmd']](config)
|
|
sys.exit(res)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
main()
|
|
except KeyboardInterrupt:
|
|
sys.exit(1)
|
|
|
|
|
|
# Local Variables:
|
|
# mode: Python
|
|
# indent-tabs-mode: nil
|
|
# python-indent: 4
|
|
# End:
|
|
#
|
|
# vim: sw=4:et:tw=80:cc=+1
|