def _execute(self): # calling the clients now self.test_result.startTestRun() detached = self.args.get('detach') if not detached: cb = ioloop.PeriodicCallback(self.refresh, self.refresh_rate, self.loop) cb.start() try: self._attach_publisher() logger.debug('Calling the broker...') res = self.client.run(self.args) self.run_id = res['run_id'] self.agents = res['agents'] if not detached: logger.debug('Waiting for results') self.loop.start() else: logger.info('Detached. run --attach to reattach') finally: if not detached: # end.. cb.stop() self.test_result.stopTestRun() self.context.destroy() self.flush()
def main(args=sys.argv): parser = argparse.ArgumentParser(description='Run an agent.') parser.add_argument('--broker', dest='broker', default=DEFAULT_FRONTEND, help="ZMQ socket to the broker.") parser.add_argument('--receiver', dest='receiver', default=DEFAULT_AGENT_RECEIVER, help="ZMQ socket to get results from workers.") parser.add_argument('--debug', action='store_true', default=False, help="Debug mode") parser.add_argument('--logfile', dest='logfile', default='stdout', help="File to log in to.") parser.add_argument('--params', dest='params', default=None, help='The parameters to be used by the agent.') parser.add_argument('--timeout', dest='timeout', type=float, default=DEFAULT_TIMEOUT_MOVF, help=('The maximum time allowed before the thread ' 'stacks is dump and the message result not sent ' 'back.')) parser.add_argument('--max-age', dest='max_age', type=float, default=DEFAULT_MAX_AGE, help=('The maximum age for a worker in seconds. ' 'After that delay, the worker will simply quit. ' 'When set to -1, never quits.')) parser.add_argument('--max-age-delta', dest='max_age_delta', type=int, default=DEFAULT_MAX_AGE_DELTA, help='The maximum value in seconds added to max_age') args = parser.parse_args() set_logger(args.debug, logfile=args.logfile) sys.path.insert(0, os.getcwd()) # XXX if args.params is None: params = {} else: params = decode_params(args.params) logger.info('Connecting to %s' % args.broker) agent = Agent(broker=args.broker, receiver=args.receiver, params=params, timeout=args.timeout, max_age=args.max_age, max_age_delta=args.max_age_delta) try: agent.start() except KeyboardInterrupt: return 1 finally: agent.stop() return 0
def lost(self): if len(self._workers) > 0: # if we're busy we won't quit! logger.info("Broker lost ! But we're busy...") return False logger.info('Broker lost ! Quitting..') self.loop.add_callback(self._stop) return True
def __init__(self, broker=DEFAULT_FRONTEND, ping_delay=10., ping_retries=3, params=None, timeout=DEFAULT_TIMEOUT_MOVF, max_age=DEFAULT_MAX_AGE, max_age_delta=DEFAULT_MAX_AGE_DELTA): logger.debug('Initializing the agent.') self.debug = logger.isEnabledFor(logging.DEBUG) self.params = params self.pid = os.getpid() self.agent_id = '%s-%s' % (get_hostname(), self.pid) self.timeout = timeout self.max_age = max_age self.max_age_delta = max_age_delta self.env = os.environ.copy() self.running = False self._workers = {} self._max_id = defaultdict(int) # Let's ask the broker its options self.broker = broker client = Client(self.broker) # this will timeout in case the broker is unreachable result = client.ping() self.endpoints = result['endpoints'] # Setup the zmq sockets self.loop = ioloop.IOLoop() self.ctx = zmq.Context() # backend socket - used to receive work from the broker self._backend = self.ctx.socket(zmq.ROUTER) self._backend.identity = self.agent_id self._backend.connect(self.endpoints['backend']) # register socket - used to register into the broker self._reg = self.ctx.socket(zmq.PUSH) self._reg.connect(self.endpoints['register']) # hearbeat socket - used to check if the broker is alive heartbeat = self.endpoints.get('heartbeat') if heartbeat is not None: logger.info("Hearbeat activated") self.ping = Stethoscope(heartbeat, onbeatlost=self.lost, delay=ping_delay, retries=ping_retries, ctx=self.ctx, io_loop=self.loop, onregister=self.register) else: self.ping = None # Setup the zmq streams. self._backstream = zmqstream.ZMQStream(self._backend, self.loop) self._backstream.on_recv(self._handle_recv_back) self._check = ioloop.PeriodicCallback(self._check_proc, ping_delay * 1000, io_loop=self.loop)
def _handle_commands(self, message): # we get the messages from the broker here data = message.data command = data['command'] logger.debug('Received command %s' % command) if command == 'RUN': test_dir = data['args'].get('test_dir') if test_dir is None: test_dir = tempfile.mkdtemp() else: test_dir += str(os.getpid()) if not os.path.exists(test_dir): os.makedirs(test_dir) data['args']['test_dir'] = test_dir # XXX should be done in _run or at least asynchronously filedata = data.get('filedata') if filedata: unpack_include_files(filedata, test_dir) args = data['args'] run_id = data.get('run_id') pid = self._run(args, run_id) return { 'result': { 'pids': [pid], 'agent_id': str(self.pid), 'command': command } } elif command in ('STATUS', '_STATUS'): return self._status(command, data) elif command == 'STOP': logger.debug('asked to STOP all runs') return self._stop_runs(command) elif command == 'QUIT': if len(self._workers) > 0 and not data.get('force', False): # if we're busy we won't quit - unless forced ! logger.info("Broker asked us to quit ! But we're busy...") logger.info("Cowardly refusing to die") return self._status(command, data) logger.debug('asked to QUIT') try: return self._stop_runs(command) finally: sys.exit(0) raise NotImplementedError(command)
def main(args=sys.argv): parser = argparse.ArgumentParser(description='Run an agent.') parser.add_argument('--broker', dest='broker', default=DEFAULT_FRONTEND, help="ZMQ socket to the broker.") parser.add_argument('--debug', action='store_true', default=False, help="Debug mode") parser.add_argument('--logfile', dest='logfile', default='stdout', help="File to log in to.") parser.add_argument('--params', dest='params', default=None, help='The parameters to be used by the agent.') parser.add_argument('--timeout', dest='timeout', type=float, default=DEFAULT_TIMEOUT_MOVF, help=('The maximum time allowed before the thread ' 'stacks is dump and the message result not sent ' 'back.')) parser.add_argument('--max-age', dest='max_age', type=float, default=DEFAULT_MAX_AGE, help=('The maximum age for a worker in seconds. ' 'After that delay, the worker will simply quit. ' 'When set to -1, never quits.')) parser.add_argument('--max-age-delta', dest='max_age_delta', type=int, default=DEFAULT_MAX_AGE_DELTA, help='The maximum value in seconds added to max_age') args = parser.parse_args() set_logger(args.debug, logfile=args.logfile) sys.path.insert(0, os.getcwd()) # XXX if args.params is None: params = {} else: params = decode_params(args.params) logger.info('Connecting to %s' % args.broker) agent = Agent(broker=args.broker, params=params, timeout=args.timeout, max_age=args.max_age, max_age_delta=args.max_age_delta) try: agent.start() except KeyboardInterrupt: return 1 finally: agent.stop() return 0
def _handle_commands(self, message): # we get the messages from the broker here data = message.data command = data['command'] logger.debug('Received command %s' % command) if command == 'RUN': test_dir = data['args'].get('test_dir') if test_dir is None: test_dir = tempfile.mkdtemp() else: test_dir += str(os.getpid()) if not os.path.exists(test_dir): os.makedirs(test_dir) data['args']['test_dir'] = test_dir # XXX should be done in _run or at least asynchronously filedata = data.get('filedata') if filedata: unpack_include_files(filedata, test_dir) args = data['args'] run_id = data.get('run_id') pid = self._run(args, run_id) return {'result': {'pids': [pid], 'agent_id': str(self.pid), 'command': command}} elif command in ('STATUS', '_STATUS'): return self._status(command, data) elif command == 'STOP': logger.debug('asked to STOP all runs') return self._stop_runs(command) elif command == 'QUIT': if len(self._workers) > 0 and not data.get('force', False): # if we're busy we won't quit - unless forced ! logger.info("Broker asked us to quit ! But we're busy...") logger.info("Cowardly refusing to die") return self._status(command, data) logger.debug('asked to QUIT') try: return self._stop_runs(command) finally: sys.exit(0) raise NotImplementedError(command)
def get_database(name='python', loop=None, **options): if name == 'python': from loads.db._python import BrokerDB klass = BrokerDB elif name == 'redis': from loads.db._redis import RedisDB klass = RedisDB else: raise NotImplementedError(name) db = klass(loop, **options) logger.info('Created a %r database connection' % name) return db
def run(args): is_slave = args.get('slave', False) has_agents = args.get('agents', None) attach = args.get('attach', False) if not attach and (is_slave or not has_agents): if args.get('test_runner', None) is not None: runner = ExternalRunner else: runner = LocalRunner try: return runner(args).execute() except Exception: print traceback.format_exc() raise else: if attach: # find out what's running client = Client(args['broker']) try: runs = client.list_runs() except TimeoutError: logger.info("Can't reach the broker at %r" % args['broker']) client.close() return 1 if len(runs) == 0: logger.info("Nothing seem to be running on that broker.") client.close() return 1 elif len(runs) == 1: run_id, run_data = runs.items()[0] __, started = run_data[-1] else: # we need to pick one raise NotImplementedError() counts = client.get_counts(run_id) events = [event for event, hits in counts] if 'stopTestRun' in events: logger.info("This test has just stopped.") client.close() return 1 metadata = client.get_metadata(run_id) logger.debug('Reattaching run %r' % run_id) started = datetime.utcfromtimestamp(started) runner = DistributedRunner(args) try: return runner.attach(run_id, started, counts, metadata) except KeyboardInterrupt: _detach_question(runner) else: logger.debug('Summoning %d agents' % args['agents']) runner = DistributedRunner(args) try: return runner.execute() except KeyboardInterrupt: _detach_question(runner)
broker = Broker(frontend=args.frontend, backend=args.backend, heartbeat=args.heartbeat, register=args.register, receiver=args.receiver, publisher=args.publisher, io_threads=args.io_threads, db=args.db, dboptions=dboptions, web_root=args.web_root) except DuplicateBrokerError, e: logger.info('There is already a broker running on PID %s' % e) logger.info('Exiting') return 1 logger.info('Listening to incoming jobs at %r' % args.frontend) logger.info('Workers may register at %r' % args.backend) if args.heartbeat is not None: logger.info('The heartbeat socket is at %r' % args.heartbeat) try: broker.start() except KeyboardInterrupt: pass finally: broker.stop() return 0 if __name__ == '__main__': sys.exit(main())
def lost(self): logger.info('Broker lost ! Quitting..') self.running = False self.loop.stop() return True
def main(args=sys.argv): parser = argparse.ArgumentParser(description='Loads broker.') parser.add_argument('--frontend', dest='frontend', default=DEFAULT_FRONTEND, help="ZMQ socket to receive jobs.") parser.add_argument('--backend', dest='backend', default=DEFAULT_BACKEND, help="ZMQ socket for agents.") parser.add_argument('--heartbeat', dest='heartbeat', default=None, help="ZMQ socket for the heartbeat.") parser.add_argument('--register', dest='register', default=DEFAULT_REG, help="ZMQ socket for the registration.") parser.add_argument('--receiver', dest='receiver', default=DEFAULT_BROKER_RECEIVER, help="ZMQ socket to receive events from the runners") parser.add_argument('--publisher', dest='publisher', default=DEFAULT_PUBLISHER, help="ZMQ socket for the registration.") parser.add_argument('--io-threads', type=int, default=DEFAULT_IOTHREADS, help="Number of I/O threads") parser.add_argument('--debug', action='store_true', default=False, help="Debug mode") parser.add_argument('--check', action='store_true', default=False, help=("Use this option to check if there's a running " " broker. Returns the PID if a broker is up.")) parser.add_argument('--logfile', dest='logfile', default='stdout', help="File to log in to.") parser.add_argument('--db', dest='db', default='python', help="Database backend.") # add db args for backend, options in get_backends(): for option, default, help, type_ in options: option = 'db_%s_%s' % (backend, option) kargs = {'dest': option, 'default': default} if type_ is bool: kargs['action'] = 'store_true' else: kargs['type'] = type_ option = option.replace('_', '-') parser.add_argument('--%s' % option, **kargs) args = parser.parse_args() set_logger(args.debug, logfile=args.logfile) if args.check: pid = verify_broker(args.frontend) if pid is None: logger.info('There seem to be no broker on this endpoint') else: logger.info('A broker is running. PID: %s' % pid) return 0 # grabbing the db options dboptions = {} prefix = 'db_%s_' % args.db for key, value in args._get_kwargs(): if not key.startswith(prefix): continue dboptions[key[len(prefix):]] = value logger.info('Starting the broker') try: broker = Broker(frontend=args.frontend, backend=args.backend, heartbeat=args.heartbeat, register=args.register, receiver=args.receiver, publisher=args.publisher, io_threads=args.io_threads, db=args.db, dboptions=dboptions) except DuplicateBrokerError, e: logger.info('There is already a broker running on PID %s' % e) logger.info('Exiting') return 1
def main(args=sys.argv): parser = argparse.ArgumentParser(description='Run some watchers.') parser.add_argument('--backend', dest='backend', default=DEFAULT_BACKEND, help="ZMQ socket to the broker.") parser.add_argument('--register', dest='register', default=DEFAULT_REG, help="ZMQ socket for the registration.") parser.add_argument('target', help="Fully qualified name of the callable.") parser.add_argument('--debug', action='store_true', default=False, help="Debug mode") parser.add_argument('--logfile', dest='logfile', default='stdout', help="File to log in to.") parser.add_argument('--heartbeat', dest='heartbeat', default=DEFAULT_HEARTBEAT, help="ZMQ socket for the heartbeat.") parser.add_argument('--params', dest='params', default=None, help='The parameters to be used in the worker.') parser.add_argument('--timeout', dest='timeout', type=float, default=DEFAULT_TIMEOUT_MOVF, help=('The maximum time allowed before the thread ' 'stacks is dump and the message result not sent ' 'back.')) parser.add_argument('--max-age', dest='max_age', type=float, default=DEFAULT_MAX_AGE, help=('The maximum age for a worker in seconds. ' 'After that delay, the worker will simply quit. ' 'When set to -1, never quits.')) parser.add_argument('--max-age-delta', dest='max_age_delta', type=int, default=DEFAULT_MAX_AGE_DELTA, help='The maximum value in seconds added to max_age') args = parser.parse_args() set_logger(args.debug, logfile=args.logfile) sys.path.insert(0, os.getcwd()) # XXX target = resolve_name(args.target) if args.params is None: params = {} else: params = decode_params(args.params) logger.info('Worker registers at %s' % args.backend) logger.info('The heartbeat socket is at %r' % args.heartbeat) worker = Worker(target, backend=args.backend, heartbeat=args.heartbeat, register=args.register, params=params, timeout=args.timeout, max_age=args.max_age, max_age_delta=args.max_age_delta) try: worker.start() except KeyboardInterrupt: return 1 finally: worker.stop() return 0
backend=args.backend, heartbeat=args.heartbeat, register=args.register, receiver=args.receiver, publisher=args.publisher, io_threads=args.io_threads, db=args.db, dboptions=dboptions, web_root=args.web_root, ) except DuplicateBrokerError, e: logger.info("There is already a broker running on PID %s" % e) logger.info("Exiting") return 1 logger.info("Listening to incoming jobs at %r" % args.frontend) logger.info("Workers may register at %r" % args.backend) if args.heartbeat is not None: logger.info("The heartbeat socket is at %r" % args.heartbeat) try: broker.start() except KeyboardInterrupt: pass finally: broker.stop() return 0 if __name__ == "__main__": sys.exit(main())
def main(args=sys.argv): parser = argparse.ArgumentParser(description='Powerhose broker.') parser.add_argument('--frontend', dest='frontend', default=DEFAULT_FRONTEND, help="ZMQ socket to receive jobs.") parser.add_argument('--backend', dest='backend', default=DEFAULT_BACKEND, help="ZMQ socket for workers.") parser.add_argument('--heartbeat', dest='heartbeat', default=DEFAULT_HEARTBEAT, help="ZMQ socket for the heartbeat.") parser.add_argument('--register', dest='register', default=DEFAULT_REG, help="ZMQ socket for the registration.") parser.add_argument('--io-threads', type=int, default=DEFAULT_IOTHREADS, help="Number of I/O threads") parser.add_argument('--debug', action='store_true', default=False, help="Debug mode") parser.add_argument('--check', action='store_true', default=False, help=("Use this option to check if there's a running " " broker. Returns the PID if a broker is up.")) parser.add_argument('--purge-ghosts', action='store_true', default=False, help="Use this option to purge ghost brokers.") parser.add_argument('--logfile', dest='logfile', default='stdout', help="File to log in to .") args = parser.parse_args() set_logger(args.debug, logfile=args.logfile) if args.purge_ghosts: broker_pids, ghosts = kill_ghost_brokers(args.frontend) if broker_pids is None: logger.info('No running broker.') else: logger.info('The active broker runs at PID: %s' % broker_pids) if len(ghosts) == 0: logger.info('No ghosts where killed.') else: logger.info('Ghost(s) killed: %s' \ % ', '.join([str(g) for g in ghosts])) return 0 if args.check: pid = verify_broker(args.frontend) if pid is None: logger.info('There seem to be no broker on this endpoint') else: logger.info('A broker is running. PID: %s' % pid) return 0 logger.info('Starting the broker') try: broker = Broker(frontend=args.frontend, backend=args.backend, heartbeat=args.heartbeat, register=args.register, io_threads=args.io_threads) except DuplicateBrokerError, e: logger.info('There is already a broker running on PID %s' % e) logger.info('Exiting') return 1
def main(args=sys.argv): parser = argparse.ArgumentParser(description="Loads broker.") parser.add_argument("--frontend", dest="frontend", default=DEFAULT_FRONTEND, help="ZMQ socket to receive jobs.") parser.add_argument("--backend", dest="backend", default=DEFAULT_BACKEND, help="ZMQ socket for agents.") parser.add_argument("--heartbeat", dest="heartbeat", default=None, help="ZMQ socket for the heartbeat.") parser.add_argument("--register", dest="register", default=DEFAULT_REG, help="ZMQ socket for the registration.") parser.add_argument( "--receiver", dest="receiver", default=DEFAULT_BROKER_RECEIVER, help="ZMQ socket to receive events from the runners", ) parser.add_argument( "--publisher", dest="publisher", default=DEFAULT_PUBLISHER, help="ZMQ socket for the registration." ) parser.add_argument("--io-threads", type=int, default=DEFAULT_IOTHREADS, help="Number of I/O threads") parser.add_argument("--debug", action="store_true", default=False, help="Debug mode") parser.add_argument( "--check", action="store_true", default=False, help=("Use this option to check if there's a running " " broker. Returns the PID if a broker is up."), ) parser.add_argument("--logfile", dest="logfile", default="stdout", help="File to log in to.") parser.add_argument("--db", dest="db", default="python", help="Database backend.") parser.add_argument("--web-root", help="Root url of the web dashboard.", type=str, default=None) # add db args for backend, options in get_backends(): for option, default, help, type_ in options: option = "db_%s_%s" % (backend, option) kargs = {"dest": option, "default": default} if type_ is bool: kargs["action"] = "store_true" else: kargs["type"] = type_ option = option.replace("_", "-") parser.add_argument("--%s" % option, **kargs) args = parser.parse_args() set_logger(args.debug, logfile=args.logfile) if args.check: pid = verify_broker(args.frontend) if pid is None: logger.info("There seem to be no broker on this endpoint") else: logger.info("A broker is running. PID: %s" % pid) return 0 # grabbing the db options dboptions = {} prefix = "db_%s_" % args.db for key, value in args._get_kwargs(): if not key.startswith(prefix): continue dboptions[key[len(prefix) :]] = value logger.info("Starting the broker") try: broker = Broker( frontend=args.frontend, backend=args.backend, heartbeat=args.heartbeat, register=args.register, receiver=args.receiver, publisher=args.publisher, io_threads=args.io_threads, db=args.db, dboptions=dboptions, web_root=args.web_root, ) except DuplicateBrokerError, e: logger.info("There is already a broker running on PID %s" % e) logger.info("Exiting") return 1
def main(args=sys.argv): parser = argparse.ArgumentParser(description='Loads broker.') parser.add_argument('--frontend', dest='frontend', default=DEFAULT_FRONTEND, help="ZMQ socket to receive jobs.") parser.add_argument('--backend', dest='backend', default=DEFAULT_BACKEND, help="ZMQ socket for agents.") parser.add_argument('--heartbeat', dest='heartbeat', default=None, help="ZMQ socket for the heartbeat.") parser.add_argument('--register', dest='register', default=DEFAULT_REG, help="ZMQ socket for the registration.") parser.add_argument('--receiver', dest='receiver', default=DEFAULT_BROKER_RECEIVER, help="ZMQ socket to receive events from the runners") parser.add_argument('--publisher', dest='publisher', default=DEFAULT_PUBLISHER, help="ZMQ socket for the registration.") parser.add_argument('--io-threads', type=int, default=DEFAULT_IOTHREADS, help="Number of I/O threads") parser.add_argument('--debug', action='store_true', default=False, help="Debug mode") parser.add_argument('--check', action='store_true', default=False, help=("Use this option to check if there's a running " " broker. Returns the PID if a broker is up.")) parser.add_argument('--logfile', dest='logfile', default='stdout', help="File to log in to.") parser.add_argument('--db', dest='db', default='python', help="Database backend.") parser.add_argument('--web-root', help='Root url of the web dashboard.', type=str, default=None) # add db args for backend, options in get_backends(): for option, default, help, type_ in options: option = 'db_%s_%s' % (backend, option) kargs = {'dest': option, 'default': default} if type_ is bool: kargs['action'] = 'store_true' else: kargs['type'] = type_ option = option.replace('_', '-') parser.add_argument('--%s' % option, **kargs) args = parser.parse_args() set_logger(args.debug, logfile=args.logfile) if args.check: pid = verify_broker(args.frontend) if pid is None: logger.info('There seem to be no broker on this endpoint') else: logger.info('A broker is running. PID: %s' % pid) return 0 # grabbing the db options dboptions = {} prefix = 'db_%s_' % args.db for key, value in args._get_kwargs(): if not key.startswith(prefix): continue dboptions[key[len(prefix):]] = value logger.info('Starting the broker') try: broker = Broker(frontend=args.frontend, backend=args.backend, heartbeat=args.heartbeat, register=args.register, receiver=args.receiver, publisher=args.publisher, io_threads=args.io_threads, db=args.db, dboptions=dboptions, web_root=args.web_root) except DuplicateBrokerError, e: logger.info('There is already a broker running on PID %s' % e) logger.info('Exiting') return 1