def test_get_connection_without_variant_selection_raises_KeyError():
    from moler.connection import get_connection

    with pytest.raises(KeyError) as err:
        get_connection(io_type='tcp', host='localhost', port=2345)
    assert "No variant selected (directly or via configuration) for 'tcp' connection" in str(
        err)
def test_get_connection_must_use_either_name_or_io_type():
    from moler.connection import get_connection

    with pytest.raises(AssertionError) as err:
        get_connection(host='localhost', port=2345)
    assert "Provide either 'name' or 'io_type' parameter (none given)" in str(
        err)
Esempio n. 3
0
def test_get_connection_may_not_use_both__name_and_io_type():
    from moler.connection import get_connection

    with pytest.raises(AssertionError) as err:
        get_connection(name='www_server_1',
                       io_type='tcp', host='localhost', port=2345)
    assert "Use either 'name' or 'io_type' parameter (not both)" in str(err)
Esempio n. 4
0
def test_cannot_select_connection_by_nonexisting_name(connections_config):
    """Non-existing means here not defined inside configuration"""
    from moler.connection import get_connection

    connections_config.set_default_variant(io_type='tcp', variant='threaded')
    with pytest.raises(KeyError) as err:
        get_connection(name='www_server_1')
    assert "Connection named 'www_server_1' was not defined inside configuration" in str(err)
Esempio n. 5
0
def test_cannot_select_nonexisting_connection_variant(connections_config):
    """Non-existing means not registered inside ConnectionFactory"""
    from moler.connection import get_connection

    connections_config.set_default_variant(io_type='tcp', variant='yedi_magic')
    with pytest.raises(KeyError) as err:
        get_connection(io_type='tcp', host='localhost', port=2345)
    assert "'yedi_magic' variant of 'tcp' connection is not registered inside ConnectionFactory" in str(err)
Esempio n. 6
0
def test_factory_has_buildin_constructors_active_by_default():
    from moler.connection import get_connection

    conn = get_connection(io_type='memory', variant='threaded')
    assert conn.__module__ == 'moler.io.raw.memory'
    assert conn.__class__.__name__ == 'ThreadedFifoBuffer'

    conn = get_connection(io_type='tcp',
                          variant='threaded',
                          host='localhost',
                          port=2345)
    assert conn.__module__ == 'moler.io.raw.tcp'
    assert conn.__class__.__name__ == 'ThreadedTcp'
Esempio n. 7
0
def main(connections2observe4ip):
    # Starting the servers
    servers = []
    for address, _, ping_ip in connections2observe4ip:
        # simulate pinging given IP
        server_thread, server_done = start_ping_sim_server(address, ping_ip)
        servers.append((server_thread, server_done))
    # Starting the clients
    connections = []
    for _, connection_name, ping_ip in connections2observe4ip:
        # ------------------------------------------------------------------
        # This front-end code hides all details of connection.
        # We just use its name - such name should be meaningful for user.
        # like: "main_dns_server", "backup_ntp_server", ...
        # Another words, all we want here is stg like:
        # "give me connection to main_dns_server"
        # ------------------------------------------------------------------
        tcp_connection = get_connection(name=connection_name)
        tcp_connection.moler_connection.name = connection_name
        client_thread = threading.Thread(target=ping_observing_task,
                                         args=(tcp_connection, ping_ip))
        client_thread.start()
        connections.append(client_thread)
    # await observers job to be done
    for client_thread in connections:
        client_thread.join()
    # stop servers
    for server_thread, server_done in servers:
        server_done.set()
        server_thread.join()
