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
@@ -23,6 +23,7 @@ from oslo_utils import versionutils
23
23
  from octavia.common.config import cfg
24
24
  from octavia.common import constants
25
25
  from octavia.common import utils as octavia_utils
26
+ from octavia.db import models
26
27
 
27
28
  PROTOCOL_MAP = {
28
29
  constants.PROTOCOL_TCP: 'tcp',
@@ -265,6 +266,8 @@ class JinjaTemplater(object):
265
266
  # listeners' connection limits.
266
267
  connection_limit_sum = 0
267
268
  for listener in listeners:
269
+ if not listener.enabled:
270
+ continue
268
271
  if listener.protocol in constants.LVS_PROTOCOLS:
269
272
  continue
270
273
  if listener.connection_limit and listener.connection_limit > -1:
@@ -298,7 +301,8 @@ class JinjaTemplater(object):
298
301
  'vrrp_priority': amphora.vrrp_priority
299
302
  }
300
303
 
301
- def _transform_listener(self, listener, tls_certs, feature_compatibility,
304
+ def _transform_listener(self, listener: models.Listener, tls_certs,
305
+ feature_compatibility,
302
306
  loadbalancer):
303
307
  """Transforms a listener into an object that will
304
308
 
@@ -363,6 +367,13 @@ class JinjaTemplater(object):
363
367
  ret_value['tls_versions'] = listener.tls_versions
364
368
  if listener.alpn_protocols is not None:
365
369
  ret_value['alpn_protocols'] = ",".join(listener.alpn_protocols)
370
+ if listener.hsts_max_age is not None:
371
+ hsts_directives = f"max-age={listener.hsts_max_age};"
372
+ if listener.hsts_include_subdomains:
373
+ hsts_directives += " includeSubDomains;"
374
+ if listener.hsts_preload:
375
+ hsts_directives += " preload;"
376
+ ret_value['hsts_directives'] = hsts_directives
366
377
 
367
378
  pools = []
368
379
  pool_gen = (pool for pool in listener.pools if
@@ -166,6 +166,9 @@ frontend {{ listener.id }}
166
166
  {% if (listener.protocol.lower() ==
167
167
  constants.PROTOCOL_TERMINATED_HTTPS.lower()) %}
168
168
  redirect scheme https if !{ ssl_fc }
169
+ {% if listener.hsts_directives is defined %}
170
+ http-response set-header Strict-Transport-Security "{{ listener.hsts_directives }}"
171
+ {% endif %}
169
172
  {% endif %}
170
173
  {{ bind_macro(constants, lib_consts, listener, lb_vip_address)|trim() }}
171
174
  {% for add_vip in additional_vips %}
@@ -324,10 +327,10 @@ backend {{ pool.id }}:{{ listener.id }}
324
327
  {% if (pool.session_persistence.type ==
325
328
  constants.SESSION_PERSISTENCE_SOURCE_IP) %}
326
329
  {% if loadbalancer.topology == constants.TOPOLOGY_ACTIVE_STANDBY %}
327
- stick-table type ip size {{ pool.stick_size }} peers {{
330
+ stick-table type ipv6 size {{ pool.stick_size }} peers {{
328
331
  "%s_peers"|format(loadbalancer.id.replace("-", ""))|trim() }}
329
332
  {% else %}
330
- stick-table type ip size {{ pool.stick_size }}
333
+ stick-table type ipv6 size {{ pool.stick_size }}
331
334
  {% endif %}
332
335
  stick on src
333
336
  {% elif (pool.session_persistence.type ==
@@ -20,6 +20,7 @@ from octavia_lib.common import constants as lib_consts
20
20
  from octavia.common.config import cfg
21
21
  from octavia.common import constants
22
22
  from octavia.common import utils as octavia_utils
23
+ from octavia.db import models
23
24
 
24
25
 
25
26
  CONF = cfg.CONF
@@ -59,7 +60,7 @@ class LvsJinjaTemplater(object):
59
60
  self.keepalivedlvs_template = (keepalivedlvs_template or
60
61
  KEEPALIVED_LVS_TEMPLATE)
61
62
 
62
- def build_config(self, listener, **kwargs):
63
+ def build_config(self, listener: models.Listener, **kwargs):
63
64
  """Convert a logical configuration to the Keepalived LVS version
64
65
 
65
66
  :param listener: The listener configuration
@@ -97,7 +98,8 @@ class LvsJinjaTemplater(object):
97
98
  constants=constants,
98
99
  lib_consts=lib_consts)
