octavia 14.0.0__py3-none-any.whl → 14.0.1__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.
Files changed (61) hide show
  1. octavia/amphorae/backends/agent/api_server/keepalivedlvs.py +9 -0
  2. octavia/amphorae/backends/agent/api_server/osutils.py +4 -2
  3. octavia/amphorae/backends/agent/api_server/plug.py +5 -4
  4. octavia/amphorae/backends/agent/api_server/server.py +3 -2
  5. octavia/amphorae/backends/agent/api_server/util.py +35 -2
  6. octavia/amphorae/backends/utils/interface.py +2 -37
  7. octavia/amphorae/backends/utils/interface_file.py +23 -10
  8. octavia/amphorae/backends/utils/nftable_utils.py +33 -11
  9. octavia/amphorae/drivers/keepalived/jinja/jinja_cfg.py +0 -1
  10. octavia/amphorae/drivers/keepalived/jinja/templates/keepalived_base.template +0 -1
  11. octavia/api/common/pagination.py +1 -1
  12. octavia/api/v2/controllers/health_monitor.py +3 -1
  13. octavia/api/v2/controllers/load_balancer.py +7 -0
  14. octavia/api/v2/controllers/member.py +12 -2
  15. octavia/common/clients.py +7 -1
  16. octavia/common/constants.py +3 -3
  17. octavia/controller/worker/v2/controller_worker.py +2 -2
  18. octavia/controller/worker/v2/flows/amphora_flows.py +14 -3
  19. octavia/controller/worker/v2/flows/flow_utils.py +6 -4
  20. octavia/controller/worker/v2/flows/listener_flows.py +17 -5
  21. octavia/controller/worker/v2/tasks/database_tasks.py +10 -6
  22. octavia/controller/worker/v2/tasks/network_tasks.py +12 -13
  23. octavia/db/base_models.py +16 -4
  24. octavia/network/drivers/neutron/allowed_address_pairs.py +3 -2
  25. octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +1 -1
  26. octavia/tests/functional/api/v2/test_health_monitor.py +18 -0
  27. octavia/tests/functional/api/v2/test_member.py +32 -0
  28. octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py +1 -1
  29. octavia/tests/unit/amphorae/backends/agent/api_server/test_plug.py +4 -3
  30. octavia/tests/unit/amphorae/backends/agent/api_server/test_util.py +89 -1
  31. octavia/tests/unit/amphorae/backends/utils/test_interface.py +3 -64
  32. octavia/tests/unit/amphorae/backends/utils/test_nftable_utils.py +28 -22
  33. octavia/tests/unit/amphorae/drivers/keepalived/jinja/test_jinja_cfg.py +0 -4
  34. octavia/tests/unit/api/common/test_pagination.py +78 -1
  35. octavia/tests/unit/cmd/test_prometheus_proxy.py +8 -1
  36. octavia/tests/unit/controller/worker/v2/flows/test_listener_flows.py +10 -15
  37. octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +4 -6
  38. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +28 -6
  39. octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +57 -2
  40. octavia/tests/unit/controller/worker/v2/test_controller_worker.py +56 -1
  41. octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +2 -1
  42. {octavia-14.0.0.dist-info → octavia-14.0.1.dist-info}/AUTHORS +5 -0
  43. octavia-14.0.1.dist-info/METADATA +156 -0
  44. {octavia-14.0.0.dist-info → octavia-14.0.1.dist-info}/RECORD +59 -59
  45. {octavia-14.0.0.dist-info → octavia-14.0.1.dist-info}/WHEEL +1 -1
  46. {octavia-14.0.0.dist-info → octavia-14.0.1.dist-info}/entry_points.txt +0 -1
  47. octavia-14.0.1.dist-info/pbr.json +1 -0
  48. octavia-14.0.0.dist-info/METADATA +0 -158
  49. octavia-14.0.0.dist-info/pbr.json +0 -1
  50. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/LICENSE +0 -0
  51. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/README.rst +0 -0
  52. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/diskimage-create/README.rst +0 -0
  53. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
  54. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
  55. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
  56. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
  57. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/diskimage-create/tox.ini +0 -0
  58. {octavia-14.0.0.data → octavia-14.0.1.data}/data/share/octavia/diskimage-create/version.txt +0 -0
  59. {octavia-14.0.0.data → octavia-14.0.1.data}/scripts/octavia-wsgi +0 -0
  60. {octavia-14.0.0.dist-info → octavia-14.0.1.dist-info}/LICENSE +0 -0
  61. {octavia-14.0.0.dist-info → octavia-14.0.1.dist-info}/top_level.txt +0 -0
@@ -103,6 +103,16 @@ class TestPaginationHelper(base.TestCase):
103
103
  helper.apply(query_mock, models.LoadBalancer)
104
104
  self.assertEqual(params, helper.filters)
105
105
 
106
+ @mock.patch('octavia.api.common.pagination.request')
107
+ def test_filter_with_booleans(self, request_mock):
108
+ params = {'backup': 'True', 'admin_state_up': 'false'}
109
+ expected_params = {'backup': True, 'enabled': False}
110
+ helper = pagination.PaginationHelper(params)
111
+ query_mock = mock.MagicMock()
112
+
113
+ helper.apply(query_mock, models.Member)
114
+ self.assertEqual(expected_params, helper.filters)
115
+
106
116
  @mock.patch('octavia.api.common.pagination.request')
