예제 #1
0
def start_simulation(simulator, description='', extra_options=None):
    """Start the simulation process for ``simulation``.

    *simulation* is the instance of your API implementation (see
    :class:`Simulator`).

    *description* may override the default description printed with the help on
    the command line.

    *extra_option* may be a list of options for `docopt <http://docopt.org/>`_
    (example: ``['-e, --example     Enable example mode']``). Commandline
    arguments are passed to :meth:`Simulator.configure()` so that your API
    implementation can handle them.

    """
    OK, ERR = 0, 1

    args = _parse_args(description or 'Start the simulation service.',
                       extra_options or [])

    logging.basicConfig(level=args['--log-level'])
    sim_name = simulator.__class__.__name__

    try:
        logger.info('Starting %s ...' % sim_name)
        env = backend.Environment()
        simulator.configure(args, backend, env)

        # Setup simpy.io and start the event loop.
        addr = _parse_addr(args['HOST:PORT'])
        sock = backend.TCPSocket.connection(env, addr)
        sock = Message(env, Packet(sock, max_packet_size=10 * 1024 * 1024))
        simulator.mosaik = MosaikProxy(sock)
        proc = env.process(run(sock, simulator))
        env.run(until=proc)
    except ConnectionRefusedError:
        logger.error('Could not connect to mosaik.')
        return ERR
    except (ConnectionError, KeyboardInterrupt):
        pass  # Exit silently.
    except Exception as exc:
        if type(exc) is OSError and exc.errno == 10057:
            # ConnectionRefusedError in Windows O.o
            logger.error('Could not connect to mosaik.')
            return ERR

        print('Error in %s:' % sim_name)
        import simpy._compat as compat
        if compat.PY2:
            compat.print_chain(type(exc), exc, exc.__traceback__)
        else:
            traceback.print_exc()  # Exit loudly
        print('---------%s-' % ('-' * len(sim_name)))
        return ERR
    finally:
        sock.close()
        simulator.finalize()

    return OK
    def __init__(self, socket, router=None):
        RPC.__init__(self, socket, router)

        self.codec = codec.JSON(
            self.types + ((Proxy, self._encode_proxy, self._decode_proxy), ),
            self.converters + ((self._encode_obj, self._decode_obj), ))
        self.message = Message(self.env, self.socket, self.codec)
        self.remote = Proxy(self, '')
class JSON(RPC):
    types = ()
    converters = ()

    def __init__(self, socket, router=None):
        RPC.__init__(self, socket, router)

        self.codec = codec.JSON(
            self.types + ((Proxy, self._encode_proxy, self._decode_proxy), ),
            self.converters + ((self._encode_obj, self._decode_obj), ))
        self.message = Message(self.env, self.socket, self.codec)
        self.remote = Proxy(self, '')

    def dispatch(self, call):
        return self.message.send(call)

    def handler(self):
        # TODO Decide if errors should be handled here, in dispatch() or in
        # callbacks to this process.
        try:
            while True:
                request = yield self.message.recv()
                path, args, kwargs = request.content

                try:
                    func, obj = self.router.dispatch(self, request, path)
                except Exception as e:
                    # FIXME Shouldn't the dispatcher handle these errors?
                    request.fail(e)
                    continue

                func(self, request, obj, args, kwargs)
        except Exception as e:
            # TODO Add proper handling of socket errors.
            pass

    def _encode_proxy(self, proxy):
        if proxy._rpc is not self:
            raise RuntimeError('Cannot serialize proxies of different '
                               'connections')

        return proxy._path

    def _decode_proxy(self, path):
        return self.router.lookup(path.split('/'))

    def _encode_obj(self, obj):
        return self.router.resolve(obj)

    def _decode_obj(self, path):
        try:
            proxy = self.proxies[path]
        except KeyError:
            proxy = Proxy(self, path)

        return proxy
예제 #4
0
def mosaik_mock(env, server_sock):
    """This functions pretends to be mosaik."""
    sock = yield server_sock.accept()
    message = Message(env, Packet(sock))

    reply = yield message.send(['init', ['ExampleSim-0'], {'step_size': 2}])
    assert reply == {
        'api_version': '2.2',
        'models': {
            'ExampleModel': {
                'public': True,
                'params': ['init_val'],
                'attrs': ['val', 'delta'],
            },
        },
    }

    reply = yield message.send(['create', [2, 'ExampleModel'], {
        'init_val': 3}])
    assert reply == [
        {'eid': 'EM_0', 'type': 'ExampleModel', 'rel': []},
        {'eid': 'EM_1', 'type': 'ExampleModel', 'rel': []},
    ]

    reply = yield message.send(["setup_done", [], {}])
    assert reply is None

    reply = yield message.send(['step', [
        0,
        {'EM_0': {}, 'EM_1': {}},
    ], {}])
    assert reply == 2

    reply = yield message.send(['get_data', [{'EM_0': ['val'],
                                              'EM_1': ['val']}], {}])
    assert reply == {
        'EM_0': {'val': 4},
        'EM_1': {'val': 4},
    }

    reply = yield message.send(['step', [
        2,
        {'EM_0': {'val_in': {'foo': 2}}, 'EM_1': {}},
    ], {}])
    assert reply == 4

    reply = yield message.send(['get_data', [{'EM_0': ['val'],
                                              'EM_1': ['val']}], {}])
    assert reply == {
        'EM_0': {'val': 5},
        'EM_1': {'val': 5},
    }

    try:
        message.send(['stop', [], {}])
    except ConnectionError:
        pass
    print('done')