99
100
 
100
- def _transform_loadbalancer(self, loadbalancer, listener):
101
+ def _transform_loadbalancer(self, loadbalancer: models.LoadBalancer,
102
+ listener: models.Listener):
101
103
  """Transforms a load balancer into an object that will
102
104
 
103
105
  be processed by the templating system
@@ -12,6 +12,7 @@
12
12
  # License for the specific language governing permissions and limitations
13
13
  # under the License.
14
14
 
15
+ from keystoneauth1 import exceptions as ks_exceptions
15
16
  from keystoneauth1 import loading as ks_loading
16
17
  from keystonemiddleware import auth_token
17
18
  from oslo_config import cfg
@@ -32,14 +33,17 @@ class KeystoneSession(object):
32
33
  self._auth = None
33
34
 
34
35
  self.section = section
35
- ks_loading.register_auth_conf_options(cfg.CONF, self.section)
36
- ks_loading.register_session_conf_options(cfg.CONF, self.section)
37
36
 
38
- def get_session(self):
37
+ def get_session(self, auth=None):
39
38
  """Initializes a Keystone session.
40
39
 
41
40
  :return: a Keystone Session object
42
41
  """
42
+ if auth:
43
+ # Do not use the singleton with custom auth params
44
+ return ks_loading.load_session_from_conf_options(
45
+ cfg.CONF, self.section, auth=auth)
46
+
43
47
  if not self._session:
44
48
  self._session = ks_loading.load_session_from_conf_options(
45
49
  cfg.CONF, self.section, auth=self.get_auth())
@@ -48,8 +52,57 @@ class KeystoneSession(object):
48
52
 
49
53
  def get_auth(self):
50
54
  if not self._auth:
51
- self._auth = ks_loading.load_auth_from_conf_options(
52
- cfg.CONF, self.section)
55
+ try:
56
+ self._auth = ks_loading.load_auth_from_conf_options(
57
+ cfg.CONF, self.section)
58
+ except ks_exceptions.auth_plugins.MissingRequiredOptions as e:
59
+ if self.section == constants.SERVICE_AUTH:
60
+ raise e
61
+ # NOTE(gthiemonge): MissingRequiredOptions is raised: there is
62
+ # one or more missing auth options in the config file. It may
63
+ # be due to the migration from python-neutronclient to
64
+ # openstacksdk.
65
+ # With neutronclient, most of the auth settings were in
66
+ # [service_auth] with a few overrides in [neutron],
67
+ # but with openstacksdk, we have all the auth settings in the
68
+ # [neutron] section. In order to support smooth upgrades, in
69
+ # case those options are missing, we override the undefined
70
+ # options with the existing settings from [service_auth].
71
+
72
+ # This code should be removed when all the deployment tools set
73
+ # the correct options in [neutron]
74
+
75
+ # The config options are lazily registered/loaded by keystone,
76
+ # it means that we cannot get/set them before invoking
77
+ # 'load_auth_from_conf_options' on 'service_auth'.
78
+ ks_loading.load_auth_from_conf_options(
79
+ cfg.CONF, constants.SERVICE_AUTH)
80
+
81
+ config = getattr(cfg.CONF, self.section)
82
+ for opt in config:
83
+ # For each option in the [neutron] section, get its setting
84
+ # location, if the location is 'opt_default' or
85
+ # 'set_default', it means that the option is not configured
86
+ # in the config file, it should be replaced with the one
87
+ # from [service_auth]
88
+ loc = cfg.CONF.get_location(opt, self.section)
89
+ if not loc or loc.location in (cfg.Locations.opt_default,
90
+ cfg.Locations.set_default):
91
+ if hasattr(cfg.CONF.service_auth, opt):
92
+ cur_value = getattr(config, opt)
93
+ value = getattr(cfg.CONF.service_auth, opt)
94
+ if value != cur_value:
95
+ log_value = (value if opt != "password"
96
+ else "<hidden>")
97
+ LOG.debug("Overriding [%s].%s with '%s'",
98
+ self.section, opt, log_value)
99
+ cfg.CONF.set_override(opt, value, self.section)
100
+
101
+ # Now we can call load_auth_from_conf_options for this specific
102
+ # service with the newly defined options.
103
+ self._auth = ks_loading.load_auth_from_conf_options(
104
+ cfg.CONF, self.section)
105
+
53
106
  return self._auth
54
107
 
55
108
  def get_service_user_id(self):
@@ -28,11 +28,13 @@ from rfc3986 import validators
28
28
  from wsme import types as wtypes
29
29
 
30
30
  from octavia.common import constants
31
+ from octavia.common import data_models
31
32
  from octavia.common import exceptions
32
33
  from octavia.common import utils
33
34
  from octavia.i18n import _
34
35
 
35
36
  CONF = cfg.CONF
37
+ _ListenerPUT = 'octavia.api.v2.types.listener.ListenerPUT'
36
38
 
37
39
 
38
40
  def url(url, require_scheme=True):
@@ -531,3 +533,36 @@ def check_alpn_protocols(protocols):
531
533
  if invalid_protocols:
532
534
  raise exceptions.ValidationException(
533
535
  detail=_('Invalid ALPN protocol: ' + ', '.join(invalid_protocols)))
536
+
537
+
538
+ def check_hsts_options(listener: dict):
539
+ if ((listener.get('hsts_include_subdomains') or
540
+ listener.get('hsts_preload')) and
541
+ not isinstance(listener.get('hsts_max_age'), int)):
542
+ raise exceptions.ValidationException(
543
+ detail=_('HSTS configuration options hsts_include_subdomains and '
544
+ 'hsts_preload only make sense if hsts_max_age is '
545
+ 'set as well.'))
546
+
547
+ if (isinstance(listener.get('hsts_max_age'), int) and
548
+ listener['protocol'] != constants.PROTOCOL_TERMINATED_HTTPS):
549
+ raise exceptions.ValidationException(
550
+ detail=_('The HSTS feature can only be used for listeners using '
551
+ 'the TERMINATED_HTTPS protocol.'))
552
+
553
+
554
+ def check_hsts_options_put(listener: _ListenerPUT,
555
+ db_listener: data_models.Listener):
556
+ hsts_disabled = all(obj.hsts_max_age in [None, wtypes.Unset] for obj
557
+ in (db_listener, listener))
558
+ if ((listener.hsts_include_subdomains or listener.hsts_preload) and
559
+ hsts_disabled):
560
+ raise exceptions.ValidationException(
561
+ detail=_('Cannot enable hsts_include_subdomains or hsts_preload '
562
+ 'if hsts_max_age was not set as well.'))
563
+
564
+ if (isinstance(listener.hsts_max_age, int) and
565
+ db_listener.protocol != constants.PROTOCOL_TERMINATED_HTTPS):
566
+ raise exceptions.ValidationException(
567
+ detail=_('The HSTS feature can only be used for listeners using '
568
+ 'the TERMINATED_HTTPS protocol.'))
@@ -12,6 +12,8 @@
12
12
  # License for the specific language governing permissions and limitations
13
13
  # under the License.
14
14
 
15
+ from collections import namedtuple
16
+
15
17
  from oslo_log import log as logging
16
18
  from oslo_utils import uuidutils
17
19
 
@@ -23,6 +25,9 @@ from octavia.network import data_models as network_models
23
25
  LOG = logging.getLogger(__name__)
24
26
 
25
27
 
28
+ NoopServerGroup = namedtuple('ServerGroup', ['id'])
29
+
30
+
26
31
  class NoopManager(object):
27
32
  def __init__(self):
28
33
  super().__init__()
@@ -76,6 +81,7 @@ class NoopManager(object):
76
81
  LOG.debug("Create Server Group %s no-op, name %s, policy %s ",
77
82
  self.__class__.__name__, name, policy)
78
83
  self.computeconfig[(name, policy)] = (name, policy, 'create')
84
+ return NoopServerGroup(id=uuidutils.generate_uuid())
79
85
 
80
86
  def delete_server_group(self, server_group_id):
81
87
  LOG.debug("Delete Server Group %s no-op, id %s ",
@@ -23,7 +23,6 @@ from oslo_log import log as logging
23
23
  from oslo_utils import excutils
24
24
 
25
25
  from octavia.common import constants
26
- from octavia.controller.worker.v1 import controller_worker as cw1
27
26
  from octavia.controller.worker.v2 import controller_worker as cw2
28
27
  from octavia.db import api as db_api
29
28
  from octavia.db import repositories as repo
@@ -58,10 +57,7 @@ def update_stats_on_done(stats, fut):
58
57
 
59
58
  class HealthManager(object):
60
59
  def __init__(self, exit_event):
61
- if CONF.api_settings.default_provider_driver == constants.AMPHORAV1:
62
- self.cw = cw1.ControllerWorker()
63
- else:
64
- self.cw = cw2.ControllerWorker()
60
+ self.cw = cw2.ControllerWorker()
65
61
  self.threads = CONF.health_manager.failover_threads
66
62
  self.executor = futures.ThreadPoolExecutor(max_workers=self.threads)
67
63
  self.amp_repo = repo.AmphoraRepository()
@@ -91,7 +87,8 @@ class HealthManager(object):
91
87
  amp_health = None
92
88
  lock_session = None
93
89
  try:
94
- lock_session = db_api.get_session(autocommit=False)
90
+ lock_session = db_api.get_session()
91
+ lock_session.begin()
95
92
  amp_health = self.amp_health_repo.get_stale_amphora(
96
93
  lock_session)
97
94
  if amp_health:
@@ -19,8 +19,6 @@ from oslo_config import cfg
19
19
  from oslo_log import log as logging
20
20
  from sqlalchemy.orm import exc as sqlalchemy_exceptions
21
21
 
22
- from octavia.common import constants
23
- from octavia.controller.worker.v1 import controller_worker as cw1
24
22
  from octavia.controller.worker.v2 import controller_worker as cw2
25
23
  from octavia.db import api as db_api
26
24
  from octavia.db import repositories as repo
@@ -41,24 +39,26 @@ class DatabaseCleanup(object):
41
39
  seconds=CONF.house_keeping.amphora_expiry_age)
42
40
 
43
41
  session = db_api.get_session()
44
- amp_ids = self.amp_repo.get_all_deleted_expiring(session,
45
- exp_age=exp_age)
46
-
47
- for amp_id in amp_ids:
48
- # If we're here, we already think the amp is expiring according to
49
- # the amphora table. Now check it is expired in the health table.
50
- # In this way, we ensure that amps aren't deleted unless they are
51
- # both expired AND no longer receiving zombie heartbeats.
52
- if self.amp_health_repo.check_amphora_health_expired(
53
- session, amp_id, exp_age):
54
- LOG.debug('Attempting to purge db record for Amphora ID: %s',
55
- amp_id)
56
- self.amp_repo.delete(session, id=amp_id)
57
- try:
58
- self.amp_health_repo.delete(session, amphora_id=amp_id)
59
- except sqlalchemy_exceptions.NoResultFound:
60
- pass # Best effort delete, this record might not exist
61
- LOG.info('Purged db record for Amphora ID: %s', amp_id)
42
+ with session.begin():
43
+ amp_ids = self.amp_repo.get_all_deleted_expiring(session,
44
+ exp_age=exp_age)
45
+
46
+ for amp_id in amp_ids:
47
+ # If we're here, we already think the amp is expiring according
48
+ # to the amphora table. Now check it is expired in the health
49
+ # table.
50
+ # In this way, we ensure that amps aren't deleted unless they
51
+ # are both expired AND no longer receiving zombie heartbeats.
52
+ if self.amp_health_repo.check_amphora_health_expired(
53
+ session, amp_id, exp_age):
54
+ LOG.debug('Attempting to purge db record for Amphora ID: '
55
+ '%s', amp_id)
56
+ self.amp_repo.delete(session, id=amp_id)
57
+ try:
58
+ self.amp_health_repo.delete(session, amphora_id=amp_id)
59
+ except sqlalchemy_exceptions.NoResultFound:
60
+ pass # Best effort delete, this record might not exist
61
+ LOG.info('Purged db record for Amphora ID: %s', amp_id)
62
62
 
63
63
  def cleanup_load_balancers(self):
64
64
  """Checks the DB for old load balancers and triggers their removal."""
@@ -66,36 +66,35 @@ class DatabaseCleanup(object):
66
66
  seconds=CONF.house_keeping.load_balancer_expiry_age)
67
67
 
68
68
  session = db_api.get_session()
69
- lb_ids = self.lb_repo.get_all_deleted_expiring(session,
70
- exp_age=exp_age)
69
+ with session.begin():
70
+ lb_ids = self.lb_repo.get_all_deleted_expiring(session,
71
+ exp_age=exp_age)
71
72
 
72
- for lb_id in lb_ids:
73
- LOG.info('Attempting to delete load balancer id : %s', lb_id)
74
- self.lb_repo.delete(session, id=lb_id)
75
- LOG.info('Deleted load balancer id : %s', lb_id)
73
+ for lb_id in lb_ids:
74
+ LOG.info('Attempting to delete load balancer id : %s', lb_id)
75
+ self.lb_repo.delete(session, id=lb_id)
76
+ LOG.info('Deleted load balancer id : %s', lb_id)
76
77
 
77
78
 
78
79
  class CertRotation(object):
79
80
  def __init__(self):
80
81
  self.threads = CONF.house_keeping.cert_rotate_threads
81
- if CONF.api_settings.default_provider_driver == constants.AMPHORAV1:
82
- self.cw = cw1.ControllerWorker()
83
- else:
84
- self.cw = cw2.ControllerWorker()
82
+ self.cw = cw2.ControllerWorker()
85
83
 
86
84
  def rotate(self):
87
85
  """Check the amphora db table for expiring auth certs."""
88
86
  amp_repo = repo.AmphoraRepository()
89
87
 
90
88
  with futures.ThreadPoolExecutor(max_workers=self.threads) as executor:
91
- session = db_api.get_session()
92
89
  rotation_count = 0
93
90
  while True:
94
- amp = amp_repo.get_cert_expiring_amphora(session)
95
- if not amp:
96
- break
97
- rotation_count += 1
98
- LOG.debug("Cert expired amphora's id is: %s", amp.id)
99
- executor.submit(self.cw.amphora_cert_rotation, amp.id)
91
+ session = db_api.get_session()
92
+ with session.begin():
93
+ amp = amp_repo.get_cert_expiring_amphora(session)
94
+ if not amp:
95
+ break
96
+ rotation_count += 1
97
+ LOG.debug("Cert expired amphora's id is: %s", amp.id)
98
+ executor.submit(self.cw.amphora_cert_rotation, amp.id)
100
99
  if rotation_count > 0:
101
100
  LOG.info("Rotated certificates for %s amphora", rotation_count)
@@ -35,10 +35,11 @@ class AmphoraBuildRateLimit(object):
35
35
  self.amp_build_req_repo = repo.AmphoraBuildReqRepository()
36
36
 
37
37
  def add_to_build_request_queue(self, amphora_id, build_priority):
38
- self.amp_build_req_repo.add_to_build_queue(
39
- db_apis.get_session(),
40
- amphora_id=amphora_id,
41
- priority=build_priority)
38
+ with db_apis.session().begin() as session:
39
+ self.amp_build_req_repo.add_to_build_queue(
40
+ session,
41
+ amphora_id=amphora_id,
42
+ priority=build_priority)
42
43
  LOG.debug("Added build request for amphora %s to the queue",
43
44
  amphora_id)
44
45
  self.wait_for_build_slot(amphora_id)
@@ -48,9 +48,10 @@ class TaskUtils(object):
48
48
  LOG.debug('Unmarking health monitoring busy on amphora: %s',
49
49
  amphora_id)
50
50
  try:
51
- self.amp_health_repo.update(db_apis.get_session(),
52
- amphora_id=amphora_id,
53
- busy=False)
51
+ with db_apis.session().begin() as session:
52
+ self.amp_health_repo.update(session,
53
+ amphora_id=amphora_id,
54
+ busy=False)
54
55
  except Exception as e:
55
56
  LOG.debug('Failed to update amphora health record %(amp)s '
56
57
  'due to: %(except)s',
@@ -64,9 +65,10 @@ class TaskUtils(object):
64
65
  :param amphora_id: Amphora ID to set the status to ERROR
65
66
  """
