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')
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')
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')
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'), [])
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)
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)
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(), [])
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))