Beispiel #1
0
    def __init__(self, name, context=zmq.Context.instance()):
        self.isac_values = WeakValueDictionary()  # Should be a weakdict

        self.rpc_regexp = re.compile('^rpc://(.*?)/(.*)$')
        self.rpc = ZmqRPC()
        self.pub_sub = ZmqPubSub(context, self._sub_callback)

        self.transport = PyreNode(name, context)
        try:
            self.surveys_manager = SurveysManager(self, self.transport)
            self.events_manager = EventsManager(self, self.transport)
        except Exception:
            self.transport.stop()
            raise

        self.transport.on_new_peer = self._on_new_peer
        self.transport.on_peer_gone = self._on_peer_gone
        self.transport.on_survey = self.surveys_manager.on_survey
        self.transport.on_event = self.events_manager.on_event

        self.rpc.setup_transport(self.transport)
        self.pub_sub.setup_transport(self.transport)

        self.rpc.start()
        self.pub_sub.start()

        self.transport.run()

        green.sleep(0.1)
Beispiel #2
0
def node_with_callbacks(request):
    n = PyreNode('testA')

    results = StoreResults()
    n.on_new_peer = results.on_new_peer
    n.on_peer_gone = results.on_peer_gone
    n.on_survey = results.on_survey
    n.on_event = results.on_event

    def teardown():
        n.shutdown()
        green.sleep(0.1) # Good to wait all other nodes shutdown

    request.addfinalizer(teardown)
    return n, results
Beispiel #3
0
def node_with_callbacks(request):
    n = PyreNode('testA')

    results = StoreResults()
    n.on_new_peer = results.on_new_peer
    n.on_peer_gone = results.on_peer_gone
    n.on_survey = results.on_survey
    n.on_event = results.on_event

    yield n, results

    n.shutdown()
    green.sleep(0.1)  # Good to wait all other nodes shutdown
Beispiel #4
0
def test_on_survey(node_with_callbacks):
    nA, results = node_with_callbacks
    nA.run()

    nB = PyreNode('testB')
    try:
        nB.run()
        wait_cb(results, 'on_new_peer')

        nB.send_survey({'req_id': 'this is a test'}, 0.1, 1)

        wait_cb(results, 'on_survey')

        peer_id, peer_name, request = results.on_survey_results
        assert peer_id == nB.uuid()
        assert peer_name == 'testB'
        assert request == {'req_id': 'this is a test'}
    finally:
        nB.shutdown()
Beispiel #5
0
def test_on_event(node_with_callbacks):
    nA, results = node_with_callbacks
    nA.run()
    nA.join('EVENT')

    nB = PyreNode('testB')
    try:
        nB.run()
        wait_cb(results, 'on_new_peer')

        nB.send_event('various data')

        wait_cb(results, 'on_event')

        peer_id, peer_name, request = results.on_event_results
        assert peer_id == nB.uuid()
        assert peer_name == 'testB'
        assert request == 'various data'
    finally:
        nB.shutdown()
Beispiel #6
0
def test_on_peer_gone(node_with_callbacks):
    nA, results = node_with_callbacks
    nA.run()

    nB = PyreNode('testB')
    nB_uuid = nB.uuid()
    try:
        nB.run()
        wait_cb(results, 'on_new_peer')
    finally:
        nB.shutdown()

    wait_cb(results, 'on_peer_gone')

    peer_id, peer_name = results.on_peer_gone_results
    assert peer_id == nB_uuid
    assert peer_name == b'testB'
Beispiel #7
0
def test_on_survey(node_with_callbacks, request):
    nA, results = node_with_callbacks
    nA.run()

    nB = PyreNode('testB')
    request.addfinalizer(nB.shutdown)

    nB.run()
    wait_cb(results, 'on_new_peer')

    nB.send_survey({'req_id': 'this is a test'}, 0.1, 1)

    wait_cb(results, 'on_survey')

    peer_id, peer_name, request = results.on_survey_results
    assert peer_id == nB.uuid()
    assert peer_name == b'testB'
    assert request == {'req_id': 'this is a test'}
Beispiel #8
0
def test_on_event(node_with_callbacks, request):
    nA, results = node_with_callbacks
    nA.run()
    nA.join('EVENT')

    nB = PyreNode('testB')
    request.addfinalizer(nB.shutdown)

    nB.run()
    wait_cb(results, 'on_new_peer')

    nB.send_event('various data')

    wait_cb(results, 'on_event')

    peer_id, peer_name, request = results.on_event_results
    assert peer_id == nB.uuid()
    assert peer_name == b'testB'
    assert request == 'various data'