66
67
  try:
67
- self.amphora_repo.update(db_apis.get_session(),
68
- id=amphora_id,
69
- status=constants.ERROR)
68
+ with db_apis.session().begin() as session:
69
+ self.amphora_repo.update(session,
70
+ id=amphora_id,
71
+ status=constants.ERROR)
70
72
  except Exception as e:
71
73
  LOG.error("Failed to update amphora %(amp)s "
72
74
  "status to ERROR due to: "
@@ -80,9 +82,10 @@ class TaskUtils(object):
80
82
  :param health_mon_id: Health Monitor ID to set prov status to ERROR
81
83
  """
82
84
  try:
83
- self.health_mon_repo.update(db_apis.get_session(),
84
- id=health_mon_id,
85
- provisioning_status=constants.ERROR)
85
+ with db_apis.session().begin() as session:
86
+ self.health_mon_repo.update(
87
+ session, id=health_mon_id,
88
+ provisioning_status=constants.ERROR)
86
89
  except Exception as e:
87
90
  LOG.error("Failed to update health monitor %(health)s "
88
91
  "provisioning status to ERROR due to: "
@@ -97,9 +100,10 @@ class TaskUtils(object):
97
100
  :param l7policy_id: L7 Policy ID to set provisioning status to ACTIVE
98
101
  """
99
102
  try:
100
- self.l7policy_repo.update(db_apis.get_session(),
101
- id=l7policy_id,
102
- provisioning_status=constants.ACTIVE)
103
+ with db_apis.session().begin() as session:
104
+ self.l7policy_repo.update(session,
105
+ id=l7policy_id,
106
+ provisioning_status=constants.ACTIVE)
103
107
  except Exception as e:
104
108
  LOG.error("Failed to update l7policy %(l7p)s "
105
109
  "provisioning status to ACTIVE due to: "
@@ -113,9 +117,10 @@ class TaskUtils(object):
113
117
  :param l7policy_id: L7 Policy ID to set provisioning status to ERROR
114
118
  """
115
119
  try:
116
- self.l7policy_repo.update(db_apis.get_session(),
117
- id=l7policy_id,
118
- provisioning_status=constants.ERROR)
120
+ with db_apis.session().begin() as session:
121
+ self.l7policy_repo.update(session,
122
+ id=l7policy_id,
123
+ provisioning_status=constants.ERROR)
119
124
  except Exception as e:
120
125
  LOG.error("Failed to update l7policy %(l7p)s "
121
126
  "provisioning status to ERROR due to: "
@@ -129,9 +134,10 @@ class TaskUtils(object):
129
134
  :param l7rule_id: L7 Rule ID to set provisioning status to ERROR
130
135
  """
131
136
  try:
132
- self.l7rule_repo.update(db_apis.get_session(),
133
- id=l7rule_id,
134
- provisioning_status=constants.ERROR)
137
+ with db_apis.session().begin() as session:
138
+ self.l7rule_repo.update(session,
139
+ id=l7rule_id,
140
+ provisioning_status=constants.ERROR)
135
141
  except Exception as e:
136
142
  LOG.error("Failed to update l7rule %(l7r)s "
137
143
  "provisioning status to ERROR due to: "
@@ -145,9 +151,10 @@ class TaskUtils(object):
145
151
  :param listener_id: Listener ID to set provisioning status to ERROR
146
152
  """
147
153
  try:
148
- self.listener_repo.update(db_apis.get_session(),
149
- id=listener_id,
150
- provisioning_status=constants.ERROR)
154
+ with db_apis.session().begin() as session:
155
+ self.listener_repo.update(session,
156
+ id=listener_id,
157
+ provisioning_status=constants.ERROR)
151
158
  except Exception as e:
152
159
  LOG.error("Failed to update listener %(list)s "
153
160
  "provisioning status to ERROR due to: "
@@ -162,9 +169,11 @@ class TaskUtils(object):
162
169
  status to ERROR
163
170
  """
164
171
  try:
165
- self.loadbalancer_repo.update(db_apis.get_session(),
166
- id=loadbalancer_id,
167
- provisioning_status=constants.ERROR)
172
+ with db_apis.session().begin() as session:
173
+ self.loadbalancer_repo.update(
174
+ session,
175
+ id=loadbalancer_id,
176
+ provisioning_status=constants.ERROR)
168
177
  except Exception as e:
169
178
  LOG.error("Failed to update load balancer %(lb)s "
170
179
  "provisioning status to ERROR due to: "
@@ -179,9 +188,10 @@ class TaskUtils(object):
179
188
  status to ACTIVE
180
189
  """
181
190
  try:
182
- self.listener_repo.update(db_apis.get_session(),
183
- id=listener_id,
184
- provisioning_status=constants.ACTIVE)
191
+ with db_apis.session().begin() as session:
192
+ self.listener_repo.update(session,
193
+ id=listener_id,
194
+ provisioning_status=constants.ACTIVE)
185
195
  except Exception as e:
186
196
  LOG.error("Failed to update listener %(list)s "
187
197
  "provisioning status to ACTIVE due to: "
@@ -195,9 +205,10 @@ class TaskUtils(object):
195
205
  :param pool_id: Pool ID to set provisioning status to ACTIVE
196
206
  """
197
207
  try:
198
- self.pool_repo.update(db_apis.get_session(),
199
- id=pool_id,
200
- provisioning_status=constants.ACTIVE)
208
+ with db_apis.session().begin() as session:
209
+ self.pool_repo.update(session,
210
+ id=pool_id,
211
+ provisioning_status=constants.ACTIVE)
201
212
  except Exception as e:
202
213
  LOG.error("Failed to update pool %(pool)s provisioning status "
203
214
  "to ACTIVE due to: %(except)s", {'pool': pool_id,
@@ -212,9 +223,11 @@ class TaskUtils(object):
212
223
  status to ACTIVE
213
224
  """
214
225
  try:
215
- self.loadbalancer_repo.update(db_apis.get_session(),
216
- id=loadbalancer_id,
217
- provisioning_status=constants.ACTIVE)
226
+ with db_apis.session().begin() as session:
227
+ self.loadbalancer_repo.update(
228
+ session,
229
+ id=loadbalancer_id,
230
+ provisioning_status=constants.ACTIVE)
218
231
  except Exception as e:
219
232
  LOG.error("Failed to update load balancer %(lb)s "
220
233
  "provisioning status to ACTIVE due to: "
@@ -228,9 +241,10 @@ class TaskUtils(object):
228
241
  :param member_id: Member ID to set provisioning status to ERROR
229
242
  """
230
243
  try:
231
- self.member_repo.update(db_apis.get_session(),
232
- id=member_id,
233
- provisioning_status=constants.ERROR)
244
+ with db_apis.session().begin() as session:
245
+ self.member_repo.update(session,
246
+ id=member_id,
247
+ provisioning_status=constants.ERROR)
234
248
  except Exception as e:
235
249
  LOG.error("Failed to update member %(member)s "
236
250
  "provisioning status to ERROR due to: "
@@ -244,9 +258,10 @@ class TaskUtils(object):
244
258
  :param pool_id: Pool ID to set provisioning status to ERROR
245
259
  """
246
260
  try:
247
- self.pool_repo.update(db_apis.get_session(),
248
- id=pool_id,
249
- provisioning_status=constants.ERROR)
261
+ with db_apis.session().begin() as session:
262
+ self.pool_repo.update(session,
263
+ id=pool_id,
264
+ provisioning_status=constants.ERROR)
250
265
  except Exception as e:
251
266
  LOG.error("Failed to update pool %(pool)s "
252
267
  "provisioning status to ERROR due to: "
@@ -258,8 +273,9 @@ class TaskUtils(object):
258
273
  :param: loadbalancer_id: Load balancer ID which to get from db
259
274
  """
260
275
  try:
261
- return self.loadbalancer_repo.get(db_apis.get_session(),
262
- id=loadbalancer_id)
276
+ with db_apis.session().begin() as session:
277
+ return self.loadbalancer_repo.get(session,
278
+ id=loadbalancer_id)
263
279
  except Exception as e:
264
280
  LOG.error("Failed to get loadbalancer %(loadbalancer)s "
265
281
  "due to: %(except)s",