Esempio n. 1
0
    def test_copy_env(self):
        old_environ = os.environ
        try:
            os.environ = {'COCONUTS': 'MIGRATE'}
            watcher = Watcher("foo", "foobar", copy_env=True)
            self.assertEqual(watcher.env, os.environ)

            watcher = Watcher("foo", "foobar", copy_env=True,
                              env={"AWESOMENESS": "YES"})
            self.assertEqual(watcher.env,
                             {'COCONUTS': 'MIGRATE', 'AWESOMENESS': 'YES'})
        finally:
            os.environ = old_environ
Esempio n. 2
0
    def __init__(self,
                 watchers,
                 endpoint,
                 pubsub_endpoint,
                 check_delay=1.,
                 prereload_fn=None,
                 context=None,
                 loop=None,
                 stats_endpoint=None,
                 plugins=None,
                 sockets=None):
        self.watchers = watchers
        self.endpoint = endpoint
        self.check_delay = check_delay
        self.prereload_fn = prereload_fn
        self.pubsub_endpoint = pubsub_endpoint

        # initialize zmq context
        self.context = context or zmq.Context.instance()
        self.loop = loop or ioloop.IOLoop()
        self.ctrl = Controller(endpoint, self.context, self.loop, self,
                               check_delay)

        self.pid = os.getpid()
        self._watchers_names = {}
        self.alive = True
        self._lock = RLock()

        # initializing circusd-stats as a watcher when configured
        self.stats_endpoint = stats_endpoint
        if self.stats_endpoint is not None:
            cmd = "%s -c 'from circus import stats; stats.main()'" % \
                        sys.executable
            cmd += ' --endpoint %s' % self.endpoint
            cmd += ' --pubsub %s' % self.pubsub_endpoint
            cmd += ' --statspoint %s' % self.stats_endpoint
            stats_watcher = Watcher('circusd-stats', cmd)
            self.watchers.append(stats_watcher)

        # adding each plugin as a watcher
        if plugins is not None:
            for plugin in plugins:
                fqnd = plugin['use']
                name = 'plugin:%s' % fqnd.replace('.', '-')
                cmd = get_plugin_cmd(plugin, self.endpoint,
                                     self.pubsub_endpoint, self.check_delay)
                plugin_watcher = Watcher(name, cmd, priority=1, singleton=True)
                self.watchers.append(plugin_watcher)

        self.sockets = CircusSockets(sockets)
Esempio n. 3
0
 def test_copy_path(self):
     stream = QueueStream()
     qstream = {'stream': stream}
     old_environ = os.environ
     old_paths = sys.path[:]
     try:
         sys.path = ['XYZ']
         os.environ = {'COCONUTS': 'MIGRATE'}
         cmd = ('%s -c "import sys; '
                'sys.stdout.write(\':\'.join(sys.path)); '
                ' sys.stdout.flush()"') % sys.executable
         watcher = Watcher('xx',
                           cmd,
                           copy_env=True,
                           copy_path=True,
                           stdout_stream=qstream)
         watcher.start()
         time.sleep(3.)
         watcher.stop()
         data = [v for k, v in stream.get().items()][1]
         data = ''.join(data)
         self.assertTrue('XYZ' in data, data)
     finally:
         os.environ = old_environ
         sys.path[:] = old_paths
Esempio n. 4
0
    def run(self):
        if self.stream:
            qstream = {'stream': self.stream}
        else:
            qstream = None

        old_environ = os.environ
        old_paths = sys.path[:]
        try:
            sys.path = ['XYZ']
            os.environ = {'COCONUTS': 'MIGRATE'}
            cmd = ('%s -c "import sys; '
                   'sys.stdout.write(\':\'.join(sys.path)); '
                   ' sys.stdout.flush()"') % PYTHON

            self.watcher = Watcher('xx',
                                   cmd,
                                   copy_env=True,
                                   copy_path=True,
                                   stdout_stream=qstream,
                                   loop=self.loop,
                                   **self.kw)
            yield self.watcher.start()
        finally:
            os.environ = old_environ
            sys.path[:] = old_paths
