Beispiel #1
0
    def __init__(
        self,
        runner: scenario_runner.ScenarioRunner,
        config: Any,
        parent: Task = None,
        abort_on_fail: bool = True,
    ) -> None:
        super().__init__(runner, config, parent, abort_on_fail)

        required_keys = {"channel_info_key"}
        if not required_keys.issubset(config.keys()):
            raise ScenarioError(
                f'Not all required keys provided. Required: {", ".join(required_keys)}'
            )

        self.web3 = self._runner.client.web3
        self.contract_name = CONTRACT_MONITORING_SERVICE

        # get the MS contract address
        contract_data = get_contracts_deployment_info(
            chain_id=self._runner.chain_id, version=DEVELOPMENT_CONTRACT_VERSION
        )
        try:
            contract_info = contract_data["contracts"][self.contract_name]
            self.contract_address = contract_info["address"]
        except KeyError:
            raise ScenarioError(f"Unknown contract name: {self.contract_name}")
    def __init__(self,
                 runner: scenario_runner.ScenarioRunner,
                 config: Any,
                 parent: Task = None) -> None:
        super().__init__(runner, config, parent)

        required_keys = {"channel_info_key"}
        if not required_keys.issubset(config.keys()):
            raise ScenarioError(
                f'Not all required keys provided. Required: {", ".join(required_keys)}'
            )

        self.web3 = self._runner.client.web3
        self.contract_name = CONTRACT_MONITORING_SERVICE

        # get the MS contract address
        contract_data = get_contracts_deployment_info(
            chain_id=self._runner.definition.settings.chain_id,
            version=RAIDEN_CONTRACT_VERSION,
            development_environment=self._runner.environment.
            development_environment,
        )
        assert contract_data
        try:
            contract_info = contract_data["contracts"][self.contract_name]
            self.contract_address = contract_info["address"]
        except KeyError:
            raise ScenarioError(f"Unknown contract name: {self.contract_name}")
Beispiel #3
0
    def check_scenario_config(self):
        if not self._scenario_runner.definition.nodes.reuse_accounts:
            raise ScenarioError("Snapshots aren't supported when 'nodes.reuse_accounts' is False.")

        token_config = self._scenario_runner.definition.token
        if (not token_config.should_reuse_token) and token_config.address is None:
            raise ScenarioError(
                "Snapshots are only supported when token reuse is enabled "
                "or a fixed token address is configured."
            )
Beispiel #4
0
    def run_scenario(self):
        from scenario_player.tasks.base import get_task_class_for_type

        log.info("Fetching node addresses")
        unreachable_nodes = [node for node, addr in self.node_to_address.items() if not addr]
        if not self.node_to_address or unreachable_nodes:
            raise NodesUnreachableError(f"Raiden nodes unreachable: {','.join(unreachable_nodes)}")
        token_ctr = get_or_deploy_token(self.client, self.scenario)
        token_address = self.token_address = to_checksum_address(token_ctr.contract_address)
        first_node = first(self.raiden_nodes)

        token_settings = self.scenario.get('token') or {}
        token_balance_min = token_settings.get(
            'balance_min',
            DEFAULT_TOKEN_BALANCE_MIN,
        )

        mint_tx = []
        for node, address in self.node_to_address.items():
            balance = token_ctr.contract.functions.balanceOf(address).call()
            if balance < token_balance_min:
                mint_amount = token_balance_min - balance
                log.debug("Minting tokens for", address=address, node=node, amount=mint_amount)
                mint_tx.append(token_ctr.transact('mintFor', mint_amount, address))
            elif balance > token_balance_min:
                log.warning("Node is overfunded", address=address, node=node, balance=balance)
        wait_for_txs(self.client, mint_tx)

        registered_tokens = set(
            self.session.get(
                API_URL_TOKENS.format(protocol=self.protocol, target_host=first_node),
            ).json(),
        )
        if token_address not in registered_tokens:
            code, msg = self.register_token(token_address, first_node)
            if not 199 < code < 300:
                log.error("Couldn't register token with network", code=code, message=msg)
                raise TokenRegistrationError(msg)

        scenario_config = self.scenario.get('scenario')
        if not scenario_config:
            raise ScenarioError("Invalid scenario definition. Missing 'scenario' key.")

        try:
            (root_task_type, root_task_config), = scenario_config.items()
        except ValueError:
            # will be thrown if it's not a 1-element dict
            raise ScenarioError(
                "Invalid scenario definition. "
                "Exactly one root task is required below the 'scenario' key.",
            ) from None

        task_class = get_task_class_for_type(root_task_type)
        self.root_task = task_class(runner=self, config=root_task_config)
        self.root_task()
