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.
Files changed (193) hide show
  1. octavia/amphorae/backends/agent/api_server/osutils.py +1 -0
  2. octavia/amphorae/backends/agent/api_server/plug.py +21 -7
  3. octavia/amphorae/backends/agent/api_server/templates/amphora-netns.systemd.j2 +2 -2
  4. octavia/amphorae/backends/agent/api_server/util.py +21 -0
  5. octavia/amphorae/backends/health_daemon/health_daemon.py +9 -3
  6. octavia/amphorae/backends/health_daemon/health_sender.py +2 -0
  7. octavia/amphorae/backends/utils/interface.py +14 -6
  8. octavia/amphorae/backends/utils/interface_file.py +6 -3
  9. octavia/amphorae/backends/utils/keepalivedlvs_query.py +8 -9
  10. octavia/amphorae/drivers/driver_base.py +1 -2
  11. octavia/amphorae/drivers/haproxy/rest_api_driver.py +11 -25
  12. octavia/amphorae/drivers/health/heartbeat_udp.py +34 -24
  13. octavia/amphorae/drivers/keepalived/jinja/jinja_cfg.py +3 -12
  14. octavia/amphorae/drivers/noop_driver/driver.py +3 -5
  15. octavia/api/common/pagination.py +4 -4
  16. octavia/api/drivers/amphora_driver/v2/driver.py +11 -5
  17. octavia/api/drivers/driver_agent/driver_get.py +22 -14
  18. octavia/api/drivers/driver_agent/driver_updater.py +8 -4
  19. octavia/api/drivers/utils.py +4 -2
  20. octavia/api/healthcheck/healthcheck_plugins.py +4 -2
  21. octavia/api/root_controller.py +4 -1
  22. octavia/api/v2/controllers/amphora.py +35 -38
  23. octavia/api/v2/controllers/availability_zone_profiles.py +43 -33
  24. octavia/api/v2/controllers/availability_zones.py +22 -18
  25. octavia/api/v2/controllers/flavor_profiles.py +37 -28
  26. octavia/api/v2/controllers/flavors.py +19 -15
  27. octavia/api/v2/controllers/health_monitor.py +44 -33
  28. octavia/api/v2/controllers/l7policy.py +52 -40
  29. octavia/api/v2/controllers/l7rule.py +68 -55
  30. octavia/api/v2/controllers/listener.py +88 -61
  31. octavia/api/v2/controllers/load_balancer.py +52 -34
  32. octavia/api/v2/controllers/member.py +63 -52
  33. octavia/api/v2/controllers/pool.py +55 -42
  34. octavia/api/v2/controllers/quotas.py +5 -3
  35. octavia/api/v2/types/listener.py +15 -0
  36. octavia/cmd/octavia_worker.py +0 -3
  37. octavia/cmd/status.py +1 -4
  38. octavia/common/clients.py +25 -45
  39. octavia/common/config.py +64 -22
  40. octavia/common/constants.py +3 -2
  41. octavia/common/data_models.py +7 -1
  42. octavia/common/jinja/haproxy/combined_listeners/jinja_cfg.py +12 -1
  43. octavia/common/jinja/haproxy/combined_listeners/templates/macros.j2 +5 -2
  44. octavia/common/jinja/lvs/jinja_cfg.py +4 -2
  45. octavia/common/keystone.py +58 -5
  46. octavia/common/validate.py +35 -0
  47. octavia/compute/drivers/noop_driver/driver.py +6 -0
  48. octavia/controller/healthmanager/health_manager.py +3 -6
  49. octavia/controller/housekeeping/house_keeping.py +36 -37
  50. octavia/controller/worker/amphora_rate_limit.py +5 -4
  51. octavia/controller/worker/task_utils.py +57 -41
  52. octavia/controller/worker/v2/controller_worker.py +160 -103
  53. octavia/controller/worker/v2/flows/listener_flows.py +3 -0
  54. octavia/controller/worker/v2/flows/load_balancer_flows.py +9 -14
  55. octavia/controller/worker/v2/tasks/amphora_driver_tasks.py +152 -91
  56. octavia/controller/worker/v2/tasks/compute_tasks.py +4 -2
  57. octavia/controller/worker/v2/tasks/database_tasks.py +542 -400
  58. octavia/controller/worker/v2/tasks/network_tasks.py +119 -79
  59. octavia/db/api.py +26 -23
  60. octavia/db/base_models.py +2 -2
  61. octavia/db/healthcheck.py +2 -1
  62. octavia/db/migration/alembic_migrations/versions/632152d2d32e_add_http_strict_transport_security_.py +42 -0
  63. octavia/db/models.py +12 -2
  64. octavia/db/prepare.py +2 -0
  65. octavia/db/repositories.py +462 -482
  66. octavia/hacking/checks.py +1 -1
  67. octavia/network/base.py +0 -14
  68. octavia/network/drivers/neutron/allowed_address_pairs.py +92 -135
  69. octavia/network/drivers/neutron/base.py +65 -77
  70. octavia/network/drivers/neutron/utils.py +69 -85
  71. octavia/network/drivers/noop_driver/driver.py +0 -7
  72. octavia/statistics/drivers/update_db.py +10 -10
  73. octavia/tests/common/constants.py +91 -84
  74. octavia/tests/common/sample_data_models.py +13 -1
  75. octavia/tests/fixtures.py +32 -0
  76. octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +9 -10
  77. octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py +260 -15
  78. octavia/tests/functional/api/test_root_controller.py +3 -28
  79. octavia/tests/functional/api/v2/base.py +5 -3
  80. octavia/tests/functional/api/v2/test_amphora.py +18 -5
  81. octavia/tests/functional/api/v2/test_availability_zone_profiles.py +1 -0
  82. octavia/tests/functional/api/v2/test_listener.py +51 -19
  83. octavia/tests/functional/api/v2/test_load_balancer.py +10 -1
  84. octavia/tests/functional/db/base.py +31 -16
  85. octavia/tests/functional/db/test_models.py +27 -28
  86. octavia/tests/functional/db/test_repositories.py +407 -50
  87. octavia/tests/unit/amphorae/backends/agent/api_server/test_amphora_info.py +2 -0
  88. octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py +1 -1
  89. octavia/tests/unit/amphorae/backends/agent/api_server/test_plug.py +54 -6
  90. octavia/tests/unit/amphorae/backends/agent/api_server/test_util.py +35 -0
  91. octavia/tests/unit/amphorae/backends/health_daemon/test_health_daemon.py +8 -0
  92. octavia/tests/unit/amphorae/backends/health_daemon/test_health_sender.py +18 -0
  93. octavia/tests/unit/amphorae/backends/utils/test_interface.py +81 -0
  94. octavia/tests/unit/amphorae/backends/utils/test_interface_file.py +2 -0
  95. octavia/tests/unit/amphorae/backends/utils/test_keepalivedlvs_query.py +129 -5
  96. octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +42 -20
  97. octavia/tests/unit/amphorae/drivers/health/test_heartbeat_udp.py +18 -20
  98. octavia/tests/unit/amphorae/drivers/keepalived/jinja/test_jinja_cfg.py +4 -4
  99. octavia/tests/unit/amphorae/drivers/noop_driver/test_driver.py +4 -1
  100. octavia/tests/unit/api/drivers/driver_agent/test_driver_get.py +3 -3
  101. octavia/tests/unit/api/drivers/driver_agent/test_driver_updater.py +11 -13
  102. octavia/tests/unit/base.py +6 -0
  103. octavia/tests/unit/cmd/test_interface.py +2 -2
  104. octavia/tests/unit/cmd/test_status.py +2 -2
  105. octavia/tests/unit/common/jinja/haproxy/combined_listeners/test_jinja_cfg.py +152 -1
  106. octavia/tests/unit/common/sample_configs/sample_configs_combined.py +10 -3
  107. octavia/tests/unit/common/test_clients.py +0 -39
  108. octavia/tests/unit/common/test_keystone.py +54 -0
  109. octavia/tests/unit/common/test_validate.py +67 -0
  110. octavia/tests/unit/controller/healthmanager/test_health_manager.py +8 -22
  111. octavia/tests/unit/controller/housekeeping/test_house_keeping.py +3 -64
  112. octavia/tests/unit/controller/worker/test_amphora_rate_limit.py +1 -1
  113. octavia/tests/unit/controller/worker/test_task_utils.py +44 -24
  114. octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +0 -1
  115. octavia/tests/unit/controller/worker/v2/tasks/test_amphora_driver_tasks.py +49 -26
  116. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +399 -196
  117. octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks_quota.py +37 -64
  118. octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +3 -14
  119. octavia/tests/unit/controller/worker/v2/test_controller_worker.py +2 -2
  120. octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +456 -561
  121. octavia/tests/unit/network/drivers/neutron/test_base.py +181 -194
  122. octavia/tests/unit/network/drivers/neutron/test_utils.py +14 -30
  123. octavia/tests/unit/statistics/drivers/test_update_db.py +7 -5
  124. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/README.rst +1 -1
  125. {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/AUTHORS +4 -0
  126. {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/METADATA +4 -4
  127. {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/RECORD +141 -189
  128. {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/entry_points.txt +1 -2
  129. octavia-13.0.0.0rc1.dist-info/pbr.json +1 -0
  130. octavia/api/drivers/amphora_driver/v1/__init__.py +0 -11
  131. octavia/api/drivers/amphora_driver/v1/driver.py +0 -547
  132. octavia/controller/queue/v1/__init__.py +0 -11
  133. octavia/controller/queue/v1/consumer.py +0 -64
  134. octavia/controller/queue/v1/endpoints.py +0 -160
  135. octavia/controller/worker/v1/__init__.py +0 -11
  136. octavia/controller/worker/v1/controller_worker.py +0 -1157
  137. octavia/controller/worker/v1/flows/__init__.py +0 -11
  138. octavia/controller/worker/v1/flows/amphora_flows.py +0 -610
  139. octavia/controller/worker/v1/flows/health_monitor_flows.py +0 -105
  140. octavia/controller/worker/v1/flows/l7policy_flows.py +0 -94
  141. octavia/controller/worker/v1/flows/l7rule_flows.py +0 -100
  142. octavia/controller/worker/v1/flows/listener_flows.py +0 -128
  143. octavia/controller/worker/v1/flows/load_balancer_flows.py +0 -692
  144. octavia/controller/worker/v1/flows/member_flows.py +0 -230
  145. octavia/controller/worker/v1/flows/pool_flows.py +0 -127
  146. octavia/controller/worker/v1/tasks/__init__.py +0 -11
  147. octavia/controller/worker/v1/tasks/amphora_driver_tasks.py +0 -453
  148. octavia/controller/worker/v1/tasks/cert_task.py +0 -51
  149. octavia/controller/worker/v1/tasks/compute_tasks.py +0 -335
  150. octavia/controller/worker/v1/tasks/database_tasks.py +0 -2756
  151. octavia/controller/worker/v1/tasks/lifecycle_tasks.py +0 -173
  152. octavia/controller/worker/v1/tasks/model_tasks.py +0 -41
  153. octavia/controller/worker/v1/tasks/network_tasks.py +0 -970
  154. octavia/controller/worker/v1/tasks/retry_tasks.py +0 -74
  155. octavia/tests/unit/api/drivers/amphora_driver/v1/__init__.py +0 -11
  156. octavia/tests/unit/api/drivers/amphora_driver/v1/test_driver.py +0 -824
  157. octavia/tests/unit/controller/queue/v1/__init__.py +0 -11
  158. octavia/tests/unit/controller/queue/v1/test_consumer.py +0 -61
  159. octavia/tests/unit/controller/queue/v1/test_endpoints.py +0 -189
  160. octavia/tests/unit/controller/worker/v1/__init__.py +0 -11
  161. octavia/tests/unit/controller/worker/v1/flows/__init__.py +0 -11
  162. octavia/tests/unit/controller/worker/v1/flows/test_amphora_flows.py +0 -474
  163. octavia/tests/unit/controller/worker/v1/flows/test_health_monitor_flows.py +0 -72
  164. octavia/tests/unit/controller/worker/v1/flows/test_l7policy_flows.py +0 -67
  165. octavia/tests/unit/controller/worker/v1/flows/test_l7rule_flows.py +0 -67
  166. octavia/tests/unit/controller/worker/v1/flows/test_listener_flows.py +0 -91
  167. octavia/tests/unit/controller/worker/v1/flows/test_load_balancer_flows.py +0 -431
  168. octavia/tests/unit/controller/worker/v1/flows/test_member_flows.py +0 -106
  169. octavia/tests/unit/controller/worker/v1/flows/test_pool_flows.py +0 -77
  170. octavia/tests/unit/controller/worker/v1/tasks/__init__.py +0 -11
  171. octavia/tests/unit/controller/worker/v1/tasks/test_amphora_driver_tasks.py +0 -792
  172. octavia/tests/unit/controller/worker/v1/tasks/test_cert_task.py +0 -46
  173. octavia/tests/unit/controller/worker/v1/tasks/test_compute_tasks.py +0 -634
  174. octavia/tests/unit/controller/worker/v1/tasks/test_database_tasks.py +0 -2615
  175. octavia/tests/unit/controller/worker/v1/tasks/test_database_tasks_quota.py +0 -415
  176. octavia/tests/unit/controller/worker/v1/tasks/test_lifecycle_tasks.py +0 -401
  177. octavia/tests/unit/controller/worker/v1/tasks/test_model_tasks.py +0 -44
  178. octavia/tests/unit/controller/worker/v1/tasks/test_network_tasks.py +0 -1788
  179. octavia/tests/unit/controller/worker/v1/tasks/test_retry_tasks.py +0 -47
  180. octavia/tests/unit/controller/worker/v1/test_controller_worker.py +0 -2096
  181. octavia-12.0.0.0rc2.dist-info/pbr.json +0 -1
  182. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/LICENSE +0 -0
  183. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/README.rst +0 -0
  184. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
  185. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
  186. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
  187. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
  188. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/tox.ini +0 -0
  189. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/version.txt +0 -0
  190. {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/scripts/octavia-wsgi +0 -0
  191. {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/LICENSE +0 -0
  192. {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/WHEEL +0 -0
  193. {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -55,16 +55,10 @@ class CalculateAmphoraDelta(BaseNetworkTask):
55
55
 
56
56
  default_provides = constants.DELTA
57
57
 
58
- # TODO(gthiemonge) ensure we no longer need vrrp_port
59
58
  def execute(self, loadbalancer, amphora, availability_zone):
60
59
  LOG.debug("Calculating network delta for amphora id: %s",
61
60
  amphora.get(constants.ID))
62
61
 
63
- vip_subnet_to_net_map = {
64
- loadbalancer[constants.VIP_SUBNET_ID]:
65
- loadbalancer[constants.VIP_NETWORK_ID]
66
- }
67
-
68
62
  # Figure out what networks we want
69
63
  # seed with lb network(s)
70
64
  if (availability_zone and
@@ -74,15 +68,15 @@ class CalculateAmphoraDelta(BaseNetworkTask):
74
68
  else:
75
69
  management_nets = CONF.controller_worker.amp_boot_network_list
76
70
 
77
- db_lb = self.loadbalancer_repo.get(
78
- db_apis.get_session(), id=loadbalancer[constants.LOADBALANCER_ID])
71
+ session = db_apis.get_session()
72
+ with session.begin():
73
+ db_lb = self.loadbalancer_repo.get(
74
+ session, id=loadbalancer[constants.LOADBALANCER_ID])
79
75
 
80
- desired_subnet_to_net_map = {}
81
- for mgmt_net_id in management_nets:
82
- for subnet_id in self.network_driver.get_network(
83
- mgmt_net_id).subnets:
84
- desired_subnet_to_net_map[subnet_id] = mgmt_net_id
85
- desired_subnet_to_net_map.update(vip_subnet_to_net_map)
76
+ desired_subnet_to_net_map = {
77
+ loadbalancer[constants.VIP_SUBNET_ID]:
78
+ loadbalancer[constants.VIP_NETWORK_ID]
79
+ }
86
80
 
87
81
  for pool in db_lb.pools:
88
82
  for member in pool.members:
@@ -101,7 +95,12 @@ class CalculateAmphoraDelta(BaseNetworkTask):
101
95
  nics = self.network_driver.get_plugged_networks(
102
96
  amphora[constants.COMPUTE_ID])
103
97
  # we don't have two nics in the same network
104
- network_to_nic_map = {nic.network_id: nic for nic in nics}
98
+ # Don't include the nics connected to the management network, we don't
99
+ # want to update these interfaces.
100
+ network_to_nic_map = {
101
+ nic.network_id: nic
102
+ for nic in nics
103
+ if nic.network_id not in management_nets}
105
104
 
106
105
  plugged_network_ids = set(network_to_nic_map)
107
106
 
@@ -183,8 +182,10 @@ class CalculateDelta(BaseNetworkTask):
183
182
 
184
183
  calculate_amp = CalculateAmphoraDelta()
185
184
  deltas = {}
186
- db_lb = self.loadbalancer_repo.get(
187
- db_apis.get_session(), id=loadbalancer[constants.LOADBALANCER_ID])
185
+ session = db_apis.get_session()
186
+ with session.begin():
187
+ db_lb = self.loadbalancer_repo.get(
188
+ session, id=loadbalancer[constants.LOADBALANCER_ID])
188
189
  for amphora in filter(
189
190
  lambda amp: amp.status == constants.AMPHORA_ALLOCATED,
190
191
  db_lb.amphorae):
@@ -317,8 +318,10 @@ class HandleNetworkDelta(BaseNetworkTask):
317
318
 
318
319
  def execute(self, amphora, delta):
319
320
  """Handle network plugging based off deltas."""
320
- db_amp = self.amphora_repo.get(db_apis.get_session(),
321
- id=amphora.get(constants.ID))
321
+ session = db_apis.get_session()
322
+ with session.begin():
323
+ db_amp = self.amphora_repo.get(session,
324
+ id=amphora.get(constants.ID))
322
325
  updated_ports = {}
323
326
  for nic in delta[constants.ADD_NICS]:
324
327
  subnet_id = nic[constants.FIXED_IPS][0][constants.SUBNET_ID]
@@ -432,8 +435,10 @@ class HandleNetworkDeltas(BaseNetworkTask):
432
435
 
433
436
  def execute(self, deltas, loadbalancer):
434
437
  """Handle network plugging based off deltas."""
435
- db_lb = self.loadbalancer_repo.get(
436
- db_apis.get_session(), id=loadbalancer[constants.LOADBALANCER_ID])
438
+ session = db_apis.get_session()
439
+ with session.begin():
440
+ db_lb = self.loadbalancer_repo.get(
441
+ session, id=loadbalancer[constants.LOADBALANCER_ID])
437
442
  amphorae = {amp.id: amp for amp in db_lb.amphorae}
438
443
 
439
444
  updated_ports = {}
@@ -481,9 +486,11 @@ class PlugVIP(BaseNetworkTask):
481
486
 
482
487
  LOG.debug("Plumbing VIP for loadbalancer id: %s",
483
488
  loadbalancer[constants.LOADBALANCER_ID])
484
- db_lb = self.loadbalancer_repo.get(
485
- db_apis.get_session(),
486
- id=loadbalancer[constants.LOADBALANCER_ID])
489
+ session = db_apis.get_session()
490
+ with session.begin():
491
+ db_lb = self.loadbalancer_repo.get(
492
+ session,
493
+ id=loadbalancer[constants.LOADBALANCER_ID])
487
494
  amps_data = self.network_driver.plug_vip(db_lb,
488
495
  db_lb.vip)
489
496
  return [amp.to_dict() for amp in amps_data]
@@ -496,9 +503,11 @@ class PlugVIP(BaseNetworkTask):
496
503
  LOG.warning("Unable to plug VIP for loadbalancer id %s",
497
504
  loadbalancer[constants.LOADBALANCER_ID])
498
505
 
499
- db_lb = self.loadbalancer_repo.get(
500
- db_apis.get_session(),
501
- id=loadbalancer[constants.LOADBALANCER_ID])
506
+ session = db_apis.get_session()
507
+ with session.begin():
508
+ db_lb = self.loadbalancer_repo.get(
509
+ session,
510
+ id=loadbalancer[constants.LOADBALANCER_ID])
502
511
  try:
503
512
  # Make sure we have the current port IDs for cleanup
504
513
  for amp_data in result:
@@ -524,8 +533,10 @@ class UpdateVIPSecurityGroup(BaseNetworkTask):
524
533
 
525
534
  LOG.debug("Setting up VIP SG for load balancer id: %s",
526
535
  loadbalancer_id)
527
- db_lb = self.loadbalancer_repo.get(
528
- db_apis.get_session(), id=loadbalancer_id)
536
+ session = db_apis.get_session()
537
+ with session.begin():
538
+ db_lb = self.loadbalancer_repo.get(
539
+ session, id=loadbalancer_id)
529
540
 
530
541
  sg_id = self.network_driver.update_vip_sg(db_lb, db_lb.vip)
531
542
  LOG.info("Set up VIP SG %s for load balancer %s complete",
@@ -557,11 +568,13 @@ class PlugVIPAmphora(BaseNetworkTask):
557
568
 
558
569
  LOG.debug("Plumbing VIP for amphora id: %s",
559
570
  amphora.get(constants.ID))
560
- db_amp = self.amphora_repo.get(db_apis.get_session(),
561
- id=amphora.get(constants.ID))
562
- db_subnet = self.network_driver.get_subnet(subnet[constants.ID])
563
- db_lb = self.loadbalancer_repo.get(
564
- db_apis.get_session(), id=loadbalancer[constants.LOADBALANCER_ID])
571
+ session = db_apis.get_session()
572
+ with session.begin():
573
+ db_amp = self.amphora_repo.get(session,
574
+ id=amphora.get(constants.ID))
575
+ db_subnet = self.network_driver.get_subnet(subnet[constants.ID])
576
+ db_lb = self.loadbalancer_repo.get(
577
+ session, id=loadbalancer[constants.LOADBALANCER_ID])
565
578
  amp_data = self.network_driver.plug_aap_port(
566
579
  db_lb, db_lb.vip, db_amp, db_subnet)
567
580
  return amp_data.to_dict()
@@ -576,14 +589,17 @@ class PlugVIPAmphora(BaseNetworkTask):
576
589
  loadbalancer[constants.LOADBALANCER_ID])
577
590
 
578
591
  try:
579
- db_amp = self.amphora_repo.get(db_apis.get_session(),
580
- id=amphora.get(constants.ID))
581
- db_amp.vrrp_port_id = result[constants.VRRP_PORT_ID]
582
- db_amp.ha_port_id = result[constants.HA_PORT_ID]
583
- db_subnet = self.network_driver.get_subnet(subnet[constants.ID])
584
- db_lb = self.loadbalancer_repo.get(
585
- db_apis.get_session(),
586
- id=loadbalancer[constants.LOADBALANCER_ID])
592
+ session = db_apis.get_session()
593
+ with session.begin():
594
+ db_amp = self.amphora_repo.get(session,
595
+ id=amphora.get(constants.ID))
596
+ db_amp.vrrp_port_id = result[constants.VRRP_PORT_ID]
597
+ db_amp.ha_port_id = result[constants.HA_PORT_ID]
598
+ db_subnet = self.network_driver.get_subnet(
599
+ subnet[constants.ID])
600
+ db_lb = self.loadbalancer_repo.get(
601
+ session,
602
+ id=loadbalancer[constants.LOADBALANCER_ID])
587
603
 
588
604
  self.network_driver.unplug_aap_port(db_lb.vip,
589
605
  db_amp, db_subnet)
@@ -600,9 +616,11 @@ class UnplugVIP(BaseNetworkTask):
600
616
 
601
617
  LOG.debug("Unplug vip on amphora")
602
618
  try:
603
- db_lb = self.loadbalancer_repo.get(
604
- db_apis.get_session(),
605
- id=loadbalancer[constants.LOADBALANCER_ID])
619
+ session = db_apis.get_session()
620
+ with session.begin():
621
+ db_lb = self.loadbalancer_repo.get(
622
+ session,
623
+ id=loadbalancer[constants.LOADBALANCER_ID])
606
624
  self.network_driver.unplug_vip(db_lb, db_lb.vip)
607
625
  except Exception:
608
626
  LOG.exception("Unable to unplug vip from load balancer %s",
@@ -621,8 +639,10 @@ class AllocateVIP(BaseNetworkTask):
621
639
  loadbalancer[constants.VIP_SUBNET_ID],
622
640
  loadbalancer[constants.VIP_ADDRESS],
623
641
  loadbalancer[constants.LOADBALANCER_ID])
624
- db_lb = self.loadbalancer_repo.get(
625
- db_apis.get_session(), id=loadbalancer[constants.LOADBALANCER_ID])
642
+ session = db_apis.get_session()
643
+ with session.begin():
644
+ db_lb = self.loadbalancer_repo.get(
645
+ session, id=loadbalancer[constants.LOADBALANCER_ID])
626
646
  vip, additional_vips = self.network_driver.allocate_vip(db_lb)
627
647
  LOG.info("Allocated vip with port id %s, subnet id %s, ip address %s "
628
648
  "for load balancer %s",
@@ -682,10 +702,12 @@ class DeallocateVIP(BaseNetworkTask):
682
702
  # will need access to the load balancer that the vip is/was attached
683
703
  # to. However the data model serialization for the vip does not give a
684
704
  # backref to the loadbalancer if accessed through the loadbalancer.
685
- db_lb = self.loadbalancer_repo.get(
686
- db_apis.get_session(), id=loadbalancer[constants.LOADBALANCER_ID])
687
- vip = db_lb.vip
688
- vip.load_balancer = db_lb
705
+ session = db_apis.get_session()
706
+ with session.begin():
707
+ db_lb = self.loadbalancer_repo.get(
708
+ session, id=loadbalancer[constants.LOADBALANCER_ID])
709
+ vip = db_lb.vip
710
+ vip.load_balancer = db_lb
689
711
  self.network_driver.deallocate_vip(vip)
690
712
 
691
713
 
@@ -693,8 +715,10 @@ class UpdateVIP(BaseNetworkTask):
693
715
  """Task to update a VIP."""
694
716
 
695
717
  def execute(self, listeners):
696
- loadbalancer = self.loadbalancer_repo.get(
697
- db_apis.get_session(), id=listeners[0][constants.LOADBALANCER_ID])
718
+ session = db_apis.get_session()
719
+ with session.begin():
720
+ loadbalancer = self.loadbalancer_repo.get(
721
+ session, id=listeners[0][constants.LOADBALANCER_ID])
698
722
 
699
723
  LOG.debug("Updating VIP of load_balancer %s.", loadbalancer.id)
700
724
 
@@ -705,8 +729,10 @@ class UpdateVIPForDelete(BaseNetworkTask):
705
729
  """Task to update a VIP for listener delete flows."""
706
730
 
707
731
  def execute(self, loadbalancer_id):
708
- loadbalancer = self.loadbalancer_repo.get(
709
- db_apis.get_session(), id=loadbalancer_id)
732
+ session = db_apis.get_session()
733
+ with session.begin():
734
+ loadbalancer = self.loadbalancer_repo.get(
735
+ session, id=loadbalancer_id)
710
736
  LOG.debug("Updating VIP for listener delete on load_balancer %s.",
711
737
  loadbalancer.id)
712
738
  self.network_driver.update_vip(loadbalancer, for_delete=True)
@@ -717,10 +743,12 @@ class GetAmphoraNetworkConfigs(BaseNetworkTask):
717
743
 
718
744
  def execute(self, loadbalancer, amphora=None):
719
745
  LOG.debug("Retrieving vip network details.")
720
- db_amp = self.amphora_repo.get(db_apis.get_session(),
721
- id=amphora.get(constants.ID))
722
- db_lb = self.loadbalancer_repo.get(
723
- db_apis.get_session(), id=loadbalancer[constants.LOADBALANCER_ID])
746
+ session = db_apis.get_session()
747
+ with session.begin():
748
+ db_amp = self.amphora_repo.get(session,
749
+ id=amphora.get(constants.ID))
750
+ db_lb = self.loadbalancer_repo.get(
751
+ session, id=loadbalancer[constants.LOADBALANCER_ID])
724
752
  db_configs = self.network_driver.get_network_configs(
725
753
  db_lb, amphora=db_amp)
726
754
  provider_dict = {}
@@ -734,9 +762,11 @@ class GetAmphoraNetworkConfigsByID(BaseNetworkTask):
734
762
 
735
763
  def execute(self, loadbalancer_id, amphora_id=None):
736
764
  LOG.debug("Retrieving vip network details.")
737
- loadbalancer = self.loadbalancer_repo.get(db_apis.get_session(),
738
- id=loadbalancer_id)
739
- amphora = self.amphora_repo.get(db_apis.get_session(), id=amphora_id)
765
+ session = db_apis.get_session()
766
+ with session.begin():
767
+ loadbalancer = self.loadbalancer_repo.get(session,
768
+ id=loadbalancer_id)
769
+ amphora = self.amphora_repo.get(session, id=amphora_id)
740
770
  db_configs = self.network_driver.get_network_configs(loadbalancer,
741
771
  amphora=amphora)
742
772
  provider_dict = {}
@@ -750,8 +780,10 @@ class GetAmphoraeNetworkConfigs(BaseNetworkTask):
750
780
 
751
781
  def execute(self, loadbalancer_id):
752
782
  LOG.debug("Retrieving vip network details.")
753
- db_lb = self.loadbalancer_repo.get(
754
- db_apis.get_session(), id=loadbalancer_id)
783
+ session = db_apis.get_session()
784
+ with session.begin():
785
+ db_lb = self.loadbalancer_repo.get(
786
+ session, id=loadbalancer_id)
755
787
  db_configs = self.network_driver.get_network_configs(db_lb)
756
788
  provider_dict = {}
757
789
  for amp_id, amp_conf in db_configs.items():
@@ -763,8 +795,10 @@ class FailoverPreparationForAmphora(BaseNetworkTask):
763
795
  """Task to prepare an amphora for failover."""
764
796
 
765
797
  def execute(self, amphora):
766
- db_amp = self.amphora_repo.get(db_apis.get_session(),
767
- id=amphora[constants.ID])
798
+ session = db_apis.get_session()
799
+ with session.begin():
800
+ db_amp = self.amphora_repo.get(session,
801
+ id=amphora[constants.ID])
768
802
  LOG.debug("Prepare amphora %s for failover.", amphora[constants.ID])
769
803
 
770
804
  self.network_driver.failover_preparation(db_amp)
@@ -799,8 +833,10 @@ class PlugPorts(BaseNetworkTask):
799
833
  """Task to plug neutron ports into a compute instance."""
800
834
 
801
835
  def execute(self, amphora, ports):
802
- db_amp = self.amphora_repo.get(db_apis.get_session(),
803
- id=amphora[constants.ID])
836
+ session = db_apis.get_session()
837
+ with session.begin():
838
+ db_amp = self.amphora_repo.get(session,
839
+ id=amphora[constants.ID])
804
840
  for port in ports:
805
841
  LOG.debug('Plugging port ID: %(port_id)s into compute instance: '
806
842
  '%(compute_id)s.',
@@ -816,15 +852,17 @@ class ApplyQos(BaseNetworkTask):
816
852
  is_revert=False, request_qos_id=None):
817
853
  """Call network driver to apply QoS Policy on the vrrp ports."""
818
854
 
819
- if not amps_data:
820
- db_lb = self.loadbalancer_repo.get(
821
- db_apis.get_session(),
822
- id=loadbalancer[constants.LOADBALANCER_ID])
823
- amps_data = db_lb.amphorae
855
+ session = db_apis.get_session()
856
+ with session.begin():
857
+ if not amps_data:
858
+ db_lb = self.loadbalancer_repo.get(
859
+ session,
860
+ id=loadbalancer[constants.LOADBALANCER_ID])
861
+ amps_data = db_lb.amphorae
824
862
 
825
- amps_data = [amp
826
- for amp in amps_data
827
- if amp.status == constants.AMPHORA_ALLOCATED]
863
+ amps_data = [amp
864
+ for amp in amps_data
865
+ if amp.status == constants.AMPHORA_ALLOCATED]
828
866
 
829
867
  apply_qos = ApplyQosAmphora()
830
868
  for amp_data in amps_data:
@@ -833,9 +871,11 @@ class ApplyQos(BaseNetworkTask):
833
871
 
834
872
  def execute(self, loadbalancer, amps_data=None, update_dict=None):
835
873
  """Apply qos policy on the vrrp ports which are related with vip."""
836
- db_lb = self.loadbalancer_repo.get(
837
- db_apis.get_session(),
838
- id=loadbalancer[constants.LOADBALANCER_ID])
874
+ session = db_apis.get_session()
875
+ with session.begin():
876
+ db_lb = self.loadbalancer_repo.get(
877
+ session,
878
+ id=loadbalancer[constants.LOADBALANCER_ID])
839
879
 
840
880
  qos_policy_id = db_lb.vip.qos_policy_id
841
881
  if not qos_policy_id and (
octavia/db/api.py CHANGED
@@ -12,15 +12,13 @@
12
12
  # License for the specific language governing permissions and limitations
13
13
  # under the License.
14
14
 
15
- import contextlib
16
15
  import time
17
16
 
18
17
  from sqlalchemy.sql.expression import select
19
18
 
20
19
  from oslo_config import cfg
21
- from oslo_db.sqlalchemy import session as db_session
20
+ from oslo_db.sqlalchemy import enginefacade
22
21
  from oslo_log import log as logging
23
- from oslo_utils import excutils
24
22
 
25
23
  LOG = logging.getLogger(__name__)
26
24
  _FACADE = None
@@ -29,32 +27,37 @@ _FACADE = None
29
27
  def _create_facade_lazily():
30
28
  global _FACADE
31
29
  if _FACADE is None:
32
- _FACADE = db_session.EngineFacade.from_config(cfg.CONF, sqlite_fk=True)
33
- return _FACADE
30
+ _FACADE = True
31
+ enginefacade.configure(sqlite_fk=True, expire_on_commit=True)
32
+
33
+
34
+ def _get_transaction_context(reader=False):
35
+ _create_facade_lazily()
36
+ # TODO(gthiemonge) Create and use new functions to get read-only sessions
37
+ if reader:
38
+ context = enginefacade.reader
39
+ else:
40
+ context = enginefacade.writer
41
+ return context
42
+
43
+
44
+ def _get_sessionmaker(reader=False):
45
+ context = _get_transaction_context(reader)
46
+ return context.get_sessionmaker()
34
47
 
35
48
 
36
49
  def get_engine():
37
- facade = _create_facade_lazily()
38
- return facade.get_engine()
50
+ context = _get_transaction_context()
51
+ return context.get_engine()
39
52
 
40
53
 
41
- def get_session(expire_on_commit=True, autocommit=True):
54
+ def get_session():
42
55
  """Helper method to grab session."""
43
- facade = _create_facade_lazily()
44
- return facade.get_session(expire_on_commit=expire_on_commit,
45
- autocommit=autocommit)
46
-
47
-
48
- @contextlib.contextmanager
49
- def get_lock_session():
50
- """Context manager for using a locking (not auto-commit) session."""
51
- lock_session = get_session(autocommit=False)
52
- try:
53
- yield lock_session
54
- lock_session.commit()
55
- except Exception:
56
- with excutils.save_and_reraise_exception():
57
- lock_session.rollback()
56
+ return _get_sessionmaker()()
57
+
58
+
59
+ def session():
60
+ return _get_sessionmaker()
58
61
 
59
62
 
60
63
  def wait_for_connection(exit_event):
octavia/db/base_models.py CHANGED
@@ -16,8 +16,8 @@ from oslo_db.sqlalchemy import models
16
16
  from oslo_utils import strutils
17
17
  from oslo_utils import uuidutils
18
18
  import sqlalchemy as sa
19
- from sqlalchemy.ext import declarative
20
19
  from sqlalchemy.orm import collections
20
+ from sqlalchemy.orm import declarative_base
21
21
 
22
22
 
23
23
  class OctaviaBase(models.ModelBase):
@@ -189,7 +189,7 @@ class TagMixin(object):
189
189
  self._tags = new_tags
190
190
 
191
191
 
192
- BASE = declarative.declarative_base(cls=OctaviaBase)
192
+ BASE = declarative_base(cls=OctaviaBase)
193
193
 
194
194
 
195
195
  class Tags(BASE):
octavia/db/healthcheck.py CHANGED
@@ -12,6 +12,7 @@
12
12
  # License for the specific language governing permissions and limitations
13
13
  # under the License.
14
14
  from oslo_log import log as logging
15
+ from sqlalchemy import text
15
16
 
16
17
  from octavia.i18n import _
17
18
 
@@ -28,7 +29,7 @@ def check_database_connection(session):
28
29
  :returns: True if the connection check is successful, False if not.
29
30
  """
30
31
  try:
31
- session.execute('SELECT 1;')
32
+ session.execute(text('SELECT 1;'))
32
33
  return True, None
33
34
  except Exception as e:
34
35
  message = _('Database health check failed due to: {err}.').format(
@@ -0,0 +1,42 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
2
+ # not use this file except in compliance with the License. You may obtain
3
+ # a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+ # License for the specific language governing permissions and limitations
11
+ # under the License.
12
+
13
+ """Add HTTP Strict Transport Security support
14
+
15
+ Revision ID: 632152d2d32e
16
+ Revises: 0995c26fc506
17
+ Create Date: 2023-04-19 13:36:44.015581
18
+
19
+ """
20
+
21
+ from alembic import op
22
+ import sqlalchemy as sa
23
+
24
+
25
+ # revision identifiers, used by Alembic.
26
+ revision = '632152d2d32e'
27
+ down_revision = '0995c26fc506'
28
+
29
+
30
+ def upgrade():
31
+ op.add_column(
32
+ 'listener',
33
+ sa.Column('hsts_max_age', sa.Integer, nullable=True)
34
+ )
35
+ op.add_column(
36
+ 'listener',
37
+ sa.Column('hsts_include_subdomains', sa.Boolean, nullable=True)
38
+ )
39
+ op.add_column(
40
+ 'listener',
41
+ sa.Column('hsts_preload', sa.Boolean, nullable=True)
42
+ )
octavia/db/models.py CHANGED
@@ -19,6 +19,7 @@ from oslo_db.sqlalchemy import models
19
19
  import sqlalchemy as sa
20
20
  from sqlalchemy.ext import orderinglist
21
21
  from sqlalchemy import orm
22
+ from sqlalchemy.orm import Mapped
22
23
  from sqlalchemy.orm import validates
23
24
  from sqlalchemy.sql import func
24
25
  from sqlalchemy_utils import ScalarListType
@@ -353,7 +354,8 @@ class Pool(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin,
353
354
  "SessionPersistence", uselist=False, cascade="delete",
354
355
  back_populates="pool")
355
356
  _default_listeners = orm.relationship("Listener", uselist=True,
356
- back_populates="default_pool")
357
+ back_populates="default_pool",
358
+ cascade_backrefs=False)
357
359
  l7policies = orm.relationship("L7Policy", uselist=True,
358
360
  back_populates="redirect_pool")
359
361
  _tags = orm.relationship(
@@ -453,6 +455,7 @@ class LoadBalancer(base_models.BASE, base_models.IdMixin,
453
455
  sa.ForeignKey("availability_zone.name",
454
456
  name="fk_load_balancer_availability_zone_name"),
455
457
  nullable=True)
458
+ flavor: Mapped["Flavor"] = orm.relationship("Flavor")
456
459
 
457
460
  def __str__(self):
458
461
  return (f"LoadBalancer(id={self.id!r}, name={self.name!r}, "
@@ -573,7 +576,8 @@ class Listener(base_models.BASE, base_models.IdMixin,
573
576
  load_balancer = orm.relationship("LoadBalancer", uselist=False,
574
577
  back_populates="listeners")
575
578
  default_pool = orm.relationship("Pool", uselist=False,
576
- back_populates="_default_listeners")
579
+ back_populates="_default_listeners",
580
+ cascade_backrefs=False)
577
581
  sni_containers = orm.relationship(
578
582
  'SNI', cascade='all,delete-orphan',
579
583
  uselist=True, backref=orm.backref('listener', uselist=False))
@@ -599,6 +603,9 @@ class Listener(base_models.BASE, base_models.IdMixin,
599
603
  tls_ciphers = sa.Column(sa.String(2048), nullable=True)
600
604
  tls_versions = sa.Column(ScalarListType(), nullable=True)
601
605
  alpn_protocols = sa.Column(ScalarListType(), nullable=True)
606
+ hsts_max_age = sa.Column(sa.Integer, nullable=True)
607
+ hsts_include_subdomains = sa.Column(sa.Boolean, nullable=True)
608
+ hsts_preload = sa.Column(sa.Boolean, nullable=True)
602
609
 
603
610
  _tags = orm.relationship(
604
611
  'Tags',
@@ -907,6 +914,7 @@ class Flavor(base_models.BASE,
907
914
  sa.ForeignKey("flavor_profile.id",
908
915
  name="fk_flavor_flavor_profile_id"),
909
916
  nullable=False)
917
+ flavor_profile: Mapped["FlavorProfile"] = orm.relationship("FlavorProfile")
910
918
 
911
919
 
912
920
  class AvailabilityZoneProfile(base_models.BASE, base_models.IdMixin,
@@ -942,6 +950,8 @@ class AvailabilityZone(base_models.BASE,
942
950
  sa.ForeignKey("availability_zone_profile.id",
943
951
  name="fk_az_az_profile_id"),
944
952
  nullable=False)
953
+ availability_zone_profile: Mapped["AvailabilityZoneProfile"] = (
954
+ orm.relationship("AvailabilityZoneProfile"))
945
955
 
946
956
 
947
957
  class ClientAuthenticationMode(base_models.BASE):
octavia/db/prepare.py CHANGED
@@ -169,6 +169,8 @@ def create_pool(pool_dict, lb_id=None):
169
169
 
170
170
 
171
171
  def create_member(member_dict, pool_id, has_health_monitor=False):
172
+ if not member_dict.get('id'):
173
+ member_dict['id'] = uuidutils.generate_uuid()
172
174
  member_dict['pool_id'] = pool_id
173
175
  member_dict[constants.PROVISIONING_STATUS] = constants.PENDING_CREATE
174
176
  if has_health_monitor: