octavia 12.0.0.0rc2__py3-none-any.whl → 13.0.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- octavia/amphorae/backends/agent/api_server/osutils.py +1 -0
- octavia/amphorae/backends/agent/api_server/plug.py +21 -7
- octavia/amphorae/backends/agent/api_server/templates/amphora-netns.systemd.j2 +2 -2
- octavia/amphorae/backends/agent/api_server/util.py +21 -0
- octavia/amphorae/backends/health_daemon/health_daemon.py +9 -3
- octavia/amphorae/backends/health_daemon/health_sender.py +2 -0
- octavia/amphorae/backends/utils/interface.py +14 -6
- octavia/amphorae/backends/utils/interface_file.py +6 -3
- octavia/amphorae/backends/utils/keepalivedlvs_query.py +8 -9
- octavia/amphorae/drivers/driver_base.py +1 -2
- octavia/amphorae/drivers/haproxy/rest_api_driver.py +11 -25
- octavia/amphorae/drivers/health/heartbeat_udp.py +34 -24
- octavia/amphorae/drivers/keepalived/jinja/jinja_cfg.py +3 -12
- octavia/amphorae/drivers/noop_driver/driver.py +3 -5
- octavia/api/common/pagination.py +4 -4
- octavia/api/drivers/amphora_driver/v2/driver.py +11 -5
- octavia/api/drivers/driver_agent/driver_get.py +22 -14
- octavia/api/drivers/driver_agent/driver_updater.py +8 -4
- octavia/api/drivers/utils.py +4 -2
- octavia/api/healthcheck/healthcheck_plugins.py +4 -2
- octavia/api/root_controller.py +4 -1
- octavia/api/v2/controllers/amphora.py +35 -38
- octavia/api/v2/controllers/availability_zone_profiles.py +43 -33
- octavia/api/v2/controllers/availability_zones.py +22 -18
- octavia/api/v2/controllers/flavor_profiles.py +37 -28
- octavia/api/v2/controllers/flavors.py +19 -15
- octavia/api/v2/controllers/health_monitor.py +44 -33
- octavia/api/v2/controllers/l7policy.py +52 -40
- octavia/api/v2/controllers/l7rule.py +68 -55
- octavia/api/v2/controllers/listener.py +88 -61
- octavia/api/v2/controllers/load_balancer.py +52 -34
- octavia/api/v2/controllers/member.py +63 -52
- octavia/api/v2/controllers/pool.py +55 -42
- octavia/api/v2/controllers/quotas.py +5 -3
- octavia/api/v2/types/listener.py +15 -0
- octavia/cmd/octavia_worker.py +0 -3
- octavia/cmd/status.py +1 -4
- octavia/common/clients.py +25 -45
- octavia/common/config.py +64 -22
- octavia/common/constants.py +3 -2
- octavia/common/data_models.py +7 -1
- octavia/common/jinja/haproxy/combined_listeners/jinja_cfg.py +12 -1
- octavia/common/jinja/haproxy/combined_listeners/templates/macros.j2 +5 -2
- octavia/common/jinja/lvs/jinja_cfg.py +4 -2
- octavia/common/keystone.py +58 -5
- octavia/common/validate.py +35 -0
- octavia/compute/drivers/noop_driver/driver.py +6 -0
- octavia/controller/healthmanager/health_manager.py +3 -6
- octavia/controller/housekeeping/house_keeping.py +36 -37
- octavia/controller/worker/amphora_rate_limit.py +5 -4
- octavia/controller/worker/task_utils.py +57 -41
- octavia/controller/worker/v2/controller_worker.py +160 -103
- octavia/controller/worker/v2/flows/listener_flows.py +3 -0
- octavia/controller/worker/v2/flows/load_balancer_flows.py +9 -14
- octavia/controller/worker/v2/tasks/amphora_driver_tasks.py +152 -91
- octavia/controller/worker/v2/tasks/compute_tasks.py +4 -2
- octavia/controller/worker/v2/tasks/database_tasks.py +542 -400
- octavia/controller/worker/v2/tasks/network_tasks.py +119 -79
- octavia/db/api.py +26 -23
- octavia/db/base_models.py +2 -2
- octavia/db/healthcheck.py +2 -1
- octavia/db/migration/alembic_migrations/versions/632152d2d32e_add_http_strict_transport_security_.py +42 -0
- octavia/db/models.py +12 -2
- octavia/db/prepare.py +2 -0
- octavia/db/repositories.py +462 -482
- octavia/hacking/checks.py +1 -1
- octavia/network/base.py +0 -14
- octavia/network/drivers/neutron/allowed_address_pairs.py +92 -135
- octavia/network/drivers/neutron/base.py +65 -77
- octavia/network/drivers/neutron/utils.py +69 -85
- octavia/network/drivers/noop_driver/driver.py +0 -7
- octavia/statistics/drivers/update_db.py +10 -10
- octavia/tests/common/constants.py +91 -84
- octavia/tests/common/sample_data_models.py +13 -1
- octavia/tests/fixtures.py +32 -0
- octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +9 -10
- octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py +260 -15
- octavia/tests/functional/api/test_root_controller.py +3 -28
- octavia/tests/functional/api/v2/base.py +5 -3
- octavia/tests/functional/api/v2/test_amphora.py +18 -5
- octavia/tests/functional/api/v2/test_availability_zone_profiles.py +1 -0
- octavia/tests/functional/api/v2/test_listener.py +51 -19
- octavia/tests/functional/api/v2/test_load_balancer.py +10 -1
- octavia/tests/functional/db/base.py +31 -16
- octavia/tests/functional/db/test_models.py +27 -28
- octavia/tests/functional/db/test_repositories.py +407 -50
- octavia/tests/unit/amphorae/backends/agent/api_server/test_amphora_info.py +2 -0
- octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py +1 -1
- octavia/tests/unit/amphorae/backends/agent/api_server/test_plug.py +54 -6
- octavia/tests/unit/amphorae/backends/agent/api_server/test_util.py +35 -0
- octavia/tests/unit/amphorae/backends/health_daemon/test_health_daemon.py +8 -0
- octavia/tests/unit/amphorae/backends/health_daemon/test_health_sender.py +18 -0
- octavia/tests/unit/amphorae/backends/utils/test_interface.py +81 -0
- octavia/tests/unit/amphorae/backends/utils/test_interface_file.py +2 -0
- octavia/tests/unit/amphorae/backends/utils/test_keepalivedlvs_query.py +129 -5
- octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +42 -20
- octavia/tests/unit/amphorae/drivers/health/test_heartbeat_udp.py +18 -20
- octavia/tests/unit/amphorae/drivers/keepalived/jinja/test_jinja_cfg.py +4 -4
- octavia/tests/unit/amphorae/drivers/noop_driver/test_driver.py +4 -1
- octavia/tests/unit/api/drivers/driver_agent/test_driver_get.py +3 -3
- octavia/tests/unit/api/drivers/driver_agent/test_driver_updater.py +11 -13
- octavia/tests/unit/base.py +6 -0
- octavia/tests/unit/cmd/test_interface.py +2 -2
- octavia/tests/unit/cmd/test_status.py +2 -2
- octavia/tests/unit/common/jinja/haproxy/combined_listeners/test_jinja_cfg.py +152 -1
- octavia/tests/unit/common/sample_configs/sample_configs_combined.py +10 -3
- octavia/tests/unit/common/test_clients.py +0 -39
- octavia/tests/unit/common/test_keystone.py +54 -0
- octavia/tests/unit/common/test_validate.py +67 -0
- octavia/tests/unit/controller/healthmanager/test_health_manager.py +8 -22
- octavia/tests/unit/controller/housekeeping/test_house_keeping.py +3 -64
- octavia/tests/unit/controller/worker/test_amphora_rate_limit.py +1 -1
- octavia/tests/unit/controller/worker/test_task_utils.py +44 -24
- octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +0 -1
- octavia/tests/unit/controller/worker/v2/tasks/test_amphora_driver_tasks.py +49 -26
- octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +399 -196
- octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks_quota.py +37 -64
- octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +3 -14
- octavia/tests/unit/controller/worker/v2/test_controller_worker.py +2 -2
- octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +456 -561
- octavia/tests/unit/network/drivers/neutron/test_base.py +181 -194
- octavia/tests/unit/network/drivers/neutron/test_utils.py +14 -30
- octavia/tests/unit/statistics/drivers/test_update_db.py +7 -5
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/README.rst +1 -1
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/AUTHORS +4 -0
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/METADATA +4 -4
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/RECORD +141 -189
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/entry_points.txt +1 -2
- octavia-13.0.0.0rc1.dist-info/pbr.json +1 -0
- octavia/api/drivers/amphora_driver/v1/__init__.py +0 -11
- octavia/api/drivers/amphora_driver/v1/driver.py +0 -547
- octavia/controller/queue/v1/__init__.py +0 -11
- octavia/controller/queue/v1/consumer.py +0 -64
- octavia/controller/queue/v1/endpoints.py +0 -160
- octavia/controller/worker/v1/__init__.py +0 -11
- octavia/controller/worker/v1/controller_worker.py +0 -1157
- octavia/controller/worker/v1/flows/__init__.py +0 -11
- octavia/controller/worker/v1/flows/amphora_flows.py +0 -610
- octavia/controller/worker/v1/flows/health_monitor_flows.py +0 -105
- octavia/controller/worker/v1/flows/l7policy_flows.py +0 -94
- octavia/controller/worker/v1/flows/l7rule_flows.py +0 -100
- octavia/controller/worker/v1/flows/listener_flows.py +0 -128
- octavia/controller/worker/v1/flows/load_balancer_flows.py +0 -692
- octavia/controller/worker/v1/flows/member_flows.py +0 -230
- octavia/controller/worker/v1/flows/pool_flows.py +0 -127
- octavia/controller/worker/v1/tasks/__init__.py +0 -11
- octavia/controller/worker/v1/tasks/amphora_driver_tasks.py +0 -453
- octavia/controller/worker/v1/tasks/cert_task.py +0 -51
- octavia/controller/worker/v1/tasks/compute_tasks.py +0 -335
- octavia/controller/worker/v1/tasks/database_tasks.py +0 -2756
- octavia/controller/worker/v1/tasks/lifecycle_tasks.py +0 -173
- octavia/controller/worker/v1/tasks/model_tasks.py +0 -41
- octavia/controller/worker/v1/tasks/network_tasks.py +0 -970
- octavia/controller/worker/v1/tasks/retry_tasks.py +0 -74
- octavia/tests/unit/api/drivers/amphora_driver/v1/__init__.py +0 -11
- octavia/tests/unit/api/drivers/amphora_driver/v1/test_driver.py +0 -824
- octavia/tests/unit/controller/queue/v1/__init__.py +0 -11
- octavia/tests/unit/controller/queue/v1/test_consumer.py +0 -61
- octavia/tests/unit/controller/queue/v1/test_endpoints.py +0 -189
- octavia/tests/unit/controller/worker/v1/__init__.py +0 -11
- octavia/tests/unit/controller/worker/v1/flows/__init__.py +0 -11
- octavia/tests/unit/controller/worker/v1/flows/test_amphora_flows.py +0 -474
- octavia/tests/unit/controller/worker/v1/flows/test_health_monitor_flows.py +0 -72
- octavia/tests/unit/controller/worker/v1/flows/test_l7policy_flows.py +0 -67
- octavia/tests/unit/controller/worker/v1/flows/test_l7rule_flows.py +0 -67
- octavia/tests/unit/controller/worker/v1/flows/test_listener_flows.py +0 -91
- octavia/tests/unit/controller/worker/v1/flows/test_load_balancer_flows.py +0 -431
- octavia/tests/unit/controller/worker/v1/flows/test_member_flows.py +0 -106
- octavia/tests/unit/controller/worker/v1/flows/test_pool_flows.py +0 -77
- octavia/tests/unit/controller/worker/v1/tasks/__init__.py +0 -11
- octavia/tests/unit/controller/worker/v1/tasks/test_amphora_driver_tasks.py +0 -792
- octavia/tests/unit/controller/worker/v1/tasks/test_cert_task.py +0 -46
- octavia/tests/unit/controller/worker/v1/tasks/test_compute_tasks.py +0 -634
- octavia/tests/unit/controller/worker/v1/tasks/test_database_tasks.py +0 -2615
- octavia/tests/unit/controller/worker/v1/tasks/test_database_tasks_quota.py +0 -415
- octavia/tests/unit/controller/worker/v1/tasks/test_lifecycle_tasks.py +0 -401
- octavia/tests/unit/controller/worker/v1/tasks/test_model_tasks.py +0 -44
- octavia/tests/unit/controller/worker/v1/tasks/test_network_tasks.py +0 -1788
- octavia/tests/unit/controller/worker/v1/tasks/test_retry_tasks.py +0 -47
- octavia/tests/unit/controller/worker/v1/test_controller_worker.py +0 -2096
- octavia-12.0.0.0rc2.dist-info/pbr.json +0 -1
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/LICENSE +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/README.rst +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/tox.ini +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/version.txt +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/scripts/octavia-wsgi +0 -0
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/LICENSE +0 -0
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/WHEEL +0 -0
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -185,6 +185,7 @@ class TestAmphoraInfo(base.TestCase):
|
|
185
185
|
u'packages': {},
|
186
186
|
u'topology': u'SINGLE',
|
187
187
|
u'topology_status': u'OK'}
|
188
|
+
self.useFixture(test_utils.OpenFixture('/etc/tuned/active_profile'))
|
188
189
|
actual = self.amp_info.compile_amphora_details()
|
189
190
|
self.assertEqual(expected_dict, actual.json)
|
190
191
|
m_count.assert_called_once_with(sorted(mget_loadbalancers()))
|
@@ -277,6 +278,7 @@ class TestAmphoraInfo(base.TestCase):
|
|
277
278
|
u'packages': {},
|
278
279
|
u'topology': u'SINGLE',
|
279
280
|
u'topology_status': u'OK'}
|
281
|
+
self.useFixture(test_utils.OpenFixture('/etc/tuned/active_profile'))
|
280
282
|
actual = self.amp_info.compile_amphora_details(self.lvs_driver)
|
281
283
|
self.assertEqual(expected_dict, actual.json)
|
282
284
|
api_server.VERSION = original_version
|
@@ -106,7 +106,7 @@ class TestOSUtils(base.TestCase):
|
|
106
106
|
'192.0.2.2', 16)
|
107
107
|
|
108
108
|
mock_interface_file.assert_called_once_with(
|
109
|
-
name='eth1',
|
109
|
+
name='eth1', if_type="lo",
|
110
110
|
addresses=[{"address": "192.0.2.2", "prefixlen": 16}])
|
111
111
|
mock_interface.write.assert_called_once()
|
112
112
|
|
@@ -265,7 +265,10 @@ class TestPlug(base.TestCase):
|
|
265
265
|
"BaseOS.write_port_interface_file")
|
266
266
|
@mock.patch("octavia.amphorae.backends.agent.api_server.osutils."
|
267
267
|
"BaseOS.bring_interface_up")
|
268
|
-
|
268
|
+
@mock.patch("octavia.amphorae.backends.agent.api_server.util."
|
269
|
+
"send_member_advertisements")
|
270
|
+
def test_plug_network(self, mock_send_member_adv,
|
271
|
+
mock_if_up, mock_write_port_interface,
|
269
272
|
mock_netns, mock_iproute,
|
270
273
|
mock_by_mac, mock_interface_exists, mock_webob):
|
271
274
|
fixed_ips = [
|
@@ -282,12 +285,13 @@ class TestPlug(base.TestCase):
|
|
282
285
|
self.test_plug.plug_network(FAKE_MAC_ADDRESS, fixed_ips, 1400)
|
283
286
|
|
284
287
|
mock_write_port_interface.assert_called_once_with(
|
285
|
-
interface='
|
286
|
-
mock_if_up.assert_called_once_with('
|
288
|
+
interface='eth2', fixed_ips=fixed_ips, mtu=mtu)
|
289
|
+
mock_if_up.assert_called_once_with('eth2', 'network')
|
290
|
+
mock_send_member_adv.assert_called_once_with(fixed_ips)
|
287
291
|
|
288
292
|
mock_webob.Response.assert_any_call(
|
289
293
|
json={'message': 'OK',
|
290
|
-
'details': 'Plugged on interface
|
294
|
+
'details': 'Plugged on interface eth2'},
|
291
295
|
status=202)
|
292
296
|
|
293
297
|
@mock.patch.object(plug, "webob")
|
@@ -300,7 +304,10 @@ class TestPlug(base.TestCase):
|
|
300
304
|
"BaseOS.write_port_interface_file")
|
301
305
|
@mock.patch("octavia.amphorae.backends.agent.api_server.osutils."
|
302
306
|
"BaseOS.bring_interface_up")
|
303
|
-
|
307
|
+
@mock.patch("octavia.amphorae.backends.agent.api_server.util."
|
308
|
+
"send_member_advertisements")
|
309
|
+
def test_plug_network_existing_interface(self, mock_send_member_adv,
|
310
|
+
mock_if_up,
|
304
311
|
mock_write_port_interface,
|
305
312
|
mock_netns, mock_by_mac,
|
306
313
|
mock_interface_exists,
|
@@ -327,6 +334,7 @@ class TestPlug(base.TestCase):
|
|
327
334
|
mock_write_port_interface.assert_called_once_with(
|
328
335
|
interface=FAKE_INTERFACE, fixed_ips=fixed_ips, mtu=mtu)
|
329
336
|
mock_if_up.assert_called_once_with(FAKE_INTERFACE, 'network')
|
337
|
+
mock_send_member_adv.assert_called_once_with(fixed_ips)
|
330
338
|
|
331
339
|
mock_webob.Response.assert_any_call(
|
332
340
|
json={'message': 'OK',
|
@@ -344,8 +352,10 @@ class TestPlug(base.TestCase):
|
|
344
352
|
"BaseOS.write_vip_interface_file")
|
345
353
|
@mock.patch("octavia.amphorae.backends.agent.api_server.osutils."
|
346
354
|
"BaseOS.bring_interface_up")
|
355
|
+
@mock.patch("octavia.amphorae.backends.agent.api_server.util."
|
356
|
+
"send_member_advertisements")
|
347
357
|
def test_plug_network_on_vip(
|
348
|
-
self, mock_if_up, mock_write_vip_interface,
|
358
|
+
self, mock_send_member_adv, mock_if_up, mock_write_vip_interface,
|
349
359
|
mock_netns, mock_by_mac, mock_interface_exists, mock_webob):
|
350
360
|
fixed_ips = [
|
351
361
|
{'ip_address': FAKE_IP_IPV4,
|
@@ -394,9 +404,47 @@ class TestPlug(base.TestCase):
|
|
394
404
|
fixed_ips=fixed_ips, mtu=mtu)
|
395
405
|
|
396
406
|
mock_if_up.assert_called_once_with(FAKE_INTERFACE, 'vip')
|
407
|
+
mock_send_member_adv.assert_called_once_with(fixed_ips)
|
397
408
|
|
398
409
|
mock_webob.Response.assert_any_call(
|
399
410
|
json={'message': 'OK',
|
400
411
|
'details': 'Updated existing interface {}'.format(
|
401
412
|
FAKE_INTERFACE)},
|
402
413
|
status=202)
|
414
|
+
|
415
|
+
@mock.patch('pyroute2.NetNS', create=True)
|
416
|
+
def test__netns_get_next_interface(self, mock_netns):
|
417
|
+
netns_handle = mock_netns.return_value.__enter__.return_value
|
418
|
+
|
419
|
+
netns_handle.get_links.return_value = [
|
420
|
+
{'attrs': [['IFLA_IFNAME', 'lo']]},
|
421
|
+
]
|
422
|
+
|
423
|
+
ifname = self.test_plug._netns_get_next_interface()
|
424
|
+
self.assertEqual('eth2', ifname)
|
425
|
+
|
426
|
+
netns_handle.get_links.return_value = [
|
427
|
+
{'attrs': [['IFLA_IFNAME', 'lo']]},
|
428
|
+
{'attrs': [['IFLA_IFNAME', 'eth1']]},
|
429
|
+
{'attrs': [['IFLA_IFNAME', 'eth2']]},
|
430
|
+
{'attrs': [['IFLA_IFNAME', 'eth3']]},
|
431
|
+
]
|
432
|
+
|
433
|
+
ifname = self.test_plug._netns_get_next_interface()
|
434
|
+
self.assertEqual('eth4', ifname)
|
435
|
+
|
436
|
+
netns_handle.get_links.return_value = [
|
437
|
+
{'attrs': [['IFLA_IFNAME', 'lo']]},
|
438
|
+
{'attrs': [['IFLA_IFNAME', 'eth1']]},
|
439
|
+
{'attrs': [['IFLA_IFNAME', 'eth3']]},
|
440
|
+
]
|
441
|
+
|
442
|
+
ifname = self.test_plug._netns_get_next_interface()
|
443
|
+
self.assertEqual('eth2', ifname)
|
444
|
+
|
445
|
+
netns_handle.get_links.return_value = [
|
446
|
+
{'attrs': [['IFLA_IFNAME', f'eth{idx}']]}
|
447
|
+
for idx in range(2, 1000)]
|
448
|
+
|
449
|
+
ifname = self.test_plug._netns_get_next_interface()
|
450
|
+
self.assertEqual('eth1000', ifname)
|
@@ -406,3 +406,38 @@ class TestUtil(base.TestCase):
|
|
406
406
|
util.send_vip_advertisements(LB_ID1)
|
407
407
|
mock_get_int_name.assert_not_called()
|
408
408
|
mock_send_advert.assert_not_called()
|
409
|
+
|
410
|
+
@mock.patch('octavia.amphorae.backends.utils.ip_advertisement.'
|
411
|
+
'send_ip_advertisement')
|
412
|
+
@mock.patch('octavia.amphorae.backends.utils.network_utils.'
|
413
|
+
'get_interface_name')
|
414
|
+
def test_send_member_advertisements(self, mock_get_int_name,
|
415
|
+
mock_send_advert):
|
416
|
+
# IPv4 fixed_ips
|
417
|
+
mock_get_int_name.side_effect = ['fake0', 'fake1']
|
418
|
+
fixed_ips = [{'ip_address': '192.0.2.1'},
|
419
|
+
{'ip_address': '192.2.0.2'}]
|
420
|
+
util.send_member_advertisements(fixed_ips)
|
421
|
+
mock_send_advert.assert_has_calls(
|
422
|
+
[mock.call('fake0', fixed_ips[0]['ip_address'],
|
423
|
+
net_ns=consts.AMPHORA_NAMESPACE),
|
424
|
+
mock.call('fake1', fixed_ips[1]['ip_address'],
|
425
|
+
net_ns=consts.AMPHORA_NAMESPACE)])
|
426
|
+
|
427
|
+
# Mixed IPv4/IPv6
|
428
|
+
mock_send_advert.reset_mock()
|
429
|
+
mock_get_int_name.side_effect = ['fake0', 'fake1']
|
430
|
+
fixed_ips = [{'ip_address': '192.0.2.1'},
|
431
|
+
{'ip_address': '2001:db8::2'}]
|
432
|
+
util.send_member_advertisements(fixed_ips)
|
433
|
+
mock_send_advert.assert_has_calls(
|
434
|
+
[mock.call('fake0', fixed_ips[0]['ip_address'],
|
435
|
+
net_ns=consts.AMPHORA_NAMESPACE),
|
436
|
+
mock.call('fake1', fixed_ips[1]['ip_address'],
|
437
|
+
net_ns=consts.AMPHORA_NAMESPACE)])
|
438
|
+
|
439
|
+
# Exception
|
440
|
+
mock_send_advert.reset_mock()
|
441
|
+
mock_get_int_name.side_effect = Exception('ERROR')
|
442
|
+
util.send_member_advertisements(fixed_ips)
|
443
|
+
mock_send_advert.assert_not_called()
|
@@ -319,6 +319,14 @@ class TestHealthDaemon(base.TestCase):
|
|
319
319
|
stats_query_mock.show_stat.assert_called_once_with()
|
320
320
|
stats_query_mock.get_pool_status.assert_called_once_with()
|
321
321
|
|
322
|
+
@mock.patch('octavia.amphorae.backends.utils.haproxy_query.HAProxyQuery')
|
323
|
+
def test_get_stats_exception(self, mock_query):
|
324
|
+
mock_query.side_effect = Exception('Boom')
|
325
|
+
|
326
|
+
stats, pool_status = health_daemon.get_stats('TEST')
|
327
|
+
self.assertEqual([], stats)
|
328
|
+
self.assertEqual({}, pool_status)
|
329
|
+
|
322
330
|
@mock.patch('octavia.amphorae.backends.agent.api_server.'
|
323
331
|
'util.is_lb_running')
|
324
332
|
@mock.patch('octavia.amphorae.backends.health_daemon.'
|
@@ -93,6 +93,24 @@ class TestHealthSender(base.TestCase):
|
|
93
93
|
|
94
94
|
sendto_mock.reset_mock()
|
95
95
|
|
96
|
+
# Test IPv6 path enclosed within square brackets ("[" and "]").
|
97
|
+
self.conf.config(group="health_manager",
|
98
|
+
controller_ip_port_list=['[2001:0db8::f00d]:80'])
|
99
|
+
mock_getaddrinfo.return_value = [(socket.AF_INET6,
|
100
|
+
socket.SOCK_DGRAM,
|
101
|
+
socket.IPPROTO_UDP,
|
102
|
+
'',
|
103
|
+
('2001:db8::f00d', 80, 0, 0))]
|
104
|
+
|
105
|
+
sender = health_sender.UDPStatusSender()
|
106
|
+
|
107
|
+
sender.dosend(SAMPLE_MSG)
|
108
|
+
|
109
|
+
sendto_mock.assert_called_once_with(SAMPLE_MSG_BIN,
|
110
|
+
('2001:db8::f00d', 80, 0, 0))
|
111
|
+
|
112
|
+
sendto_mock.reset_mock()
|
113
|
+
|
96
114
|
# Test IPv6 link-local address path
|
97
115
|
self.conf.config(
|
98
116
|
group="health_manager",
|
@@ -74,6 +74,7 @@ class TestInterface(base.TestCase):
|
|
74
74
|
'],\n'
|
75
75
|
'"mtu": 1450,\n'
|
76
76
|
'"name": "eth1",\n'
|
77
|
+
'"if_type": "mytype",\n'
|
77
78
|
'"routes": [\n'
|
78
79
|
'{"dst": "0.0.0.0/0",\n'
|
79
80
|
'"gateway": "10.0.0.1"},\n'
|
@@ -107,6 +108,7 @@ class TestInterface(base.TestCase):
|
|
107
108
|
|
108
109
|
expected_dict = {
|
109
110
|
consts.NAME: "eth1",
|
111
|
+
consts.IF_TYPE: "mytype",
|
110
112
|
consts.MTU: 1450,
|
111
113
|
consts.ADDRESSES: [{
|
112
114
|
consts.ADDRESS: "10.0.0.2",
|
@@ -331,6 +333,7 @@ class TestInterface(base.TestCase):
|
|
331
333
|
mock_link, mock_addr, mock_route, mock_rule):
|
332
334
|
iface = interface_file.InterfaceFile(
|
333
335
|
name="eth1",
|
336
|
+
if_type="vip",
|
334
337
|
mtu=1450,
|
335
338
|
addresses=[{
|
336
339
|
consts.ADDRESS: '1.2.3.4',
|
@@ -445,6 +448,78 @@ class TestInterface(base.TestCase):
|
|
445
448
|
mock.call(["post-up", "eth1"])
|
446
449
|
])
|
447
450
|
|
451
|
+
@mock.patch('pyroute2.IPRoute.rule')
|
452
|
+
@mock.patch('pyroute2.IPRoute.route')
|
453
|
+
@mock.patch('pyroute2.IPRoute.addr')
|
454
|
+
@mock.patch('pyroute2.IPRoute.link')
|
455
|
+
@mock.patch('pyroute2.IPRoute.get_links')
|
456
|
+
@mock.patch('pyroute2.IPRoute.link_lookup')
|
457
|
+
@mock.patch('pyroute2.IPRoute.get_rules')
|
458
|
+
@mock.patch('subprocess.check_output')
|
459
|
+
def test_up_backend(self, mock_check_output, mock_get_rules,
|
460
|
+
mock_link_lookup, mock_get_links, mock_link, mock_addr,
|
461
|
+
mock_route, mock_rule):
|
462
|
+
iface = interface_file.InterfaceFile(
|
463
|
+
name="eth1",
|
464
|
+
if_type="backend",
|
465
|
+
mtu=1450,
|
466
|
+
addresses=[{
|
467
|
+
consts.ADDRESS: '1.2.3.4',
|
468
|
+
consts.PREFIXLEN: 24
|
469
|
+
}],
|
470
|
+
routes=[],
|
471
|
+
rules=[],
|
472
|
+
scripts={
|
473
|
+
consts.IFACE_UP: [{
|
474
|
+
consts.COMMAND: "post-up eth1"
|
475
|
+
}],
|
476
|
+
consts.IFACE_DOWN: [{
|
477
|
+
consts.COMMAND: "post-down eth1"
|
478
|
+
}],
|
479
|
+
})
|
480
|
+
|
481
|
+
idx = mock.MagicMock()
|
482
|
+
mock_link_lookup.return_value = [idx]
|
483
|
+
|
484
|
+
mock_get_links.return_value = [{
|
485
|
+
consts.STATE: consts.IFACE_DOWN
|
486
|
+
}]
|
487
|
+
mock_get_rules.return_value = [{
|
488
|
+
'src_len': 32,
|
489
|
+
'attrs': {
|
490
|
+
'FRA_SRC': '1.1.1.1',
|
491
|
+
'FRA_TABLE': 20,
|
492
|
+
'FRA_PROTOCOL': 0
|
493
|
+
}
|
494
|
+
}]
|
495
|
+
|
496
|
+
controller = interface.InterfaceController()
|
497
|
+
controller.up(iface)
|
498
|
+
|
499
|
+
mock_link.assert_called_once_with(
|
500
|
+
controller.SET,
|
501
|
+
index=idx,
|
502
|
+
state=consts.IFACE_UP,
|
503
|
+
mtu=1450)
|
504
|
+
|
505
|
+
mock_addr.assert_has_calls([
|
506
|
+
mock.call(controller.ADD,
|
507
|
+
index=idx,
|
508
|
+
address='1.2.3.4',
|
509
|
+
prefixlen=24,
|
510
|
+
family=socket.AF_INET),
|
511
|
+
])
|
512
|
+
|
513
|
+
mock_route.assert_called_once_with(
|
514
|
+
'dump', family=mock.ANY, match=mock.ANY)
|
515
|
+
|
516
|
+
# for 'backend' iface, we don't update the rules
|
517
|
+
mock_rule.assert_not_called()
|
518
|
+
|
519
|
+
mock_check_output.assert_has_calls([
|
520
|
+
mock.call(["post-up", "eth1"])
|
521
|
+
])
|
522
|
+
|
448
523
|
@mock.patch('pyroute2.IPRoute.rule')
|
449
524
|
@mock.patch('pyroute2.IPRoute.route')
|
450
525
|
@mock.patch('pyroute2.IPRoute.addr')
|
@@ -463,6 +538,7 @@ class TestInterface(base.TestCase):
|
|
463
538
|
mock_route, mock_rule):
|
464
539
|
iface = interface_file.InterfaceFile(
|
465
540
|
name="eth1",
|
541
|
+
if_type="vip",
|
466
542
|
mtu=1450,
|
467
543
|
addresses=[{
|
468
544
|
consts.ADDRESS: '1.2.3.4',
|
@@ -658,6 +734,7 @@ class TestInterface(base.TestCase):
|
|
658
734
|
mock_route, mock_rule):
|
659
735
|
iface = interface_file.InterfaceFile(
|
660
736
|
name="eth1",
|
737
|
+
if_type="vip",
|
661
738
|
mtu=1450,
|
662
739
|
addresses=[{
|
663
740
|
consts.DHCP: True,
|
@@ -722,6 +799,7 @@ class TestInterface(base.TestCase):
|
|
722
799
|
mock_link, mock_addr, mock_route, mock_rule):
|
723
800
|
iface = interface_file.InterfaceFile(
|
724
801
|
name="eth1",
|
802
|
+
if_type="vip",
|
725
803
|
mtu=1450,
|
726
804
|
addresses=[{
|
727
805
|
consts.ADDRESS: '1.2.3.4',
|
@@ -848,6 +926,7 @@ class TestInterface(base.TestCase):
|
|
848
926
|
mock_addr, mock_route, mock_rule):
|
849
927
|
iface = interface_file.InterfaceFile(
|
850
928
|
name="eth1",
|
929
|
+
if_type="vip",
|
851
930
|
mtu=1450,
|
852
931
|
addresses=[{
|
853
932
|
consts.ADDRESS: '1.2.3.4',
|
@@ -997,6 +1076,7 @@ class TestInterface(base.TestCase):
|
|
997
1076
|
mock_route, mock_rule):
|
998
1077
|
iface = interface_file.InterfaceFile(
|
999
1078
|
name="eth1",
|
1079
|
+
if_type="vip",
|
1000
1080
|
mtu=1450,
|
1001
1081
|
addresses=[{
|
1002
1082
|
consts.ADDRESS: '1.2.3.4',
|
@@ -1069,6 +1149,7 @@ class TestInterface(base.TestCase):
|
|
1069
1149
|
mock_addr, mock_route, mock_rule):
|
1070
1150
|
iface = interface_file.InterfaceFile(
|
1071
1151
|
name="eth1",
|
1152
|
+
if_type="vip",
|
1072
1153
|
mtu=1450,
|
1073
1154
|
addresses=[{
|
1074
1155
|
consts.DHCP: True,
|
@@ -691,6 +691,7 @@ class TestInterfaceFile(base.TestCase):
|
|
691
691
|
'"prefixlen": 26}\n'
|
692
692
|
'],\n'
|
693
693
|
'"mtu": 1450,\n'
|
694
|
+
'"if_type": "mytype",\n'
|
694
695
|
'"name": "eth1",\n'
|
695
696
|
'"routes": [\n'
|
696
697
|
'{"dst": "0.0.0.0/0",\n'
|
@@ -717,6 +718,7 @@ class TestInterfaceFile(base.TestCase):
|
|
717
718
|
|
718
719
|
expected_dict = {
|
719
720
|
consts.NAME: "eth1",
|
721
|
+
consts.IF_TYPE: "mytype",
|
720
722
|
consts.MTU: 1450,
|
721
723
|
consts.ADDRESSES: [{
|
722
724
|
consts.ADDRESS: "10.0.0.181",
|
@@ -52,6 +52,24 @@ KERNAL_FILE_SAMPLE_V6 = (
|
|
52
52
|
" -> [fd79:35e2::8f3f]:115C "
|
53
53
|
"Masq 2 0 0")
|
54
54
|
|
55
|
+
KERNEL_FILE_SAMPLE_MIXED = (
|
56
|
+
"IP Virtual Server version 1.2.1 (size=4096)\n"
|
57
|
+
"Prot LocalAddress:Port Scheduler Flags\n"
|
58
|
+
" -> RemoteAddress:Port Forward Weight ActiveConn InActConn\n"
|
59
|
+
"UDP [fd79:35e2:9963:0000:f816:3eff:fe6d:7a2a]:1E61 rr\n"
|
60
|
+
" -> [fd79:35e2:9963:0000:f816:3eff:feca:b7bf]:08AE "
|
61
|
+
"Masq 3 0 0\n"
|
62
|
+
" -> [fd79:35e2:9963:0000:f816:3eff:fe9d:94df]:0D05 "
|
63
|
+
"Masq 2 0 0\n"
|
64
|
+
" -> [fd79:35e2::8f3f]:115C "
|
65
|
+
"Masq 2 0 0\n"
|
66
|
+
"UDP 0A000025:1E61 rr\n"
|
67
|
+
" -> 0A000023:0D05 Masq 2 0 0\n"
|
68
|
+
" -> 0A000019:08AE Masq 3 0 0\n"
|
69
|
+
"UDP 0A000025:FF12 rr\n"
|
70
|
+
" -> 0A000023:12AB Masq 2 0 0\n"
|
71
|
+
" -> 0A000019:BF2E Masq 3 0 0")
|
72
|
+
|
55
73
|
CFG_FILE_TEMPLATE_v4 = (
|
56
74
|
"# Configuration for Listener %(listener_id)s\n\n"
|
57
75
|
"net_namespace %(ns_name)s\n\n"
|
@@ -190,6 +208,37 @@ CFG_FILE_TEMPLATE_mixed = (
|
|
190
208
|
" # Member %(member_id5)s is disabled\n\n"
|
191
209
|
"}")
|
192
210
|
|
211
|
+
CFG_FILE_TEMPLATE_mixed_no_ipv6_member = (
|
212
|
+
"# Configuration for Listener %(listener_id)s\n\n"
|
213
|
+
"net_namespace %(ns_name)s\n\n"
|
214
|
+
"virtual_server_group ipv4-group {\n"
|
215
|
+
" 10.0.0.37 7777\n"
|
216
|
+
"}\n\n"
|
217
|
+
"virtual_server group ipv4-group {\n"
|
218
|
+
" lb_algo rr\n"
|
219
|
+
" lvs_method NAT\n"
|
220
|
+
" protocol udp\n\n\n"
|
221
|
+
" # Configuration for Pool %(pool_id)s\n"
|
222
|
+
" # Configuration for Member %(member_id1)s\n"
|
223
|
+
" real_server 10.0.0.25 2222 {\n"
|
224
|
+
" weight 3\n"
|
225
|
+
" MISC_CHECK {\n\n"
|
226
|
+
" misc_path \"/usr/bin/check_script.sh\"\n\n"
|
227
|
+
" misc_timeout 5\n\n"
|
228
|
+
" }\n\n"
|
229
|
+
" }\n\n"
|
230
|
+
" # Member %(member_id2)s is disabled\n\n"
|
231
|
+
"}\n"
|
232
|
+
"virtual_server_group ipv6-group {\n"
|
233
|
+
" fd79:35e2:9963:0:f816:3eff:fe6d:7a2a 7777\n"
|
234
|
+
"}\n\n"
|
235
|
+
"virtual_server group ipv6-group {\n"
|
236
|
+
" lb_algo rr\n"
|
237
|
+
" lvs_method NAT\n"
|
238
|
+
" protocol udp\n\n\n"
|
239
|
+
" # Configuration for Pool %(pool_id)s\n"
|
240
|
+
"}")
|
241
|
+
|
193
242
|
CFG_FILE_TEMPLATE_DISABLED_LISTENER = (
|
194
243
|
"# Listener %(listener_id)s is disabled \n\n"
|
195
244
|
"net_namespace %(ns_name)s\n\n"
|
@@ -233,6 +282,7 @@ class LvsQueryTestCase(base.TestCase):
|
|
233
282
|
self.member_id4_v6 = uuidutils.generate_uuid()
|
234
283
|
self.member_id5_v6 = uuidutils.generate_uuid()
|
235
284
|
self.listener_id_mixed = uuidutils.generate_uuid()
|
285
|
+
self.listener_id_mixed_no_ipv6_member = uuidutils.generate_uuid()
|
236
286
|
self.pool_id_mixed = uuidutils.generate_uuid()
|
237
287
|
self.disabled_listener_id = uuidutils.generate_uuid()
|
238
288
|
cfg_content_v4 = CFG_FILE_TEMPLATE_v4 % {
|
@@ -264,6 +314,15 @@ class LvsQueryTestCase(base.TestCase):
|
|
264
314
|
'member_id4': self.member_id4_v6,
|
265
315
|
'member_id5': self.member_id5_v6
|
266
316
|
}
|
317
|
+
cfg_content_mixed_no_ipv6_member = (
|
318
|
+
CFG_FILE_TEMPLATE_mixed_no_ipv6_member % {
|
319
|
+
'listener_id': self.listener_id_mixed,
|
320
|
+
'ns_name': constants.AMPHORA_NAMESPACE,
|
321
|
+
'pool_id': self.pool_id_mixed,
|
322
|
+
'member_id1': self.member_id1_v4,
|
323
|
+
'member_id2': self.member_id2_v4
|
324
|
+
}
|
325
|
+
)
|
267
326
|
cfg_content_disabled_listener = (
|
268
327
|
CFG_FILE_TEMPLATE_DISABLED_LISTENER % {
|
269
328
|
'listener_id': self.listener_id_v6,
|
@@ -277,6 +336,10 @@ class LvsQueryTestCase(base.TestCase):
|
|
277
336
|
self.useFixture(test_utils.OpenFixture(
|
278
337
|
util.keepalived_lvs_cfg_path(self.listener_id_mixed),
|
279
338
|
cfg_content_mixed))
|
339
|
+
self.useFixture(test_utils.OpenFixture(
|
340
|
+
util.keepalived_lvs_cfg_path(
|
341
|
+
self.listener_id_mixed_no_ipv6_member),
|
342
|
+
cfg_content_mixed_no_ipv6_member))
|
280
343
|
self.useFixture(test_utils.OpenFixture(
|
281
344
|
util.keepalived_lvs_cfg_path(self.disabled_listener_id),
|
282
345
|
cfg_content_disabled_listener))
|
@@ -300,7 +363,7 @@ class LvsQueryTestCase(base.TestCase):
|
|
300
363
|
'Weight': '2',
|
301
364
|
'ActiveConn': '0',
|
302
365
|
'InActConn': '0'}}
|
303
|
-
self.assertEqual(
|
366
|
+
self.assertEqual(expected, result)
|
304
367
|
|
305
368
|
# Ipv6 resolver
|
306
369
|
input_listener_ip_port = [
|
@@ -327,7 +390,45 @@ class LvsQueryTestCase(base.TestCase):
|
|
327
390
|
'Weight': '2',
|
328
391
|
'ActiveConn': '0',
|
329
392
|
'InActConn': '0'}}
|
330
|
-
self.assertEqual(
|
393
|
+
self.assertEqual(expected, result)
|
394
|
+
|
395
|
+
# mixed resolver
|
396
|
+
input_listener_ip_port = [
|
397
|
+
'[fd79:35e2:9963:0:f816:3eff:fe6d:7a2a]:7777',
|
398
|
+
'10.0.0.37:7777']
|
399
|
+
mock_check_output.return_value = KERNEL_FILE_SAMPLE_MIXED
|
400
|
+
result = lvs_query.get_listener_realserver_mapping(
|
401
|
+
target_ns, input_listener_ip_port,
|
402
|
+
health_monitor_enabled=True)
|
403
|
+
expected = {'[fd79:35e2:9963:0:f816:3eff:feca:b7bf]:2222':
|
404
|
+
{'status': constants.UP,
|
405
|
+
'Forward': 'Masq',
|
406
|
+
'Weight': '3',
|
407
|
+
'ActiveConn': '0',
|
408
|
+
'InActConn': '0'},
|
409
|
+
'[fd79:35e2:9963:0:f816:3eff:fe9d:94df]:3333':
|
410
|
+
{'status': constants.UP,
|
411
|
+
'Forward': 'Masq',
|
412
|
+
'Weight': '2',
|
413
|
+
'ActiveConn': '0',
|
414
|
+
'InActConn': '0'},
|
415
|
+
'[fd79:35e2::8f3f]:4444':
|
416
|
+
{'status': constants.UP,
|
417
|
+
'Forward': 'Masq',
|
418
|
+
'Weight': '2',
|
419
|
+
'ActiveConn': '0',
|
420
|
+
'InActConn': '0'},
|
421
|
+
'10.0.0.25:2222': {'status': 'UP',
|
422
|
+
'Forward': 'Masq',
|
423
|
+
'Weight': '3',
|
424
|
+
'ActiveConn': '0',
|
425
|
+
'InActConn': '0'},
|
426
|
+
'10.0.0.35:3333': {'status': 'UP',
|
427
|
+
'Forward': 'Masq',
|
428
|
+
'Weight': '2',
|
429
|
+
'ActiveConn': '0',
|
430
|
+
'InActConn': '0'}}
|
431
|
+
self.assertEqual(expected, result)
|
331
432
|
|
332
433
|
# negetive cases
|
333
434
|
mock_check_output.return_value = KERNAL_FILE_SAMPLE_V4
|
@@ -335,7 +436,7 @@ class LvsQueryTestCase(base.TestCase):
|
|
335
436
|
result = lvs_query.get_listener_realserver_mapping(
|
336
437
|
target_ns, [listener_ip_port],
|
337
438
|
health_monitor_enabled=True)
|
338
|
-
self.assertEqual(
|
439
|
+
self.assertEqual({}, result)
|
339
440
|
|
340
441
|
mock_check_output.return_value = KERNAL_FILE_SAMPLE_V6
|
341
442
|
for listener_ip_port in [
|
@@ -344,7 +445,7 @@ class LvsQueryTestCase(base.TestCase):
|
|
344
445
|
result = lvs_query.get_listener_realserver_mapping(
|
345
446
|
target_ns, [listener_ip_port],
|
346
447
|
health_monitor_enabled=True)
|
347
|
-
self.assertEqual(
|
448
|
+
self.assertEqual({}, result)
|
348
449
|
|
349
450
|
def test_get_lvs_listener_resource_ipports_nsname(self):
|
350
451
|
# ipv4
|
@@ -526,7 +627,7 @@ class LvsQueryTestCase(base.TestCase):
|
|
526
627
|
mock.Mock(st_mtime=1234),
|
527
628
|
mock.Mock(st_mtime=1234),
|
528
629
|
)
|
529
|
-
mock_get_mapping.return_value =
|
630
|
+
mock_get_mapping.return_value = {}
|
530
631
|
res = lvs_query.get_lvs_listener_pool_status(self.listener_id_v4)
|
531
632
|
expected = {
|
532
633
|
'lvs':
|
@@ -629,6 +730,29 @@ class LvsQueryTestCase(base.TestCase):
|
|
629
730
|
res = lvs_query.get_lvs_listeners_stats()
|
630
731
|
self.assertEqual({}, res)
|
631
732
|
|
733
|
+
# listener for both ipv4 and ipv6, but no member in the ipv6 pool
|
734
|
+
mock_is_running.return_value = True
|
735
|
+
mock_get_listener.return_value = [
|
736
|
+
self.listener_id_mixed_no_ipv6_member]
|
737
|
+
output_list = list()
|
738
|
+
output_list.append(IPVSADM_OUTPUT_TEMPLATE % {
|
739
|
+
"listener_ipport": "10.0.0.37:7777",
|
740
|
+
"member1_ipport": "10.0.0.25:2222",
|
741
|
+
"member2_ipport": "10.0.0.35:3333"})
|
742
|
+
output_list.append(IPVSADM_STATS_OUTPUT_TEMPLATE % {
|
743
|
+
"listener_ipport": "10.0.0.37:7777",
|
744
|
+
"member1_ipport": "10.0.0.25:2222",
|
745
|
+
"member2_ipport": "10.0.0.35:3333"})
|
746
|
+
mock_check_output.side_effect = output_list
|
747
|
+
res = lvs_query.get_lvs_listeners_stats()
|
748
|
+
# We can check the expected result reference the stats sample,
|
749
|
+
# that means this func can compute the stats info of single listener.
|
750
|
+
expected = {self.listener_id_mixed_no_ipv6_member: {
|
751
|
+
'status': constants.OPEN,
|
752
|
+
'stats': {'bin': 6387472, 'stot': 5, 'bout': 7490,
|
753
|
+
'ereq': 0, 'scur': 0}}}
|
754
|
+
self.assertEqual(expected, res)
|
755
|
+
|
632
756
|
@mock.patch('subprocess.check_output')
|
633
757
|
@mock.patch("octavia.amphorae.backends.agent.api_server.util."
|
634
758
|
"is_lvs_listener_running", return_value=True)
|