def test_path_config_defaults_for_linux(self): """Tests the default path configuration settings on Linux and other POSIX environments. Sets os.name to 'posix' (so the test works on all platforms), then compares all path settings to their expected default value. - config_dir = /etc/sawtooth - key_dir = /etc/sawtooth/keys - data_dir = /var/lib/sawtooth - log_dir = /var/log/sawtooth Also specifies a configuration directory which does not exist (as we want to avoid loading any files for this test). The test also attempts to avoid environment variables from interfering with the test by clearing os.environ and restoring it after the test. """ orig_os_name = os.name orig_environ = dict(os.environ) try: os.name = 'posix' os.environ.clear() config = load_path_config() self.assertEqual(config.config_dir, "/etc/sawtooth") self.assertEqual(config.key_dir, "/etc/sawtooth/keys") self.assertEqual(config.data_dir, "/var/lib/sawtooth") self.assertEqual(config.log_dir, "/var/log/sawtooth") finally: os.name = orig_os_name os.environ.update(orig_environ)
def parse_permissions(permissions): roles = {} path_config = load_path_config() policy_dir = path_config.policy_dir if permissions is not None: for role_name in permissions: policy_name = permissions[role_name] policy_path = os.path.join(policy_dir, policy_name) rules = [] if os.path.exists(policy_path): with open(policy_path) as policy_file: rules = policy_file.read().splitlines() entries = [] for rule in rules: rule = rule.split(" ") if rule[0] == "PERMIT_KEY": entry = Policy.Entry(type=Policy.PERMIT_KEY, key=rule[1]) entries.append(entry) elif rule[0] == "DENY_KEY": entry = Policy.Entry(type=Policy.DENY_KEY, key=rule[1]) entries.append(entry) policy = Policy(name=policy_name, entries=entries) roles[role_name] = policy else: LOGGER.warning("%s does not exist. %s will not be set.", policy_path, role_name) if not roles: return None return roles
def main(args=sys.argv[1:]): opts = parse_args(args) verbose_level = opts.verbose init_console_logging(verbose_level=verbose_level) try: path_config = load_path_config(config_dir=opts.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) for line in path_config.to_toml_string(): LOGGER.info("config [path]: %s", line) # Process initial initialization errors, delaying the sys.exit(1) until # all errors have been reported to the user (via LOGGER.error()). This # is intended to provide enough information to the user so they can correct # multiple errors before restarting the validator. init_errors = False if not check_directory(path=path_config.data_dir, human_readable_name='Data'): init_errors = True if not check_directory(path=path_config.log_dir, human_readable_name='Log'): init_errors = True try: identity_signing_key = load_identity_signing_key( key_dir=path_config.key_dir, key_name='validator') except LocalConfigurationError as e: LOGGER.error(str(e)) init_errors = True if init_errors: LOGGER.error("Initialization errors occurred (see previous log " "ERROR messages), shutting down.") sys.exit(1) validator = Validator(opts.network_endpoint, opts.component_endpoint, opts.peers, path_config.data_dir, identity_signing_key) # pylint: disable=broad-except try: validator.start() except KeyboardInterrupt: print("Interrupted!", file=sys.stderr) sys.exit(1) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) except GenesisError as genesis_err: LOGGER.error(str(genesis_err)) sys.exit(1) except Exception as e: LOGGER.exception(e) sys.exit(1)
def test_path_config_load_from_file(self): """Tests loading config settings from a TOML configuration file. Sets the SAWTOOTH_HOME environment variable to a temporary directory, writes a path.toml config file, then loads that config and verifies all the path settings are their expected values. The test also attempts to avoid environment variables from interfering with the test by clearing os.environ and restoring it after the test. """ orig_environ = dict(os.environ) os.environ.clear() directory = tempfile.mkdtemp(prefix="test-path-config-") try: os.environ['SAWTOOTH_HOME'] = directory config_dir = os.path.join(directory, 'etc') os.mkdir(config_dir) with open(os.path.join(config_dir, 'path.toml'), 'w') as fd: fd.write('key_dir = "/tmp/no-such-dir-from-config/keys"') fd.write(os.linesep) fd.write('data_dir = "/tmp/no-such-dir-from-config/data"') fd.write(os.linesep) fd.write('log_dir = "/tmp/no-such-dir-from-config/logs"') fd.write(os.linesep) fd.write('policy_dir = "/tmp/no-such-dir-from-config/policy"') fd.write(os.linesep) config = load_path_config() self.assertEqual(config.config_dir, config_dir) self.assertEqual(config.key_dir, "/tmp/no-such-dir-from-config/keys") self.assertEqual(config.data_dir, "/tmp/no-such-dir-from-config/data") self.assertEqual(config.log_dir, "/tmp/no-such-dir-from-config/logs") self.assertEqual(config.policy_dir, "/tmp/no-such-dir-from-config/policy") finally: os.environ.clear() os.environ.update(orig_environ) shutil.rmtree(directory)
def test_path_config_defaults_sawtooth_home(self): """Tests the default path configuration settings when SAWTOOTH_HOME is set. Sets the SAWTOOTH_HOME environment variable to /tmp/no-such-sawtooth-home, then compares all path settings for their expected values. - config_dir = /tmp/no-such-sawtooth-home/etc - key_dir = /tmp/no-such-sawtooth-home/keys - data_dir = /tmp/no-such-sawtooth-home/data - log_dir = /tmp/no-such-sawtooth-home/logs Also specifies a configuration directory which does not exist (as we want to avoid loading any files for this test). We use a different directory than SAWTOOTH_HOME as the config directory specified for config files should not impact the settings. The test also attempts to avoid environment variables from interfering with the test by clearing os.environ and restoring it after the test. """ orig_environ = dict(os.environ) os.environ.clear() try: os.environ['SAWTOOTH_HOME'] = '/tmp/no-such-sawtooth-home' config = load_path_config() self.assertEqual(config.config_dir, "/tmp/no-such-sawtooth-home/etc") self.assertEqual(config.key_dir, "/tmp/no-such-sawtooth-home/keys") self.assertEqual(config.data_dir, "/tmp/no-such-sawtooth-home/data") self.assertEqual(config.log_dir, "/tmp/no-such-sawtooth-home/logs") self.assertEqual(config.policy_dir, "/tmp/no-such-sawtooth-home/policy") finally: os.environ.clear() os.environ.update(orig_environ)
def test_path_config_defaults_for_windows(self): """Tests the default path configuration settings on Windows operating systems. Sets os.name to 'nt' (so the test works on all platforms), then compares all path settings to their expected default value. - config_dir = /etc/sawtooth - key_dir = /etc/sawtooth/keys - data_dir = /var/lib/sawtooth - log_dir = /var/log/sawtooth Also specifies a configuration directory which does not exist (as we want to avoid loading any files for this test). The test also attempts to avoid environment variables from interfering with the test by clearing os.environ and restoring it after the test. """ orig_os_name = os.name orig_argv0 = sys.argv[0] try: os.name = 'nt' sys.argv[0] = "/tmp/no-such-directory/bin/validator" config = load_path_config() self.assertEqual(config.config_dir, "/tmp/no-such-directory/conf") self.assertEqual(config.key_dir, "/tmp/no-such-directory/conf/keys") self.assertEqual(config.data_dir, "/tmp/no-such-directory/data") self.assertEqual(config.log_dir, "/tmp/no-such-directory/logs") finally: os.name = orig_os_name sys.argv[0] = orig_argv0
def main(args=None): if args is None: args = sys.argv[1:] opts = parse_args(args) verbose_level = opts.verbose # Determine if any args which support delimited lists should be # modified if opts.peers: opts.peers = _split_comma_append_args(opts.peers) if opts.seeds: opts.seeds = _split_comma_append_args(opts.seeds) init_console_logging(verbose_level=verbose_level) if opts.network_auth: opts.network_auth = {"network": opts.network_auth} try: path_config = load_path_config(config_dir=opts.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) try: opts_config = create_validator_config(opts) validator_config = \ load_validator_config(opts_config, path_config.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) # Process initial initialization errors, delaying the sys.exit(1) until # all errors have been reported to the user (via LOGGER.error()). This # is intended to provide enough information to the user so they can correct # multiple errors before restarting the validator. init_errors = False try: identity_signer = load_identity_signer(key_dir=path_config.key_dir, key_name='validator') except LocalConfigurationError as e: log_configuration(log_dir=path_config.log_dir, name="validator") LOGGER.error(str(e)) init_errors = True log_config = get_log_config() if not init_errors: if log_config is not None: log_configuration(log_config=log_config) if log_config.get('root') is not None: init_console_logging(verbose_level=verbose_level) else: log_configuration(log_dir=path_config.log_dir, name="validator") try: version = pkg_resources.get_distribution(DISTRIBUTION_NAME).version except pkg_resources.DistributionNotFound: version = 'UNKNOWN' LOGGER.info('%s (Hyperledger Sawtooth) version %s', DISTRIBUTION_NAME, version) if LOGGER.isEnabledFor(logging.INFO): LOGGER.info('; '.join([ 'config [path]: {}'.format(line) for line in path_config.to_toml_string() ])) if not check_directory(path=path_config.data_dir, human_readable_name='Data'): init_errors = True if not check_directory(path=path_config.log_dir, human_readable_name='Log'): init_errors = True endpoint = validator_config.endpoint if endpoint is None: # Need to use join here to get the string "0.0.0.0". Otherwise, # bandit thinks we are binding to all interfaces and returns a # Medium security risk. interfaces = ["*", ".".join(["0", "0", "0", "0"])] interfaces += netifaces.interfaces() endpoint = validator_config.bind_network for interface in interfaces: if interface in validator_config.bind_network: LOGGER.error("Endpoint must be set when using %s", interface) init_errors = True break if init_errors: LOGGER.error("Initialization errors occurred (see previous log " "ERROR messages), shutting down.") sys.exit(1) bind_network = validator_config.bind_network bind_component = validator_config.bind_component if "tcp://" not in bind_network: bind_network = "tcp://" + bind_network if "tcp://" not in bind_component: bind_component = "tcp://" + bind_component if validator_config.network_public_key is None or \ validator_config.network_private_key is None: LOGGER.warning("Network key pair is not configured, Network " "communications between validators will not be " "authenticated or encrypted.") wrapped_registry = None metrics_reporter = None if validator_config.opentsdb_url: LOGGER.info("Adding metrics reporter: url=%s, db=%s", validator_config.opentsdb_url, validator_config.opentsdb_db) url = urlparse(validator_config.opentsdb_url) proto, db_server, db_port, = url.scheme, url.hostname, url.port registry = MetricsRegistry() wrapped_registry = MetricsRegistryWrapper(registry) metrics_reporter = InfluxReporter( registry=registry, reporting_interval=10, database=validator_config.opentsdb_db, prefix="sawtooth_validator", port=db_port, protocol=proto, server=db_server, username=validator_config.opentsdb_username, password=validator_config.opentsdb_password) metrics_reporter.start() # Verify state integrity before startup verify_state(bind_network, bind_component, validator_config.scheduler, path_config.data_dir) LOGGER.info('Starting validator with %s scheduler', validator_config.scheduler) validator = Validator(bind_network, bind_component, endpoint, validator_config.peering, validator_config.seeds, validator_config.peers, path_config.data_dir, path_config.config_dir, identity_signer, validator_config.scheduler, validator_config.permissions, validator_config.minimum_peer_connectivity, validator_config.maximum_peer_connectivity, validator_config.network_public_key, validator_config.network_private_key, roles=validator_config.roles, metrics_registry=wrapped_registry) # pylint: disable=broad-except try: validator.start() except KeyboardInterrupt: LOGGER.info("Initiating graceful " "shutdown (press Ctrl+C again to force)") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) except GenesisError as genesis_err: LOGGER.error(str(genesis_err)) sys.exit(1) except Exception as e: LOGGER.exception(e) sys.exit(1) finally: if metrics_reporter: metrics_reporter.stop() validator.stop()
def main(args=None): if args is None: args = sys.argv[1:] opts = parse_args(args) verbose_level = opts.verbose # Determine if any args which support delimited lists should be # modified if opts.peers: opts.peers = _split_comma_append_args(opts.peers) if opts.seeds: opts.seeds = _split_comma_append_args(opts.seeds) init_console_logging(verbose_level=verbose_level) if opts.network_auth: opts.network_auth = {"network": opts.network_auth} try: path_config = load_path_config(config_dir=opts.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) try: opts_config = create_validator_config(opts) validator_config = \ load_validator_config(opts_config, path_config.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) # Process initial initialization errors, delaying the sys.exit(1) until # all errors have been reported to the user (via LOGGER.error()). This # is intended to provide enough information to the user so they can correct # multiple errors before restarting the validator. init_errors = False try: identity_signer = load_identity_signer( key_dir=path_config.key_dir, key_name='validator') except LocalConfigurationError as e: log_configuration(log_dir=path_config.log_dir, name="validator") LOGGER.error(str(e)) init_errors = True log_config = get_log_config() if not init_errors: if log_config is not None: log_configuration(log_config=log_config) if log_config.get('root') is not None: init_console_logging(verbose_level=verbose_level) else: log_configuration(log_dir=path_config.log_dir, name="validator") try: version = pkg_resources.get_distribution(DISTRIBUTION_NAME).version except pkg_resources.DistributionNotFound: version = 'UNKNOWN' LOGGER.info( '%s (Hyperledger Sawtooth) version %s', DISTRIBUTION_NAME, version) if LOGGER.isEnabledFor(logging.INFO): LOGGER.info( '; '.join([ 'config [path]: {}'.format(line) for line in path_config.to_toml_string() ]) ) if not check_directory(path=path_config.data_dir, human_readable_name='Data'): init_errors = True if not check_directory(path=path_config.log_dir, human_readable_name='Log'): init_errors = True endpoint = validator_config.endpoint if endpoint is None: # Need to use join here to get the string "0.0.0.0". Otherwise, # bandit thinks we are binding to all interfaces and returns a # Medium security risk. interfaces = ["*", ".".join(["0", "0", "0", "0"])] interfaces += netifaces.interfaces() endpoint = validator_config.bind_network for interface in interfaces: if interface in validator_config.bind_network: LOGGER.error("Endpoint must be set when using %s", interface) init_errors = True break if init_errors: LOGGER.error("Initialization errors occurred (see previous log " "ERROR messages), shutting down.") sys.exit(1) bind_network = validator_config.bind_network bind_component = validator_config.bind_component if "tcp://" not in bind_network: bind_network = "tcp://" + bind_network if "tcp://" not in bind_component: bind_component = "tcp://" + bind_component if validator_config.network_public_key is None or \ validator_config.network_private_key is None: LOGGER.warning("Network key pair is not configured, Network " "communications between validators will not be " "authenticated or encrypted.") wrapped_registry = None metrics_reporter = None if validator_config.opentsdb_url: LOGGER.info("Adding metrics reporter: url=%s, db=%s", validator_config.opentsdb_url, validator_config.opentsdb_db) url = urlparse(validator_config.opentsdb_url) proto, db_server, db_port, = url.scheme, url.hostname, url.port registry = MetricsRegistry() wrapped_registry = MetricsRegistryWrapper(registry) metrics_reporter = InfluxReporter( registry=registry, reporting_interval=10, database=validator_config.opentsdb_db, prefix="sawtooth_validator", port=db_port, protocol=proto, server=db_server, username=validator_config.opentsdb_username, password=validator_config.opentsdb_password) metrics_reporter.start() LOGGER.info( 'Starting validator with %s scheduler', validator_config.scheduler) validator = Validator( bind_network, bind_component, endpoint, validator_config.peering, validator_config.seeds, validator_config.peers, path_config.data_dir, path_config.config_dir, identity_signer, validator_config.scheduler, validator_config.permissions, validator_config.minimum_peer_connectivity, validator_config.maximum_peer_connectivity, validator_config.network_public_key, validator_config.network_private_key, roles=validator_config.roles, metrics_registry=wrapped_registry) # pylint: disable=broad-except try: validator.start() except KeyboardInterrupt: LOGGER.info("Initiating graceful " "shutdown (press Ctrl+C again to force)") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) except GenesisError as genesis_err: LOGGER.error(str(genesis_err)) sys.exit(1) except Exception as e: LOGGER.exception(e) sys.exit(1) finally: if metrics_reporter: metrics_reporter.stop() validator.stop()
def main(args=sys.argv[1:]): opts = parse_args(args) verbose_level = opts.verbose # Determine if any args which support delimited lists should be # modified if opts.peers: opts.peers = _split_comma_append_args(opts.peers) if opts.join: opts.join = _split_comma_append_args(opts.join) init_console_logging(verbose_level=verbose_level) try: path_config = load_path_config(config_dir=opts.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) # Process initial initialization errors, delaying the sys.exit(1) until # all errors have been reported to the user (via LOGGER.error()). This # is intended to provide enough information to the user so they can correct # multiple errors before restarting the validator. init_errors = False try: identity_signing_key = load_identity_signing_key( key_dir=path_config.key_dir, key_name='validator') pubkey = signing.generate_pubkey(identity_signing_key) except LocalConfigurationError as e: log_configuration(log_dir=path_config.log_dir, name="validator") LOGGER.error(str(e)) init_errors = True log_config = get_log_config() if not init_errors: if log_config is not None: log_configuration(log_config=log_config) if log_config.get('root') is not None: init_console_logging(verbose_level=verbose_level) else: log_configuration(log_dir=path_config.log_dir, name="validator-" + pubkey[:8]) for line in path_config.to_toml_string(): LOGGER.info("config [path]: %s", line) if not check_directory(path=path_config.data_dir, human_readable_name='Data'): init_errors = True if not check_directory(path=path_config.log_dir, human_readable_name='Log'): init_errors = True if init_errors: LOGGER.error("Initialization errors occurred (see previous log " "ERROR messages), shutting down.") sys.exit(1) validator = Validator(opts.network_endpoint, opts.component_endpoint, opts.public_uri, opts.peering, opts.join, opts.peers, path_config.data_dir, identity_signing_key) # pylint: disable=broad-except try: validator.start() except KeyboardInterrupt: LOGGER.info("Initiating graceful " "shutdown (press Ctrl+C again to force)") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) except GenesisError as genesis_err: LOGGER.error(str(genesis_err)) sys.exit(1) except Exception as e: LOGGER.exception(e) sys.exit(1) finally: validator.stop()
def main(args): try: path_config = load_path_config(config_dir=args['config_dir']) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) try: opts_config = ValidatorConfig( bind_component=args['bind_component'], bind_network=args['bind_network'], bind_consensus=args['bind_consensus'], endpoint=args['endpoint'], maximum_peer_connectivity=args['maximum_peer_connectivity'], minimum_peer_connectivity=args['minimum_peer_connectivity'], roles=args['roles'], opentsdb_db=args['opentsdb_db'], opentsdb_url=args['opentsdb_url'], peering=args['peering'], peers=args['peers'], scheduler=args['scheduler'], seeds=args['seeds'], state_pruning_block_depth=args['state_pruning_block_depth'], fork_cache_keep_time=args['fork_cache_keep_time'], ) validator_config = \ load_validator_config(opts_config, path_config.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) try: log_configuration(log_dir=path_config.log_dir, name="validator") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) # Process initial initialization errors, delaying the sys.exit(1) until # all errors have been reported to the user (via LOGGER.error()). This # is intended to provide enough information to the user so they can correct # multiple errors before restarting the validator. init_errors = False try: identity_signer = load_identity_signer(key_dir=path_config.key_dir, key_name='validator') except LocalConfigurationError as e: LOGGER.error(str(e)) init_errors = True log_config = get_log_config() if not init_errors: if log_config is not None: log_configuration(log_config=log_config) if log_config.get('root') is not None: init_console_logging(verbose_level=args['verbose']) else: log_configuration(log_dir=path_config.log_dir, name="validator") try: version = pkg_resources.get_distribution(DISTRIBUTION_NAME).version except pkg_resources.DistributionNotFound: version = 'UNKNOWN' LOGGER.info('%s (Hyperledger Sawtooth) version %s', DISTRIBUTION_NAME, version) if LOGGER.isEnabledFor(logging.INFO): LOGGER.info('; '.join([ 'config [path]: {}'.format(line) for line in path_config.to_toml_string() ])) if not check_directory(path=path_config.data_dir, human_readable_name='Data'): init_errors = True if not check_directory(path=path_config.log_dir, human_readable_name='Log'): init_errors = True endpoint = validator_config.endpoint if endpoint is None: # Need to use join here to get the string "0.0.0.0". Otherwise, # bandit thinks we are binding to all interfaces and returns a # Medium security risk. interfaces = ["*", ".".join(["0", "0", "0", "0"])] interfaces += netifaces.interfaces() endpoint = validator_config.bind_network parsed_endpoint = urlparse(validator_config.bind_network) for interface in interfaces: if interface == parsed_endpoint.hostname: LOGGER.error("Endpoint must be set when using %s", interface) init_errors = True if init_errors: LOGGER.error("Initialization errors occurred (see previous log " "ERROR messages), shutting down.") sys.exit(1) bind_network = validator_config.bind_network bind_component = validator_config.bind_component bind_consensus = validator_config.bind_consensus if "tcp://" not in bind_network: bind_network = "tcp://" + bind_network if "tcp://" not in bind_component: bind_component = "tcp://" + bind_component if bind_consensus and "tcp://" not in bind_consensus: bind_consensus = "tcp://" + bind_consensus if validator_config.network_public_key is None or \ validator_config.network_private_key is None: LOGGER.warning("Network key pair is not configured, Network " "communications between validators will not be " "authenticated or encrypted.") metrics_reporter = None if validator_config.opentsdb_url: LOGGER.info("Adding metrics reporter: url=%s, db=%s", validator_config.opentsdb_url, validator_config.opentsdb_db) url = urlparse(validator_config.opentsdb_url) proto, db_server, db_port, = url.scheme, url.hostname, url.port registry = MetricsRegistry() metrics.init_metrics(registry=registry) metrics_reporter = InfluxReporter( registry=registry, reporting_interval=10, database=validator_config.opentsdb_db, prefix="sawtooth_validator", port=db_port, protocol=proto, server=db_server, username=validator_config.opentsdb_username, password=validator_config.opentsdb_password) metrics_reporter.start() else: metrics.init_metrics() # Verify state integrity before startup global_state_db, blockstore = state_verifier.get_databases( bind_network, path_config.data_dir) state_verifier.verify_state(global_state_db, blockstore, bind_component, validator_config.scheduler) # Explicitly drop this, so there are not two db instances global_state_db.drop() global_state_db = None LOGGER.info('Starting validator with %s scheduler', validator_config.scheduler) component_workers = validator_config.component_thread_pool_workers network_workers = validator_config.network_thread_pool_workers sig_workers = validator_config.signature_thread_pool_workers validator = Validator(bind_network, bind_component, bind_consensus, endpoint, validator_config.peering, validator_config.seeds, validator_config.peers, path_config.data_dir, path_config.config_dir, identity_signer, path_config.key_dir, validator_config.scheduler, validator_config.permissions, validator_config.minimum_peer_connectivity, validator_config.maximum_peer_connectivity, validator_config.state_pruning_block_depth, validator_config.fork_cache_keep_time, validator_config.network_public_key, validator_config.network_private_key, roles=validator_config.roles, component_thread_pool_workers=component_workers, network_thread_pool_workers=network_workers, signature_thread_pool_workers=sig_workers) # pylint: disable=broad-except try: validator.start() except KeyboardInterrupt: LOGGER.info("Initiating graceful " "shutdown (press Ctrl+C again to force)") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) except GenesisError as genesis_err: LOGGER.error(str(genesis_err)) sys.exit(1) except Exception as e: LOGGER.exception(e) sys.exit(1) finally: if metrics_reporter: metrics_reporter.stop() validator.stop()
def main(args): try: path_config = load_path_config(config_dir=args['config_dir']) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) try: opts_config = ValidatorConfig( bind_component=args['bind_component'], bind_network=args['bind_network'], bind_consensus=args['bind_consensus'], endpoint=args['endpoint'], maximum_peer_connectivity=args['maximum_peer_connectivity'], minimum_peer_connectivity=args['minimum_peer_connectivity'], roles=args['roles'], opentsdb_db=args['opentsdb_db'], opentsdb_url=args['opentsdb_url'], peering=args['peering'], peers=args['peers'], scheduler=args['scheduler'], seeds=args['seeds'], state_pruning_block_depth=args['state_pruning_block_depth'], fork_cache_keep_time=args['fork_cache_keep_time'], ) validator_config = \ load_validator_config(opts_config, path_config.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) try: log_configuration(log_dir=path_config.log_dir, name="validator") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) # Process initial initialization errors, delaying the sys.exit(1) until # all errors have been reported to the user (via LOGGER.error()). This # is intended to provide enough information to the user so they can correct # multiple errors before restarting the validator. init_errors = False try: identity_signer = load_identity_signer( key_dir=path_config.key_dir, key_name='validator') except LocalConfigurationError as e: LOGGER.error(str(e)) init_errors = True log_config = get_log_config() if not init_errors: if log_config is not None: log_configuration(log_config=log_config) if log_config.get('root') is not None: init_console_logging(verbose_level=args['verbose']) else: log_configuration(log_dir=path_config.log_dir, name="validator") try: version = pkg_resources.get_distribution(DISTRIBUTION_NAME).version except pkg_resources.DistributionNotFound: version = 'UNKNOWN' LOGGER.info( '%s (Hyperledger Sawtooth) version %s', DISTRIBUTION_NAME, version) if LOGGER.isEnabledFor(logging.INFO): LOGGER.info( '; '.join([ 'config [path]: {}'.format(line) for line in path_config.to_toml_string() ]) ) if not check_directory(path=path_config.data_dir, human_readable_name='Data'): init_errors = True if not check_directory(path=path_config.log_dir, human_readable_name='Log'): init_errors = True endpoint = validator_config.endpoint if endpoint is None: # Need to use join here to get the string "0.0.0.0". Otherwise, # bandit thinks we are binding to all interfaces and returns a # Medium security risk. interfaces = ["*", ".".join(["0", "0", "0", "0"])] interfaces += netifaces.interfaces() endpoint = validator_config.bind_network parsed_endpoint = urlparse(validator_config.bind_network) for interface in interfaces: if interface == parsed_endpoint.hostname: LOGGER.error("Endpoint must be set when using %s", interface) init_errors = True if init_errors: LOGGER.error("Initialization errors occurred (see previous log " "ERROR messages), shutting down.") sys.exit(1) bind_network = validator_config.bind_network bind_component = validator_config.bind_component bind_consensus = validator_config.bind_consensus if "tcp://" not in bind_network: bind_network = "tcp://" + bind_network if "tcp://" not in bind_component: bind_component = "tcp://" + bind_component if bind_consensus and "tcp://" not in bind_consensus: bind_consensus = "tcp://" + bind_consensus if validator_config.network_public_key is None or \ validator_config.network_private_key is None: LOGGER.warning("Network key pair is not configured, Network " "communications between validators will not be " "authenticated or encrypted.") metrics_reporter = None if validator_config.opentsdb_url: LOGGER.info("Adding metrics reporter: url=%s, db=%s", validator_config.opentsdb_url, validator_config.opentsdb_db) url = urlparse(validator_config.opentsdb_url) proto, db_server, db_port, = url.scheme, url.hostname, url.port registry = MetricsRegistry() metrics.init_metrics(registry=registry) metrics_reporter = InfluxReporter( registry=registry, reporting_interval=10, database=validator_config.opentsdb_db, prefix="sawtooth_validator", port=db_port, protocol=proto, server=db_server, username=validator_config.opentsdb_username, password=validator_config.opentsdb_password) metrics_reporter.start() else: metrics.init_metrics() # Verify state integrity before startup global_state_db, blockstore = state_verifier.get_databases( bind_network, path_config.data_dir) state_verifier.verify_state( global_state_db, blockstore, bind_component, validator_config.scheduler) # Explicitly drop this, so there are not two db instances global_state_db.drop() global_state_db = None LOGGER.info( 'Starting validator with %s scheduler', validator_config.scheduler) component_workers = validator_config.component_thread_pool_workers network_workers = validator_config.network_thread_pool_workers sig_workers = validator_config.signature_thread_pool_workers validator = Validator( bind_network, bind_component, bind_consensus, endpoint, validator_config.peering, validator_config.seeds, validator_config.peers, path_config.data_dir, path_config.config_dir, identity_signer, validator_config.scheduler, validator_config.permissions, validator_config.minimum_peer_connectivity, validator_config.maximum_peer_connectivity, validator_config.state_pruning_block_depth, validator_config.fork_cache_keep_time, validator_config.network_public_key, validator_config.network_private_key, roles=validator_config.roles, component_thread_pool_workers=component_workers, network_thread_pool_workers=network_workers, signature_thread_pool_workers=sig_workers) # pylint: disable=broad-except try: validator.start() except KeyboardInterrupt: LOGGER.info("Initiating graceful " "shutdown (press Ctrl+C again to force)") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) except GenesisError as genesis_err: LOGGER.error(str(genesis_err)) sys.exit(1) except Exception as e: LOGGER.exception(e) sys.exit(1) finally: if metrics_reporter: metrics_reporter.stop() validator.stop()
def main(args=None): if args is None: args = sys.argv[1:] opts = parse_args(args) verbose_level = opts.verbose # Determine if any args which support delimited lists should be # modified if opts.peers: opts.peers = _split_comma_append_args(opts.peers) if opts.seeds: opts.seeds = _split_comma_append_args(opts.seeds) init_console_logging(verbose_level=verbose_level) try: path_config = load_path_config(config_dir=opts.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) try: opts_config = create_validator_config(opts) validator_config = \ load_validator_config(opts_config, path_config.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) # Process initial initialization errors, delaying the sys.exit(1) until # all errors have been reported to the user (via LOGGER.error()). This # is intended to provide enough information to the user so they can correct # multiple errors before restarting the validator. init_errors = False try: identity_signing_key = load_identity_signing_key( key_dir=path_config.key_dir, key_name='validator') pubkey = signing.generate_pubkey(identity_signing_key) except LocalConfigurationError as e: log_configuration(log_dir=path_config.log_dir, name="validator") LOGGER.error(str(e)) init_errors = True log_config = get_log_config() if not init_errors: if log_config is not None: log_configuration(log_config=log_config) if log_config.get('root') is not None: init_console_logging(verbose_level=verbose_level) else: log_configuration(log_dir=path_config.log_dir, name="validator-" + pubkey[:8]) for line in path_config.to_toml_string(): LOGGER.info("config [path]: %s", line) if not check_directory(path=path_config.data_dir, human_readable_name='Data'): init_errors = True if not check_directory(path=path_config.log_dir, human_readable_name='Log'): init_errors = True endpoint = validator_config.endpoint if endpoint is None: # Need to use join here to get the string "0.0.0.0". Otherwise, # bandit thinks we are binding to all interfaces and returns a # Medium security risk. interfaces = ["*", ".".join(["0", "0", "0", "0"])] interfaces += netifaces.interfaces() endpoint = validator_config.bind_network for interface in interfaces: if interface in validator_config.bind_network: LOGGER.error("Endpoint must be set when using %s", interface) init_errors = True break if init_errors: LOGGER.error("Initialization errors occurred (see previous log " "ERROR messages), shutting down.") sys.exit(1) bind_network = validator_config.bind_network bind_component = validator_config.bind_component if "tcp://" not in bind_network: bind_network = "tcp://" + bind_network if "tcp://" not in bind_component: bind_component = "tcp://" + bind_component if validator_config.network_public_key is None or \ validator_config.network_private_key is None: LOGGER.warning("Network key pair is not configured, Network " "communications between validators will not be " "authenticated or encrypted.") validator = Validator(bind_network, bind_component, endpoint, validator_config.peering, validator_config.seeds, validator_config.peers, path_config.data_dir, path_config.config_dir, identity_signing_key, validator_config.scheduler, validator_config.permissions, validator_config.network_public_key, validator_config.network_private_key) # pylint: disable=broad-except try: validator.start() except KeyboardInterrupt: LOGGER.info("Initiating graceful " "shutdown (press Ctrl+C again to force)") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) except GenesisError as genesis_err: LOGGER.error(str(genesis_err)) sys.exit(1) except Exception as e: LOGGER.exception(e) sys.exit(1) finally: validator.stop()
def main(args=None): if args is None: args = sys.argv[1:] opts = parse_args(args) verbose_level = opts.verbose # Determine if any args which support delimited lists should be # modified if opts.peers: opts.peers = _split_comma_append_args(opts.peers) if opts.seeds: opts.seeds = _split_comma_append_args(opts.seeds) init_console_logging(verbose_level=verbose_level) try: path_config = load_path_config(config_dir=opts.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) try: opts_config = create_validator_config(opts) validator_config = \ load_validator_config(opts_config, path_config.config_dir) except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) # Process initial initialization errors, delaying the sys.exit(1) until # all errors have been reported to the user (via LOGGER.error()). This # is intended to provide enough information to the user so they can correct # multiple errors before restarting the validator. init_errors = False try: identity_signing_key = load_identity_signing_key( key_dir=path_config.key_dir, key_name='validator') pubkey = signing.generate_pubkey(identity_signing_key) except LocalConfigurationError as e: log_configuration(log_dir=path_config.log_dir, name="validator") LOGGER.error(str(e)) init_errors = True log_config = get_log_config() if not init_errors: if log_config is not None: log_configuration(log_config=log_config) if log_config.get('root') is not None: init_console_logging(verbose_level=verbose_level) else: log_configuration(log_dir=path_config.log_dir, name="validator-" + pubkey[:8]) for line in path_config.to_toml_string(): LOGGER.info("config [path]: %s", line) if not check_directory(path=path_config.data_dir, human_readable_name='Data'): init_errors = True if not check_directory(path=path_config.log_dir, human_readable_name='Log'): init_errors = True endpoint = validator_config.endpoint if endpoint is None: # Need to use join here to get the string "0.0.0.0". Otherwise, # bandit thinks we are binding to all interfaces and returns a # Medium security risk. interfaces = ["*", ".".join(["0", "0", "0", "0"])] interfaces += netifaces.interfaces() endpoint = validator_config.bind_network for interface in interfaces: if interface in validator_config.bind_network: LOGGER.error("Endpoint must be set when using %s", interface) init_errors = True break if init_errors: LOGGER.error("Initialization errors occurred (see previous log " "ERROR messages), shutting down.") sys.exit(1) bind_network = validator_config.bind_network bind_component = validator_config.bind_component if "tcp://" not in bind_network: bind_network = "tcp://" + bind_network if "tcp://" not in bind_component: bind_component = "tcp://" + bind_component if validator_config.network_public_key is None or \ validator_config.network_private_key is None: LOGGER.warning("Network key pair is not configured, Network " "communications between validators will not be " "authenticated or encrypted.") validator = Validator(bind_network, bind_component, endpoint, validator_config.peering, validator_config.seeds, validator_config.peers, path_config.data_dir, path_config.config_dir, identity_signing_key, validator_config.network_public_key, validator_config.network_private_key) # pylint: disable=broad-except try: validator.start() except KeyboardInterrupt: LOGGER.info("Initiating graceful " "shutdown (press Ctrl+C again to force)") except LocalConfigurationError as local_config_err: LOGGER.error(str(local_config_err)) sys.exit(1) except GenesisError as genesis_err: LOGGER.error(str(genesis_err)) sys.exit(1) except Exception as e: LOGGER.exception(e) sys.exit(1) finally: validator.stop()