Beispiel #5
0
    def __init__(self,
                 runner: scenario_runner.ScenarioRunner,
                 config: Any,
                 parent: Task = None) -> None:
        super().__init__(runner, config, parent)

        if "source" not in config:
            raise ScenarioError(
                "Not all required keys provided. Required: source ")

        if not any(k in config for k in ["iou_exists", "amount"]):
            raise ScenarioError("Expected either iou_exists or amount.")
Beispiel #6
0
    def _url_params(self):
        pfs_url = self._runner.scenario.services.get('pfs', {}).get('url')
        if not pfs_url:
            raise ScenarioError(
                'PFS tasks require settings.services.pfs.url to be set.')

        source = self._config['source']
        if isinstance(source, str) and len(source) == 42:
            source_address = source
        else:
            source_address = self._runner.get_node_address(source)

        extra_params = ''
        if 'target' in self._config:
            target = self._config['target']
            if isinstance(target, str) and len(target) == 42:
                target_address = target
            else:
                target_address = self._runner.get_node_address(target)
            extra_params = f'/{target_address}'

        params = dict(
            pfs_url=pfs_url,
            token_network_address=self._runner.token_network_address,
            source_address=source_address,
            extra_params=extra_params,
        )
        return params
    def start(self):
        log.info(
            "Starting node",
            node=self._index,
            address=self.address,
            port=self.api_address.rpartition(":")[2],
        )
        log.debug("Node start command", command=self.executor.command)
        self._output_files["stdout"] = self._stdout_file.open("at", 1)
        self._output_files["stderr"] = self._stderr_file.open("at", 1)
        for file in self._output_files.values():
            file.write("--------- Starting ---------\n")
        self._output_files["stdout"].write(
            f"Command line: {self.executor.command}\n")

        begin = time.monotonic()
        try:
            ret = self.executor.start(**self._output_files)
        except ProcessExitedWithError as ex:
            raise ScenarioError(
                f"Failed to start Raiden node {self._index}") from ex
        self.state = NodeState.STARTED
        duration = str(timedelta(seconds=time.monotonic() - begin))
        log.info("Node started", node=self._index, duration=duration)
        return ret
Beispiel #8
0
    def _url_params(self):
        pfs_url = self._runner.scenario.services.get("pfs", {}).get("url")
        if not pfs_url:
            raise ScenarioError("PFS tasks require settings.services.pfs.url to be set.")

        params = dict(pfs_url=pfs_url, token_network_address=self._runner.token_network_address)
        return params
Beispiel #9
0
    def start(self):
        log.info(
            'Starting node',
            node=self._index,
            address=self.address,
            port=self.api_address.rpartition(':')[2],
        )
        log.debug('Node start command', command=self.executor.command)
        self._output_files['stdout'] = self._stdout_file.open('at', 1)
        self._output_files['stderr'] = self._stderr_file.open('at', 1)
        for file in self._output_files.values():
            file.write('--------- Starting ---------\n')
        self._output_files['stdout'].write(
            f'Command line: {self.executor.command}\n')

        begin = time.monotonic()
        try:
            ret = self.executor.start(**self._output_files)
        except ProcessExitedWithError as ex:
            raise ScenarioError(
                f'Failed to start Raiden node {self._index}') from ex
        self.state = NodeState.STARTED
        duration = str(timedelta(seconds=time.monotonic() - begin))
        log.info('Node started', node=self._index, duration=duration)
        return ret
