Ejemplo n.º 1
0
    def test_simple_publish(self):

        ebc = EventBusClient(EventBus())

        mock = Mock()
        ebc.subscribe('news', mock)

        ebc.publish('news', 'message')

        self.assertEqual(mock.call_count, 1)
        mock.assert_called_with('news', 'message')
Ejemplo n.º 2
0
    def test_topic_filtering(self):

        ebc = EventBusClient(EventBus())

        mock = Mock()
        ebc.subscribe('news', mock)

        ebc.publish('news', 'msg1')
        ebc.publish('alerts', 'msg2')
        ebc.publish('logs', 'msg3')

        self.assertEqual(mock.call_count, 1)
        mock.assert_called_with('news', 'msg1')
Ejemplo n.º 3
0
    def test_multiple_subscribers(self):

        ebc = EventBusClient(EventBus())

        mock1 = Mock()
        ebc.subscribe('news', mock1)

        mock2 = Mock()
        ebc.subscribe('alerts', mock2)

        mock3 = Mock()
        ebc.subscribe('logs', mock3)

        mock4 = Mock()
        ebc.subscribe('logs', mock4)

        ebc.publish('news', 'msg1')
        ebc.publish('alerts', 'msg2')
        ebc.publish('logs', 'msg3')

        self.assertEqual(mock1.call_count, 1)
        mock1.assert_called_with('news', 'msg1')

        self.assertEqual(mock2.call_count, 1)
        mock2.assert_called_with('alerts', 'msg2')

        self.assertEqual(mock3.call_count, 1)
        mock3.assert_called_with('logs', 'msg3')

        self.assertEqual(mock4.call_count, 1)
        mock4.assert_called_with('logs', 'msg3')
Ejemplo n.º 4
0
    def test_unsubscribe(self):

        ebc = EventBusClient(EventBus())
        sub = ebc.subscribe('news', lambda msg, topic: None)
        ebc.unsubscribe(sub)
        self.assertEqual(ebc.list_subscribers(), [])
        self.assertEqual(ebc.list_subscribers('news'), [])
Ejemplo n.º 5
0
    def test_subscribe(self):

        ebc = EventBusClient()
        sub = ebc.subscribe('news', lambda msg, topic: None)
        self.assertEqual(len(ebc.list_subscribers()), 1)
        self.assertEqual(len(ebc.list_subscribers('news')), 1)
        self.assertEqual(len(ebc.list_subscribers('other')), 0)
Ejemplo n.º 6
0
class EventBusPublisher(object):
    def __init__(self, kafka_proxy, config):
        self.kafka_proxy = kafka_proxy
        self.config = config
        self.topic_mappings = config.get('topic_mappings', {})
        self.event_bus = EventBusClient()
        self.subscriptions = None

    def start(self):
        log.debug('starting')
        self.subscriptions = list()
        self._setup_subscriptions(self.topic_mappings)
        log.info('started')
        return self

    def stop(self):
        try:
            log.debug('stopping-event-bus')
            if self.subscriptions:
                for subscription in self.subscriptions:
                    self.event_bus.unsubscribe(subscription)
            log.info('stopped-event-bus')
        except Exception as e:
            log.exception('failed-stopping-event-bus', e=e)
            return

    def _setup_subscriptions(self, mappings):

        for event_bus_topic, mapping in six.iteritems(mappings):

            kafka_topic = mapping.get('kafka_topic', None)

            if kafka_topic is None:
                log.error('no-kafka-topic-in-config',
                          event_bus_topic=event_bus_topic,
                          mapping=mapping)
                continue

            self.subscriptions.append(
                self.event_bus.subscribe(
                    event_bus_topic,
                    # to avoid Python late-binding to the last registered
                    # kafka_topic, we force instant binding with the default arg
                    lambda _, m, k=kafka_topic: self.forward(k, m)))

            log.info('event-to-kafka',
                     kafka_topic=kafka_topic,
                     event_bus_topic=event_bus_topic)

    def forward(self, kafka_topic, msg):
        try:
            # convert to JSON string if msg is a protobuf msg
            if isinstance(msg, Message):
                msg = dumps(MessageToDict(msg, True, True))
            log.debug('forward-event-bus-publisher')
            self.kafka_proxy.send_message(kafka_topic, msg)
        except Exception as e:
            log.exception('failed-forward-event-bus-publisher', e=e)
