octavia 12.0.0.0rc2__py3-none-any.whl → 13.0.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- octavia/amphorae/backends/agent/api_server/osutils.py +1 -0
- octavia/amphorae/backends/agent/api_server/plug.py +21 -7
- octavia/amphorae/backends/agent/api_server/templates/amphora-netns.systemd.j2 +2 -2
- octavia/amphorae/backends/agent/api_server/util.py +21 -0
- octavia/amphorae/backends/health_daemon/health_daemon.py +9 -3
- octavia/amphorae/backends/health_daemon/health_sender.py +2 -0
- octavia/amphorae/backends/utils/interface.py +14 -6
- octavia/amphorae/backends/utils/interface_file.py +6 -3
- octavia/amphorae/backends/utils/keepalivedlvs_query.py +8 -9
- octavia/amphorae/drivers/driver_base.py +1 -2
- octavia/amphorae/drivers/haproxy/rest_api_driver.py +11 -25
- octavia/amphorae/drivers/health/heartbeat_udp.py +34 -24
- octavia/amphorae/drivers/keepalived/jinja/jinja_cfg.py +3 -12
- octavia/amphorae/drivers/noop_driver/driver.py +3 -5
- octavia/api/common/pagination.py +4 -4
- octavia/api/drivers/amphora_driver/v2/driver.py +11 -5
- octavia/api/drivers/driver_agent/driver_get.py +22 -14
- octavia/api/drivers/driver_agent/driver_updater.py +8 -4
- octavia/api/drivers/utils.py +4 -2
- octavia/api/healthcheck/healthcheck_plugins.py +4 -2
- octavia/api/root_controller.py +4 -1
- octavia/api/v2/controllers/amphora.py +35 -38
- octavia/api/v2/controllers/availability_zone_profiles.py +43 -33
- octavia/api/v2/controllers/availability_zones.py +22 -18
- octavia/api/v2/controllers/flavor_profiles.py +37 -28
- octavia/api/v2/controllers/flavors.py +19 -15
- octavia/api/v2/controllers/health_monitor.py +44 -33
- octavia/api/v2/controllers/l7policy.py +52 -40
- octavia/api/v2/controllers/l7rule.py +68 -55
- octavia/api/v2/controllers/listener.py +88 -61
- octavia/api/v2/controllers/load_balancer.py +52 -34
- octavia/api/v2/controllers/member.py +63 -52
- octavia/api/v2/controllers/pool.py +55 -42
- octavia/api/v2/controllers/quotas.py +5 -3
- octavia/api/v2/types/listener.py +15 -0
- octavia/cmd/octavia_worker.py +0 -3
- octavia/cmd/status.py +1 -4
- octavia/common/clients.py +25 -45
- octavia/common/config.py +64 -22
- octavia/common/constants.py +3 -2
- octavia/common/data_models.py +7 -1
- octavia/common/jinja/haproxy/combined_listeners/jinja_cfg.py +12 -1
- octavia/common/jinja/haproxy/combined_listeners/templates/macros.j2 +5 -2
- octavia/common/jinja/lvs/jinja_cfg.py +4 -2
- octavia/common/keystone.py +58 -5
- octavia/common/validate.py +35 -0
- octavia/compute/drivers/noop_driver/driver.py +6 -0
- octavia/controller/healthmanager/health_manager.py +3 -6
- octavia/controller/housekeeping/house_keeping.py +36 -37
- octavia/controller/worker/amphora_rate_limit.py +5 -4
- octavia/controller/worker/task_utils.py +57 -41
- octavia/controller/worker/v2/controller_worker.py +160 -103
- octavia/controller/worker/v2/flows/listener_flows.py +3 -0
- octavia/controller/worker/v2/flows/load_balancer_flows.py +9 -14
- octavia/controller/worker/v2/tasks/amphora_driver_tasks.py +152 -91
- octavia/controller/worker/v2/tasks/compute_tasks.py +4 -2
- octavia/controller/worker/v2/tasks/database_tasks.py +542 -400
- octavia/controller/worker/v2/tasks/network_tasks.py +119 -79
- octavia/db/api.py +26 -23
- octavia/db/base_models.py +2 -2
- octavia/db/healthcheck.py +2 -1
- octavia/db/migration/alembic_migrations/versions/632152d2d32e_add_http_strict_transport_security_.py +42 -0
- octavia/db/models.py +12 -2
- octavia/db/prepare.py +2 -0
- octavia/db/repositories.py +462 -482
- octavia/hacking/checks.py +1 -1
- octavia/network/base.py +0 -14
- octavia/network/drivers/neutron/allowed_address_pairs.py +92 -135
- octavia/network/drivers/neutron/base.py +65 -77
- octavia/network/drivers/neutron/utils.py +69 -85
- octavia/network/drivers/noop_driver/driver.py +0 -7
- octavia/statistics/drivers/update_db.py +10 -10
- octavia/tests/common/constants.py +91 -84
- octavia/tests/common/sample_data_models.py +13 -1
- octavia/tests/fixtures.py +32 -0
- octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +9 -10
- octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py +260 -15
- octavia/tests/functional/api/test_root_controller.py +3 -28
- octavia/tests/functional/api/v2/base.py +5 -3
- octavia/tests/functional/api/v2/test_amphora.py +18 -5
- octavia/tests/functional/api/v2/test_availability_zone_profiles.py +1 -0
- octavia/tests/functional/api/v2/test_listener.py +51 -19
- octavia/tests/functional/api/v2/test_load_balancer.py +10 -1
- octavia/tests/functional/db/base.py +31 -16
- octavia/tests/functional/db/test_models.py +27 -28
- octavia/tests/functional/db/test_repositories.py +407 -50
- octavia/tests/unit/amphorae/backends/agent/api_server/test_amphora_info.py +2 -0
- octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py +1 -1
- octavia/tests/unit/amphorae/backends/agent/api_server/test_plug.py +54 -6
- octavia/tests/unit/amphorae/backends/agent/api_server/test_util.py +35 -0
- octavia/tests/unit/amphorae/backends/health_daemon/test_health_daemon.py +8 -0
- octavia/tests/unit/amphorae/backends/health_daemon/test_health_sender.py +18 -0
- octavia/tests/unit/amphorae/backends/utils/test_interface.py +81 -0
- octavia/tests/unit/amphorae/backends/utils/test_interface_file.py +2 -0
- octavia/tests/unit/amphorae/backends/utils/test_keepalivedlvs_query.py +129 -5
- octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +42 -20
- octavia/tests/unit/amphorae/drivers/health/test_heartbeat_udp.py +18 -20
- octavia/tests/unit/amphorae/drivers/keepalived/jinja/test_jinja_cfg.py +4 -4
- octavia/tests/unit/amphorae/drivers/noop_driver/test_driver.py +4 -1
- octavia/tests/unit/api/drivers/driver_agent/test_driver_get.py +3 -3
- octavia/tests/unit/api/drivers/driver_agent/test_driver_updater.py +11 -13
- octavia/tests/unit/base.py +6 -0
- octavia/tests/unit/cmd/test_interface.py +2 -2
- octavia/tests/unit/cmd/test_status.py +2 -2
- octavia/tests/unit/common/jinja/haproxy/combined_listeners/test_jinja_cfg.py +152 -1
- octavia/tests/unit/common/sample_configs/sample_configs_combined.py +10 -3
- octavia/tests/unit/common/test_clients.py +0 -39
- octavia/tests/unit/common/test_keystone.py +54 -0
- octavia/tests/unit/common/test_validate.py +67 -0
- octavia/tests/unit/controller/healthmanager/test_health_manager.py +8 -22
- octavia/tests/unit/controller/housekeeping/test_house_keeping.py +3 -64
- octavia/tests/unit/controller/worker/test_amphora_rate_limit.py +1 -1
- octavia/tests/unit/controller/worker/test_task_utils.py +44 -24
- octavia/tests/unit/controller/worker/v2/flows/test_load_balancer_flows.py +0 -1
- octavia/tests/unit/controller/worker/v2/tasks/test_amphora_driver_tasks.py +49 -26
- octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +399 -196
- octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks_quota.py +37 -64
- octavia/tests/unit/controller/worker/v2/tasks/test_network_tasks.py +3 -14
- octavia/tests/unit/controller/worker/v2/test_controller_worker.py +2 -2
- octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +456 -561
- octavia/tests/unit/network/drivers/neutron/test_base.py +181 -194
- octavia/tests/unit/network/drivers/neutron/test_utils.py +14 -30
- octavia/tests/unit/statistics/drivers/test_update_db.py +7 -5
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/README.rst +1 -1
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/AUTHORS +4 -0
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/METADATA +4 -4
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/RECORD +141 -189
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/entry_points.txt +1 -2
- octavia-13.0.0.0rc1.dist-info/pbr.json +1 -0
- octavia/api/drivers/amphora_driver/v1/__init__.py +0 -11
- octavia/api/drivers/amphora_driver/v1/driver.py +0 -547
- octavia/controller/queue/v1/__init__.py +0 -11
- octavia/controller/queue/v1/consumer.py +0 -64
- octavia/controller/queue/v1/endpoints.py +0 -160
- octavia/controller/worker/v1/__init__.py +0 -11
- octavia/controller/worker/v1/controller_worker.py +0 -1157
- octavia/controller/worker/v1/flows/__init__.py +0 -11
- octavia/controller/worker/v1/flows/amphora_flows.py +0 -610
- octavia/controller/worker/v1/flows/health_monitor_flows.py +0 -105
- octavia/controller/worker/v1/flows/l7policy_flows.py +0 -94
- octavia/controller/worker/v1/flows/l7rule_flows.py +0 -100
- octavia/controller/worker/v1/flows/listener_flows.py +0 -128
- octavia/controller/worker/v1/flows/load_balancer_flows.py +0 -692
- octavia/controller/worker/v1/flows/member_flows.py +0 -230
- octavia/controller/worker/v1/flows/pool_flows.py +0 -127
- octavia/controller/worker/v1/tasks/__init__.py +0 -11
- octavia/controller/worker/v1/tasks/amphora_driver_tasks.py +0 -453
- octavia/controller/worker/v1/tasks/cert_task.py +0 -51
- octavia/controller/worker/v1/tasks/compute_tasks.py +0 -335
- octavia/controller/worker/v1/tasks/database_tasks.py +0 -2756
- octavia/controller/worker/v1/tasks/lifecycle_tasks.py +0 -173
- octavia/controller/worker/v1/tasks/model_tasks.py +0 -41
- octavia/controller/worker/v1/tasks/network_tasks.py +0 -970
- octavia/controller/worker/v1/tasks/retry_tasks.py +0 -74
- octavia/tests/unit/api/drivers/amphora_driver/v1/__init__.py +0 -11
- octavia/tests/unit/api/drivers/amphora_driver/v1/test_driver.py +0 -824
- octavia/tests/unit/controller/queue/v1/__init__.py +0 -11
- octavia/tests/unit/controller/queue/v1/test_consumer.py +0 -61
- octavia/tests/unit/controller/queue/v1/test_endpoints.py +0 -189
- octavia/tests/unit/controller/worker/v1/__init__.py +0 -11
- octavia/tests/unit/controller/worker/v1/flows/__init__.py +0 -11
- octavia/tests/unit/controller/worker/v1/flows/test_amphora_flows.py +0 -474
- octavia/tests/unit/controller/worker/v1/flows/test_health_monitor_flows.py +0 -72
- octavia/tests/unit/controller/worker/v1/flows/test_l7policy_flows.py +0 -67
- octavia/tests/unit/controller/worker/v1/flows/test_l7rule_flows.py +0 -67
- octavia/tests/unit/controller/worker/v1/flows/test_listener_flows.py +0 -91
- octavia/tests/unit/controller/worker/v1/flows/test_load_balancer_flows.py +0 -431
- octavia/tests/unit/controller/worker/v1/flows/test_member_flows.py +0 -106
- octavia/tests/unit/controller/worker/v1/flows/test_pool_flows.py +0 -77
- octavia/tests/unit/controller/worker/v1/tasks/__init__.py +0 -11
- octavia/tests/unit/controller/worker/v1/tasks/test_amphora_driver_tasks.py +0 -792
- octavia/tests/unit/controller/worker/v1/tasks/test_cert_task.py +0 -46
- octavia/tests/unit/controller/worker/v1/tasks/test_compute_tasks.py +0 -634
- octavia/tests/unit/controller/worker/v1/tasks/test_database_tasks.py +0 -2615
- octavia/tests/unit/controller/worker/v1/tasks/test_database_tasks_quota.py +0 -415
- octavia/tests/unit/controller/worker/v1/tasks/test_lifecycle_tasks.py +0 -401
- octavia/tests/unit/controller/worker/v1/tasks/test_model_tasks.py +0 -44
- octavia/tests/unit/controller/worker/v1/tasks/test_network_tasks.py +0 -1788
- octavia/tests/unit/controller/worker/v1/tasks/test_retry_tasks.py +0 -47
- octavia/tests/unit/controller/worker/v1/test_controller_worker.py +0 -2096
- octavia-12.0.0.0rc2.dist-info/pbr.json +0 -1
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/LICENSE +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/README.rst +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/diskimage-create.sh +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/image-tests.sh +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/requirements.txt +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/test-requirements.txt +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/tox.ini +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/data/share/octavia/diskimage-create/version.txt +0 -0
- {octavia-12.0.0.0rc2.data → octavia-13.0.0.0rc1.data}/scripts/octavia-wsgi +0 -0
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/LICENSE +0 -0
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/WHEEL +0 -0
- {octavia-12.0.0.0rc2.dist-info → octavia-13.0.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -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,
|
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
|
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
|
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,
|
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
|
octavia/common/keystone.py
CHANGED
@@ -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
|
-
|
52
|
-
|
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):
|
octavia/common/validate.py
CHANGED
@@ -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
|
-
|
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(
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
self.
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
70
|
-
|
69
|
+
with session.begin():
|
70
|
+
lb_ids = self.lb_repo.get_all_deleted_expiring(session,
|
71
|
+
exp_age=exp_age)
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
101
|
-
|
102
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
133
|
-
|
134
|
-
|
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
|
-
|
149
|
-
|
150
|
-
|
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
|
-
|
166
|
-
|
167
|
-
|
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
|
-
|
183
|
-
|
184
|
-
|
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
|
-
|
199
|
-
|
200
|
-
|
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
|
-
|
216
|
-
|
217
|
-
|
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
|
-
|
232
|
-
|
233
|
-
|
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
|
-
|
248
|
-
|
249
|
-
|
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
|
-
|
262
|
-
|
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",
|