107
117
  def test_filter_mismatched_params(self, request_mock):
108
118
  params = {
@@ -227,12 +237,46 @@ class TestPaginationHelper(base.TestCase):
227
237
  helper = pagination.PaginationHelper(params)
228
238
  links = helper._make_links(model_list)
229
239
  self.assertEqual(links[0].rel, "previous")
240
+ self.assertEqual(
241
+ links[0].href,
242
+ ("{base_uri}{path}?limit={limit}&marker={marker}"
243
+ "&page_reverse=True").format(
244
+ base_uri=api_base_uri,
245
+ path=request_mock.path,
246
+ limit=params['limit'],
247
+ marker=member1.id
248
+ ))
249
+ self.assertEqual(links[1].rel, "next")
230
250
  self.assertEqual(
231
251
  links[1].href,
232
252
  "{base_uri}{path}?limit={limit}&marker={marker}".format(
233
253
  base_uri=api_base_uri,
234
254
  path=request_mock.path,
235
255
  limit=params['limit'],
256
+ marker=member1.id))
257
+
258
+ @mock.patch('octavia.api.common.pagination.request')
259
+ def test_make_links_with_zero_limit(self, request_mock):
260
+ request_mock.path = "/lbaas/v2/pools/1/members"
261
+ request_mock.path_url = "http://localhost" + request_mock.path
262
+ api_base_uri = "https://127.0.0.1"
263
+ conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
264
+ conf.config(group='api_settings', api_base_uri=api_base_uri)
265
+ member1 = models.Member()
266
+ member1.id = uuidutils.generate_uuid()
267
+ model_list = [member1]
268
+
269
+ params = {'limit': 0, 'marker': member1.id}
270
+ helper = pagination.PaginationHelper(params)
271
+ links = helper._make_links(model_list)
272
+ self.assertEqual(links[0].rel, "previous")
273
+ self.assertEqual(
274
+ links[0].href,
275
+ ("{base_uri}{path}?limit={limit}&marker={marker}"
276
+ "&page_reverse=True").format(
277
+ base_uri=api_base_uri,
278
+ path=request_mock.path,
279
+ limit=None,
236
280
  marker=member1.id
237
281
  ))
238
282
  self.assertEqual(links[1].rel, "next")
@@ -241,5 +285,38 @@ class TestPaginationHelper(base.TestCase):
241
285
  "{base_uri}{path}?limit={limit}&marker={marker}".format(
242
286
  base_uri=api_base_uri,
243
287
  path=request_mock.path,
244
- limit=params['limit'],
288
+ limit=None,
289
+ marker=member1.id))
290
+
291
+ @mock.patch('octavia.api.common.pagination.request')
292
+ def test_make_links_with_negative_limit(self, request_mock):
293
+ request_mock.path = "/lbaas/v2/pools/1/members"
294
+ request_mock.path_url = "http://localhost" + request_mock.path
295
+ api_base_uri = "https://127.0.0.1"
296
+ conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
297
+ conf.config(group='api_settings', api_base_uri=api_base_uri)
298
+ member1 = models.Member()
299
+ member1.id = uuidutils.generate_uuid()
300
+ model_list = [member1]
301
+
302
+ params = {'limit': -1, 'marker': member1.id}
303
+ helper = pagination.PaginationHelper(params)
304
+ links = helper._make_links(model_list)
305
+ self.assertEqual(links[0].rel, "previous")
306
+ self.assertEqual(
307
+ links[0].href,
308
+ ("{base_uri}{path}?limit={limit}&marker={marker}"
309
+ "&page_reverse=True").format(
310
+ base_uri=api_base_uri,
311
+ path=request_mock.path,
312
+ limit=None,
313
+ marker=member1.id
314
+ ))
315
+ self.assertEqual(links[1].rel, "next")
316
+ self.assertEqual(
317
+ links[1].href,
318
+ "{base_uri}{path}?limit={limit}&marker={marker}".format(
319
+ base_uri=api_base_uri,
320
+ path=request_mock.path,
321
+ limit=None,
245
322
  marker=member1.id))
@@ -147,6 +147,7 @@ class TestPrometheusProxyCMD(base.TestCase):
147
147
  mock_http.shutdown.assert_called_once()
148
148
 
149
149
  @mock.patch('threading.Thread')
150
+ @mock.patch('http.server.ThreadingHTTPServer.__init__')
150
151
  @mock.patch('http.server.ThreadingHTTPServer.serve_forever')
151
152
  @mock.patch('octavia.amphorae.backends.utils.network_namespace.'
152
153
  'NetworkNamespace.__exit__')
@@ -155,12 +156,18 @@ class TestPrometheusProxyCMD(base.TestCase):
155
156
  @mock.patch('octavia.cmd.prometheus_proxy.EXIT_EVENT')
156
157
  @mock.patch('octavia.cmd.prometheus_proxy.SignalHandler')
157
158
  def test_main(self, mock_signal_handler, mock_exit_event, mock_netns_enter,
158
- mock_netns_exit, mock_serve_forever, mock_thread):
159
+ mock_netns_exit, mock_serve_forever, mock_server_init,
160
+ mock_thread):
159
161
 
