def __init__(self, role, name, client_name, client, *, type=None, monitoring=None, notification=None, venv_path=None, witness_id=None, signing_key=None, **kwargs): self.role = role if type is not None: self._type = type self.name = name self.witness_signing_key = None self.monitoring = to_list(monitoring) self.notification = to_list(notification) self.client_name = client_name data_dir = client.get('data_dir') if data_dir: data_dir = expanduser(data_dir) try: log.info('Loading RPC config for %s from %s (client = %s)' % (self.name, data_dir, client_name)) config = configparser.ConfigParser() config_str = '[bts]\n' + open( expanduser(join(data_dir, 'config.ini'))).read() # config parser can't handle duplicate values, and we don't need seed nodes config_lines = [ l for l in config_str.splitlines() if not l.startswith('seed-node') ] config.read_string('\n'.join(config_lines)) rpc = { } # FIXME: need it to get the rpc user and rpc password, if necessary try: cfg_port = int(config['bts']['rpc-endpoint'].split(':')[1]) except KeyError: cfg_port = 0 try: if self.affiliation() == 'steem': self.witness_signing_key = config['bts']['private-key'] else: self.witness_signing_key = json.loads( config['bts']['private-key'])[0] except KeyError: self.witness_signing_key = None log.debug('signing key: {}'.format(self.witness_signing_key)) except Exception as e: log.warning('Cannot read RPC config from %s' % data_dir) log.exception(e) rpc = {} cfg_port = None else: rpc = {} cfg_port = None self.witness_host = client.get('witness_host') self.witness_port = client.get('witness_port') self.witness_user = client.get('witness_user') self.witness_password = client.get('witness_password') self.wallet_host = client.get('wallet_host') self.wallet_port = client.get('wallet_port') or cfg_port or 0 self.wallet_user = client.get('wallet_user') self.wallet_password = client.get('wallet_password') self.proxy_host = client.get('proxy_host') self.proxy_port = client.get('proxy_port') self.proxy_user = client.get('proxy_user') self.proxy_password = client.get('proxy_password') self.rpc_id = (self.wallet_host, self.wallet_port) self.ws_rpc_id = (self.witness_host, self.witness_port) self.venv_path = venv_path self.witness_id = witness_id self.witness_signing_key = signing_key or self.witness_signing_key # direct json-rpc call def direct_call(funcname, *args): # we want to avoid connecting to the client and block because # it is in a stopped state (eg: in gdb after having crashed) if self.is_localhost() and not bts_binary_running(self): raise RPCError( 'Connection aborted: {} binary does not seem to be running' .format(self.type())) if self.proxy_host is not None and self.proxy_port is not None: return rpc_call(self.proxy_host, self.proxy_port, None, None, funcname, *args, rpc_args=dict( proxy_user=self.proxy_user, proxy_password=self.proxy_password, wallet_port=self.wallet_port)) return rpc_call(self.wallet_host, self.wallet_port, self.wallet_user, self.wallet_password, funcname, *args) self._rpc_call = direct_call if core.config.get('profile', False): self._rpc_call = core.profile(self._rpc_call) self.opts = kwargs if self.opts: log.debug('Additional opts for node {} - {}'.format( self.name, self.opts)) # get a special "smart" cache for slots as it is a very expensive call self._slot_cache = make_region().configure('dogpile.cache.memory') # caches for committee member and witness names self._witness_names = {} self._committee_member_names = {}
def __init__(self, role, name, client_name, client, type=None, monitoring=None, notification=None, venv_path=None, witness_id=None, signing_key=None, **kwargs): self.role = role if type is not None: self._type = type self.name = name self.witness_signing_key = None self.monitoring = to_list(monitoring) self.notification = to_list(notification) self.client_name = client_name data_dir = client.get('data_dir') if data_dir: data_dir = expanduser(data_dir) try: log.info('Loading RPC config for %s from %s (run_env = %s)' % (self.name, data_dir, client_name)) if is_graphene_based(client_name): config = configparser.ConfigParser() config_str = '[bts]\n' + open(expanduser(join(data_dir, 'config.ini'))).read() # config parser can't handle duplicate values, and we don't need seed nodes config_lines = [l for l in config_str.splitlines() if not l.startswith('seed-node')] config.read_string('\n'.join(config_lines)) rpc = {} # FIXME: need it to get the rpc user and rpc password, if necessary try: cfg_port = int(config['bts']['rpc-endpoint'].split(':')[1]) except KeyError: cfg_port = 0 try: if self.type() == 'steem': self.witness_signing_key = config['bts']['private-key'] else: self.witness_signing_key = json.loads(config['bts']['private-key'])[0] except KeyError: self.witness_signing_key = None log.debug('signing key: {}'.format(self.witness_signing_key)) else: rpc = json.load(open(expanduser(join(data_dir, 'config.json'))))['rpc'] cfg_port = int(rpc['httpd_endpoint'].split(':')[1]) except Exception as e: log.warning('Cannot read RPC config from %s' % data_dir) log.exception(e) rpc = {} cfg_port = None else: rpc = {} cfg_port = None self.witness_host = client.get('witness_host') self.witness_port = client.get('witness_port') self.witness_user = client.get('witness_user') self.witness_password = client.get('witness_password') self.wallet_host = client.get('wallet_host') self.wallet_port = client.get('wallet_port') or client.get('rpc_port') or cfg_port or 0 self.wallet_user = client.get('wallet_user') self.wallet_password = client.get('wallet_password') self.proxy_host = client.get('proxy_host') self.proxy_port = client.get('proxy_port') self.proxy_user = client.get('proxy_user') self.proxy_password = client.get('proxy_password') self.rpc_port = self.proxy_port or self.wallet_port self.rpc_user = self.wallet_user or client.get('rpc_user') or rpc.get('rpc_user') or '' self.rpc_password = self.wallet_password or client.get('rpc_password') or rpc.get('rpc_password') or '' self.rpc_host = self.wallet_host or client.get('rpc_host') or self.proxy_host or 'localhost' self.rpc_id = (self.rpc_host, self.wallet_port) self.ws_rpc_id = (self.witness_host, self.witness_port) self.venv_path = venv_path self.witness_id = witness_id self.witness_signing_key = signing_key or self.witness_signing_key self.bin_name = get_bin_name(client_name or 'bts') if self.is_graphene_based(): # direct json-rpc call def direct_call(funcname, *args): # we want to avoid connecting to the client and block because # it is in a stopped state (eg: in gdb after having crashed) if self.is_localhost() and not bts_binary_running(self): raise RPCError('Connection aborted: {} binary does not seem to be running'.format(self.type())) if self.proxy_host is not None and self.proxy_port is not None: return rpc_call(self.proxy_host, self.proxy_port, None, None, funcname, *args, __graphene=True, rpc_args=dict(proxy_user=self.proxy_user, proxy_password=self.proxy_password, wallet_port=self.wallet_port)) return rpc_call(self.wallet_host, self.wallet_port, self.wallet_user, self.wallet_password, funcname, *args, __graphene=True) self._rpc_call = direct_call elif self.rpc_host == 'localhost': # direct json-rpc call def local_call(funcname, *args): # we want to avoid connecting to the client and block because # it is in a stopped state (eg: in gdb after having crashed) if not bts_binary_running(self): raise RPCError('Connection aborted: {} binary does not seem to be running'.format(self.type())) result = rpc_call('localhost', self.rpc_port, self.rpc_user, self.rpc_password, funcname, *args) return result self._rpc_call = local_call else: raise RuntimeError('Cannot connect to remote host for non-graphene nodes') if core.config.get('profile', False): self._rpc_call = core.profile(self._rpc_call) self.opts = kwargs if self.opts: log.debug('Additional opts for node {} on {}:{} - {}'.format(self.name, self.rpc_host, self.rpc_port, self.opts)) # get a special "smart" cache for slots as it is a very expensive call self._slot_cache = make_region().configure('dogpile.cache.memory') # caches for committee member and witness names self._witness_names = {} self._committee_member_names = {}
def __init__(self, type, name, client=None, monitoring=None, rpc_port=None, rpc_user=None, rpc_password=None, rpc_host=None, venv_path=None, desired_number_of_connections=None, maximum_number_of_connections=None): self.type = type self.name = name self.monitoring = ([] if monitoring is None else [monitoring] if not isinstance(monitoring, list) else monitoring) if client: data_dir = get_data_dir(client) try: log.info('Loading RPC config for %s from %s' % (self.name, data_dir)) rpc = json.load(open(expanduser(join(data_dir, 'config.json'))))['rpc'] cfg_port = int(rpc['httpd_endpoint'].split(':')[1]) except Exception: log.warning('Cannot read RPC config from %s' % data_dir) rpc = {} cfg_port = None else: rpc = {} cfg_port = None self.rpc_port = rpc_port or cfg_port or 0 self.rpc_user = rpc_user or rpc.get('rpc_user') or '' self.rpc_password = rpc_password or rpc.get('rpc_password') or '' self.rpc_host = rpc_host or 'localhost' self.rpc_cache_key = (self.rpc_host, self.rpc_port) self.venv_path = venv_path self.bin_name = get_bin_name(client or 'bts') self.desired_number_of_connections = desired_number_of_connections self.maximum_number_of_connections = maximum_number_of_connections if self.rpc_host == 'localhost': # direct json-rpc call def local_call(funcname, *args): # we want to avoid connecting to the client and block because # it is in a stopped state (eg: in gdb after having crashed) if not bts_binary_running(self): raise RPCError( 'Connection aborted: BTS binary does not seem to be running' ) result = rpc_call('localhost', self.rpc_port, self.rpc_user, self.rpc_password, funcname, *args) return result self._rpc_call = local_call else: # do it over ssh using bts-rpc # FIXME: make sure the password doesn't come out in an ssh log or bash history def remote_call(funcname, *args): cmd = 'ssh %s "' % self.rpc_host if self.venv_path: cmd += 'source %s/bin/activate; ' % self.venv_path #cmd += 'bts-rpc %s %s"' % (funcname, '"%s"' % '" "'.join(str(arg) for arg in args)) cmd += 'bts-rpc %d %s %s %s %s 2>/dev/null"' % ( self.rpc_port, self.rpc_user, self.rpc_password, funcname, ' '.join(str(arg) for arg in args)) result = run(cmd, io=True).stdout try: result = json.loads(result) except: log.error('Error while parsing JSON:') log.error(result) raise if 'error' in result: # re-raise original exception log.debug('Received error in RPC result: %s(%s)' % (result['type'], result['error'])) try: exc_module, exc_class = result['type'].rsplit('.', 1) except ValueError: exc_module, exc_class = 'builtins', result['type'] exc_class = getattr(importlib.import_module(exc_module), exc_class) raise exc_class(result['error']) return result self._rpc_call = remote_call if core.config.get('profile', False): self._rpc_call = core.profile(self._rpc_call) # get a special "smart" cache for slots as it is a very expensive call self._slot_cache = make_region().configure('dogpile.cache.memory')