Beispiel #10
0
 def __init__(self,
              runner: scenario_runner.ScenarioRunner,
              config: Any,
              parent: Task = None) -> None:
     super().__init__(runner, config, parent)
     if "key" not in config:
         raise ScenarioError('Required config "key" not found')
Beispiel #11
0
    def __init__(self, runner: ScenarioRunner, index: int, raiden_version, options: dict):
        self._runner = runner
        self._index = index
        self._raiden_version = raiden_version
        self._options = options
        self._datadir = runner.data_path.joinpath(f'node_{index:03d}')

        self._address = None
        self._eth_rpc_endpoint = None
        self._executor = None
        self._api_address = None

        self.state: NodeState = NodeState.STOPPED

        self._output_files = {}

        if options.pop('_clean', False):
            shutil.rmtree(self._datadir)
        self._datadir.mkdir(parents=True, exist_ok=True)

        for option_name, option_value in options.items():
            if option_name.startswith('no-'):
                option_name = option_name.replace('no-', '')
            if option_name in MANAGED_CONFIG_OPTIONS:
                raise ScenarioError(
                    f'Raiden node option "{option_name}" is managed by the scenario player '
                    f'and cannot be changed.',
                )
            if option_name in MANAGED_CONFIG_OPTIONS_OVERRIDABLE:
                log.warning(
                    'Overriding managed option',
                    option_name=option_name,
                    option_value=option_value,
                    node=self._index,
                )
Beispiel #12
0
    def _run(self, *args, **kwargs):  # pylint: disable=unused-argument
        # get the correct contract address
        # this has to be done in `_run`, otherwise `_runner` is not initialized yet
        contract_data = get_contracts_deployment_info(
            chain_id=self._runner.chain_id, version=DEVELOPMENT_CONTRACT_VERSION
        )
        if self.contract_name == CONTRACT_TOKEN_NETWORK:
            self.contract_address = self._runner.token_network_address
        else:
            try:
                contract_info = contract_data["contracts"][self.contract_name]
                self.contract_address = contract_info["address"]
            except KeyError:
                raise ScenarioError(f"Unknown contract name: {self.contract_name}")

        events = query_blockchain_events(
            web3=self.web3,
            contract_manager=self._runner.contract_manager,
            contract_address=self.contract_address,
            contract_name=self.contract_name,
            topics=[],
            from_block=BlockNumber(self._runner.token.deployment_block),
            to_block=BlockNumber(self.web3.eth.blockNumber),
        )

        # Filter matching events
        events = [e for e in events if e["event"] == self.event_name]

        # Raise exception when events do not match
        if not self.num_events == len(events):
            raise ScenarioAssertionError(
                f"Expected number of events ({self.num_events}) did not match the number "
                f"of events found ({len(events)})"
            )
Beispiel #13
0
    def _process_response(self, response_dict: dict):
        response_dict = super()._process_response(response_dict)
        for field in ["balance", "total_deposit", "state"]:
            if field not in self._config:
                continue
            if field not in response_dict:
                raise ScenarioError(
                    f'Field "{field}" is missing in channel: {response_dict}')
            allow_error = self._config.get("allow_" + field + "_error")
            if allow_error:
                success = (int(response_dict[field]) - allow_error <=
                           self._config[field] <=
                           int(response_dict[field]) + allow_error)
                log.info("allow_error",
                         allow_error=allow_error,
                         error_success=success)
            else:
                success = str(response_dict[field]) == str(self._config[field])

            if not success:
                raise ScenarioAssertionError(
                    f'Value mismatch for "{field}". '
                    f'Should: "{self._config[field]}" '
                    f'Is: "{response_dict[field]}" '
                    f"Channel: {response_dict}")
        return response_dict
