octavia 13.0.0__py3-none-any.whl → 14.0.0__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 (135) hide show
  1. octavia/amphorae/backends/agent/api_server/lvs_listener_base.py +1 -1
  2. octavia/amphorae/backends/agent/api_server/osutils.py +5 -5
  3. octavia/amphorae/backends/agent/api_server/plug.py +3 -2
  4. octavia/amphorae/backends/agent/api_server/rules_schema.py +52 -0
  5. octavia/amphorae/backends/agent/api_server/server.py +28 -1
  6. octavia/amphorae/backends/utils/interface.py +45 -6
  7. octavia/amphorae/backends/utils/interface_file.py +9 -6
  8. octavia/amphorae/backends/utils/nftable_utils.py +125 -0
  9. octavia/amphorae/drivers/driver_base.py +27 -0
  10. octavia/amphorae/drivers/haproxy/rest_api_driver.py +42 -10
  11. octavia/amphorae/drivers/health/heartbeat_udp.py +2 -2
  12. octavia/amphorae/drivers/keepalived/vrrp_rest_driver.py +2 -1
  13. octavia/amphorae/drivers/noop_driver/driver.py +25 -0
  14. octavia/api/app.py +3 -0
  15. octavia/api/common/pagination.py +2 -2
  16. octavia/api/drivers/amphora_driver/flavor_schema.py +6 -1
  17. octavia/api/root_controller.py +4 -1
  18. octavia/api/v2/controllers/health_monitor.py +0 -1
  19. octavia/api/v2/controllers/l7policy.py +0 -1
  20. octavia/api/v2/controllers/l7rule.py +0 -1
  21. octavia/api/v2/controllers/listener.py +0 -1
  22. octavia/api/v2/controllers/load_balancer.py +13 -7
  23. octavia/api/v2/controllers/member.py +6 -3
  24. octavia/api/v2/controllers/pool.py +6 -7
  25. octavia/api/v2/types/load_balancer.py +5 -1
  26. octavia/api/v2/types/pool.py +1 -1
  27. octavia/certificates/common/pkcs12.py +9 -9
  28. octavia/certificates/manager/barbican.py +24 -16
  29. octavia/certificates/manager/castellan_mgr.py +12 -7
  30. octavia/certificates/manager/local.py +4 -4
  31. octavia/certificates/manager/noop.py +106 -0
  32. octavia/cmd/driver_agent.py +1 -1
  33. octavia/cmd/health_checker.py +0 -4
  34. octavia/cmd/health_manager.py +1 -5
  35. octavia/cmd/house_keeping.py +1 -1
  36. octavia/cmd/interface.py +0 -4
  37. octavia/cmd/octavia_worker.py +0 -4
  38. octavia/cmd/prometheus_proxy.py +0 -5
  39. octavia/cmd/status.py +0 -6
  40. octavia/common/base_taskflow.py +1 -1
  41. octavia/common/clients.py +15 -3
  42. octavia/common/config.py +24 -6
  43. octavia/common/constants.py +34 -0
  44. octavia/common/data_models.py +3 -1
  45. octavia/common/exceptions.py +11 -0
  46. octavia/common/jinja/haproxy/combined_listeners/templates/macros.j2 +7 -5
  47. octavia/common/keystone.py +7 -7
  48. octavia/common/tls_utils/cert_parser.py +24 -10
  49. octavia/common/utils.py +6 -0
  50. octavia/common/validate.py +2 -2
  51. octavia/compute/drivers/nova_driver.py +23 -5
  52. octavia/controller/worker/task_utils.py +28 -6
  53. octavia/controller/worker/v2/controller_worker.py +49 -15
  54. octavia/controller/worker/v2/flows/amphora_flows.py +120 -21
  55. octavia/controller/worker/v2/flows/flow_utils.py +15 -13
  56. octavia/controller/worker/v2/flows/listener_flows.py +95 -5
  57. octavia/controller/worker/v2/flows/load_balancer_flows.py +74 -30
  58. octavia/controller/worker/v2/taskflow_jobboard_driver.py +17 -1
  59. octavia/controller/worker/v2/tasks/amphora_driver_tasks.py +145 -24
  60. octavia/controller/worker/v2/tasks/compute_tasks.py +1 -1
  61. octavia/controller/worker/v2/tasks/database_tasks.py +72 -41
  62. octavia/controller/worker/v2/tasks/lifecycle_tasks.py +97 -41
  63. octavia/controller/worker/v2/tasks/network_tasks.py +57 -60
  64. octavia/controller/worker/v2/tasks/shim_tasks.py +28 -0
  65. octavia/db/migration/alembic_migrations/versions/55874a4ceed6_add_l7policy_action_redirect_prefix.py +1 -1
  66. octavia/db/migration/alembic_migrations/versions/5a3ee5472c31_add_cert_expiration__infor_in_amphora_table.py +1 -1
  67. octavia/db/migration/alembic_migrations/versions/6742ca1b27c2_add_l7policy_redirect_http_code.py +1 -1
  68. octavia/db/migration/alembic_migrations/versions/db2a73e82626_add_vnic_type_for_vip.py +36 -0
  69. octavia/db/models.py +1 -0
  70. octavia/db/prepare.py +1 -1
  71. octavia/db/repositories.py +53 -34
  72. octavia/distributor/drivers/driver_base.py +1 -1
  73. octavia/network/base.py +3 -16
  74. octavia/network/data_models.py +4 -1
  75. octavia/network/drivers/neutron/allowed_address_pairs.py +27 -26
  76. octavia/network/drivers/noop_driver/driver.py +10 -23
  77. octavia/tests/common/sample_certs.py +115 -0
  78. octavia/tests/common/sample_haproxy_prometheus +1 -1
  79. octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +37 -0
  80. octavia/tests/functional/api/test_healthcheck.py +2 -2
  81. octavia/tests/functional/api/v2/base.py +1 -1
  82. octavia/tests/functional/api/v2/test_listener.py +45 -0
  83. octavia/tests/functional/api/v2/test_load_balancer.py +17 -0
  84. octavia/tests/functional/db/base.py +9 -0
  85. octavia/tests/functional/db/test_models.py +2 -1
  86. octavia/tests/functional/db/test_repositories.py +55 -99
  87. octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py +4 -2
  88. octavia/tests/unit/amphorae/backends/utils/test_interface.py +201 -1
  89. octavia/tests/unit/amphorae/backends/utils/test_keepalivedlvs_query.py +1 -1
  90. octavia/tests/unit/amphorae/backends/utils/test_nftable_utils.py +194 -0
  91. octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver.py +27 -5
  92. octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +15 -2
  93. octavia/tests/unit/amphorae/drivers/keepalived/test_vrrp_rest_driver.py +17 -0
  94. octavia/tests/unit/amphorae/drivers/noop_driver/test_driver.py +2 -1
  95. octavia/tests/unit/api/v2/types/test_pool.py +71 -0
  96. octavia/tests/unit/certificates/manager/test_barbican.py +3 -3
  97. octavia/tests/unit/certificates/manager/test_noop.py +53 -0
  98. octavia/tests/unit/common/jinja/haproxy/combined_listeners/test_jinja_cfg.py +16 -17
  99. octavia/tests/unit/common/sample_configs/sample_configs_combined.py +5 -3
  100. octavia/tests/unit/common/test_config.py +35 -0
  101. octavia/tests/unit/common/test_keystone.py +32 -0
  102. octavia/tests/unit/common/test_utils.py +39 -0
  103. octavia/tests/unit/compute/drivers/test_nova_driver.py +22 -0
  104. octavia/tests/unit/controller/worker/test_task_utils.py +58 -2
  105. octavia/tests/unit/controller/worker/v2/flows/test_amphora_flows.py +28 -5
  106. octavia/tests/unit/controller/worker/v2/flows/test_listener_flows.py +64 -16
  107. octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +49 -9
  108. octavia/tests/unit/controller/worker/v2/tasks/test_amphora_driver_tasks.py +265 -17
  109. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +101 -1
  110. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks_quota.py +19 -19
  111. octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +105 -42
  112. octavia/tests/unit/controller/worker/v2/tasks/test_shim_tasks.py +33 -0
  113. octavia/tests/unit/controller/worker/v2/test_controller_worker.py +85 -42
  114. octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +48 -51
  115. octavia/tests/unit/network/drivers/neutron/test_utils.py +2 -0
  116. octavia/tests/unit/network/drivers/noop_driver/test_driver.py +0 -7
  117. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/README.rst +6 -1
  118. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/diskimage-create.sh +10 -4
  119. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/requirements.txt +0 -2
  120. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/tox.ini +30 -13
  121. {octavia-13.0.0.dist-info → octavia-14.0.0.dist-info}/AUTHORS +5 -0
  122. {octavia-13.0.0.dist-info → octavia-14.0.0.dist-info}/METADATA +6 -6
  123. {octavia-13.0.0.dist-info → octavia-14.0.0.dist-info}/RECORD +134 -126
  124. {octavia-13.0.0.dist-info → octavia-14.0.0.dist-info}/entry_points.txt +1 -1
  125. octavia-14.0.0.dist-info/pbr.json +1 -0
  126. octavia-13.0.0.dist-info/pbr.json +0 -1
  127. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/LICENSE +0 -0
  128. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/README.rst +0 -0
  129. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
  130. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
  131. {octavia-13.0.0.data → octavia-14.0.0.data}/data/share/octavia/diskimage-create/version.txt +0 -0
  132. {octavia-13.0.0.data → octavia-14.0.0.data}/scripts/octavia-wsgi +0 -0
  133. {octavia-13.0.0.dist-info → octavia-14.0.0.dist-info}/LICENSE +0 -0
  134. {octavia-13.0.0.dist-info → octavia-14.0.0.dist-info}/WHEEL +0 -0
  135. {octavia-13.0.0.dist-info → octavia-14.0.0.dist-info}/top_level.txt +0 -0