Esempio n. 5
0
    def test_stopping_a_watcher_doesnt_spawn(self):
        watcher = Watcher("foo",
                          "foobar",
                          respawn=True,
                          numprocesses=3,
                          graceful_timeout=0)
        watcher._status = "started"

        watcher.spawn_processes = MagicMockFuture()
        watcher.send_signal = mock.MagicMock()

        # We have one running process and a dead one.
        watcher.processes = {
            1234: FakeProcess(1234, status=RUNNING),
            1235: FakeProcess(1235, status=RUNNING)
        }

        # When we call manage_process(), the watcher should try to spawn a new
        # process since we aim to have 3 of them.
        yield watcher.manage_processes()
        self.assertTrue(watcher.spawn_processes.called)
        # Now, we want to stop everything.
        watcher.processes = {
            1234: FakeProcess(1234, status=RUNNING),
            1235: FakeProcess(1235, status=RUNNING)
        }
        watcher.spawn_processes.reset_mock()
        yield watcher.stop()
        yield watcher.manage_processes()
        # And be sure we don't spawn new processes in the meantime.
        self.assertFalse(watcher.spawn_processes.called)
Esempio n. 6
0
def create_watcher(beam):
    """
    creates a global watcher object for a specified beam

    Parameters:
    beam (int): the beam number to make a watcher 
    """
    global watcher
    watcher = Watcher(
        'cheeta',
        f'/home/artemis/development/arecibo/dev/build/linux/gcc/release/work/arecibo/alfaburst_16bit --config /home/artemis/configs/beam{beam}.xml -p empty -s udp'
    )
Esempio n. 7
0
    def test_hook_in_PYTHON_PATH(self):
        # we have a hook in PYTHONPATH
        tempdir = self.get_tmpdir()

        hook = 'def hook(*args, **kw):\n    return True\n'
        with open(os.path.join(tempdir, 'plugins.py'), 'w') as f:
            f.write(hook)

        old_environ = os.environ
        try:
            os.environ = {'PYTHONPATH': tempdir}
            hooks = {'before_start': ('plugins.hook', False)}

            watcher = Watcher("foo", "foobar", copy_env=True, hooks=hooks)

            self.assertEqual(watcher.env, os.environ)
        finally:
            os.environ = old_environ
Esempio n. 8
0
    def add_watcher(self, name, cmd, **kw):
        """Adds a watcher.

        Options:

        - **name**: name of the watcher to add
        - **cmd**: command to run.
        - all other options defined in the Watcher constructor.
        """
        if name in self._watchers_names:
            raise AlreadyExist("%r already exist" % name)

        if not name:
            return ValueError("command name shouldn't be empty")

        watcher = Watcher(name, cmd, **kw)
        watcher.initialize(self.evpub_socket, self.sockets)
        self.watchers.append(watcher)
        self._watchers_names[watcher.name.lower()] = watcher
        return watcher
Esempio n. 9
0
    def run(self):
        qstream = {'stream': self.stream}
        old_environ = os.environ
        old_paths = sys.path[:]
        try:
            sys.path = ['XYZ']
            os.environ = {'COCONUTS': 'MIGRATE'}
            cmd = ('%s -c "import sys; '
                   'sys.stdout.write(\':\'.join(sys.path)); '
                   ' sys.stdout.flush()"') % sys.executable

            self.loop = ioloop.IOLoop()
            self.watcher = Watcher('xx', cmd, copy_env=True, copy_path=True,
                                   stdout_stream=qstream, loop=self.loop,
                                   **self.kw)
            self.watcher.start()
            self.loop.start()
        finally:
            os.environ = old_environ
            sys.path[:] = old_paths