Esempio n. 8
0
async def main(connections2observe4ip):
    logger = logging.getLogger('asyncio.main')
    logger.debug('starting jobs observing connections')
    # Starting the clients
    jobs_on_connections = []
    for _, connection_name, ping_ip in connections2observe4ip:
        # ------------------------------------------------------------------
        # This front-end code hides all details of connection.
        # We just use its name - such name should be meaningful for user.
        # like: "main_dns_server", "backup_ntp_server", ...
        # Another words, all we want here is stg like:
        # "give me connection to main_dns_server"
        # ------------------------------------------------------------------
        con_logger = logging.getLogger(
            'tcp-async-io.{}'.format(connection_name))
        tcp_connection = get_connection(name=connection_name,
                                        variant='asyncio',
                                        logger=con_logger)

        # client_task= asyncio.ensure_future(ping_observing_task(tcp_connection, ping_ip))
        jobs_on_connections.append(ping_observing_task(tcp_connection,
                                                       ping_ip))
    # await observers job to be done
    completed, pending = await asyncio.wait(jobs_on_connections)
    logger.debug('all jobs observing connections are done')
def main(connections2observe4ip):
    # Starting the servers
    servers = []
    for address, ping_ip in connections2observe4ip:
        # simulate pinging given IP
        server_thread, server_done = start_ping_sim_server(address, ping_ip)
        servers.append((server_thread, server_done))
    # Starting the clients
    connections = []
    for address, ping_ip in connections2observe4ip:
        host, port = address
        # ------------------------------------------------------------------
        # This front-end code hides parallelism variant
        # used to read data from connection.
        # We don't care if it is TCP connection based on threads or asyncio.
        # All we want here is "any TCP connection towards given host/port".
        # "any" means here: TCP variant as configured on backend.
        # ------------------------------------------------------------------
        tcp_connection = get_connection(io_type='tcp', host=host, port=port)
        client_thread = threading.Thread(target=ping_observing_task,
                                         args=(tcp_connection, ping_ip))
        client_thread.start()
        connections.append(client_thread)
    # await observers job to be done
    for client_thread in connections:
        client_thread.join()
    # stop servers
    for server_thread, server_done in servers:
        server_done.set()
        server_thread.join()
Esempio n. 10
0
def test_can_select_connection_variant_from_buildin_connections(connections_config):
    from moler.connection import get_connection

    connections_config.set_default_variant(io_type='tcp', variant='threaded')
    conn = get_connection(io_type='tcp', host='localhost', port=2345)
    assert conn.__module__ == 'moler.io.raw.tcp'
    assert conn.__class__.__name__ == 'ThreadedTcp'
Esempio n. 11
0
def test_returned_connections_have_moler_integrated_connection(
        builtin_variant, builtin_io_type_example):
    from moler.connection import get_connection

    io_type, kwargs = builtin_io_type_example
    conn = get_connection(io_type=io_type, variant=builtin_variant, **kwargs)
    assert hasattr(conn, 'moler_connection')
    assert conn.moler_connection.how2send != conn.moler_connection._unknown_send
Esempio n. 12
0
def test_can_select_connection_loaded_from_config_file(moler_config):
    from moler.connection import get_connection

    conn_config = os.path.join(os.path.dirname(__file__), "resources", "www_servers_connections.yml")
    moler_config.load_config(config=conn_config, config_type='yaml')

    conn = get_connection(name='www_server_1')
    assert conn.__module__ == 'moler.io.raw.tcp'
    assert conn.__class__.__name__ == 'ThreadedTcp'
    assert conn.host == 'localhost'
    assert conn.port == 2345
Esempio n. 13
0
def test_can_select_connection_by_name(connections_config):
    from moler.connection import get_connection

    connections_config.define_connection(name="www_server_1",
                                         io_type='tcp',
                                         host='localhost', port=2345)
    connections_config.set_default_variant(io_type='tcp', variant='threaded')
    conn = get_connection(name='www_server_1')
    assert conn.__module__ == 'moler.io.raw.tcp'
    assert conn.__class__.__name__ == 'ThreadedTcp'
    assert conn.host == 'localhost'
    assert conn.port == 2345