@@ -270,6 +270,14 @@ class ControllerWorker(object):
270
270
  raise db_exceptions.NoResultFound
271
271
 
272
272
  load_balancer = db_listener.load_balancer
273
+ flavor_dict = {}
274
+ if load_balancer.flavor_id:
275
+ with session.begin():
276
+ flavor_dict = (
277
+ self._flavor_repo.get_flavor_metadata_dict(
278
+ session, load_balancer.flavor_id))
279
+ flavor_dict[constants.LOADBALANCER_TOPOLOGY] = load_balancer.topology
280
+
273
281
  provider_lb = provider_utils.db_loadbalancer_to_provider_loadbalancer(
274
282
  load_balancer).to_dict(recurse=True)
275
283
 
@@ -279,7 +287,7 @@ class ControllerWorker(object):
279
287
 
280
288
  self.run_flow(
281
289
  flow_utils.get_create_listener_flow,
282
- store=store)
290
+ flavor_dict=flavor_dict, store=store)
283
291
 
284
292
  def delete_listener(self, listener):
285
293
  """Deletes a listener.
@@ -288,12 +296,32 @@ class ControllerWorker(object):
288
296
  :returns: None
289
297
  :raises ListenerNotFound: The referenced listener was not found
290
298
  """
299
+ try:
300
+ db_lb = self._get_db_obj_until_pending_update(
301
+ self._lb_repo, listener[constants.LOADBALANCER_ID])
302
+ except tenacity.RetryError as e:
303
+ LOG.warning('Loadbalancer did not go into %s in 60 seconds. '
304
+ 'This either due to an in-progress Octavia upgrade '
305
+ 'or an overloaded and failing database. Assuming '
306
+ 'an upgrade is in progress and continuing.',
307
+ constants.PENDING_UPDATE)
308
+ db_lb = e.last_attempt.result()
309
+
310
+ flavor_dict = {}
311
+ if db_lb.flavor_id:
312
+ session = db_apis.get_session()
313
+ with session.begin():
314
+ flavor_dict = (
315
+ self._flavor_repo.get_flavor_metadata_dict(
316
+ session, db_lb.flavor_id))
317
+ flavor_dict[constants.LOADBALANCER_TOPOLOGY] = db_lb.topology
318
+
291
319
  store = {constants.LISTENER: listener,
292
320
  constants.LOADBALANCER_ID:
293
321
  listener[constants.LOADBALANCER_ID],
294
322
  constants.PROJECT_ID: listener[constants.PROJECT_ID]}