160
162
  mock_exit_event.is_set.side_effect = [False, False, True]
161
163
  mock_netns_enter.side_effect = [Exception('boom'), True]
162
164
 
165
+ mock_server_init.return_value = None
166
+
163
167
  prometheus_proxy.main()
164
168
 
165
169
  mock_signal_handler.assert_called_once()
170
+ mock_server_init.assert_called_once_with(
171
+ ('127.0.0.1', 9102),
172
+ prometheus_proxy.PrometheusProxy)
166
173
  mock_serve_forever.assert_called_once()
@@ -44,15 +44,14 @@ class TestListenerFlows(base.TestCase):
44
44
 
45
45
  self.assertIn(constants.LISTENERS, listener_flow.requires)
46
46
  self.assertIn(constants.LOADBALANCER_ID, listener_flow.requires)
47
- self.assertIn(constants.AMPHORAE_STATUS, listener_flow.requires)
48
47
 
49
48
  self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
50
49
  listener_flow.provides)
51
50
  self.assertIn(constants.AMPHORAE, listener_flow.provides)
52
51
  self.assertIn(constants.AMPHORA_FIREWALL_RULES, listener_flow.provides)
53
52
 
54
- self.assertEqual(3, len(listener_flow.requires))
55
- self.assertEqual(3, len(listener_flow.provides))
53
+ self.assertEqual(2, len(listener_flow.requires))
54
+ self.assertEqual(4, len(listener_flow.provides))
56
55
 
57
56
  def test_get_delete_listener_flow(self, mock_get_net_driver):
58
57
  flavor_dict = {
@@ -66,15 +65,14 @@ class TestListenerFlows(base.TestCase):
66
65
  self.assertIn(constants.LISTENER, listener_flow.requires)
67
66
  self.assertIn(constants.LOADBALANCER_ID, listener_flow.requires)
68
67
  self.assertIn(constants.PROJECT_ID, listener_flow.requires)
69
- self.assertIn(constants.AMPHORAE_STATUS, listener_flow.requires)
70
68
 
71
69
  self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
72
70
  listener_flow.provides)
73
71
  self.assertIn(constants.AMPHORAE, listener_flow.provides)
74
72
  self.assertIn(constants.AMPHORA_FIREWALL_RULES, listener_flow.provides)
75
73
 
76
- self.assertEqual(4, len(listener_flow.requires))
77
- self.assertEqual(3, len(listener_flow.provides))
74
+ self.assertEqual(3, len(listener_flow.requires))
75
+ self.assertEqual(4, len(listener_flow.provides))
78
76
 
79
77
  def test_get_delete_listener_internal_flow(self, mock_get_net_driver):
80
78
  flavor_dict = {
@@ -88,15 +86,14 @@ class TestListenerFlows(base.TestCase):
88
86
 
89
87
  self.assertIn(constants.LOADBALANCER_ID, listener_flow.requires)
90
88
  self.assertIn(constants.PROJECT_ID, listener_flow.requires)
91
- self.assertIn(constants.AMPHORAE_STATUS, listener_flow.requires)
92
89
 
93
90
  self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
94
91
  listener_flow.provides)
95
92
  self.assertIn(constants.AMPHORAE, listener_flow.provides)
96
93
  self.assertIn(constants.AMPHORA_FIREWALL_RULES, listener_flow.provides)
97
94
 
98
- self.assertEqual(3, len(listener_flow.requires))
99
- self.assertEqual(3, len(listener_flow.provides))
95
+ self.assertEqual(2, len(listener_flow.requires))
96
+ self.assertEqual(4, len(listener_flow.provides))
100
97
 
101
98
  def test_get_update_listener_flow(self, mock_get_net_driver):
102
99
  flavor_dict = {
@@ -112,15 +109,14 @@ class TestListenerFlows(base.TestCase):
112
109
  self.assertIn(constants.UPDATE_DICT, listener_flow.requires)
113
110
  self.assertIn(constants.LISTENERS, listener_flow.requires)
114
111
  self.assertIn(constants.LOADBALANCER_ID, listener_flow.requires)
115
- self.assertIn(constants.AMPHORAE_STATUS, listener_flow.requires)
116
112
 
117
113
  self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
118
114
  listener_flow.provides)
119
115
  self.assertIn(constants.AMPHORAE, listener_flow.provides)
120
116
  self.assertIn(constants.AMPHORA_FIREWALL_RULES, listener_flow.provides)
121
117
 
122
- self.assertEqual(5, len(listener_flow.requires))
123
- self.assertEqual(3, len(listener_flow.provides))
118
+ self.assertEqual(4, len(listener_flow.requires))
119
+ self.assertEqual(4, len(listener_flow.provides))
124
120
 
125
121
  def test_get_create_all_listeners_flow(self, mock_get_net_driver):