Beispiel #14
0
    def _url_params(self):
        pfs_url = self._runner.scenario.services.get("pfs", {}).get("url")
        if not pfs_url:
            raise ScenarioError("PFS tasks require settings.services.pfs.url to be set.")

        source = self._config["source"]
        if isinstance(source, str) and len(source) == 42:
            source_address = source
        else:
            source_address = self._runner.get_node_address(source)

        extra_params = ""
        if "target" in self._config:
            target = self._config["target"]
            if isinstance(target, str) and len(target) == 42:
                target_address = target
            else:
                target_address = self._runner.get_node_address(target)
            extra_params = f"/{target_address}"

        params = dict(
            pfs_url=pfs_url,
            token_network_address=self._runner.token_network_address,
            source_address=source_address,
            extra_params=extra_params,
        )
        return params
Beispiel #15
0
 def update_options(self, new_options: Dict[str, Any]):
     if self.state is not NodeState.STOPPED:
         raise ScenarioError(
             "Can't update node options while node is running.")
     self._validate_options(new_options)
     self._options.update(new_options)
     self._executor = None
    def _run(self, *args, **kwargs) -> Dict[str, Any]:  # pylint: disable=unused-argument
        # get the correct contract address
        # this has to be done in `_run`, otherwise `_runner` is not initialized yet
        contract_data = get_contracts_deployment_info(
            chain_id=self._runner.definition.settings.chain_id,
            version=RAIDEN_CONTRACT_VERSION,
            development_environment=self._runner.environment.
            development_environment,
        )
        if self.contract_name == CONTRACT_TOKEN_NETWORK:
            self.contract_address = self._runner.token_network_address
        else:
            try:
                assert contract_data
                contract_info = contract_data["contracts"][self.contract_name]
                self.contract_address = to_checksum_address(
                    contract_info["address"])
            except KeyError:
                raise ScenarioError(
                    f"Unknown contract name: {self.contract_name}")

        assert self.contract_address, "Contract address not set"
        events = query_blockchain_events(
            web3=self.web3,
            contract_manager=self._runner.contract_manager,
            contract_address=to_canonical_address(self.contract_address),
            contract_name=self.contract_name,
            topics=[],
            from_block=BlockNumber(self._runner.block_execution_started),
            to_block=BlockNumber(self.web3.eth.blockNumber),
        )

        # Filter matching events
        events = [e for e in events if e["event"] == self.event_name]

        if self.event_args:
            for key, value in self.event_args.items():
                if "participant" in key:
                    if isinstance(value, int) or (isinstance(value, str)
                                                  and value.isnumeric()):
                        # Replace node index with eth address
                        self.event_args[key] = self._runner.get_node_address(
                            int(value))

            event_args_items = self.event_args.items()
            # Filter the events by the given event args.
            # `.items()` produces a set like object which supports intersection (`&`)
            events = [
                e for e in events
                if e["args"] and event_args_items & e["args"].items()
            ]

        # Raise exception when events do not match
        if not self.num_events == len(events):
            raise ScenarioAssertionError(
                f"Expected number of events ({self.num_events}) did not match the number "
                f"of events found ({len(events)})")

        return {"events": events}
Beispiel #17
0
 def __init__(self,
              runner: ScenarioRunner,
              config: Any,
              parent: Task = None,
              abort_on_fail=True) -> None:
     super().__init__(runner, config, parent, abort_on_fail)
     if "key" not in config:
         raise ScenarioError('Required config "key" not found')