Esempio n. 14
0
def test_can_select_connection_loaded_from_env_variable(moler_config, monkeypatch):
    from moler.connection import get_connection

    conn_config = os.path.join(os.path.dirname(__file__), "resources", "www_servers_connections.yml")
    monkeypatch.setitem(os.environ, 'MOLER_CONFIG', conn_config)
    moler_config.load_config(from_env_var="MOLER_CONFIG", config_type='yaml')

    conn = get_connection(name='www_server_1')
    assert conn.__module__ == 'moler.io.raw.tcp'
    assert conn.__class__.__name__ == 'ThreadedTcp'
    assert conn.host == 'localhost'
    assert conn.port == 2345
Esempio n. 15
0
    def __init__(self,
                 io_connection=None,
                 io_type=None,
                 variant=None,
                 sm_params=dict()):
        """
        Create Device communicating over io_connection
        CAUTION: Device owns (takes over ownership) of connection. It will be open when device "is born" and close when
        device "dies".

        :param io_connection: External-IO connection having embedded moler-connection
        :param io_type: type of connection - tcp, udp, ssh, telnet, ...
        :param variant: connection implementation variant, ex. 'threaded', 'twisted', 'asyncio', ...
                        (if not given then default one is taken)
        """
        self.logger = logging.getLogger('moler.textualdevice')
        self.states = []
        self.goto_states_triggers = []
        # Below line will modify self extending it with methods and atributes od StateMachine
        # For eg. it will add attribute self.state
        self.SM = StateMachine(model=self,
                               states=self.states,
                               initial=TextualDevice.not_connected,
                               auto_transitions=False,
                               queued=True)

        self._state_hops = {}
        self._state_prompts = {}
        self._prompts_events = {}
        self._configurations = dict()

        self._prepare_transitions()
        self._prepare_state_hops()
        self._configure_state_machine(sm_params)

        if io_connection:
            self.io_connection = io_connection
        else:
            self.io_connection = get_connection(io_type=io_type,
                                                variant=variant)
        self.io_connection.notify(callback=self.on_connection_made,
                                  when="connection_made")
        # TODO: Need test to ensure above sentence for all connection
        self.io_connection.open()
        self.io_connection.notify(callback=self.on_connection_lost,
                                  when="connection_lost")
        self._cmdnames_available_in_state = dict()
        self._eventnames_available_in_state = dict()

        self._collect_cmds_for_state_machine()
        self._collect_events_for_state_machine()
        self._run_prompts_observers()
        self._default_prompt = re.compile(r'^[^<]*[\$|%|#|>|~]\s*$')
Esempio n. 16
0
def test_can_select_connection_variant_from_plugin_connections(builtin_connection_factories,
                                                               connections_config):
    from moler.connection import ConnectionFactory, get_connection

    class DummyTcpConnection(object):
        def __init__(self, host, port):
            pass

    ConnectionFactory.register_construction(io_type='tcp', variant='dummy',
                                            constructor=DummyTcpConnection)
    connections_config.set_default_variant(io_type='tcp', variant='dummy')
    conn = get_connection(io_type='tcp', host='localhost', port=2345)
    assert conn.__class__.__name__ == 'DummyTcpConnection'
Esempio n. 17
0
def test_can_select_connection_loaded_from_dict(moler_config):
    from moler.connection import get_connection

    configuration_in_dict = {'NAMED_CONNECTIONS':
                                 {'www_server_1': {'io_type': 'tcp', 'host': 'localhost', 'port': 2344}},
                             'IO_TYPES':
                                 {'default_variant': {'tcp': 'threaded'}}}
    moler_config.load_config(config=configuration_in_dict, config_type='dict')

    conn = get_connection(name='www_server_1')
    assert conn.__module__ == 'moler.io.raw.tcp'
    assert conn.__class__.__name__ == 'ThreadedTcp'
    assert conn.host == 'localhost'
    assert conn.port == 2344