Esempio n. 10
0
    def __init__(self,
                 watchers,
                 endpoint,
                 pubsub_endpoint,
                 check_delay=1.,
                 prereload_fn=None,
                 context=None,
                 loop=None,
                 check_flapping=True,
                 stats_endpoint=None):
        self.watchers = watchers
        self.endpoint = endpoint
        self.check_delay = check_delay
        self.prereload_fn = prereload_fn
        self.pubsub_endpoint = pubsub_endpoint

        # initialize zmq context
        self.context = context or zmq.Context.instance()
        self.loop = loop or ioloop.IOLoop()
        self.ctrl = Controller(endpoint, self.context, self.loop, self,
                               check_delay)

        self.pid = os.getpid()
        self._watchers_names = {}
        self.alive = True
        self.busy = False
        self.check_flapping = check_flapping

        # initializing circusd-stats as a watcher when configured
        self.stats_endpoint = stats_endpoint
        if self.stats_endpoint is not None:
            cmd = "%s -c 'from circus import stats; stats.main()'" % \
                        sys.executable
            cmd += ' --endpoint %s' % self.endpoint
            cmd += ' --pubsub %s' % self.pubsub_endpoint
            cmd += ' --statspoint %s' % self.stats_endpoint
            stats_watcher = Watcher('circusd-stats', cmd)
            self.watchers.append(stats_watcher)
Esempio n. 11
0
    def __init__(self,
                 watchers,
                 endpoint,
                 pubsub_endpoint,
                 check_delay=1.0,
                 prereload_fn=None,
                 context=None,
                 loop=None,
                 statsd=False,
                 stats_endpoint=None,
                 statsd_close_outputs=False,
                 multicast_endpoint=None,
                 plugins=None,
                 sockets=None,
                 warmup_delay=0,
                 httpd=False,
                 httpd_host='localhost',
                 httpd_port=8080,
                 httpd_close_outputs=False,
                 debug=False,
                 debug_gc=False,
                 ssh_server=None,
                 proc_name='circusd',
                 pidfile=None,
                 loglevel=None,
                 logoutput=None,
                 fqdn_prefix=None,
                 umask=None,
                 endpoint_owner=None):

        self.watchers = watchers
        self.endpoint = endpoint
        self.check_delay = check_delay
        self.prereload_fn = prereload_fn
        self.pubsub_endpoint = pubsub_endpoint
        self.multicast_endpoint = multicast_endpoint
        self.proc_name = proc_name
        self.ssh_server = ssh_server
        self.evpub_socket = None
        self.pidfile = pidfile
        self.loglevel = loglevel
        self.logoutput = logoutput
        self.umask = umask
        self.endpoint_owner = endpoint_owner

        try:
            # getfqdn appears to fail in Python3.3 in the unittest
            # framework so fall back to gethostname
            socket_fqdn = socket.getfqdn()
        except KeyError:
            socket_fqdn = socket.gethostname()
        if fqdn_prefix is None:
            fqdn = socket_fqdn
        else:
            fqdn = '{}@{}'.format(fqdn_prefix, socket_fqdn)
        self.fqdn = fqdn

        self.ctrl = self.loop = None
        self._provided_loop = False
        self.socket_event = False
        if loop is not None:
            self._provided_loop = True
            self.loop = loop

        # initialize zmq context
        self._init_context(context)
        self.pid = os.getpid()
        self._watchers_names = {}
        self._stopping = False
        self._restarting = False
        self.debug = debug
        self._exclusive_running_command = None
        if self.debug:
            self.stdout_stream = self.stderr_stream = {'class': 'StdoutStream'}
        else:
            self.stdout_stream = self.stderr_stream = None

        self.debug_gc = debug_gc
        if debug_gc:
            gc.set_debug(gc.DEBUG_LEAK)

        # initializing circusd-stats as a watcher when configured
        self.statsd = statsd
        self.stats_endpoint = stats_endpoint

        if self.statsd:
            cmd = "%s -c 'from circus import stats; stats.main()'" % \
                sys.executable
            cmd += ' --endpoint %s' % self.endpoint
            cmd += ' --pubsub %s' % self.pubsub_endpoint
            cmd += ' --statspoint %s' % self.stats_endpoint
            if ssh_server is not None:
                cmd += ' --ssh %s' % ssh_server
            if debug:
                cmd += ' --log-level DEBUG'
            stats_watcher = Watcher('circusd-stats',
                                    cmd,
                                    use_sockets=True,
                                    singleton=True,
                                    stdout_stream=self.stdout_stream,
                                    stderr_stream=self.stderr_stream,
                                    copy_env=True,
                                    copy_path=True,
                                    close_child_stderr=statsd_close_outputs,
                                    close_child_stdout=statsd_close_outputs)

            self.watchers.append(stats_watcher)

        # adding the httpd
        if httpd:
            # adding the socket
            httpd_socket = CircusSocket(name='circushttpd',
                                        host=httpd_host,
                                        port=httpd_port)
            if sockets is None:
                sockets = [httpd_socket]
            else:
                sockets.append(httpd_socket)

            cmd = ("%s -c 'from circusweb import circushttpd; "
                   "circushttpd.main()'") % sys.executable
            cmd += ' --endpoint %s' % self.endpoint
            cmd += ' --fd $(circus.sockets.circushttpd)'
            if ssh_server is not None:
                cmd += ' --ssh %s' % ssh_server

            # Adding the watcher
            httpd_watcher = Watcher('circushttpd',
                                    cmd,
                                    use_sockets=True,
                                    singleton=True,
                                    stdout_stream=self.stdout_stream,
                                    stderr_stream=self.stderr_stream,
                                    copy_env=True,
                                    copy_path=True,
                                    close_child_stderr=httpd_close_outputs,
                                    close_child_stdout=httpd_close_outputs)
            self.watchers.append(httpd_watcher)

        # adding each plugin as a watcher
        ch_stderr = self.stderr_stream is None
        ch_stdout = self.stdout_stream is None

        if plugins is not None:
            for plugin in plugins:
                fqn = plugin['use']
                cmd = get_plugin_cmd(plugin,
                                     self.endpoint,
                                     self.pubsub_endpoint,
                                     self.check_delay,
                                     ssh_server,
                                     debug=self.debug)
                plugin_cfg = dict(cmd=cmd,
                                  priority=1,
                                  singleton=True,
                                  stdout_stream=self.stdout_stream,
                                  stderr_stream=self.stderr_stream,
                                  copy_env=True,
                                  copy_path=True,
                                  close_child_stderr=ch_stderr,
                                  close_child_stdout=ch_stdout)
                plugin_cfg.update(plugin)
                if 'name' not in plugin_cfg:
                    plugin_cfg['name'] = fqn

                plugin_watcher = Watcher.load_from_config(plugin_cfg)
                self.watchers.append(plugin_watcher)

        self.sockets = CircusSockets(sockets)
        self.warmup_delay = warmup_delay