126
122
  flavor_dict = {
@@ -131,12 +127,11 @@ class TestListenerFlows(base.TestCase):
131
127
  self.assertIsInstance(listeners_flow, flow.Flow)
132
128
  self.assertIn(constants.LOADBALANCER, listeners_flow.requires)
133
129
  self.assertIn(constants.LOADBALANCER_ID, listeners_flow.requires)
134
- self.assertIn(constants.AMPHORAE_STATUS, listeners_flow.requires)
135
130
  self.assertIn(constants.LOADBALANCER, listeners_flow.provides)
136
131
  self.assertIn(constants.AMPHORAE_NETWORK_CONFIG,
137
132
  listeners_flow.provides)
138
133
  self.assertIn(constants.AMPHORAE, listeners_flow.provides)
139
134
  self.assertIn(constants.AMPHORA_FIREWALL_RULES,
140
135
  listeners_flow.provides)
141
- self.assertEqual(3, len(listeners_flow.requires))
142
- self.assertEqual(5, len(listeners_flow.provides))
136
+ self.assertEqual(2, len(listeners_flow.requires))
137
+ self.assertEqual(6, len(listeners_flow.provides))
@@ -344,7 +344,6 @@ class TestLoadBalancerFlows(base.TestCase):
344
344
  self.assertIn(constants.FLAVOR, failover_flow.requires)
345
345
  self.assertIn(constants.LOADBALANCER, failover_flow.requires)
346
346
  self.assertIn(constants.LOADBALANCER_ID, failover_flow.requires)
347
- self.assertIn(constants.AMPHORAE_STATUS, failover_flow.requires)
348
347
 
349
348
  self.assertIn(constants.UPDATED_PORTS, failover_flow.provides)
350
349
  self.assertIn(constants.AMPHORA, failover_flow.provides)
@@ -364,9 +363,9 @@ class TestLoadBalancerFlows(base.TestCase):
364
363
  self.assertIn(constants.SUBNET, failover_flow.provides)
365
364
  self.assertIn(constants.NEW_AMPHORAE, failover_flow.provides)
366
365
 
367
- self.assertEqual(7, len(failover_flow.requires),
366
+ self.assertEqual(6, len(failover_flow.requires),
368
367
  failover_flow.requires)
369
- self.assertEqual(16, len(failover_flow.provides),
368
+ self.assertEqual(17, len(failover_flow.provides),
370
369
  failover_flow.provides)
371
370
 
372
371
  @mock.patch('octavia.common.rpc.NOTIFIER',
@@ -424,7 +423,6 @@ class TestLoadBalancerFlows(base.TestCase):
424
423
  self.assertIn(constants.FLAVOR, failover_flow.requires)
425
424
  self.assertIn(constants.LOADBALANCER, failover_flow.requires)
426
425
  self.assertIn(constants.LOADBALANCER_ID, failover_flow.requires)
427
- self.assertIn(constants.AMPHORAE_STATUS, failover_flow.requires)
428
426
 
429
427
  self.assertIn(constants.UPDATED_PORTS, failover_flow.provides)
430
428
  self.assertIn(constants.AMPHORA, failover_flow.provides)
@@ -445,9 +443,9 @@ class TestLoadBalancerFlows(base.TestCase):
445
443
  self.assertIn(constants.SUBNET, failover_flow.provides)
446
444
  self.assertIn(constants.NEW_AMPHORAE, failover_flow.provides)
447
445
 
448
- self.assertEqual(7, len(failover_flow.requires),
446
+ self.assertEqual(6, len(failover_flow.requires),
449
447
  failover_flow.requires)
450
- self.assertEqual(16, len(failover_flow.provides),
448
+ self.assertEqual(17, len(failover_flow.provides),
451
449
  failover_flow.provides)
452
450
 
453
451
  @mock.patch('octavia.common.rpc.NOTIFIER',
@@ -184,7 +184,9 @@ class TestDatabaseTasks(base.TestCase):
184
184
 
185
185
  @mock.patch('octavia.db.repositories.AmphoraRepository.create',
186
186
  return_value=_db_amphora_mock)
187
+ @mock.patch('octavia.db.repositories.AmphoraHealthRepository.delete')
187
188
  def test_create_amphora_in_db(self,
189
+ mock_amphora_health_repo_delete,
188
190
  mock_create,
189
191
  mock_generate_uuid,
190
192
  mock_LOG,
@@ -210,23 +212,43 @@ class TestDatabaseTasks(base.TestCase):
210
212
 
211
213
  # Test the revert
212
214
  create_amp_in_db.revert(_tf_failure_mock)
213
- self.assertFalse(mock_amphora_repo_delete.called)
215
+ mock_amphora_repo_delete.assert_not_called()
216
+ mock_amphora_health_repo_delete.assert_not_called()
214
217
 
218
+ amp_id = 'AMP'
215
219
  mock_amphora_repo_delete.reset_mock()
216
- create_amp_in_db.revert(result='AMP')
220
+ mock_amphora_health_repo_delete.reset_mock()
221
+ create_amp_in_db.revert(result=amp_id)
217
222
  self.assertTrue(mock_amphora_repo_delete.called)
223
+ self.assertTrue(mock_amphora_health_repo_delete.called)
218
224
  mock_amphora_repo_delete.assert_called_once_with(
219
225
  mock_session,
220
- id='AMP')
226
+ id=amp_id)
227
+ mock_amphora_health_repo_delete.assert_called_once_with(
228
+ mock_session,
229
+ amphora_id=amp_id)
230
+ mock_LOG.error.assert_not_called()
231
+ mock_LOG.debug.assert_not_called()
221
232
 
222
233
  # Test revert with exception
223
234
  mock_amphora_repo_delete.reset_mock()
224
- mock_amphora_repo_delete.side_effect = Exception('fail')
225
- create_amp_in_db.revert(result='AMP')
235
+ mock_amphora_health_repo_delete.reset_mock()
236
+ err1_msg, err2_msg = ('fail', 'fail2')
237
+ mock_amphora_repo_delete.side_effect = Exception(err1_msg)
238
+ mock_amphora_health_repo_delete.side_effect = Exception(err2_msg)
239
+ create_amp_in_db.revert(result=amp_id)
226
240
  self.assertTrue(mock_amphora_repo_delete.called)
241
+ self.assertTrue(mock_amphora_health_repo_delete.called)
227
242
  mock_amphora_repo_delete.assert_called_once_with(
228
243
  mock_session,
229
- id='AMP')
244
+ id=amp_id)
245
+ mock_amphora_health_repo_delete.assert_called_once_with(
246
+ mock_session,
247
+ amphora_id=amp_id)
248
+ mock_LOG.error.assert_called_once_with(
249
+ "Failed to delete amphora %(amp)s "
250
+ "in the database due to: "
251
+ "%(except)s", {'amp': amp_id, 'except': err1_msg})
230
252
 
231
253
  @mock.patch('octavia.db.repositories.ListenerRepository.delete')
232
254
  def test_delete_listener_in_db(self,
@@ -1526,6 +1526,57 @@ class TestNetworkTasks(base.TestCase):
1526
1526
  mock_driver.unplug_aap_port.assert_called_once_with(
1527
1527
  LB.vip, self.db_amphora_mock, mockSubnet)
1528
1528
 
1529
+ @mock.patch('octavia.db.repositories.AmphoraRepository.get')
1530
+ @mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
1531
+ @mock.patch('octavia.db.api.get_session', return_value=_session_mock)
1532
+ def test_revert_plug_vip_amphora_subnet_not_found(
1533
+ self, mock_session, mock_lb_get, mock_get, mock_get_net_driver):
1534
+ mock_driver = mock.MagicMock()
1535
+ mock_lb_get.return_value = LB
1536
+ mock_get.return_value = self.db_amphora_mock
1537
+ mock_get_net_driver.return_value = mock_driver
1538
+ net = network_tasks.PlugVIPAmphora()
1539
+ amphora = {constants.ID: AMPHORA_ID,
1540
+ constants.LB_NETWORK_IP: IP_ADDRESS}
1541
+ subnet = {constants.ID: SUBNET_ID}
1542
+ err_msg = 'Subnet not found'
1543
+ mock_driver.get_subnet.side_effect = net_base.SubnetNotFound(err_msg)
1544
+ result = AMPS_DATA[0].to_dict()
1545
+ net.revert(result, self.load_balancer_mock, amphora, subnet)
1546
+ mock_driver.unplug_aap_port.assert_not_called()
1547
+ network_tasks.LOG.error.assert_called_once_with(
1548
+ 'Failed to unplug AAP port for load balancer: %s. '
1549
+ 'Resources may still be in use for VRRP port: %s. '
1550
+ 'Due to error: %s',
1551
+ self.load_balancer_mock[constants.LOADBALANCER_ID],
1552
+ result[constants.VRRP_PORT_ID], err_msg
1553
+ )
1554
+
1555
+ @mock.patch('octavia.db.repositories.AmphoraRepository.get')
1556
+ @mock.patch('octavia.db.repositories.LoadBalancerRepository.get')
1557
+ @mock.patch('octavia.db.api.get_session', return_value=_session_mock)
1558
+ def test_revert_plug_vip_amphora_raise_db_error(
1559
+ self, mock_session, mock_lb_get, mock_get, mock_get_net_driver):
1560
+ mock_driver = mock.MagicMock()
1561
+ mock_lb_get.return_value = LB
1562
+ err_msg = 'Some Error'
1563
+ mock_get.side_effect = Exception(err_msg)
1564
+ net = network_tasks.PlugVIPAmphora()
1565
+ amphora = {constants.ID: AMPHORA_ID,
1566
+ constants.LB_NETWORK_IP: IP_ADDRESS}
1567
+ subnet = {constants.ID: SUBNET_ID}
1568
+ result = AMPS_DATA[0].to_dict()
1569
+ net.revert(result, self.load_balancer_mock, amphora, subnet)
1570
+ mock_driver.unplug_aap_port.assert_not_called()
1571
+ mock_lb_get.assert_not_called()
1572
+ network_tasks.LOG.error.assert_called_once_with(
1573
+ 'Failed to unplug AAP port for load balancer: %s. '
1574
+ 'Resources may still be in use for VRRP port: %s. '
1575
+ 'Due to error: %s',
1576
+ self.load_balancer_mock[constants.LOADBALANCER_ID],
1577
+ result[constants.VRRP_PORT_ID], err_msg
1578
+ )
1579
+
1529
1580
  @mock.patch('octavia.controller.worker.v2.tasks.network_tasks.DeletePort.'
1530
1581
  'update_progress')
1531
1582
  def test_delete_port(self, mock_update_progress, mock_get_net_driver):
@@ -1670,7 +1721,11 @@ class TestNetworkTasks(base.TestCase):
1670
1721
  # Test revert
1671
1722
  mock_driver.reset_mock()
1672
1723
 
1673
- net_task.revert([port_mock], vip_dict, VIP_SG_ID, AMP_ID,
1724
+ # The execute path generates a port dict, so this will be the result
1725
+ # passed into the revert method by Taskflow
1726
+ port_dict = {constants.ID: PORT_ID}
1727
+
1728
+ net_task.revert(port_dict, vip_dict, VIP_SG_ID, AMP_ID,
1674
1729
  additional_vips)
1675
1730
 
1676
1731
  mock_driver.delete_port.assert_called_once_with(PORT_ID)
@@ -1678,7 +1733,7 @@ class TestNetworkTasks(base.TestCase):
1678
1733
  # Test revert exception
1679
1734
  mock_driver.reset_mock()
1680
1735
 
1681
- net_task.revert([port_mock], vip_dict, VIP_SG_ID, AMP_ID,
1736
+ net_task.revert(port_dict, vip_dict, VIP_SG_ID, AMP_ID,
1682
1737
  additional_vips)
1683
1738
 
1684
1739
  mock_driver.delete_port.assert_called_once_with(PORT_ID)
@@ -27,7 +27,7 @@ from octavia.controller.worker.v2 import controller_worker
27
27
  from octavia.controller.worker.v2.flows import flow_utils
28
28
  import octavia.tests.unit.base as base
29
29
 
30
-
30
+ TLS_CERT_ID = uuidutils.generate_uuid()
31
31
  AMP_ID = uuidutils.generate_uuid()
32
32
  LB_ID = uuidutils.generate_uuid()
33
33
  LISTENER_ID = uuidutils.generate_uuid()
@@ -804,6 +804,61 @@ class TestControllerWorker(base.TestCase):
804
804
  })
805
805
  )
806
806
 
807
+ @mock.patch(
808
+ "octavia.common.tls_utils.cert_parser.load_certificates_data",
809
+ side_effect=RuntimeError
810
+ )
811
+ def test_delete_load_balancer_with_cascade_tls_unavailable(
812
+ self,
813
+ mock_load_tls_cert,
814
+ mock_api_get_session,
815
+ mock_dyn_log_listener,
816
+ mock_taskflow_load,
817
+ mock_pool_repo_get,
818
+ mock_member_repo_get,
819
+ mock_l7rule_repo_get,
820
+ mock_l7policy_repo_get,
821
+ mock_listener_repo_get,
822
+ mock_lb_repo_get,
823
+ mock_health_mon_repo_get,
824
+ mock_amp_repo_get
825
+ ):
826
+ _flow_mock.reset_mock()
827
+
828
+ _listener_mock.tls_certificate_id = TLS_CERT_ID
829
+ _listener_mock.to_dict.return_value[
830
+ constants.TLS_CERTIFICATE_ID] = TLS_CERT_ID
831
+
832
+ cw = controller_worker.ControllerWorker()
833
+ cw.delete_load_balancer(_load_balancer_mock, cascade=True)
834
+
835
+ mock_lb_repo_get.assert_called_once_with(
836
+ _db_session,
837
+ id=LB_ID)
838
+
839
+ # Check load_certificates_data called and error is raised
840
+ # Error must be ignored because it is not critical for current flow
841
+ mock_load_tls_cert.assert_called_once()
842
+
843
+ listener_list = [{constants.LISTENER_ID: LISTENER_ID,
844
+ constants.LOADBALANCER_ID: LB_ID,
845
+ constants.PROJECT_ID: PROJECT_ID,
846
+ "default_tls_container_ref": TLS_CERT_ID}]
847
+
848
+ (cw.services_controller.run_poster.
849
+ assert_called_once_with(
850
+ flow_utils.get_cascade_delete_load_balancer_flow,
851
+ _load_balancer_mock, listener_list, [],
852
+ store={constants.LOADBALANCER: _load_balancer_mock,
853
+ constants.LOADBALANCER_ID: LB_ID,
854
+ constants.SERVER_GROUP_ID:
855
+ _db_load_balancer_mock.server_group_id,
856
+ constants.PROJECT_ID: _db_load_balancer_mock.project_id,
857
+ })
858
+ )
859
+
860
+ _listener_mock.reset_mock()
861
+
807
862
  @mock.patch('octavia.db.repositories.ListenerRepository.get_all',
808
863
  return_value=([_listener_mock], None))
809
864
  def test_update_load_balancer(self,
@@ -1071,7 +1071,8 @@ class TestAllowedAddressPairsDriver(base.TestCase):
1071
1071
  fake_rules = [
1072
1072
  {'id': 'rule-80', 'port_range_max': 80, 'protocol': 'tcp',
1073
1073
  'remote_ip_prefix': '10.0.101.0/24'},
1074
- {'id': 'rule-22', 'port_range_max': 22, 'protocol': 'tcp'}
1074
+ {'id': 'rule-22', 'port_range_max': 22, 'protocol': 'tcp'},
1075
+ {'id': 'rule-None', 'port_range_max': 22},
1075
1076
  ]
1076
1077
  list_rules = self.driver.network_proxy.security_group_rules
1077
1078
  list_rules.return_value = fake_rules
@@ -69,6 +69,7 @@ Elena Ezhova <eezhova@mirantis.com>
69
69
  EranRaichstein <eranra@il.ibm.com>
70
70
  Erik Olof Gunnar Andersson <eandersson@blizzard.com>
71
71
  Evan Gray <evanscottgray@gmail.com>
72
+ Evgeniy Bykov <chypakabre@gmail.com>
72
73
  Evgeny Fedoruk <evgenyf@radware.com>
73
74
  Fei Long Wang <flwang@catalyst.net.nz>
74
75
  Fernando Royo <froyo@redhat.com>
@@ -101,6 +102,7 @@ Hongbin Lu <hongbin.lu@huawei.com>
101
102
  Ian Wienand <iwienand@redhat.com>
102
103
  Ihar Hrachyshka <ihrachys@redhat.com>
103
104
  Ildar Iskhakov <iiskhako@cisco.com>
105
+ Ilia Kerbs <ikerbs@protonmail.com>
104
106
  Itzik Brown <itzikb@redhat.com>
105
107
  Jacky Hu <hudayou@hotmail.com>
106
108
  James Arendt <james.arendt@hp.com>
@@ -145,6 +147,7 @@ Martin Chlumsky <martin.chlumsky@ubisoft.com>
145
147
  Masayuki Igawa <masayuki@igawa.io>
146
148
  Matt Alline <matt.alline@gmail.com>
147
149
  Maximilian Stinsky <maximilian.stinsky@gec.io>
150
+ Michael Johnson <johnosmor@gmail.com>
148
151
  Michael Johnson <johnsom@hp.com>
149
152
  Michael Johnson <johnsomor@gmail.com>
150
153
  Michal Arbet <michal.arbet@ultimum.io>
@@ -188,6 +191,8 @@ Santhosh Fernandes <santhosh.fernandes@gmail.com>
188
191
  Sean McGinnis <sean.mcginnis@gmail.com>
189
192
  Selvakumar S <selvakumar.s2@hp.com>
190
193
  Sergey Belous <sbelous@mirantis.com>
194
+ Sergey Kraynev <sergejyit@gmail.com>
195
+ Seunghun Lee <seunghun@stackhpc.com>
191
196
  ShangXiao <shangxiaobj@inspur.com>
192
197
  Shashank Kumar Shankar <shashank.kumar.shankar@intel.com>
193
198
  Sherif Abdelwahab <sherif.abdelwahab@hp.com>
@@ -0,0 +1,156 @@
1
+ Metadata-Version: 2.1
2
+ Name: octavia
3
+ Version: 14.0.1
4
+ Summary: OpenStack Octavia Scalable Load Balancer as a Service
5
+ Home-page: https://docs.openstack.org/octavia/latest/
6
+ Author: OpenStack
7
+ Author-email: openstack-discuss@lists.openstack.org
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Environment :: OpenStack
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Information Technology
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Requires-Python: >=3.8
22
+ License-File: LICENSE
23
+ License-File: AUTHORS
24
+ Requires-Dist: alembic >=0.9.6
25
+ Requires-Dist: cotyledon >=1.3.0
26
+ Requires-Dist: pecan >=1.3.2
27
+ Requires-Dist: pbr >=3.1.1
28
+ Requires-Dist: SQLAlchemy >=1.2.19
29
+ Requires-Dist: SQLAlchemy-Utils >=0.30.11
30
+ Requires-Dist: futurist >=1.2.0
31
+ Requires-Dist: requests >=2.23.0
32
+ Requires-Dist: rfc3986 >=1.2.0
33
+ Requires-Dist: keystoneauth1 >=3.4.0
34
+ Requires-Dist: keystonemiddleware >=9.5.0
35
+ Requires-Dist: WebOb >=1.8.2
36
+ Requires-Dist: stevedore >=1.20.0
37
+ Requires-Dist: openstacksdk >=0.103.0
38
+ Requires-Dist: oslo.config >=6.8.0
39
+ Requires-Dist: oslo.context >=2.22.0
40
+ Requires-Dist: oslo.db[mysql] >=8.4.0
41
+ Requires-Dist: oslo.i18n >=3.20.0
42
+ Requires-Dist: oslo.log >=4.3.0
43
+ Requires-Dist: oslo.messaging >=14.1.0
44
+ Requires-Dist: oslo.middleware >=4.0.1
45
+ Requires-Dist: oslo.policy >=3.7.0
46
+ Requires-Dist: oslo.reports >=1.18.0
47
+ Requires-Dist: oslo.serialization >=2.28.1
48
+ Requires-Dist: oslo.upgradecheck >=1.3.0
49
+ Requires-Dist: oslo.utils >=4.7.0
50
+ Requires-Dist: psutil >=5.7.1
51
+ Requires-Dist: pyasn1 !=0.2.3,>=0.1.8
52
+ Requires-Dist: pyasn1-modules >=0.0.6
53
+ Requires-Dist: python-barbicanclient >=4.5.2
54
+ Requires-Dist: python-glanceclient >=2.8.0
55
+ Requires-Dist: python-novaclient >=9.1.0
56
+ Requires-Dist: python-cinderclient >=3.3.0
57
+ Requires-Dist: WSME >=0.8.0
58
+ Requires-Dist: Jinja2 >=2.10
59
+ Requires-Dist: taskflow >=5.5.0
60
+ Requires-Dist: castellan >=0.16.0
61
+ Requires-Dist: tenacity >=5.0.4
62
+ Requires-Dist: distro >=1.2.0
63
+ Requires-Dist: jsonschema >=3.2.0
64
+ Requires-Dist: octavia-lib >=3.3.0
65
+ Requires-Dist: simplejson >=3.13.2
66
+ Requires-Dist: setproctitle >=1.1.10
67
+ Requires-Dist: python-dateutil >=2.7.0
68
+ Requires-Dist: Flask !=0.11,>=0.10
69
+ Requires-Dist: cryptography >=3.0
70
+ Requires-Dist: gunicorn >=19.9.0
71
+ Requires-Dist: Werkzeug >=0.14.1
72
+ Requires-Dist: pyroute2 >=0.5.14 ; (sys_platform!='win32')
73
+ Provides-Extra: redis
74
+ Requires-Dist: redis >=3.4.0 ; extra == 'redis'
75
+ Provides-Extra: test
76
+ Requires-Dist: hacking <6.2.0,>=6.1.0 ; extra == 'test'
77
+ Requires-Dist: requests-mock >=1.2.0 ; extra == 'test'
78
+ Requires-Dist: coverage !=4.4,>=4.0 ; extra == 'test'
79
+ Requires-Dist: fixtures >=3.0.0 ; extra == 'test'
80
+ Requires-Dist: flake8-import-order <0.19.0,>=0.18.0 ; extra == 'test'
81
+ Requires-Dist: python-subunit >=1.0.0 ; extra == 'test'
82
+ Requires-Dist: oslotest >=3.2.0 ; extra == 'test'
83
+ Requires-Dist: pylint <3.2.0,>=2.5.3 ; extra == 'test'
84
+ Requires-Dist: testrepository >=0.0.18 ; extra == 'test'
85
+ Requires-Dist: testtools >=2.2.0 ; extra == 'test'
86
+ Requires-Dist: testresources >=2.0.0 ; extra == 'test'
87
+ Requires-Dist: testscenarios >=0.4 ; extra == 'test'
88
+ Requires-Dist: doc8 >=0.6.0 ; extra == 'test'
89
+ Requires-Dist: bandit !=1.6.0,>=1.1.0 ; extra == 'test'
90
+ Requires-Dist: tempest >=23.0.0 ; extra == 'test'
91
+ Requires-Dist: sphinx !=2.1.0,>=2.0.0 ; extra == 'test'
92
+ Requires-Dist: bashate >=0.5.1 ; extra == 'test'
93
+ Requires-Dist: WebTest >=2.0.26 ; extra == 'test'
94
+ Provides-Extra: zookeeper
95
+ Requires-Dist: kazoo >=2.6.0 ; extra == 'zookeeper'
96
+ Requires-Dist: zake >=0.1.6 ; extra == 'zookeeper'
97
+
98
+ ========================
99
+ Team and repository tags
100
+ ========================
101
+
102
+ .. image:: https://governance.openstack.org/tc/badges/octavia.svg
103
+ :target: https://governance.openstack.org/tc/reference/tags/index.html
104
+
105
+ .. Change things from this point on
106
+
107
+ =======
108
+ Octavia
109
+ =======
110
+
111
+ .. image:: https://img.shields.io/pypi/v/octavia.svg
112
+ :target: https://pypi.org/project/octavia/
113
+ :alt: Latest Version
114
+
115
+ Octavia is an operator-grade open source scalable load balancer for use in
116
+ large OpenStack deployments.
117
+
118
+ Octavia provides the load balancing API for OpenStack. It supports multiple
119
+ "provider drivers" that implement load balancing, including the "amphora"
120
+ reference driver included with Octavia.
121
+
122
+ Octavia is distributed under the terms of the Apache License, Version 2.0.
123
+ The full terms and conditions of this license are detailed in the LICENSE
124
+ file.
125
+
126
+ Project resources
127
+ ~~~~~~~~~~~~~~~~~
128
+
129
+ Developer documentation for the Octavia project is available at
130
+ https://docs.openstack.org/octavia/latest/
131
+
132
+ Release notes for the Octavia project are available at
133
+ https://docs.openstack.org/releasenotes/octavia/
134
+
135
+ The project source code repository is located at
136
+ https://opendev.org/openstack/octavia
137
+
138
+ Project status, bugs, and requests for feature enhancements are tracked on
139
+ https://launchpad.net/octavia
140
+
141
+ For more information on project direction and guiding principles for
142
+ contributors, please see the CONSTITUTION.rst file in this directory, or
143
+ specifications in the specs/ sub-directory.
144
+
145
+ The project roadmap is available at
146
+ https://wiki.openstack.org/wiki/Octavia/Roadmap
147
+
148
+ External Resources
149
+ ~~~~~~~~~~~~~~~~~~
150
+
151
+ * Octavia Wiki: https://wiki.openstack.org/wiki/Octavia
152
+
153
+ * For help on usage and hacking of Octavia, please send an email to
154
+ OpenStack-dev Mailing List <mailto:openstack-discuss@lists.openstack.org>
155
+ with **[Octavia]** tag.
156
+