Allowing for a host amphora configuration

Currently there is no way to for the haproxy templater
to know any data about the current host configuration.
This patch passes the 'host amphora' to the templater
allowing deployer the ability to use this information
if needed. This information is not currently needed in
the default configuration.

Change-Id: Ifbc07618e470c375f7c574a1bc82ae24f080f1c3
Closes-Bug: #1582507
This commit is contained in:
ptoohill1 2016-05-15 23:56:11 -05:00
parent 80a323b230
commit b3a97e3887
5 changed files with 88 additions and 17 deletions

View File

@ -66,11 +66,13 @@ class HaproxyAmphoraLoadBalancerDriver(
# Process listener certificate info
certs = self._process_tls_certificates(listener)
# Generate HaProxy configuration from listener object
config = self.jinja.build_config(listener, certs['tls_cert'])
for amp in listener.load_balancer.amphorae:
if amp.status != constants.DELETED:
# Generate HaProxy configuration from listener object
config = self.jinja.build_config(amp,
listener,
certs['tls_cert'])
self.client.upload_config(amp, listener.id, config)
# todo (german): add a method to REST interface to reload or
# start without having to check

View File

@ -84,18 +84,19 @@ class JinjaTemplater(object):
self.timeout_server = timeout_server
self.timeout_connect = timeout_connect
def build_config(self, listener, tls_cert,
def build_config(self, host_amphora, listener, tls_cert,
socket_path=None,
user_group='nogroup'):
"""Convert a logical configuration to the HAProxy version
:param host_amphora: The Amphora this configuration is hosted on
:param listener: The listener configuration
:param tls_cert: The TLS certificates for the listener
:param socket_path: The socket path for Haproxy process
:param user_group: The user group
:return: Rendered configuration
"""
return self.render_loadbalancer_obj(listener,
return self.render_loadbalancer_obj(host_amphora, listener,
tls_cert=tls_cert,
user_group=user_group,
socket_path=socket_path)
@ -113,12 +114,13 @@ class JinjaTemplater(object):
JINJA_ENV.filters['hash_amp_id'] = octavia_utils.base64_sha1_string
return JINJA_ENV.get_template(os.path.basename(self.haproxy_template))
def render_loadbalancer_obj(self, listener,
def render_loadbalancer_obj(self, host_amphora, listener,
tls_cert=None,
user_group='nogroup',
socket_path=None):
"""Renders a templated configuration from a load balancer object
:param host_amphora: The Amphora this configuration is hosted on
:param listener: The listener configuration
:param tls_cert: The TLS certificates for the listener
:param socket_path: The socket path for Haproxy process
@ -126,6 +128,7 @@ class JinjaTemplater(object):
:return: Rendered configuration
"""
loadbalancer = self._transform_loadbalancer(
host_amphora,
listener.load_balancer,
listener,
tls_cert)
@ -142,7 +145,8 @@ class JinjaTemplater(object):
'timeout_connect': self.timeout_connect},
constants=constants)
def _transform_loadbalancer(self, loadbalancer, listener, tls_cert):
def _transform_loadbalancer(self, host_amphora, loadbalancer, listener,
tls_cert):
"""Transforms a load balancer into an object that will
be processed by the templating system
@ -153,7 +157,26 @@ class JinjaTemplater(object):
'vip_address': loadbalancer.vip.ip_address,
'listener': listener,
'topology': loadbalancer.topology,
'enabled': loadbalancer.enabled
'enabled': loadbalancer.enabled,
'host_amphora': self._transform_amphora(host_amphora)
}
def _transform_amphora(self, amphora):
"""Transform an amphora into an object that will
be processed by the templating system.
"""
return {
'id': amphora.id,
'lb_network_ip': amphora.lb_network_ip,
'vrrp_ip': amphora.vrrp_ip,
'ha_ip': amphora.ha_ip,
'vrrp_port_id': amphora.vrrp_port_id,
'ha_port_id': amphora.ha_port_id,
'role': amphora.role,
'status': amphora.status,
'vrrp_interface': amphora.vrrp_interface,
'vrrp_priority': amphora.vrrp_priority
}
def _transform_listener(self, listener, tls_cert):

View File

@ -41,6 +41,7 @@ class ListenerTestCase(base.TestCase):
certificate='imaCert1', private_key='imaPrivateKey1',
primary_cn='FakeCN')
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(proto='TERMINATED_HTTPS',
tls=True, sni=True),
tls_tupe)
@ -58,6 +59,7 @@ class ListenerTestCase(base.TestCase):
# render_template_tls_no_sni
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(
proto='TERMINATED_HTTPS', tls=True),
tls_cert=sample_configs.sample_tls_container_tuple(
@ -77,6 +79,7 @@ class ListenerTestCase(base.TestCase):
# render_template_http
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple())
self.useFixture(test_utils.OpenFixture(path, rendered_obj))
@ -89,6 +92,7 @@ class ListenerTestCase(base.TestCase):
# template_https
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(proto='HTTPS'))
self.useFixture(test_utils.OpenFixture(path, rendered_obj))

View File

@ -57,6 +57,7 @@ class TestHaproxyCfg(base.TestCase):
certificate='imaCert1', private_key='imaPrivateKey1',
primary_cn='FakeCN')
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(proto='TERMINATED_HTTPS',
tls=True, sni=True),
tls_tupe)
@ -89,6 +90,7 @@ class TestHaproxyCfg(base.TestCase):
"weight 13 check inter 30s fall 3 rise 2 "
"cookie sample_member_id_2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(
proto='TERMINATED_HTTPS', tls=True),
tls_cert=sample_configs.sample_tls_container_tuple(
@ -115,6 +117,7 @@ class TestHaproxyCfg(base.TestCase):
"weight 13 check inter 30s fall 3 rise 2 "
"cookie sample_member_id_2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple())
self.assertEqual(
sample_configs.sample_base_expected_config(backend=be),
@ -142,6 +145,7 @@ class TestHaproxyCfg(base.TestCase):
"weight 13 check inter 30s fall 3 rise 2 "
"cookie sample_member_id_2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(proto='HTTPS'))
self.assertEqual(sample_configs.sample_base_expected_config(
frontend=fe, backend=be), rendered_obj)
@ -156,6 +160,7 @@ class TestHaproxyCfg(base.TestCase):
" server sample_member_id_2 10.0.0.98:82 weight 13 "
"cookie sample_member_id_2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(proto='HTTP', monitor=False))
self.assertEqual(sample_configs.sample_base_expected_config(
backend=be), rendered_obj)
@ -176,6 +181,7 @@ class TestHaproxyCfg(base.TestCase):
" server sample_member_id_2 10.0.0.98:82 weight 13 "
"cookie sample_member_id_2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(proto='HTTPS', monitor=False))
self.assertEqual(sample_configs.sample_base_expected_config(
frontend=fe, backend=be), rendered_obj)
@ -193,6 +199,7 @@ class TestHaproxyCfg(base.TestCase):
" server sample_member_id_1 10.0.0.99:82 weight 13\n"
" server sample_member_id_2 10.0.0.98:82 weight 13\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(proto='HTTPS', monitor=False,
persistence=False))
self.assertEqual(sample_configs.sample_base_expected_config(
@ -205,6 +212,7 @@ class TestHaproxyCfg(base.TestCase):
" server sample_member_id_1 10.0.0.99:82 weight 13\n"
" server sample_member_id_2 10.0.0.98:82 weight 13\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(proto='HTTP', monitor=False,
persistence=False))
self.assertEqual(sample_configs.sample_base_expected_config(
@ -224,6 +232,7 @@ class TestHaproxyCfg(base.TestCase):
" server sample_member_id_2 10.0.0.98:82 "
"weight 13 check inter 30s fall 3 rise 2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(
persistence_type='SOURCE_IP'))
self.assertEqual(
@ -245,6 +254,7 @@ class TestHaproxyCfg(base.TestCase):
" server sample_member_id_2 10.0.0.98:82 "
"weight 13 check inter 30s fall 3 rise 2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(
persistence_type='APP_COOKIE',
persistence_cookie='JSESSIONID'))
@ -294,6 +304,7 @@ class TestHaproxyCfg(base.TestCase):
" server sample_member_id_3 10.0.0.97:82 weight 13 check "
"inter 30s fall 3 rise 2 cookie sample_member_id_3\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(l7=True))
self.assertEqual(sample_configs.sample_base_expected_config(
frontend=fe, backend=be), rendered_obj)
@ -314,6 +325,7 @@ class TestHaproxyCfg(base.TestCase):
"weight 13 check inter 30s fall 3 rise 2 "
"cookie sample_member_id_2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(
insert_headers={'X-Forwarded-For': 'true'}))
self.assertEqual(
@ -337,6 +349,7 @@ class TestHaproxyCfg(base.TestCase):
"weight 13 check inter 30s fall 3 rise 2 "
"cookie sample_member_id_2\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(
insert_headers={'X-Forwarded-For': 'true',
'X-Forwarded-Port': 'true'}))
@ -381,15 +394,22 @@ class TestHaproxyCfg(base.TestCase):
self.assertEqual(sample_configs.RET_LISTENER_L7, ret)
def test_transform_loadbalancer(self):
in_amphora = sample_configs.sample_amphora_tuple()
in_listener = sample_configs.sample_listener_tuple()
ret = self.jinja_cfg._transform_loadbalancer(
in_listener.load_balancer, in_listener, None)
in_amphora, in_listener.load_balancer, in_listener, None)
self.assertEqual(sample_configs.RET_LB, ret)
def test_transform_amphora(self):
in_amphora = sample_configs.sample_amphora_tuple()
ret = self.jinja_cfg._transform_amphora(in_amphora)
self.assertEqual(sample_configs.RET_AMPHORA, ret)
def test_transform_loadbalancer_with_l7(self):
in_amphora = sample_configs.sample_amphora_tuple()
in_listener = sample_configs.sample_listener_tuple(l7=True)
ret = self.jinja_cfg._transform_loadbalancer(
in_listener.load_balancer, in_listener, None)
in_amphora, in_listener.load_balancer, in_listener, None)
self.assertEqual(sample_configs.RET_LB_L7, ret)
def test_transform_l7policy(self):

View File

@ -20,13 +20,21 @@ from octavia.common import constants
def sample_amphora_tuple():
amphora = collections.namedtuple('amphora', 'id, load_balancer_id, '
'compute_id, status,'
'lb_network_ip, vrrp_ip')
return amphora(id='sample_amp_id_1', load_balancer_id='sample_lb_id_1',
compute_id='sample_compute_id_1', status='ACTIVE',
lb_network_ip='10.0.0.1',
vrrp_ip='10.0.0.2')
in_amphora = collections.namedtuple(
'amphora', 'id, lb_network_ip, vrrp_ip, ha_ip, vrrp_port_id, '
'ha_port_id, role, status, vrrp_interface,'
'vrrp_priority')
return in_amphora(
id='sample_amphora_id_1',
lb_network_ip='10.0.1.1',
vrrp_ip='10.1.1.1',
ha_ip='192.168.10.1',
vrrp_port_id='1234',
ha_port_id='1234',
role=None,
status='ACTIVE',
vrrp_interface=None,
vrrp_priority=None)
RET_PERSISTENCE = {
'type': 'HTTP_COOKIE',
@ -256,7 +264,20 @@ RET_LISTENER_TLS_SNI = {
'enabled': True,
'insert_headers': {}}
RET_AMPHORA = {
'id': 'sample_amphora_id_1',
'lb_network_ip': '10.0.1.1',
'vrrp_ip': '10.1.1.1',
'ha_ip': '192.168.10.1',
'vrrp_port_id': '1234',
'ha_port_id': '1234',
'role': None,
'status': 'ACTIVE',
'vrrp_interface': None,
'vrrp_priority': None}
RET_LB = {
'host_amphora': RET_AMPHORA,
'name': 'test-lb',
'vip_address': '10.0.0.2',
'listener': RET_LISTENER,
@ -276,6 +297,7 @@ RET_LB_TLS_SNI = {
'enabled': True}
RET_LB_L7 = {
'host_amphora': RET_AMPHORA,
'name': 'test-lb',
'vip_address': '10.0.0.2',
'listener': RET_LISTENER_L7,
@ -642,4 +664,4 @@ def sample_base_expected_config(frontend=None, backend=None, peers=None):
" option redispatch\n"
" timeout connect 5000\n"
" timeout client 50000\n"
" timeout server 50000\n\n" + peers + frontend + backend)
" timeout server 50000\n\n" + peers + frontend + backend)