Esempio n. 12
0
def main():
    #configure_logger(logger, 'DEBUG')
    config_mod = 'circus_settings'
    if len(sys.argv) > 1:
        config_mod = sys.argv[1]
    
    config = import_module(config_mod)
    
    
    for p in config.PATHS:
        ap = os.path.abspath(p)
        if ap not in os.sys.path:
            os.sys.path.append(ap)

    watchers = []
    sockets = []

    for s in config.SERVERS:
        
        w = Watcher(gc(s, SERVER_NAME), 
                    gc(s, SERVER_PROGRAM), 
                    gc(s, SERVER_ARGS),
                    numprocesses=gc(s, SERVER_WORKERS, 1), 
                    working_dir=gc(s, SERVER_WORKING_DIR, './'),
                    env=gc(s, SERVER_ENV, dict()),
                    copy_env=True, 
                    copy_path=True,
                    use_sockets=True)
        
        watchers.append(w)
        
        sock_port = gc(s, SERVER_PORT)
        if sock_port is not None:
            sock_name = gc(s, SERVER_NAME)
            sock_host = gc(s, SERVER_HOST, '127.0.0.1')
            sock = CircusSocket(sock_name, host=sock_host, port=sock_port)
            sockets.append(sock)
        
    for sock in sockets:
        print '>> %s'%(sock,)

    try:
        WANT_WEB = getattr(config, 'WANT_WEB')
    except Exception:
        WANT_WEB = True

    if HAS_WEB and WANT_WEB:
        arbiter = Arbiter(watchers, DEFAULT_ENDPOINT_DEALER, DEFAULT_ENDPOINT_SUB, 
                          sockets=sockets,
                        stats_endpoint=DEFAULT_ENDPOINT_STATS, 
                        multicast_endpoint=DEFAULT_ENDPOINT_MULTICAST, 
                        statsd=True, 
                        httpd=True,
                        httpd_port=9999)
    else:
        arbiter = Arbiter(watchers, DEFAULT_ENDPOINT_DEALER, DEFAULT_ENDPOINT_SUB,
                          sockets=sockets,
                        stats_endpoint=DEFAULT_ENDPOINT_STATS, 
                        multicast_endpoint=DEFAULT_ENDPOINT_MULTICAST)

    arbiter.start()