295
323
  self.run_flow(
296
- flow_utils.get_delete_listener_flow,
324
+ flow_utils.get_delete_listener_flow, flavor_dict=flavor_dict,
297
325
  store=store)
298
326
 
299
327
  def update_listener(self, listener, listener_updates):
@@ -315,12 +343,21 @@ class ControllerWorker(object):
315
343
  constants.PENDING_UPDATE)
316
344
  db_lb = e.last_attempt.result()
317
345
 
346
+ session = db_apis.get_session()
347
+ flavor_dict = {}
348
+ if db_lb.flavor_id:
349
+ with session.begin():
350
+ flavor_dict = (
351
+ self._flavor_repo.get_flavor_metadata_dict(
352
+ session, db_lb.flavor_id))
353
+ flavor_dict[constants.LOADBALANCER_TOPOLOGY] = db_lb.topology
354
+
318
355
  store = {constants.LISTENER: listener,
319
356
  constants.UPDATE_DICT: listener_updates,
320
357
  constants.LOADBALANCER_ID: db_lb.id,
321
358
  constants.LISTENERS: [listener]}
322
359
  self.run_flow(
323
- flow_utils.get_update_listener_flow,
360
+ flow_utils.get_update_listener_flow, flavor_dict=flavor_dict,
324
361
  store=store)
325
362
 
326
363
  @tenacity.retry(
@@ -375,7 +412,7 @@ class ControllerWorker(object):
375
412
  }
376
413
  self.run_flow(
377
414
  flow_utils.get_create_load_balancer_flow,
378
- topology, listeners=listeners_dicts,
415
+ topology, listeners=listeners_dicts, flavor_dict=flavor,
379
416
  store=store)
380
417
 
381
418
  def delete_load_balancer(self, load_balancer, cascade=False):
@@ -536,7 +573,7 @@ class ControllerWorker(object):
536
573
  self._member_repo.get(
537
574
  session, id=member[constants.MEMBER_ID])
538
575
  for member in new_members]
539
- # The API may not have commited all of the new member records yet.
576
+ # The API may not have committed all of the new member records yet.
540
577
  # Make sure we retry looking them up.
541
578
  if None in db_new_members or len(db_new_members) != len(new_members):
