From 19a656c88bd2708a7fc3e94031570d3444c82ad8 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 21 Jun 2022 01:53:07 +0100 Subject: [PATCH] If bridge_master.py is killed with HUP: write config and bridge state to disk. If, when started again, state files are less that 25 seconds old load these instead of parsing freedmr.cfg and rules.py This means, it's possible to effect a seamless restart, without causing systems to have to re-login. --- FreeDMR-SAMPLE-commented.cfg | 8 ++++- bridge_master.py | 58 ++++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/FreeDMR-SAMPLE-commented.cfg b/FreeDMR-SAMPLE-commented.cfg index 7863033..ed9f224 100755 --- a/FreeDMR-SAMPLE-commented.cfg +++ b/FreeDMR-SAMPLE-commented.cfg @@ -4,7 +4,13 @@ # - how often the Master maintenance loop runs # MAX_MISSED - how many pings are missed before we give up and re-register # - number of times the master maintenance loop runs before de-registering a peer +# You should not need to change this from the default. # +# GEN_STAT_BRIDGES - Generate static bridges to forward traffic to other connected servers. +# Generally this should be left True, unless you are building a hidden server +# Which does not participate in the mesh network +# +# ALLOW_NULL_PASSPHRASE # ACLs: # # Access Control Lists are a very powerful tool for administering your system. @@ -45,7 +51,7 @@ REG_ACL: PERMIT:ALL SUB_ACL: DENY:1 TGID_TS1_ACL: PERMIT:ALL TGID_TS2_ACL: PERMIT:ALL -GEN_STAT_BRIDGES: False +GEN_STAT_BRIDGES: True ALLOW_NULL_PASSPHRASE: True ANNOUNCEMENT_LANGUAGES: SERVER_ID: 0000 diff --git a/bridge_master.py b/bridge_master.py index 96eca58..20beb0e 100644 --- a/bridge_master.py +++ b/bridge_master.py @@ -409,6 +409,24 @@ def subMapWrite(): except: logger.warning('(SUBSCRIBER) Cannot write SUB_MAP to file') +def configPickle(): + try: + _fh = open('config.pkl','wb') + pickle.dump(CONFIG,_fh) + _fh.close() + logger.info('(GLOBAL) Writing CONFIG to disk') + except: + logger.warning('(GLOBAL) Cannot write config.pkl') + +def bridgePickle(): + try: + _fh = open('bridge.pkl','wb') + pickle.dump(BRIDGES,_fh) + _fh.close() + logger.info('(GLOBAL) Writing BRIDGES to disk') + except: + logger.warning('(GLOBAL) Cannot write bridge.pkl') + #Subscriber Map trimmer loop def SubMapTrimmer(): logger.debug('(SUBSCRIBER) Subscriber Map trimmer loop started') @@ -2828,8 +2846,20 @@ if __name__ == '__main__': if not cli_args.CONFIG_FILE: cli_args.CONFIG_FILE = os.path.dirname(os.path.abspath(__file__))+'/hblink.cfg' - # Call the external routine to build the configuration dictionary - CONFIG = config.build_config(cli_args.CONFIG_FILE) + file_exists = os.path.isfile('config.pkl') == True + if file_exists: + if os.path.getmtime('config.pkl') > (time() - 25): + try: + with open('config.pkl','rb') as _fh: + CONFIG = pickle.load(_fh) + print('(CONFIG) loaded config .pkl from previous shutdown') + except: + print('(CONFIG) Cannot load config.pkl file') + CONFIG = config.build_config(cli_args.CONFIG_FILE) + else: + os.unlink("config.pkl") + else: + CONFIG = config.build_config(cli_args.CONFIG_FILE) # Ensure we have a path for the rules file, if one wasn't specified, then use the default (top of file) if not cli_args.RULES_FILE: @@ -2883,9 +2913,13 @@ if __name__ == '__main__': reactor.stop() if CONFIG['ALIASES']['SUB_MAP_FILE']: subMapWrite() + if _signal == signal.SIGHUP: + configPickle() + bridgePickle() + # Set signal handers so that we can gracefully exit if need be - for sig in [signal.SIGINT, signal.SIGTERM]: + for sig in [signal.SIGINT, signal.SIGTERM, signal.SIGHUP]: signal.signal(sig, sig_handler) # Create the name-number mapping dictionaries @@ -2911,8 +2945,22 @@ if __name__ == '__main__': except (ImportError, FileNotFoundError): sys.exit('(ROUTER) TERMINATING: Routing bridges file not found or invalid: {}'.format(cli_args.RULES_FILE)) - # Build the routing rules file - BRIDGES = make_bridges(rules_module.BRIDGES) + #Load pickle of bridges if it's less than 25 seconds old + if os.path.isfile('bridge.pkl'): + if os.path.getmtime('config.pkl') > (time() - 25): + try: + with open('bridge.pkl','rb') as _fh: + BRIDGES = pickle.load(_fh) + logger.info('(BRIDGE) loaded bridge.pkl from previous shutdown') + except: + logger.warning('(BRIDGE) Cannot load bridge.pkl file') + BRIDGES = make_bridges(rules_module.BRIDGES) + else: + BRIDGES = make_bridges(rules_module.BRIDGES) + os.unlink("bridge.pkl") + else: + BRIDGES = make_bridges(rules_module.BRIDGES) + #Subscriber map for unit calls - complete with test entry #SUB_MAP = {bytes_3(73578):('REP-1',1,time())}