def _api_exit(self, stream, request, query): POLLER.sched(0, lambda *args, **kwargs: POLLER.break_loop()) response = Message() stringio = StringIO.StringIO("See you, space cowboy\n") response.compose(code="200", reason="Ok", body=stringio, mimetype="text/plain") stream.send_response(request, response)
def main(args): config.register_descriptions() common.main("bittorrent", "Neubot BitTorrent module", args) conf = CONFIG.copy() config.finalize_conf(conf) if conf["bittorrent.listen"]: # # If we need to negotiate and we're runing # standalone we also need to bring up the # global HTTP server. # if conf["bittorrent.negotiate"]: HTTP_SERVER.configure(conf) HTTP_SERVER.listen((conf["bittorrent.address"], conf["bittorrent.negotiate.port"])) conf["negotiate.listen"] = True negotiate.run(POLLER, conf) # # Drop privileges after listen() so we can # bind() to privileged ports # if conf["bittorrent.daemonize"]: system.change_dir() system.go_background() LOG.redirect() system.drop_privileges(LOG.error) else: # # When we're connecting to a remote host to perform a test # we want Neubot to quit at the end of the test. When this # happens the test code publishes the "testdone" event, so # here we prepare to intercept the event and break our main # loop. # NOTIFIER.subscribe("testdone", lambda event, ctx: POLLER.break_loop()) run(POLLER, conf) POLLER.loop()
def _api_exit(self, stream, request, query): # Break out of the loop immediately POLLER.break_loop()
def main(args): """ Starts the server module """ if not system.has_enough_privs(): sys.exit('FATAL: you must be root') try: options, arguments = getopt.getopt(args[1:], 'A:b:D:dv') except getopt.error: sys.exit(USAGE) if arguments: sys.exit(USAGE) address = ':: 0.0.0.0' backend = 'mlab' for name, value in options: if name == '-A': address = value elif name == '-b': backend = value elif name == '-D': name, value = value.split('=', 1) if name not in VALID_MACROS: sys.exit(USAGE) if name != 'server.datadir': # XXX value = int(value) SETTINGS[name] = value elif name == '-d': SETTINGS['server.daemonize'] = 0 elif name == '-v': CONFIG['verbose'] = 1 logging.debug('server: using backend: %s... in progress', backend) if backend == 'mlab': BACKEND.datadir_init(None, SETTINGS['server.datadir']) BACKEND.use_backend('mlab') elif backend == 'neubot': DATABASE.connect() BACKEND.use_backend('neubot') elif backend == 'volatile': BACKEND.use_backend('volatile') else: BACKEND.use_backend('null') logging.debug('server: using backend: %s... complete', backend) for name, value in SETTINGS.items(): CONFIG[name] = value conf = CONFIG.copy() # # Configure our global HTTP server and make # sure that we don't provide filesystem access # even by mistake. # conf["http.server.rootdir"] = "" HTTP_SERVER.configure(conf) # # New-new style: don't bother with abstraction and start the f*****g # server by invoking its listen() method. # if CONFIG['server.raw']: logging.debug('server: starting raw server... in progress') RAW_SERVER_EX.listen((address, 12345), CONFIG['prefer_ipv6'], 0, '') logging.debug('server: starting raw server... complete') if conf['server.skype']: logging.debug('server: starting skype server... in progress') SKYPE_SERVER_EX.listen((":: 0.0.0.0", 45678), CONFIG['prefer_ipv6'], 0, '') logging.debug('server: starting skype server... complete') # # New-style modules are started just setting a # bunch of conf[] variables and then invoking # their run() method in order to kick them off. # This is now depricated in favor of the new- # new style described above. # if conf["server.negotiate"]: negotiate.run(POLLER, conf) if conf["server.bittorrent"]: conf["bittorrent.address"] = address conf["bittorrent.listen"] = True conf["bittorrent.negotiate"] = True bittorrent.run(POLLER, conf) if conf['server.speedtest']: #conf['speedtest.listen'] = 1 # Not yet #conf['speedtest.negotiate'] = 1 # Not yet neubot.speedtest.wrapper.run(POLLER, conf) # Migrating from old style to new style if conf["server.rendezvous"]: #conf["rendezvous.listen"] = True # Not yet neubot.rendezvous.server.run() # # Historically Neubot runs on port 9773 and # 8080 but we would like to switch to port 80 # in the long term period, because it's rare # that they filter it. # OTOH it looks like it's not possible to # do that easily w/ M-Lab because the port # is already taken. # ports = (80, 8080, 9773) for port in ports: HTTP_SERVER.listen((address, port)) # # Start server-side API for Nagios plugin # to query the state of the server. # functionalities. # if conf["server.sapi"]: server = ServerSideAPI(POLLER) server.configure(conf) HTTP_SERVER.register_child(server, "/sapi") # # Create localhost-only debug server # if CONFIG['server.debug']: logging.info('server: Starting debug server at {127.0.0.1,::1}:9774') server = DebugAPI(POLLER) server.configure(conf) server.listen(('127.0.0.1 ::1', 9774)) # Probe existing modules and ask them to attach to us utils_modules.modprobe(None, "server", { "http_server": HTTP_SERVER, "negotiate_server": NEGOTIATE_SERVER, }) # # Go background and drop privileges, # then enter into the main loop. # if conf["server.daemonize"]: LOG.redirect() system.go_background() sigterm_handler = lambda signo, frame: POLLER.break_loop() signal.signal(signal.SIGTERM, sigterm_handler) logging.info('Neubot server -- starting up') system.drop_privileges() POLLER.loop() logging.info('Neubot server -- shutting down') utils_posix.remove_pidfile('/var/run/neubot.pid')
def main(args): config.register_descriptions() common.main("bittorrent", "Neubot BitTorrent module", args) conf = CONFIG.copy() config.finalize_conf(conf) if conf["bittorrent.listen"]: # # If we need to negotiate and we're runing # standalone we also need to bring up the # global HTTP server. # if conf["bittorrent.negotiate"]: HTTP_SERVER.configure(conf) HTTP_SERVER.listen((conf["bittorrent.address"], conf["bittorrent.negotiate.port"])) conf["negotiate.listen"] = True negotiate.run(POLLER, conf) # # Drop privileges after listen() so we can # bind() to privileged ports # if conf["bittorrent.daemonize"]: system.change_dir() system.go_background() LOG.redirect() system.drop_privileges(LOG.error) else: # # If possible use the runner, which will execute the # test in the context of the neubot daemon. Then exit # to bypass the run() invokation that is below here. # If the runner fails, fallback to the usual code path, # which executes the test in the context of the local # process. # Set 'runned.enabled' to 0 to bypass the runner and # run the test locally. # if (utils.intify(conf['runner.enabled']) and runner_clnt.runner_client(conf["agent.api.address"], conf["agent.api.port"], LOG.noisy, "bittorrent")): sys.exit(0) LOG.info('Will run the test in the local context...') # # When we're connecting to a remote host to perform a test # we want Neubot to quit at the end of the test. When this # happens the test code publishes the "testdone" event, so # here we prepare to intercept the event and break our main # loop. # NOTIFIER.subscribe("testdone", lambda event, ctx: POLLER.break_loop()) run(POLLER, conf) POLLER.loop()
def __start_neubot_agent(): ''' Fork a new process and run neubot agent ''' # Fork a new process pid = os.fork() if pid > 0: syslog.syslog(syslog.LOG_INFO, 'Neubot agent PID: %d' % pid) return pid # # The child code is surrounded by this giant try..except # because we don't want the child process to eventually # return to the caller. # try: syslog.openlog('neubot', syslog.LOG_PID, syslog.LOG_DAEMON) # Add neubot directory to python search path if not os.access(VERSIONDIR, os.R_OK|os.X_OK): raise RuntimeError('Cannot access: %s' % VERSIONDIR) if not VERSIONDIR in sys.path: syslog.syslog(syslog.LOG_ERR, 'Prepending "%s" to Python search path' % VERSIONDIR) sys.path.insert(0, VERSIONDIR) # Import the required modules from neubot.log import LOG from neubot.net.poller import POLLER from neubot import agent # # Redirect logger to syslog now, so early errors in # agent.py:main() are logged. # LOG.redirect() # # Close all unneeded file descriptors, but save stdio, # which has just been redirected. # for tmpdesc in range(3, 64): try: os.close(tmpdesc) except OSError: pass except: pass # Handle SIGTERM gracefully sigterm_handler = lambda signo, frame: POLLER.break_loop() signal.signal(signal.SIGTERM, sigterm_handler) # # Here we're running as root but this is OK because # neubot/agent.py is going to drop the privileges to # the unprivileged user `_neubot`. # agent.main(['neubot/agent.py', '-D agent.daemonize=OFF', '-D agent.use_syslog=ON']) # # We must employ __exit() instead of sys.exit() because # the latter is catched below by our catch-all clauses and # the child process will start running the parent code. # OTOH __exit() exits immediately. # except: try: why = asyncore.compact_traceback() syslog.syslog(syslog.LOG_ERR, 'Unhandled exception in the Neubot agent: %s' % str(why)) except: pass __exit(1) else: __exit(0)
def main(args): ''' This function is invoked when the user wants to run precisely this module. ''' try: options, arguments = getopt.getopt(args[1:], '6A:fp:v') except getopt.error: sys.exit('usage: neubot bittorrent [-6fv] [-A address] [-p port]') if arguments: sys.exit('usage: neubot bittorrent [-6fv] [-A address] [-p port]') prefer_ipv6 = 0 address = 'master.neubot.org' force = 0 port = 6881 noisy = 0 for name, value in options: if name == '-6': prefer_ipv6 = 1 elif name == '-A': address = value elif name == '-f': force = 1 elif name == '-p': port = int(value) elif name == '-v': noisy = 1 if os.path.isfile(DATABASE.path): DATABASE.connect() CONFIG.merge_database(DATABASE.connection()) else: logging.warning('bittorrent: database file is missing: %s', DATABASE.path) BACKEND.use_backend('null') if noisy: log.set_verbose() config.register_descriptions() # Needed? conf = CONFIG.copy() config.finalize_conf(conf) conf['bittorrent.address'] = address conf['bittorrent.port'] = port conf['prefer_ipv6'] = prefer_ipv6 if not force: if runner_clnt.runner_client(conf["agent.api.address"], conf["agent.api.port"], CONFIG['verbose'], "bittorrent"): sys.exit(0) logging.warning( 'bittorrent: failed to contact Neubot; is Neubot running?') sys.exit(1) logging.info('bittorrent: run the test in the local process context...') # # When we're connecting to a remote host to perform a test # we want Neubot to quit at the end of the test. When this # happens the test code publishes the "testdone" event, so # here we prepare to intercept the event and break our main # loop. # NOTIFIER.subscribe("testdone", lambda event, ctx: POLLER.break_loop()) run(POLLER, conf) POLLER.loop()