542
579
  LOG.warning('Failed to fetch one of the new members from DB. '
@@ -998,16 +1035,14 @@ class ControllerWorker(object):
998
1035
  lb_id = loadbalancer.id
999
1036
  # Even if the LB doesn't have a flavor, create one and
1000
1037
  # pass through the topology.
1038
+ flavor_dict = {}
1001
1039
  if loadbalancer.flavor_id:
1002
1040
  with session.begin():
1003
1041
  flavor_dict = (
1004
1042
  self._flavor_repo.get_flavor_metadata_dict(
1005
1043
  session, loadbalancer.flavor_id))
1006
- flavor_dict[constants.LOADBALANCER_TOPOLOGY] = (
1007
- loadbalancer.topology)
1008
- else:
1009
- flavor_dict = {constants.LOADBALANCER_TOPOLOGY:
1010
- loadbalancer.topology}
1044
+ flavor_dict[constants.LOADBALANCER_TOPOLOGY] = (
1045
+ loadbalancer.topology)
1011
1046
  if loadbalancer.availability_zone:
1012
1047
  with session.begin():
1013
1048
  az_metadata = (
@@ -1035,7 +1070,7 @@ class ControllerWorker(object):
1035
1070
 
1036
1071
  self.run_flow(
1037
1072
  flow_utils.get_failover_amphora_flow,
1038
- amphora.to_dict(), lb_amp_count,
1073
+ amphora.to_dict(), lb_amp_count, flavor_dict=flavor_dict,
1039
1074
  store=stored_params)
1040
1075
 
1041
1076
  LOG.info("Successfully completed the failover for an amphora: %s",
@@ -1128,7 +1163,7 @@ class ControllerWorker(object):
1128
1163
 
1129
1164
  :param load_balancer_id: ID for load balancer to failover
1130
1165
  :returns: None
1131
- :raises octavia.commom.exceptions.NotFound: The load balancer was not
1166
+ :raises octavia.common.exceptions.NotFound: The load balancer was not
1132
1167
  found.
1133
1168
  """
1134
1169
  try:
@@ -1162,13 +1197,12 @@ class ControllerWorker(object):
1162
1197
  # We must provide a topology in the flavor definition
1163
1198
  # here for the amphora to be created with the correct
1164
1199
  # configuration.
1200
+ flavor = {}
1165
1201
  if lb.flavor_id:
1166
1202
  with session.begin():
1167
1203
  flavor = self._flavor_repo.get_flavor_metadata_dict(
1168
1204
  session, lb.flavor_id)
1169
- flavor[constants.LOADBALANCER_TOPOLOGY] = lb.topology
1170
- else:
1171
- flavor = {constants.LOADBALANCER_TOPOLOGY: lb.topology}
1205
+ flavor[constants.LOADBALANCER_TOPOLOGY] = lb.topology
1172
1206
 
1173
1207
  if lb:
1174
1208
  provider_lb_dict = (
@@ -28,6 +28,7 @@ from octavia.controller.worker.v2.tasks import database_tasks
28
28
  from octavia.controller.worker.v2.tasks import lifecycle_tasks
29
29
  from octavia.controller.worker.v2.tasks import network_tasks
30
30
  from octavia.controller.worker.v2.tasks import retry_tasks
31
+ from octavia.controller.worker.v2.tasks import shim_tasks
31
32
 
32
33
  CONF = cfg.CONF
33
34
  LOG = logging.getLogger(__name__)
@@ -226,7 +227,8 @@ class AmphoraFlows(object):
226
227
  return delete_amphora_flow
227
228
 
228
229
  def get_vrrp_subflow(self, prefix, timeout_dict=None,
229
- create_vrrp_group=True):
230
+ create_vrrp_group=True,
231
+ get_amphorae_status=True, flavor_dict=None):
230
232
  sf_name = prefix + '-' + constants.GET_VRRP_SUBFLOW
231
233
  vrrp_subflow = linear_flow.Flow(sf_name)
232
234
 
@@ -242,17 +244,29 @@ class AmphoraFlows(object):
242
244
  requires=constants.LOADBALANCER_ID,
243
245
  provides=constants.AMPHORAE_NETWORK_CONFIG))
244
246
 
247
+ if get_amphorae_status:
248
+ # Get the amphorae_status dict in case the caller hasn't fetched
249
+ # it yet.
250
+ vrrp_subflow.add(
251
+ amphora_driver_tasks.AmphoraeGetConnectivityStatus(
252
+ name=constants.AMPHORAE_GET_CONNECTIVITY_STATUS,
253
+ requires=constants.AMPHORAE,
254
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
255
+ inject={constants.TIMEOUT_DICT: timeout_dict},
256
+ provides=constants.AMPHORAE_STATUS))
257
+
245
258
  # VRRP update needs to be run on all amphora to update
246
259
  # their peer configurations. So parallelize this with an
247
260
  # unordered subflow.
248
261
  update_amps_subflow = unordered_flow.Flow('VRRP-update-subflow')
249
262
 
250
- # We have three tasks to run in order, per amphora
263
+ # We have tasks to run in order, per amphora
251
264
  amp_0_subflow = linear_flow.Flow('VRRP-amp-0-update-subflow')
252
265
 
253
266
  amp_0_subflow.add(amphora_driver_tasks.AmphoraIndexUpdateVRRPInterface(
254
267
  name=sf_name + '-0-' + constants.AMP_UPDATE_VRRP_INTF,
255
- requires=constants.AMPHORAE,
268
+ requires=(constants.AMPHORAE, constants.AMPHORAE_STATUS),
269
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
256
270
  inject={constants.AMPHORA_INDEX: 0,
257
271
  constants.TIMEOUT_DICT: timeout_dict},
258
272
  provides=constants.AMP_VRRP_INT))
@@ -261,13 +275,30 @@ class AmphoraFlows(object):
261
275
  name=sf_name + '-0-' + constants.AMP_VRRP_UPDATE,
262
276
  requires=(constants.LOADBALANCER_ID,
263
277
  constants.AMPHORAE_NETWORK_CONFIG, constants.AMPHORAE,
264
- constants.AMP_VRRP_INT),
278
+ constants.AMPHORAE_STATUS, constants.AMP_VRRP_INT),
279
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
265
280
  inject={constants.AMPHORA_INDEX: 0,
266
281
  constants.TIMEOUT_DICT: timeout_dict}))
267
282
 
283
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
284
+ amp_0_subflow.add(database_tasks.GetAmphoraFirewallRules(
285
+ name=sf_name + '-0-' + constants.GET_AMPHORA_FIREWALL_RULES,
286
+ requires=(constants.AMPHORAE,
287
+ constants.AMPHORAE_NETWORK_CONFIG),
288
+ provides=constants.AMPHORA_FIREWALL_RULES,
289
+ inject={constants.AMPHORA_INDEX: 0}))
290
+
291
+ amp_0_subflow.add(amphora_driver_tasks.SetAmphoraFirewallRules(
292
+ name=sf_name + '-0-' + constants.SET_AMPHORA_FIREWALL_RULES,
293
+ requires=(constants.AMPHORAE, constants.AMPHORAE_STATUS,
294
+ constants.AMPHORA_FIREWALL_RULES),
295
+ inject={constants.AMPHORA_INDEX: 0,
296
+ constants.TIMEOUT_DICT: timeout_dict}))
297
+
268
298
  amp_0_subflow.add(amphora_driver_tasks.AmphoraIndexVRRPStart(
269
299
  name=sf_name + '-0-' + constants.AMP_VRRP_START,
270
- requires=constants.AMPHORAE,
300
+ requires=(constants.AMPHORAE, constants.AMPHORAE_STATUS),
301
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
271
302
  inject={constants.AMPHORA_INDEX: 0,
272
303
  constants.TIMEOUT_DICT: timeout_dict}))
273
304
 
@@ -275,7 +306,8 @@ class AmphoraFlows(object):
275
306
 
276
307
  amp_1_subflow.add(amphora_driver_tasks.AmphoraIndexUpdateVRRPInterface(
277
308
  name=sf_name + '-1-' + constants.AMP_UPDATE_VRRP_INTF,
278
- requires=constants.AMPHORAE,
309
+ requires=(constants.AMPHORAE, constants.AMPHORAE_STATUS),
310
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
279
311
  inject={constants.AMPHORA_INDEX: 1,
280
312
  constants.TIMEOUT_DICT: timeout_dict},
281
313
  provides=constants.AMP_VRRP_INT))
@@ -284,12 +316,30 @@ class AmphoraFlows(object):
284
316
  name=sf_name + '-1-' + constants.AMP_VRRP_UPDATE,
285
317
  requires=(constants.LOADBALANCER_ID,
286
318
  constants.AMPHORAE_NETWORK_CONFIG, constants.AMPHORAE,
287
- constants.AMP_VRRP_INT),
319
+ constants.AMPHORAE_STATUS, constants.AMP_VRRP_INT),
320
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
288
321
  inject={constants.AMPHORA_INDEX: 1,
289
322
  constants.TIMEOUT_DICT: timeout_dict}))
323
+
324
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
325
+ amp_1_subflow.add(database_tasks.GetAmphoraFirewallRules(
326
+ name=sf_name + '-1-' + constants.GET_AMPHORA_FIREWALL_RULES,
327
+ requires=(constants.AMPHORAE,
328
+ constants.AMPHORAE_NETWORK_CONFIG),
329
+ provides=constants.AMPHORA_FIREWALL_RULES,
330
+ inject={constants.AMPHORA_INDEX: 1}))
331
+
332
+ amp_1_subflow.add(amphora_driver_tasks.SetAmphoraFirewallRules(
333
+ name=sf_name + '-1-' + constants.SET_AMPHORA_FIREWALL_RULES,
334
+ requires=(constants.AMPHORAE, constants.AMPHORAE_STATUS,
335
+ constants.AMPHORA_FIREWALL_RULES),
336
+ inject={constants.AMPHORA_INDEX: 1,
337
+ constants.TIMEOUT_DICT: timeout_dict}))
338
+
290
339
  amp_1_subflow.add(amphora_driver_tasks.AmphoraIndexVRRPStart(
291
340
  name=sf_name + '-1-' + constants.AMP_VRRP_START,
292
- requires=constants.AMPHORAE,
341
+ requires=(constants.AMPHORAE, constants.AMPHORAE_STATUS),
342
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
293
343
  inject={constants.AMPHORA_INDEX: 1,
294
344
  constants.TIMEOUT_DICT: timeout_dict}))
295
345
 
@@ -353,7 +403,8 @@ class AmphoraFlows(object):
353
403
 
354
404
  def get_amphora_for_lb_failover_subflow(
355
405
  self, prefix, role=constants.ROLE_STANDALONE,
356
- failed_amp_vrrp_port_id=None, is_vrrp_ipv6=False):
406
+ failed_amp_vrrp_port_id=None, is_vrrp_ipv6=False,
407
+ flavor_dict=None):
357
408
  """Creates a new amphora that will be used in a failover flow.
358
409
 
359
410
  :requires: loadbalancer_id, flavor, vip, vip_sg_id, loadbalancer
@@ -374,13 +425,24 @@ class AmphoraFlows(object):
374
425
  prefix=prefix + '-' + constants.FAILOVER_LOADBALANCER_FLOW,
375
426
  role=role))
376
427
 
377
- # Create the VIP base (aka VRRP) port for the amphora.
378
- amp_for_failover_flow.add(network_tasks.CreateVIPBasePort(
379
- name=prefix + '-' + constants.CREATE_VIP_BASE_PORT,
380
- requires=(constants.VIP, constants.VIP_SG_ID,
381
- constants.AMPHORA_ID,
382
- constants.ADDITIONAL_VIPS),
383
- provides=constants.BASE_PORT))
428
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
429
+ amp_for_failover_flow.add(network_tasks.GetSubnetFromVIP(
430
+ name=prefix + '-' + constants.GET_SUBNET_FROM_VIP,
431
+ requires=constants.LOADBALANCER,
432
+ provides=constants.SUBNET))
433
+ amp_for_failover_flow.add(network_tasks.CreateSRIOVBasePort(
434
+ name=prefix + '-' + constants.PLUG_VIP_AMPHORA,
435
+ requires=(constants.LOADBALANCER, constants.AMPHORA,
436
+ constants.SUBNET),
437
+ provides=constants.BASE_PORT))
438
+ else:
439
+ # Create the VIP base (aka VRRP) port for the amphora.
440
+ amp_for_failover_flow.add(network_tasks.CreateVIPBasePort(
441
+ name=prefix + '-' + constants.CREATE_VIP_BASE_PORT,
442
+ requires=(constants.VIP, constants.VIP_SG_ID,
443
+ constants.AMPHORA_ID,
444
+ constants.ADDITIONAL_VIPS),
445
+ provides=constants.BASE_PORT))
384
446
 
385
447
  # Attach the VIP base (aka VRRP) port to the amphora.
386
448
  amp_for_failover_flow.add(compute_tasks.AttachPort(
@@ -413,6 +475,27 @@ class AmphoraFlows(object):
413
475
  requires=(constants.AMPHORA, constants.LOADBALANCER,
414
476
  constants.AMPHORAE_NETWORK_CONFIG)))
415
477
 
478
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
479
+ amp_for_failover_flow.add(
480
+ shim_tasks.AmphoraToAmphoraeWithVRRPIP(
481
+ name=prefix + '-' + constants.AMPHORA_TO_AMPHORAE_VRRP_IP,
482
+ requires=(constants.AMPHORA, constants.BASE_PORT),
483
+ provides=constants.NEW_AMPHORAE))
484
+ amp_for_failover_flow.add(database_tasks.GetAmphoraFirewallRules(
485
+ name=prefix + '-' + constants.GET_AMPHORA_FIREWALL_RULES,
486
+ requires=(constants.AMPHORAE,
487
+ constants.AMPHORAE_NETWORK_CONFIG),
488
+ rebind={constants.AMPHORAE: constants.NEW_AMPHORAE},
489
+ provides=constants.AMPHORA_FIREWALL_RULES,
490
+ inject={constants.AMPHORA_INDEX: 0}))
491
+ amp_for_failover_flow.add(
492
+ amphora_driver_tasks.SetAmphoraFirewallRules(
493
+ name=prefix + '-' + constants.SET_AMPHORA_FIREWALL_RULES,
494
+ requires=(constants.AMPHORAE,
495
+ constants.AMPHORA_FIREWALL_RULES),
496
+ rebind={constants.AMPHORAE: constants.NEW_AMPHORAE},
497
+ inject={constants.AMPHORA_INDEX: 0}))
498
+
416
499
  # Plug member ports
417
500
  amp_for_failover_flow.add(network_tasks.CalculateAmphoraDelta(
418
501
  name=prefix + '-' + constants.CALCULATE_AMPHORA_DELTA,
@@ -431,7 +514,8 @@ class AmphoraFlows(object):
431
514
 
432
515
  return amp_for_failover_flow
433
516
 
434
- def get_failover_amphora_flow(self, failed_amphora, lb_amp_count):
517
+ def get_failover_amphora_flow(self, failed_amphora, lb_amp_count,
518
+ flavor_dict=None):
435
519
  """Get a Taskflow flow to failover an amphora.
436
520
 
437
521
  1. Build a replacement amphora.
@@ -441,6 +525,7 @@ class AmphoraFlows(object):
441
525
 
442
526
  :param failed_amphora: The amphora dict to failover.
443
527
  :param lb_amp_count: The number of amphora on this load balancer.
528
+ :param flavor_dict: The load balancer flavor dictionary.
444
529
  :returns: The flow that will provide the failover.
445
530
  """
446
531
  failover_amp_flow = linear_flow.Flow(
@@ -501,7 +586,7 @@ class AmphoraFlows(object):
501
586
  role=failed_amphora[constants.ROLE],
502
587
  failed_amp_vrrp_port_id=failed_amphora.get(
503
588
  constants.VRRP_PORT_ID),
504
- is_vrrp_ipv6=is_vrrp_ipv6))
589
+ is_vrrp_ipv6=is_vrrp_ipv6, flavor_dict=flavor_dict))
505
590
 
