예제 #1
0
class Plugin(AbstractPlugin):
    SERVER_HOST = server_app.SERVER_HOST
    SERVER_PORT = server_app.SERVER_PORT
    RESERVED_PORTS: Set[int] = {SERVER_PORT}
    PING_URL = server_app.PING_URL

    COMPONENT_NAME = get_directory_name(__file__)
    COMPONENT_PATH = Path(os.path.dirname(os.path.abspath(__file__)))
    SCRIPT_PATH = COMPONENT_PATH / "server_app.py"

    def __init__(self, cli_inputs: CLIInputs):
        self.cli_inputs = cli_inputs
        self.plugin_tools = PluginTools(self, self.cli_inputs)
        self.logger = logging.getLogger(self.COMPONENT_NAME)

        self.src = self.COMPONENT_PATH
        self.datadir = None  # dynamically allocated
        self.id = None  # dynamically allocated
        self.port = None  # dynamically allocated
        self.component_info: Optional[Component] = None

    def install(self) -> None:
        self.logger.debug(
            f"Installing {self.COMPONENT_NAME} is not applicable")

    def start(self) -> None:
        self.id = self.plugin_tools.get_id(self.COMPONENT_NAME)
        logfile = self.plugin_tools.get_logfile_path(self.id)
        env_vars = {"PYTHONUNBUFFERED": "1"}
        command = f"{sys.executable} {self.SCRIPT_PATH}"

        self.plugin_tools.spawn_process(command,
                                        env_vars=env_vars,
                                        id=self.id,
                                        component_name=self.COMPONENT_NAME,
                                        src=self.src,
                                        logfile=logfile)

    def stop(self) -> None:
        self.logger.debug(
            "Attempting to kill the process if it is even running")
        self.plugin_tools.call_for_component_id_or_type(self.COMPONENT_NAME,
                                                        callable=kill_process)

    def reset(self) -> None:
        self.logger.info("resetting the status monitor is not applicable.")
예제 #2
0
class Plugin(AbstractPlugin):

    DEFAULT_PORT = 5050
    RESERVED_PORTS: Set[int] = {DEFAULT_PORT}
    COMPONENT_NAME = get_directory_name(__file__)

    NODE_HOST = os.environ.get("NODE_HOST") or "127.0.0.1"
    NODE_RPC_PORT = int(os.environ.get("NODE_RPC_PORT") or 18332)
    NODE_RPC_USERNAME = os.environ.get("NODE_RPC_USERNAME") or "rpcuser"
    NODE_RPC_PASSWORD = os.environ.get("NODE_RPC_PASSWORD") or "rpcpassword"
    NODE_ZMQ_PORT = int(os.environ.get("NODE_ZMQ_PORT") or 28332)
    MERCHANT_API_HOST = os.environ.get("MERCHANT_API_HOST") or "127.0.0.1"
    MERCHANT_API_PORT = int(
        os.environ.get("MERCHANT_API_PORT") or DEFAULT_PORT)

    def __init__(self, cli_inputs: CLIInputs):
        self.cli_inputs = cli_inputs
        self.config = Config()
        self.plugin_tools = PluginTools(self, self.cli_inputs)
        self.logger = logging.getLogger(self.COMPONENT_NAME)

        self.src = self.plugin_tools.get_source_dir(dirname="merchant_api")
        self.datadir: Optional[Path] = None  # dynamically allocated
        self.id: Optional[str] = None  # dynamically allocated
        self.port: Optional[int] = None  # dynamically allocated
        self.component_info: Optional[Component] = None
        download_and_init_postgres()  # only if necessary

    def install(self) -> None:
        assert self.src is not None  # typing bug in mypy
        download_and_install(self.src)

        if SDK_SKIP_POSTGRES_INIT != 1:
            if SDK_PORTABLE_MODE == 1:
                # stop_postgres()
                # reset_postgres()
                start_postgres()

            prepare_fresh_postgres()
            drop_db_on_install()
            check_postgres_db()

        self.logger.debug(f"Installed {self.COMPONENT_NAME}")

    def start(self) -> None:
        assert self.src is not None  # typing bug
        if SDK_PORTABLE_MODE == 1:
            download_and_install(self.src)
            start_postgres()

        self.logger.debug(f"Starting Merchant API")
        prepare_fresh_postgres()
        check_postgres_db()

        if not self.src.exists():
            self.logger.error(
                f"source code directory does not exist - try 'electrumsv-sdk install "
                f"{self.COMPONENT_NAME}' to install the plugin first")
            sys.exit(1)

        self.id = self.plugin_tools.get_id(self.COMPONENT_NAME)
        self.port = self.MERCHANT_API_PORT
        # The primary reason we need this to be the current directory is so that the `settings.conf`
        # file is directly accessible to the MAPI executable (it should look there first).
        os.chdir(self.src)

        # EXE RUN MODE
        load_env_vars()
        try:
            chmod_exe(self.src)
            command = get_run_path(self.src)
        except FileNotFoundError:
            self.logger.error(
                f"Could not find version: {MERCHANT_API_VERSION} of the "
                f"merchant_api. Have you tried re-running 'electrumsv-sdk install merchant_api' to "
                f"pull the latest version?")
            return

        logfile = self.plugin_tools.get_logfile_path(self.id)
        status_endpoint = "http://127.0.0.1:5050/mapi/feeQuote"

        self.add_node_thread = AddNodeThread(mapi_url="http://127.0.0.1:5050",
                                             max_wait_time=10)
        self.add_node_thread.start()

        self.plugin_tools.spawn_process(str(command),
                                        env_vars=os.environ.copy(),
                                        id=self.id,
                                        component_name=self.COMPONENT_NAME,
                                        src=self.src,
                                        logfile=logfile,
                                        status_endpoint=status_endpoint)

        # will keep trying to add node until mAPI REST API available (up to a limited wait time)
        self.logger.info("Adding node to mAPI instance (if not already added)")
        self.add_node_thread.join()

    def stop(self) -> None:
        self.plugin_tools.call_for_component_id_or_type(self.COMPONENT_NAME,
                                                        callable=kill_process)

        if SDK_PORTABLE_MODE == 1:
            assert self.config.DATADIR is not None
            postgres_install_path = self.config.DATADIR / "postgres"

            # Set this environment variable before importing postgres script
            os.environ['SDK_POSTGRES_INSTALL_DIR'] = str(postgres_install_path)
            from .. import _postgres
            if asyncio.run(_postgres.check_running()):
                stop_postgres()

        self.logger.info(
            f"stopped selected {self.COMPONENT_NAME} instance (if running)")

    def reset(self) -> None:
        self.logger.info("resetting Merchant API is not applicable")