Ejemplo n.º 7
0
    def test_wildcard_topic(self):

        ebc = EventBusClient(EventBus())
        subs = []

        wildcard_sub = Mock()
        subs.append(ebc.subscribe(re.compile(r'.*'), wildcard_sub))

        prefix_sub = Mock()
        subs.append(ebc.subscribe(re.compile(r'ham.*'), prefix_sub))

        contains_sub = Mock()
        subs.append(ebc.subscribe(re.compile(r'.*burg.*'), contains_sub))

        ebc.publish('news', 1)
        ebc.publish('hamsters', 2)
        ebc.publish('hamburgers', 3)
        ebc.publish('nonsense', 4)

        c = call

        self.assertEqual(wildcard_sub.call_count, 4)
        wildcard_sub.assert_has_calls([
            c('news', 1),
            c('hamsters', 2),
            c('hamburgers', 3),
            c('nonsense', 4)])

        self.assertEqual(prefix_sub.call_count, 2)
        prefix_sub.assert_has_calls([
            c('hamsters', 2),
            c('hamburgers', 3)])

        self.assertEqual(contains_sub.call_count, 1)
        contains_sub.assert_has_calls([c('hamburgers', 3)])

        for sub in subs:
            ebc.unsubscribe(sub)

        self.assertEqual(ebc.list_subscribers(), [])
Ejemplo n.º 8
0
    def test_predicates(self):

        ebc = EventBusClient(EventBus())

        get_foos = Mock()
        ebc.subscribe('', get_foos, lambda msg: msg.startswith('foo'))

        get_bars = Mock()
        ebc.subscribe('', get_bars, lambda msg: msg.endswith('bar'))

        get_all = Mock()
        ebc.subscribe('', get_all)

        get_none = Mock()
        ebc.subscribe('', get_none, lambda msg: msg.find('zoo') >= 0)

        errored = Mock()
        ebc.subscribe('', errored, lambda msg: 1/0)

        ebc.publish('', 'foo')
        ebc.publish('', 'foobar')
        ebc.publish('', 'bar')

        c = call

        self.assertEqual(get_foos.call_count, 2)
        get_foos.assert_has_calls([c('', 'foo'), c('', 'foobar')])

        self.assertEqual(get_bars.call_count, 2)
        get_bars.assert_has_calls([c('', 'foobar'), c('', 'bar')])

        self.assertEqual(get_all.call_count, 3)
        get_all.assert_has_calls([c('', 'foo'), c('', 'foobar'), c('', 'bar')])

        get_none.assert_not_called()

        errored.assert_not_called()