Esempio n. 13
0
    def __init__(self, watchers, endpoint, pubsub_endpoint, check_delay=.5,
                 prereload_fn=None, context=None, loop=None,
                 stats_endpoint=None, plugins=None, sockets=None,
                 warmup_delay=0, httpd=False, httpd_host='localhost',
                 httpd_port=8080, debug=False, ssh_server=None,
                 proc_name='circusd'):
        self.watchers = watchers
        self.endpoint = endpoint
        self.check_delay = check_delay
        self.prereload_fn = prereload_fn
        self.pubsub_endpoint = pubsub_endpoint
        self.proc_name = proc_name

        self.ctrl = self.loop = None
        self.socket_event = False

        # initialize zmq context
        self.context = context or zmq.Context.instance()
        self.pid = os.getpid()
        self._watchers_names = {}
        self.alive = True
        self._lock = RLock()
        self.debug = debug
        if self.debug:
            stdout_stream = stderr_stream = {'class': 'StdoutStream'}
        else:
            stdout_stream = stderr_stream = None

        # initializing circusd-stats as a watcher when configured
        self.stats_endpoint = stats_endpoint
        if self.stats_endpoint is not None:
            cmd = "%s -c 'from circus import stats; stats.main()'" % \
                sys.executable
            cmd += ' --endpoint %s' % self.endpoint
            cmd += ' --pubsub %s' % self.pubsub_endpoint
            cmd += ' --statspoint %s' % self.stats_endpoint
            if ssh_server is not None:
                cmd += ' --ssh %s' % ssh_server
            if debug:
                cmd += ' --log-level DEBUG'
            stats_watcher = Watcher('circusd-stats', cmd, use_sockets=True,
                                    singleton=True,
                                    stdout_stream=stdout_stream,
                                    stderr_stream=stderr_stream,
                                    copy_env=True, copy_path=True)

            self.watchers.append(stats_watcher)

        # adding the httpd
        if httpd:
            cmd = ("%s -c 'from circusweb import circushttpd; "
                   "circushttpd.main()'") % sys.executable
            cmd += ' --endpoint %s' % self.endpoint
            cmd += ' --fd $(circus.sockets.circushttpd)'
            if ssh_server is not None:
                cmd += ' --ssh %s' % ssh_server
            httpd_watcher = Watcher('circushttpd', cmd, use_sockets=True,
                                    singleton=True,
                                    stdout_stream=stdout_stream,
                                    stderr_stream=stderr_stream,
                                    copy_env=True, copy_path=True)
            self.watchers.append(httpd_watcher)
            httpd_socket = CircusSocket(name='circushttpd', host=httpd_host,
                                        port=httpd_port)

            # adding the socket
            if sockets is None:
                sockets = [httpd_socket]
            else:
                sockets.append(httpd_socket)

        # adding each plugin as a watcher
        if plugins is not None:
            for plugin in plugins:
                fqnd = plugin['use']
                name = 'plugin:%s' % fqnd.replace('.', '-')
                cmd = get_plugin_cmd(plugin, self.endpoint,
                                     self.pubsub_endpoint, self.check_delay,
                                     ssh_server, debug=self.debug)
                plugin_watcher = Watcher(name, cmd, priority=1, singleton=True,
                                         stdout_stream=stdout_stream,
                                         stderr_stream=stderr_stream,
                                         copy_env=True, copy_path=True)
                self.watchers.append(plugin_watcher)

        self.sockets = CircusSockets(sockets)
        self.warmup_delay = warmup_delay
        self.loop = ioloop.IOLoop.instance()
        self.ctrl = Controller(self.endpoint, self.context, self.loop, self,
                               self.check_delay)