예제 #3
0
class Plugin(AbstractPlugin):

    # As per woc-explorer/cli_inputs.js
    # TODO This is obsolete. ElectrumX is no longer supported in the SDK. Either we need to get
    #      rid of the WOC components or replace them with an explorer component which we would
    #      embed in the TestUI project.
    ELECTRUMX_HOST = os.environ.get("ELECTRUMX_HOST") or "127.0.0.1"
    ELECTRUMX_PORT = os.environ.get("ELECTRUMX_PORT") or 51001

    # As per woc-explorer/app.js
    RPC_HOST = os.environ.get("RPC_HOST") or "127.0.0.1"
    RPC_PORT = int(os.environ.get("RPC_PORT") or 18332)
    RPC_USERNAME = os.environ.get("RPC_USERNAME") or "rpcuser"
    RPC_PASSWORD = os.environ.get("RPC_PASSWORD") or "rpcpassword"

    DEFAULT_PORT = 3002
    RESERVED_PORTS: Set[int] = {DEFAULT_PORT}
    COMPONENT_NAME = get_directory_name(__file__)

    def __init__(self, cli_inputs: CLIInputs):
        self.cli_inputs = cli_inputs
        self.config = Config()
        self.plugin_tools = PluginTools(self, self.cli_inputs)
        self.tools = LocalTools(self)
        self.logger = logging.getLogger(self.COMPONENT_NAME)

        self.src = self.plugin_tools.get_source_dir("woc-explorer")
        self.datadir = None  # N/A
        self.id = self.plugin_tools.get_id(self.COMPONENT_NAME)
        self.port = None  # N/A
        self.component_info: Optional[Component] = None

    def install(self) -> None:
        if not self.cli_inputs.repo == "":  # default
            self.logger.error(
                "ignoring --repo flag for whatsonchain - not applicable.")
        self.tools.fetch_whatsonchain(
            url="https://github.com/AustEcon/woc-explorer.git", branch='')
        self.tools.packages_whatsonchain()
        self.logger.debug(f"Installed {self.COMPONENT_NAME}")

    def start(self) -> None:
        self.logger.debug(f"Starting whatsonchain explorer...")
        assert self.src is not None  # typing bug
        if not self.src.exists():
            self.logger.error(
                f"source code directory does not exist - try 'electrumsv-sdk install "
                f"{self.COMPONENT_NAME}' to install the plugin first")
            sys.exit(1)

        if not self.tools.check_node_for_woc(self.RPC_HOST, self.RPC_PORT,
                                             self.RPC_USERNAME,
                                             self.RPC_PASSWORD):
            sys.exit(1)

        os.chdir(self.src)
        # npm without .cmd extension doesn't work with Popen shell=False
        if sys.platform == "win32":
            command = f"npm.cmd start"
        elif sys.platform in {"linux", "darwin"}:
            command = f"npm start"
        env_vars = {
            "PYTHONUNBUFFERED": "1",
            "ELECTRUMX_HOST": self.ELECTRUMX_HOST,
            "ELECTRUMX_PORT": str(self.ELECTRUMX_PORT),
            "RPC_HOST": self.RPC_HOST,
            "RPC_PORT": str(self.RPC_PORT),
            "RPC_USERNAME": self.RPC_USERNAME,
            "RPC_PASSWORD": self.RPC_PASSWORD,
        }
        self.id = self.plugin_tools.get_id(self.COMPONENT_NAME)
        logfile = self.plugin_tools.get_logfile_path(self.id)
        status_endpoint = "http://127.0.0.1:3002"
        self.plugin_tools.spawn_process(command,
                                        env_vars=env_vars,
                                        id=self.id,
                                        component_name=self.COMPONENT_NAME,
                                        src=self.src,
                                        logfile=logfile,
                                        status_endpoint=status_endpoint)

    def stop(self) -> None:
        """some components require graceful shutdown via a REST API or RPC API but most can use the
        generic 'app_state.kill_component()' function to track down the pid and kill the process."""
        self.plugin_tools.call_for_component_id_or_type(self.COMPONENT_NAME,
                                                        callable=kill_process)
        self.logger.info(
            f"stopped selected {self.COMPONENT_NAME} instance (if running)")

    def reset(self) -> None:
        self.logger.info("resetting the whatsonchain is not applicable")