예제 #5
0
def mosaik_mock(env, client_sock):
    """This functions pretends to be mosaik."""
    message = Message(env, Packet(client_sock))

    reply = yield message.send(['init', ['ExampleMAS-0'], {'step_size': 2}])
    assert reply == {
        'api_version': '2.2',
        'models': {
            'ExampleAgent': {
                'public': True,
                'params': [],
                'attrs': [],
            },
        },
    }

    reply = yield message.send(['create', [1, 'ExampleAgent'], {}])
    assert reply == [
        {
            'eid': 'EA_0',
            'type': 'ExampleAgent',
            'rel': []
        },
    ]

    reply = yield message.send(["setup_done", [], {}])
    assert reply is None

    # Make step request
    step_req = message.send(['step', [0, {}], {}])

    # Handle async. requests
    request = yield message.recv()
    assert request.content == ['get_progress', [], {}]
    request.succeed(3.14)

    request = yield message.recv()
    assert request.content == ['get_related_entities', [], {}]
    request.succeed({
        'nodes': {
            'sid_0/eid_0': {
                'type': 'A'
            },
            'sid_0/eid_1': {
                'type': 'B'
            },
        },
        'edges': [
            ['sid_0/eid_0', 'sid_1/eid0', {}],
        ],
    })

    request = yield message.recv()
    assert request.content == ['get_related_entities', ['eid0'], {}]
    request.succeed({'sid_0/eid_0': {'type': 'A'}})

    request = yield message.recv()
    assert request.content == ['get_related_entities', [['eid0', 'eid1']], {}]
    request.succeed({'sid_0/eid_0': {'sid_0/eid_1': {'type': 'B'}}})

    request = yield message.recv()
    assert request.content == ['get_data', [{'eid0': ['a']}], {}]
    request.succeed({'eid0': {'a': 42}})

    request = yield message.recv()
    assert request.content == ['set_data', [{'EA_0': {'eid0': {'a': 42}}}], {}]
    request.succeed()

    # Wait for step to finish
    reply = yield step_req
    assert reply == 2

    try:
        message.send(['stop', [], {}])
    except ConnectionError:
        pass
    print('done')
예제 #6
0
def start_simulation(simulator, description='', extra_options=None):
    """Start the simulation process for ``simulation``.

    *simulation* is the instance of your API implementation (see
    :class:`Simulator`).

    *description* may override the default description printed with the help on
    the command line.

    *extra_option* may be a list of options for `docopt <http://docopt.org/>`_
    (example: ``['-e, --example     Enable example mode']``). Commandline
    arguments are passed to :meth:`Simulator.configure()` so that your API
    implementation can handle them.

    """
    OK, ERR = 0, 1

    args = _parse_args(description or 'Start the simulation service.',
                       extra_options or [])

    logging.basicConfig(level=args['--log-level'])
    remote_flag = args['--remote'] if '--remote' in args.keys() else False
    sim_name = simulator.__class__.__name__

    sock = None
    srv_sock = None
    try:
        logger.info('Starting %s ...' % sim_name)
        env = backend.Environment()
        simulator.configure(args, backend, env)

        # Setup simpy.io and start the event loop.
        addr = _parse_addr(args['HOST:PORT'])
        # Interception for remote simulators
        if remote_flag:
            srv_sock = backend.TCPSocket.server(env, addr)
            start_timeout = env.timeout(int(args['--timeout']))

            def greeter():
                """ Handshake with mosaik to establish a socket for communication """
                logger.info('Waiting for connection from mosaik')
                accept_con = srv_sock.accept()
                results = yield accept_con | start_timeout
                if start_timeout in results:
                    raise RuntimeError(
                        'Connection from mosaik not received in time')
                else:
                    sock = results[accept_con]
                return sock

            sock = env.run(until=env.process(greeter()))
        else:
            sock = backend.TCPSocket.connection(env, addr)
        sock = Message(env, Packet(sock, max_packet_size=10 * 1024 * 1024))
        simulator.mosaik = MosaikProxy(sock)
        proc = env.process(run(sock, simulator))
        env.run(until=proc)
    except ConnectionRefusedError:
        logger.error('Could not connect to mosaik.')
        errstr = 'INFO:mosaik_api:Starting ExampleSim ...\n' + 'ERROR:mosaik_api:Could not connect to mosaik.\n'
        return errstr
    except (ConnectionError, KeyboardInterrupt):
        pass  # Exit silently.
    except Exception as exc:
        if type(exc) is OSError and exc.errno == 10057:
            # ConnectionRefusedError in Windows O.o
            logger.error('Could not connect to mosaik.')
            return ERR

        print('Error in %s:' % sim_name)
        traceback.print_exc()  # Exit loudly
        print('---------%s-' % ('-' * len(sim_name)))
        return ERR
    finally:
        if sock is not None:
            sock.close()
        if srv_sock is not None:
            srv_sock.close()
        simulator.finalize()

    return OK