506
591
  failover_amp_flow.add(
507
592
  self.get_delete_amphora_flow(
@@ -538,6 +623,14 @@ class AmphoraFlows(object):
538
623
  constants.CONN_RETRY_INTERVAL:
539
624
  CONF.haproxy_amphora.active_connection_retry_interval}
540
625
 
626
+ failover_amp_flow.add(
627
+ amphora_driver_tasks.AmphoraeGetConnectivityStatus(
628
+ name=constants.AMPHORAE_GET_CONNECTIVITY_STATUS,
629
+ requires=constants.AMPHORAE,
630
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
631
+ inject={constants.TIMEOUT_DICT: timeout_dict},
632
+ provides=constants.AMPHORAE_STATUS))
633
+
541
634
  # Listeners update needs to be run on all amphora to update
542
635
  # their peer configurations. So parallelize this with an
543
636
  # unordered subflow.
@@ -548,7 +641,9 @@ class AmphoraFlows(object):
548
641
  update_amps_subflow.add(
549
642
  amphora_driver_tasks.AmphoraIndexListenerUpdate(
550
643
  name=str(amp_index) + '-' + constants.AMP_LISTENER_UPDATE,
551
- requires=(constants.LOADBALANCER, constants.AMPHORAE),
644
+ requires=(constants.LOADBALANCER, constants.AMPHORAE,
645
+ constants.AMPHORAE_STATUS),
646
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
552
647
  inject={constants.AMPHORA_INDEX: amp_index,
553
648
  constants.TIMEOUT_DICT: timeout_dict}))
554
649
 
@@ -558,7 +653,9 @@ class AmphoraFlows(object):
558
653
  if lb_amp_count == 2:
559
654
  failover_amp_flow.add(
560
655
  self.get_vrrp_subflow(constants.GET_VRRP_SUBFLOW,
561
- timeout_dict, create_vrrp_group=False))
656
+ timeout_dict, create_vrrp_group=False,
657
+ get_amphorae_status=False,
658
+ flavor_dict=flavor_dict))
562
659
 
