def main(): ### Options management parser = ArgumentParser() parser.add_argument("-V", action="store_true", dest="display_version", default=False, help="Display the xPL hub version.") parser.add_argument("-f", action="store_true", dest="run_in_foreground", default=False, help="Run the xPL hub in foreground, default to background.") options = parser.parse_args() if options.display_version: print(VERSION) return if not options.run_in_foreground: daemon = True ctx = DaemonContext() ctx.open() #from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor #from twisted.python import log else: daemon = False #from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor #from twisted.python import log ### Launch the hub from domogik.xpl.hub.lib import Hub Hub(daemon)
def main(): cfg = Loader('mq') my_conf = cfg.load() config = dict(my_conf[1]) ctx = DaemonContext() ctx.open() context = zmq.Context() print(("tcp://{0}:{1}".format(config['ip'], config['req_rep_port']))) broker = MDPBroker(context, "tcp://{0}:{1}".format(config['ip'], config['req_rep_port'])) IOLoop.instance().start() broker.shutdown()
def main(): cfg = Loader('mq') my_conf = cfg.load() config = dict(my_conf[1]) ctx = DaemonContext() ctx.open() context = zmq.Context() print(("tcp://{0}:{1}".format(config['ip'], config['req_rep_port']))) broker = MDPBroker( context, "tcp://{0}:{1}".format(config['ip'], config['req_rep_port'])) IOLoop.instance().start() broker.shutdown()
def main(): """ Main loop for the forwarder """ ctx = DaemonContext() ctx.open() cfg = Loader('mq').load() config = dict(cfg[1]) log = logger.Logger('mq_forwarder').get_logger() log.info("Starting the forwarder") try: context = zmq.Context(1) # Socket facing emitters frontend = context.socket(zmq.SUB) # Forwarder subscribes to the emitter *pub* port sub_addr = "tcp://{0}:{1}".format(\ config['ip'], config['pub_port']) frontend.bind(sub_addr) log.info("Waiting for messages on {0}".format(sub_addr)) # We want to get all messages from emitters frontend.setsockopt(zmq.SUBSCRIBE, "") # Socket facing receivers backend = context.socket(zmq.PUB) # Forwarder publishes to the receiver *sub* port pub_addr = "tcp://{0}:{1}".format(\ config['ip'], config['sub_port']) backend.bind(pub_addr) log.info("Sending messages to {0}".format(pub_addr)) log.info("Forwarding messages...") zmq.device(zmq.FORWARDER, frontend, backend) except Exception as exp: log.error(exp) log.error("Bringing down ZMQ device") raise Exception("Error with forwarder device") finally: frontend.close() backend.close() context.term() log.info("Forwarder stopped")
def main(): ### Options management parser = ArgumentParser() parser.add_argument("-V", action="store_true", dest="display_version", default=False, help="Display the xPL hub version.") parser.add_argument( "-f", action="store_true", dest="run_in_foreground", default=False, help="Run the xPL hub in foreground, default to background.") options = parser.parse_args() if options.display_version: print(VERSION) return if not options.run_in_foreground: daemon = True ctx = DaemonContext() ctx.open() #from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor #from twisted.python import log else: daemon = False #from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor #from twisted.python import log ### Launch the hub from domogik.xpl.hub.lib import Hub Hub(daemon)
def __init__(self, name, stop_cb = None, p = None, daemonize = True, log_prefix= ""): ''' @param p : An instance of ArgumentParser. If you want to add extra options to the generic option parser, create your own ArgumentParser instance, use parser.add_argument and then pass your parser instance as parameter. Your options/params will then be available on self.options and self.args @param daemonize : If set to False, force the instance *not* to daemonize, even if '-f' is not passed on the command line. If set to True (default), will check if -f was added. @param log_prefix : If set, use this prefix when creating the log file in Logger() ''' ### First, check if the user is allowed to launch the plugin. The user must be the same as the one defined # in the file /etc/default/domogik : DOMOGIK_USER Default = DefaultLoader() dmg_user = Default.get("DOMOGIK_USER") logname = pwd.getpwuid(os.getuid())[0] if dmg_user != logname: print(u"ERROR : this Domogik part must be run with the user defined in /etc/default/domogik as DOMOGIK_USER : %s" % dmg_user) sys.exit(1) if name is not None: self._plugin_name = name l = logger.Logger(name, use_filename = "{0}{1}".format(log_prefix, name)) self.log = l.get_logger() ### Check if the plugin is not already launched # notice that when the plugin is launched from the manager, this call is not done as the manager already does this test before starting a plugin res, pid_list = is_already_launched(self.log, name) if res: sys.exit(2) ### Create a file to handle the return code # this is used by the function set_return_code and get_return_code # this is needed as a Domogik process is forked, there is no way to send from a class a return code from the child to the parent. try: self.return_code_filename = "{0}/{1}_return_code_{2}".format(FIFO_DIR, self._plugin_name, os.getpid()) # just touch the file to create it open(self.return_code_filename, 'a').close() except: self.log.error("Error while creating return_code file '{0}' : {1}".format(self.return_code_filename, traceback.format_exc())) sys.exit(3) ### Start the plugin... self._threads = [] self._timers = [] self._stop = threading.Event() self._lock_add_thread = threading.Semaphore() self._lock_add_timer = threading.Semaphore() self._lock_add_cb = threading.Semaphore() if stop_cb is not None: self._stop_cb = [stop_cb] else: self._stop_cb = [] ### options management if p is not None and isinstance(p, ArgumentParser): parser = p else: parser = ArgumentParser() parser.add_argument("-V", "--version", action="store_true", dest="display_version", default=False, help="Display Domogik version.") parser.add_argument("-f", action="store_true", dest="run_in_foreground", default=False, help="Run the plugin in foreground, default to background.") parser.add_argument("-T", dest="test_option", default=None, help="Test option.") self.options = parser.parse_args() if self.options.display_version: __import__("domogik") global_release = sys.modules["domogik"].__version__ print(global_release) sys.exit(0) elif not self.options.run_in_foreground and daemonize: self.log.info(u"Starting the plugin in background...") ctx = DaemonContext() ctx.files_preserve = l.get_fds([name]) ctx.open() self.log.info(u"Daemonize plugin %s" % name) self.is_daemon = True else: #l = logger.Logger(name) #self.log = l.get_logger() self.is_daemon = False
def __init__(self, name, stop_cb=None, p=None, daemonize=True, log_prefix="", log_on_stdout=True): ''' @param p : An instance of ArgumentParser. If you want to add extra options to the generic option parser, create your own ArgumentParser instance, use parser.add_argument and then pass your parser instance as parameter. Your options/params will then be available on self.options and self.args @param daemonize : If set to False, force the instance *not* to daemonize, even if '-f' is not passed on the command line. If set to True (default), will check if -f was added. @param log_prefix : If set, use this prefix when creating the log file in Logger() @param log_on_stdout : if set to True, allow to read logs on both stdout and log file ''' ### First, check if the user is allowed to launch the plugin. The user must be the same as the one defined # in the file /etc/default/domogik : DOMOGIK_USER Default = DefaultLoader() dmg_user = Default.get("DOMOGIK_USER") logname = pwd.getpwuid(os.getuid())[0] if dmg_user != logname: print( u"ERROR : this Domogik part must be run with the user defined in /etc/default/domogik as DOMOGIK_USER : %s" % dmg_user) sys.exit(1) if name is not None: self._plugin_name = name l = logger.Logger(name, use_filename="{0}{1}".format(log_prefix, name), log_on_stdout=log_on_stdout) self.log = l.get_logger() ### Check if the plugin is not already launched # notice that when the plugin is launched from the manager, this call is not done as the manager already does this test before starting a plugin # TODO : improve ? currently, as it is not used, we set the type of the client to None # in case the 'is_already_launched function would use it a day, we should find a way to get the client type res, pid_list = is_already_launched(self.log, None, name) if res: sys.exit(2) ### Create a file to handle the return code # this is used by the function set_return_code and get_return_code # this is needed as a Domogik process is forked, there is no way to send from a class a return code from the child to the parent. try: self.return_code_filename = "{0}/{1}_return_code_{2}".format( FIFO_DIR, self._plugin_name, os.getpid()) # just touch the file to create it open(self.return_code_filename, 'a').close() except: self.log.error( "Error while creating return_code file '{0}' : {1}".format( self.return_code_filename, traceback.format_exc())) sys.exit(3) ### Start the plugin... self._threads = [] self._timers = [] self._stop = threading.Event() self._lock_add_thread = threading.Semaphore() self._lock_add_timer = threading.Semaphore() self._lock_add_cb = threading.Semaphore() if stop_cb is not None: self._stop_cb = [stop_cb] else: self._stop_cb = [] ### options management if p is not None and isinstance(p, ArgumentParser): parser = p else: parser = ArgumentParser() parser.add_argument("-V", "--version", action="store_true", dest="display_version", default=False, help="Display Domogik version.") parser.add_argument( "-f", action="store_true", dest="run_in_foreground", default=False, help="Run the plugin in foreground, default to background.") parser.add_argument("-T", dest="test_option", default=None, help="Test option.") self.options = parser.parse_args() if self.options.display_version: __import__("domogik") global_release = sys.modules["domogik"].__version__ print(global_release) sys.exit(0) elif not self.options.run_in_foreground and daemonize: self.log.info(u"Starting the plugin in background...") ctx = DaemonContext() ctx.files_preserve = l.get_fds([name]) ctx.open() self.log.info(u"Daemonize plugin %s" % name) self.is_daemon = True else: #l = logger.Logger(name) #self.log = l.get_logger() self.is_daemon = False
class DaemonRunner(object): """ Controller for a callable running in a separate background process. The first command-line argument is the action to take: * 'start': Become a daemon and call `app.run()`. * 'stop': Exit the daemon process specified in the PID file. * 'restart': Stop, then start. """ start_message = "started with pid %(pid)d" def __init__(self, app): """ Set up the parameters of a new runner. The `app` argument must have the following attributes: * `stdin_path`, `stdout_path`, `stderr_path`: Filesystem paths to open and replace the existing `sys.stdin`, `sys.stdout`, `sys.stderr`. * `pidfile_path`: Absolute filesystem path to a file that will be used as the PID file for the daemon. If ``None``, no PID file will be used. * `pidfile_timeout`: Used as the default acquisition timeout value supplied to the runner's PID lock file. * `run`: Callable that will be invoked when the daemon is started. """ self.parse_args() self.app = app self.daemon_context = DaemonContext() self.daemon_context.stdin = open(app.stdin_path, 'r') self.daemon_context.stdout = open(app.stdout_path, 'w+') self.daemon_context.stderr = open( app.stderr_path, 'w+', buffering=0) self.pidfile = None if app.pidfile_path is not None: self.pidfile = make_pidlockfile( app.pidfile_path, app.pidfile_timeout) self.daemon_context.pidfile = self.pidfile def _usage_exit(self, argv): """ Emit a usage message, then exit. """ progname = os.path.basename(argv[0]) usage_exit_code = 2 action_usage = "|".join(self.action_funcs.keys()) message = "usage: %(progname)s %(action_usage)s" % vars() emit_message(message) sys.exit(usage_exit_code) def parse_args(self, argv=None): """ Parse command-line arguments. """ if argv is None: argv = sys.argv min_args = 2 if len(argv) < min_args: self._usage_exit(argv) self.action = argv[1] if self.action not in self.action_funcs: self._usage_exit(argv) def _start(self): """ Open the daemon context and run the application. """ if is_pidfile_stale(self.pidfile): self.pidfile.break_lock() try: self.daemon_context.open() except pidlockfile.AlreadyLocked: pidfile_path = self.pidfile.path raise DaemonRunnerStartFailureError( "PID file %(pidfile_path)r already locked" % vars()) pid = os.getpid() message = self.start_message % vars() emit_message(message) self.app.run() def _terminate_daemon_process(self): """ Terminate the daemon process specified in the current PID file. """ pid = self.pidfile.read_pid() try: os.kill(pid, signal.SIGTERM) except OSError as exc: raise DaemonRunnerStopFailureError( "Failed to terminate %(pid)d: %(exc)s" % vars()) def _stop(self): """ Exit the daemon process specified in the current PID file. """ if not self.pidfile.is_locked(): pidfile_path = self.pidfile.path raise DaemonRunnerStopFailureError( "PID file %(pidfile_path)r not locked" % vars()) if is_pidfile_stale(self.pidfile): self.pidfile.break_lock() else: self._terminate_daemon_process() def _restart(self): """ Stop, then start. """ self._stop() self._start() action_funcs = { 'start': _start, 'stop': _stop, 'restart': _restart, } def _get_action_func(self): """ Return the function for the specified action. Raises ``DaemonRunnerInvalidActionError`` if the action is unknown. """ try: func = self.action_funcs[self.action] except KeyError: raise DaemonRunnerInvalidActionError( "Unknown action: %(action)r" % vars(self)) return func def do_action(self): """ Perform the requested action. """ func = self._get_action_func() func(self)
class DaemonRunner(object): """ Controller for a callable running in a separate background process. The first command-line argument is the action to take: * 'start': Become a daemon and call `app.run()`. * 'stop': Exit the daemon process specified in the PID file. * 'restart': Stop, then start. """ start_message = "started with pid %(pid)d" def __init__(self, app): """ Set up the parameters of a new runner. The `app` argument must have the following attributes: * `stdin_path`, `stdout_path`, `stderr_path`: Filesystem paths to open and replace the existing `sys.stdin`, `sys.stdout`, `sys.stderr`. * `pidfile_path`: Absolute filesystem path to a file that will be used as the PID file for the daemon. If ``None``, no PID file will be used. * `pidfile_timeout`: Used as the default acquisition timeout value supplied to the runner's PID lock file. * `run`: Callable that will be invoked when the daemon is started. """ self.parse_args() self.app = app self.daemon_context = DaemonContext() self.daemon_context.stdin = open(app.stdin_path, 'r') self.daemon_context.stdout = open(app.stdout_path, 'w+') self.daemon_context.stderr = open(app.stderr_path, 'w+', buffering=0) self.pidfile = None if app.pidfile_path is not None: self.pidfile = make_pidlockfile(app.pidfile_path, app.pidfile_timeout) self.daemon_context.pidfile = self.pidfile def _usage_exit(self, argv): """ Emit a usage message, then exit. """ progname = os.path.basename(argv[0]) usage_exit_code = 2 action_usage = "|".join(self.action_funcs.keys()) message = "usage: %(progname)s %(action_usage)s" % vars() emit_message(message) sys.exit(usage_exit_code) def parse_args(self, argv=None): """ Parse command-line arguments. """ if argv is None: argv = sys.argv min_args = 2 if len(argv) < min_args: self._usage_exit(argv) self.action = argv[1] if self.action not in self.action_funcs: self._usage_exit(argv) def _start(self): """ Open the daemon context and run the application. """ if is_pidfile_stale(self.pidfile): self.pidfile.break_lock() try: self.daemon_context.open() except pidlockfile.AlreadyLocked: pidfile_path = self.pidfile.path raise DaemonRunnerStartFailureError( "PID file %(pidfile_path)r already locked" % vars()) pid = os.getpid() message = self.start_message % vars() emit_message(message) self.app.run() def _terminate_daemon_process(self): """ Terminate the daemon process specified in the current PID file. """ pid = self.pidfile.read_pid() try: os.kill(pid, signal.SIGTERM) except OSError as exc: raise DaemonRunnerStopFailureError( "Failed to terminate %(pid)d: %(exc)s" % vars()) def _stop(self): """ Exit the daemon process specified in the current PID file. """ if not self.pidfile.is_locked(): pidfile_path = self.pidfile.path raise DaemonRunnerStopFailureError( "PID file %(pidfile_path)r not locked" % vars()) if is_pidfile_stale(self.pidfile): self.pidfile.break_lock() else: self._terminate_daemon_process() def _restart(self): """ Stop, then start. """ self._stop() self._start() action_funcs = { 'start': _start, 'stop': _stop, 'restart': _restart, } def _get_action_func(self): """ Return the function for the specified action. Raises ``DaemonRunnerInvalidActionError`` if the action is unknown. """ try: func = self.action_funcs[self.action] except KeyError: raise DaemonRunnerInvalidActionError("Unknown action: %(action)r" % vars(self)) return func def do_action(self): """ Perform the requested action. """ func = self._get_action_func() func(self)