aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ansible/module_utils/kolla_docker_worker.py4
-rw-r--r--ansible/roles/cloudkitty/defaults/main.yml12
-rw-r--r--ansible/roles/etcd/defaults/main.yml4
-rw-r--r--ansible/roles/loadbalancer/templates/proxysql/proxysql.yaml.j22
-rw-r--r--ansible/roles/service-uwsgi-config/defaults/main.yml1
-rw-r--r--ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j23
-rw-r--r--releasenotes/notes/cloudkitty-haproxy-custom-timeouts-2f5c30619269d2f0.yaml10
-rw-r--r--releasenotes/notes/fix-proxysql-distributed-reads-5142e40995499611.yaml13
-rw-r--r--tests/kolla_container_tests/test_docker_worker.py60
9 files changed, 105 insertions, 4 deletions
diff --git a/ansible/module_utils/kolla_docker_worker.py b/ansible/module_utils/kolla_docker_worker.py
index f488bab66..db41d5599 100644
--- a/ansible/module_utils/kolla_docker_worker.py
+++ b/ansible/module_utils/kolla_docker_worker.py
@@ -41,8 +41,8 @@ class DockerWorker(ContainerWorker):
def generate_tls(self):
tls = {'verify': self.params.get('tls_verify')}
- tls_cert = self.params.get('tls_cert'),
- tls_key = self.params.get('tls_key'),
+ tls_cert = self.params.get('tls_cert')
+ tls_key = self.params.get('tls_key')
tls_cacert = self.params.get('tls_cacert')
if tls['verify']:
diff --git a/ansible/roles/cloudkitty/defaults/main.yml b/ansible/roles/cloudkitty/defaults/main.yml
index 0b74f8e27..8cfe7d3a4 100644
--- a/ansible/roles/cloudkitty/defaults/main.yml
+++ b/ansible/roles/cloudkitty/defaults/main.yml
@@ -16,9 +16,12 @@ cloudkitty_services:
external: false
port: "{{ cloudkitty_api_port }}"
listen_port: "{{ cloudkitty_api_listen_port }}"
+ frontend_http_extra:
+ - "timeout client {{ haproxy_cloudkitty_api_client_timeout }}"
backend_http_extra:
- "option httpchk GET /healthcheck"
- "http-check expect status 200"
+ - "timeout server {{ haproxy_cloudkitty_api_server_timeout }}"
cloudkitty_api_external:
enabled: "{{ enable_cloudkitty }}"
mode: "http"
@@ -26,9 +29,12 @@ cloudkitty_services:
external_fqdn: "{{ cloudkitty_external_fqdn }}"
port: "{{ cloudkitty_api_public_port }}"
listen_port: "{{ cloudkitty_api_listen_port }}"
+ frontend_http_extra:
+ - "timeout client {{ haproxy_cloudkitty_api_client_timeout }}"
backend_http_extra:
- "option httpchk GET /healthcheck"
- "http-check expect status 200"
+ - "timeout server {{ haproxy_cloudkitty_api_server_timeout }}"
cloudkitty-processor:
container_name: "cloudkitty_processor"
group: "cloudkitty-processor"
@@ -53,6 +59,12 @@ cloudkitty_database_user: "{% if use_preconfigured_databases | bool and use_comm
cloudkitty_database_address: "{{ database_address | put_address_in_context('url') }}:{{ database_port }}"
####################
+# HAProxy
+####################
+haproxy_cloudkitty_api_client_timeout: "1m"
+haproxy_cloudkitty_api_server_timeout: "1m"
+
+####################
# Database sharding
####################
cloudkitty_database_shard_root_user: "{% if enable_proxysql | bool %}root_shard_{{ cloudkitty_database_shard_id }}{% else %}{{ database_user }}{% endif %}"
diff --git a/ansible/roles/etcd/defaults/main.yml b/ansible/roles/etcd/defaults/main.yml
index 563eff9dc..510e8fe2b 100644
--- a/ansible/roles/etcd/defaults/main.yml
+++ b/ansible/roles/etcd/defaults/main.yml
@@ -92,7 +92,9 @@ etcd_enable_healthchecks: "{{ enable_container_healthchecks }}"
etcd_healthcheck_interval: "{{ default_container_healthcheck_interval }}"
etcd_healthcheck_retries: "{{ default_container_healthcheck_retries }}"
etcd_healthcheck_start_period: "{{ default_container_healthcheck_start_period }}"
-etcd_healthcheck_test: ["CMD-SHELL", "healthcheck_curl http://{{ api_interface_address | put_address_in_context('url') }}:{{ etcd_client_port }}/health"]
+etcd_healthcheck_test:
+ - "CMD-SHELL"
+ - "healthcheck_curl {{ etcd_protocol }}://{{ api_interface_address | put_address_in_context('url') }}:{{ etcd_client_port }}/health"
etcd_healthcheck_timeout: "{{ default_container_healthcheck_timeout }}"
etcd_healthcheck:
interval: "{{ etcd_healthcheck_interval }}"
diff --git a/ansible/roles/loadbalancer/templates/proxysql/proxysql.yaml.j2 b/ansible/roles/loadbalancer/templates/proxysql/proxysql.yaml.j2
index f7a8b0a08..549051383 100644
--- a/ansible/roles/loadbalancer/templates/proxysql/proxysql.yaml.j2
+++ b/ansible/roles/loadbalancer/templates/proxysql/proxysql.yaml.j2
@@ -111,6 +111,6 @@ mysql_galera_hostgroups:
offline_hostgroup: {{ _offline_group }}
max_connections: {{ proxysql_backend_max_connections }}
max_writers: 1
- writer_is_also_reader: 0
+ writer_is_also_reader: 2
comment: "Galera cluster for shard {{ shard_id }}"
{% endfor %}
diff --git a/ansible/roles/service-uwsgi-config/defaults/main.yml b/ansible/roles/service-uwsgi-config/defaults/main.yml
index 9c5e13ed3..e5a452dc4 100644
--- a/ansible/roles/service-uwsgi-config/defaults/main.yml
+++ b/ansible/roles/service-uwsgi-config/defaults/main.yml
@@ -7,3 +7,4 @@ service_uwsgi_config_socket_port: ""
service_uwsgi_config_tls_backend: false
service_uwsgi_config_worker_timeout: 80
service_uwsgi_config_workers: "{{ openstack_service_workers }}"
+service_uwsgi_config_env: {}
diff --git a/ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2 b/ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2
index e8873eefc..1095aa1fc 100644
--- a/ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2
+++ b/ansible/roles/service-uwsgi-config/templates/uwsgi.ini.j2
@@ -46,3 +46,6 @@ uid = {{ service_uwsgi_config_uid }}
{% endif %}
worker-reload-mercy = {{ service_uwsgi_config_worker_timeout }}
static-map = /static=/var/lib/kolla/venv/lib/python3/site-packages/static
+{% for key, value in service_uwsgi_config_env.items() %}
+env = {{ key }}={{ value }}
+{% endfor %}
diff --git a/releasenotes/notes/cloudkitty-haproxy-custom-timeouts-2f5c30619269d2f0.yaml b/releasenotes/notes/cloudkitty-haproxy-custom-timeouts-2f5c30619269d2f0.yaml
new file mode 100644
index 000000000..cbab01202
--- /dev/null
+++ b/releasenotes/notes/cloudkitty-haproxy-custom-timeouts-2f5c30619269d2f0.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ CloudKitty v1 API does not support pagination, which may require increasing
+ timeouts for large requests. Adds two HAProxy timeout variables for the
+ CloudKitty API: ``haproxy_cloudkitty_api_client_timeout`` and
+ ``haproxy_cloudkitty_api_server_timeout``. These variables are used to
+ populate HAProxy's ``frontend_http_extra`` and ``backend_http_extra`` for
+ the ``cloudkitty_api`` and ``cloudkitty_api_external`` listeners. The
+ defaults are set to one minute.
diff --git a/releasenotes/notes/fix-proxysql-distributed-reads-5142e40995499611.yaml b/releasenotes/notes/fix-proxysql-distributed-reads-5142e40995499611.yaml
new file mode 100644
index 000000000..1ec90b0fd
--- /dev/null
+++ b/releasenotes/notes/fix-proxysql-distributed-reads-5142e40995499611.yaml
@@ -0,0 +1,13 @@
+---
+fixes:
+ - |
+ Fix ProxySQL Galera configuration so that the backup writer
+ node also serves read queries, instead of leaving it idle
+ and sending all reads to the single remaining reader node.
+ This is done by setting ``writer_is_also_reader`` to ``2``,
+ which adds backup writer hostgroup nodes to the reader
+ hostgroup while still excluding the active writer node. See
+ the `ProxySQL documentation
+ <https://proxysql.com/documentation/group-replication-configuration/>`__
+ for details.
+ `LP#2167037 <https://launchpad.net/bugs/2167037>`__
diff --git a/tests/kolla_container_tests/test_docker_worker.py b/tests/kolla_container_tests/test_docker_worker.py
index e32da66cb..90f1a2d41 100644
--- a/tests/kolla_container_tests/test_docker_worker.py
+++ b/tests/kolla_container_tests/test_docker_worker.py
@@ -1161,6 +1161,66 @@ class TestVolume(base.BaseTestCase):
)
+class TestTLS(base.BaseTestCase):
+
+ @mock.patch('docker.tls.TLSConfig')
+ def test_tls_disabled_by_default(self, mock_tls_config):
+ self.dw = get_DockerWorker({'name': 'test_container'})
+ self.dw.generate_tls()
+ mock_tls_config.assert_called_once_with(verify=None)
+
+ @mock.patch('docker.tls.TLSConfig')
+ def test_tls_verify_enabled_no_certs(self, mock_tls_config):
+ self.dw = get_DockerWorker({
+ 'name': 'test_container',
+ 'tls_verify': True})
+ self.dw.generate_tls()
+ mock_tls_config.assert_called_once_with(verify=True)
+
+ @mock.patch('os.path.isfile', return_value=True)
+ @mock.patch('os.access', return_value=True)
+ @mock.patch('docker.tls.TLSConfig')
+ def test_tls_verify_with_client_cert_and_key(self, mock_tls_config,
+ mock_access, mock_isfile):
+ self.dw = get_DockerWorker({
+ 'name': 'test_container',
+ 'tls_verify': True,
+ 'tls_cert': '/path/to/cert.pem',
+ 'tls_key': '/path/to/key.pem'})
+ self.dw.generate_tls()
+ mock_tls_config.assert_called_once_with(
+ verify=True,
+ client_cert=('/path/to/cert.pem', '/path/to/key.pem'))
+
+ @mock.patch('os.path.isfile', return_value=True)
+ @mock.patch('os.access', return_value=True)
+ @mock.patch('docker.tls.TLSConfig')
+ def test_tls_verify_with_cacert(self, mock_tls_config,
+ mock_access, mock_isfile):
+ self.dw = get_DockerWorker({
+ 'name': 'test_container',
+ 'tls_verify': True,
+ 'tls_cacert': '/path/to/ca.pem'})
+ self.dw.generate_tls()
+ mock_tls_config.assert_called_once_with(
+ verify='/path/to/ca.pem')
+
+ @mock.patch('os.path.isfile', return_value=False)
+ @mock.patch('os.access', return_value=True)
+ @mock.patch('docker.tls.TLSConfig')
+ def test_tls_verify_cert_file_missing_fails(self, mock_tls_config,
+ mock_access, mock_isfile):
+ self.dw = get_DockerWorker({
+ 'name': 'test_container',
+ 'tls_verify': True,
+ 'tls_cert': '/missing/cert.pem',
+ 'tls_key': '/missing/key.pem'})
+ self.dw.generate_tls()
+ self.dw.module.fail_json.assert_any_call(
+ failed=True,
+ msg='There is no file at "/missing/cert.pem"')
+
+
class TestAttrComp(base.BaseTestCase):
def setUp(self):