563
660
  # Reload the listener. This needs to be done here because
564
661
  # it will create the required haproxy check scripts for
@@ -574,7 +671,9 @@ class AmphoraFlows(object):
574
671
  amphora_driver_tasks.AmphoraIndexListenersReload(
575
672
  name=(str(amp_index) + '-' +
576
673
  constants.AMPHORA_RELOAD_LISTENER),
577
- requires=(constants.LOADBALANCER, constants.AMPHORAE),
674
+ requires=(constants.LOADBALANCER, constants.AMPHORAE,
675
+ constants.AMPHORAE_STATUS),
676
+ rebind={constants.NEW_AMPHORA_ID: constants.AMPHORA_ID},
578
677
  inject={constants.AMPHORA_INDEX: amp_index,
579
678
  constants.TIMEOUT_DICT: timeout_dict}))
580
679
 
@@ -32,9 +32,9 @@ M_FLOWS = member_flows.MemberFlows()
32
32
  P_FLOWS = pool_flows.PoolFlows()
33
33
 
34
34
 
35
- def get_create_load_balancer_flow(topology, listeners=None):
36
- return LB_FLOWS.get_create_load_balancer_flow(topology,
37
- listeners=listeners)
35
+ def get_create_load_balancer_flow(topology, listeners=None, flavor_dict=None):
36
+ return LB_FLOWS.get_create_load_balancer_flow(
37
+ topology, listeners=listeners, flavor_dict=flavor_dict)
38
38
 
