def test_database_callbacks(self): """Test database callback routines""" sf = io.StringIO(general_config) database.init(sf) rval = None def test_cb(key, val, udata): # Use a closure for our callback nonlocal rval rval = (key, val) database.callback_add("test", "PITCH", test_cb, None) database.write("PITCH", -11.4) self.assertEqual(rval, ("PITCH", (-11.4, False, False, False, False, False))) database.write("PITCH", 10.2) self.assertEqual(rval, ("PITCH", (10.2, False, False, False, False, False))) i = database.get_raw_item("PITCH") i.fail = True self.assertEqual(rval, ("PITCH", (10.2, False, False, False, True, False))) i.annunciate = True self.assertEqual(rval, ("PITCH", (10.2, True, False, False, True, False))) i.bad = True self.assertEqual(rval, ("PITCH", (10.2, True, False, True, True, False))) time.sleep(0.250) database.update() # force the update self.assertEqual(rval, ("PITCH", (10.2, True, True, True, True, False)))
def test_subscription(self): self.sock.sendall("@sALT\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@sALT\n") database.write("ALT", 3000) res = self.sock.recv(1024).decode() self.assertEqual(res, "ALT;3000.0;00000\n")
def test_aux_subscription(self): self.sock.sendall("@sOILP1\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@sOILP1\n") database.write("OILP1.lowWarn", 12.5) res = self.sock.recv(1024).decode() self.assertEqual(res, "OILP1.lowWarn;12.5\n")
def test_quality_bits(self): """Test quality bits""" sf = io.StringIO(general_config) database.init(sf) i = database.get_raw_item("OILP1") database.write("OILP1", 15.4) x = database.read("OILP1") self.assertEqual(x, (15.4, False, False, False, False, False)) i.annunciate = True x = database.read("OILP1") self.assertEqual(x, (15.4, True, False, False, False, False)) i.annunciate = False x = database.read("OILP1") self.assertEqual(x, (15.4, False, False, False, False, False)) i.fail = True x = database.read("OILP1") self.assertEqual(x, (15.4, False, False, False, True, False)) i.fail = False x = database.read("OILP1") self.assertEqual(x, (15.4, False, False, False, False, False)) i.bad = True x = database.read("OILP1") self.assertEqual(x, (15.4, False, False, True, False, False)) i.bad = False x = database.read("OILP1") self.assertEqual(x, (15.4, False, False, False, False, False))
def test_string_datatype(self): """test writing a string to an item""" sf = io.StringIO(general_config) database.init(sf) database.write("DUMMY", "test string") x = database.read("DUMMY") self.assertEqual(x[0], "test string")
def test_wrong_datatype(self): """test using wrong datatype for item""" sf = io.StringIO(general_config) database.init(sf) database.write("DUMMY", 1234) x = database.read("DUMMY") self.assertEqual(x[0], "1234") database.write("PITCH", "23.4") x = database.read("PITCH") self.assertEqual(x[0], 23.4)
def test_similar_aux_items(self): """it would be easy for a single aux array to be pointed to by different database items.""" sf = io.StringIO(variable_config) database.init(sf) database.write("EGT11.Max", 700) database.write("EGT12.Max", 800) x = database.read("EGT11.Max") y = database.read("EGT12.Max") self.assertNotEqual(y, x)
def test_database_aux_data_bounds(self): """Test database aux data bounds checking""" sf = io.StringIO(general_config) database.init(sf) tests = [(0.0, 0.0), (-180.0, -180.0), (-180.1, -180.0), (0.0, 0, 0), (180.0, 180.0), (180.1, 180.0)] for test in tests: database.write("AOA.Warn", test[0]) x = database.read("AOA.Warn") self.assertEqual(x, test[1])
def test_timeout_lifetime(self): """Test item timeout lifetime""" sf = io.StringIO(general_config) database.init(sf) database.write("PITCH", -11.4) x = database.read("PITCH") self.assertEqual(x, (-11.4, False, False, False, False, False)) time.sleep(0.250) x = database.read("PITCH") self.assertEqual(x, (-11.4, False, True, False, False, False)) database.write("PITCH", -11.4) x = database.read("PITCH") self.assertEqual(x, (-11.4, False, False, False, False, False))
def test_value_write_with_subscription(self): """Make sure we don't get a response to a value write on our subscriptions""" self.sock.sendall("@sALT\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@sALT\n") self.sock.sendall("@sIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@sIAS\n") # writing both from database should give subscription returns database.write("IAS", 135.4) database.write("ALT", 4300) res = self.sock.recv(1024).decode() self.assertEqual(res, "IAS;135.4;00000\nALT;4300.0;00000\n") # writing over the socket should not create a callback self.sock.sendall("@wALT;3200\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@wALT;3200.0;00000\n") database.write("IAS", 132.4) res = self.sock.recv(1024).decode() # we should only get the IAS one self.assertEqual(res, "IAS;132.4;00000\n") # using a normal write should do the same self.sock.sendall("ALT;3400;000\n".encode()) database.write("IAS", 136.4) res = self.sock.recv(1024).decode() self.assertEqual(res, "IAS;136.4;00000\n")
def test_multiple_subscription_fail(self): """Test that we receive an error if we try to subscribe to the same point again""" self.sock.sendall("@sALT\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@sALT\n") database.write("ALT", 3100) res = self.sock.recv(1024).decode() self.assertEqual(res, "ALT;3100.0;00000\n") self.sock.sendall("@sALT\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@sALT!002\n")
def test_database_aux_data_bounds(self): """Test database aux data bounds checking""" sf = io.StringIO(general_config) database.init(sf) tests = [(0.0, 0.0), (-180.0, -180.0), (-180.1, -180.0), (0.0, 0,0), (180.0, 180.0), (180.1, 180.0)] for test in tests: database.write("AOA.Warn", test[0]) x = database.read("AOA.Warn") self.assertEqual(x, test[1])
def test_aux_data_read_write(self): """Test database auxillary data reading and writing""" sf = io.StringIO(general_config) database.init(sf) tests = [("Min", -160.0), ("Max", -130.0), ("0g", 10.0), ("Warn", 23.4), ("Stall", 45.6)] for test in tests: x = database.write("AOA." + test[0], test[1]) x = database.read("AOA." + test[0]) self.assertEqual(x, test[1])
def test_read(self): database.write("IAS", 105.4) self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;00000\n") i = database.get_raw_item("IAS") i.annunciate = True self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;10000\n") i.bad = True self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;10100\n") i.fail = True self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;10110\n") i.secfail = True self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;10111\n") i.annunciate = False self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;00111\n") i.bad = False self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;00011\n") i.fail = False self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;00001\n") i.secfail = False self.sock.sendall("@rIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rIAS;105.4;00000\n")
def test_unsubscribe(self): self.sock.sendall("@sIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@sIAS\n") self.sock.sendall("@sALT\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@sALT\n") database.write("IAS", 120.0) database.write("ALT", 3100) res = self.sock.recv(1024).decode() self.assertEqual(res, "IAS;120.0;00000\nALT;3100.0;00000\n") self.sock.sendall("@uIAS\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@uIAS\n") database.write("IAS", 125.0) database.write("ALT", 3200) res = self.sock.recv(1024).decode() self.assertEqual(res, "ALT;3200.0;00000\n")
def main_setup(): global config_path global log # Look for our configuration file in the list of directories for directory in path_options: # store the first match that we find d = directory.format(USER=user_home, PREFIX=prefix_path) if os.path.isfile("{}/{}".format(d, config_filename)): config_path = d break config_file = "{}/{}".format(config_path, config_filename) parser = argparse.ArgumentParser(description='FIX Gateway') parser.add_argument('--debug', '-d', action='store_true', help='Run in debug mode') parser.add_argument('--verbose', '-v', action='store_true', help='Run in verbose mode') parser.add_argument('--daemonize', '-D', action='store_true', help='Run program in the background') parser.add_argument('--config-file', type=argparse.FileType('r'), help='Alternate configuration file') parser.add_argument('--log-config', type=argparse.FileType('r'), help='Alternate logger configuration file') args, unknown_args = parser.parse_known_args() # if we passed in a configuration file on the command line... if args.config_file: cf = args.config_file config_file = cf.name elif config_path is not None: # otherwise use the default cf = open(config_file) else: # If all else fails copy the configuration from the package # to ~/.makerplane/fixgw/config create_config_dir("{USER}/.makerplane/fixgw".format(USER=user_home)) # Reset this stuff like we found it config_file = "{USER}/.makerplane/fixgw/config/{FILE}".format( USER=user_home, FILE=config_filename) cf = open(config_file) config_path = os.path.dirname(cf.name) config = yaml.safe_load(cf) # Either load the config file given as a command line argument or # look in the configuration for the logging object if args.log_config: logging.config.fileConfig(args.log_config) elif 'logging' in config: logging.config.dictConfig(config['logging']) else: logging.basicConfig() log = logging.getLogger("fixgw") if args.verbose: log.setLevel(logging.INFO) if args.debug: log.setLevel(logging.DEBUG) log.info("Starting FIX Gateway") log.info("Configuration Found at {}".format(config_file)) # Open database definition file and send to database initialization try: ddfile = config["database file"].format(CONFIG=config_path) f = open(ddfile, 'r') except: log.critical("Unable to open database definition file - " + ddfile) raise try: database.init(f) except Exception as e: log.error("Database failure, Exiting:" + str(e)) raise if "initialization files" in config and config["initialization files"]: ifiles = config["initialization files"] for fn in ifiles: filename = fn.format(CONFIG=config_path) log.info("Setting Initial Values - {}".format(filename)) try: f = open(filename, 'r') for line in f.readlines(): l = line.strip() if l and l[0] != '#': x = l.split("=") if len(x) >= 2: database.write(x[0].strip(), x[1].strip()) except Exception as e: log.error( "Problem setting initial values from configuration - {0}". format(e)) raise # TODO: Need to do some more thorough error checking here # run through the plugin_list dict and find all the plugins that are # configured to be loaded and load them. for each in config['connections']: if config['connections'][each]['load']: module = config['connections'][each]["module"] try: load_plugin(each, module, config['connections'][each]) except Exception as e: logging.critical("Unable to load module - " + module + ": " + str(e)) if args.debug: raise ss = {"Configuration File": config_file, "Configuration Path": config_path} status.initialize(plugins, ss) if not args.daemonize: signal.signal(signal.SIGINT, sig_int_handler) signal.signal(signal.SIGTERM, sig_int_handler) return args
def test_compute_average(self): database.write("EGT11", 300) database.write("EGT12", 320) database.write("EGT13", 340) database.write("EGT14", 360) x = database.read("EGTAVG1") self.assertEqual(x, (330, False, False, False, False, False)) database.write("EGT13", (340, False, True, False, False)) x = database.read("EGTAVG1") self.assertEqual(x, (330, False, False, True, False, False)) database.write("EGT13", (340, False, False, True, False)) x = database.read("EGTAVG1") self.assertEqual(x, (0, False, False, False, True, False)) database.write("EGT13", (340, False, False, False, True)) x = database.read("EGTAVG1") self.assertEqual(x, (330, False, False, False, False, True))
def test_bool_write(self): """test using wrong datatype for item""" sf = io.StringIO(general_config) database.init(sf) # Test actual booleans database.write("BTN1", True) x = database.read("BTN1") self.assertEqual(x[0], True) database.write("BTN1", False) x = database.read("BTN1") self.assertEqual(x[0], False) # Test strings database.write("BTN1", "True") x = database.read("BTN1") self.assertEqual(x[0], True) database.write("BTN1", "False") x = database.read("BTN1") self.assertEqual(x[0], False) database.write("BTN1", "1") x = database.read("BTN1") self.assertEqual(x[0], True) database.write("BTN1", "0") x = database.read("BTN1") self.assertEqual(x[0], False) database.write("BTN1", "Yes") x = database.read("BTN1") self.assertEqual(x[0], True) database.write("BTN1", "No") x = database.read("BTN1") self.assertEqual(x[0], False) # Test integers database.write("BTN1", 1) x = database.read("BTN1") self.assertEqual(x[0], True) database.write("BTN1", 0) x = database.read("BTN1") self.assertEqual(x[0], False)
def test_compute_span(self): database.write("EGT11", 300) database.write("EGT12", 320) database.write("EGT13", 340) database.write("EGT14", 360) x = database.read("EGTSPAN1") self.assertEqual(x, (60, False, False, False, False, False)) database.write("EGT13", (340, False, True, False, False)) x = database.read("EGTSPAN1") self.assertEqual(x, (60, False, False, True, False, False)) database.write("EGT13", (340, False, False, True, False)) x = database.read("EGTSPAN1") self.assertEqual(x, (0, False, False, False, True, False)) database.write("EGT13", (340, False, False, False, True)) x = database.read("EGTSPAN1") self.assertEqual(x, (60, False, False, False, False, True))
def test_compute_max(self): database.write("CHT11", 300) database.write("CHT12", 320) database.write("CHT13", 340) database.write("CHT14", 360) x = database.read("CHTMAX1") self.assertEqual(x, (360, False, False, False, False, False)) database.write("CHT11", 370) x = database.read("CHTMAX1") self.assertEqual(x, (370, False, False, False, False, False)) database.write("CHT12", 380) x = database.read("CHTMAX1") self.assertEqual(x, (380, False, False, False, False, False)) database.write("CHT13", 390) x = database.read("CHTMAX1") self.assertEqual(x, (390, False, False, False, False, False)) database.write("CHT13", (340, False, True, False, False)) x = database.read("CHTMAX1") self.assertEqual(x, (380, False, False, True, False, False)) database.write("CHT13", (340, False, False, True, False)) x = database.read("CHTMAX1") self.assertEqual(x, (0, False, False, False, True, False)) database.write("CHT13", (340, False, False, False, True)) x = database.read("CHTMAX1") self.assertEqual(x, (380, False, False, False, False, True))
def test_compute_min(self): database.write("CHT11", 300) database.write("CHT12", 320) database.write("CHT13", 340) database.write("CHT14", 360) x = database.read("CHTMIN1") self.assertEqual(x, (300, False, False, False, False, False)) database.write("CHT11", 295) x = database.read("CHTMIN1") self.assertEqual(x, (295, False, False, False, False, False)) database.write("CHT12", 290) x = database.read("CHTMIN1") self.assertEqual(x, (290, False, False, False, False, False)) database.write("CHT13", 280) x = database.read("CHTMIN1") self.assertEqual(x, (280, False, False, False, False, False)) database.write("CHT13", (280, False, True, False, False)) x = database.read("CHTMIN1") self.assertEqual(x, (280, False, False, True, False, False)) database.write("CHT13", (280, False, False, True, False)) x = database.read("CHTMIN1") self.assertEqual(x, (0, False, False, False, True, False)) database.write("CHT13", (280, False, False, False, True)) x = database.read("CHTMIN1") self.assertEqual(x, (280, False, False, False, False, True))
def test_compute_sum(self): database.write("FUELQ1", 10) database.write("FUELQ2", 10) x = database.read("FUELQT") self.assertEqual(x, (20, False, False, False, False, False)) database.write("FUELQ1", 10) database.write("FUELQ2", 0) x = database.read("FUELQT") self.assertEqual(x, (10, False, False, False, False, False)) database.write("FUELQ1", 0) database.write("FUELQ2", 15) x = database.read("FUELQT") self.assertEqual(x, (15, False, False, False, False, False)) database.write("FUELQ1", (10, False, True, False, False)) x = database.read("FUELQT") self.assertEqual(x, (25, False, False, True, False, False)) database.write("FUELQ1", (10, False, False, True, False)) x = database.read("FUELQT") self.assertEqual(x, (0, False, False, False, True, False)) database.write("FUELQ1", (10, False, False, False, True)) x = database.read("FUELQT") self.assertEqual(x, (25, False, False, False, False, True))
def test_unowned_outputs(self): database.write("BARO", 30.04) msg = self.bus.recv(1.0) self.assertEqual(msg.arbitration_id, self.node + 1760) self.assertEqual(msg.data, bytearray([12, 0x90, 0x01, 0x58, 0x75]))
def main(): global config_path # Look for our configuration file in the list of directories for directory in path_options: # store the first match that we find d = directory.format(USER=user_home, PREFIX=prefix_path) if os.path.isfile("{}/{}".format(d, config_filename)): config_path = d break config_file = "{}/{}".format(config_path, config_filename) parser = argparse.ArgumentParser(description='FIX Gateway') parser.add_argument('--debug', '-d', action='store_true', help='Run in debug mode') parser.add_argument('--verbose', '-v', action='store_true', help='Run in verbose mode') parser.add_argument('--config-file', type=argparse.FileType('r'), help='Alternate configuration file') parser.add_argument('--log-config', type=argparse.FileType('r'), help='Alternate logger configuration file') args, unknown_args = parser.parse_known_args() # if we passed in a configuration file on the command line... if args.config_file: cf = args.config_file config_file = cf.name elif config_path is not None: # otherwise use the default cf = open(config_file) else: # If all else fails copy the configuration from the package # to ~/.makerplane/fixgw/config create_config_dir("{USER}/.makerplane/fixgw".format(USER=user_home)) # Reset this stuff like we found it config_file = "{USER}/.makerplane/fixgw/config/{FILE}".format(USER=user_home, FILE=config_filename) cf = open(config_file) config_path = os.path.dirname(cf.name) config = yaml.safe_load(cf) # Either load the config file given as a command line argument or # look in the configuration for the logging object if args.log_config: logging.config.fileConfig(args.log_config) elif 'logging' in config: logging.config.dictConfig(config['logging']) else: logging.basicConfig() log = logging.getLogger() if args.verbose: log.setLevel(logging.INFO) if args.debug: log.setLevel(logging.DEBUG) log.info("Starting FIX Gateway") log.info("Configuration Found at {}".format(config_file)) # Open database definition file and send to database initialization try: ddfile = config["database file"].format(CONFIG=config_path) f = open(ddfile,'r') except: log.critical("Unable to open database definition file - " + ddfile) raise try: database.init(f) except Exception as e: log.error("Database failure, Exiting:" + str(e)) raise if "initialization files" in config and config["initialization files"]: log.info("Setting Initial Values") ifiles = config["initialization files"] for fn in ifiles: try: f = open(fn.format(CONFIG=config_path), 'r') for line in f.readlines(): l = line.strip() if l and l[0] != '#': x = l.split("=") if len(x) >= 2: database.write(x[0].strip(), x[1].strip()) except Exception as e: log.error("Problem setting initial values from configuration - {0}".format(e)) raise # TODO: Need to do some more thorough error checking here # run through the plugin_list dict and find all the plugins that are # configured to be loaded and load them. for each in config['connections']: if config['connections'][each]['load']: module = config['connections'][each]["module"] try: load_plugin(each, module, config['connections'][each]) except Exception as e: logging.critical("Unable to load module - " + module + ": " + str(e)) if args.debug: raise ss = {"Configuration File": config_file, "Configuration Path": config_path} status.initialize(plugins, ss) def sig_int_handler(signum, frame): plugin.jobQueue.put("QUIT") signal.signal(signal.SIGINT, sig_int_handler) signal.signal(signal.SIGTERM, sig_int_handler) for each in plugins: log.debug("Attempting to start plugin {0}".format(each)) try: plugins[each].start() except Exception as e: if args.debug: raise e # If we have debuggin set we'll raise this exception iteration = 0 while True: try: job = plugin.jobQueue.get(timeout=1.0) if job == "QUIT": break except KeyboardInterrupt: # This should be broken by the signal handler log.info("Termination from keybaord received") break except queue.Empty: pass iteration += 1 # Every four times through the loop we do some stuff if iteration % 4 == 0: # check how many plugins are running and exit if zero running_count = 0 for each in plugins: if plugins[each].is_running(): running_count += 1 if running_count == 0: log.info("No plugins running, quitting") break cleanstop = True for each in plugins: log.debug("Attempting to stop plugin {0}".format(each)) try: plugins[each].shutdown() except plugin.PluginFail: log.warning("Plugin {0} did not shutdown properly".format(each)) cleanstop = False if cleanstop == True: log.info("FIX Gateway Exiting Normally") else: log.info("FIX Gateway Exiting Forcefully") os._exit(-1)
def test_none_string(self): database.write("ACID", None) self.sock.sendall("@rACID\n".encode()) res = self.sock.recv(1024).decode() self.assertEqual(res, "@rACID;;00000\n")
def db_write(self, key, value): database.write(key, value)
def test_compute_aoa(self): database.write("IAS.Vs", 72) database.write("AOA.0g", -1.0) database.write("PITCH", 0) database.write("IAS", 10) x = database.read("AOA") self.assertEqual(x, (2.0, False, False, False, False, False)) # Takeoff roll for i in range(100): database.write("PITCH", 0) database.write("IAS", 10 + i) database.write("VS", 0) database.write("ANORM", 9.8) database.write("HEAD", 0) x = database.read("AOA") self.assertEqual(x, (2.0, False, False, True, False, False)) # Climbout for i in range(100): database.write("PITCH", 5) database.write("IAS", 110) database.write("VS", 500) database.write("ANORM", 9.8) database.write("HEAD", 0) x = database.read("AOA") self.assertEqual(x, (7.0, False, False, True, False, False)) # Turn for i in range(100): database.write("PITCH", 2) database.write("IAS", 130) database.write("VS", 50) database.write("ANORM", 10.8) database.write("HEAD", i) x = database.read("AOA") self.assertEqual(x, (4.0, False, False, True, False, False)) # Straight and level for i in range(110): database.write("PITCH", 1) database.write("IAS", 130) database.write("VS", 0) database.write("ANORM", 9.8) database.write("HEAD", 100) x = database.read("AOA") y, a, o, b, f, s = x x = (round(y, 2), a, o, b, f, s) self.assertEqual(x, (3.0, False, False, False, False, False)) database.write("IAS", 100) database.write("ANORM", 10.8) x = database.read("AOA") y, a, o, b, f, s = x x = (round(y, 2), a, o, b, f, s) self.assertEqual(x, (4.72, False, False, False, False, False)) database.write("IAS", 130) database.write("ANORM", 7.8) x = database.read("AOA") y, a, o, b, f, s = x x = (round(y, 2), a, o, b, f, s) self.assertEqual(x, (2.59, False, False, False, False, False))
def main(): global config_path # Look for our configuration file in the list of directories for directory in path_options: # store the first match that we find d = directory.format(USER=user_home, PREFIX=prefix_path) if os.path.isfile("{}/{}".format(d, config_filename)): config_path = d break config_file = "{}/{}".format(config_path, config_filename) parser = argparse.ArgumentParser(description='FIX Gateway') parser.add_argument('--debug', '-d', action='store_true', help='Run in debug mode') parser.add_argument('--verbose', '-v', action='store_true', help='Run in verbose mode') parser.add_argument('--config-file', type=argparse.FileType('r'), help='Alternate configuration file') parser.add_argument('--log-config', type=argparse.FileType('r'), help='Alternate logger configuration file') args, unknown_args = parser.parse_known_args() # if we passed in a configuration file on the command line... if args.config_file: cf = args.config_file config_file = cf.name elif config_path is not None: # otherwise use the default cf = open(config_file) else: # If all else fails copy the configuration from the package # to ~/.makerplane/fixgw/config create_config_dir("{USER}/.makerplane/fixgw".format(USER=user_home)) # Reset this stuff like we found it config_file = "{USER}/.makerplane/fixgw/config/{FILE}".format(USER=user_home, FILE=config_filename) cf = open(config_file) config_path = os.path.dirname(cf.name) config = yaml.safe_load(cf) # Either load the config file given as a command line argument or # look in the configuration for the logging object if args.log_config: logging.config.fileConfig(args.log_config) elif 'logging' in config: logging.config.dictConfig(config['logging']) else: logging.basicConfig() log = logging.getLogger() if args.verbose: log.setLevel(logging.INFO) if args.debug: log.setLevel(logging.DEBUG) log.info("Starting FIX Gateway") log.info("Configuration Found at {}".format(config_file)) # Open database definition file and send to database initialization try: ddfile = config["database file"].format(CONFIG=config_path) f = open(ddfile,'r') except: log.critical("Unable to open database definition file - " + ddfile) raise try: database.init(f) except Exception as e: log.error("Database failure, Exiting:" + str(e)) raise if "initialization files" in config and config["initialization files"]: log.info("Setting Initial Values") ifiles = config["initialization files"] for fn in ifiles: try: f = open(fn.format(CONFIG=config_path), 'r') for line in f.readlines(): l = line.strip() if l and l[0] != '#': x = l.split("=") if len(x) >= 2: database.write(x[0].strip(), x[1].strip()) except Exception as e: log.error("Problem setting initial values from configuration - {0}".format(e)) raise # TODO: Need to do some more thorough error checking here # run through the plugin_list dict and find all the plugins that are # configured to be loaded and load them. for each in config['connections']: if config['connections'][each]['load']: module = config['connections'][each]["module"] try: load_plugin(each, module, config['connections'][each]) except Exception as e: logging.critical("Unable to load module - " + module + ": " + str(e)) if args.debug: raise ss = {"Configuration File": config_file, "Configuration Path": config_path} status.initialize(plugins, ss) def sig_int_handler(signum, frame): plugin.jobQueue.put("QUIT") signal.signal(signal.SIGINT, sig_int_handler) signal.signal(signal.SIGTERM, sig_int_handler) for each in plugins: log.debug("Attempting to start plugin {0}".format(each)) try: plugins[each].start() except Exception as e: log.error("Problem Starting Plugin: {} - {}".format(each,e)) if args.debug: raise e # If we have debuggin set we'll raise this exception iteration = 0 while True: try: job = plugin.jobQueue.get(timeout=1.0) if job == "QUIT": break except KeyboardInterrupt: # This should be broken by the signal handler log.info("Termination from keybaord received") break except queue.Empty: pass iteration += 1 # Every four times through the loop we do some stuff if iteration % 4 == 0: # check how many plugins are running and exit if zero running_count = 0 for each in plugins: if plugins[each].is_running(): running_count += 1 if running_count == 0: log.info("No plugins running, quitting") break cleanstop = True for each in plugins: log.debug("Attempting to stop plugin {0}".format(each)) try: plugins[each].shutdown() except plugin.PluginFail: log.warning("Plugin {0} did not shutdown properly".format(each)) cleanstop = False if cleanstop == True: log.info("FIX Gateway Exiting Normally") else: log.info("FIX Gateway Exiting Forcefully") os._exit(-1)