def __init__(self, endpoint, context, loop, arbiter, check_delay=1.0): self.arbiter = arbiter self.endpoint = endpoint self.context = context self.loop = loop self.check_delay = check_delay * 1000 self.jobs = Queue() # initialize the sys handler self.sys_hdl = SysHandler(self) # get registered commands self.commands = get_commands()
def __init__(self, endpoint, multicast_endpoint, context, loop, arbiter, check_delay=1.0): self.arbiter = arbiter self.endpoint = endpoint self.multicast_endpoint = multicast_endpoint self.context = context self.loop = loop self.check_delay = check_delay * 1000 self.started = False self.jobs = Queue() # initialize the sys handler self.sys_hdl = SysHandler(self) # get registered commands self.commands = get_commands()
def __init__(self, endpoint, trainer, timeout=1.0, ipc_prefix=None): self.context = zmq.Context() self.skt = self.context.socket(zmq.REP) self.skt.bind(endpoint) # bind the socket to internal ipc. ipc_name = "circus-ipc-%s" % os.getpid() if not ipc_prefix: ipc_prefix = tempfile.gettempdir() ipc_path = os.path.join(os.path.dirname(ipc_prefix), ipc_name) self.skt.bind("ipc://%s" % ipc_path) self.poller = zmq.Poller() self.poller.register(self.skt, zmq.POLLIN) self.trainer = trainer self.timeout = timeout * 1000 # start the sys handler self.sys_hdl = SysHandler(ipc_path)
def _init_syshandler(self): self.sys_hdl = SysHandler(self)
class Controller(object): def __init__(self, endpoint, multicast_endpoint, context, loop, arbiter, check_delay=1.0, endpoint_owner=None): self.arbiter = arbiter self.caller = None self.endpoint = endpoint self.multicast_endpoint = multicast_endpoint self.context = context self.loop = loop self.check_delay = check_delay * 1000 self.endpoint_owner = endpoint_owner self.started = False self._managing_watchers_future = None # initialize the sys handler self._init_syshandler() # get registered commands self.commands = get_commands() def _init_syshandler(self): self.sys_hdl = SysHandler(self) def _init_stream(self): self.stream = zmqstream.ZMQStream(self.ctrl_socket, self.loop) self.stream.on_recv(self.handle_message) def _init_multicast_endpoint(self): multicast_addr, multicast_port = urlparse(self.multicast_endpoint)\ .netloc.split(':') try: self.udp_socket = create_udp_socket(multicast_addr, multicast_port) self.loop.add_handler(self.udp_socket.fileno(), self.handle_autodiscover_message, ioloop.IOLoop.READ) except (IOError, OSError, ValueError): message = ("Multicast discovery is disabled, there was an " "error during udp socket creation.") logger.warning(message, exc_info=True) @property def endpoint_owner_mode(self): return self.endpoint_owner is not None and \ self.endpoint.startswith('ipc://') def initialize(self): # initialize controller # Initialize ZMQ Sockets self.ctrl_socket = self.context.socket(zmq.ROUTER) self.ctrl_socket.bind(self.endpoint) self.ctrl_socket.linger = 0 # support chown'ing the zmq endpoint on unix platforms if self.endpoint_owner_mode: uid = to_uid(self.endpoint_owner) sockpath = self.endpoint[6:] # length of 'ipc://' prefix os.chown(sockpath, uid, -1) self._init_stream() # Initialize UDP Socket if self.multicast_endpoint: self._init_multicast_endpoint() def manage_watchers(self): if self._managing_watchers_future is not None: logger.debug("manage_watchers is already running...") return try: self._managing_watchers_future = self.arbiter.manage_watchers() self.loop.add_future(self._managing_watchers_future, self._manage_watchers_cb) except ConflictError: logger.debug("manage_watchers is conflicting with another command") def _manage_watchers_cb(self, future): self._managing_watchers_future = None def start(self): self.initialize() if self.check_delay > 0: # The specific case (check_delay < 0) # so with no period callback to manage_watchers # is probably "unit tests only" self.caller = ioloop.PeriodicCallback(self.manage_watchers, self.check_delay, self.loop) self.caller.start() self.started = True def stop(self): if self.started: if self.caller is not None: self.caller.stop() try: self.stream.flush() self.stream.close() except (IOError, zmq.ZMQError): pass self.ctrl_socket.close() self.sys_hdl.stop() def handle_message(self, raw_msg): cid, msg = raw_msg msg = msg.strip() if not msg: self.send_response(None, cid, msg, "error: empty command") else: logger.debug("got message %s", msg) self.dispatch((cid, msg)) def handle_autodiscover_message(self, fd_no, type): __, address = self.udp_socket.recvfrom(1024) self.udp_socket.sendto(json.dumps({'endpoint': self.endpoint}), address) def _dispatch_callback_future(self, msg, cid, mid, cast, cmd_name, send_resp, future): exception = check_future_exception_and_log(future) if exception is not None: if send_resp: self.send_error(mid, cid, msg, "server error", cast=cast, errno=errors.BAD_MSG_DATA_ERROR) else: resp = future.result() if send_resp: self._dispatch_callback(msg, cid, mid, cast, cmd_name, resp) def _dispatch_callback(self, msg, cid, mid, cast, cmd_name, resp=None): if resp is None: resp = ok() if not isinstance(resp, (dict, list)): msg = "msg %r tried to send a non-dict: %s" % (msg, str(resp)) logger.error("msg %r tried to send a non-dict: %s", msg, str(resp)) return self.send_error(mid, cid, msg, "server error", cast=cast, errno=errors.BAD_MSG_DATA_ERROR) if isinstance(resp, list): resp = {"results": resp} self.send_ok(mid, cid, msg, resp, cast=cast) if cmd_name.lower() == "quit": if cid is not None: self.stream.flush() def dispatch(self, job, future=None): cid, msg = job try: json_msg = json.loads(msg) except ValueError: return self.send_error(None, cid, msg, "json invalid", errno=errors.INVALID_JSON) mid = json_msg.get('id') cmd_name = json_msg.get('command') properties = json_msg.get('properties', {}) cast = json_msg.get('msg_type') == "cast" try: cmd = self.commands[cmd_name.lower()] except KeyError: error_ = "unknown command: %r" % cmd_name return self.send_error(mid, cid, msg, error_, cast=cast, errno=errors.UNKNOWN_COMMAND) try: cmd.validate(properties) resp = cmd.execute(self.arbiter, properties) if isinstance(resp, Future): if properties.get('waiting', False): cb = functools.partial(self._dispatch_callback_future, msg, cid, mid, cast, cmd_name, True) resp.add_done_callback(cb) else: cb = functools.partial(self._dispatch_callback_future, msg, cid, mid, cast, cmd_name, False) resp.add_done_callback(cb) self._dispatch_callback(msg, cid, mid, cast, cmd_name, None) else: self._dispatch_callback(msg, cid, mid, cast, cmd_name, resp) except MessageError as e: return self.send_error(mid, cid, msg, str(e), cast=cast, errno=errors.MESSAGE_ERROR) except ConflictError as e: if self._managing_watchers_future is not None: logger.debug("the command conflicts with running " "manage_watchers, re-executing it at " "the end") cb = functools.partial(self.dispatch, job) self.loop.add_future(self._managing_watchers_future, cb) return # conflicts between two commands, sending error... return self.send_error(mid, cid, msg, str(e), cast=cast, errno=errors.COMMAND_ERROR) except OSError as e: return self.send_error(mid, cid, msg, str(e), cast=cast, errno=errors.OS_ERROR) except: exctype, value = sys.exc_info()[:2] tb = traceback.format_exc() reason = "command %r: %s" % (msg, value) logger.debug("error: command %r: %s\n\n%s", msg, value, tb) return self.send_error(mid, cid, msg, reason, tb, cast=cast, errno=errors.COMMAND_ERROR) def send_error(self, mid, cid, msg, reason="unknown", tb=None, cast=False, errno=errors.NOT_SPECIFIED): resp = error(reason=reason, tb=tb, errno=errno) self.send_response(mid, cid, msg, resp, cast=cast) def send_ok(self, mid, cid, msg, props=None, cast=False): resp = ok(props) self.send_response(mid, cid, msg, resp, cast=cast) def send_response(self, mid, cid, msg, resp, cast=False): if cast: return if cid is None: return if isinstance(resp, string_types): raise DeprecationWarning('Takes only a mapping') resp['id'] = mid resp = json.dumps(resp) logger.debug("sending response %s", resp) try: self.stream.send(cid, zmq.SNDMORE) self.stream.send(resp) except (IOError, zmq.ZMQError) as e: logger.debug("Received %r - Could not send back %r - %s", msg, resp, str(e))
class Controller(object): def __init__(self, endpoint, multicast_endpoint, context, loop, arbiter, check_delay=1.0, endpoint_owner=None): self.arbiter = arbiter self.caller = None self.endpoint = endpoint self.multicast_endpoint = multicast_endpoint self.context = context self.loop = loop self.check_delay = check_delay * 1000 self.endpoint_owner = endpoint_owner self.started = False self._managing_watchers_future = None # initialize the sys handler self._init_syshandler() # get registered commands self.commands = get_commands() def _init_syshandler(self): self.sys_hdl = SysHandler(self) def _init_stream(self): self.stream = zmqstream.ZMQStream(self.ctrl_socket, self.loop) self.stream.on_recv(self.handle_message) def _init_multicast_endpoint(self): multicast_addr, multicast_port = urlparse(self.multicast_endpoint)\ .netloc.split(':') try: self.udp_socket = create_udp_socket(multicast_addr, multicast_port) self.loop.add_handler(self.udp_socket.fileno(), self.handle_autodiscover_message, ioloop.IOLoop.READ) except (IOError, OSError, ValueError): message = ("Multicast discovery is disabled, there was an " "error during udp socket creation.") logger.warning(message, exc_info=True) @property def endpoint_owner_mode(self): return self.endpoint_owner is not None and \ self.endpoint.startswith('ipc://') def initialize(self): # initialize controller # Initialize ZMQ Sockets self.ctrl_socket = self.context.socket(zmq.ROUTER) self.ctrl_socket.bind(self.endpoint) self.ctrl_socket.linger = 0 # support chown'ing the zmq endpoint on unix platforms if self.endpoint_owner_mode: uid = to_uid(self.endpoint_owner) sockpath = self.endpoint[6:] # length of 'ipc://' prefix os.chown(sockpath, uid, -1) self._init_stream() # Initialize UDP Socket if self.multicast_endpoint: self._init_multicast_endpoint() def manage_watchers(self): if self._managing_watchers_future is not None: logger.debug("manage_watchers is already running...") return try: self._managing_watchers_future = self.arbiter.manage_watchers() self.loop.add_future(self._managing_watchers_future, self._manage_watchers_cb) except ConflictError: logger.debug("manage_watchers is conflicting with another command") def _manage_watchers_cb(self, future): self._managing_watchers_future = None def start(self): self.initialize() if self.check_delay > 0: # The specific case (check_delay < 0) # so with no period callback to manage_watchers # is probably "unit tests only" self.caller = ioloop.PeriodicCallback(self.manage_watchers, self.check_delay, self.loop) self.caller.start() self.started = True def stop(self): if self.started: if self.caller is not None: self.caller.stop() try: self.stream.flush() self.stream.close() except (IOError, zmq.ZMQError): pass self.ctrl_socket.close() self.sys_hdl.stop() def handle_message(self, raw_msg): cid, msg = raw_msg msg = msg.strip() if not msg: self.send_response(None, cid, msg, "error: empty command") else: logger.debug("got message %s", msg) self.dispatch((cid, msg)) def handle_autodiscover_message(self, fd_no, type): __, address = self.udp_socket.recvfrom(1024) self.udp_socket.sendto(json.dumps({'endpoint': self.endpoint}), address) def _dispatch_callback_future(self, msg, cid, mid, cast, cmd_name, send_resp, future): exception = check_future_exception_and_log(future) if exception is not None: if send_resp: self.send_error(mid, cid, msg, "server error", cast=cast, errno=errors.BAD_MSG_DATA_ERROR) else: resp = future.result() if send_resp: self._dispatch_callback(msg, cid, mid, cast, cmd_name, resp) def _dispatch_callback(self, msg, cid, mid, cast, cmd_name, resp=None): if resp is None: resp = ok() if not isinstance(resp, (dict, list)): msg = "msg %r tried to send a non-dict: %s" % (msg, str(resp)) logger.error("msg %r tried to send a non-dict: %s", msg, str(resp)) return self.send_error(mid, cid, msg, "server error", cast=cast, errno=errors.BAD_MSG_DATA_ERROR) if isinstance(resp, list): resp = {"results": resp} self.send_ok(mid, cid, msg, resp, cast=cast) if cmd_name.lower() == "quit": if cid is not None: self.stream.flush() self.arbiter.stop() def dispatch(self, job, future=None): cid, msg = job try: json_msg = json.loads(msg) except ValueError: return self.send_error(None, cid, msg, "json invalid", errno=errors.INVALID_JSON) mid = json_msg.get('id') cmd_name = json_msg.get('command') properties = json_msg.get('properties', {}) cast = json_msg.get('msg_type') == "cast" try: cmd = self.commands[cmd_name.lower()] except KeyError: error_ = "unknown command: %r" % cmd_name return self.send_error(mid, cid, msg, error_, cast=cast, errno=errors.UNKNOWN_COMMAND) try: cmd.validate(properties) resp = cmd.execute(self.arbiter, properties) if isinstance(resp, Future): if properties.get('waiting', False): cb = functools.partial(self._dispatch_callback_future, msg, cid, mid, cast, cmd_name, True) resp.add_done_callback(cb) else: cb = functools.partial(self._dispatch_callback_future, msg, cid, mid, cast, cmd_name, False) resp.add_done_callback(cb) self._dispatch_callback(msg, cid, mid, cast, cmd_name, None) else: self._dispatch_callback(msg, cid, mid, cast, cmd_name, resp) except MessageError as e: return self.send_error(mid, cid, msg, str(e), cast=cast, errno=errors.MESSAGE_ERROR) except ConflictError as e: if self._managing_watchers_future is not None: logger.debug("the command conflicts with running " "manage_watchers, re-executing it at " "the end") cb = functools.partial(self.dispatch, job) self.loop.add_future(self._managing_watchers_future, cb) return # conflicts between two commands, sending error... return self.send_error(mid, cid, msg, str(e), cast=cast, errno=errors.COMMAND_ERROR) except OSError as e: return self.send_error(mid, cid, msg, str(e), cast=cast, errno=errors.OS_ERROR) except: exctype, value = sys.exc_info()[:2] tb = traceback.format_exc() reason = "command %r: %s" % (msg, value) logger.debug("error: command %r: %s\n\n%s", msg, value, tb) return self.send_error(mid, cid, msg, reason, tb, cast=cast, errno=errors.COMMAND_ERROR) def send_error(self, mid, cid, msg, reason="unknown", tb=None, cast=False, errno=errors.NOT_SPECIFIED): resp = error(reason=reason, tb=tb, errno=errno) self.send_response(mid, cid, msg, resp, cast=cast) def send_ok(self, mid, cid, msg, props=None, cast=False): resp = ok(props) self.send_response(mid, cid, msg, resp, cast=cast) def send_response(self, mid, cid, msg, resp, cast=False): if cast: return if cid is None: return if isinstance(resp, string_types): raise DeprecationWarning('Takes only a mapping') resp['id'] = mid resp = json.dumps(resp) try: self.stream.send(cid, zmq.SNDMORE) self.stream.send(resp) except (IOError, zmq.ZMQError) as e: logger.debug("Received %r - Could not send back %r - %s", msg, resp, str(e))
class Controller(object): def __init__(self, endpoint, multicast_endpoint, context, loop, arbiter, check_delay=1.0): self.arbiter = arbiter self.endpoint = endpoint self.multicast_endpoint = multicast_endpoint self.context = context self.loop = loop self.check_delay = check_delay * 1000 self.started = False # initialize the sys handler self._init_syshandler() # get registered commands self.commands = get_commands() def _init_syshandler(self): self.sys_hdl = SysHandler(self) def _init_stream(self): self.stream = zmqstream.ZMQStream(self.ctrl_socket, self.loop) self.stream.on_recv(self.handle_message) def initialize(self): # initialize controller # Initialize ZMQ Sockets self.ctrl_socket = self.context.socket(zmq.ROUTER) self.ctrl_socket.bind(self.endpoint) self.ctrl_socket.linger = 0 self._init_stream() # Initialize UDP Socket if self.multicast_endpoint: multicast_addr, multicast_port = urlparse(self.multicast_endpoint)\ .netloc.split(':') self.udp_socket = create_udp_socket(multicast_addr, multicast_port) self.loop.add_handler(self.udp_socket.fileno(), self.handle_autodiscover_message, ioloop.IOLoop.READ) def start(self): self.initialize() self.caller = ioloop.PeriodicCallback(self.arbiter.manage_watchers, self.check_delay, self.loop) self.caller.start() self.started = True def stop(self): if self.started: self.caller.stop() try: self.stream.flush() self.stream.close() except (IOError, zmq.ZMQError): pass self.ctrl_socket.close() self.sys_hdl.stop() def handle_message(self, raw_msg): cid, msg = raw_msg msg = msg.strip() if not msg: self.send_response(cid, msg, "error: empty command") else: logger.debug("got message %s", msg) self.add_job(cid, msg) def add_job(self, cid, msg): # using a single argument to stay compatible w/ pyzmq <= 13.0.0 self.loop.add_callback(functools.partial(self.dispatch, (cid, msg))) def handle_autodiscover_message(self, fd_no, type): data, address = self.udp_socket.recvfrom(1024) data = json.loads(data) self.udp_socket.sendto(json.dumps({'endpoint': self.endpoint}), address) def dispatch(self, job): cid, msg = job try: json_msg = json.loads(msg) except ValueError: return self.send_error(cid, msg, "json invalid", errno=errors.INVALID_JSON) cmd_name = json_msg.get('command') properties = json_msg.get('properties', {}) cast = json_msg.get('msg_type') == "cast" try: cmd = self.commands[cmd_name.lower()] except KeyError: error_ = "unknown command: %r" % cmd_name return self.send_error(cid, msg, error_, cast=cast, errno=errors.UNKNOWN_COMMAND) try: cmd.validate(properties) resp = cmd.execute(self.arbiter, properties) except MessageError as e: return self.send_error(cid, msg, str(e), cast=cast, errno=errors.MESSAGE_ERROR) except OSError as e: return self.send_error(cid, msg, str(e), cast=cast, errno=errors.OS_ERROR) except: exctype, value = sys.exc_info()[:2] tb = traceback.format_exc() reason = "command %r: %s" % (msg, value) logger.debug("error: command %r: %s\n\n%s", msg, value, tb) return self.send_error(cid, msg, reason, tb, cast=cast, errno=errors.COMMAND_ERROR) if resp is None: resp = ok() if not isinstance(resp, ( dict, list, )): msg = "msg %r tried to send a non-dict: %s" % (msg, str(resp)) logger.error("msg %r tried to send a non-dict: %s", msg, str(resp)) return self.send_error(cid, msg, "server error", cast=cast, errno=errors.BAD_MSG_DATA_ERROR) if isinstance(resp, list): resp = {"results": resp} self.send_ok(cid, msg, resp, cast=cast) if cmd_name.lower() == "quit": if cid is not None: self.stream.flush() self.arbiter.stop() def send_error(self, cid, msg, reason="unknown", tb=None, cast=False, errno=errors.NOT_SPECIFIED): resp = error(reason=reason, tb=tb, errno=errno) self.send_response(cid, msg, resp, cast=cast) def send_ok(self, cid, msg, props=None, cast=False): resp = ok(props) self.send_response(cid, msg, resp, cast=cast) def send_response(self, cid, msg, resp, cast=False): if cast: return if cid is None: return if not isinstance(resp, string_types): resp = json.dumps(resp) if isinstance(resp, unicode): resp = resp.encode('utf8') try: self.stream.send(cid, zmq.SNDMORE) self.stream.send(resp) except zmq.ZMQError as e: logger.debug("Received %r - Could not send back %r - %s", msg, resp, str(e))
class Controller(object): def __init__(self, endpoint, multicast_endpoint, context, loop, arbiter, check_delay=1.0): self.arbiter = arbiter self.endpoint = endpoint self.multicast_endpoint = multicast_endpoint self.context = context self.loop = loop self.check_delay = check_delay * 1000 self.started = False self.jobs = Queue() # initialize the sys handler self.sys_hdl = SysHandler(self) # get registered commands self.commands = get_commands() def _init_stream(self): self.stream = zmqstream.ZMQStream(self.ctrl_socket, self.loop) self.stream.on_recv(self.handle_message) def initialize(self): # initialize controller # Initialize ZMQ Sockets self.ctrl_socket = self.context.socket(zmq.ROUTER) self.ctrl_socket.bind(self.endpoint) self.ctrl_socket.linger = 0 self._init_stream() # Initialize UDP Socket multicast_addr, multicast_port = urlparse(self.multicast_endpoint)\ .netloc.split(':') self.udp_socket = create_udp_socket(multicast_addr, multicast_port) self.loop.add_handler(self.udp_socket.fileno(), self.handle_autodiscover_message, ioloop.IOLoop.READ) def start(self): self.initialize() self.caller = ioloop.PeriodicCallback(self.wakeup, self.check_delay, self.loop) self.caller.start() self.started = True def stop(self): if self.started: self.caller.stop() try: self.stream.flush() self.stream.close() except (IOError, zmq.ZMQError): pass self.ctrl_socket.close() self.sys_hdl.stop() def wakeup(self): job = None try: job = self.jobs.get(block=False) except Empty: pass if job is not None: self.dispatch(job) self.arbiter.manage_watchers() def add_job(self, cid, msg): self.jobs.put((cid, msg), False) self.wakeup() def handle_message(self, raw_msg): cid, msg = raw_msg msg = msg.strip() if not msg: self.send_response(cid, msg, "error: empty command") else: logger.debug("got message %s", msg) self.add_job(cid, msg) def handle_autodiscover_message(self, fd_no, type): data, address = self.udp_socket.recvfrom(1024) data = json.loads(data) self.udp_socket.sendto(json.dumps({'endpoint': self.endpoint}), address) def dispatch(self, job): cid, msg = job try: json_msg = json.loads(msg) except ValueError: return self.send_error(cid, msg, "json invalid", errno=errors.INVALID_JSON) cmd_name = json_msg.get('command') properties = json_msg.get('properties', {}) cast = json_msg.get('msg_type') == "cast" try: cmd = self.commands[cmd_name.lower()] except KeyError: error_ = "unknown command: %r" % cmd_name return self.send_error(cid, msg, error_, cast=cast, errno=errors.UNKNOWN_COMMAND) try: cmd.validate(properties) resp = cmd.execute(self.arbiter, properties) except MessageError as e: return self.send_error(cid, msg, str(e), cast=cast, errno=errors.MESSAGE_ERROR) except OSError as e: return self.send_error(cid, msg, str(e), cast=cast, errno=errors.OS_ERROR) except: exctype, value = sys.exc_info()[:2] tb = traceback.format_exc() reason = "command %r: %s" % (msg, value) logger.debug("error: command %r: %s\n\n%s", msg, value, tb) return self.send_error(cid, msg, reason, tb, cast=cast, errno=errors.COMMAND_ERROR) if resp is None: resp = ok() if not isinstance(resp, (dict, list,)): msg = "msg %r tried to send a non-dict: %s" % (msg, str(resp)) logger.error("msg %r tried to send a non-dict: %s", msg, str(resp)) return self.send_error(cid, msg, "server error", cast=cast, errno=errors.BAD_MSG_DATA_ERROR) if isinstance(resp, list): resp = {"results": resp} self.send_ok(cid, msg, resp, cast=cast) if cmd_name.lower() == "quit": if cid is not None: self.stream.flush() self.arbiter.stop() def send_error(self, cid, msg, reason="unknown", tb=None, cast=False, errno=errors.NOT_SPECIFIED): resp = error(reason=reason, tb=tb, errno=errno) self.send_response(cid, msg, resp, cast=cast) def send_ok(self, cid, msg, props=None, cast=False): resp = ok(props) self.send_response(cid, msg, resp, cast=cast) def send_response(self, cid, msg, resp, cast=False): if cast: return if cid is None: return if not isinstance(resp, string_types): resp = json.dumps(resp) if isinstance(resp, unicode): resp = resp.encode('utf8') try: self.stream.send(cid, zmq.SNDMORE) self.stream.send(resp) except zmq.ZMQError as e: logger.debug("Received %r - Could not send back %r - %s", msg, resp, str(e))