diff --git a/octavia/amphorae/backends/health_daemon/health_daemon.py b/octavia/amphorae/backends/health_daemon/health_daemon.py index 319ef4b041..42d475a8fe 100644 --- a/octavia/amphorae/backends/health_daemon/health_daemon.py +++ b/octavia/amphorae/backends/health_daemon/health_daemon.py @@ -17,10 +17,12 @@ import errno import os import queue +import stat import time from oslo_config import cfg from oslo_log import log as logging +import simplejson from octavia.amphorae.backends.agent.api_server import util from octavia.amphorae.backends.health_daemon import health_sender @@ -38,8 +40,57 @@ SEQ = 0 # # ver 1 - Adds UDP listener status when no pool or members are present # ver 2 - Switch to all listeners in a single combined haproxy config -# -MSG_VER = 2 +# ver 3 - Switch stats reporting to deltas + +MSG_VER = 3 + +DELTA_METRICS = ('bin', 'bout', 'ereq', 'stot') + +# Filesystem persistent counters for statistics deltas +COUNTERS = None +COUNTERS_FILE = None + + +def get_counters_file(): + global COUNTERS_FILE + if COUNTERS_FILE is None: + stats_file_path = os.path.join( + CONF.haproxy_amphora.base_path, "stats_counters.json") + # Open for read+write and create if necessary + flags = os.O_RDWR | os.O_CREAT + # mode 00644 + mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP + try: + COUNTERS_FILE = os.fdopen( + os.open(stats_file_path, flags, mode), 'r+') + except OSError: + LOG.info("Failed to open `%s`, ignoring...", stats_file_path) + COUNTERS_FILE.seek(0) + return COUNTERS_FILE + + +def get_counters(): + global COUNTERS + if COUNTERS is None: + try: + COUNTERS = simplejson.load(get_counters_file()) or {} + except (simplejson.JSONDecodeError, AttributeError): + COUNTERS = {} + return COUNTERS + + +def persist_counters(): + """Attempt to persist the latest statistics values""" + if COUNTERS is None: + return + try: + stats = simplejson.dumps(COUNTERS) + counters_file = get_counters_file() + counters_file.truncate(0) + counters_file.write(stats) + counters_file.flush() + except (OSError, AttributeError): + LOG.warning("Couldn't persist statistics counter file!") def list_sock_stat_files(hadir=None): @@ -83,11 +134,12 @@ def run_sender(cmd_queue): LOG.error('Keepalived is configured but not running, ' 'skipping health heartbeat.') else: - LOG.error('Failed to check keepalived and haproxy status due ' - 'to exception %s, skipping health heartbeat.', e) + LOG.exception('Failed to check keepalived and haproxy status ' + 'due to exception %s, skipping health ' + 'heartbeat.', e) except Exception as e: - LOG.error('Failed to check keepalived and haproxy status due to ' - 'exception %s, skipping health heartbeat.', e) + LOG.exception('Failed to check keepalived and haproxy status due ' + 'to exception %s, skipping health heartbeat.', e) try: cmd = cmd_queue.get_nowait() @@ -109,33 +161,59 @@ def get_stats(stat_sock_file): return stats, pool_status +def calculate_stats_deltas(listener_id, row): + counters = get_counters() + listener_counters = counters.get(listener_id, {}) + counters[listener_id] = listener_counters + + delta_values = {} + for metric_key in DELTA_METRICS: + current_value = int(row[metric_key]) + # Get existing counter for our metrics + last_value = listener_counters.get(metric_key, 0) + # Store the new absolute value + listener_counters[metric_key] = current_value + # Calculate a delta for each metric + delta = current_value - last_value + # Did HAProxy restart or reset counters? + if delta < 0: + delta = current_value # If so, reset ours. + delta_values[metric_key] = delta + + return delta_values + + def build_stats_message(): - # Example version 2 message without UDP: - # { - # "id": "", - # "seq": 67, - # "listeners": { - # "": { - # "status": "OPEN", - # "stats": { - # "tx": 0, - # "rx": 0, - # "conns": 0, - # "totconns": 0, - # "ereq": 0 - # } - # } - # }, - # "pools": { - # ":": { - # "status": "UP", - # "members": { - # "": "no check" - # } - # } - # }, - # "ver": 2 - # } + """Build a stats message based on retrieved listener statistics. + + Example version 3 message without UDP (note that values are deltas, + not absolutes):: + + {"id": "", + "seq": 67, + "listeners": { + "": { + "status": "OPEN", + "stats": { + "tx": 0, + "rx": 0, + "conns": 0, + "totconns": 0, + "ereq": 0 + } + } + }, + "pools": { + ":": { + "status": "UP", + "members": { + "": "no check" + } + } + }, + "ver": 3 + } + """ global SEQ msg = {'id': CONF.amphora_agent.amphora_id, 'seq': SEQ, 'listeners': {}, 'pools': {}, @@ -149,13 +227,14 @@ def build_stats_message(): for row in stats: if row['svname'] == 'FRONTEND': listener_id = row['pxname'] + delta_values = calculate_stats_deltas(listener_id, row) msg['listeners'][listener_id] = { 'status': row['status'], - 'stats': {'tx': int(row['bout']), - 'rx': int(row['bin']), + 'stats': {'tx': delta_values['bout'], + 'rx': delta_values['bin'], 'conns': int(row['scur']), - 'totconns': int(row['stot']), - 'ereq': int(row['ereq'])}} + 'totconns': delta_values['stot'], + 'ereq': delta_values['ereq']}} for pool_id, pool in pool_status.items(): msg['pools'][pool_id] = {"status": pool['status'], "members": pool['members']} @@ -166,16 +245,18 @@ def build_stats_message(): listeners_stats = keepalivedlvs_query.get_udp_listeners_stats() if listeners_stats: for listener_id, listener_stats in listeners_stats.items(): + delta_values = calculate_stats_deltas( + listener_id, listener_stats['stats']) pool_status = keepalivedlvs_query.get_udp_listener_pool_status( listener_id) udp_listener_dict = dict() udp_listener_dict['status'] = listener_stats['status'] udp_listener_dict['stats'] = { - 'tx': listener_stats['stats']['bout'], - 'rx': listener_stats['stats']['bin'], + 'tx': delta_values['bout'], + 'rx': delta_values['bin'], 'conns': listener_stats['stats']['scur'], - 'totconns': listener_stats['stats']['stot'], - 'ereq': listener_stats['stats']['ereq'] + 'totconns': delta_values['stot'], + 'ereq': delta_values['ereq'] } if pool_status: pool_id = pool_status['lvs']['uuid'] @@ -184,4 +265,5 @@ def build_stats_message(): "members": pool_status['lvs']['members'] } msg['listeners'][listener_id] = udp_listener_dict + persist_counters() return msg diff --git a/octavia/common/data_models.py b/octavia/common/data_models.py index 7ecc4df11b..236943df3e 100644 --- a/octavia/common/data_models.py +++ b/octavia/common/data_models.py @@ -208,6 +208,10 @@ class ListenerStatistics(BaseDataModel): self.bytes_out += other.bytes_out self.request_errors += other.request_errors self.total_connections += other.total_connections + else: + raise TypeError( # noqa: O342 + "unsupported operand type(s) for +=: '{0}' and '{1}'".format( + type(self), type(other))) return self diff --git a/octavia/controller/healthmanager/health_drivers/update_db.py b/octavia/controller/healthmanager/health_drivers/update_db.py index c9e4659ece..e011fc00cc 100644 --- a/octavia/controller/healthmanager/health_drivers/update_db.py +++ b/octavia/controller/healthmanager/health_drivers/update_db.py @@ -23,6 +23,7 @@ import sqlalchemy from stevedore import driver as stevedore_driver from octavia.common import constants +from octavia.common import data_models from octavia.common import stats from octavia.controller.healthmanager.health_drivers import update_base from octavia.db import api as db_api @@ -461,10 +462,6 @@ class UpdateHealthDb(update_base.HealthUpdateBase): class UpdateStatsDb(update_base.StatsUpdateBase, stats.StatsMixin): - def __init__(self): - super(UpdateStatsDb, self).__init__() - self.repo_listener = repo.ListenerRepository() - def update_stats(self, health_message, srcaddr): # The executor will eat any exceptions from the update_stats code # so we need to wrap it and log the unhandled exception @@ -533,7 +530,28 @@ class UpdateStatsDb(update_base.StatsUpdateBase, stats.StatsMixin): "ver": 2 } + Example V3 message:: + + See V2 message, except values are deltas rather than absolutes. + """ + + version = health_message.get("ver", 1) + + if version <= 2: + self.version2(health_message) + elif version == 3: + self.version3(health_message) + else: + LOG.warning("Unknown message version: %s, ignoring...", version) + + def version2(self, health_message): + """Parse version 1 and 2 of the health message. + + :param health_message: health message dictionary + :type health_message: dict + """ + session = db_api.get_session() amphora_id = health_message['id'] @@ -545,8 +563,36 @@ class UpdateStatsDb(update_base.StatsUpdateBase, stats.StatsMixin): 'active_connections': stats['conns'], 'total_connections': stats['totconns'], 'request_errors': stats['ereq']} - LOG.debug("Updating listener stats in db and sending event.") - LOG.debug("Listener %s / Amphora %s stats: %s", + LOG.debug("Updating listener stats in db." + "Listener %s / Amphora %s stats: %s", listener_id, amphora_id, stats) self.listener_stats_repo.replace( session, listener_id, amphora_id, **stats) + + def version3(self, health_message): + """Parse version 3 of the health message. + + :param health_message: health message dictionary + :type health_message: dict + """ + + session = db_api.get_session() + + amphora_id = health_message['id'] + listeners = health_message['listeners'] + for listener_id, listener in listeners.items(): + + delta_stats = listener.get('stats') + delta_stats_model = data_models.ListenerStatistics( + listener_id=listener_id, + amphora_id=amphora_id, + bytes_in=delta_stats['rx'], + bytes_out=delta_stats['tx'], + active_connections=delta_stats['conns'], + total_connections=delta_stats['totconns'], + request_errors=delta_stats['ereq'] + ) + LOG.debug("Updating listener stats in db." + "Listener %s / Amphora %s stats: %s", + listener_id, amphora_id, delta_stats_model.to_dict()) + self.listener_stats_repo.increment(session, delta_stats_model) diff --git a/octavia/db/models.py b/octavia/db/models.py index 5891ef3c73..83ec3740b5 100644 --- a/octavia/db/models.py +++ b/octavia/db/models.py @@ -175,6 +175,21 @@ class ListenerStatistics(base_models.BASE): 'Current value is %(value)d.') % data) return value + def __iadd__(self, other): + + if isinstance(other, (ListenerStatistics, + data_models.ListenerStatistics)): + self.bytes_in += other.bytes_in + self.bytes_out += other.bytes_out + self.request_errors += other.request_errors + self.total_connections += other.total_connections + else: + raise TypeError( # noqa: O342 + "unsupported operand type(s) for +=: '{0}' and '{1}'".format( + type(self), type(other))) + + return self + class Member(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, models.TimestampMixin, base_models.NameMixin, diff --git a/octavia/db/repositories.py b/octavia/db/repositories.py index 336487130b..0d4a885bd1 100644 --- a/octavia/db/repositories.py +++ b/octavia/db/repositories.py @@ -1222,8 +1222,39 @@ class ListenerStatisticsRepository(BaseRepository): model_kwargs['amphora_id'] = amphora_id self.create(session, **model_kwargs) + def increment(self, session, delta_stats): + """Updates a listener's statistics, incrementing by the passed deltas. + + :param session: A Sql Alchemy database session + :param delta_stats: Listener statistics deltas to add + :type delta_stats: octavia.common.data_models.ListenerStatistics + + """ + + with session.begin(subtransactions=True): + count = session.query(self.model_class).filter_by( + listener_id=delta_stats.listener_id, + amphora_id=delta_stats.amphora_id).count() + if count: + existing_stats = session.query( + self.model_class).with_for_update().filter_by( + listener_id=delta_stats.listener_id, + amphora_id=delta_stats.amphora_id).one() + existing_stats += delta_stats + existing_stats.active_connections = ( + delta_stats.active_connections) + else: + self.create(session, **delta_stats.to_dict()) + def update(self, session, listener_id, **model_kwargs): - """Updates a listener's statistics by a listener's id.""" + """Updates a listener's statistics, overriding with the passed values. + + :param session: A Sql Alchemy database session + :param listener_id: The UUID of the listener to update + :type listener_id: str + :param model_kwargs: Entity attributes that should be updated + + """ with session.begin(subtransactions=True): session.query(self.model_class).filter_by( listener_id=listener_id).update(model_kwargs) diff --git a/octavia/tests/functional/db/test_repositories.py b/octavia/tests/functional/db/test_repositories.py index 7222d926ea..4ea4484067 100644 --- a/octavia/tests/functional/db/test_repositories.py +++ b/octavia/tests/functional/db/test_repositories.py @@ -25,7 +25,7 @@ from sqlalchemy.orm import defer from sqlalchemy.orm import exc as sa_exception from octavia.common import constants -from octavia.common import data_models as models +from octavia.common import data_models from octavia.common import exceptions from octavia.db import api as db_api from octavia.db import models as db_models @@ -512,7 +512,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): db_lb = self.repos.create_load_balancer_tree(self.session, lock_session, lb) self.assertIsNotNone(db_lb) - self.assertIsInstance(db_lb, models.LoadBalancer) + self.assertIsInstance(db_lb, data_models.LoadBalancer) def test_sqlite_transactions_broken(self): self.skipTest("SLQAlchemy/PySqlite transaction handling is broken. " @@ -1081,7 +1081,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='api_settings', auth_strategy=constants.NOAUTH) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) conf.config(group='api_settings', auth_strategy=constants.TESTING) @@ -1089,14 +1089,15 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.assertRaises(exceptions.MissingProjectID, self.repos.check_quota_met, self.session, self.session, - models.LoadBalancer, None) + data_models.LoadBalancer, None) # Test non-quota object project_id = uuidutils.generate_uuid() - self.assertFalse(self.repos.check_quota_met(self.session, - self.session, - models.SessionPersistence, - project_id)) + self.assertFalse( + self.repos.check_quota_met(self.session, + self.session, + data_models.SessionPersistence, + project_id)) # Test DB deadlock case project_id = uuidutils.generate_uuid() mock_session = mock.MagicMock() @@ -1105,7 +1106,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.assertRaises(exceptions.ProjectBusyException, self.repos.check_quota_met, self.session, mock_session, - models.LoadBalancer, project_id) + data_models.LoadBalancer, project_id) # ### Test load balancer quota # Test with no pre-existing quota record default 0 @@ -1113,7 +1114,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_load_balancer_quota=0) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertIsNone(self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -1123,14 +1124,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_load_balancer_quota=1) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -1141,14 +1142,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): default_load_balancer_quota=constants.QUOTA_UNLIMITED) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) # Test above project adding another load balancer self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -1156,7 +1157,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): # Test upgrade case with pre-quota load balancers project_id = uuidutils.generate_uuid() conf.config(group='quotas', default_load_balancer_quota=1) - lb = self.repos.load_balancer.create( + self.repos.load_balancer.create( self.session, id=uuidutils.generate_uuid(), project_id=project_id, name="lb_name", description="lb_description", @@ -1165,13 +1166,13 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): enabled=True) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) # Test upgrade case with pre-quota deleted load balancers project_id = uuidutils.generate_uuid() conf.config(group='quotas', default_load_balancer_quota=1) - lb = self.repos.load_balancer.create( + self.repos.load_balancer.create( self.session, id=uuidutils.generate_uuid(), project_id=project_id, name="lb_name", description="lb_description", @@ -1180,7 +1181,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): enabled=True) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -1192,7 +1193,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) # Test pre-existing quota with quota of one @@ -1202,14 +1203,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -1221,14 +1222,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) # Test above project adding another load balancer self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -1239,7 +1240,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_listener_quota=0) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertIsNone(self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -1249,14 +1250,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_listener_quota=1) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -1267,14 +1268,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): default_listener_quota=constants.QUOTA_UNLIMITED) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) # Test above project adding another listener self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -1296,7 +1297,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): load_balancer_id=lb.id) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) # Test upgrade case with pre-quota deleted listener @@ -1316,7 +1317,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): load_balancer_id=lb.id) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -1328,7 +1329,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) # Test pre-existing quota with quota of one @@ -1338,14 +1339,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -1357,14 +1358,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) # Test above project adding another listener self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Listener, + data_models.Listener, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -1375,7 +1376,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_pool_quota=0) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertIsNone(self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -1385,14 +1386,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_pool_quota=1) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -1403,14 +1404,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): default_pool_quota=constants.QUOTA_UNLIMITED) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) # Test above project adding another pool self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -1425,7 +1426,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): provisioning_status=constants.ACTIVE, operating_status=constants.ONLINE, enabled=True) - pool = self.repos.pool.create( + self.repos.pool.create( self.session, id=uuidutils.generate_uuid(), project_id=project_id, name="pool1", protocol=constants.PROTOCOL_HTTP, @@ -1435,7 +1436,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): enabled=True, load_balancer_id=lb.id) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) # Test upgrade case with pre-quota deleted pool @@ -1448,7 +1449,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): provisioning_status=constants.ACTIVE, operating_status=constants.ONLINE, enabled=True) - pool = self.repos.pool.create( + self.repos.pool.create( self.session, id=uuidutils.generate_uuid(), project_id=project_id, name="pool1", protocol=constants.PROTOCOL_HTTP, @@ -1458,7 +1459,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): enabled=True, load_balancer_id=lb.id) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -1470,7 +1471,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) # Test pre-existing quota with quota of one @@ -1480,14 +1481,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -1499,14 +1500,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) # Test above project adding another pool self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Pool, + data_models.Pool, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -1517,7 +1518,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_health_monitor_quota=0) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertIsNone(self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -1527,14 +1528,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_health_monitor_quota=1) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -1545,14 +1546,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): default_health_monitor_quota=constants.QUOTA_UNLIMITED) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) # Test above project adding another health monitor self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -1584,7 +1585,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): enabled=True, pool_id=pool.id) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) # Test upgrade case with pre-quota deleted health monitor @@ -1614,7 +1615,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): enabled=True, pool_id=pool.id) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -1626,7 +1627,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) # Test pre-existing quota with quota of one @@ -1636,14 +1637,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -1655,14 +1656,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) # Test above project adding another health monitor self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -1673,7 +1674,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_member_quota=0) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertIsNone(self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -1683,14 +1684,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_member_quota=1) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -1701,14 +1702,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): default_member_quota=constants.QUOTA_UNLIMITED) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) # Test above project adding another member self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -1739,7 +1740,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): enabled=True, pool_id=pool.id, backup=False) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) # Test upgrade case with pre-quota deleted member @@ -1768,7 +1769,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): enabled=True, pool_id=pool.id, backup=False) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -1780,7 +1781,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) # Test pre-existing quota with quota of one @@ -1790,14 +1791,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -1809,14 +1810,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) # Test above project adding another member self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.Member, + data_models.Member, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -1827,7 +1828,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_l7policy_quota=0) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertIsNone(self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -1837,14 +1838,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_l7policy_quota=1) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -1855,14 +1856,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): default_l7policy_quota=constants.QUOTA_UNLIMITED) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) # Test above project adding another l7policy self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -1890,7 +1891,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): id=uuidutils.generate_uuid()) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) # Test upgrade case with pre-quota deleted l7policy @@ -1916,7 +1917,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): id=uuidutils.generate_uuid()) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -1928,7 +1929,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) # Test pre-existing quota with quota of one @@ -1938,14 +1939,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -1957,14 +1958,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) # Test above project adding another l7policy self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Policy, + data_models.L7Policy, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -1975,7 +1976,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_l7rule_quota=0) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertIsNone(self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -1985,14 +1986,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf.config(group='quotas', default_l7rule_quota=1) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2003,14 +2004,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): default_l7rule_quota=constants.QUOTA_UNLIMITED) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) # Test above project adding another l7rule self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2044,7 +2045,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): operating_status=constants.ONLINE, project_id=project_id) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) # Test upgrade case with pre-quota deleted l7rule @@ -2076,7 +2077,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): operating_status=constants.ONLINE, project_id=project_id) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2088,7 +2089,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) # Test pre-existing quota with quota of one @@ -2098,14 +2099,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) # Test above project is now at quota self.assertTrue(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2117,14 +2118,14 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.repos.quotas.update(self.session, project_id, quota=quota) self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(1, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) # Test above project adding another l7rule self.assertFalse(self.repos.check_quota_met(self.session, self.session, - models.L7Rule, + data_models.L7Rule, project_id)) self.assertEqual(2, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2135,7 +2136,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): conf = self.useFixture(oslo_fixture.Config(cfg.CONF)) conf.config(group='api_settings', auth_strategy=constants.NOAUTH) self.repos.decrement_quota(self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id) self.assertEqual(0, self.repos.quotas.count(self.session, project_id=project_id)) @@ -2144,7 +2145,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): # Test decrement on non-existent quota project_id = uuidutils.generate_uuid() self.repos.decrement_quota(self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id) self.assertEqual(0, self.repos.quotas.count(self.session, project_id=project_id)) @@ -2157,7 +2158,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): self.assertRaises(exceptions.ProjectBusyException, self.repos.decrement_quota, mock_session, - models.LoadBalancer, project_id) + data_models.LoadBalancer, project_id) # ### Test load balancer quota # Test decrement on zero in use quota @@ -2165,7 +2166,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_load_balancer': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -2177,7 +2178,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_load_balancer': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -2188,7 +2189,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_load_balancer': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -2200,7 +2201,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_load_balancer': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.LoadBalancer, + data_models.LoadBalancer, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_load_balancer) @@ -2212,7 +2213,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_listener': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Listener, + data_models.Listener, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -2224,7 +2225,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_listener': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Listener, + data_models.Listener, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -2235,7 +2236,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_listener': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Listener, + data_models.Listener, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -2247,7 +2248,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_listener': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Listener, + data_models.Listener, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_listener) @@ -2259,7 +2260,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_pool': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Pool, + data_models.Pool, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -2271,7 +2272,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_pool': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Pool, + data_models.Pool, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -2282,7 +2283,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_pool': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Pool, + data_models.Pool, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -2294,7 +2295,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_pool': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Pool, + data_models.Pool, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_pool) @@ -2306,7 +2307,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_health_monitor': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -2318,7 +2319,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_health_monitor': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -2329,7 +2330,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_health_monitor': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -2341,7 +2342,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_health_monitor': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.HealthMonitor, + data_models.HealthMonitor, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_health_monitor) @@ -2353,7 +2354,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_member': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Member, + data_models.Member, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -2365,7 +2366,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_member': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Member, + data_models.Member, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -2376,7 +2377,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_member': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Member, + data_models.Member, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -2388,7 +2389,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_member': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.Member, + data_models.Member, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_member) @@ -2399,7 +2400,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_l7policy': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.L7Policy, + data_models.L7Policy, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -2411,7 +2412,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_l7policy': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.L7Policy, + data_models.L7Policy, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -2422,7 +2423,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_l7policy': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.L7Policy, + data_models.L7Policy, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -2434,7 +2435,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_l7policy': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.L7Policy, + data_models.L7Policy, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7policy) @@ -2446,7 +2447,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_l7rule': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.L7Rule, + data_models.L7Rule, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2458,7 +2459,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_l7rule': 0} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.L7Rule, + data_models.L7Rule, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2469,7 +2470,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_l7rule': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.L7Rule, + data_models.L7Rule, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2481,7 +2482,7 @@ class AllRepositoriesTest(base.OctaviaDBTestBase): quota = {'in_use_l7rule': 1} self.repos.quotas.update(self.session, project_id, quota=quota) self.repos.decrement_quota(self.session, - models.L7Rule, + data_models.L7Rule, project_id) self.assertEqual(0, self.repos.quotas.get( self.session, project_id=project_id).in_use_l7rule) @@ -2537,7 +2538,7 @@ class PoolRepositoryTest(BaseRepositoryTest): pool = self.create_pool(pool_id=self.FAKE_UUID_1, project_id=self.FAKE_UUID_2) new_pool = self.pool_repo.get(self.session, id=pool.id) - self.assertIsInstance(new_pool, models.Pool) + self.assertIsInstance(new_pool, data_models.Pool) self.assertEqual(pool, new_pool) def test_get_all(self): @@ -2555,7 +2556,7 @@ class PoolRepositoryTest(BaseRepositoryTest): def test_create(self): pool = self.create_pool(pool_id=self.FAKE_UUID_1, project_id=self.FAKE_UUID_2) - self.assertIsInstance(pool, models.Pool) + self.assertIsInstance(pool, data_models.Pool) self.assertEqual(self.FAKE_UUID_2, pool.project_id) self.assertEqual("pool_test", pool.name) self.assertEqual("pool_description", pool.description) @@ -2689,7 +2690,7 @@ class MemberRepositoryTest(BaseRepositoryTest): member = self.create_member(self.FAKE_UUID_1, self.FAKE_UUID_2, self.pool.id, "192.0.2.1") new_member = self.member_repo.get(self.session, id=member.id) - self.assertIsInstance(new_member, models.Member) + self.assertIsInstance(new_member, data_models.Member) self.assertEqual(member, new_member) def test_get_all(self): @@ -2771,7 +2772,7 @@ class SessionPersistenceRepositoryTest(BaseRepositoryTest): def test_get(self): sp = self.create_session_persistence(self.pool.id) new_sp = self.sp_repo.get(self.session, pool_id=sp.pool_id) - self.assertIsInstance(new_sp, models.SessionPersistence) + self.assertIsInstance(new_sp, data_models.SessionPersistence) self.assertEqual(sp, new_sp) def test_create(self): @@ -2844,7 +2845,7 @@ class TestListenerRepositoryTest(BaseRepositoryTest): def test_get(self): listener = self.create_listener(self.FAKE_UUID_1, 80) new_listener = self.listener_repo.get(self.session, id=listener.id) - self.assertIsInstance(new_listener, models.Listener) + self.assertIsInstance(new_listener, data_models.Listener) self.assertEqual(listener, new_listener) def test_get_all(self): @@ -2925,8 +2926,8 @@ class TestListenerRepositoryTest(BaseRepositoryTest): 'tls_container_id': self.FAKE_UUID_1} container2 = {'listener_id': listener.id, 'tls_container_id': self.FAKE_UUID_2} - container1_dm = models.SNI(**container1) - container2_dm = models.SNI(**container2) + container1_dm = data_models.SNI(**container1) + container2_dm = data_models.SNI(**container2) self.sni_repo.create(self.session, **container1) self.sni_repo.create(self.session, **container2) new_listener = self.listener_repo.get(self.session, id=listener.id) @@ -2945,7 +2946,7 @@ class TestListenerRepositoryTest(BaseRepositoryTest): listener = self.create_listener(self.FAKE_UUID_1, 80) container1 = {'listener_id': listener.id, 'tls_container_id': self.FAKE_UUID_2} - container1_dm = models.SNI(**container1) + container1_dm = data_models.SNI(**container1) self.listener_repo.update(self.session, listener.id, sni_containers=[self.FAKE_UUID_2]) new_listener = self.listener_repo.get(self.session, id=listener.id) @@ -3129,7 +3130,7 @@ class ListenerStatisticsRepositoryTest(BaseRepositoryTest): stats = self.create_listener_stats(self.listener.id, self.amphora.id) new_stats = self.listener_stats_repo.get(self.session, listener_id=stats.listener_id) - self.assertIsInstance(new_stats, models.ListenerStatistics) + self.assertIsInstance(new_stats, data_models.ListenerStatistics) self.assertEqual(stats.listener_id, new_stats.listener_id) def test_create(self): @@ -3150,7 +3151,7 @@ class ListenerStatisticsRepositoryTest(BaseRepositoryTest): bytes_in=bytes_in_change) new_stats = self.listener_stats_repo.get(self.session, listener_id=stats.listener_id) - self.assertIsInstance(new_stats, models.ListenerStatistics) + self.assertIsInstance(new_stats, data_models.ListenerStatistics) self.assertEqual(stats.listener_id, new_stats.listener_id) def test_delete(self): @@ -3213,6 +3214,61 @@ class ListenerStatisticsRepositoryTest(BaseRepositoryTest): self.assertEqual(total_conns_2, obj.total_connections) self.assertEqual(request_errors_2, obj.request_errors) + def test_increment(self): + # Test the create path + bytes_in = random.randrange(1000000000) + bytes_out = random.randrange(1000000000) + active_conns = random.randrange(1000000000) + total_conns = random.randrange(1000000000) + request_errors = random.randrange(1000000000) + self.assertIsNone(self.listener_stats_repo.get( + self.session, listener_id=self.listener.id)) + delta_stats = data_models.ListenerStatistics( + listener_id=self.listener.id, + amphora_id=self.amphora.id, + bytes_in=bytes_in, + bytes_out=bytes_out, + active_connections=active_conns, + total_connections=total_conns, + request_errors=request_errors + ) + self.listener_stats_repo.increment(self.session, delta_stats) + obj = self.listener_stats_repo.get(self.session, + listener_id=self.listener.id) + self.assertIsNotNone(obj) + self.assertEqual(self.listener.id, obj.listener_id) + self.assertEqual(bytes_in, obj.bytes_in) + self.assertEqual(bytes_out, obj.bytes_out) + self.assertEqual(active_conns, obj.active_connections) + self.assertEqual(total_conns, obj.total_connections) + self.assertEqual(request_errors, obj.request_errors) + + # Test the update path + bytes_in_2 = random.randrange(1000000000) + bytes_out_2 = random.randrange(1000000000) + active_conns_2 = random.randrange(1000000000) + total_conns_2 = random.randrange(1000000000) + request_errors_2 = random.randrange(1000000000) + delta_stats_2 = data_models.ListenerStatistics( + listener_id=self.listener.id, + amphora_id=self.amphora.id, + bytes_in=bytes_in_2, + bytes_out=bytes_out_2, + active_connections=active_conns_2, + total_connections=total_conns_2, + request_errors=request_errors_2 + ) + self.listener_stats_repo.increment(self.session, delta_stats_2) + obj = self.listener_stats_repo.get(self.session, + listener_id=self.listener.id) + self.assertIsNotNone(obj) + self.assertEqual(self.listener.id, obj.listener_id) + self.assertEqual(bytes_in + bytes_in_2, obj.bytes_in) + self.assertEqual(bytes_out + bytes_out_2, obj.bytes_out) + self.assertEqual(active_conns_2, obj.active_connections) # not a delta + self.assertEqual(total_conns + total_conns_2, obj.total_connections) + self.assertEqual(request_errors + request_errors_2, obj.request_errors) + class HealthMonitorRepositoryTest(BaseRepositoryTest): @@ -3248,7 +3304,7 @@ class HealthMonitorRepositoryTest(BaseRepositoryTest): def test_get(self): hm = self.create_health_monitor(self.FAKE_UUID_3, self.pool.id) new_hm = self.hm_repo.get(self.session, id=hm.id) - self.assertIsInstance(new_hm, models.HealthMonitor) + self.assertIsInstance(new_hm, data_models.HealthMonitor) self.assertEqual(hm, new_hm) def test_create(self): @@ -3300,7 +3356,7 @@ class LoadBalancerRepositoryTest(BaseRepositoryTest): def test_get(self): lb = self.create_loadbalancer(self.FAKE_UUID_1) new_lb = self.lb_repo.get(self.session, id=lb.id) - self.assertIsInstance(new_lb, models.LoadBalancer) + self.assertIsInstance(new_lb, data_models.LoadBalancer) self.assertEqual(lb, new_lb) def test_get_all(self): @@ -3597,7 +3653,7 @@ class VipRepositoryTest(BaseRepositoryTest): vip = self.create_vip(self.lb.id) new_vip = self.vip_repo.get(self.session, load_balancer_id=vip.load_balancer_id) - self.assertIsInstance(new_vip, models.Vip) + self.assertIsInstance(new_vip, data_models.Vip) self.assertEqual(vip, new_vip) def test_create(self): @@ -3663,7 +3719,7 @@ class SNIRepositoryTest(BaseRepositoryTest): def test_get(self): sni = self.create_sni(self.listener.id) new_sni = self.sni_repo.get(self.session, listener_id=sni.listener_id) - self.assertIsInstance(new_sni, models.SNI) + self.assertIsInstance(new_sni, data_models.SNI) self.assertEqual(sni, new_sni) def test_create(self): @@ -3721,7 +3777,7 @@ class AmphoraRepositoryTest(BaseRepositoryTest): def test_get(self): amphora = self.create_amphora(self.FAKE_UUID_1) new_amphora = self.amphora_repo.get(self.session, id=amphora.id) - self.assertIsInstance(new_amphora, models.Amphora) + self.assertIsInstance(new_amphora, data_models.Amphora) self.assertEqual(amphora, new_amphora) def test_count(self): @@ -3777,7 +3833,8 @@ class AmphoraRepositoryTest(BaseRepositoryTest): new_amphora = self.amphora_repo.get(self.session, id=amphora.id) self.assertIsNotNone(new_amphora.load_balancer) - self.assertIsInstance(new_amphora.load_balancer, models.LoadBalancer) + self.assertIsInstance(new_amphora.load_balancer, + data_models.LoadBalancer) def test_delete_amphora_with_load_balancer(self): amphora = self.create_amphora(self.FAKE_UUID_1) @@ -3798,7 +3855,7 @@ class AmphoraRepositoryTest(BaseRepositoryTest): new_amphora = self.amphora_repo.allocate_and_associate(self.session, self.lb.id) self.assertIsNotNone(new_amphora) - self.assertIsInstance(new_amphora, models.Amphora) + self.assertIsInstance(new_amphora, data_models.Amphora) def test_get_lb_for_amphora(self): # TODO(bzhao) this test will raise error as there are more than 64 @@ -4009,7 +4066,7 @@ class AmphoraHealthRepositoryTest(BaseRepositoryTest): new_amphora_health = self.amphora_health_repo.get( self.session, amphora_id=amphora_health.amphora_id) - self.assertIsInstance(new_amphora_health, models.AmphoraHealth) + self.assertIsInstance(new_amphora_health, data_models.AmphoraHealth) self.assertEqual(amphora_health, new_amphora_health) def test_check_amphora_expired_default_exp_age(self): @@ -4174,7 +4231,7 @@ class L7PolicyRepositoryTest(BaseRepositoryTest): listener.id, 999, redirect_pool_id=pool.id) new_l7policy = self.l7policy_repo.get(self.session, id=l7policy.id) - self.assertIsInstance(new_l7policy, models.L7Policy) + self.assertIsInstance(new_l7policy, data_models.L7Policy) self.assertEqual(l7policy, new_l7policy) self.assertEqual(1, new_l7policy.position) @@ -4560,7 +4617,7 @@ class L7RuleRepositoryTest(BaseRepositoryTest): l7rule = self.create_l7rule(uuidutils.generate_uuid(), self.l7policy.id) new_l7rule = self.l7rule_repo.get(self.session, id=l7rule.id) - self.assertIsInstance(new_l7rule, models.L7Rule) + self.assertIsInstance(new_l7rule, data_models.L7Rule) self.assertEqual(l7rule, new_l7rule) def test_get_all(self): @@ -4936,7 +4993,7 @@ class TestQuotasRepository(BaseRepositoryTest): expected = self.update_quotas(self.FAKE_UUID_1) observed = self.quota_repo.get(self.session, project_id=self.FAKE_UUID_1) - self.assertIsInstance(observed, models.Quotas) + self.assertIsInstance(observed, data_models.Quotas) self._compare(expected, observed) def test_update(self): @@ -4946,9 +5003,9 @@ class TestQuotasRepository(BaseRepositoryTest): second_expected = self.update_quotas(self.FAKE_UUID_1, load_balancer=1) second_observed = self.quota_repo.get(self.session, project_id=self.FAKE_UUID_1) - self.assertIsInstance(first_expected, models.Quotas) + self.assertIsInstance(first_expected, data_models.Quotas) self._compare(first_expected, first_observed) - self.assertIsInstance(second_expected, models.Quotas) + self.assertIsInstance(second_expected, data_models.Quotas) self._compare(second_expected, second_observed) self.assertIsNot(first_expected.load_balancer, second_expected.load_balancer) @@ -4957,7 +5014,7 @@ class TestQuotasRepository(BaseRepositoryTest): expected = self.update_quotas(self.FAKE_UUID_1) observed = self.quota_repo.get(self.session, project_id=self.FAKE_UUID_1) - self.assertIsInstance(observed, models.Quotas) + self.assertIsInstance(observed, data_models.Quotas) self._compare(expected, observed) self.quota_repo.delete(self.session, self.FAKE_UUID_1) observed = self.quota_repo.get(self.session, @@ -4987,7 +5044,7 @@ class FlavorProfileRepositoryTest(BaseRepositoryTest): def test_get(self): fp = self.create_flavor_profile(fp_id=self.FAKE_UUID_1) new_fp = self.flavor_profile_repo.get(self.session, id=fp.id) - self.assertIsInstance(new_fp, models.FlavorProfile) + self.assertIsInstance(new_fp, data_models.FlavorProfile) self.assertEqual(fp, new_fp) def test_get_all(self): @@ -5002,7 +5059,7 @@ class FlavorProfileRepositoryTest(BaseRepositoryTest): def test_create(self): fp = self.create_flavor_profile(fp_id=self.FAKE_UUID_1) - self.assertIsInstance(fp, models.FlavorProfile) + self.assertIsInstance(fp, data_models.FlavorProfile) self.assertEqual(self.FAKE_UUID_1, fp.id) self.assertEqual("fp1", fp.name) @@ -5035,7 +5092,7 @@ class FlavorRepositoryTest(BaseRepositoryTest): def test_get(self): flavor = self.create_flavor(flavor_id=self.FAKE_UUID_2, name='flavor') new_flavor = self.flavor_repo.get(self.session, id=flavor.id) - self.assertIsInstance(new_flavor, models.Flavor) + self.assertIsInstance(new_flavor, data_models.Flavor) self.assertEqual(flavor, new_flavor) def test_get_all(self): @@ -5050,7 +5107,7 @@ class FlavorRepositoryTest(BaseRepositoryTest): def test_create(self): fl = self.create_flavor(flavor_id=self.FAKE_UUID_2, name='fl1') - self.assertIsInstance(fl, models.Flavor) + self.assertIsInstance(fl, data_models.Flavor) self.assertEqual(self.FAKE_UUID_2, fl.id) self.assertEqual("fl1", fl.name) diff --git a/octavia/tests/unit/amphorae/backends/health_daemon/test_health_daemon.py b/octavia/tests/unit/amphorae/backends/health_daemon/test_health_daemon.py index 3981890f7a..34824ecd75 100644 --- a/octavia/tests/unit/amphorae/backends/health_daemon/test_health_daemon.py +++ b/octavia/tests/unit/amphorae/backends/health_daemon/test_health_daemon.py @@ -12,21 +12,26 @@ # License for the specific language governing permissions and limitations # under the License. # +import os import queue from unittest import mock from oslo_config import cfg from oslo_config import fixture as oslo_fixture from oslo_utils import uuidutils +import simplejson from octavia.amphorae.backends.health_daemon import health_daemon from octavia.common import constants +from octavia.tests.common import utils as test_utils import octavia.tests.unit.base as base +LB_ID1 = uuidutils.generate_uuid() LISTENER_ID1 = uuidutils.generate_uuid() LISTENER_ID2 = uuidutils.generate_uuid() LISTENER_IDS = [LISTENER_ID1, LISTENER_ID2] +AMPHORA_ID = uuidutils.generate_uuid() BASE_PATH = '/tmp/test' SAMPLE_POOL_STATUS = { '432fc8b3-d446-48d4-bb64-13beb90e22bc': { @@ -45,46 +50,46 @@ SAMPLE_BOGUS_POOL_STATUS = {LISTENER_ID1: { '302e33d9-dee1-4de9-98d5-36329a06fb58': 'DOWN'}}} -SAMPLE_STATS = ({'': '', 'status': 'OPEN', 'lastchg': '', - 'weight': '', 'slim': '2000', 'pid': '1', 'comp_byp': '0', - 'lastsess': '', 'rate_lim': '0', 'check_duration': '', - 'rate': '0', 'req_rate': '0', 'check_status': '', - 'econ': '', 'comp_out': '0', 'wredis': '', 'dresp': '0', - 'ereq': '0', 'tracked': '', 'comp_in': '0', - 'pxname': LISTENER_ID1, - 'dreq': '0', 'hrsp_5xx': '0', 'last_chk': '', - 'check_code': '', 'sid': '0', 'bout': '0', 'hrsp_1xx': '0', - 'qlimit': '', 'hrsp_other': '0', 'bin': '0', 'rtime': '', - 'smax': '0', 'req_tot': '0', 'lbtot': '', 'stot': '0', - 'wretr': '', 'req_rate_max': '0', 'ttime': '', 'iid': '2', - 'hrsp_4xx': '0', 'chkfail': '', 'hanafail': '', - 'downtime': '', 'qcur': '', 'eresp': '', 'comp_rsp': '0', - 'cli_abrt': '', 'ctime': '', 'qtime': '', 'srv_abrt': '', - 'throttle': '', 'last_agt': '', 'scur': '0', 'type': '0', - 'bck': '', 'qmax': '', 'rate_max': '0', 'hrsp_2xx': '0', - 'act': '', 'chkdown': '', 'svname': 'FRONTEND', - 'hrsp_3xx': '0'}, - {'': '', 'status': 'no check', 'lastchg': '', 'weight': '1', - 'slim': '', 'pid': '1', 'comp_byp': '', 'lastsess': '-1', - 'rate_lim': '', 'check_duration': '', 'rate': '0', - 'req_rate': '', 'check_status': '', 'econ': '0', - 'comp_out': '', 'wredis': '0', 'dresp': '0', 'ereq': '', - 'tracked': '', 'comp_in': '', - 'pxname': '432fc8b3-d446-48d4-bb64-13beb90e22bc', - 'dreq': '', 'hrsp_5xx': '0', 'last_chk': '', - 'check_code': '', 'sid': '1', 'bout': '0', 'hrsp_1xx': '0', - 'qlimit': '', 'hrsp_other': '0', 'bin': '0', 'rtime': '0', - 'smax': '0', 'req_tot': '', 'lbtot': '0', 'stot': '0', - 'wretr': '0', 'req_rate_max': '', 'ttime': '0', 'iid': '3', - 'hrsp_4xx': '0', 'chkfail': '', 'hanafail': '0', - 'downtime': '', 'qcur': '0', 'eresp': '0', 'comp_rsp': '', - 'cli_abrt': '0', 'ctime': '0', 'qtime': '0', 'srv_abrt': '0', - 'throttle': '', 'last_agt': '', 'scur': '0', 'type': '2', - 'bck': '0', 'qmax': '0', 'rate_max': '0', 'hrsp_2xx': '0', - 'act': '1', 'chkdown': '', - 'svname': '302e33d9-dee1-4de9-98d5-36329a06fb58', - 'hrsp_3xx': '0'}, - {'': '', 'status': 'UP', 'lastchg': '122', 'weight': '1', +FRONTEND_STATS = {'': '', 'status': 'OPEN', 'lastchg': '', + 'weight': '', 'slim': '2000', 'pid': '1', 'comp_byp': '0', + 'lastsess': '', 'rate_lim': '0', 'check_duration': '', + 'rate': '0', 'req_rate': '0', 'check_status': '', + 'econ': '', 'comp_out': '0', 'wredis': '', 'dresp': '0', + 'ereq': '5', 'tracked': '', 'comp_in': '0', + 'pxname': LISTENER_ID1, + 'dreq': '0', 'hrsp_5xx': '0', 'last_chk': '', + 'check_code': '', 'sid': '0', 'bout': '10', 'hrsp_1xx': '0', + 'qlimit': '', 'hrsp_other': '0', 'bin': '5', 'rtime': '', + 'smax': '0', 'req_tot': '0', 'lbtot': '', 'stot': '0', + 'wretr': '', 'req_rate_max': '0', 'ttime': '', 'iid': '2', + 'hrsp_4xx': '0', 'chkfail': '', 'hanafail': '', + 'downtime': '', 'qcur': '', 'eresp': '', 'comp_rsp': '0', + 'cli_abrt': '', 'ctime': '', 'qtime': '', 'srv_abrt': '', + 'throttle': '', 'last_agt': '', 'scur': '0', 'type': '0', + 'bck': '', 'qmax': '', 'rate_max': '0', 'hrsp_2xx': '0', + 'act': '', 'chkdown': '', 'svname': 'FRONTEND', + 'hrsp_3xx': '0'} +MEMBER_STATS = {'': '', 'status': 'no check', 'lastchg': '', 'weight': '1', + 'slim': '', 'pid': '1', 'comp_byp': '', 'lastsess': '-1', + 'rate_lim': '', 'check_duration': '', 'rate': '0', + 'req_rate': '', 'check_status': '', 'econ': '0', + 'comp_out': '', 'wredis': '0', 'dresp': '0', 'ereq': '', + 'tracked': '', 'comp_in': '', + 'pxname': '432fc8b3-d446-48d4-bb64-13beb90e22bc', + 'dreq': '', 'hrsp_5xx': '0', 'last_chk': '', + 'check_code': '', 'sid': '1', 'bout': '0', 'hrsp_1xx': '0', + 'qlimit': '', 'hrsp_other': '0', 'bin': '0', 'rtime': '0', + 'smax': '0', 'req_tot': '', 'lbtot': '0', 'stot': '0', + 'wretr': '0', 'req_rate_max': '', 'ttime': '0', 'iid': '3', + 'hrsp_4xx': '0', 'chkfail': '', 'hanafail': '0', + 'downtime': '', 'qcur': '0', 'eresp': '0', 'comp_rsp': '', + 'cli_abrt': '0', 'ctime': '0', 'qtime': '0', 'srv_abrt': '0', + 'throttle': '', 'last_agt': '', 'scur': '0', 'type': '2', + 'bck': '0', 'qmax': '0', 'rate_max': '0', 'hrsp_2xx': '0', + 'act': '1', 'chkdown': '', + 'svname': '302e33d9-dee1-4de9-98d5-36329a06fb58', + 'hrsp_3xx': '0'} +BACKEND_STATS = {'': '', 'status': 'UP', 'lastchg': '122', 'weight': '1', 'slim': '200', 'pid': '1', 'comp_byp': '0', 'lastsess': '-1', 'rate_lim': '', 'check_duration': '', 'rate': '0', 'req_rate': '', 'check_status': '', 'econ': '0', @@ -101,14 +106,15 @@ SAMPLE_STATS = ({'': '', 'status': 'OPEN', 'lastchg': '', 'srv_abrt': '0', 'throttle': '', 'last_agt': '', 'scur': '0', 'type': '1', 'bck': '0', 'qmax': '0', 'rate_max': '0', 'hrsp_2xx': '0', 'act': '1', 'chkdown': '0', - 'svname': 'BACKEND', 'hrsp_3xx': '0'}) + 'svname': 'BACKEND', 'hrsp_3xx': '0'} +SAMPLE_STATS = (FRONTEND_STATS, MEMBER_STATS, BACKEND_STATS) SAMPLE_STATS_MSG = { 'listeners': { LISTENER_ID1: { 'stats': { 'totconns': 0, 'conns': 0, - 'tx': 0, 'rx': 0, 'ereq': 0}, + 'tx': 8, 'rx': 4, 'ereq': 5}, 'status': 'OPEN'}, }, 'pools': { @@ -119,8 +125,29 @@ SAMPLE_STATS_MSG = { 'members': {'e657f950-a6a2-4d28-bffa-0c8a8c05f815': 'DOWN'}, 'status': 'UP'}, }, - 'id': None, - 'seq': 0, + 'id': AMPHORA_ID, + 'seq': mock.ANY, + 'ver': health_daemon.MSG_VER +} + +SAMPLE_MSG_HAPROXY_RESTART = { + 'listeners': { + LISTENER_ID1: { + 'stats': { + 'totconns': 0, 'conns': 0, + 'tx': 10, 'rx': 5, 'ereq': 5}, + 'status': 'OPEN'}, + }, + 'pools': { + '432fc8b3-d446-48d4-bb64-13beb90e22bc': { + 'members': {'302e33d9-dee1-4de9-98d5-36329a06fb58': 'DOWN'}, + 'status': 'UP'}, + '3661ed10-99db-4d2c-bffb-99b60eb876ff': { + 'members': {'e657f950-a6a2-4d28-bffa-0c8a8c05f815': 'DOWN'}, + 'status': 'UP'}, + }, + 'id': AMPHORA_ID, + 'seq': mock.ANY, 'ver': health_daemon.MSG_VER } @@ -131,6 +158,10 @@ class TestHealthDaemon(base.TestCase): super(TestHealthDaemon, self).setUp() conf = oslo_fixture.Config(cfg.CONF) conf.config(group="haproxy_amphora", base_path=BASE_PATH) + conf.config(group="amphora_agent", amphora_id=AMPHORA_ID) + file_name = os.path.join(BASE_PATH, "stats_counters") + self.mock_open = self.useFixture( + test_utils.OpenFixture(file_name)).mock_open @mock.patch('octavia.amphorae.backends.agent.' 'api_server.util.get_loadbalancers') @@ -296,18 +327,33 @@ class TestHealthDaemon(base.TestCase): 'health_daemon.list_sock_stat_files') def test_build_stats_message(self, mock_list_files, mock_get_stats, mock_is_running): - mock_list_files.return_value = {LISTENER_ID1: 'TEST', - LISTENER_ID2: 'TEST2'} + health_daemon.COUNTERS = None + health_daemon.COUNTERS_FILE = None + lb1_stats_socket = '/var/lib/octavia/{0}/haproxy.sock'.format(LB_ID1) + mock_list_files.return_value = {LB_ID1: lb1_stats_socket} mock_is_running.return_value = True mock_get_stats.return_value = SAMPLE_STATS, SAMPLE_POOL_STATUS - msg = health_daemon.build_stats_message() + with mock.patch('os.open'), mock.patch.object( + os, 'fdopen', self.mock_open) as mock_fdopen: + mock_fdopen().read.return_value = simplejson.dumps({ + LISTENER_ID1: {'bin': 1, 'bout': 2}, + }) + msg = health_daemon.build_stats_message() self.assertEqual(SAMPLE_STATS_MSG, msg) - mock_get_stats.assert_any_call('TEST') - mock_get_stats.assert_any_call('TEST2') + mock_get_stats.assert_any_call(lb1_stats_socket) + mock_fdopen().write.assert_called_once_with(simplejson.dumps({ + LISTENER_ID1: { + 'bin': int(FRONTEND_STATS['bin']), + 'bout': int(FRONTEND_STATS['bout']), + 'ereq': int(FRONTEND_STATS['ereq']), + 'stot': int(FRONTEND_STATS['stot']) + + } + })) @mock.patch('octavia.amphorae.backends.agent.api_server.' 'util.is_lb_running') @@ -318,15 +364,19 @@ class TestHealthDaemon(base.TestCase): def test_build_stats_message_no_listener(self, mock_list_files, mock_get_stats, mock_is_running): - mock_list_files.return_value = {LISTENER_ID1: 'TEST', - LISTENER_ID2: 'TEST2'} + health_daemon.COUNTERS = None + health_daemon.COUNTERS_FILE = None + lb1_stats_socket = '/var/lib/octavia/{0}/haproxy.sock'.format(LB_ID1) + mock_list_files.return_value = {LB_ID1: lb1_stats_socket} - mock_is_running.side_effect = [True, False] - mock_get_stats.return_value = SAMPLE_STATS, SAMPLE_POOL_STATUS + mock_is_running.return_value = False - health_daemon.build_stats_message() + with mock.patch('os.open'), mock.patch.object( + os, 'fdopen', self.mock_open) as mock_fdopen: + health_daemon.build_stats_message() - self.assertEqual(1, mock_get_stats.call_count) + self.assertEqual(0, mock_get_stats.call_count) + self.assertEqual(0, mock_fdopen().read.call_count) @mock.patch("octavia.amphorae.backends.utils.keepalivedlvs_query." "get_udp_listener_pool_status") @@ -335,8 +385,10 @@ class TestHealthDaemon(base.TestCase): @mock.patch("octavia.amphorae.backends.agent.api_server.util." "get_udp_listeners") def test_build_stats_message_with_udp_listener( - self, mock_get_udp_listeners, mock_get_listener_stats, - mock_get_pool_status): + self, mock_get_udp_listeners, + mock_get_listener_stats, mock_get_pool_status): + health_daemon.COUNTERS = None + health_daemon.COUNTERS_FILE = None udp_listener_id1 = uuidutils.generate_uuid() udp_listener_id2 = uuidutils.generate_uuid() udp_listener_id3 = uuidutils.generate_uuid() @@ -346,10 +398,11 @@ class TestHealthDaemon(base.TestCase): mock_get_udp_listeners.return_value = [udp_listener_id1, udp_listener_id2, udp_listener_id3] + mock_get_listener_stats.return_value = { udp_listener_id1: { 'status': constants.OPEN, - 'stats': {'bin': 6387472, 'stot': 5, 'bout': 7490, + 'stats': {'bin': 5, 'stot': 5, 'bout': 10, 'ereq': 0, 'scur': 0}}, udp_listener_id3: { 'status': constants.DOWN, @@ -373,7 +426,7 @@ class TestHealthDaemon(base.TestCase): udp_listener_id1: { 'status': constants.OPEN, 'stats': {'conns': 0, 'totconns': 5, 'ereq': 0, - 'rx': 6387472, 'tx': 7490}}, + 'rx': 4, 'tx': 8}}, udp_listener_id3: { 'status': constants.DOWN, 'stats': {'conns': 0, 'totconns': 0, 'ereq': 0, @@ -384,10 +437,58 @@ class TestHealthDaemon(base.TestCase): 'members': { member_id1: constants.UP, member_id2: constants.UP}}}, - 'id': None, + 'id': AMPHORA_ID, 'seq': mock.ANY, 'ver': health_daemon.MSG_VER} - msg = health_daemon.build_stats_message() + + with mock.patch('os.open'), mock.patch.object( + os, 'fdopen', self.mock_open) as mock_fdopen: + mock_fdopen().read.return_value = simplejson.dumps({ + udp_listener_id1: { + 'bin': 1, 'bout': 2, "ereq": 0, "stot": 0} + }) + msg = health_daemon.build_stats_message() + self.assertEqual(expected, msg) + mock_fdopen().write.assert_called_once_with(simplejson.dumps({ + udp_listener_id1: {'bin': 5, 'bout': 10, 'ereq': 0, 'stot': 5}, + udp_listener_id3: {'bin': 0, 'bout': 0, 'ereq': 0, 'stot': 0}, + })) + + @mock.patch('octavia.amphorae.backends.agent.api_server.' + 'util.is_lb_running') + @mock.patch('octavia.amphorae.backends.health_daemon.' + 'health_daemon.get_stats') + @mock.patch('octavia.amphorae.backends.health_daemon.' + 'health_daemon.list_sock_stat_files') + def test_haproxy_restart(self, mock_list_files, + mock_get_stats, mock_is_running): + health_daemon.COUNTERS = None + health_daemon.COUNTERS_FILE = None + lb1_stats_socket = '/var/lib/octavia/{0}/haproxy.sock'.format(LB_ID1) + mock_list_files.return_value = {LB_ID1: lb1_stats_socket} + + mock_is_running.return_value = True + mock_get_stats.return_value = SAMPLE_STATS, SAMPLE_POOL_STATUS + + with mock.patch('os.open'), mock.patch.object( + os, 'fdopen', self.mock_open) as mock_fdopen: + mock_fdopen().read.return_value = simplejson.dumps({ + LISTENER_ID1: {'bin': 15, 'bout': 20}, + }) + msg = health_daemon.build_stats_message() + + self.assertEqual(SAMPLE_MSG_HAPROXY_RESTART, msg) + + mock_get_stats.assert_any_call(lb1_stats_socket) + mock_fdopen().write.assert_called_once_with(simplejson.dumps({ + LISTENER_ID1: { + 'bin': int(FRONTEND_STATS['bin']), + 'bout': int(FRONTEND_STATS['bout']), + 'ereq': int(FRONTEND_STATS['ereq']), + 'stot': int(FRONTEND_STATS['stot']) + + } + })) class FileNotFoundError(IOError): diff --git a/octavia/tests/unit/common/test_data_models.py b/octavia/tests/unit/common/test_data_models.py index 1700cd9982..20d9551ee3 100644 --- a/octavia/tests/unit/common/test_data_models.py +++ b/octavia/tests/unit/common/test_data_models.py @@ -14,6 +14,7 @@ import copy import datetime +import random from oslo_utils import uuidutils @@ -27,6 +28,7 @@ class TestDataModels(base.TestCase): def setUp(self): self.LB_ID = uuidutils.generate_uuid() + self.LISTENER_ID = uuidutils.generate_uuid() self.PROJECT_ID = uuidutils.generate_uuid() self.SERVER_GROUP_ID = uuidutils.generate_uuid() self.CREATED_AT = datetime.datetime.now() @@ -479,3 +481,55 @@ class TestDataModels(base.TestCase): test_Quota_obj.update(update_dict) self.assertEqual(reference_Quota_obj, test_Quota_obj) + + 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") diff --git a/octavia/tests/unit/controller/healthmanager/health_drivers/test_update_db.py b/octavia/tests/unit/controller/healthmanager/health_drivers/test_update_db.py index 27cef11542..22ce85ab43 100644 --- a/octavia/tests/unit/controller/healthmanager/health_drivers/test_update_db.py +++ b/octavia/tests/unit/controller/healthmanager/health_drivers/test_update_db.py @@ -1385,7 +1385,7 @@ class TestUpdateStatsDb(base.TestCase): self.loadbalancer_repo.get.return_value = self.loadbalancer @mock.patch('octavia.db.api.get_session') - def test_update_stats(self, mock_session): + def test_update_stats_v1(self, mock_session): health = { "id": self.amphora_id, @@ -1422,11 +1422,53 @@ class TestUpdateStatsDb(base.TestCase): total_connections=self.listener_stats.total_connections, request_errors=self.listener_stats.request_errors) - # Test with missing DB listener - self.sm.repo_listener.get.return_value = None + # Test with update failure + mock_session.side_effect = Exception + self.sm.update_stats(health, '192.0.2.1') + + @mock.patch('octavia.db.api.get_session') + def test_update_stats_v3(self, mock_session): + + health = { + "id": self.amphora_id, + "seq": random.randint(0, 100), + "ver": 3, + "listeners": { + self.listener_id: { + "status": constants.OPEN, + "stats": { + "ereq": self.listener_stats.request_errors, + "conns": self.listener_stats.active_connections, + "totconns": self.listener_stats.total_connections, + "rx": self.listener_stats.bytes_in, + "tx": self.listener_stats.bytes_out, + }, + "pools": { + "pool-id-1": { + "status": constants.UP, + "members": {"member-id-1": constants.ONLINE} + } + } + } + } + } + + delta_stats_model = data_models.ListenerStatistics( + listener_id=self.listener_id, + amphora_id=self.amphora_id, + bytes_in=self.listener_stats.bytes_in, + bytes_out=self.listener_stats.bytes_out, + active_connections=self.listener_stats.active_connections, + total_connections=self.listener_stats.total_connections, + request_errors=self.listener_stats.request_errors + ) + mock_session.return_value = 'blah' self.sm.update_stats(health, '192.0.2.1') + self.listener_stats_repo.increment.assert_called_once_with( + 'blah', delta_stats_model) + # Test with update failure mock_session.side_effect = Exception self.sm.update_stats(health, '192.0.2.1')