class OmciTestRequest(Task):
    """
    OpenOMCI Test an OMCI ME Instance Attributes

    Upon completion, the Task deferred callback is invoked with a reference of
    this Task object.

    """
    task_priority = 128
    name = "ONU OMCI Test Task"
    MAX_TABLE_SIZE = 16 * 1024  # Keep get-next logic reasonable
    OPTICAL_GROUP_NAME = 'PON_Optical'
    DEFAULT_COLLECTION_FREQUENCY = 600 * 10  # 10 minutes
    DEFAULT_FREQUENCY_KEY = 'default-collection-frequency'

    def __init__(self,
                 core_proxy,
                 omci_agent,
                 device_id,
                 entity_class,
                 serial_number,
                 logical_device_id,
                 exclusive=True,
                 uuid=None,
                 allow_failure=False,
                 **kwargs):
        """
        Class initialization

        :param omci_agent: (OmciAdapterAgent) OMCI Adapter agent
        :param device_id: (str) ONU Device ID
        :param entity_class: (EntityClass) ME Class to retrieve
        :param entity_id: (int) ME Class instance ID to retrieve
        :param attributes: (list or set) Name of attributes to retrieve
        :param exclusive: (bool) True if this GET request Task exclusively own the
                                 OMCI-CC while running. Default: True
        :param allow_failure: (bool) If true, attempt to get all valid attributes
                                     if the original request receives an error
                                     code of 9 (Attributes failed or unknown).
        """
        super(OmciTestRequest,
              self).__init__(OmciTestRequest.name,
                             omci_agent,
                             device_id,
                             priority=OmciTestRequest.task_priority,
                             exclusive=exclusive)
        self._device = omci_agent.get_device(device_id)
        self._entity_class = entity_class
        self._allow_failure = allow_failure
        self._failed_or_unknown_attributes = set()
        self._results = None
        self._local_deferred = None
        self.device_id = device_id
        self.event_bus = EventBusClient()
        self.lc = None
        self.default_freq = \
            kwargs.get(OmciTestRequest.DEFAULT_FREQUENCY_KEY,
                       OmciTestRequest.DEFAULT_COLLECTION_FREQUENCY)
        self.serial_number = serial_number
        self.logical_device_id = logical_device_id
        self.core_proxy = core_proxy
        self.uuid = uuid
        topic = 'omci-rx:{}:{}'.format(self.device_id, 'Test_Result')
        self.msg = self.event_bus.subscribe(topic, self.process_messages)

    def cancel_deferred(self):
        """

        :return: None
        """
        super(OmciTestRequest, self).cancel_deferred()

        d, self._local_deferred = self._local_deferred, None
        try:
            if d is not None and not d.called:
                d.cancel()
        except:
            pass

    @property
    def me_class(self):
        """The OMCI Managed Entity Class associated with this request"""
        return self._entity_class

    @property
    def entity_id(self):
        """The ME Entity ID associated with this request"""
        return self._entity_id

    @property
    def success_code(self):
        """
        Return the OMCI success/reason code for the Get Response.
        """
        if self._results is None:
            return None
        return self._results.fields['omci_message'].fields['success']

    def start_collector(self, callback=None):
        """
                Start the collection loop for an adapter if the frequency > 0

                :param callback: (callable) Function to call to collect PM data
        """
        self.log.info("starting-pm-collection",
                      device_name=self.name,
                      default_freq=self.default_freq)
        if callback is None:
            callback = self.perform_test_omci

        if self.lc is None:
            self.lc = LoopingCall(callback)

        if self.default_freq > 0:
            self.lc.start(interval=self.default_freq / 10)

    def stop_collector(self):
        """ Stop the collection loop"""
        if self.lc is not None and self.default_freq > 0:
            self.lc.stop()

    def format_id(self, event):
        return 'voltha.{}.{}.{}'.format(self.core_proxy.listening_topic,
                                        self.device_id, event)

    def get_event_header(self, _type, category, sub_category, event,
                         raised_ts):
        """

        :return: (dict) Event header
        """
        hdr = EventHeader(id=self.format_id(event),
                          category=category,
                          sub_category=sub_category,
                          type=_type,
                          type_version="0.1",
                          raised_ts=raised_ts)
        hdr.reported_ts.GetCurrentTime()
        return hdr

    def publish_metrics(self, data, event_name, onu_device_id):
        """

        :param data:  actual test result dict
        :param event_name: Test_result
        :param onu_device_id:  Onu device id
        :return: None
        """
        metric_data = MetricInformation(metadata=MetricMetaData(
            title=OmciTestRequest.OPTICAL_GROUP_NAME,
            ts=arrow.utcnow().float_timestamp,
            logical_device_id=self.logical_device_id,
            serial_no=self.serial_number,
            device_id=onu_device_id,
            uuid=self.uuid,
            context={'events': event_name}),
                                        metrics=data)
        self.log.info('Publish-Test-Result')
        raised_ts = Timestamp()
        raised_ts.GetCurrentTime()
        event_header = self.get_event_header(EventType.KPI_EVENT2,
                                             EventCategory.EQUIPMENT,
                                             EventSubCategory.ONU, "KPI_EVENT",
                                             raised_ts)
        kpi_event = KpiEvent2(type=KpiEventType.slice,
                              ts=arrow.utcnow().float_timestamp,
                              slice_data=[metric_data])
        event = Event(header=event_header, kpi_event2=kpi_event)
        self.core_proxy.submit_event(event)

    def process_messages(self, topic, msg):
        """

        :param topic: topic name of onu.
        :param msg: actual test result dict
        :return: None
        """
        result_frame = {}
        event_name = topic.split(':')[-1]
        onu_device_id = topic.split(':')[-2]
        frame = msg['rx-response']
        for key, value in six.iteritems((frame.fields['omci_message'].fields)):
            result_frame[key] = int(value)
        self.publish_metrics(result_frame, event_name, onu_device_id)

    @inlineCallbacks
    def perform_test_omci(self):
        """
        Perform the initial test request
        """
        ani_g_entities = self._device.configuration.ani_g_entities
        ani_g_entities_ids = list(ani_g_entities.keys()) if ani_g_entities \
                                                      is not None else None
        self._entity_id = ani_g_entities_ids[0]
        self.log.info('perform-test',
                      entity_class=self._entity_class,
                      entity_id=self._entity_id)
        try:
            frame = MEFrame(self._entity_class, self._entity_id, []).test()
            result = yield self._device.omci_cc.send(frame)
            if not result.fields['omci_message'].fields['success_code']:
                self.log.info(
                    'Self-Test Submitted Successfully',
                    code=result.fields['omci_message'].fields['success_code'])
            else:
                raise TestFailure('Test Failure: {}'.format(
                    result.fields['omci_message'].fields['success_code']))
        except TimeoutError as e:
            self.deferred.errback(failure.Failure(e))

        except Exception as e:
            self.log.exception('perform-test-Error',
                               e=e,
                               class_id=self._entity_class,
                               entity_id=self._entity_id)
            self.deferred.errback(failure.Failure(e))