Beispiel #9
0
def test_on_peer_gone(node_with_callbacks):
    nA, results = node_with_callbacks
    nA.run()

    nB = PyreNode('testB')
    nB_uuid = nB.uuid()
    try:
        nB.run()
        wait_cb(results, 'on_new_peer')
    finally:
        nB.shutdown()

    wait_cb(results, 'on_peer_gone')

    peer_id, peer_name = results.on_peer_gone_results
    assert peer_id == nB_uuid
    assert peer_name == 'testB'
Beispiel #10
0
def test_survey_process(node_with_callbacks):
    nA, results = node_with_callbacks
    nA.run()

    nB = PyreNode('testB')
    try:
        nB.run()
        wait_cb(results, 'on_new_peer')

        # Test it can cope with wrong req_id
        nA.reply_survey(nB.uuid(), {'req_id': 'wrong!', 'data': ''})

        def _reply():
            wait_cb(results, 'on_survey')
            peer_id, peer_name, request = results.on_survey_results
            nA.reply_survey(peer_id, {'req_id': 'this is a test', 'data': 'OK!'})
        green.spawn(_reply)

        assert nB.send_survey({'req_id': 'this is a test'}, 1, 1) == [('testA', 'OK!')]
    finally:
        nB.shutdown()
Beispiel #11
0
def test_survey_process(node_with_callbacks, request):
    nA, results = node_with_callbacks
    nA.run()

    nB = PyreNode('testB')
    request.addfinalizer(nB.shutdown)

    nB.run()
    wait_cb(results, 'on_new_peer')

    # Test it can cope with wrong req_id
    nA.reply_survey(nB.uuid(), {'req_id': 'wrong!', 'data': ''})

    def _reply():
        wait_cb(results, 'on_survey')
        peer_id, peer_name, request = results.on_survey_results
        nA.reply_survey(peer_id, {'req_id': 'this is a test', 'data': 'OK!'})

    green.spawn(_reply)

    assert nB.send_survey({'req_id': 'this is a test'}, 1,
                          1) == [(b'testA', 'OK!')]
Beispiel #12
0
def test_on_new_peer(node_with_callbacks):
    nA, results = node_with_callbacks
    nA.run()

    nB = PyreNode('testB')
    try:
        nB.set_header('rpc_proto', 'tcp')
        nB.set_header('rpc_port', str(999))
        nB.set_header('pub_proto', 'tcp')
        nB.set_header('pub_port', str(999))
        nB.run()

        wait_cb(results, 'on_new_peer')

        peer_id, peer_name, pub_endpoint, rpc_endpoint = results.on_new_peer_results
        assert peer_id == nB.uuid()
        assert peer_name == 'testB'
        assert re.match('^tcp://(.*):999$', pub_endpoint), 'Bad PUB endpoint'
        assert re.match('^tcp://(.*):999$', rpc_endpoint), 'Bad RPC endpoint'

    finally:
        nB.shutdown()
Beispiel #13
0
def test_on_new_peer(node_with_callbacks, request):
    nA, results = node_with_callbacks
    nA.run()

    nB = PyreNode('testB')
    request.addfinalizer(nB.shutdown)

    nB.set_header('rpc_proto', 'tcp')
    nB.set_header('rpc_port', str(999))
    nB.set_header('pub_proto', 'tcp')
    nB.set_header('pub_port', str(999))
    nB.run()

    wait_cb(results, 'on_new_peer')

    peer_id, peer_name, pub_endpoint, rpc_endpoint = results.on_new_peer_results
    assert peer_id == nB.uuid()
    assert peer_name == b'testB'
    assert re.match('^tcp://(.*):999$', pub_endpoint), 'Bad PUB endpoint'
    assert re.match('^tcp://(.*):999$', rpc_endpoint), 'Bad RPC endpoint'