Esempio n. 18
0
def test_can_plugin_alternative_connection_instead_of_builtin_one(
        builtin_connection_factories):
    from moler.connection import ConnectionFactory, get_connection
    from moler.connection import ObservableConnection

    class DummyTcpConnection(object):
        def __init__(self, host, port):
            self.moler_connection = ObservableConnection(how2send=self.send)

        def send(self, data):
            pass

    ConnectionFactory.register_construction(io_type='tcp',
                                            variant='threaded',
                                            constructor=DummyTcpConnection)
    conn = get_connection(io_type='tcp',
                          variant='threaded',
                          host='localhost',
                          port=2345)
    assert conn.__class__.__name__ == 'DummyTcpConnection'
Esempio n. 19
0
def main(connections2observe4ip):
    # Starting the clients
    connections = []
    for address, ping_ip in connections2observe4ip:
        host, port = address
        # ------------------------------------------------------------------
        # This front-end code hides parallelism variant
        # used to read data from connection.
        # We don't care if it is TCP connection based on threads or asyncio.
        # All we want here is "any TCP connection towards given host/port".
        # "any" means here: TCP variant as configured on backend.
        # ------------------------------------------------------------------
        tcp_connection = get_connection(io_type='tcp', host=host, port=port)
        tcp_connection.moler_connection.name = "{}:{}".format(host, port)
        client_thread = threading.Thread(target=ping_observing_task,
                                         args=(tcp_connection, ping_ip))
        client_thread.start()
        connections.append(client_thread)
    # await observers job to be done
    for client_thread in connections:
        client_thread.join()
Esempio n. 20
0
def main(connections2observe4ip):
    logger = logging.getLogger('asyncio.main')
    logger.debug('starting jobs observing connections')
    # Starting the clients
    jobs_on_connections = []
    for connection_name, ping_ip in connections2observe4ip:
        # ------------------------------------------------------------------
        # This front-end code hides all details of connection.
        # We just use its name - such name should be meaningful for user.
        # like: "main_dns_server", "backup_ntp_server", ...
        # Another words, all we want here is stg like:
        # "give me connection to main_dns_server"
        # ------------------------------------------------------------------
        # con_logger = logging.getLogger('tcp-async_in_thrd-io.{}'.format(connection_name))
        # tcp_connection = get_connection(name=connection_name, variant='asyncio-in-thread', logger=con_logger)
        tcp_connection = get_connection(name=connection_name, variant='asyncio-in-thread')
        client_thread = threading.Thread(target=ping_observing_task,
                                         args=(tcp_connection, ping_ip))
        client_thread.start()
        jobs_on_connections.append(client_thread)
    # await observers job to be done
    for client_thread in jobs_on_connections:
        client_thread.join()
    logger.debug('all jobs observing connections are done')
Esempio n. 21
0
 def from_named_connection(cls, connection_name):
     io_conn = get_connection(name=connection_name)
     return cls(io_connection=io_conn)
Esempio n. 22
0
from moler.cmd.unix.ps import Ps
from moler.connection import ObservableConnection, get_connection
from moler.io.raw.terminal import ThreadedTerminal

# v.1 - combine all manually
# moler_conn = ObservableConnection()
# terminal = ThreadedTerminal(moler_connection=moler_conn)
# v.2 - let factory combine
# terminal = get_connection(io_type='terminal', variant='threaded')
# v.3 - let factory select default variant
terminal = get_connection(io_type='terminal')
terminal.open()
ps_cmd = Ps(connection=terminal.moler_connection, options="-ef")

processes = ps_cmd()
for proc in processes:
    if 'python' in proc['CMD']:
        print("PID: {} CMD: {}".format(proc['PID'], proc['CMD']))
terminal.close()

# result:
"""
PID: 1817 CMD: /usr/bin/python /usr/share/system-config-printer/applet.py
PID: 21825 CMD: /usr/bin/python /home/gl/moler/examples/command/unix_ps.py
"""
Esempio n. 23
0
def test_can_get_connection():
    from moler.connection import get_connection
    tcp_connection = get_connection(io_type='tcp', variant='asyncio-in-thread', host='localhost', port=2345)
    assert tcp_connection is not None