39
39
 
40
40
  def get_delete_load_balancer_flow(lb):
@@ -90,8 +90,9 @@ def get_failover_LB_flow(amps, lb):
90
90
  return LB_FLOWS.get_failover_LB_flow(amps, lb)
91
91
 
92
92
 
93
- def get_failover_amphora_flow(amphora_dict, lb_amp_count):
94
- return AMP_FLOWS.get_failover_amphora_flow(amphora_dict, lb_amp_count)
93
+ def get_failover_amphora_flow(amphora_dict, lb_amp_count, flavor_dict=None):
94
+ return AMP_FLOWS.get_failover_amphora_flow(amphora_dict, lb_amp_count,
95
+ flavor_dict=flavor_dict)
95
96
 
96
97
 
97
98
  def cert_rotate_amphora_flow():
@@ -138,20 +139,21 @@ def get_update_l7rule_flow():
138
139
  return L7_RULES_FLOWS.get_update_l7rule_flow()
139
140
 
140
141
 
141
- def get_create_listener_flow():
142
- return LISTENER_FLOWS.get_create_listener_flow()
142
+ def get_create_listener_flow(flavor_dict=None):
143
+ return LISTENER_FLOWS.get_create_listener_flow(flavor_dict=flavor_dict)
143
144
 
144
145
 
145
- def get_create_all_listeners_flow():
146
- return LISTENER_FLOWS.get_create_all_listeners_flow()
146
+ def get_create_all_listeners_flow(flavor_dict=None):
147
+ return LISTENER_FLOWS.get_create_all_listeners_flow(
148
+ flavor_dict=flavor_dict)
147
149
 
148
150
 
149
- def get_delete_listener_flow():
150
- return LISTENER_FLOWS.get_delete_listener_flow()
151
+ def get_delete_listener_flow(flavor_dict=None):
152
+ return LISTENER_FLOWS.get_delete_listener_flow(flavor_dict=flavor_dict)
151
153
 
152
154
 
153
- def get_update_listener_flow():
154
- return LISTENER_FLOWS.get_update_listener_flow()
155
+ def get_update_listener_flow(flavor_dict=None):
156
+ return LISTENER_FLOWS.get_update_listener_flow(flavor_dict=flavor_dict)
155
157
 
156
158
 
157
159
  def get_create_member_flow():
@@ -14,6 +14,7 @@
14
14
  #
15
15
 
16
16
  from taskflow.patterns import linear_flow
17
+ from taskflow.patterns import unordered_flow
17
18
 
18
19
  from octavia.common import constants
19
20
  from octavia.controller.worker.v2.tasks import amphora_driver_tasks
@@ -24,7 +25,7 @@ from octavia.controller.worker.v2.tasks import network_tasks
24
25
 
25
26
  class ListenerFlows(object):
26
27
 
27
- def get_create_listener_flow(self):
28
+ def get_create_listener_flow(self, flavor_dict=None):
28
29
  """Create a flow to create a listener
29
30
 
30
31
  :returns: The flow for creating a listener
@@ -36,13 +37,18 @@ class ListenerFlows(object):
36
37
  requires=constants.LOADBALANCER_ID))
37
38
  create_listener_flow.add(network_tasks.UpdateVIP(
38
39
  requires=constants.LISTENERS))
40
+
41
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
42
+ create_listener_flow.add(*self._get_firewall_rules_subflow(
43
+ flavor_dict))
44
+
39
45
  create_listener_flow.add(database_tasks.
40
46
  MarkLBAndListenersActiveInDB(
41
47
  requires=(constants.LOADBALANCER_ID,
42
48
  constants.LISTENERS)))
43
49
  return create_listener_flow
44
50
 
45
- def get_create_all_listeners_flow(self):
51
+ def get_create_all_listeners_flow(self, flavor_dict=None):
46
52
  """Create a flow to create all listeners
47
53
 
48
54
  :returns: The flow for creating all listeners
@@ -60,12 +66,17 @@ class ListenerFlows(object):
60
66
  requires=constants.LOADBALANCER_ID))
61
67
  create_all_listeners_flow.add(network_tasks.UpdateVIP(
62
68
  requires=constants.LISTENERS))
69
+
70
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
71
+ create_all_listeners_flow.add(*self._get_firewall_rules_subflow(
72
+ flavor_dict))
73
+
63
74
  create_all_listeners_flow.add(
64
75
  database_tasks.MarkHealthMonitorsOnlineInDB(
65
76
  requires=constants.LOADBALANCER))
66
77
  return create_all_listeners_flow
67
78
 
68
- def get_delete_listener_flow(self):
79
+ def get_delete_listener_flow(self, flavor_dict=None):
69
80
  """Create a flow to delete a listener
70
81
 
71
82
  :returns: The flow for deleting a listener
@@ -79,6 +90,11 @@ class ListenerFlows(object):
79
90
  requires=constants.LOADBALANCER_ID))
80
91
  delete_listener_flow.add(database_tasks.DeleteListenerInDB(
81
92
  requires=constants.LISTENER))
93
+
94
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
95
+ delete_listener_flow.add(*self._get_firewall_rules_subflow(
96
+ flavor_dict))
97
+
82
98
  delete_listener_flow.add(database_tasks.DecrementListenerQuota(
83
99
  requires=constants.PROJECT_ID))
84
100
  delete_listener_flow.add(database_tasks.MarkLBActiveInDBByListener(
@@ -86,7 +102,7 @@ class ListenerFlows(object):
86
102
 
87
103
  return delete_listener_flow
88
104
 
89
- def get_delete_listener_internal_flow(self, listener):
105
+ def get_delete_listener_internal_flow(self, listener, flavor_dict=None):
90
106
  """Create a flow to delete a listener and l7policies internally