Beispiel #18
0
    def configuration(self):
        """Return the scenario's configuration.

        :raises ScenarioError: if no 'scenario' key is present in the yaml file.
        """
        try:
            return self._config["scenario"]
        except KeyError:
            raise ScenarioError("Invalid scenario definition. Missing 'scenario' key.")
    def _run(self, *args, **kwargs) -> Dict[str, Any]:  # pylint: disable=unused-argument
        channel_infos = self._runner.task_storage[
            STORAGE_KEY_CHANNEL_INFO].get(self._config["channel_info_key"])

        if channel_infos is None:
            raise ScenarioError(
                f"No stored channel info found for key '{self._config['channel_info_key']}'."
            )

        # calculate reward_id
        assert "token_network_address" in channel_infos.keys()
        assert "channel_identifier" in channel_infos.keys()

        reward_id = bytes(
            Web3.soliditySha3(  # pylint: disable=no-value-for-parameter
                ["uint256", "address"],
                [
                    int(channel_infos["channel_identifier"]),
                    channel_infos["token_network_address"],
                ],
            ))

        log.info("Calculated reward ID", reward_id=encode_hex(reward_id))

        events = query_blockchain_events(
            web3=self.web3,
            contract_manager=self._runner.contract_manager,
            contract_address=to_canonical_address(self.contract_address),
            contract_name=self.contract_name,
            topics=[],
            from_block=BlockNumber(self._runner.block_execution_started),
            to_block=BlockNumber(self.web3.eth.blockNumber),
        )

        # Filter matching events
        def match_event(event: Dict):
            if not event["event"] == MonitoringServiceEvent.REWARD_CLAIMED:
                return False

            event_reward_id = bytes(event["args"]["reward_identifier"])
            return event_reward_id == reward_id

        events = [e for e in events if match_event(e)]
        log.info("Matching events", events=events)

        must_claim = self._config.get("must_claim", True)
        found_events = len(events) > 0

        # Raise exception when no event was found
        if must_claim and not found_events:
            raise ScenarioAssertionError(
                "No RewardClaimed event found for this channel.")
        elif not must_claim and found_events:
            raise ScenarioAssertionError(
                "Unexpected RewardClaimed event found for this channel.")

        return {"events": events}
Beispiel #20
0
def get_or_deploy_token(runner: 'ScenarioRunner') -> ContractProxy:
    """ Deploy or reuse  """
    contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH)
    token_contract = contract_manager.get_contract(CONTRACT_CUSTOM_TOKEN)

    token_config = runner.scenario.get('token', {})
    if not token_config:
        token_config = {}
    address = token_config.get('address')
    reuse = token_config.get('reuse', False)

    token_address_file = runner.data_path.joinpath('token.addr')
    if reuse:
        if address:
            raise ScenarioError(
                'Token settings "address" and "reuse" are mutually exclusive.')
        if token_address_file.exists():
            address = token_address_file.read_text()
    if address:
        check_address_has_code(runner.client, address, 'Token')
        token_ctr = runner.client.new_contract_proxy(token_contract['abi'],
                                                     address)

        log.debug(
            "Reusing token",
            address=to_checksum_address(address),
            name=token_ctr.contract.functions.name().call(),
            symbol=token_ctr.contract.functions.symbol().call(),
        )
        return token_ctr

    token_id = uuid.uuid4()
    now = datetime.now()
    name = token_config.get(
        'name', f"Scenario Test Token {token_id!s} {now:%Y-%m-%dT%H:%M}")
    symbol = token_config.get('symbol', f"T{token_id!s:.3}")
    decimals = token_config.get('decimals', 0)

    log.debug("Deploying token", name=name, symbol=symbol, decimals=decimals)

    token_ctr = runner.client.deploy_solidity_contract(
        'CustomToken',
        contract_manager.contracts,
        constructor_parameters=(0, decimals, name, symbol),
        confirmations=1,
    )
    contract_checksum_address = to_checksum_address(token_ctr.contract_address)
    if reuse:
        token_address_file.write_text(contract_checksum_address)

    log.info(
        "Deployed token",
        address=contract_checksum_address,
        name=name,
        symbol=symbol,
    )
    return token_ctr