Esempio n. 24
0
    def __init__(self,
                 sm_params=None,
                 name=None,
                 io_connection=None,
                 io_type=None,
                 variant=None,
                 io_constructor_kwargs={},
                 initial_state=None):
        """
        Create Device communicating over io_connection
        CAUTION: Device owns (takes over ownership) of connection. It will be open when device "is born" and close when
        device "dies".

        :param sm_params: dict with parameters of state machine for device
        :param name: name of device
        :param io_connection: External-IO connection having embedded moler-connection
        :param io_type: type of connection - tcp, udp, ssh, telnet, ...
        :param variant: connection implementation variant, ex. 'threaded', 'twisted', 'asyncio', ...
                        (if not given then default one is taken)
        :param io_constructor_kwargs: additional parameter into constructor of selected connection type
                        (if not given then default one is taken)
        :param initial_state: name of initial state. State machine tries to enter this state just after creation.
        """
        sm_params = copy_dict(sm_params, deep_copy=True)
        io_constructor_kwargs = copy_dict(io_constructor_kwargs,
                                          deep_copy=True)
        self.initial_state = initial_state if initial_state is not None else "NOT_CONNECTED"
        self.states = [TextualDevice.not_connected]
        self.goto_states_triggers = []
        self._name = name
        self.device_data_logger = None

        # Below line will modify self extending it with methods and atributes od StateMachine
        # For eg. it will add attribute self.state
        self.SM = StateMachine(model=self,
                               states=self.states,
                               initial=TextualDevice.not_connected,
                               auto_transitions=False,
                               queued=True)

        self._state_hops = {}
        self._state_prompts = {}
        self._prompts_events = {}
        self._configurations = dict()
        self._newline_chars = dict(
        )  # key is state, value is chars to send as newline
        if io_connection:
            self.io_connection = io_connection
        else:
            self.io_connection = get_connection(io_type=io_type,
                                                variant=variant,
                                                **io_constructor_kwargs)

        self.io_connection.name = self.name
        self.io_connection.moler_connection.name = self.name
        self.logger = logging.getLogger('moler.connection.{}'.format(
            self.name))
        self.configure_logger(name=self.name, propagate=False)

        self._prepare_transitions()
        self._prepare_state_hops()
        self._configure_state_machine(sm_params)
        self._prepare_newline_chars()

        # TODO: Need test to ensure above sentence for all connection
        self.io_connection.notify(callback=self.on_connection_made,
                                  when="connection_made")
        self.io_connection.notify(callback=self.on_connection_lost,
                                  when="connection_lost")
        self.io_connection.open()

        self._cmdnames_available_in_state = dict()
        self._eventnames_available_in_state = dict()

        self._collect_cmds_for_state_machine()
        self._collect_events_for_state_machine()
        self._run_prompts_observers()
        self._default_prompt = re.compile(r'^[^<]*[\$|%|#|>|~]\s*$')
Esempio n. 25
0
from moler.cmd.unix.ps import Ps
from moler.connection import ObservableConnection, get_connection
from moler.io.raw.terminal import ThreadedTerminal

# v.1 - combine all manually
# moler_conn = ObservableConnection()
# terminal = ThreadedTerminal(moler_connection=moler_conn)
# v.2 - let factory combine
terminal = get_connection(io_type='terminal', variant='threaded')
# v.3 - let factory select default variant
# terminal = get_connection(io_type='terminal')
with terminal.open():
    ps_cmd = Ps(connection=terminal.moler_connection, options="-ef")

    processes = ps_cmd()
    for proc in processes:
        if 'python' in proc['CMD']:
            print("PID: {} CMD: {}".format(proc['PID'], proc['CMD']))

# result:
"""
PID: 1817 CMD: /usr/bin/python /usr/share/system-config-printer/applet.py
PID: 21825 CMD: /usr/bin/python /home/gl/moler/examples/command/unix_ps.py
"""