Esempio n. 14
0
    def __init__(self,
                 watchers,
                 endpoint,
                 pubsub_endpoint,
                 check_delay=.5,
                 prereload_fn=None,
                 context=None,
                 loop=None,
                 statsd=False,
                 stats_endpoint=None,
                 statsd_close_outputs=False,
                 multicast_endpoint=None,
                 plugins=None,
                 sockets=None,
                 warmup_delay=0,
                 httpd=False,
                 httpd_host='localhost',
                 httpd_port=8080,
                 httpd_close_outputs=False,
                 debug=False,
                 ssh_server=None,
                 proc_name='circusd',
                 pidfile=None,
                 loglevel=None,
                 logoutput=None,
                 fqdn_prefix=None):
        self.watchers = watchers
        self.endpoint = endpoint
        self.check_delay = check_delay
        self.prereload_fn = prereload_fn
        self.pubsub_endpoint = pubsub_endpoint
        self.multicast_endpoint = multicast_endpoint
        self.proc_name = proc_name
        self.ssh_server = ssh_server

        self.pidfile = pidfile
        self.loglevel = loglevel
        self.logoutput = logoutput

        socket_fqdn = socket.getfqdn()
        if fqdn_prefix is None:
            fqdn = socket_fqdn
        else:
            fqdn = '{}@{}'.format(fqdn_prefix, socket_fqdn)
        self.fqdn = fqdn

        self.ctrl = self.loop = None
        self.socket_event = False

        # initialize zmq context
        self._init_context(context)
        self.pid = os.getpid()
        self._watchers_names = {}
        self.alive = True
        self._lock = RLock()
        self.debug = debug
        if self.debug:
            self.stdout_stream = self.stderr_stream = {'class': 'StdoutStream'}
        else:
            self.stdout_stream = self.stderr_stream = None

        # initializing circusd-stats as a watcher when configured
        self.statsd = statsd
        self.stats_endpoint = stats_endpoint

        if self.statsd:
            cmd = "%s -c 'from circus import stats; stats.main()'" % \
                sys.executable
            cmd += ' --endpoint %s' % self.endpoint
            cmd += ' --pubsub %s' % self.pubsub_endpoint
            cmd += ' --statspoint %s' % self.stats_endpoint
            if ssh_server is not None:
                cmd += ' --ssh %s' % ssh_server
            if debug:
                cmd += ' --log-level DEBUG'
            stats_watcher = Watcher('circusd-stats',
                                    cmd,
                                    use_sockets=True,
                                    singleton=True,
                                    stdout_stream=self.stdout_stream,
                                    stderr_stream=self.stderr_stream,
                                    copy_env=True,
                                    copy_path=True,
                                    close_child_stderr=statsd_close_outputs,
                                    close_child_stdout=statsd_close_outputs)

            self.watchers.append(stats_watcher)

        # adding the httpd
        if httpd:
            cmd = ("%s -c 'from circusweb import circushttpd; "
                   "circushttpd.main()'") % sys.executable
            cmd += ' --endpoint %s' % self.endpoint
            cmd += ' --fd $(circus.sockets.circushttpd)'
            if ssh_server is not None:
                cmd += ' --ssh %s' % ssh_server

            httpd_watcher = Watcher('circushttpd',
                                    cmd,
                                    use_sockets=True,
                                    singleton=True,
                                    stdout_stream=self.stdout_stream,
                                    stderr_stream=self.stderr_stream,
                                    copy_env=True,
                                    copy_path=True,
                                    close_child_stderr=httpd_close_outputs,
                                    close_child_stdout=httpd_close_outputs)

            self.watchers.append(httpd_watcher)
            httpd_socket = CircusSocket(name='circushttpd',
                                        host=httpd_host,
                                        port=httpd_port)

            # adding the socket
            if sockets is None:
                sockets = [httpd_socket]
            else:
                sockets.append(httpd_socket)

        # adding each plugin as a watcher
        ch_stderr = self.stderr_stream is None
        ch_stdout = self.stdout_stream is None

        if plugins is not None:
            for plugin in plugins:
                fqn = plugin['use']
                cmd = get_plugin_cmd(plugin,
                                     self.endpoint,
                                     self.pubsub_endpoint,
                                     self.check_delay,
                                     ssh_server,
                                     debug=self.debug)
                plugin_cfg = dict(cmd=cmd,
                                  priority=1,
                                  singleton=True,
                                  stdout_stream=self.stdout_stream,
                                  stderr_stream=self.stderr_stream,
                                  copy_env=True,
                                  copy_path=True,
                                  close_child_stderr=ch_stderr,
                                  close_child_stdout=ch_stdout)
                plugin_cfg.update(plugin)
                if 'name' not in plugin_cfg:
                    plugin_cfg['name'] = fqn

                plugin_watcher = Watcher.load_from_config(plugin_cfg)
                self.watchers.append(plugin_watcher)

        self.sockets = CircusSockets(sockets)
        self.warmup_delay = warmup_delay