Beispiel #21
0
 def _process_response(self, response_dict: dict):
     response_dict = super()._process_response(response_dict)
     channel_count = len(response_dict)
     for field in ["balance", "total_deposit", "state"]:
         # The task parameter field names are the plural of the channel field names
         assert_field = f"{field}s"
         if assert_field not in self._config:
             continue
         try:
             channel_field_values = [
                 channel[field] for channel in response_dict
             ]
         except KeyError:
             raise ScenarioError(
                 f'Field "{field}" is missing in at least one channel: {response_dict}'
             )
         assert_field_value_count = len(self._config[assert_field])
         if assert_field_value_count != channel_count:
             direction = ["many",
                          "few"][assert_field_value_count < channel_count]
             raise ScenarioError(
                 f'Assertion field "{field}" has too {direction} values. '
                 f"Have {channel_count} channels but {assert_field_value_count} values."
             )
         channel_field_values_all = channel_field_values[:]
         for value in self._config[assert_field]:
             try:
                 channel_field_values.remove(str(value))
             except ValueError:
                 channel_field_values_str = ", ".join(
                     str(val) for val in channel_field_values_all)
                 assert_field_values_str = ", ".join(
                     str(val) for val in self._config[assert_field])
                 raise ScenarioAssertionError(
                     f'Expected value "{value}" for field "{field}" not found in any channel. '
                     f"Existing values: {channel_field_values_str} "
                     f"Expected values: {assert_field_values_str} "
                     f"Channels: {response_dict}") from None
         if len(channel_field_values) != 0:
             raise ScenarioAssertionError(
                 f'Value mismatch for field "{field}". '
                 f"Not all values consumed, remaining: {channel_field_values}"
             )
     return response_dict
Beispiel #22
0
 def _monitor(runner: NodeRunner):
     while not self._runner.root_task.done:
         if runner.state is NodeState.STARTED:
             try:
                 runner.executor.check_subprocess()
             except ProcessExitedWithError as ex:
                 raise ScenarioError(
                     f'Raiden node {runner._index} died with non-zero exit status',
                 ) from ex
         gevent.sleep(.5)
Beispiel #23
0
    def _validate_options(self, options: Dict[str, Any]):
        for option_name, option_value in options.items():
            if option_name.startswith("no-"):
                option_name = option_name.replace("no-", "")
            if option_name in MANAGED_CONFIG_OPTIONS:
                raise ScenarioError(
                    f'Raiden node option "{option_name}" is managed by the scenario player '
                    f"and cannot be changed."
                )
            if option_name in MANAGED_CONFIG_OPTIONS_OVERRIDABLE:
                log.warning(
                    "Overriding managed option",
                    option_name=option_name,
                    option_value=option_value,
                    node=self._index,
                )

            if option_name not in KNOWN_OPTIONS:
                raise ScenarioError(f'Unknown option "{option_name}" supplied.')
Beispiel #24
0
def get_or_deploy_token(runner) -> Tuple[ContractProxy, int]:
    """ Deploy or reuse  """
    token_contract = runner.contract_manager.get_contract(CONTRACT_CUSTOM_TOKEN)

    token_config = runner.yaml.token
    if not token_config:
        token_config = {}
    address = token_config.get("address")
    block = token_config.get("block", 0)
    reuse = token_config.get("reuse", False)

    token_address_file = runner.data_path.joinpath("token.infos")
    if reuse:
        if address:
            raise ScenarioError('Token settings "address" and "reuse" are mutually exclusive.')
        if token_address_file.exists():
            token_data = json.loads(token_address_file.read_text())
            address = token_data["address"]
            block = token_data["block"]
    if address:
        check_address_has_code(runner.client, address, "Token")
        token_ctr = runner.client.new_contract_proxy(token_contract["abi"], address)

        log.debug(
            "Reusing token",
            address=to_checksum_address(address),
            name=token_ctr.contract.functions.name().call(),
            symbol=token_ctr.contract.functions.symbol().call(),
        )
        return token_ctr, block

    token_id = uuid.uuid4()
    now = datetime.now()
    name = token_config.get("name", f"Scenario Test Token {token_id!s} {now:%Y-%m-%dT%H:%M}")
    symbol = token_config.get("symbol", f"T{token_id!s:.3}")
    decimals = token_config.get("decimals", 0)

    log.debug("Deploying token", name=name, symbol=symbol, decimals=decimals)

    token_ctr, receipt = runner.client.deploy_single_contract(
        "CustomToken",
        runner.contract_manager.contracts["CustomToken"],
        constructor_parameters=(1, decimals, name, symbol),
    )
    contract_deployment_block = receipt["blockNumber"]
    contract_checksum_address = to_checksum_address(token_ctr.contract_address)
    if reuse:
        token_address_file.write_text(
            json.dumps({"address": contract_checksum_address, "block": contract_deployment_block})
        )

    log.info("Deployed token", address=contract_checksum_address, name=name, symbol=symbol)
    return token_ctr, contract_deployment_block
