def buffer_connection(): from moler.io.raw.memory import ThreadedFifoBuffer from moler.connection import ObservableConnection from moler.config.loggers import configure_device_logger class RemoteConnection(ThreadedFifoBuffer): def remote_inject_response(self, input_strings, delay=0.0): """ Simulate remote endpoint that sends response. Response is given as strings. """ in_bytes = [data.encode("utf-8") for data in input_strings] self.inject_response(in_bytes, delay) moler_conn = ObservableConnection( encoder=lambda data: data.encode("utf-8"), decoder=lambda data: data.decode("utf-8"), name="buffer") ext_io_in_memory = RemoteConnection( moler_connection=moler_conn, echo=False) # we don't want echo on connection configure_device_logger(moler_conn.name) # all tests assume working with already open connection with ext_io_in_memory.open(): # open it (autoclose by context-mngr) yield ext_io_in_memory
def test_calling_telnet_returns_result_parsed_from_command_output(buffer_connection, command_output_and_expected_result): from moler.config.loggers import configure_device_logger command_output, expected_result = command_output_and_expected_result configure_device_logger(connection_name="host") buffer_connection.name = "host-name" # just to have log named as we want buffer_connection.remote_inject_response([command_output]) telnet_cmd = Telnet(connection=buffer_connection.moler_connection, login="******", password="******", port=1500, host="host.domain.net", expected_prompt="host:.*#") result = telnet_cmd() assert result == expected_result
def test_calling_telnet_raise_exception_command_failure(buffer_connection): from moler.config.loggers import configure_device_logger command_output ="""TERM=xterm-mono telnet host.domain.net 1500 bash: telnet: command not found user@client:~>""" configure_device_logger(connection_name="host") buffer_connection.remote_inject_response([command_output]) telnet_cmd = Telnet(connection=buffer_connection.moler_connection, login="******", password="******", port=1500, host="host.domain.net", expected_prompt="host:.*#") with pytest.raises(CommandFailure): telnet_cmd()
def configure_logger(self, name, propagate): if not self.device_data_logger: self.device_data_logger = configure_device_logger( connection_name=name, propagate=propagate) self.io_connection.moler_connection.set_data_logger( self.device_data_logger)
def test_raw_logger_can_create_both_raw_logs(monkeypatch): import os import moler.config.loggers as m_logger binary_msg = b"127.0.0.1 \xe2\x86\x92 ttl" monkeypatch.setattr(m_logger, 'raw_logs_active', True) monkeypatch.setattr(m_logger, 'date_format', "%H:%M:%S") device_data_logger = m_logger.configure_device_logger( connection_name='Suse_10', propagate=False) device_data_logger.log(level=m_logger.RAW_DATA, msg=binary_msg, extra={'transfer_direction': '<'}) created_files = [] raw_logfile_full_path = '' raw_trace_logfile_full_path = '' for hndl in device_data_logger.handlers: hndl.close() created_files.append(hndl.baseFilename) if isinstance(hndl, m_logger.RawFileHandler): if isinstance(hndl.formatter, m_logger.RawTraceFormatter): raw_trace_logfile_full_path = hndl.baseFilename else: raw_logfile_full_path = hndl.baseFilename with open(raw_logfile_full_path, mode='rb') as logfh: content = logfh.read() assert content == binary_msg with open(raw_trace_logfile_full_path, mode='r') as logfh: content = logfh.read() assert 'direction: <, bytesize: 17, offset: 0}\n' in content for filename in created_files: os.remove(filename)
def test_raw_logger_can_log_decoded_binary_raw_data(monkeypatch): import os import moler.config.loggers as m_logger binary_msg = b"1 0.000000000 127.0.0.1 \xe2\x86\x92 127.0.0.1 ICMP 98 Echo (ping) request id=0x693b, seq=48/12288, ttl=64" decoded_msg = binary_msg.decode(encoding='utf-8') monkeypatch.setattr(m_logger, 'raw_logs_active', True) device_data_logger = m_logger.configure_device_logger( connection_name='Solaris_old_1', propagate=False) device_data_logger.log( level=m_logger.RAW_DATA, msg=decoded_msg, extra={ 'transfer_direction': '<', # decoded_msg must be combined with encoder 'encoder': lambda data: data.encode('utf-8') }) created_files = [] raw_logfile_full_path = '' for hndl in device_data_logger.handlers: hndl.close() created_files.append(hndl.baseFilename) if isinstance(hndl, m_logger.RawFileHandler) and not isinstance( hndl.formatter, m_logger.RawTraceFormatter): raw_logfile_full_path = hndl.baseFilename with open(raw_logfile_full_path, mode='rb') as logfh: content = logfh.read() assert content == binary_msg for filename in created_files: os.remove(filename)
def test_raw_logger_can_log_binary_raw_data(monkeypatch): import os import moler.config.loggers as m_logger binary_msg = b"1 0.000000000 127.0.0.1 \xe2\x86\x92 127.0.0.1 ICMP 98 Echo (ping) request id=0x693b, seq=48/12288, ttl=64" buffer = bytearray() buffer.extend(binary_msg) size2read = len(buffer) data = buffer[:size2read] # should work well with bytes and bytearray monkeypatch.setattr(m_logger, 'raw_logs_active', True) device_data_logger = m_logger.configure_device_logger( connection_name='Linux_xyz_2', propagate=False) device_data_logger.log(level=m_logger.RAW_DATA, msg=data, extra={'transfer_direction': '<'}) created_files = [] raw_logfile_full_path = '' for hndl in device_data_logger.handlers: hndl.close() created_files.append(hndl.baseFilename) if isinstance(hndl, m_logger.RawFileHandler) and not isinstance( hndl.formatter, m_logger.RawTraceFormatter): raw_logfile_full_path = hndl.baseFilename with open(raw_logfile_full_path, mode='rb') as logfh: content = logfh.read() assert content == binary_msg for filename in created_files: os.remove(filename)
def get_memory_device_connection(): from moler.threaded_moler_connection import ThreadedMolerConnection from moler.moler_connection_for_single_thread_runner import MolerConnectionForSingleThreadRunner from moler.config.loggers import configure_device_logger # moler_conn = ThreadedMolerConnection(encoder=lambda data: data.encode("utf-8"), # decoder=lambda data: data.decode("utf-8"), # name="buffer") moler_conn = MolerConnectionForSingleThreadRunner( encoder=lambda data: data.encode("utf-8"), decoder=lambda data: data.decode("utf-8"), name="buffer") ext_io_in_memory = RemoteConnection( moler_connection=moler_conn, echo=False) # we don't want echo on connection configure_device_logger(moler_conn.name) moler_conn.how2send = ext_io_in_memory.send return ext_io_in_memory
def buffer_connection(): from moler.io.raw.memory import ThreadedFifoBuffer from moler.threaded_moler_connection import ThreadedMolerConnection from moler.config.loggers import configure_device_logger class RemoteConnection(ThreadedFifoBuffer): def remote_inject_response(self, input_strings, delay=0.0): """ Simulate remote endpoint that sends response. Response is given as strings. """ in_bytes = [data.encode("utf-8") for data in input_strings] self.inject_response(in_bytes, delay) def remote_inject_line(self, line, add_newline=True, delay=0.0): """ Simulate remote endpoint that sends full line. Line is given as string. """ if add_newline: if not line.endswith("\n"): line = line + "\n" line_as_bytes = line.encode("utf-8") self.inject([line_as_bytes], delay) def get_runner(self): """Get default runner for this connection.""" return None # moler_conn = ThreadedMolerConnection(encoder=lambda data: data.encode("utf-8"), # decoder=lambda data: data.decode("utf-8"), # name="buffer") moler_conn = MolerConnectionForSingleThreadRunner( encoder=lambda data: data.encode("utf-8"), decoder=lambda data: data.decode("utf-8"), name="buffer") ext_io_in_memory = RemoteConnection( moler_connection=moler_conn, echo=False) # we don't want echo on connection configure_device_logger(moler_conn.name) # all tests assume working with already open connection with ext_io_in_memory.open(): # open it (autoclose by context-mngr) yield ext_io_in_memory
def test_raw_trace_log_can_be_yaml_loaded(monkeypatch): import os import yaml import moler.config.loggers as m_logger binary_msg = b"127.0.0.1 \xe2\x86\x92 ttl" monkeypatch.setattr(m_logger, 'raw_logs_active', True) monkeypatch.setattr(m_logger, 'date_format', "%H:%M:%S") device_data_logger = m_logger.configure_device_logger( connection_name='RHat_10', propagate=False) device_data_logger.log(level=m_logger.RAW_DATA, msg=binary_msg, extra={'transfer_direction': '<'}) device_data_logger.log(level=m_logger.RAW_DATA, msg=binary_msg, extra={'transfer_direction': '<'}) device_data_logger.log(level=m_logger.RAW_DATA, msg=binary_msg, extra={'transfer_direction': '<'}) created_files = [] raw_trace_logfile_full_path = '' for hndl in device_data_logger.handlers: hndl.close() created_files.append(hndl.baseFilename) if isinstance(hndl, m_logger.RawFileHandler) and isinstance( hndl.formatter, m_logger.RawTraceFormatter): raw_trace_logfile_full_path = hndl.baseFilename with open(raw_trace_logfile_full_path, mode='r') as logfh: raw_log_records = yaml.load(logfh) assert len(raw_log_records) == 3 rec1 = raw_log_records[0] rec2 = raw_log_records[1] rec3 = raw_log_records[2] time1 = list(rec1.keys())[0] # always one key - timestamp time2 = list(rec2.keys())[0] time3 = list(rec3.keys())[0] assert rec1[time1]['direction'] == '<' assert rec1[time1]['bytesize'] == 17 assert rec1[time1]['offset'] == 0 assert rec2[time2]['direction'] == '<' assert rec2[time2]['bytesize'] == 17 assert rec2[time2]['offset'] == 17 assert rec3[time3]['direction'] == '<' assert rec3[time3]['bytesize'] == 17 assert rec3[time3]['offset'] == 34 for filename in created_files: os.remove(filename)
def device_connection(): from moler.io.raw.memory import ThreadedFifoBuffer from moler.connection import ObservableConnection from moler.config.loggers import configure_device_logger class RemoteConnection(ThreadedFifoBuffer): def remote_inject_response(self, input_strings): """ Simulate remote endpoint that sends response. Response is given as strings. """ self.data = input_strings def _inject_deferred(self): """ Inject response on connection. """ cmd_data_string = self.input_bytes.decode("utf-8") if cmd_data_string: if '\n' in cmd_data_string: cmd_data_string = cmd_data_string[: -1] # remove \n from command_string on connection else: cmd_data_string = self.input_bytes try: binary_cmd_ret = self.data[ self.device.state][cmd_data_string].encode('utf-8') self.inject([self.input_bytes + binary_cmd_ret]) except KeyError as exc: raise MolerException("No output for cmd: '{}' in state '{}'!\n" "Please update your device_output dict!\n" "{}".format(cmd_data_string, self.device.state, exc)) def write(self, input_bytes): """ What is written to connection comes back on read() only if we simulate echo service of remote end. """ if self.echo: self.inject([input_bytes]) self.input_bytes = input_bytes self._inject_deferred() def set_device(self, device): """ Need to get actual state of device when sending cmds response. """ self.device = device send = write # just alias to make base class happy :-) moler_conn = ObservableConnection( encoder=lambda data: data.encode("utf-8"), decoder=lambda data: data.decode("utf-8"), name="buffer") ext_io_in_memory = RemoteConnection( moler_connection=moler_conn, echo=False) # we don't want echo on connection configure_device_logger(moler_conn.name) # all tests assume working with already open connection with ext_io_in_memory: # open it (autoclose by context-mngr) yield ext_io_in_memory