91
107
 
92
108
  (will skip deletion on the amp and marking LB active)
@@ -104,13 +120,22 @@ class ListenerFlows(object):
104
120
  name='delete_listener_in_db_' + listener_id,
105
121
  requires=constants.LISTENER,
106
122
  inject={constants.LISTENER: listener}))
123
+
124
+ # Currently the flavor_dict will always be None since there is
125
+ # no point updating the firewall rules when deleting the LB.
126
+ # However, this may be used for additional flows in the future, so
127
+ # adding this code for completeness.
128
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
129
+ delete_listener_flow.add(*self._get_firewall_rules_subflow(
130
+ flavor_dict))
131
+
107
132
  delete_listener_flow.add(database_tasks.DecrementListenerQuota(
108
133
  name='decrement_listener_quota_' + listener_id,
109
134
  requires=constants.PROJECT_ID))
110
135
 
111
136
  return delete_listener_flow
112
137
 
113
- def get_update_listener_flow(self):
138
+ def get_update_listener_flow(self, flavor_dict=None):
114
139
  """Create a flow to update a listener
115
140
 
116
141
  :returns: The flow for updating a listener
@@ -122,6 +147,11 @@ class ListenerFlows(object):
122
147
  requires=constants.LOADBALANCER_ID))
123
148
  update_listener_flow.add(network_tasks.UpdateVIP(
124
149
  requires=constants.LISTENERS))
150
+
151
+ if flavor_dict and flavor_dict.get(constants.SRIOV_VIP, False):
152
+ update_listener_flow.add(*self._get_firewall_rules_subflow(
153
+ flavor_dict))
154
+
125
155
  update_listener_flow.add(database_tasks.UpdateListenerInDB(
126
156
  requires=[constants.LISTENER, constants.UPDATE_DICT]))
127
157
  update_listener_flow.add(database_tasks.
@@ -130,3 +160,63 @@ class ListenerFlows(object):
130
160
  constants.LISTENERS)))
131
161
 
132
162
  return update_listener_flow
163
+
164
+ def _get_firewall_rules_subflow(self, flavor_dict):
165
+ """Creates a subflow that updates the firewall rules in the amphorae.
166
+
167
+ :returns: The subflow for updating firewall rules in the amphorae.
168
+ """
169
+ sf_name = constants.FIREWALL_RULES_SUBFLOW
170
+ fw_rules_subflow = linear_flow.Flow(sf_name)
171
+
172
+ fw_rules_subflow.add(database_tasks.GetAmphoraeFromLoadbalancer(
173
+ name=sf_name + '-' + constants.GET_AMPHORAE_FROM_LB,
174
+ requires=constants.LOADBALANCER_ID,
175
+ provides=constants.AMPHORAE))
176
+
177
+ fw_rules_subflow.add(network_tasks.GetAmphoraeNetworkConfigs(
178
+ name=sf_name + '-' + constants.GET_AMP_NETWORK_CONFIG,
179
+ requires=constants.LOADBALANCER_ID,
180
+ provides=constants.AMPHORAE_NETWORK_CONFIG))
181
+
182
+ update_amps_subflow = unordered_flow.Flow(
183
+ constants.AMP_UPDATE_FW_SUBFLOW)
184
+
185
+ amp_0_subflow = linear_flow.Flow('amp-0-fw-update')
186
+
187
+ amp_0_subflow.add(database_tasks.GetAmphoraFirewallRules(
188
+ name=sf_name + '-0-' + constants.GET_AMPHORA_FIREWALL_RULES,
189
+ requires=(constants.AMPHORAE, constants.AMPHORAE_NETWORK_CONFIG),
190
+ provides=constants.AMPHORA_FIREWALL_RULES,
191
+ inject={constants.AMPHORA_INDEX: 0}))
192
+
193
+ amp_0_subflow.add(amphora_driver_tasks.SetAmphoraFirewallRules(
194
+ name=sf_name + '-0-' + constants.SET_AMPHORA_FIREWALL_RULES,
195
+ requires=(constants.AMPHORAE, constants.AMPHORA_FIREWALL_RULES),
196
+ inject={constants.AMPHORA_INDEX: 0}))
197
+
198
+ update_amps_subflow.add(amp_0_subflow)
199
+
200
+ if (flavor_dict[constants.LOADBALANCER_TOPOLOGY] ==
201
+ constants.TOPOLOGY_ACTIVE_STANDBY):
202
+
203
+ amp_1_subflow = linear_flow.Flow('amp-1-fw-update')
204
+
205
+ amp_1_subflow.add(database_tasks.GetAmphoraFirewallRules(
206
+ name=sf_name + '-1-' + constants.GET_AMPHORA_FIREWALL_RULES,
207
+ requires=(constants.AMPHORAE,
208
+ constants.AMPHORAE_NETWORK_CONFIG),
209
+ provides=constants.AMPHORA_FIREWALL_RULES,
210
+ inject={constants.AMPHORA_INDEX: 1}))
211
+
212
+ amp_1_subflow.add(amphora_driver_tasks.SetAmphoraFirewallRules(
213
+ name=sf_name + '-1-' + constants.SET_AMPHORA_FIREWALL_RULES,
214
+ requires=(constants.AMPHORAE,
215
+ constants.AMPHORA_FIREWALL_RULES),
216
+ inject={constants.AMPHORA_INDEX: 1}))
217
+
218
+ update_amps_subflow.add(amp_1_subflow)
219
+
220
+ fw_rules_subflow.add(update_amps_subflow)
221
+
222
+ return fw_rules_subflow