Beispiel #14
0
class IsacNode(object):

    def __init__(self, name, context=zmq.Context.instance()):
        self.isac_values = WeakValueDictionary()  # Should be a weakdict

        self.rpc_regexp = re.compile('^rpc://(.*?)/(.*)$')
        self.rpc = ZmqRPC()
        self.pub_sub = ZmqPubSub(context, self._sub_callback)

        self.transport = PyreNode(name, context)
        try:
            self.surveys_manager = SurveysManager(self, self.transport)
            self.events_manager = EventsManager(self, self.transport)
        except Exception:
            self.transport.stop()
            raise

        self.transport.on_new_peer = self._on_new_peer
        self.transport.on_peer_gone = self._on_peer_gone
        self.transport.on_survey = self.surveys_manager.on_survey
        self.transport.on_event = self.events_manager.on_event

        self.rpc.setup_transport(self.transport)
        self.pub_sub.setup_transport(self.transport)

        self.rpc.start()
        self.pub_sub.start()

        self.transport.run()

        green.sleep(0.1)

    def add_rpc(self, f, name=None):
        if name is None:
            name = f.__name__

        published_uri = 'rpc://%s/%s' % (self.name, name)

        self.rpc.register(f, name=name)

        return published_uri

    def call_rpc(self, uri, *args, **kwargs):
        peer_name, func_name = self.rpc_regexp.match(uri).groups()
        return self.rpc.call_on(peer_name.encode(), func_name, *args, **kwargs)

    @property
    def name(self):
        return self.transport.name()

    def name_uuid(self):
        return {'peer_name': self.name, 'peer_uuid': str(self.transport.uuid())}

    def subscribe(self, topic, isac_value):
        self.isac_values[topic] = isac_value
        self.pub_sub.subscribe(topic, isac_value)

    def _sub_callback(self, uri, data):
        logger.debug('(%s) Received update for %s: %s', self.name, uri, data)

        if uri in self.isac_values:
            isac_value = self.isac_values[uri]
            isac_value.update_value_from_isac(*data)

    def survey_value_uri(self, match, timeout=0.5, limit_peers=0):
        return self.surveys_manager.call(
            'SurveyValueUri', match, timeout=timeout, limit_peers=limit_peers)

    def survey_last_value(self, uri, timeout=0.5, limit_peers=3):
        return self.surveys_manager.call(
            'SurveyLastValue', uri, timeout=timeout, limit_peers=limit_peers)

    def survey_value_static_tags(self, uri, timeout=0.5, limit_peers=1):
        return self.surveys_manager.call(
            'SurveyValueStaticTags', uri, timeout=timeout, limit_peers=limit_peers)

    def survey_value_metadata(self, uri, timeout=0.5, limit_peers=1):
        return self.surveys_manager.call(
            'SurveyValueMetadata', uri, timeout=timeout, limit_peers=limit_peers)

    def survey_values_metadata(self, uris, is_re=False, timeout=0.5, limit_peers=1):
        return self.surveys_manager.call(
            'SurveyValuesMetadata', uris, is_re=is_re, timeout=timeout, limit_peers=limit_peers)

    def survey_value_history(self, uri, time_period, timeout=0.5, limit_peers=1):
        return self.surveys_manager.call(
            'SurveyValueHistory', uri, time_period, timeout=timeout, limit_peers=limit_peers)

    def event_isac_value_entering(self, value_uri):
        self.events_manager.send('IsacValueEnteringEvent', value_uri)

    def register_isac_value_entering(self, observer):
        self.events_manager.call('IsacValueEnteringEvent', 'register_observer', observer)

    def unregister_isac_value_entering(self, observer):
        self.events_manager.call('IsacValueEnteringEvent', 'unregister_observer', observer)

    def event_value_metadata_update(self, value_uri, metadata, source_peer):
        self.events_manager.send('ValueMetadataUpdateEvent', value_uri, metadata, source_peer)

    def _on_new_peer(self, peer_id, peer_name, pub_endpoint, rpc_endpoint):
        logger.debug('New peer: %s, %d', peer_name, peer_id)

        self.pub_sub.connect(peer_id, peer_name, pub_endpoint)
        self.rpc.connect(peer_id, peer_name, rpc_endpoint)

    def _on_peer_gone(self, peer_id, peer_name):
        logger.debug('Peer gone: %s, %s', peer_name, peer_id)
        # TODO: cleanup sub and rpc connections

    def serve_forever(self):
        self.transport.task.join()

    def shutdown(self):
        logger.debug('Shutting down transport')
        self.transport.shutdown()

        self.rpc.shutdown()
        self.pub_sub.shutdown()

        green.sleep(0.1)