Esempio n. 15
0
def serve_development(
    bento_identifier: str,
    working_dir: str,
    port: int = Provide[DeploymentContainer.api_server_config.port],
    host: str = Provide[DeploymentContainer.api_server_config.host],
    backlog: int = Provide[DeploymentContainer.api_server_config.backlog],
    with_ngrok: bool = False,
    reload: bool = False,
    reload_delay: float = 0.25,
) -> None:
    working_dir = os.path.realpath(os.path.expanduser(working_dir))

    from circus.sockets import CircusSocket  # type: ignore
    from circus.watcher import Watcher  # type: ignore

    watchers: t.List[Watcher] = []
    if with_ngrok:
        watchers.append(
            Watcher(
                name="ngrok",
                cmd=sys.executable,
                args=[
                    "-m",
                    SCRIPT_NGROK,
                ],
                copy_env=True,
                numprocesses=1,
                stop_children=True,
                working_dir=working_dir,
            ))

    circus_socket_map: t.Dict[str, CircusSocket] = {}
    circus_socket_map["_bento_api_server"] = CircusSocket(
        name="_bento_api_server",
        host=host,
        port=port,
        backlog=backlog,
    )

    watchers.append(
        Watcher(
            name="dev_api_server",
            cmd=sys.executable,
            args=[
                "-m",
                SCRIPT_DEV_API_SERVER,
                bento_identifier,
                "fd://$(circus.sockets._bento_api_server)",
                "--working-dir",
                working_dir,
            ] + (["--reload", "--reload-delay", f"{reload_delay}"]
                 if reload else []),
            copy_env=True,
            numprocesses=1,
            stop_children=True,
            use_sockets=True,
            working_dir=working_dir,
        ))

    arbiter = create_standalone_arbiter(
        watchers,
        sockets=list(circus_socket_map.values()),
    )
    _ensure_prometheus_dir()

    arbiter.start(
        cb=lambda _: logger.info(  # type: ignore
            f'Starting development BentoServer from "{bento_identifier}" '
            f"running on http://{host}:{port} (Press CTRL+C to quit)"), )
