def test_ListenerStatistics_iadd(self): # test incrementing add function bytes_in1 = random.randrange(1000000000) bytes_out1 = random.randrange(1000000000) active_conns1 = random.randrange(1000000000) total_conns1 = random.randrange(1000000000) request_errors1 = random.randrange(1000000000) stats_1 = data_models.ListenerStatistics( listener_id=self.LISTENER_ID, amphora_id=self.AMP_ID, bytes_in=bytes_in1, bytes_out=bytes_out1, active_connections=active_conns1, total_connections=total_conns1, request_errors=request_errors1) bytes_in2 = random.randrange(1000000000) bytes_out2 = random.randrange(1000000000) active_conns2 = random.randrange(1000000000) total_conns2 = random.randrange(1000000000) request_errors2 = random.randrange(1000000000) stats_2 = data_models.ListenerStatistics( listener_id="listener 2", amphora_id="amphora 2", bytes_in=bytes_in2, bytes_out=bytes_out2, active_connections=active_conns2, total_connections=total_conns2, request_errors=request_errors2) # test successful += stats_1 += stats_2 # not a delta, so it won't be incremented self.assertEqual(stats_1.active_connections, active_conns1) self.assertEqual(stats_1.listener_id, self.LISTENER_ID) self.assertEqual(stats_1.amphora_id, self.AMP_ID) # deltas will be incremented self.assertEqual(stats_1.bytes_in, bytes_in1 + bytes_in2) self.assertEqual(stats_1.bytes_out, bytes_out1 + bytes_out2) self.assertEqual(stats_1.total_connections, total_conns1 + total_conns2) self.assertEqual(stats_1.request_errors, request_errors1 + request_errors2) # test incrementing an incompatible object self.assertRaises(TypeError, stats_1.__iadd__, "boom")
def setUp(self): super(TestStatsMixin, self).setUp() self.sm = stats.StatsMixin() self.session = mock.MagicMock() self.listener_id = uuidutils.generate_uuid() self.amphora_id = uuidutils.generate_uuid() self.repo_listener_stats = mock.MagicMock() self.sm.listener_stats_repo = self.repo_listener_stats self.fake_stats = data_models.ListenerStatistics( listener_id=self.listener_id, amphora_id=self.amphora_id, bytes_in=random.randrange(1000000000), bytes_out=random.randrange(1000000000), active_connections=random.randrange(1000000000), total_connections=random.randrange(1000000000), request_errors=random.randrange(1000000000)) self.sm.listener_stats_repo.get_all.return_value = ([self.fake_stats], None) self.repo_amphora = mock.MagicMock() self.sm.repo_amphora = self.repo_amphora
def setUp(self): super(TestStatsBase, self).setUp() self.conf = oslo_fixture.Config(cfg.CONF) self.conf.config(group="controller_worker", statistics_drivers=STATS_DRIVERS) self.amphora_id = uuidutils.generate_uuid() self.listener_id = uuidutils.generate_uuid() self.listener_stats = data_models.ListenerStatistics( amphora_id=self.amphora_id, listener_id=self.listener_id, bytes_in=random.randrange(1000000000), bytes_out=random.randrange(1000000000), active_connections=random.randrange(1000000000), total_connections=random.randrange(1000000000), request_errors=random.randrange(1000000000)) self.listener_stats_dict = { self.listener_id: { "request_errors": self.listener_stats.request_errors, "active_connections": self.listener_stats.active_connections, "total_connections": self.listener_stats.total_connections, "bytes_in": self.listener_stats.bytes_in, "bytes_out": self.listener_stats.bytes_out, } }
def test_update_stats(self, mock_get_session, mock_listener_stats_repo): bytes_in1 = random.randrange(1000000000) bytes_out1 = random.randrange(1000000000) active_conns1 = random.randrange(1000000000) total_conns1 = random.randrange(1000000000) request_errors1 = random.randrange(1000000000) stats_1 = data_models.ListenerStatistics( listener_id=self.listener_id, amphora_id=self.amphora_id, bytes_in=bytes_in1, bytes_out=bytes_out1, active_connections=active_conns1, total_connections=total_conns1, request_errors=request_errors1 ) bytes_in2 = random.randrange(1000000000) bytes_out2 = random.randrange(1000000000) active_conns2 = random.randrange(1000000000) total_conns2 = random.randrange(1000000000) request_errors2 = random.randrange(1000000000) stats_2 = data_models.ListenerStatistics( listener_id=self.listener_id, amphora_id=self.amphora_id, bytes_in=bytes_in2, bytes_out=bytes_out2, active_connections=active_conns2, total_connections=total_conns2, request_errors=request_errors2 ) update_db.StatsUpdateDb().update_stats( [stats_1, stats_2], deltas=False) mock_listener_stats_repo().replace.assert_has_calls([ mock.call(mock_get_session(), stats_1), mock.call(mock_get_session(), stats_2) ]) update_db.StatsUpdateDb().update_stats( [stats_1, stats_2], deltas=True) mock_listener_stats_repo().increment.assert_has_calls([ mock.call(mock_get_session(), stats_1), mock.call(mock_get_session(), stats_2) ])
def test_update_listeners_stats_with_statistics(self, mock_stats_base): LISTENER_STATS = o_data_models.ListenerStatistics( listener_id=uuidutils.generate_uuid()) mock_get_listener = task.UpdateListenersStats() mock_get_listener.listener_repo = mock.MagicMock() mock_get_listener.listener_repo.get_all.return_value = [LISTENER], None mock_get_listener.listener_stats_repo = mock.MagicMock() mock_get_listener.listener_stats_repo.get_all.return_value = [ LISTENER_STATS ], None mock_get_listener.execute([LISTENER_STATS]) mock_stats_base.assert_called_once_with([LISTENER_STATS])
def update_listener_statistics(self, statistics): """Update listener statistics. :param statistics: Statistics for listeners: id (string): ID for listener. active_connections (int): Number of currently active connections. bytes_in (int): Total bytes received. bytes_out (int): Total bytes sent. request_errors (int): Total requests not fulfilled. total_connections (int): The total connections handled. :type statistics: dict :raises: UpdateStatisticsError :returns: None """ listener_stats = statistics.get(lib_consts.LISTENERS, []) stats_objects = [] for stat in listener_stats: try: stats_obj = data_models.ListenerStatistics( listener_id=stat['id'], bytes_in=stat['bytes_in'], bytes_out=stat['bytes_out'], active_connections=stat['active_connections'], total_connections=stat['total_connections'], request_errors=stat['request_errors'], received_time=time.time()) stats_objects.append(stats_obj) except Exception as e: return { lib_consts.STATUS_CODE: lib_consts.DRVR_STATUS_CODE_FAILED, lib_consts.FAULT_STRING: str(e), lib_consts.STATS_OBJECT: lib_consts.LISTENERS } # Provider drivers other than the amphora driver do not have # an amphora ID, use the listener ID again here to meet the # constraint requirement. try: if stats_objects: stats_base.update_stats_via_driver(stats_objects) except Exception as e: return { lib_consts.STATUS_CODE: lib_consts.DRVR_STATUS_CODE_FAILED, lib_consts.FAULT_STRING: str(e), lib_consts.STATS_OBJECT: lib_consts.LISTENERS } return {lib_consts.STATUS_CODE: lib_consts.DRVR_STATUS_CODE_OK}
def setUp(self): super(TestUpdateStatsDb, self).setUp() conf = self.useFixture(oslo_fixture.Config(cfg.CONF)) conf.config(group="health_manager", event_streamer_driver='queue_event_streamer') self.sm = update_db.UpdateStatsDb() self.event_client = mock.MagicMock() self.sm.event_streamer.client = self.event_client self.listener_stats_repo = mock.MagicMock() self.sm.listener_stats_repo = self.listener_stats_repo self.loadbalancer_id = uuidutils.generate_uuid() self.listener_id = uuidutils.generate_uuid() self.listener_stats = data_models.ListenerStatistics( listener_id=self.listener_id, bytes_in=random.randrange(1000000000), bytes_out=random.randrange(1000000000), active_connections=random.randrange(1000000000), total_connections=random.randrange(1000000000), request_errors=random.randrange(1000000000)) self.sm.get_listener_stats = mock.MagicMock() self.sm.get_listener_stats.return_value = self.listener_stats self.loadbalancer_id = uuidutils.generate_uuid() self.amphora_id = uuidutils.generate_uuid() self.listener_id = uuidutils.generate_uuid() self.listener = db_models.Listener( load_balancer_id=self.loadbalancer_id) self.listener_repo = mock.MagicMock() self.sm.repo_listener = self.listener_repo self.sm.repo_listener.get.return_value = self.listener self.loadbalancer_repo = mock.MagicMock() self.sm.repo_loadbalancer = self.loadbalancer_repo self.loadbalancer = db_models.LoadBalancer( id=self.loadbalancer_id, listeners=[self.listener]) self.loadbalancer_repo.get.return_value = self.loadbalancer
def get_listener_stats(self, session, listener_id): """Gets the listener statistics data_models object.""" db_ls, _ = self.listener_stats_repo.get_all(session, listener_id=listener_id) if not db_ls: LOG.warning("Listener Statistics for Listener %s was not found", listener_id) statistics = data_models.ListenerStatistics(listener_id=listener_id) for db_l in db_ls: statistics += db_l amp = self.repo_amphora.get(session, id=db_l.amphora_id) if amp and amp.status == constants.AMPHORA_ALLOCATED: statistics.active_connections += db_l.active_connections return statistics
def setUp(self): super(TestUpdateStatsDb, self).setUp() self.sm = update_db.UpdateStatsDb() self.event_client = mock.MagicMock() self.sm.event_streamer.client = self.event_client self.listener_stats_repo = mock.MagicMock() self.sm.listener_stats_repo = self.listener_stats_repo self.loadbalancer_id = uuidutils.generate_uuid() self.listener_id = uuidutils.generate_uuid() self.listener_stats = data_models.ListenerStatistics( listener_id=self.listener_id, bytes_in=random.randrange(1000000000), bytes_out=random.randrange(1000000000), active_connections=random.randrange(1000000000), total_connections=random.randrange(1000000000), request_errors=random.randrange(1000000000)) self.sm.get_listener_stats = mock.MagicMock() self.sm.get_listener_stats.return_value = self.listener_stats self.loadbalancer_id = uuidutils.generate_uuid() self.amphora_id = uuidutils.generate_uuid() self.listener_id = uuidutils.generate_uuid() self.listener = db_models.Listener( load_balancer_id=self.loadbalancer_id) self.listener_repo = mock.MagicMock() self.sm.repo_listener = self.listener_repo self.sm.repo_listener.get.return_value = self.listener self.loadbalancer_repo = mock.MagicMock() self.sm.repo_loadbalancer = self.loadbalancer_repo self.loadbalancer = db_models.LoadBalancer(id=self.loadbalancer_id, listeners=[self.listener]) self.loadbalancer_repo.get.return_value = self.loadbalancer
def get_listener_stats(self, session, listener_id): """Gets the listener statistics data_models object.""" db_ls, _ = self.listener_stats_repo.get_all(session, listener_id=listener_id) if not db_ls: LOG.warning("Listener Statistics for Listener %s was not found", listener_id) statistics = data_models.ListenerStatistics(listener_id=listener_id) for db_l in db_ls: statistics += db_l amp = self.repo_amphora.get(session, id=db_l.amphora_id) # Amphora ID and Listener ID will be the same in the case that the # stats are coming from a provider driver other than the `amphora` # driver. In that case and when the current amphora is ALLOCATED # are the only times we should include the *active* connections, # because non-active amphora will have incorrect counts. if (amp and amp.status == constants.AMPHORA_ALLOCATED) or ( db_l.amphora_id == db_l.listener_id): statistics.active_connections += db_l.active_connections return statistics
def update_stats(health_message): """Parses the health message then passes it to the stats driver(s) :param health_message: The health message containing the listener stats :type health_message: dict Example V1 message:: health = { "id": "<amphora_id>", "listeners": { "<listener_id>": { "status": "OPEN", "stats": { "ereq": 0, "conns": 0, "totconns": 0, "rx": 0, "tx": 0, }, "pools": { "<pool_id>": { "status": "UP", "members": {"<member_id>": "ONLINE"} } } } } } Example V2 message:: {"id": "<amphora_id>", "seq": 67, "listeners": { "<listener_id>": { "status": "OPEN", "stats": { "tx": 0, "rx": 0, "conns": 0, "totconns": 0, "ereq": 0 } } }, "pools": { "<pool_id>:<listener_id>": { "status": "UP", "members": { "<member_id>": "no check" } } }, "ver": 2 "recv_time": time.time() } Example V3 message:: Same as V2 message, except values are deltas rather than absolutes. """ version = health_message.get("ver", 2) deltas = False if version >= 3: deltas = True amphora_id = health_message.get('id') listeners = health_message.get('listeners', {}) listener_stats = [] for listener_id, listener in listeners.items(): listener_dict = listener.get('stats') stats_model = data_models.ListenerStatistics( listener_id=listener_id, amphora_id=amphora_id, bytes_in=listener_dict.get('rx'), bytes_out=listener_dict.get('tx'), active_connections=listener_dict.get('conns'), total_connections=listener_dict.get('totconns'), request_errors=listener_dict.get('ereq'), received_time=health_message.get('recv_time')) LOG.debug("Listener %s / Amphora %s stats: %s", listener_id, amphora_id, stats_model.get_stats()) listener_stats.append(stats_model) stats_base.update_stats_via_driver(listener_stats, deltas=deltas)
def test_update_listener_statistics(self, mock_stats_base, mock_time): mock_time.return_value = 12345.6 listener_stats_li = [ {"id": 1, "active_connections": 10, "bytes_in": 20, "bytes_out": 30, "request_errors": 40, "total_connections": 50}, {"id": 2, "active_connections": 60, "bytes_in": 70, "bytes_out": 80, "request_errors": 90, "total_connections": 100}] listener_stats_dict = {"listeners": listener_stats_li} mock_stats_base.side_effect = [mock.DEFAULT, Exception('boom')] result = self.driver_updater.update_listener_statistics( listener_stats_dict) listener_stats_objects = [ data_models.ListenerStatistics( listener_id=listener_stats_li[0]['id'], active_connections=listener_stats_li[0]['active_connections'], bytes_in=listener_stats_li[0]['bytes_in'], bytes_out=listener_stats_li[0]['bytes_out'], request_errors=listener_stats_li[0]['request_errors'], total_connections=listener_stats_li[0]['total_connections'], received_time=mock_time.return_value), data_models.ListenerStatistics( listener_id=listener_stats_li[1]['id'], active_connections=listener_stats_li[1]['active_connections'], bytes_in=listener_stats_li[1]['bytes_in'], bytes_out=listener_stats_li[1]['bytes_out'], request_errors=listener_stats_li[1]['request_errors'], total_connections=listener_stats_li[1]['total_connections'], received_time=mock_time.return_value)] mock_stats_base.assert_called_once_with(listener_stats_objects) self.assertEqual(self.ref_ok_response, result) # Test empty stats updates mock_stats_base.reset_mock() result = self.driver_updater.update_listener_statistics({}) mock_stats_base.assert_not_called() self.assertEqual(self.ref_ok_response, result) # Test missing ID bad_id_dict = {"listeners": [{"notID": "one"}]} result = self.driver_updater.update_listener_statistics(bad_id_dict) ref_update_listener_stats_error = { lib_consts.STATUS_CODE: lib_consts.DRVR_STATUS_CODE_FAILED, lib_consts.STATS_OBJECT: lib_consts.LISTENERS, lib_consts.FAULT_STRING: "'id'"} self.assertEqual(ref_update_listener_stats_error, result) # Test for replace exception result = self.driver_updater.update_listener_statistics( listener_stats_dict) ref_update_listener_stats_error = { lib_consts.STATUS_CODE: lib_consts.DRVR_STATUS_CODE_FAILED, lib_consts.STATS_OBJECT: lib_consts.LISTENERS, lib_consts.FAULT_STRING: 'boom'} self.assertEqual(ref_update_listener_stats_error, result)
def test_update_stats(self, mock_log): self.logger.update_stats([data_models.ListenerStatistics()]) self.assertEqual(1, mock_log.info.call_count)