Beispiel #25
0
 def _run(self, *args, **kwargs):
     command = self._runner.node_commands.get(self._command)
     if not command:
         raise ScenarioError(
             'Invalid scenario definition. '
             f'The {self._command}_node task requires '
             f'nodes.commands.{self._command} to be set.',
         )
     command = command.format(self._config)
     log.debug('Command', type_=self._command, command=command)
     greenlet = gevent.spawn(subprocess.run, shlex.split(command), check=True)
     self._handle_process(greenlet)
Beispiel #26
0
    def _url_params(self):
        pfs_url = self._runner.scenario.services.get("pfs", {}).get("url")
        if not pfs_url:
            raise ScenarioError("PFS tasks require settings.services.pfs.url to be set.")

        source = self._config["source"]
        if isinstance(source, str) and len(source) == 42:
            source_address = source
        else:
            source_address = self._runner.get_node_address(source)

        params = dict(pfs_url=pfs_url, source_address=source_address)
        return params
Beispiel #27
0
 def get_snapshot_info(self) -> Tuple[bool, List[Path]]:
     snapshot_dirs = self._get_snapshot_dirs()
     dirs_exist = [snapshot_dir.exists() for snapshot_dir in snapshot_dirs]
     if any(dirs_exist) and not all(dirs_exist):
         missing_nodes = ", ".join(snapshot_dir.name
                                   for snapshot_dir in snapshot_dirs
                                   if not snapshot_dir.exists())
         raise ScenarioError(
             f"Inconsistent snapshot. "
             f"Snapshot dirs for nodes {missing_nodes} are missing. "
             f"Use --delete-snapshots to clean.")
     elif not all(dirs_exist):
         return False, snapshot_dirs
     return True, snapshot_dirs
Beispiel #28
0
 def check(self):
     if self.state is not NodeState.STARTED:
         return
     try:
         try:
             self.executor.check_subprocess()
         except ProcessExitedWithError as ex:
             raise ScenarioError(
                 f"Raiden node {self._index} died with non-zero exit status: {ex.exit_code}"
             ) from ex
     except BaseException:
         # We do this nested handling to log the proper re-raised ScenarioError
         # exception and message.
         log.exception("Node error")
         raise
Beispiel #29
0
 def _validate_options(self, options: Dict[str, Any]):
     for option_name, option_value in options.items():
         if option_name.startswith('no-'):
             option_name = option_name.replace('no-', '')
         if option_name in MANAGED_CONFIG_OPTIONS:
             raise ScenarioError(
                 f'Raiden node option "{option_name}" is managed by the scenario player '
                 f'and cannot be changed.', )
         if option_name in MANAGED_CONFIG_OPTIONS_OVERRIDABLE:
             log.warning(
                 'Overriding managed option',
                 option_name=option_name,
                 option_value=option_value,
                 node=self._index,
             )
Beispiel #30
0
 def mode(self):
     if self._scenario_version == 2:
         try:
             mode = self._config["mode"].upper()
         except KeyError:
             raise MissingNodesConfiguration(
                 'Version 2 scenarios require a "mode" in the "nodes" section.'
             )
         try:
             return NodeMode[mode]
         except KeyError:
             known_modes = ", ".join(mode.name.lower() for mode in NodeMode)
             raise ScenarioError(
                 f'Unknown node mode "{mode}". Expected one of {known_modes}'
             ) from None
     return NodeMode.EXTERNAL