Esempio n. 16
0
def serve_production(
    bento_identifier: str,
    working_dir: str,
    port: int = Provide[DeploymentContainer.api_server_config.port],
    host: str = Provide[DeploymentContainer.api_server_config.host],
    backlog: int = Provide[DeploymentContainer.api_server_config.backlog],
    app_workers: t.Optional[int] = None,
) -> None:
    working_dir = os.path.realpath(os.path.expanduser(working_dir))
    svc = load(bento_identifier,
               working_dir=working_dir,
               change_global_cwd=True)

    from circus.sockets import CircusSocket  # type: ignore
    from circus.watcher import Watcher  # type: ignore

    watchers: t.List[Watcher] = []
    circus_socket_map: t.Dict[str, CircusSocket] = {}
    runner_bind_map: t.Dict[str, str] = {}
    uds_path = None

    if psutil.POSIX:
        # use AF_UNIX sockets for Circus
        uds_path = tempfile.mkdtemp()
        for runner_name, runner in svc.runners.items():
            sockets_path = os.path.join(uds_path, f"{id(runner)}.sock")
            assert len(sockets_path) < MAX_AF_UNIX_PATH_LENGTH

            runner_bind_map[runner_name] = path_to_uri(sockets_path)
            circus_socket_map[runner_name] = CircusSocket(
                name=runner_name,
                path=sockets_path,
                backlog=backlog,
            )

            watchers.append(
                Watcher(
                    name=f"runner_{runner_name}",
                    cmd=sys.executable,
                    args=[
                        "-m",
                        SCRIPT_RUNNER,
                        bento_identifier,
                        runner_name,
                        f"fd://$(circus.sockets.{runner_name})",
                        "--working-dir",
                        working_dir,
                    ],
                    copy_env=True,
                    stop_children=True,
                    working_dir=working_dir,
                    use_sockets=True,
                    numprocesses=runner.num_replica,
                ))

    elif psutil.WINDOWS:
        # Windows doesn't (fully) support AF_UNIX sockets
        with contextlib.ExitStack() as port_stack:
            for runner_name, runner in svc.runners.items():
                runner_port = port_stack.enter_context(reserve_free_port())
                runner_host = "127.0.0.1"

                runner_bind_map[
                    runner_name] = f"tcp://{runner_host}:{runner_port}"
                circus_socket_map[runner_name] = CircusSocket(
                    name=runner_name,
                    host=runner_host,
                    port=runner_port,
                    backlog=backlog,
                )

                watchers.append(
                    Watcher(
                        name=f"runner_{runner_name}",
                        cmd=sys.executable,
                        args=[
                            "-m",
                            SCRIPT_RUNNER,
                            bento_identifier,
                            runner_name,
                            f"fd://$(circus.sockets.{runner_name})",
                            "--working-dir",
                            working_dir,
                        ],
                        copy_env=True,
                        stop_children=True,
                        use_sockets=True,
                        working_dir=working_dir,
                        numprocesses=runner.num_replica,
                    ))
            port_stack.enter_context(
                reserve_free_port())  # reserve one more to avoid conflicts
    else:
        raise NotImplementedError("Unsupported platform: {}".format(
            sys.platform))

    logger.debug("Runner map: %s", runner_bind_map)

    circus_socket_map["_bento_api_server"] = CircusSocket(
        name="_bento_api_server",
        host=host,
        port=port,
        backlog=backlog,
    )
    watchers.append(
        Watcher(
            name="api_server",
            cmd=sys.executable,
            args=[
                "-m",
                SCRIPT_API_SERVER,
                bento_identifier,
                "fd://$(circus.sockets._bento_api_server)",
                "--runner-map",
                json.dumps(runner_bind_map),
                "--working-dir",
                working_dir,
                "--backlog",
                f"{backlog}",
            ],
            copy_env=True,
            numprocesses=app_workers or 1,
            stop_children=True,
            use_sockets=True,
            working_dir=working_dir,
        ))

    arbiter = create_standalone_arbiter(
        watchers=watchers,
        sockets=list(circus_socket_map.values()),
    )

    _ensure_prometheus_dir()
    try:
        arbiter.start(
            cb=lambda _: logger.info(  # type: ignore
                f'Starting production BentoServer from "bento_identifier" '
                f"running on http://{host}:{port} (Press CTRL+C to quit)"), )
    finally:
        if uds_path is not None:
            shutil.rmtree(uds_path)