def get_update_handler(): """ Construct and return an update handler from the configuration data. """ action, model, interval = (None, DEFAULT_MODEL, DEFAULT_INTERVAL) try: config = ConfigurationParser() action = config.get("updates", "action") try: model = config.get("updates", "model") except NoOptionError: pass try: str_interval = config.get("updates", "interval") interval = int(str_interval) except (NoOptionError, ValueError): pass except (NoSectionError, NoOptionError): pass (bleeding_edge, api_url) = __parse_model(model) if not action: notifyer = None elif "notify" == action.lower(): notifyer = UpdateNotifyer(REPO, api_url, bleeding_edge, interval) else: raise UnknownAction(action) return notifyer
def test_notify_on_stable_no_interval(self): """ Make sure that the default interval is used for the StableUpdater, if no default interval is given in the configuration. """ mock_file = self.mox.CreateMockAnything() mock_timer = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" action, model = ("notify", "stable") self.mox.StubOutWithMock(SafeConfigParser, "get") self.mox.StubOutWithMock(StableUpdater, "__init__") self.mox.StubOutWithMock(threading, "Timer") config = ConfigurationParser() config.parse(mock_file) config.get("updates", "action").AndReturn(action) config.get("updates", "model").AndReturn(model) config.get("updates", "interval").AndRaise(NoOptionError("updates", "interval")) StableUpdater.__init__(REPO, construct_url_for_version_file()) threading.Timer(DEFAULT_INTERVAL, mox.IgnoreArg()).AndReturn(mock_timer) mock_timer.start() self.mox.ReplayAll() update_handler = get_update_handler() update_handler.start() self.assertTrue(isinstance(update_handler, UpdateNotifyer))
def test_notify_on_stable_interval(self): """ Make sure that an UpdateNotifyer, with a StableUpdater, for the configured interval is constructed when the configuration data indicates so. """ mock_file = self.mox.CreateMockAnything() mock_timer = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" action, model, interval = ("notify", "stable", "43200") self.mox.StubOutWithMock(SafeConfigParser, "get") self.mox.StubOutWithMock(StableUpdater, "__init__") self.mox.StubOutWithMock(threading, "Timer") config = ConfigurationParser() config.parse(mock_file) config.get("updates", "action").AndReturn(action) config.get("updates", "model").AndReturn(model) config.get("updates", "interval").AndReturn(interval) StableUpdater.__init__(REPO, construct_url_for_version_file()) threading.Timer(int(interval), mox.IgnoreArg()).AndReturn(mock_timer) mock_timer.start() self.mox.ReplayAll() update_handler = get_update_handler() update_handler.start() self.assertTrue(isinstance(update_handler, UpdateNotifyer))
def test_notify_on_stable_malformed_interval(self): """ A malformed interval in the configuration (i.e. non-integer) should result in the default interval being used. """ mock_file = self.mox.CreateMockAnything() mock_timer = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" action, model, interval = ("notify", "stable", "FOO") self.mox.StubOutWithMock(SafeConfigParser, "get") self.mox.StubOutWithMock(StableUpdater, "__init__") self.mox.StubOutWithMock(threading, "Timer") config = ConfigurationParser() config.parse(mock_file) config.get("updates", "action").AndReturn(action) config.get("updates", "model").AndReturn(model) config.get("updates", "interval").AndReturn(interval) StableUpdater.__init__(REPO, construct_url_for_version_file()) threading.Timer(DEFAULT_INTERVAL, mox.IgnoreArg()).AndReturn(mock_timer) mock_timer.start() self.mox.ReplayAll() update_handler = get_update_handler() update_handler.start() self.assertTrue(isinstance(update_handler, UpdateNotifyer))
def test_notify_on_bleeding_edge_interval(self): """ Make sure that a BleedingEdgeUpdater is constructed if the configuration details it. """ mock_file = self.mox.CreateMockAnything() mock_timer = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" action, model, interval = ("notify", "bleeding", "43200") self.mox.StubOutWithMock(SafeConfigParser, "get") self.mox.StubOutWithMock(BleedingEdgeUpdater, "__init__") self.mox.StubOutWithMock(threading, "Timer") config = ConfigurationParser() config.parse(mock_file) config.get("updates", "action").AndReturn(action) config.get("updates", "model").AndReturn(model) config.get("updates", "interval").AndReturn(interval) BleedingEdgeUpdater.__init__(REPO, construct_url_for_head_commit()) threading.Timer(int(interval), mox.IgnoreArg()).AndReturn(mock_timer) mock_timer.start() self.mox.ReplayAll() update_handler = get_update_handler() update_handler.start() self.assertTrue(isinstance(update_handler, UpdateNotifyer))
def test_get_credentials_missing_section(self): """ Test reading the credentials from a configuration file where the credentials section is missing (uninitialized). """ mock_file = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" username, password = ("*****@*****.**", "password") self.mox.StubOutWithMock(SafeConfigParser, "get") self.mox.StubOutWithMock(SafeConfigParser, "add_section") self.mox.StubOutWithMock(SafeConfigParser, "set") self.mox.StubOutWithMock(__builtin__, "raw_input") config = ConfigurationParser() config.parse(mock_file) error = NoSectionError("credentials") config.get("credentials", "username").AndRaise(error) config.add_section("credentials") raw_input(mox.IgnoreArg()).AndReturn(username) raw_input(mox.IgnoreArg()).AndReturn(password) config.set("credentials", "username", username) config.set("credentials", "password", password) self.mox.ReplayAll() self.assertEquals((username, password), credentials.get_credentials())
def test_parsing_existing_configuration_file(self): """ Test the parsing of an 'existing' file """ existing_config_file = self.mox.CreateMockAnything() existing_config_file.closed = False existing_config_file.name = "foobar" self.mox.StubOutWithMock(SafeConfigParser, "read") SafeConfigParser.read(existing_config_file.name) self.mox.ReplayAll() config = ConfigurationParser() try: config.parse(existing_config_file) except FileNotFoundException: self.fail()
def restricted_set(): """ Returns the restricted command set to be allowed (if the RestrictedCommandHandler is to be used). The command set is defined as a List of tuples of (cmd, args, help), where cmd is the command to execute in a shell, args is the command arguments, and hlp is the help to display upon receiving the help command. """ result = [] config = ConfigurationParser() if config.has_section("commands"): options = config.items("commands") result = map(__transform_set, [tuple(value.split(':')) for (_, value) in options]) return result
def test_update_section_no_action(self): """ If there is no configured action, no update handler should be constructed. """ mock_file = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" self.mox.StubOutWithMock(SafeConfigParser, "get") self.mox.StubOutWithMock(StableUpdater, "__init__") config = ConfigurationParser() config.parse(mock_file) config.get("updates", "action").AndRaise(NoOptionError("updates", "action")) self.mox.ReplayAll() self.assertEqual(None, get_update_handler())
def test_get_credentials(self): """ Ensure proper behavior when the configuration file contains the username-password pair. """ mock_file = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" username, password = ("*****@*****.**", "password") self.mox.StubOutWithMock(SafeConfigParser, "get") config = ConfigurationParser() config.parse(mock_file) config.get("credentials", "username").AndReturn(username) config.get("credentials", "password").AndReturn(password) self.mox.ReplayAll() self.assertEquals((username, password), credentials.get_credentials())
def get_command_handler(): """ Returns the command handler that is to parse incoming commands. """ config = ConfigurationParser() handlers = { "restricted": RestrictedCommandHandler(), "passthru": UnsafeCommandHandler() } try: configured_handler = config.get("general", "handler").lower() except NoSectionError: raise UnknownHandler("[general] section not found in configuration") except NoOptionError: raise UnknownHandler("handler option not found under [general] section") result = handlers.get(configured_handler) if not result: raise UnknownHandler("unknown handler (valid are restricted/passthru") return result
def test_setting_option(self): """ Test setting an option - this should be a simple delegate to SafeConfigParser.set, with a write upon successful set. """ mock_file = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" self.mox.StubOutWithMock(SafeConfigParser, "read") self.mox.StubOutWithMock(SafeConfigParser, "set") self.mox.StubOutWithMock(SafeConfigParser, "write") SafeConfigParser.read(mock_file.name) SafeConfigParser.set("credentials", "username", "foo") mock_file.truncate(0) mock_file.flush() SafeConfigParser.write(mock_file) self.mox.ReplayAll() config = ConfigurationParser() config.parse(mock_file) config.set("credentials", "username", "foo")
def test_removing_section(self): """ Test removin a section - this should be a simple delegate to SafeConfigParser.remove_section, with a write upon successful removal. """ mock_file = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" self.mox.StubOutWithMock(SafeConfigParser, "read") self.mox.StubOutWithMock(SafeConfigParser, "remove_section") self.mox.StubOutWithMock(SafeConfigParser, "write") SafeConfigParser.read(mock_file.name) SafeConfigParser.remove_section("credentials") mock_file.truncate(0) mock_file.flush() SafeConfigParser.write(mock_file) self.mox.ReplayAll() config = ConfigurationParser() config.parse(mock_file) config.remove_section("credentials")
def test_update_section_unknown_model(self): """ If the configured model string does not match a known model, an UnknownModel exception should be raised. """ mock_file = self.mox.CreateMockAnything() mock_file.closed = False mock_file.name = "foobar" action, model, interval = ("notify", "stabble", "43200") self.mox.StubOutWithMock(SafeConfigParser, "get") self.mox.StubOutWithMock(StableUpdater, "__init__") config = ConfigurationParser() config.parse(mock_file) config.get("updates", "action").AndReturn(action) config.get("updates", "model").AndReturn(model) config.get("updates", "interval").AndReturn(interval) self.mox.ReplayAll() self.assertRaises(UnknownModel, get_update_handler)
def set_up_object_under_test(self): self.parser = ConfigurationParser()
def create_producer_node(self, account, path, p2p_address): try: nodepath = join(path, self.folder_scheme + account.name) if not os.path.isdir(nodepath): os.makedirs(nodepath) os.chdir(nodepath) config = ConfigurationParser() config.read(join(self.parent_dir, 'config/template_config.ini')) config.set('blocks-dir', join(nodepath, 'blocks')) config.set('http-server-address', '0.0.0.0:' + str(self.get_open_port())) p2p_port = str(self.get_open_port()) config.set('p2p-listen-endpoint', '0.0.0.0:' + p2p_port) config.set('p2p-server-address', '%s:%s' % (str(p2p_address), str(p2p_port))) config.set('producer-name', account.name) config.set('signature-provider', self.create_sig_provider(account.keypair)) plugins = ['eosio::producer_plugin'] config.append('plugin', plugins) config.write(join(nodepath, 'config.ini')) copyfile(join(self.parent_dir, 'config/genesis.json'), join(nodepath, "genesis.json")) node = Node(account.name, nodepath) return node except FileNotFoundError as e: print(e)
def start_full(self, path, p2p_address, http_port, p2p_port): try: nodepath = join(path, self.folder_scheme + 'genesis') if not os.path.isdir(nodepath): os.makedirs(nodepath) os.chdir(nodepath) config = ConfigurationParser() config.read(join(self.parent_dir, 'config/template_config.ini')) config.set('blocks-dir', join(nodepath, 'blocks')) config.set('http-server-address', '0.0.0.0:' + http_port) config.set('p2p-listen-endpoint', '0.0.0.0:' + p2p_port) config.set('p2p-server-address', '%s:%s' % (p2p_address, p2p_port)) config.set('enable-stale-production', True) config.set('producer-name', 'eosio') pair = self.wallet.create_import() self.edit_new_genesis(pair.public) config.set('signature-provider', self.create_sig_provider(pair)) plugins = [ 'eosio::http_plugin', 'eosio::chain_plugin', 'eosio::chain_api_plugin', 'eosio::history_plugin', 'eosio::history_api_plugin', 'eosio::net_plugin', 'eosio::net_api_plugin', 'eosio::producer_plugin' ] config.append('plugin', plugins) config.write(join(nodepath, 'config.ini')) copyfile(join(self.parent_dir, 'config/genesis.json'), join(nodepath, "genesis.json")) node = Node('genesis', nodepath) node.start(3.0) self.update_node_state(node) self.save() except FileNotFoundError as e: print(e)
def __init__(self, name, path): self.config = ConfigurationParser() self.path = os.path.abspath(path) self.name = name self.config.read(join(path, 'config.ini')) self.pid = self.get_pid()
class Node: def __init__(self, name, path): self.config = ConfigurationParser() self.path = os.path.abspath(path) self.name = name self.config.read(join(path, 'config.ini')) self.pid = self.get_pid() def is_running(self): try: pid = self.get_pid() if pid != -1: return psutil.pid_exists(pid) return False except OSError as e: print(e) return False def get_pid(self): path = join(self.path, 'node.pid') if os.path.isfile(path): pid = int(file_get_contents(path)) self.pid = pid return pid return -1 def start(self, delay_time=1.0): if not os.path.isdir(self.path): os.makedirs(self.path) cmd = NodeFactory.nodeos_dir + ' --config-dir %s --genesis-json %s --delete-all-blocks' genesis_dir = join(self.path, 'genesis.json') print('Starting node: %s' % self.name) start_background_proc(cmd % (self.path, genesis_dir), log_file(join(self.path, 'stderr.txt')), join(self.path, 'node.pid')) sleep(delay_time) def restart(self, delay_time=1.0): if self.is_running(): self.stop() if os.path.isdir(self.path): cmd = NodeFactory.nodeos_dir + ' --config-dir %s --hard-replay-blockchain' start_background_proc(cmd % self.path, log_file(join(self.path, 'stderr.txt')), join(self.path, 'node.pid')) sleep(delay_time) else: print('nodeos folder path: %s does not exist' % self.path) def stop(self): try: pid = self.get_pid() if pid != -1 and self.is_running(): p = psutil.Process(pid) p.terminate() except OSError as e: print(e) def show_output(self): tail(join(self.path, 'stderr.txt')) def get_ports(self): return [self.get_p2p_port(), self.get_http_port()] def get_p2p_port(self): p2p = self.config.get('p2p-listen-endpoint') return int(p2p[p2p.index(':') + 1:len(p2p) + 1]) def get_http_port(self): http = self.config.get('http-server-address') return int(http[http.index(':') + 1:len(http) + 1]) def get_endpoints(self): return self.config.get('p2p-server-address') def set_peers(self, peers): tmp = peers.copy() self.remove_self(tmp) endpoints = [] for name in tmp: endpoints.append(tmp[name]) self.config.append('p2p-peer-address', endpoints) self.config.write(join(self.path, 'config.ini')) def remove_self(self, peers): if self.name in peers: del peers[self.name] def get_info(self): return { 'name': self.name, 'pid': self.get_pid(), 'path': self.path, 'ports': self.get_ports() } def __str__(self): info = self.get_info() return json.dumps(info, indent=4, sort_keys=True)
def fetch_configurations(config_path): config = open(config_path, "r").read() return ConfigurationParser().parse_configuration(config)