Add support for HAProxy L7 checks

This change add several configuration options to enable HTTP checks
to the HAProxy configuration, instead of the default TCP connection
checks (which continue to be the default). It also enables /healthcheck
endpoint for neutron-api.

Closes-Bug: #1880610

Change-Id: Ia820d8c2ca709d6b358b1c80d770624568d9a85b
This commit is contained in:
Gabriel Cocenza 2023-02-17 15:27:55 -03:00
parent 25711a290b
commit 7330c5badf
4 changed files with 39 additions and 5 deletions

View File

@ -33,6 +33,7 @@ from charmhelpers.contrib.openstack import context
from charmhelpers.contrib.hahelpers.cluster import ( from charmhelpers.contrib.hahelpers.cluster import (
determine_api_port, determine_api_port,
determine_apache_port, determine_apache_port,
https,
) )
from charmhelpers.contrib.openstack.utils import ( from charmhelpers.contrib.openstack.utils import (
os_release, os_release,
@ -762,6 +763,15 @@ class HAProxyContext(context.HAProxyContext):
from neutron_api_utils import api_port from neutron_api_utils import api_port
ctxt = super(HAProxyContext, self).__call__() ctxt = super(HAProxyContext, self).__call__()
healthcheck = [{
'option': 'httpchk GET /healthcheck',
'http-check': 'expect status 200',
}]
backend_options = {
'neutron-server': healthcheck,
}
# Apache ports # Apache ports
a_neutron_api = determine_apache_port(api_port('neutron-server'), a_neutron_api = determine_apache_port(api_port('neutron-server'),
singlenode_mode=True) singlenode_mode=True)
@ -778,6 +788,8 @@ class HAProxyContext(context.HAProxyContext):
# for haproxy.conf # for haproxy.conf
ctxt['service_ports'] = port_mapping ctxt['service_ports'] = port_mapping
ctxt['backend_options'] = backend_options
ctxt['https'] = https()
return ctxt return ctxt

View File

@ -1,6 +1,7 @@
[composite:neutron] [composite:neutron]
use = egg:Paste#urlmap use = egg:Paste#urlmap
/: neutronversions_composite /: neutronversions_composite
/healthcheck: healthcheck
/v2.0: neutronapi_v2_0 /v2.0: neutronapi_v2_0
[composite:neutronapi_v2_0] [composite:neutronapi_v2_0]
@ -50,3 +51,8 @@ paste.app_factory = neutron.api.v2.router:APIRouter.factory
[filter:osprofiler] [filter:osprofiler]
paste.filter_factory = osprofiler.web:WsgiMiddleware.factory paste.filter_factory = osprofiler.web:WsgiMiddleware.factory
[app:healthcheck]
paste.app_factory = oslo_middleware:Healthcheck.app_factory
backends = disable_by_file
disable_by_file_path = /var/lib/neutron/healthcheck_disable

View File

@ -25,7 +25,7 @@ setenv = VIRTUAL_ENV={envdir}
commands = stestr run --slowest {posargs} commands = stestr run --slowest {posargs}
allowlist_externals = allowlist_externals =
charmcraft charmcraft
rename.sh {toxinidir}/rename.sh
passenv = passenv =
HOME HOME
TERM TERM

View File

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import collections
import json import json
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
@ -30,6 +31,7 @@ TO_PATCH = [
'relation_get', 'relation_get',
'relation_ids', 'relation_ids',
'related_units', 'related_units',
'https'
] ]
@ -377,6 +379,7 @@ class HAProxyContextTest(CharmTestCase):
with patch('builtins.__import__'): with patch('builtins.__import__'):
self.assertTrue('units' not in hap_ctxt()) self.assertTrue('units' not in hap_ctxt())
@patch.object(charmhelpers.contrib.network.ip, 'is_ipv6_disabled')
@patch.object(charmhelpers.contrib.openstack.context, 'get_relation_ip') @patch.object(charmhelpers.contrib.openstack.context, 'get_relation_ip')
@patch.object(charmhelpers.contrib.openstack.context, 'mkdir') @patch.object(charmhelpers.contrib.openstack.context, 'mkdir')
@patch.object( @patch.object(
@ -395,11 +398,21 @@ class HAProxyContextTest(CharmTestCase):
def test_context_peers(self, _open, _import, _kv, _log, _rids, _runits, def test_context_peers(self, _open, _import, _kv, _log, _rids, _runits,
_rget, _lunit, _config, _rget, _lunit, _config,
_get_address_in_network, _get_netmask_for_address, _get_address_in_network, _get_netmask_for_address,
_mkdir, _get_relation_ip): _mkdir, _get_relation_ip, _is_ipv6_disabled):
unit_addresses = { healthcheck = [{
'neutron-api-0': '10.10.10.10', 'option': 'httpchk GET /healthcheck',
'neutron-api-1': '10.10.10.11', 'http-check': 'expect status 200',
}]
backend_options = {
'neutron-server': healthcheck,
} }
self.https.return_value = False
unit_addresses = collections.OrderedDict(
[
('neutron-api-1', '10.10.10.11'),
('neutron-api-0', '10.10.10.10'),
]
)
_rids.return_value = ['rid1'] _rids.return_value = ['rid1']
_runits.return_value = ['neutron-api/0'] _runits.return_value = ['neutron-api/0']
_rget.return_value = unit_addresses['neutron-api-0'] _rget.return_value = unit_addresses['neutron-api-0']
@ -409,6 +422,7 @@ class HAProxyContextTest(CharmTestCase):
_get_address_in_network.return_value = None _get_address_in_network.return_value = None
_get_netmask_for_address.return_value = '255.255.255.0' _get_netmask_for_address.return_value = '255.255.255.0'
_kv().get.return_value = 'abcdefghijklmnopqrstuvwxyz123456' _kv().get.return_value = 'abcdefghijklmnopqrstuvwxyz123456'
_is_ipv6_disabled.return_value = True
service_ports = {'neutron-server': [9696, 9686]} service_ports = {'neutron-server': [9696, 9686]}
ctxt_data = { ctxt_data = {
'local_host': '127.0.0.1', 'local_host': '127.0.0.1',
@ -426,6 +440,8 @@ class HAProxyContextTest(CharmTestCase):
'service_ports': service_ports, 'service_ports': service_ports,
'neutron_bind_port': 9686, 'neutron_bind_port': 9686,
'ipv6_enabled': True, 'ipv6_enabled': True,
'https': False,
'backend_options': backend_options,
} }
_import().api_port.return_value = 9696 _import().api_port.return_value = 9696
hap_ctxt = context.HAProxyContext() hap_ctxt = context.HAProxyContext()