def run_process_as_sudo(component, port, asynchronous=False, env_vars=None): # make sure we can run sudo commands try: ensure_can_use_sudo() except Exception as e: LOG.error("cannot start service on privileged port %s: %s", port, str(e)) return # prepare environment env_vars = env_vars or {} env_vars["PYTHONPATH"] = f".:{LOCALSTACK_ROOT_FOLDER}" env_vars["EDGE_FORWARD_URL"] = config.get_edge_url() env_vars["EDGE_BIND_HOST"] = config.EDGE_BIND_HOST env_vars_str = env_vars_to_string(env_vars) # start the process as sudo sudo_cmd = "sudo -n" python_cmd = sys.executable cmd = [ sudo_cmd, env_vars_str, python_cmd, "-m", "localstack.services.edge", component, str(port), ] shell_cmd = " ".join(cmd) def run_command(*_): run(shell_cmd, outfile=subprocess.PIPE, print_error=False, env_vars=env_vars) LOG.debug("Running command as sudo: %s", shell_cmd) result = start_thread(run_command, quiet=True) if asynchronous else run_command() return result
def serve_flask_app(app, port, host=None, cors=True, asynchronous=False): if cors: CORS(app) if not config.DEBUG: logging.getLogger("werkzeug").setLevel(logging.ERROR) if not host: host = "0.0.0.0" ssl_context = None if not config.FORWARD_EDGE_INMEM: ssl_context = GenericProxy.get_flask_ssl_context(serial_number=port) app.config["ENV"] = "development" def noecho(*args, **kwargs): pass try: import click click.echo = noecho except Exception: pass def _run(*_): app.run(port=int(port), threaded=True, host=host, ssl_context=ssl_context) return app if asynchronous: return start_thread(_run) return _run()
def _do_start_retry(self, *_): # TODO: actually retry try: if config.DEBUG_ANALYTICS: LOG.debug("trying to register session with analytics backend") response = self._client.start_session(get_client_metadata()) if config.DEBUG_ANALYTICS: LOG.debug("session endpoint returned: %s", response) except Exception: self.tracking_disabled = True if config.DEBUG_ANALYTICS: LOG.exception( "error while registering session. disabling tracking") return finally: self._startup_complete = True start_thread(self.run) def _do_close(): self.close_sync(timeout=2) atexit.register(_do_close)
def do_start_thread(self) -> FuncThread: """ Creates and starts the thread running the server. By default, it calls the do_run method in a FuncThread, but can be overridden to if the subclass wants to return its own thread. """ def _run(*_): try: return self.do_run() except StopServer: LOG.debug("stopping server %s", self.url) finally: self._stopped.set() return start_thread(_run)
def start_local_api(name, port, api, method, asynchronous=False, listener=None): log_startup_message(name) if config.FORWARD_EDGE_INMEM: port = get_free_tcp_port() PROXY_LISTENERS[api] = (api, port, listener) if asynchronous: thread = start_thread(method, port, quiet=True) return thread else: method(port)
def run(self, *_): flush_scheduler = start_thread(self._run_flush_schedule) try: while True: command = self._command_queue.get() if command is self._cmd_flush or command is self._cmd_stop: try: self._do_flush() except Exception: if config.DEBUG_ANALYTICS: LOG.exception("error while flushing events") if command is self._cmd_stop: return finally: self._stopped.set() flush_scheduler.stop()
def start_runtime_components(): from localstack.services.edge import start_edge # TODO: we want a composable LocalStack runtime (edge proxy, service manager, dns, ...) t = start_thread(start_edge, quiet=False) # TODO: properly encapsulate starting/stopping of edge server in a class if not poll_condition( lambda: is_port_open(config.get_edge_port_http()), timeout=15, interval=0.3): if LOG.isEnabledFor(logging.DEBUG): # make another call with quiet=False to print detailed error logs is_port_open(config.get_edge_port_http(), quiet=False) raise TimeoutError( f"gave up waiting for edge server on {config.EDGE_BIND_HOST}:{config.EDGE_PORT}" ) return t