From 7a2df883a09d2f9877c640a77914c2f2b62f86e7 Mon Sep 17 00:00:00 2001 From: Tom Weininger Date: Tue, 25 Oct 2022 13:39:36 +0200 Subject: [PATCH] Remove support for split listener configuration Remove support for Amphora API 0.5 or earlier. During the PTG for the Antelope cycle it has been decided to remove split listener configuration.[1] [1]: https://etherpad.opendev.org/p/antelope-ptg-octavia Change-Id: Ia0c1d4107161fff8d1f3071d57860bfd265f596f --- .../amphorae/driver_exceptions/exceptions.py | 5 + .../drivers/haproxy/rest_api_driver.py | 236 +-- .../drivers/keepalived/vrrp_rest_driver.py | 1 - octavia/common/constants.py | 2 - .../jinja/haproxy/split_listeners/__init__.py | 0 .../haproxy/split_listeners/jinja_cfg.py | 470 ------ .../haproxy/split_listeners/templates/base.j2 | 50 - .../split_listeners/templates/haproxy.cfg.j2 | 40 - .../split_listeners/templates/macros.j2 | 373 ----- .../drivers/haproxy/test_rest_api_driver.py | 9 + .../haproxy/test_rest_api_driver_0_5.py | 1359 ----------------- .../haproxy/test_rest_api_driver_1_0.py | 6 +- .../jinja/haproxy/split_listeners/__init__.py | 0 .../haproxy/split_listeners/test_jinja_cfg.py | 1157 -------------- .../sample_configs/sample_configs_split.py | 1139 -------------- ...move-split-listeners-6a4ccdf66fe7b683.yaml | 6 + 16 files changed, 55 insertions(+), 4798 deletions(-) delete mode 100644 octavia/common/jinja/haproxy/split_listeners/__init__.py delete mode 100644 octavia/common/jinja/haproxy/split_listeners/jinja_cfg.py delete mode 100644 octavia/common/jinja/haproxy/split_listeners/templates/base.j2 delete mode 100644 octavia/common/jinja/haproxy/split_listeners/templates/haproxy.cfg.j2 delete mode 100644 octavia/common/jinja/haproxy/split_listeners/templates/macros.j2 delete mode 100644 octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_0_5.py delete mode 100644 octavia/tests/unit/common/jinja/haproxy/split_listeners/__init__.py delete mode 100644 octavia/tests/unit/common/jinja/haproxy/split_listeners/test_jinja_cfg.py delete mode 100644 octavia/tests/unit/common/sample_configs/sample_configs_split.py create mode 100644 releasenotes/notes/remove-split-listeners-6a4ccdf66fe7b683.yaml diff --git a/octavia/amphorae/driver_exceptions/exceptions.py b/octavia/amphorae/driver_exceptions/exceptions.py index 42b9ea24d7..789d12f23d 100644 --- a/octavia/amphorae/driver_exceptions/exceptions.py +++ b/octavia/amphorae/driver_exceptions/exceptions.py @@ -125,3 +125,8 @@ class AmpConnectionRetry(AmphoraDriverError): message = _('Could not connect to amphora, exception caught: ' '%(exception)s') + + +class AmpVersionUnsupported(AmphoraDriverError): + + message = _('Amphora version %(version)s is no longer supported.') diff --git a/octavia/amphorae/drivers/haproxy/rest_api_driver.py b/octavia/amphorae/drivers/haproxy/rest_api_driver.py index ffba69de6e..0be632e45d 100644 --- a/octavia/amphorae/drivers/haproxy/rest_api_driver.py +++ b/octavia/amphorae/drivers/haproxy/rest_api_driver.py @@ -17,6 +17,7 @@ import hashlib import os import ssl import time +from typing import Optional import warnings from oslo_context import context as oslo_context @@ -33,20 +34,16 @@ from octavia.amphorae.drivers.keepalived import vrrp_rest_driver from octavia.common.config import cfg from octavia.common import constants as consts import octavia.common.jinja.haproxy.combined_listeners.jinja_cfg as jinja_combo -import octavia.common.jinja.haproxy.split_listeners.jinja_cfg as jinja_split from octavia.common.jinja.lvs import jinja_cfg as jinja_udp_cfg from octavia.common.tls_utils import cert_parser from octavia.common import utils from octavia.db import api as db_apis +from octavia.db import models as db_models from octavia.db import repositories as repo from octavia.network import data_models as network_models LOG = logging.getLogger(__name__) -API_VERSION = consts.API_VERSION -OCTAVIA_API_CLIENT = ( - "Octavia HaProxy Rest Client/{version} " - "(https://wiki.openstack.org/wiki/Octavia)").format(version=API_VERSION) CONF = cfg.CONF @@ -58,7 +55,6 @@ class HaproxyAmphoraLoadBalancerDriver( super().__init__() self.clients = { 'base': AmphoraAPIClientBase(), - '0.5': AmphoraAPIClient0_5(), '1.0': AmphoraAPIClient1_0(), } self.cert_manager = stevedore_driver.DriverManager( @@ -72,11 +68,6 @@ class HaproxyAmphoraLoadBalancerDriver( base_crt_dir=CONF.haproxy_amphora.base_cert_dir, haproxy_template=CONF.haproxy_amphora.haproxy_template, connection_logging=CONF.haproxy_amphora.connection_logging) - self.jinja_split = jinja_split.JinjaTemplater( - base_amp_path=CONF.haproxy_amphora.base_path, - base_crt_dir=CONF.haproxy_amphora.base_cert_dir, - haproxy_template=CONF.haproxy_amphora.haproxy_template, - connection_logging=CONF.haproxy_amphora.connection_logging) self.lvs_jinja = jinja_udp_cfg.LvsJinjaTemplater() def _get_haproxy_versions(self, amphora, timeout_dict=None): @@ -113,7 +104,13 @@ class HaproxyAmphoraLoadBalancerDriver( amphora.api_version = '0.5' LOG.debug('Amphora %s has API version %s', amphora.id, amphora.api_version) - return list(map(int, amphora.api_version.split('.'))) + api_version = list(map(int, amphora.api_version.split('.'))) + + if api_version[0] == 0 and api_version[1] <= 5: # 0.5 or earlier + raise driver_except.AmpVersionUnsupported( + version=amphora.api_version) + + return api_version def update_amphora_listeners(self, loadbalancer, amphora, timeout_dict=None): @@ -141,17 +138,8 @@ class HaproxyAmphoraLoadBalancerDriver( # Check which HAProxy version is on the amp haproxy_versions = self._get_haproxy_versions( amphora, timeout_dict=timeout_dict) - # Check which config style to use - api_version = self._populate_amphora_api_version(amphora) - if api_version[0] == 0 and api_version[1] <= 5: # 0.5 or earlier - split_config = True - LOG.warning( - 'Amphora %s for loadbalancer %s needs upgrade to single ' - 'process mode.', amphora.id, loadbalancer.id) - else: - split_config = False - LOG.debug('Amphora %s for loadbalancer %s is already in single ' - 'process mode.', amphora.id, loadbalancer.id) + # Check if version is supported + self._populate_amphora_api_version(amphora) has_tcp = False certs = {} @@ -168,10 +156,7 @@ class HaproxyAmphoraLoadBalancerDriver( amphora, listener.id, timeout_dict=timeout_dict) else: has_tcp = True - if split_config: - obj_id = listener.id - else: - obj_id = loadbalancer.id + obj_id = loadbalancer.id try: certs.update({ @@ -192,21 +177,7 @@ class HaproxyAmphoraLoadBalancerDriver( certs.update(self._process_listener_pool_certs( listener, amphora, obj_id)) - if split_config: - config = self.jinja_split.build_config( - host_amphora=amphora, listener=listener, - haproxy_versions=haproxy_versions, - client_ca_filename=certs[ - listener.client_ca_tls_certificate_id], - client_crl=certs[listener.client_crl_container_id], - pool_tls_certs=certs) - self.clients[amphora.api_version].upload_config( - amphora, listener.id, config, - timeout_dict=timeout_dict) - self.clients[amphora.api_version].reload_listener( - amphora, listener.id, timeout_dict=timeout_dict) - else: - listeners_to_update.append(listener) + listeners_to_update.append(listener) except Exception as e: LOG.exception('Unable to update listener %s due to ' '"%s". Skipping this listener.', @@ -216,7 +187,7 @@ class HaproxyAmphoraLoadBalancerDriver( provisioning_status=consts.ERROR, operating_status=consts.ERROR) - if has_tcp and not split_config: + if has_tcp: if listeners_to_update: # Generate HaProxy configuration from listener object amp_details = self.clients[amphora.api_version].get_details( @@ -272,35 +243,20 @@ class HaproxyAmphoraLoadBalancerDriver( else: amphorae = [amphora] - timeout_dict = args[0] - for amp in amphorae: if amp.status != consts.DELETED: - api_version = self._populate_amphora_api_version( - amp, timeout_dict=timeout_dict) - # Check which config style to use - if api_version[0] == 0 and api_version[1] <= 5: - # 0.5 or earlier - LOG.warning( - 'Amphora %s for loadbalancer %s needs upgrade to ' - 'single process mode.', amp.id, loadbalancer.id) - for listener in loadbalancer.listeners: + self._populate_amphora_api_version( + amp, timeout_dict=args[0]) + has_tcp = False + for listener in loadbalancer.listeners: + if listener.protocol in consts.LVS_PROTOCOLS: getattr(self.clients[amp.api_version], func_name)( amp, listener.id, *args) - else: - LOG.debug( - 'Amphora %s for loadbalancer %s is already in single ' - 'process mode.', amp.id, loadbalancer.id) - has_tcp = False - for listener in loadbalancer.listeners: - if listener.protocol in consts.LVS_PROTOCOLS: - getattr(self.clients[amp.api_version], func_name)( - amp, listener.id, *args) - else: - has_tcp = True - if has_tcp: - getattr(self.clients[amp.api_version], func_name)( - amp, loadbalancer.id, *args) + else: + has_tcp = True + if has_tcp: + getattr(self.clients[amp.api_version], func_name)( + amp, loadbalancer.id, *args) def reload(self, loadbalancer, amphora=None, timeout_dict=None): self._apply('reload_listener', loadbalancer, amphora, timeout_dict) @@ -321,24 +277,9 @@ class HaproxyAmphoraLoadBalancerDriver( return # In case the listener is not UDP or SCTP, things get more complicated. - # We need to do this individually for each amphora in case some are - # using split config and others are using combined config. for amp in loadbalancer.amphorae: if amp.status != consts.DELETED: - api_version = self._populate_amphora_api_version(amp) - # Check which config style to use - if api_version[0] == 0 and api_version[1] <= 5: - # 0.5 or earlier - LOG.warning( - 'Amphora %s for loadbalancer %s needs upgrade to ' - 'single process mode.', amp.id, loadbalancer.id) - self.clients[amp.api_version].delete_listener( - amp, listener.id) - else: - LOG.debug( - 'Amphora %s for loadbalancer %s is already in single ' - 'process mode.', amp.id, loadbalancer.id) - self._combined_config_delete(amp, listener) + self._combined_config_delete(amp, listener) def _combined_config_delete(self, amphora, listener): # Remove the listener from the listener list on the LB before @@ -706,8 +647,10 @@ class AmphoraAPIClientBase(object): ip=ip, port=CONF.haproxy_amphora.bind_port) - def request(self, method, amp, path='/', timeout_dict=None, - retry_404=True, raise_retry_exception=False, **kwargs): + def request(self, method: str, amp: db_models.Amphora, path: str = '/', + timeout_dict: Optional[dict] = None, + retry_404: bool = True, raise_retry_exception: bool = False, + **kwargs): cfg_ha_amp = CONF.haproxy_amphora if timeout_dict is None: timeout_dict = {} @@ -731,7 +674,9 @@ class AmphoraAPIClientBase(object): reqargs.update(kwargs) headers = reqargs.setdefault('headers', {}) - headers['User-Agent'] = OCTAVIA_API_CLIENT + headers['User-Agent'] = ( + f"Octavia HaProxy Rest Client/{amp.api_version} " + f"(https://wiki.openstack.org/wiki/Octavia)") self.ssl_adapter.uuid = amp.id exception = None # Keep retrying @@ -797,123 +742,6 @@ class AmphoraAPIClientBase(object): return r.json() -class AmphoraAPIClient0_5(AmphoraAPIClientBase): - def __init__(self): - super().__init__() - - self.start_listener = functools.partial(self._action, - consts.AMP_ACTION_START) - self.reload_listener = functools.partial(self._action, - consts.AMP_ACTION_RELOAD) - - self.start_vrrp = functools.partial(self._vrrp_action, - consts.AMP_ACTION_START) - self.stop_vrrp = functools.partial(self._vrrp_action, - consts.AMP_ACTION_STOP) - self.reload_vrrp = functools.partial(self._vrrp_action, - consts.AMP_ACTION_RELOAD) - - def upload_config(self, amp, listener_id, config, timeout_dict=None): - r = self.put( - amp, - 'listeners/{amphora_id}/{listener_id}/haproxy'.format( - amphora_id=amp.id, listener_id=listener_id), timeout_dict, - data=config) - return exc.check_exception(r) - - def _action(self, action, amp, listener_id, timeout_dict=None): - r = self.put(amp, 'listeners/{listener_id}/{action}'.format( - listener_id=listener_id, action=action), timeout_dict=timeout_dict) - return exc.check_exception(r) - - def upload_cert_pem(self, amp, listener_id, pem_filename, pem_file): - r = self.put( - amp, 'listeners/{listener_id}/certificates/{filename}'.format( - listener_id=listener_id, filename=pem_filename), - data=pem_file) - return exc.check_exception(r) - - def get_cert_md5sum(self, amp, listener_id, pem_filename, ignore=tuple()): - r = self.get( - amp, 'listeners/{listener_id}/certificates/{filename}'.format( - listener_id=listener_id, filename=pem_filename)) - if exc.check_exception(r, ignore): - return r.json().get("md5sum") - return None - - def delete_cert_pem(self, amp, listener_id, pem_filename): - r = self.delete( - amp, 'listeners/{listener_id}/certificates/{filename}'.format( - listener_id=listener_id, filename=pem_filename)) - return exc.check_exception(r, (404,)) - - def update_cert_for_rotation(self, amp, pem_file): - r = self.put(amp, 'certificate', data=pem_file) - return exc.check_exception(r) - - def delete_listener(self, amp, listener_id): - r = self.delete( - amp, 'listeners/{listener_id}'.format(listener_id=listener_id)) - return exc.check_exception(r, (404,)) - - def get_info(self, amp, raise_retry_exception=False, - timeout_dict=None): - r = self.get(amp, "info", raise_retry_exception=raise_retry_exception, - timeout_dict=timeout_dict) - if exc.check_exception(r): - return r.json() - return None - - def get_details(self, amp): - r = self.get(amp, "details") - if exc.check_exception(r): - return r.json() - return None - - def get_all_listeners(self, amp): - r = self.get(amp, "listeners") - if exc.check_exception(r): - return r.json() - return None - - def plug_network(self, amp, port): - r = self.post(amp, 'plug/network', - json=port) - return exc.check_exception(r) - - def plug_vip(self, amp, vip, net_info): - r = self.post(amp, - 'plug/vip/{vip}'.format(vip=vip), - json=net_info) - return exc.check_exception(r) - - def upload_vrrp_config(self, amp, config): - r = self.put(amp, 'vrrp/upload', data=config) - return exc.check_exception(r) - - def _vrrp_action(self, action, amp, timeout_dict=None): - r = self.put(amp, 'vrrp/{action}'.format(action=action), - timeout_dict=timeout_dict) - return exc.check_exception(r) - - def get_interface(self, amp, ip_addr, timeout_dict=None, log_error=True): - r = self.get(amp, 'interface/{ip_addr}'.format(ip_addr=ip_addr), - timeout_dict=timeout_dict) - return exc.check_exception(r, log_error=log_error).json() - - def upload_udp_config(self, amp, listener_id, config, timeout_dict=None): - r = self.put( - amp, - 'listeners/{amphora_id}/{listener_id}/udp_listener'.format( - amphora_id=amp.id, listener_id=listener_id), timeout_dict, - data=config) - return exc.check_exception(r) - - def update_agent_config(self, amp, agent_config, timeout_dict=None): - r = self.put(amp, 'config', timeout_dict, data=agent_config) - return exc.check_exception(r) - - class AmphoraAPIClient1_0(AmphoraAPIClientBase): def __init__(self): super().__init__() diff --git a/octavia/amphorae/drivers/keepalived/vrrp_rest_driver.py b/octavia/amphorae/drivers/keepalived/vrrp_rest_driver.py index c309f081b1..9680d5ff23 100644 --- a/octavia/amphorae/drivers/keepalived/vrrp_rest_driver.py +++ b/octavia/amphorae/drivers/keepalived/vrrp_rest_driver.py @@ -19,7 +19,6 @@ from octavia.amphorae.drivers.keepalived.jinja import jinja_cfg from octavia.common import constants LOG = logging.getLogger(__name__) -API_VERSION = constants.API_VERSION class KeepalivedAmphoraDriverMixin(driver_base.VRRPDriverMixin): diff --git a/octavia/common/constants.py b/octavia/common/constants.py index 4f8f6f4ed2..23916f63ba 100644 --- a/octavia/common/constants.py +++ b/octavia/common/constants.py @@ -666,8 +666,6 @@ QUOTA_UNLIMITED = -1 MIN_QUOTA = QUOTA_UNLIMITED MAX_QUOTA = 2000000000 -API_VERSION = '0.5' - HAPROXY_BASE_PEER_PORT = 1025 KEEPALIVED_JINJA2_UPSTART = 'keepalived.upstart.j2' KEEPALIVED_JINJA2_SYSTEMD = 'keepalived.systemd.j2' diff --git a/octavia/common/jinja/haproxy/split_listeners/__init__.py b/octavia/common/jinja/haproxy/split_listeners/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/octavia/common/jinja/haproxy/split_listeners/jinja_cfg.py b/octavia/common/jinja/haproxy/split_listeners/jinja_cfg.py deleted file mode 100644 index 0e4485ce98..0000000000 --- a/octavia/common/jinja/haproxy/split_listeners/jinja_cfg.py +++ /dev/null @@ -1,470 +0,0 @@ -# Copyright (c) 2015 Rackspace -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import re - -import jinja2 -from oslo_log import log as logging - -from octavia.common.config import cfg -from octavia.common import constants -from octavia.common import utils as octavia_utils - -PROTOCOL_MAP = { - constants.PROTOCOL_TCP: 'tcp', - constants.PROTOCOL_HTTP: 'http', - constants.PROTOCOL_HTTPS: 'tcp', - constants.PROTOCOL_PROXY: 'proxy', - constants.PROTOCOL_TERMINATED_HTTPS: 'http' -} - -BALANCE_MAP = { - constants.LB_ALGORITHM_ROUND_ROBIN: 'roundrobin', - constants.LB_ALGORITHM_LEAST_CONNECTIONS: 'leastconn', - constants.LB_ALGORITHM_SOURCE_IP: 'source' -} - -CLIENT_AUTH_MAP = {constants.CLIENT_AUTH_NONE: 'none', - constants.CLIENT_AUTH_OPTIONAL: 'optional', - constants.CLIENT_AUTH_MANDATORY: 'required'} - -ACTIVE_PENDING_STATUSES = constants.SUPPORTED_PROVISIONING_STATUSES + ( - constants.DEGRADED,) - -BASE_PATH = '/var/lib/octavia' -BASE_CRT_DIR = BASE_PATH + '/certs' - -HAPROXY_TEMPLATE = os.path.abspath( - os.path.join(os.path.dirname(__file__), - 'templates/haproxy.cfg.j2')) - -CONF = cfg.CONF -LOG = logging.getLogger(__name__) - -JINJA_ENV = None - - -class JinjaTemplater(object): - - def __init__(self, - base_amp_path=None, - base_crt_dir=None, - haproxy_template=None, - log_http=None, - log_server=None, - connection_logging=True): - """HaProxy configuration generation - - :param base_amp_path: Base path for amphora data - :param base_crt_dir: Base directory for certificate storage - :param haproxy_template: Absolute path to Jinja template - :param log_http: Haproxy HTTP logging path - :param log_server: Haproxy Server logging path - :param connection_logging: enable logging connections in haproxy - """ - - self.base_amp_path = base_amp_path or BASE_PATH - self.base_crt_dir = base_crt_dir or BASE_CRT_DIR - self.haproxy_template = haproxy_template or HAPROXY_TEMPLATE - self.log_http = log_http - self.log_server = log_server - self.connection_logging = connection_logging - - def build_config(self, host_amphora, listener, haproxy_versions, - socket_path=None, client_ca_filename=None, - client_crl=None, pool_tls_certs=None): - """Convert a logical configuration to the HAProxy version - - :param host_amphora: The Amphora this configuration is hosted on - :param listener: The listener configuration - :param socket_path: The socket path for Haproxy process - :return: Rendered configuration - """ - - # Check for any backward compatibility items we need to check - # This is done here for upgrade scenarios where one amp in a - # pair might be running an older amphora version. - - feature_compatibility = {} - # Is it newer than haproxy 1.5? - if not (int(haproxy_versions[0]) < 2 and int(haproxy_versions[1]) < 6): - feature_compatibility[constants.HTTP_REUSE] = True - - return self.render_loadbalancer_obj( - host_amphora, listener, socket_path=socket_path, - feature_compatibility=feature_compatibility, - client_ca_filename=client_ca_filename, client_crl=client_crl, - pool_tls_certs=pool_tls_certs) - - def _get_template(self): - """Returns the specified Jinja configuration template.""" - global JINJA_ENV - if not JINJA_ENV: - template_loader = jinja2.FileSystemLoader( - searchpath=os.path.dirname(self.haproxy_template)) - JINJA_ENV = jinja2.Environment( - autoescape=True, - loader=template_loader, - trim_blocks=True, - lstrip_blocks=True) - JINJA_ENV.filters['hash_amp_id'] = octavia_utils.base64_sha1_string - return JINJA_ENV.get_template(os.path.basename(self.haproxy_template)) - - def _format_log_string(self, load_balancer, protocol): - log_format = CONF.haproxy_amphora.user_log_format.replace( - '{{ project_id }}', load_balancer.project_id) - log_format = log_format.replace('{{ lb_id }}', load_balancer.id) - - # Order of these filters matter. - # TODO(johnsom) Remove when HAProxy handles the format string - # with HTTP variables in TCP listeners. - # Currently it either throws an error or just fails - # to log the message. - if protocol not in constants.HAPROXY_HTTP_PROTOCOLS: - log_format = log_format.replace('%{+Q}r', '-') - log_format = log_format.replace('%r', '-') - log_format = log_format.replace('%{+Q}ST', '-') - log_format = log_format.replace('%ST', '-') - - log_format = log_format.replace(' ', '\\ ') - return log_format - - def render_loadbalancer_obj(self, host_amphora, listener, socket_path=None, - feature_compatibility=None, - client_ca_filename=None, client_crl=None, - pool_tls_certs=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 client_ca_filename: The CA certificate for client authorization - :param socket_path: The socket path for Haproxy process - :return: Rendered configuration - """ - feature_compatibility = feature_compatibility or {} - loadbalancer = self._transform_loadbalancer( - host_amphora, listener.load_balancer, listener, - feature_compatibility, client_ca_filename=client_ca_filename, - client_crl=client_crl, pool_tls_certs=pool_tls_certs) - if not socket_path: - socket_path = '%s/%s.sock' % (self.base_amp_path, listener.id) - return self._get_template().render( - {'loadbalancer': loadbalancer, - 'stats_sock': socket_path, - 'log_http': self.log_http, - 'log_server': self.log_server, - 'administrative_log_facility': - CONF.amphora_agent.administrative_log_facility, - 'user_log_facility': CONF.amphora_agent.user_log_facility, - 'connection_logging': self.connection_logging}, - constants=constants) - - def _transform_loadbalancer(self, host_amphora, loadbalancer, listener, - feature_compatibility, client_ca_filename=None, - client_crl=None, pool_tls_certs=None): - """Transforms a load balancer into an object that will - - be processed by the templating system - """ - t_listener = self._transform_listener( - listener, feature_compatibility, loadbalancer, - client_ca_filename=client_ca_filename, client_crl=client_crl, - pool_tls_certs=pool_tls_certs) - additional_vips = [ - vip.ip_address for vip in loadbalancer.additional_vips] - ret_value = { - 'id': loadbalancer.id, - 'vip_address': loadbalancer.vip.ip_address, - 'additional_vips': additional_vips, - 'listener': t_listener, - 'topology': loadbalancer.topology, - 'enabled': loadbalancer.enabled, - 'host_amphora': self._transform_amphora( - host_amphora, feature_compatibility) - } - # NOTE(sbalukoff): Global connection limit should be a sum of all - # listeners' connection limits. Since Octavia presently supports - # just one listener per haproxy process, this makes determining - # the global value trivial. - if listener.connection_limit and listener.connection_limit > -1: - ret_value['global_connection_limit'] = listener.connection_limit - else: - ret_value['global_connection_limit'] = ( - constants.HAPROXY_MAX_MAXCONN) - return ret_value - - def _transform_amphora(self, amphora, feature_compatibility): - """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, feature_compatibility, - loadbalancer, client_ca_filename=None, - client_crl=None, pool_tls_certs=None): - """Transforms a listener into an object that will - - be processed by the templating system - """ - ret_value = { - 'id': listener.id, - 'protocol_port': listener.protocol_port, - 'protocol_mode': PROTOCOL_MAP[listener.protocol], - 'protocol': listener.protocol, - 'peer_port': listener.peer_port, - 'insert_headers': listener.insert_headers, - 'topology': listener.load_balancer.topology, - 'amphorae': listener.load_balancer.amphorae, - 'enabled': listener.enabled, - 'timeout_client_data': ( - listener.timeout_client_data or - CONF.haproxy_amphora.timeout_client_data), - 'timeout_member_connect': ( - listener.timeout_member_connect or - CONF.haproxy_amphora.timeout_member_connect), - 'timeout_member_data': ( - listener.timeout_member_data or - CONF.haproxy_amphora.timeout_member_data), - 'timeout_tcp_inspect': (listener.timeout_tcp_inspect or - CONF.haproxy_amphora.timeout_tcp_inspect), - } - if self.connection_logging: - ret_value['user_log_format'] = ( - self._format_log_string(loadbalancer, listener.protocol)) - if listener.connection_limit and listener.connection_limit > -1: - ret_value['connection_limit'] = listener.connection_limit - else: - ret_value['connection_limit'] = constants.HAPROXY_MAX_MAXCONN - - if listener.tls_certificate_id: - ret_value['crt_list_filename'] = os.path.join( - CONF.haproxy_amphora.base_cert_dir, - listener.id, '{}.pem'.format(listener.id)) - - if listener.client_ca_tls_certificate_id: - ret_value['client_ca_tls_path'] = '%s' % ( - os.path.join(self.base_crt_dir, listener.id, - client_ca_filename)) - ret_value['client_auth'] = CLIENT_AUTH_MAP.get( - listener.client_authentication) - if listener.client_crl_container_id: - ret_value['client_crl_path'] = '%s' % ( - os.path.join(self.base_crt_dir, listener.id, client_crl)) - - if (listener.default_pool and - listener.default_pool.provisioning_status != - constants.PENDING_DELETE): - kwargs = {} - if pool_tls_certs and pool_tls_certs.get(listener.default_pool.id): - kwargs = {'pool_tls_certs': pool_tls_certs.get( - listener.default_pool.id)} - ret_value['default_pool'] = self._transform_pool( - listener.default_pool, feature_compatibility, **kwargs) - pools = [] - pool_gen = (pool for pool in listener.pools if - pool.provisioning_status != constants.PENDING_DELETE) - for x in pool_gen: - kwargs = {} - if pool_tls_certs and pool_tls_certs.get(x.id): - kwargs = {'pool_tls_certs': pool_tls_certs.get(x.id)} - pools.append(self._transform_pool( - x, feature_compatibility, **kwargs)) - ret_value['pools'] = pools - policy_gen = (policy for policy in listener.l7policies if - policy.provisioning_status != constants.PENDING_DELETE) - l7policies = [self._transform_l7policy( - x, feature_compatibility, pool_tls_certs) - for x in policy_gen] - ret_value['l7policies'] = l7policies - return ret_value - - def _transform_pool(self, pool, feature_compatibility, - pool_tls_certs=None): - """Transforms a pool into an object that will - - be processed by the templating system - """ - ret_value = { - 'id': pool.id, - 'protocol': PROTOCOL_MAP[pool.protocol], - 'lb_algorithm': BALANCE_MAP.get(pool.lb_algorithm, 'roundrobin'), - 'members': [], - 'health_monitor': '', - 'session_persistence': '', - 'enabled': pool.enabled, - 'operating_status': pool.operating_status, - 'stick_size': CONF.haproxy_amphora.haproxy_stick_size, - constants.HTTP_REUSE: feature_compatibility.get( - constants.HTTP_REUSE, False), - 'ca_tls_path': '', - 'crl_path': '', - 'tls_enabled': pool.tls_enabled - } - members_gen = (mem for mem in pool.members if - mem.provisioning_status != constants.PENDING_DELETE) - members = [self._transform_member(x, feature_compatibility) - for x in members_gen] - ret_value['members'] = members - health_mon = pool.health_monitor - if (health_mon and - health_mon.provisioning_status != constants.PENDING_DELETE): - ret_value['health_monitor'] = self._transform_health_monitor( - health_mon, feature_compatibility) - if pool.session_persistence: - ret_value[ - 'session_persistence'] = self._transform_session_persistence( - pool.session_persistence, feature_compatibility) - if (pool.tls_certificate_id and pool_tls_certs and - pool_tls_certs.get('client_cert')): - ret_value['client_cert'] = pool_tls_certs.get('client_cert') - if (pool.ca_tls_certificate_id and pool_tls_certs and - pool_tls_certs.get('ca_cert')): - ret_value['ca_cert'] = pool_tls_certs.get('ca_cert') - if (pool.crl_container_id and pool_tls_certs and - pool_tls_certs.get('crl')): - ret_value['crl'] = pool_tls_certs.get('crl') - - return ret_value - - @staticmethod - def _transform_session_persistence(persistence, feature_compatibility): - """Transforms session persistence into an object that will - - be processed by the templating system - """ - return { - 'type': persistence.type, - 'cookie_name': persistence.cookie_name - } - - @staticmethod - def _transform_member(member, feature_compatibility): - """Transforms a member into an object that will - - be processed by the templating system - """ - return { - 'id': member.id, - 'address': member.ip_address, - 'protocol_port': member.protocol_port, - 'weight': member.weight, - 'enabled': member.enabled, - 'subnet_id': member.subnet_id, - 'operating_status': member.operating_status, - 'monitor_address': member.monitor_address, - 'monitor_port': member.monitor_port, - 'backup': member.backup - } - - def _transform_health_monitor(self, monitor, feature_compatibility): - """Transforms a health monitor into an object that will - - be processed by the templating system - """ - codes = None - if monitor.expected_codes: - codes = '|'.join(octavia_utils.expand_expected_codes( - monitor.expected_codes)) - return { - 'id': monitor.id, - 'type': monitor.type, - 'delay': monitor.delay, - 'timeout': monitor.timeout, - 'fall_threshold': monitor.fall_threshold, - 'rise_threshold': monitor.rise_threshold, - 'http_method': monitor.http_method, - 'url_path': monitor.url_path, - 'expected_codes': codes, - 'enabled': monitor.enabled, - 'http_version': monitor.http_version, - 'domain_name': monitor.domain_name, - } - - def _transform_l7policy(self, l7policy, feature_compatibility, - pool_tls_certs=None): - """Transforms an L7 policy into an object that will - - be processed by the templating system - """ - ret_value = { - 'id': l7policy.id, - 'action': l7policy.action, - 'redirect_url': l7policy.redirect_url, - 'redirect_prefix': l7policy.redirect_prefix, - 'enabled': l7policy.enabled - } - if (l7policy.redirect_pool and - l7policy.redirect_pool.provisioning_status != - constants.PENDING_DELETE): - kwargs = {} - if pool_tls_certs and pool_tls_certs.get( - l7policy.redirect_pool.id): - kwargs = {'pool_tls_certs': - pool_tls_certs.get(l7policy.redirect_pool.id)} - ret_value['redirect_pool'] = self._transform_pool( - l7policy.redirect_pool, feature_compatibility, **kwargs) - else: - ret_value['redirect_pool'] = None - if (l7policy.action in [constants.L7POLICY_ACTION_REDIRECT_TO_URL, - constants.L7POLICY_ACTION_REDIRECT_PREFIX] and - l7policy.redirect_http_code): - ret_value['redirect_http_code'] = l7policy.redirect_http_code - else: - ret_value['redirect_http_code'] = None - rule_gen = (rule for rule in l7policy.l7rules if rule.enabled and - rule.provisioning_status != constants.PENDING_DELETE) - l7rules = [self._transform_l7rule(x, feature_compatibility) - for x in rule_gen] - ret_value['l7rules'] = l7rules - return ret_value - - def _transform_l7rule(self, l7rule, feature_compatibility): - """Transforms an L7 rule into an object that will - - be processed by the templating system - """ - return { - 'id': l7rule.id, - 'type': l7rule.type, - 'compare_type': l7rule.compare_type, - 'key': l7rule.key, - 'value': self._escape_haproxy_config_string(l7rule.value), - 'invert': l7rule.invert, - 'enabled': l7rule.enabled - } - - @staticmethod - def _escape_haproxy_config_string(value): - """Escapes certain characters in a given string such that - - haproxy will parse the string as a single value - """ - # Escape backslashes first - value = re.sub(r'\\', r'\\\\', value) - # Spaces next - value = re.sub(' ', '\\ ', value) - return value diff --git a/octavia/common/jinja/haproxy/split_listeners/templates/base.j2 b/octavia/common/jinja/haproxy/split_listeners/templates/base.j2 deleted file mode 100644 index 591b4442fa..0000000000 --- a/octavia/common/jinja/haproxy/split_listeners/templates/base.j2 +++ /dev/null @@ -1,50 +0,0 @@ -{# Copyright (c) 2015 Rackspace -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -#} -# Configuration for loadbalancer {{ loadbalancer_id }} -global - daemon - user nobody - log {{ log_http | default('/run/rsyslog/octavia/log', true)}} local{{ user_log_facility }} - log {{ log_server | default('/run/rsyslog/octavia/log', true)}} local{{ administrative_log_facility }} notice - stats socket {{ sock_path }} mode 0666 level user - {% if loadbalancer.global_connection_limit is defined %} - maxconn {{ loadbalancer.global_connection_limit }} - {% endif %} - {% set found_ns = namespace(found=false) %} - {% for pool in loadbalancer.listener.pools if pool.enabled %} - {% if pool.health_monitor and pool.health_monitor.enabled and - pool.health_monitor.type == constants.HEALTH_MONITOR_PING and - found_ns.found == false %} - {% set found_ns.found = true %} - external-check - {% endif %} - {% endfor %} - -defaults - {% if connection_logging %} - log global - {% else %} - no log - {% endif %} - retries 3 - option redispatch - option splice-request - option splice-response - option http-keep-alive - -{% block peers %}{% endblock peers %} - -{% block proxies %}{% endblock proxies %} diff --git a/octavia/common/jinja/haproxy/split_listeners/templates/haproxy.cfg.j2 b/octavia/common/jinja/haproxy/split_listeners/templates/haproxy.cfg.j2 deleted file mode 100644 index 48ab2d3f4d..0000000000 --- a/octavia/common/jinja/haproxy/split_listeners/templates/haproxy.cfg.j2 +++ /dev/null @@ -1,40 +0,0 @@ -{# Copyright (c) 2015 Rackspace -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -#} -{% extends 'base.j2' %} - - -{% from 'macros.j2' import frontend_macro, backend_macro %} -{% from 'macros.j2' import peers_macro %} - - -{% set loadbalancer_id = loadbalancer.id %} -{% set sock_path = stats_sock %} - - -{% block peers %} -{{ peers_macro(constants, loadbalancer.listener) }} -{% endblock peers %} - - -{% block proxies %} - {% if loadbalancer.enabled and loadbalancer.listener.enabled %} - {{- frontend_macro(constants, loadbalancer.listener, - loadbalancer.vip_address, loadbalancer.additional_vips) }} - {% for pool in loadbalancer.listener.pools if pool.enabled %} - {{- backend_macro(constants, loadbalancer.listener, pool) }} - {% endfor %} - {% endif %} -{% endblock proxies %} diff --git a/octavia/common/jinja/haproxy/split_listeners/templates/macros.j2 b/octavia/common/jinja/haproxy/split_listeners/templates/macros.j2 deleted file mode 100644 index 2c08900941..0000000000 --- a/octavia/common/jinja/haproxy/split_listeners/templates/macros.j2 +++ /dev/null @@ -1,373 +0,0 @@ -{# Copyright (c) 2015 Rackspace -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -#} -{% macro peers_macro(constants,listener) %} - {% if listener.topology == constants.TOPOLOGY_ACTIVE_STANDBY %} -peers {{ "%s_peers"|format(listener.id.replace("-", ""))|trim() }} - {% for amp in listener.amphorae if ( - amp.status == constants.AMPHORA_ALLOCATED) %} - {# HAProxy has peer name limitations, thus the hash filter #} - peer {{ amp.id|hash_amp_id|replace('=', '') }} {{ - amp.vrrp_ip }}:{{ listener.peer_port }} - {% endfor %} - {% endif %} -{% endmacro %} - - -{% macro bind_macro(constants, listener, lb_vip_address) %} - {% if listener.crt_list_filename is defined %} - {% set def_crt_opt = ("ssl crt-list %s"|format( - listener.crt_list_filename)|trim()) %} - {% else %} - {% set def_crt_opt = "" %} - {% endif %} - {% if listener.client_ca_tls_path and listener.client_auth %} - {% set client_ca_opt = "ca-file %s verify %s"|format(listener.client_ca_tls_path, listener.client_auth)|trim() %} - {% else %} - {% set client_ca_opt = "" %} - {% endif %} - {% if listener.client_crl_path and listener.client_ca_tls_path %} - {% set ca_crl_opt = "crl-file %s"|format(listener.client_crl_path)|trim() %} - {% else %} - {% set ca_crl_opt = "" %} - {% endif %} -bind {{ lb_vip_address }}:{{ listener.protocol_port }} {{ -"%s %s %s"|format(def_crt_opt, client_ca_opt, ca_crl_opt)|trim() }} -{% endmacro %} - - -{% macro l7rule_compare_type_macro(constants, ctype) %} - {% if ctype == constants.L7RULE_COMPARE_TYPE_REGEX %} - {{- "-m reg" -}} - {% elif ctype == constants.L7RULE_COMPARE_TYPE_STARTS_WITH %} - {{- "-m beg" -}} - {% elif ctype == constants.L7RULE_COMPARE_TYPE_ENDS_WITH %} - {{- "-m end" -}} - {% elif ctype == constants.L7RULE_COMPARE_TYPE_CONTAINS %} - {{- "-m sub" -}} - {% elif ctype == constants.L7RULE_COMPARE_TYPE_EQUAL_TO %} - {{- "-m str" -}} - {% endif %} -{% endmacro %} - - -{% macro l7rule_macro(constants, l7rule) %} - {% if l7rule.type == constants.L7RULE_TYPE_HOST_NAME %} - acl {{ l7rule.id }} req.hdr(host) -i {{ l7rule_compare_type_macro( - constants, l7rule.compare_type) }} {{ l7rule.value }} - {% elif l7rule.type == constants.L7RULE_TYPE_PATH %} - acl {{ l7rule.id }} path {{ l7rule_compare_type_macro( - constants, l7rule.compare_type) }} {{ l7rule.value }} - {% elif l7rule.type == constants.L7RULE_TYPE_FILE_TYPE %} - acl {{ l7rule.id }} path_end {{ l7rule_compare_type_macro( - constants, l7rule.compare_type) }} {{ l7rule.value }} - {% elif l7rule.type == constants.L7RULE_TYPE_HEADER %} - acl {{ l7rule.id }} req.hdr({{ l7rule.key }}) {{ - l7rule_compare_type_macro( - constants, l7rule.compare_type) }} {{ l7rule.value }} - {% elif l7rule.type == constants.L7RULE_TYPE_COOKIE %} - acl {{ l7rule.id }} req.cook({{ l7rule.key }}) {{ - l7rule_compare_type_macro( - constants, l7rule.compare_type) }} {{ l7rule.value }} - {% elif l7rule.type == constants.L7RULE_TYPE_SSL_CONN_HAS_CERT %} - acl {{ l7rule.id }} ssl_c_used - {% elif l7rule.type == constants.L7RULE_TYPE_SSL_VERIFY_RESULT %} - acl {{ l7rule.id }} ssl_c_verify eq {{ l7rule.value }} - {% elif l7rule.type == constants.L7RULE_TYPE_SSL_DN_FIELD %} - acl {{ l7rule.id }} ssl_c_s_dn({{ l7rule.key }}) {{ - l7rule_compare_type_macro( - constants, l7rule.compare_type) }} {{ l7rule.value }} - {% endif %} -{% endmacro %} - - -{% macro l7rule_invert_macro(invert) %} - {% if invert %} - {{- "!" -}} - {% endif %} -{% endmacro %} - - -{% macro l7rule_list_macro(l7policy) %} - {% for l7rule in l7policy.l7rules %} - {{- " " -}}{{- l7rule_invert_macro(l7rule.invert) -}}{{- l7rule.id -}} - {% endfor %} -{% endmacro %} - - -{% macro l7policy_macro(constants, l7policy) %} - {% for l7rule in l7policy.l7rules %} - {{- l7rule_macro(constants, l7rule) -}} - {% endfor %} - {% if l7policy.redirect_http_code %} - {% set redirect_http_code_opt = " code %s"|format( - l7policy.redirect_http_code) %} - {% else %} - {% set redirect_http_code_opt = "" %} - {% endif %} - {% if l7policy.action == constants.L7POLICY_ACTION_REJECT %} - http-request deny if{{ l7rule_list_macro(l7policy) }} - {% elif l7policy.action == constants.L7POLICY_ACTION_REDIRECT_TO_URL %} - redirect {{- redirect_http_code_opt }} location {{ l7policy.redirect_url }} if{{ l7rule_list_macro( - l7policy) }} - {% elif l7policy.action == constants.L7POLICY_ACTION_REDIRECT_TO_POOL and l7policy.redirect_pool.enabled %} - use_backend {{ l7policy.redirect_pool.id }} if{{ l7rule_list_macro( - l7policy) }} - {% elif l7policy.action == constants.L7POLICY_ACTION_REDIRECT_PREFIX %} - redirect {{- redirect_http_code_opt }} prefix {{ l7policy.redirect_prefix }} if{{ l7rule_list_macro( - l7policy) }} - {% endif %} -{% endmacro %} - - -{% macro frontend_macro(constants, listener, lb_vip_address, additional_vips) %} -frontend {{ listener.id }} - {% if listener.connection_limit is defined %} - maxconn {{ listener.connection_limit }} - {% endif %} - {% if (listener.protocol.lower() == - constants.PROTOCOL_TERMINATED_HTTPS.lower()) %} - redirect scheme https if !{ ssl_fc } - {% endif %} - {{ bind_macro(constants, listener, lb_vip_address)|trim() }} - {% for add_vip in additional_vips %} - {{ bind_macro(constants, listener, add_vip)|trim() }} - {% endfor %} - mode {{ listener.protocol_mode }} - {% for l7policy in listener.l7policies if (l7policy.enabled and - l7policy.l7rules|length > 0) %} - {{- l7policy_macro(constants, l7policy) -}} - {% endfor %} - {% if listener.default_pool and listener.default_pool.enabled %} - default_backend {{ listener.default_pool.id }} - {% endif %} - timeout client {{ listener.timeout_client_data }} - {% if listener.user_log_format is defined %} - log-format {{ listener.user_log_format }} - {% endif %} - {% if listener.timeout_tcp_inspect %} - tcp-request inspect-delay {{ listener.timeout_tcp_inspect }} - {% endif %} -{% endmacro %} - - -{% macro member_macro(constants, pool, member) %} - {% if pool.health_monitor and pool.health_monitor.enabled %} - {% if member.monitor_address %} - {% set monitor_addr_opt = " addr %s"|format(member.monitor_address) %} - {% else %} - {% set monitor_addr_opt = "" %} - {% endif %} - {% if member.monitor_port %} - {% set monitor_port_opt = " port %s"|format(member.monitor_port) %} - {% else %} - {% set monitor_port_opt = "" %} - {% endif %} - {% if pool.health_monitor.type == constants.HEALTH_MONITOR_HTTPS %} - {% set monitor_ssl_opt = " check-ssl verify none" %} - {% else %} - {% set monitor_ssl_opt = "" %} - {% endif %} - {% set hm_opt = " check%s inter %ds fall %d rise %d%s%s"|format( - monitor_ssl_opt, pool.health_monitor.delay, - pool.health_monitor.fall_threshold, - pool.health_monitor.rise_threshold, monitor_addr_opt, - monitor_port_opt) %} - {% else %} - {% set hm_opt = "" %} - {% endif %} - {% if (pool.session_persistence.type == - constants.SESSION_PERSISTENCE_HTTP_COOKIE) %} - {% set persistence_opt = " cookie %s"|format(member.id) %} - {% else %} - {% set persistence_opt = "" %} - {% endif %} - {% if pool.protocol.lower() == constants.PROTOCOL_PROXY.lower() %} - {% set proxy_protocol_opt = " send-proxy" %} - {% else %} - {% set proxy_protocol_opt = "" %} - {% endif %} - {% if member.backup %} - {% set member_backup_opt = " backup" %} - {% else %} - {% set member_backup_opt = "" %} - {% endif %} - {% if member.enabled %} - {% set member_enabled_opt = "" %} - {% else %} - {% set member_enabled_opt = " disabled" %} - {% endif %} - {% if pool.tls_enabled %} - {% set def_opt_prefix = " ssl" %} - {% set def_sni_opt = " sni ssl_fc_sni" %} - {% else %} - {% set def_opt_prefix = "" %} - {% set def_sni_opt = "" %} - {% endif %} - {% if pool.client_cert and pool.tls_enabled %} - {% set def_crt_opt = " crt %s"|format(pool.client_cert) %} - {% else %} - {% set def_crt_opt = "" %} - {% endif %} - {% if pool.ca_cert and pool.tls_enabled %} - {% set ca_opt = " ca-file %s"|format(pool.ca_cert) %} - {% set def_verify_opt = " verify required" %} - {% if pool.crl %} - {% set crl_opt = " crl-file %s"|format(pool.crl) %} - {% else %} - {% set def_verify_opt = "" %} - {% endif %} - {% elif pool.tls_enabled %} - {% set def_verify_opt = " verify none" %} - {% endif %} - {{ "server %s %s:%d weight %s%s%s%s%s%s%s%s%s%s%s%s"|e|format( - member.id, member.address, member.protocol_port, member.weight, - hm_opt, persistence_opt, proxy_protocol_opt, member_backup_opt, - member_enabled_opt, def_opt_prefix, def_crt_opt, ca_opt, crl_opt, - def_verify_opt, def_sni_opt)|trim() }} -{% endmacro %} - - -{% macro backend_macro(constants, listener, pool) %} -backend {{ pool.id }} - {% if pool.protocol.lower() == constants.PROTOCOL_PROXY.lower() %} - mode {{ listener.protocol_mode }} - {% else %} - mode {{ pool.protocol }} - {% endif %} - {% if pool.get(constants.HTTP_REUSE, False) and ( - pool.protocol.lower() == constants.PROTOCOL_HTTP.lower() or - (pool.protocol.lower() == constants.PROTOCOL_PROXY.lower() and - listener.protocol_mode.lower() == - constants.PROTOCOL_HTTP.lower()))%} - http-reuse safe - {% endif %} - balance {{ pool.lb_algorithm }} - {% if pool.session_persistence %} - {% if (pool.session_persistence.type == - constants.SESSION_PERSISTENCE_SOURCE_IP) %} - {% if listener.topology == constants.TOPOLOGY_ACTIVE_STANDBY %} - stick-table type ip size {{ pool.stick_size }} peers {{ - "%s_peers"|format(listener.id.replace("-", ""))|trim() }} - {% else %} - stick-table type ip size {{ pool.stick_size }} - {% endif %} - stick on src - {% elif (pool.session_persistence.type == - constants.SESSION_PERSISTENCE_APP_COOKIE) %} - {% if listener.topology == constants.TOPOLOGY_ACTIVE_STANDBY %} - stick-table type string len 64 size {{ - pool.stick_size }} peers {{ - "%s_peers"|format(listener.id.replace("-", ""))|trim() }} - {% else %} - stick-table type string len 64 size {{ pool.stick_size }} - {% endif %} - stick store-response res.cook({{ pool.session_persistence.cookie_name }}) - stick match req.cook({{ pool.session_persistence.cookie_name }}) - {% elif (pool.session_persistence.type == - constants.SESSION_PERSISTENCE_HTTP_COOKIE) %} - cookie SRV insert indirect nocache - {% endif %} - {% endif %} - {% if pool.health_monitor and pool.health_monitor.enabled %} - timeout check {{ pool.health_monitor.timeout }}s - {% if (pool.health_monitor.type == - constants.HEALTH_MONITOR_HTTP or pool.health_monitor.type == - constants.HEALTH_MONITOR_HTTPS) %} - {% if (pool.health_monitor.http_version and - pool.health_monitor.http_version == 1.1 and - pool.health_monitor.domain_name) %} - option httpchk {{ pool.health_monitor.http_method }} {{ pool.health_monitor.url_path }} HTTP/ - {{- pool.health_monitor.http_version -}}{{- "\\r\\n" | safe -}} - Host:\ {{ pool.health_monitor.domain_name }} - {% elif pool.health_monitor.http_version %} - option httpchk {{ pool.health_monitor.http_method }} {{ pool.health_monitor.url_path }} HTTP/ - {{- pool.health_monitor.http_version -}}{{- "\\r\\n" | safe }} - {% else %} - option httpchk {{ pool.health_monitor.http_method }} {{ pool.health_monitor.url_path }} - {% endif %} - http-check expect rstatus {{ pool.health_monitor.expected_codes }} - {% endif %} - {% if pool.health_monitor.type == constants.HEALTH_MONITOR_TLS_HELLO %} - option ssl-hello-chk - {% endif %} - {% if pool.health_monitor.type == constants.HEALTH_MONITOR_PING %} - option external-check - external-check command /var/lib/octavia/ping-wrapper.sh - {% endif %} - {% endif %} - {% if pool.protocol.lower() == constants.PROTOCOL_HTTP.lower() %} - {% if listener.insert_headers.get('X-Forwarded-For', - 'False').lower() == 'true' %} - option forwardfor - {% endif %} - {% if listener.insert_headers.get('X-Forwarded-Port', - 'False').lower() == 'true' %} - http-request set-header X-Forwarded-Port %[dst_port] - {% endif %} - {% endif %} - {% if listener.insert_headers.get('X-Forwarded-Proto', - 'False').lower() == 'true' %} - {% if listener.protocol.lower() == constants.PROTOCOL_HTTP.lower() %} - http-request set-header X-Forwarded-Proto http - {% elif listener.protocol.lower() == - constants.PROTOCOL_TERMINATED_HTTPS.lower() %} - http-request set-header X-Forwarded-Proto https - {% endif %} - {% endif %} - {% if listener.protocol.lower() == constants.PROTOCOL_TERMINATED_HTTPS.lower() %} - {% if listener.insert_headers.get('X-SSL-Client-Verify', - 'False').lower() == 'true' %} - http-request set-header X-SSL-Client-Verify %[ssl_c_verify] - {% endif %} - {% if listener.insert_headers.get('X-SSL-Client-Has-Cert', - 'False').lower() == 'true' %} - http-request set-header X-SSL-Client-Has-Cert %[ssl_c_used] - {% endif %} - {% if listener.insert_headers.get('X-SSL-Client-DN', - 'False').lower() == 'true' %} - http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn] - {% endif %} - {% if listener.insert_headers.get('X-SSL-Client-CN', - 'False').lower() == 'true' %} - http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)] - {% endif %} - {% if listener.insert_headers.get('X-SSL-Issuer', - 'False').lower() == 'true' %} - http-request set-header X-SSL-Issuer %{+Q}[ssl_c_i_dn] - {% endif %} - {% if listener.insert_headers.get('X-SSL-Client-SHA1', - 'False').lower() == 'true' %} - http-request set-header X-SSL-Client-SHA1 %{+Q}[ssl_c_sha1,hex] - {% endif %} - {% if listener.insert_headers.get('X-SSL-Client-Not-Before', - 'False').lower() == 'true' %} - http-request set-header X-SSL-Client-Not-Before %{+Q}[ssl_c_notbefore] - {% endif %} - {% if listener.insert_headers.get('X-SSL-Client-Not-After', - 'False').lower() == 'true' %} - http-request set-header X-SSL-Client-Not-After %{+Q}[ssl_c_notafter] - {% endif %} - {% endif %} - {% if listener.connection_limit is defined %} - fullconn {{ listener.connection_limit }} - {% endif %} - option allbackups - timeout connect {{ listener.timeout_member_connect }} - timeout server {{ listener.timeout_member_data }} - {% for member in pool.members %} - {{- member_macro(constants, pool, member) -}} - {% endfor %} -{% endmacro %} diff --git a/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver.py b/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver.py index 8bef00ebea..928446e96d 100644 --- a/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver.py +++ b/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver.py @@ -13,6 +13,7 @@ # under the License. from unittest import mock +from octavia.amphorae.driver_exceptions.exceptions import AmpVersionUnsupported from octavia.amphorae.drivers.haproxy import exceptions as exc from octavia.amphorae.drivers.haproxy import rest_api_driver import octavia.tests.unit.base as base @@ -81,3 +82,11 @@ class TestHAProxyAmphoraDriver(base.TestCase): mock_api_version.assert_called_once_with(amphora_mock, None) client_mock.get_interface.assert_called_once_with( amphora_mock, IP_ADDRESS, None, log_error=False) + + def test_unsupported_api_version(self): + mock_amp = mock.MagicMock() + mock_amp.api_version = "0.5" + + self.assertRaises(AmpVersionUnsupported, + self.driver._populate_amphora_api_version, + mock_amp) diff --git a/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_0_5.py b/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_0_5.py deleted file mode 100644 index 990d71e0f3..0000000000 --- a/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_0_5.py +++ /dev/null @@ -1,1359 +0,0 @@ -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# Copyright (c) 2015 Rackspace -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -import hashlib -from unittest import mock - -from oslo_config import cfg -from oslo_config import fixture as oslo_fixture -from oslo_utils.secretutils import md5 -from oslo_utils import uuidutils -import requests -import requests_mock - -from octavia.amphorae.driver_exceptions import exceptions as driver_except -from octavia.amphorae.drivers.haproxy import exceptions as exc -from octavia.amphorae.drivers.haproxy import rest_api_driver as driver -from octavia.common import constants -from octavia.common import data_models -from octavia.common import utils as octavia_utils -from octavia.db import models -from octavia.network import data_models as network_models -from octavia.tests.common import sample_certs -from octavia.tests.unit import base -from octavia.tests.unit.common.sample_configs import sample_configs_split - -API_VERSION = '0.5' -FAKE_CIDR = '198.51.100.0/24' -FAKE_GATEWAY = '192.51.100.1' -FAKE_IP = '192.0.2.10' -FAKE_IPV6 = '2001:db8::cafe' -FAKE_IPV6_LLA = 'fe80::00ff:fe00:cafe' -FAKE_PEM_FILENAME = "file_name" -FAKE_UUID_1 = uuidutils.generate_uuid() -FAKE_VRRP_IP = '10.1.0.1' -FAKE_MAC_ADDRESS = '123' -FAKE_MTU = 1450 -FAKE_MEMBER_IP_PORT_NAME_1 = "10.0.0.10:1003" -FAKE_MEMBER_IP_PORT_NAME_2 = "10.0.0.11:1004" - - -class TestHaproxyAmphoraLoadBalancerDriverTest(base.TestCase): - - def setUp(self): - super().setUp() - - DEST1 = '198.51.100.0/24' - DEST2 = '203.0.113.0/24' - NEXTHOP = '192.0.2.1' - - self.driver = driver.HaproxyAmphoraLoadBalancerDriver() - - self.driver.cert_manager = mock.MagicMock() - self.driver.cert_parser = mock.MagicMock() - self.driver.clients = { - 'base': mock.MagicMock(), - API_VERSION: mock.MagicMock()} - self.driver.clients['base'].get_api_version.return_value = { - 'api_version': API_VERSION} - self.driver.clients[ - API_VERSION].get_info.return_value = { - 'haproxy_version': u'1.6.3-1ubuntu0.1', - 'api_version': API_VERSION} - self.driver.jinja_split = mock.MagicMock() - self.driver.lvs_jinja = mock.MagicMock() - - # Build sample Listener and VIP configs - self.sl = sample_configs_split.sample_listener_tuple( - tls=True, sni=True, client_ca_cert=True, client_crl_cert=True, - recursive_nest=True) - self.sl_udp = sample_configs_split.sample_listener_tuple( - proto=constants.PROTOCOL_UDP, - persistence_type=constants.SESSION_PERSISTENCE_SOURCE_IP, - persistence_timeout=33, - persistence_granularity='255.255.0.0', - monitor_proto=constants.HEALTH_MONITOR_UDP_CONNECT) - self.pool_has_cert = sample_configs_split.sample_pool_tuple( - pool_cert=True, pool_ca_cert=True, pool_crl=True) - self.amp = self.sl.load_balancer.amphorae[0] - self.sv = sample_configs_split.sample_vip_tuple() - self.lb = self.sl.load_balancer - self.lb_udp = ( - sample_configs_split.sample_lb_with_udp_listener_tuple()) - self.fixed_ip = mock.MagicMock() - self.fixed_ip.ip_address = '198.51.100.5' - self.fixed_ip.subnet.cidr = '198.51.100.0/24' - self.fixed_ip.subnet.gateway_ip = FAKE_GATEWAY - self.network = network_models.Network(mtu=FAKE_MTU) - self.port = network_models.Port(mac_address=FAKE_MAC_ADDRESS, - fixed_ips=[self.fixed_ip], - network=self.network) - - self.host_routes = [network_models.HostRoute(destination=DEST1, - nexthop=NEXTHOP), - network_models.HostRoute(destination=DEST2, - nexthop=NEXTHOP)] - host_routes_data = [{'destination': DEST1, 'nexthop': NEXTHOP}, - {'destination': DEST2, 'nexthop': NEXTHOP}] - self.subnet_info = {'subnet_cidr': FAKE_CIDR, - 'gateway': FAKE_GATEWAY, - 'mac_address': FAKE_MAC_ADDRESS, - 'vrrp_ip': self.amp.vrrp_ip, - 'mtu': FAKE_MTU, - 'host_routes': host_routes_data, - 'additional_vips': []} - - self.timeout_dict = {constants.REQ_CONN_TIMEOUT: 1, - constants.REQ_READ_TIMEOUT: 2, - constants.CONN_MAX_RETRIES: 3, - constants.CONN_RETRY_INTERVAL: 4} - self.amp_net_config = network_models.AmphoraNetworkConfig( - vip_subnet=self.lb.vip.subnet_id - ) - - @mock.patch('octavia.amphorae.drivers.haproxy.rest_api_driver.' - 'HaproxyAmphoraLoadBalancerDriver._process_secret') - @mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data') - def test_update_amphora_listeners(self, mock_load_cert, mock_secret): - mock_amphora = mock.MagicMock() - mock_amphora.id = 'mock_amphora_id' - mock_amphora.api_version = API_VERSION - mock_secret.return_value = 'filename.pem' - mock_load_cert.return_value = { - 'tls_cert': self.sl.default_tls_container, 'sni_certs': [], - 'client_ca_cert': None} - self.driver.jinja_split.build_config.return_value = 'the_config' - - mock_empty_lb = mock.MagicMock() - mock_empty_lb.listeners = [] - self.driver.update_amphora_listeners(mock_empty_lb, mock_amphora, - self.timeout_dict) - mock_load_cert.assert_not_called() - self.driver.jinja_split.build_config.assert_not_called() - self.driver.clients[API_VERSION].upload_config.assert_not_called() - self.driver.clients[API_VERSION].reload_listener.assert_not_called() - - self.driver.update_amphora_listeners(self.lb, - mock_amphora, self.timeout_dict) - self.driver.clients[API_VERSION].upload_config.assert_called_once_with( - mock_amphora, self.sl.id, 'the_config', - timeout_dict=self.timeout_dict) - self.driver.clients[API_VERSION].reload_listener( - mock_amphora, self.sl.id, timeout_dict=self.timeout_dict) - - mock_load_cert.reset_mock() - self.driver.jinja_split.build_config.reset_mock() - self.driver.clients[API_VERSION].upload_config.reset_mock() - self.driver.clients[API_VERSION].reload_listener.reset_mock() - mock_amphora.status = constants.DELETED - self.driver.update_amphora_listeners(self.lb, - mock_amphora, self.timeout_dict) - mock_load_cert.assert_not_called() - self.driver.jinja_split.build_config.assert_not_called() - self.driver.clients[API_VERSION].upload_config.assert_not_called() - self.driver.clients[API_VERSION].reload_listener.assert_not_called() - - @mock.patch('octavia.db.api.get_session') - @mock.patch('octavia.db.repositories.ListenerRepository.update') - @mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data') - def test_update_amphora_listeners_bad_cert( - self, mock_load_cert, mock_list_update, mock_get_session): - mock_amphora = mock.MagicMock() - mock_amphora.id = 'mock_amphora_id' - mock_amphora.api_version = API_VERSION - - mock_get_session.return_value = 'fake_session' - mock_load_cert.side_effect = [Exception] - self.driver.update_amphora_listeners(self.lb, - mock_amphora, self.timeout_dict) - mock_list_update.assert_called_once_with( - 'fake_session', self.lb.listeners[0].id, - provisioning_status=constants.ERROR, - operating_status=constants.ERROR) - self.driver.jinja_split.build_config.assert_not_called() - self.driver.clients[API_VERSION].delete_listener.assert_not_called() - - @mock.patch('octavia.amphorae.drivers.haproxy.rest_api_driver.' - 'HaproxyAmphoraLoadBalancerDriver._process_secret') - @mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data') - @mock.patch('octavia.common.tls_utils.cert_parser.get_host_names') - def test_update(self, mock_cert, mock_load_crt, mock_secret): - mock_cert.return_value = {'cn': sample_certs.X509_CERT_CN} - mock_secret.side_effect = ['filename.pem', 'crl-filename.pem'] - sconts = [] - for sni_container in self.sl.sni_containers: - sconts.append(sni_container.tls_container) - mock_load_crt.side_effect = [{ - 'tls_cert': self.sl.default_tls_container, 'sni_certs': sconts}, - {'tls_cert': None, 'sni_certs': []}] - self.driver.clients[API_VERSION].get_cert_md5sum.side_effect = [ - exc.NotFound, 'Fake_MD5', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'CA_CERT_MD5'] - self.driver.jinja_split.build_config.side_effect = ['fake_config'] - - # Execute driver method - self.driver.update(self.lb) - - # verify result - gcm_calls = [ - mock.call(self.amp, self.sl.id, - self.sl.default_tls_container.id + '.pem', - ignore=(404,)), - mock.call(self.amp, self.sl.id, - sconts[0].id + '.pem', ignore=(404,)), - mock.call(self.amp, self.sl.id, - sconts[1].id + '.pem', ignore=(404,)), - ] - - self.driver.clients[API_VERSION].get_cert_md5sum.assert_has_calls( - gcm_calls, any_order=True) - - # this is called three times (last MD5 matches) - fp1 = b'\n'.join([sample_certs.X509_CERT, - sample_certs.X509_CERT_KEY, - sample_certs.X509_IMDS]) + b'\n' - fp2 = b'\n'.join([sample_certs.X509_CERT_2, - sample_certs.X509_CERT_KEY_2, - sample_certs.X509_IMDS]) + b'\n' - fp3 = b'\n'.join([sample_certs.X509_CERT_3, - sample_certs.X509_CERT_KEY_3, - sample_certs.X509_IMDS]) + b'\n' - - ucp_calls = [ - mock.call(self.amp, self.sl.id, - self.sl.default_tls_container.id + '.pem', fp1), - mock.call(self.amp, self.sl.id, - sconts[0].id + '.pem', fp2), - mock.call(self.amp, self.sl.id, - sconts[1].id + '.pem', fp3), - ] - - self.driver.clients[API_VERSION].upload_cert_pem.assert_has_calls( - ucp_calls, any_order=True) - - # upload only one config file - self.driver.clients[API_VERSION].upload_config.assert_called_once_with( - self.amp, self.sl.id, 'fake_config', timeout_dict=None) - # start should be called once - self.driver.clients[ - API_VERSION].reload_listener.assert_called_once_with( - self.amp, self.sl.id, timeout_dict=None) - secret_calls = [ - mock.call(self.sl, self.sl.client_ca_tls_certificate_id, self.amp, - self.sl.id), - mock.call(self.sl, self.sl.client_crl_container_id, self.amp, - self.sl.id) - ] - mock_secret.assert_has_calls(secret_calls) - - def test_udp_update(self): - self.driver.lvs_jinja.build_config.side_effect = ['fake_udp_config'] - - # Execute driver method - self.driver.update(self.lb_udp) - - # upload only one config file - self.driver.clients[ - API_VERSION].upload_udp_config.assert_called_once_with( - self.amp, self.sl_udp.id, 'fake_udp_config', timeout_dict=None) - - # start should be called once - self.driver.clients[ - API_VERSION].reload_listener.assert_called_once_with( - self.amp, self.sl_udp.id, timeout_dict=None) - - def test_upload_cert_amp(self): - self.driver.upload_cert_amp(self.amp, octavia_utils.b('test')) - self.driver.clients[ - API_VERSION].update_cert_for_rotation.assert_called_once_with( - self.amp, octavia_utils.b('test')) - - @mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data') - def test__process_tls_certificates_no_ca_cert(self, mock_load_crt): - sample_listener = sample_configs_split.sample_listener_tuple( - tls=True, sni=True) - sconts = [] - for sni_container in sample_listener.sni_containers: - sconts.append(sni_container.tls_container) - mock_load_crt.return_value = { - 'tls_cert': self.sl.default_tls_container, - 'sni_certs': sconts - } - self.driver.clients[API_VERSION].get_cert_md5sum.side_effect = [ - exc.NotFound, 'Fake_MD5', 'aaaaa', 'aaaaaaaa'] - self.driver._process_tls_certificates( - sample_listener, self.amp, sample_listener.id) - gcm_calls = [ - mock.call(self.amp, sample_listener.id, - self.sl.default_tls_container.id + '.pem', - ignore=(404,)), - mock.call(self.amp, sample_listener.id, - sconts[0].id + '.pem', ignore=(404,)), - mock.call(self.amp, sample_listener.id, - sconts[1].id + '.pem', ignore=(404,)) - ] - self.driver.clients[API_VERSION].get_cert_md5sum.assert_has_calls( - gcm_calls, any_order=True) - fp1 = b'\n'.join([sample_certs.X509_CERT, - sample_certs.X509_CERT_KEY, - sample_certs.X509_IMDS]) + b'\n' - fp2 = b'\n'.join([sample_certs.X509_CERT_2, - sample_certs.X509_CERT_KEY_2, - sample_certs.X509_IMDS]) + b'\n' - fp3 = b'\n'.join([sample_certs.X509_CERT_3, - sample_certs.X509_CERT_KEY_3, - sample_certs.X509_IMDS]) + b'\n' - ucp_calls = [ - mock.call(self.amp, sample_listener.id, - self.sl.default_tls_container.id + '.pem', fp1), - mock.call(self.amp, sample_listener.id, - sconts[0].id + '.pem', fp2), - mock.call(self.amp, sample_listener.id, - sconts[1].id + '.pem', fp3) - ] - self.driver.clients[API_VERSION].upload_cert_pem.assert_has_calls( - ucp_calls, any_order=True) - self.assertEqual( - 4, self.driver.clients[API_VERSION].upload_cert_pem.call_count) - - @mock.patch('oslo_context.context.RequestContext') - @mock.patch('octavia.amphorae.drivers.haproxy.rest_api_driver.' - 'HaproxyAmphoraLoadBalancerDriver._upload_cert') - def test_process_secret(self, mock_upload_cert, mock_oslo): - # Test bypass if no secret_ref - sample_listener = sample_configs_split.sample_listener_tuple( - tls=True, sni=True) - - result = self.driver._process_secret(sample_listener, None) - - self.assertIsNone(result) - self.driver.cert_manager.get_secret.assert_not_called() - - # Test the secret process - sample_listener = sample_configs_split.sample_listener_tuple( - tls=True, sni=True, client_ca_cert=True) - fake_context = 'fake context' - fake_secret = b'fake cert' - mock_oslo.return_value = fake_context - self.driver.cert_manager.get_secret.reset_mock() - self.driver.cert_manager.get_secret.return_value = fake_secret - ref_md5 = md5(fake_secret, usedforsecurity=False).hexdigest() # nosec - ref_id = hashlib.sha1(fake_secret).hexdigest() # nosec - ref_name = '{id}.pem'.format(id=ref_id) - - result = self.driver._process_secret( - sample_listener, sample_listener.client_ca_tls_certificate_id, - self.amp, sample_listener.id) - - mock_oslo.assert_called_once_with( - project_id=sample_listener.project_id) - self.driver.cert_manager.get_secret.assert_called_once_with( - fake_context, sample_listener.client_ca_tls_certificate_id) - mock_upload_cert.assert_called_once_with( - self.amp, sample_listener.id, pem=fake_secret, - md5sum=ref_md5, name=ref_name) - self.assertEqual(ref_name, result) - - @mock.patch('octavia.amphorae.drivers.haproxy.rest_api_driver.' - 'HaproxyAmphoraLoadBalancerDriver._process_pool_certs') - def test__process_listener_pool_certs(self, mock_pool_cert): - sample_listener = sample_configs_split.sample_listener_tuple( - l7=True) - - ref_pool_cert_1 = {'client_cert': '/some/fake/cert-1.pem'} - ref_pool_cert_2 = {'client_cert': '/some/fake/cert-2.pem'} - - mock_pool_cert.side_effect = [ref_pool_cert_1, ref_pool_cert_2] - - ref_cert_dict = {'sample_pool_id_1': ref_pool_cert_1, - 'sample_pool_id_2': ref_pool_cert_2} - - result = self.driver._process_listener_pool_certs( - sample_listener, self.amp, sample_listener.id) - - pool_certs_calls = [ - mock.call(sample_listener, sample_listener.default_pool, - self.amp, sample_listener.id), - mock.call(sample_listener, sample_listener.pools[1], - self.amp, sample_listener.id) - ] - - mock_pool_cert.assert_has_calls(pool_certs_calls, any_order=True) - - self.assertEqual(ref_cert_dict, result) - - @mock.patch('octavia.amphorae.drivers.haproxy.rest_api_driver.' - 'HaproxyAmphoraLoadBalancerDriver._process_secret') - @mock.patch('octavia.amphorae.drivers.haproxy.rest_api_driver.' - 'HaproxyAmphoraLoadBalancerDriver._upload_cert') - @mock.patch('octavia.common.tls_utils.cert_parser.build_pem') - @mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data') - def test__process_pool_certs(self, mock_load_certs, mock_build_pem, - mock_upload_cert, mock_secret): - fake_cert_dir = '/fake/cert/dir' - conf = oslo_fixture.Config(cfg.CONF) - conf.config(group="haproxy_amphora", base_cert_dir=fake_cert_dir) - sample_listener = sample_configs_split.sample_listener_tuple( - pool_cert=True, pool_ca_cert=True, pool_crl=True) - pool_cert = data_models.TLSContainer( - id=uuidutils.generate_uuid(), certificate='pool cert') - pool_data = {'tls_cert': pool_cert, 'sni_certs': []} - mock_load_certs.return_value = pool_data - fake_pem = b'fake pem' - mock_build_pem.return_value = fake_pem - ref_md5 = md5(fake_pem, usedforsecurity=False).hexdigest() # nosec - ref_name = '{id}.pem'.format(id=pool_cert.id) - ref_path = '{cert_dir}/{list_id}/{name}'.format( - cert_dir=fake_cert_dir, list_id=sample_listener.id, name=ref_name) - ref_ca_name = 'fake_ca.pem' - ref_ca_path = '{cert_dir}/{list_id}/{name}'.format( - cert_dir=fake_cert_dir, list_id=sample_listener.id, - name=ref_ca_name) - ref_crl_name = 'fake_crl.pem' - ref_crl_path = '{cert_dir}/{list_id}/{name}'.format( - cert_dir=fake_cert_dir, list_id=sample_listener.id, - name=ref_crl_name) - ref_result = {'client_cert': ref_path, 'ca_cert': ref_ca_path, - 'crl': ref_crl_path} - mock_secret.side_effect = [ref_ca_name, ref_crl_name] - - result = self.driver._process_pool_certs( - sample_listener, sample_listener.default_pool, self.amp, - sample_listener.id) - - secret_calls = [ - mock.call(sample_listener, - sample_listener.default_pool.ca_tls_certificate_id, - self.amp, sample_listener.id), - mock.call(sample_listener, - sample_listener.default_pool.crl_container_id, - self.amp, sample_listener.id)] - - mock_build_pem.assert_called_once_with(pool_cert) - mock_upload_cert.assert_called_once_with( - self.amp, sample_listener.id, pem=fake_pem, - md5sum=ref_md5, name=ref_name) - mock_secret.assert_has_calls(secret_calls) - self.assertEqual(ref_result, result) - - def test_start(self): - amp1 = mock.MagicMock() - amp1.api_version = API_VERSION - amp2 = mock.MagicMock() - amp2.api_version = API_VERSION - amp2.status = constants.DELETED - loadbalancer = mock.MagicMock() - loadbalancer.id = uuidutils.generate_uuid() - loadbalancer.amphorae = [amp1, amp2] - loadbalancer.vip = self.sv - listener = mock.MagicMock() - listener.id = uuidutils.generate_uuid() - listener.protocol = constants.PROTOCOL_HTTP - loadbalancer.listeners = [listener] - listener.load_balancer = loadbalancer - self.driver.clients[ - API_VERSION].start_listener.__name__ = 'start_listener' - # Execute driver method - self.driver.start(loadbalancer) - self.driver.clients[ - API_VERSION].start_listener.assert_called_once_with( - amp1, listener.id, None) - - def test_reload(self): - amp1 = mock.MagicMock() - amp1.api_version = API_VERSION - amp2 = mock.MagicMock() - amp2.api_version = API_VERSION - amp2.status = constants.DELETED - loadbalancer = mock.MagicMock() - loadbalancer.id = uuidutils.generate_uuid() - loadbalancer.amphorae = [amp1, amp2] - loadbalancer.vip = self.sv - listener = mock.MagicMock() - listener.id = uuidutils.generate_uuid() - listener.protocol = constants.PROTOCOL_HTTP - loadbalancer.listeners = [listener] - listener.load_balancer = loadbalancer - self.driver.clients[ - API_VERSION].reload_listener.__name__ = 'reload_listener' - # Execute driver method - self.driver.reload(loadbalancer) - self.driver.clients[ - API_VERSION].reload_listener.assert_called_once_with( - amp1, listener.id, None) - - self.driver.clients[ - API_VERSION].reload_listener.reset_mock() - timeout_dict = { - 'elem1': 1000 - } - self.driver.reload(loadbalancer, timeout_dict=timeout_dict) - self.driver.clients[ - API_VERSION].reload_listener.assert_called_once_with( - amp1, listener.id, timeout_dict) - - def test_start_with_amphora(self): - # Execute driver method - amp = mock.MagicMock() - self.driver.clients[ - API_VERSION].start_listener.__name__ = 'start_listener' - self.driver.start(self.lb, self.amp) - self.driver.clients[ - API_VERSION].start_listener.assert_called_once_with( - self.amp, self.sl.id, None) - - self.driver.clients[API_VERSION].start_listener.reset_mock() - amp.status = constants.DELETED - self.driver.start(self.lb, amp) - self.driver.clients[API_VERSION].start_listener.assert_not_called() - - def test_udp_start(self): - self.driver.clients[ - API_VERSION].start_listener.__name__ = 'start_listener' - # Execute driver method - self.driver.start(self.lb_udp) - self.driver.clients[ - API_VERSION].start_listener.assert_called_once_with( - self.amp, self.sl_udp.id, None) - - @mock.patch('octavia.amphorae.drivers.haproxy.rest_api_driver.' - 'HaproxyAmphoraLoadBalancerDriver._process_secret') - @mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data') - @mock.patch('octavia.common.tls_utils.cert_parser.get_host_names') - def test_delete_second_listener(self, mock_cert, mock_load_crt, - mock_secret): - self.driver.clients[ - API_VERSION].delete_listener.__name__ = 'delete_listener' - sl = sample_configs_split.sample_listener_tuple( - tls=True, sni=True, client_ca_cert=True, client_crl_cert=True, - recursive_nest=True) - sl2 = sample_configs_split.sample_listener_tuple( - id='sample_listener_id_2') - sl.load_balancer.listeners.append(sl2) - mock_cert.return_value = {'cn': sample_certs.X509_CERT_CN} - mock_secret.side_effect = ['filename.pem', 'crl-filename.pem'] - sconts = [] - for sni_container in self.sl.sni_containers: - sconts.append(sni_container.tls_container) - mock_load_crt.side_effect = [{ - 'tls_cert': self.sl.default_tls_container, 'sni_certs': sconts}, - {'tls_cert': None, 'sni_certs': []}] - self.driver.jinja_split.build_config.side_effect = ['fake_config'] - - # Execute driver method - self.driver.delete(sl) - - # Now just make sure we did a delete - self.driver.clients[ - API_VERSION].delete_listener.assert_called_once_with( - self.amp, self.sl.id) - - @mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data') - def test_delete_last_listener(self, mock_load_crt): - self.driver.clients[ - API_VERSION].delete_listener.__name__ = 'delete_listener' - sl = sample_configs_split.sample_listener_tuple( - tls=True, sni=True, client_ca_cert=True, client_crl_cert=True, - recursive_nest=True) - mock_load_crt.side_effect = [{ - 'tls_cert': sl.default_tls_container, 'sni_certs': None}] - # Execute driver method - self.driver.delete(sl) - self.driver.clients[ - API_VERSION].delete_listener.assert_called_once_with( - self.amp, sl.id) - - def test_udp_delete(self): - self.driver.clients[ - API_VERSION].delete_listener.__name__ = 'delete_listener' - # Execute driver method - self.driver.delete(self.sl_udp) - self.driver.clients[ - API_VERSION].delete_listener.assert_called_once_with( - self.amp, self.sl_udp.id) - - def test_get_info(self): - expected_info = {'haproxy_version': '1.6.3-1ubuntu0.1', - 'api_version': API_VERSION} - result = self.driver.get_info(self.amp) - self.assertEqual(expected_info, result) - - def test_get_diagnostics(self): - # TODO(johnsom) Implement once this exists on the amphora agent. - result = self.driver.get_diagnostics(self.amp) - self.assertIsNone(result) - - def test_finalize_amphora(self): - # TODO(johnsom) Implement once this exists on the amphora agent. - result = self.driver.finalize_amphora(self.amp) - self.assertIsNone(result) - - def test_post_vip_plug(self): - amphorae_network_config = mock.MagicMock() - amphorae_network_config.get().vip_subnet.cidr = FAKE_CIDR - amphorae_network_config.get().vip_subnet.gateway_ip = FAKE_GATEWAY - amphorae_network_config.get().vip_subnet.host_routes = self.host_routes - amphorae_network_config.get().vip_subnet.to_dict.return_value = { - 'cidr': FAKE_CIDR, - 'gateway_ip': FAKE_GATEWAY, - 'host_routes': [ - hr.to_dict(recurse=True) - for hr in self.host_routes] - } - amphorae_network_config.get().vrrp_port = self.port - self.driver.post_vip_plug(self.amp, self.lb, amphorae_network_config) - self.driver.clients[API_VERSION].plug_vip.assert_called_once_with( - self.amp, self.lb.vip.ip_address, self.subnet_info) - - def test_post_network_plug(self): - # Test dhcp path - port = network_models.Port(mac_address=FAKE_MAC_ADDRESS, - fixed_ips=[], - network=self.network) - self.driver.post_network_plug(self.amp, port, self.amp_net_config) - self.driver.clients[API_VERSION].plug_network.assert_called_once_with( - self.amp, dict(mac_address=FAKE_MAC_ADDRESS, - fixed_ips=[], - mtu=FAKE_MTU)) - - self.driver.clients[API_VERSION].plug_network.reset_mock() - - # Test fixed IP path - self.driver.post_network_plug(self.amp, self.port, self.amp_net_config) - self.driver.clients[API_VERSION].plug_network.assert_called_once_with( - self.amp, dict(mac_address=FAKE_MAC_ADDRESS, - fixed_ips=[dict(ip_address='198.51.100.5', - subnet_cidr='198.51.100.0/24', - host_routes=[], - gateway=FAKE_GATEWAY)], - mtu=FAKE_MTU)) - - def test_post_network_plug_with_host_routes(self): - SUBNET_ID = 'SUBNET_ID' - FIXED_IP1 = '192.0.2.2' - FIXED_IP2 = '192.0.2.3' - SUBNET_CIDR = '192.0.2.0/24' - DEST1 = '198.51.100.0/24' - DEST2 = '203.0.113.0/24' - NEXTHOP = '192.0.2.1' - host_routes = [network_models.HostRoute(destination=DEST1, - nexthop=NEXTHOP), - network_models.HostRoute(destination=DEST2, - nexthop=NEXTHOP)] - subnet = network_models.Subnet(id=SUBNET_ID, cidr=SUBNET_CIDR, - gateway_ip=FAKE_GATEWAY, - ip_version=4, host_routes=host_routes) - fixed_ips = [ - network_models.FixedIP(subnet_id=subnet.id, ip_address=FIXED_IP1, - subnet=subnet), - network_models.FixedIP(subnet_id=subnet.id, ip_address=FIXED_IP2, - subnet=subnet) - ] - port = network_models.Port(mac_address=FAKE_MAC_ADDRESS, - fixed_ips=fixed_ips, - network=self.network) - self.driver.post_network_plug(self.amp, port, self.amp_net_config) - expected_fixed_ips = [ - {'ip_address': FIXED_IP1, 'subnet_cidr': SUBNET_CIDR, - 'gateway': FAKE_GATEWAY, - 'host_routes': [{'destination': DEST1, 'nexthop': NEXTHOP}, - {'destination': DEST2, 'nexthop': NEXTHOP}]}, - {'ip_address': FIXED_IP2, 'subnet_cidr': SUBNET_CIDR, - 'gateway': FAKE_GATEWAY, - 'host_routes': [{'destination': DEST1, 'nexthop': NEXTHOP}, - {'destination': DEST2, 'nexthop': NEXTHOP}]} - ] - self.driver.clients[API_VERSION].plug_network.assert_called_once_with( - self.amp, dict(mac_address=FAKE_MAC_ADDRESS, - fixed_ips=expected_fixed_ips, - mtu=FAKE_MTU)) - - def test_get_haproxy_versions(self): - ref_haproxy_versions = ['1', '6'] - result = self.driver._get_haproxy_versions(self.amp) - self.driver.clients[API_VERSION].get_info.assert_called_once_with( - self.amp, timeout_dict=None) - self.assertEqual(ref_haproxy_versions, result) - - def test_get_haproxy_versions_with_timeout_dict(self): - ref_haproxy_versions = ['1', '6'] - timeout_dict = { - constants.CONN_MAX_RETRIES: 100, - constants.CONN_RETRY_INTERVAL: 1 - } - result = self.driver._get_haproxy_versions(self.amp, - timeout_dict=timeout_dict) - self.driver.clients[API_VERSION].get_info.assert_called_once_with( - self.amp, timeout_dict=timeout_dict) - self.assertEqual(ref_haproxy_versions, result) - - def test_populate_amphora_api_version(self): - - # Normal path, populate the version - # clear out any previous values - ref_haproxy_version = list(map(int, API_VERSION.split('.'))) - mock_amp = mock.MagicMock() - mock_amp.api_version = None - result = self.driver._populate_amphora_api_version(mock_amp) - self.assertEqual(API_VERSION, mock_amp.api_version) - self.assertEqual(ref_haproxy_version, result) - - # Existing version passed in - fake_version = '9999.9999' - ref_haproxy_version = list(map(int, fake_version.split('.'))) - mock_amp = mock.MagicMock() - mock_amp.api_version = fake_version - result = self.driver._populate_amphora_api_version(mock_amp) - self.assertEqual(fake_version, mock_amp.api_version) - self.assertEqual(ref_haproxy_version, result) - - def test_update_amphora_agent_config(self): - self.driver.update_amphora_agent_config( - self.amp, octavia_utils.b('test')) - self.driver.clients[ - API_VERSION].update_agent_config.assert_called_once_with( - self.amp, octavia_utils.b('test'), timeout_dict=None) - - -class TestAmphoraAPIClientTest(base.TestCase): - - def setUp(self): - super().setUp() - self.driver = driver.AmphoraAPIClient0_5() - self.base_url = "https://192.0.2.77:9443/" - self.base_url_ver = self.base_url + API_VERSION - self.amp = models.Amphora(lb_network_ip='192.0.2.77', compute_id='123') - self.amp.api_version = API_VERSION - self.port_info = dict(mac_address=FAKE_MAC_ADDRESS) - # Override with much lower values for testing purposes.. - conf = oslo_fixture.Config(cfg.CONF) - conf.config(group="haproxy_amphora", connection_max_retries=2) - - self.subnet_info = {'subnet_cidr': FAKE_CIDR, - 'gateway': FAKE_GATEWAY, - 'mac_address': FAKE_MAC_ADDRESS, - 'vrrp_ip': self.amp.vrrp_ip} - patcher = mock.patch('time.sleep').start() - self.addCleanup(patcher.stop) - self.timeout_dict = {constants.REQ_CONN_TIMEOUT: 1, - constants.REQ_READ_TIMEOUT: 2, - constants.CONN_MAX_RETRIES: 3, - constants.CONN_RETRY_INTERVAL: 4} - - def test_base_url(self): - url = self.driver._base_url(FAKE_IP) - self.assertEqual('https://192.0.2.10:9443/', url) - url = self.driver._base_url(FAKE_IPV6, self.amp.api_version) - self.assertEqual('https://[2001:db8::cafe]:9443/0.5/', url) - url = self.driver._base_url(FAKE_IPV6_LLA, self.amp.api_version) - self.assertEqual('https://[fe80::00ff:fe00:cafe%o-hm0]:9443/0.5/', url) - - @mock.patch('requests.Session.get', side_effect=requests.ConnectionError) - @mock.patch('octavia.amphorae.drivers.haproxy.rest_api_driver.time.sleep') - def test_request(self, mock_sleep, mock_get): - self.assertRaises(driver_except.TimeOutException, - self.driver.request, 'get', self.amp, - 'unavailableURL', self.timeout_dict) - - @requests_mock.mock() - def test_get_api_version(self, mock_requests): - ref_api_version = {'api_version': '0.1'} - mock_requests.get('{base}/'.format(base=self.base_url), - json=ref_api_version) - result = self.driver.get_api_version(self.amp) - self.assertEqual(ref_api_version, result) - - @requests_mock.mock() - def test_get_api_version_not_found(self, mock_requests): - mock_requests.get('{base}/'.format(base=self.base_url), - status_code=404) - self.assertRaises(exc.NotFound, self.driver.get_api_version, self.amp) - - @requests_mock.mock() - def test_get_info(self, m): - info = {"hostname": "some_hostname", "version": "some_version", - "api_version": "0.5", "uuid": FAKE_UUID_1} - m.get("{base}/info".format(base=self.base_url_ver), - json=info) - information = self.driver.get_info(self.amp) - self.assertEqual(info, information) - - @requests_mock.mock() - def test_get_info_with_timeout_dict(self, m): - info = {"hostname": "some_hostname", "version": "some_version", - "api_version": "0.5", "uuid": FAKE_UUID_1} - m.get("{base}/info".format(base=self.base_url_ver), - json=info) - timeout_dict = { - constants.CONN_MAX_RETRIES: 100, - constants.CONN_RETRY_INTERVAL: 1 - } - information = self.driver.get_info(self.amp, timeout_dict=timeout_dict) - self.assertEqual(info, information) - - @requests_mock.mock() - def test_get_info_unauthorized(self, m): - m.get("{base}/info".format(base=self.base_url_ver), - status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.get_info, self.amp) - - @requests_mock.mock() - def test_get_info_missing(self, m): - m.get("{base}/info".format(base=self.base_url_ver), - status_code=404, - headers={'content-type': 'application/json'}) - self.assertRaises(exc.NotFound, self.driver.get_info, self.amp) - - @requests_mock.mock() - def test_get_info_server_error(self, m): - m.get("{base}/info".format(base=self.base_url_ver), - status_code=500) - self.assertRaises(exc.InternalServerError, self.driver.get_info, - self.amp) - - @requests_mock.mock() - def test_get_info_service_unavailable(self, m): - m.get("{base}/info".format(base=self.base_url_ver), - status_code=503) - self.assertRaises(exc.ServiceUnavailable, self.driver.get_info, - self.amp) - - @requests_mock.mock() - def test_get_details(self, m): - details = {"hostname": "some_hostname", "version": "some_version", - "api_version": "0.5", "uuid": FAKE_UUID_1, - "network_tx": "some_tx", "network_rx": "some_rx", - "active": True, "haproxy_count": 10} - m.get("{base}/details".format(base=self.base_url_ver), - json=details) - amp_details = self.driver.get_details(self.amp) - self.assertEqual(details, amp_details) - - @requests_mock.mock() - def test_get_details_unauthorized(self, m): - m.get("{base}/details".format(base=self.base_url_ver), - status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.get_details, self.amp) - - @requests_mock.mock() - def test_get_details_missing(self, m): - m.get("{base}/details".format(base=self.base_url_ver), - status_code=404, - headers={'content-type': 'application/json'}) - self.assertRaises(exc.NotFound, self.driver.get_details, self.amp) - - @requests_mock.mock() - def test_get_details_server_error(self, m): - m.get("{base}/details".format(base=self.base_url_ver), - status_code=500) - self.assertRaises(exc.InternalServerError, self.driver.get_details, - self.amp) - - @requests_mock.mock() - def test_get_details_service_unavailable(self, m): - m.get("{base}/details".format(base=self.base_url_ver), - status_code=503) - self.assertRaises(exc.ServiceUnavailable, self.driver.get_details, - self.amp) - - @requests_mock.mock() - def test_get_all_listeners(self, m): - listeners = [{"status": "ONLINE", "provisioning_status": "ACTIVE", - "type": "PASSIVE", "uuid": FAKE_UUID_1}] - m.get("{base}/listeners".format(base=self.base_url_ver), - json=listeners) - all_listeners = self.driver.get_all_listeners(self.amp) - self.assertEqual(listeners, all_listeners) - - @requests_mock.mock() - def test_get_all_listeners_unauthorized(self, m): - m.get("{base}/listeners".format(base=self.base_url_ver), - status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.get_all_listeners, - self.amp) - - @requests_mock.mock() - def test_get_all_listeners_missing(self, m): - m.get("{base}/listeners".format(base=self.base_url_ver), - status_code=404, - headers={'content-type': 'application/json'}) - self.assertRaises(exc.NotFound, self.driver.get_all_listeners, - self.amp) - - @requests_mock.mock() - def test_get_all_listeners_server_error(self, m): - m.get("{base}/listeners".format(base=self.base_url_ver), - status_code=500) - self.assertRaises(exc.InternalServerError, - self.driver.get_all_listeners, self.amp) - - @requests_mock.mock() - def test_get_all_listeners_service_unavailable(self, m): - m.get("{base}/listeners".format(base=self.base_url_ver), - status_code=503) - self.assertRaises(exc.ServiceUnavailable, - self.driver.get_all_listeners, self.amp) - - @requests_mock.mock() - def test_start_listener(self, m): - m.put("{base}/listeners/{listener_id}/start".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1)) - self.driver.start_listener(self.amp, FAKE_UUID_1) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_start_listener_missing(self, m): - m.put("{base}/listeners/{listener_id}/start".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), - status_code=404, - headers={'content-type': 'application/json'}) - self.assertRaises(exc.NotFound, self.driver.start_listener, - self.amp, FAKE_UUID_1) - - @requests_mock.mock() - def test_start_listener_unauthorized(self, m): - m.put("{base}/listeners/{listener_id}/start".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), - status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.start_listener, - self.amp, FAKE_UUID_1) - - @requests_mock.mock() - def test_start_listener_server_error(self, m): - m.put("{base}/listeners/{listener_id}/start".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), - status_code=500) - self.assertRaises(exc.InternalServerError, self.driver.start_listener, - self.amp, FAKE_UUID_1) - - @requests_mock.mock() - def test_start_listener_service_unavailable(self, m): - m.put("{base}/listeners/{listener_id}/start".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), - status_code=503) - self.assertRaises(exc.ServiceUnavailable, self.driver.start_listener, - self.amp, FAKE_UUID_1) - - @requests_mock.mock() - def test_delete_listener(self, m): - m.delete("{base}/listeners/{listener_id}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), json={}) - self.driver.delete_listener(self.amp, FAKE_UUID_1) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_delete_listener_missing(self, m): - m.delete("{base}/listeners/{listener_id}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), - status_code=404, - headers={'content-type': 'application/json'}) - self.driver.delete_listener(self.amp, FAKE_UUID_1) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_delete_listener_unauthorized(self, m): - m.delete("{base}/listeners/{listener_id}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), - status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.delete_listener, - self.amp, FAKE_UUID_1) - - @requests_mock.mock() - def test_delete_listener_server_error(self, m): - m.delete("{base}/listeners/{listener_id}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), - status_code=500) - self.assertRaises(exc.InternalServerError, self.driver.delete_listener, - self.amp, FAKE_UUID_1) - - @requests_mock.mock() - def test_delete_listener_service_unavailable(self, m): - m.delete("{base}/listeners/{listener_id}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1), - status_code=503) - self.assertRaises(exc.ServiceUnavailable, self.driver.delete_listener, - self.amp, FAKE_UUID_1) - - @requests_mock.mock() - def test_upload_cert_pem(self, m): - m.put("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME)) - self.driver.upload_cert_pem(self.amp, FAKE_UUID_1, - FAKE_PEM_FILENAME, - "some_file") - self.assertTrue(m.called) - - @requests_mock.mock() - def test_upload_invalid_cert_pem(self, m): - m.put("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=400) - self.assertRaises(exc.InvalidRequest, self.driver.upload_cert_pem, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME, - "some_file") - - @requests_mock.mock() - def test_upload_cert_pem_unauthorized(self, m): - m.put("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.upload_cert_pem, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME, - "some_file") - - @requests_mock.mock() - def test_upload_cert_pem_server_error(self, m): - m.put("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=500) - self.assertRaises(exc.InternalServerError, self.driver.upload_cert_pem, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME, - "some_file") - - @requests_mock.mock() - def test_upload_cert_pem_service_unavailable(self, m): - m.put("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=503) - self.assertRaises(exc.ServiceUnavailable, self.driver.upload_cert_pem, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME, - "some_file") - - @requests_mock.mock() - def test_update_cert_for_rotation(self, m): - m.put("{base}/certificate".format(base=self.base_url_ver)) - resp_body = self.driver.update_cert_for_rotation(self.amp, - "some_file") - self.assertEqual(200, resp_body.status_code) - - @requests_mock.mock() - def test_update_invalid_cert_for_rotation(self, m): - m.put("{base}/certificate".format(base=self.base_url_ver), - status_code=400) - self.assertRaises(exc.InvalidRequest, - self.driver.update_cert_for_rotation, self.amp, - "some_file") - - @requests_mock.mock() - def test_update_cert_for_rotation_unauthorized(self, m): - m.put("{base}/certificate".format(base=self.base_url_ver), - status_code=401) - self.assertRaises(exc.Unauthorized, - self.driver.update_cert_for_rotation, self.amp, - "some_file") - - @requests_mock.mock() - def test_update_cert_for_rotation_error(self, m): - m.put("{base}/certificate".format(base=self.base_url_ver), - status_code=500) - self.assertRaises(exc.InternalServerError, - self.driver.update_cert_for_rotation, self.amp, - "some_file") - - @requests_mock.mock() - def test_update_cert_for_rotation_unavailable(self, m): - m.put("{base}/certificate".format(base=self.base_url_ver), - status_code=503) - self.assertRaises(exc.ServiceUnavailable, - self.driver.update_cert_for_rotation, self.amp, - "some_file") - - @requests_mock.mock() - def test_get_cert_5sum(self, m): - md5sum = {"md5sum": "some_real_sum"} - m.get("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), json=md5sum) - sum_test = self.driver.get_cert_md5sum(self.amp, FAKE_UUID_1, - FAKE_PEM_FILENAME) - self.assertIsNotNone(sum_test) - - @requests_mock.mock() - def test_get_cert_5sum_missing(self, m): - m.get("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=404, - headers={'content-type': 'application/json'}) - self.assertRaises(exc.NotFound, self.driver.get_cert_md5sum, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME) - - @requests_mock.mock() - def test_get_cert_5sum_unauthorized(self, m): - m.get("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.get_cert_md5sum, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME) - - @requests_mock.mock() - def test_get_cert_5sum_server_error(self, m): - m.get("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=500) - self.assertRaises(exc.InternalServerError, self.driver.get_cert_md5sum, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME) - - @requests_mock.mock() - def test_get_cert_5sum_service_unavailable(self, m): - m.get("{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=503) - self.assertRaises(exc.ServiceUnavailable, self.driver.get_cert_md5sum, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME) - - @requests_mock.mock() - def test_delete_cert_pem(self, m): - m.delete( - "{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME)) - self.driver.delete_cert_pem(self.amp, FAKE_UUID_1, - FAKE_PEM_FILENAME) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_delete_cert_pem_missing(self, m): - m.delete( - "{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=404, - headers={'content-type': 'application/json'}) - self.driver.delete_cert_pem(self.amp, FAKE_UUID_1, - FAKE_PEM_FILENAME) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_delete_cert_pem_unauthorized(self, m): - m.delete( - "{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.delete_cert_pem, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME) - - @requests_mock.mock() - def test_delete_cert_pem_server_error(self, m): - m.delete( - "{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=500) - self.assertRaises(exc.InternalServerError, self.driver.delete_cert_pem, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME) - - @requests_mock.mock() - def test_delete_cert_pem_service_unavailable(self, m): - m.delete( - "{base}/listeners/{listener_id}/certificates/{filename}".format( - base=self.base_url_ver, listener_id=FAKE_UUID_1, - filename=FAKE_PEM_FILENAME), status_code=503) - self.assertRaises(exc.ServiceUnavailable, self.driver.delete_cert_pem, - self.amp, FAKE_UUID_1, FAKE_PEM_FILENAME) - - @requests_mock.mock() - def test_upload_config(self, m): - config = {"name": "fake_config"} - m.put( - "{base}/listeners/{" - "amphora_id}/{listener_id}/haproxy".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - json=config) - self.driver.upload_config(self.amp, FAKE_UUID_1, - config) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_upload_invalid_config(self, m): - config = '{"name": "bad_config"}' - m.put( - "{base}/listeners/{" - "amphora_id}/{listener_id}/haproxy".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - status_code=400) - self.assertRaises(exc.InvalidRequest, self.driver.upload_config, - self.amp, FAKE_UUID_1, config) - - @requests_mock.mock() - def test_upload_config_unauthorized(self, m): - config = '{"name": "bad_config"}' - m.put( - "{base}/listeners/{" - "amphora_id}/{listener_id}/haproxy".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.upload_config, - self.amp, FAKE_UUID_1, config) - - @requests_mock.mock() - def test_upload_config_server_error(self, m): - config = '{"name": "bad_config"}' - m.put( - "{base}/listeners/{" - "amphora_id}/{listener_id}/haproxy".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - status_code=500) - self.assertRaises(exc.InternalServerError, self.driver.upload_config, - self.amp, FAKE_UUID_1, config) - - @requests_mock.mock() - def test_upload_config_service_unavailable(self, m): - config = '{"name": "bad_config"}' - m.put( - "{base}/listeners/{" - "amphora_id}/{listener_id}/haproxy".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - status_code=503) - self.assertRaises(exc.ServiceUnavailable, self.driver.upload_config, - self.amp, FAKE_UUID_1, config) - - @requests_mock.mock() - def test_upload_udp_config(self, m): - config = {"name": "fake_config"} - m.put( - "{base}/listeners/" - "{amphora_id}/{listener_id}/udp_listener".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - json=config) - self.driver.upload_udp_config(self.amp, FAKE_UUID_1, config) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_upload_udp_invalid_config(self, m): - config = '{"name": "bad_config"}' - m.put( - "{base}/listeners/" - "{amphora_id}/{listener_id}/udp_listener".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - status_code=400) - self.assertRaises(exc.InvalidRequest, self.driver.upload_udp_config, - self.amp, FAKE_UUID_1, config) - - @requests_mock.mock() - def test_upload_udp_config_unauthorized(self, m): - config = '{"name": "bad_config"}' - m.put( - "{base}/listeners/" - "{amphora_id}/{listener_id}/udp_listener".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - status_code=401) - self.assertRaises(exc.Unauthorized, self.driver.upload_udp_config, - self.amp, FAKE_UUID_1, config) - - @requests_mock.mock() - def test_upload_udp_config_server_error(self, m): - config = '{"name": "bad_config"}' - m.put( - "{base}/listeners/" - "{amphora_id}/{listener_id}/udp_listener".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - status_code=500) - self.assertRaises(exc.InternalServerError, - self.driver.upload_udp_config, - self.amp, FAKE_UUID_1, config) - - @requests_mock.mock() - def test_upload_udp_config_service_unavailable(self, m): - config = '{"name": "bad_config"}' - m.put( - "{base}/listeners/" - "{amphora_id}/{listener_id}/udp_listener".format( - amphora_id=self.amp.id, base=self.base_url_ver, - listener_id=FAKE_UUID_1), - status_code=503) - self.assertRaises(exc.ServiceUnavailable, - self.driver.upload_udp_config, - self.amp, FAKE_UUID_1, config) - - @requests_mock.mock() - def test_plug_vip(self, m): - m.post("{base}/plug/vip/{vip}".format( - base=self.base_url_ver, vip=FAKE_IP) - ) - self.driver.plug_vip(self.amp, FAKE_IP, self.subnet_info) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_plug_vip_api_not_ready(self, m): - m.post("{base}/plug/vip/{vip}".format( - base=self.base_url_ver, vip=FAKE_IP), - status_code=404, headers={'content-type': 'text/html'} - ) - self.assertRaises(driver_except.TimeOutException, - self.driver.plug_vip, - self.amp, FAKE_IP, self.subnet_info) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_plug_network(self, m): - m.post("{base}/plug/network".format( - base=self.base_url_ver) - ) - self.driver.plug_network(self.amp, self.port_info) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_upload_vrrp_config(self, m): - config = '{"name": "bad_config"}' - m.put("{base}/vrrp/upload".format( - base=self.base_url_ver) - ) - self.driver.upload_vrrp_config(self.amp, config) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_vrrp_action(self, m): - action = 'start' - m.put("{base}/vrrp/{action}".format(base=self.base_url_ver, - action=action)) - self.driver._vrrp_action(action, self.amp) - self.assertTrue(m.called) - - @requests_mock.mock() - def test_get_interface(self, m): - interface = [{"interface": "eth1"}] - ip_addr = '192.51.100.1' - m.get("{base}/interface/{ip_addr}".format(base=self.base_url_ver, - ip_addr=ip_addr), - json=interface) - self.driver.get_interface(self.amp, ip_addr) - self.assertTrue(m.called) - - m.register_uri('GET', - self.base_url_ver + '/interface/' + ip_addr, - status_code=500, reason='FAIL', json='FAIL') - self.assertRaises(exc.InternalServerError, - self.driver.get_interface, - self.amp, ip_addr) - - @requests_mock.mock() - def test_update_agent_config(self, m): - m.put("{base}/config".format(base=self.base_url_ver)) - resp_body = self.driver.update_agent_config(self.amp, "some_file") - self.assertEqual(200, resp_body.status_code) - - @requests_mock.mock() - def test_update_agent_config_error(self, m): - m.put("{base}/config".format(base=self.base_url_ver), status_code=500) - self.assertRaises(exc.InternalServerError, - self.driver.update_agent_config, self.amp, - "some_file") diff --git a/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py b/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py index bd466c430d..ef286f1331 100644 --- a/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py +++ b/octavia/tests/unit/amphorae/drivers/haproxy/test_rest_api_driver_1_0.py @@ -934,7 +934,7 @@ class TestAmphoraAPIClientTest(base.TestCase): @requests_mock.mock() def test_get_info(self, m): info = {"hostname": "some_hostname", "version": "some_version", - "api_version": "0.5", "uuid": FAKE_UUID_1} + "api_version": "1.0", "uuid": FAKE_UUID_1} m.get("{base}/info".format(base=self.base_url_ver), json=info) information = self.driver.get_info(self.amp) @@ -943,7 +943,7 @@ class TestAmphoraAPIClientTest(base.TestCase): @requests_mock.mock() def test_get_info_with_timeout_dict(self, m): info = {"hostname": "some_hostname", "version": "some_version", - "api_version": "0.5", "uuid": FAKE_UUID_1} + "api_version": "1.0", "uuid": FAKE_UUID_1} m.get("{base}/info".format(base=self.base_url_ver), json=info) timeout_dict = { @@ -983,7 +983,7 @@ class TestAmphoraAPIClientTest(base.TestCase): @requests_mock.mock() def test_get_details(self, m): details = {"hostname": "some_hostname", "version": "some_version", - "api_version": "0.5", "uuid": FAKE_UUID_1, + "api_version": "1.0", "uuid": FAKE_UUID_1, "network_tx": "some_tx", "network_rx": "some_rx", "active": True, "haproxy_count": 10} m.get("{base}/details".format(base=self.base_url_ver), diff --git a/octavia/tests/unit/common/jinja/haproxy/split_listeners/__init__.py b/octavia/tests/unit/common/jinja/haproxy/split_listeners/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/octavia/tests/unit/common/jinja/haproxy/split_listeners/test_jinja_cfg.py b/octavia/tests/unit/common/jinja/haproxy/split_listeners/test_jinja_cfg.py deleted file mode 100644 index 73d3201206..0000000000 --- a/octavia/tests/unit/common/jinja/haproxy/split_listeners/test_jinja_cfg.py +++ /dev/null @@ -1,1157 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import os - -from oslo_config import cfg -from oslo_config import fixture as oslo_fixture - -from octavia.common import constants -from octavia.common.jinja.haproxy.split_listeners import jinja_cfg -from octavia.tests.unit import base -from octavia.tests.unit.common.sample_configs import sample_configs_split - -CONF = cfg.CONF - - -class TestHaproxyCfg(base.TestCase): - def setUp(self): - super().setUp() - self.jinja_cfg = jinja_cfg.JinjaTemplater( - base_amp_path='/var/lib/octavia', - base_crt_dir='/var/lib/octavia/certs') - - def test_get_template(self): - template = self.jinja_cfg._get_template() - self.assertEqual('haproxy.cfg.j2', template.name) - - def test_render_template_tls(self): - conf = oslo_fixture.Config(cfg.CONF) - conf.config(group="haproxy_amphora", base_cert_dir='/fake_cert_dir') - FAKE_CRT_LIST_FILENAME = os.path.join( - CONF.haproxy_amphora.base_cert_dir, - 'sample_listener_id_1/sample_listener_id_1.pem') - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " redirect scheme https if !{{ ssl_fc }}\n" - " bind 10.0.0.2:443 " - "ssl crt-list {crt_list} " - "ca-file /var/lib/octavia/certs/sample_listener_id_1/" - "client_ca.pem verify required crl-file /var/lib/octavia/" - "certs/sample_listener_id_1/SHA_ID.pem\n" - " mode http\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN, - crt_list=FAKE_CRT_LIST_FILENAME) - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 cookie " - "sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='TERMINATED_HTTPS', tls=True, sni=True, - client_ca_cert=True, client_crl_cert=True), - client_ca_filename='client_ca.pem', - client_crl='SHA_ID.pem') - self.assertEqual( - sample_configs_split.sample_base_expected_config( - frontend=fe, backend=be), - rendered_obj) - - def test_render_template_tls_no_sni(self): - conf = oslo_fixture.Config(cfg.CONF) - conf.config(group="haproxy_amphora", base_cert_dir='/fake_cert_dir') - FAKE_CRT_LIST_FILENAME = os.path.join( - CONF.haproxy_amphora.base_cert_dir, - 'sample_listener_id_1/sample_listener_id_1.pem') - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " redirect scheme https if !{{ ssl_fc }}\n" - " bind 10.0.0.2:443 " - "ssl crt-list {crt_list}\n" - " mode http\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN, - crt_list=FAKE_CRT_LIST_FILENAME) - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='TERMINATED_HTTPS', tls=True)) - self.assertEqual( - sample_configs_split.sample_base_expected_config( - frontend=fe, backend=be), - rendered_obj) - - def test_render_template_http(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple()) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_additional_vips(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:80\n" - " bind 10.0.1.2:80\n" - " bind 2001:db8::2:80\n" - " mode http\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple(additional_vips=True)) - self.assertEqual( - sample_configs_split.sample_base_expected_config(frontend=fe), - rendered_obj) - - def test_render_template_member_backup(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "addr 192.168.1.1 port 9000 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "addr 192.168.1.1 port 9000 " - "cookie sample_member_id_2 backup\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - monitor_ip_port=True, backup_member=True)) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_custom_timeouts(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:80\n" - " mode http\n" - " default_backend sample_pool_id_1\n" - " timeout client 2\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 1\n" - " timeout server 3\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie " - "sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - timeout_member_connect=1, timeout_client_data=2, - timeout_member_data=3)) - self.assertEqual( - sample_configs_split.sample_base_expected_config( - frontend=fe, backend=be), - rendered_obj) - - def test_render_template_null_timeouts(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:80\n" - " mode http\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie " - "sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - timeout_member_connect=None, timeout_client_data=None, - timeout_member_data=None)) - self.assertEqual( - sample_configs_split.sample_base_expected_config( - frontend=fe, backend=be), - rendered_obj) - - def test_render_template_member_monitor_addr_port(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "addr 192.168.1.1 port 9000 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "addr 192.168.1.1 port 9000 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple(monitor_ip_port=True)) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_https_real_monitor(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:443\n" - " mode tcp\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - lg = (" log-format 12345\\ sample_loadbalancer_id_1\\ %f\\ " - "%ci\\ %cp\\ %t\\ -\\ -\\ %B\\ %U\\ " - "%[ssl_c_verify]\\ %{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ " - "%tsc\n\n") - be = ("backend sample_pool_id_1\n" - " mode tcp\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check check-ssl verify none inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check check-ssl verify none inter 30s fall 3 rise 2 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple(proto='HTTPS')) - self.assertEqual(sample_configs_split.sample_base_expected_config( - frontend=fe, logging=lg, backend=be), rendered_obj) - - def test_render_template_https_hello_monitor(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:443\n" - " mode tcp\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - lg = (" log-format 12345\\ sample_loadbalancer_id_1\\ %f\\ " - "%ci\\ %cp\\ %t\\ -\\ -\\ %B\\ %U\\ " - "%[ssl_c_verify]\\ %{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ " - "%tsc\n\n") - be = ("backend sample_pool_id_1\n" - " mode tcp\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option ssl-hello-chk\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTPS', monitor_proto='TLS-HELLO')) - self.assertEqual(sample_configs_split.sample_base_expected_config( - frontend=fe, logging=lg, backend=be), rendered_obj) - - def test_render_template_no_monitor_http(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTP', monitor=False)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - backend=be), rendered_obj) - - def test_render_template_disabled_member(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "cookie sample_member_id_2 disabled\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTP', monitor=False, disabled_member=True)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - backend=be), rendered_obj) - - def test_render_template_ping_monitor_http(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option external-check\n" - " external-check command /var/lib/octavia/ping-wrapper.sh\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - go = " maxconn {maxconn}\n external-check\n\n".format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTP', monitor_proto='PING')) - self.assertEqual(sample_configs_split.sample_base_expected_config( - backend=be, global_opts=go), rendered_obj) - - def test_render_template_no_monitor_https(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:443\n" - " mode tcp\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - lg = (" log-format 12345\\ sample_loadbalancer_id_1\\ %f\\ " - "%ci\\ %cp\\ %t\\ -\\ -\\ %B\\ %U\\ " - "%[ssl_c_verify]\\ %{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ " - "%tsc\n\n") - be = ("backend sample_pool_id_1\n" - " mode tcp\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTPS', monitor=False)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - frontend=fe, logging=lg, backend=be), rendered_obj) - - def test_render_template_health_monitor_http_check(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.1\\r\\nHost:\\ " - "testlab.com\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTP', monitor_proto='HTTP', hm_host_http_check=True)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - backend=be), rendered_obj) - - def test_render_template_no_persistence_https(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:443\n" - " mode tcp\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - lg = (" log-format 12345\\ sample_loadbalancer_id_1\\ %f\\ " - "%ci\\ %cp\\ %t\\ -\\ -\\ %B\\ %U\\ " - "%[ssl_c_verify]\\ %{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ " - "%tsc\n\n") - be = ("backend sample_pool_id_1\n" - " mode tcp\n" - " balance roundrobin\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " 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").format(maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTPS', monitor=False, persistence=False)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - frontend=fe, logging=lg, backend=be), rendered_obj) - - def test_render_template_no_persistence_http(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " 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").format(maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTP', monitor=False, persistence=False)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - backend=be), rendered_obj) - - def test_render_template_sourceip_persistence(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " stick-table type ip size 10k\n" - " stick on src\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - persistence_type='SOURCE_IP')) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_appcookie_persistence(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " stick-table type string len 64 size 10k\n" - " stick store-response res.cook(JSESSIONID)\n" - " stick match req.cook(JSESSIONID)\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - persistence_type='APP_COOKIE', - persistence_cookie='JSESSIONID')) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_unlimited_connections(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:443\n" - " mode tcp\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - lg = (" log-format 12345\\ sample_loadbalancer_id_1\\ %f\\ " - "%ci\\ %cp\\ %t\\ -\\ -\\ %B\\ %U\\ " - "%[ssl_c_verify]\\ %{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ " - "%tsc\n\n") - be = ("backend sample_pool_id_1\n" - " mode tcp\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTPS', monitor=False)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - frontend=fe, logging=lg, backend=be), rendered_obj) - - def test_render_template_limited_connections(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn 2014\n" - " bind 10.0.0.2:443\n" - " mode tcp\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n") - lg = (" log-format 12345\\ sample_loadbalancer_id_1\\ %f\\ " - "%ci\\ %cp\\ %t\\ -\\ -\\ %B\\ %U\\ " - "%[ssl_c_verify]\\ %{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ " - "%tsc\n\n") - be = ("backend sample_pool_id_1\n" - " mode tcp\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " fullconn 2014\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "cookie sample_member_id_2\n\n") - g_opts = " maxconn 2014\n\n" - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - proto='HTTPS', monitor=False, connection_limit=2014)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - frontend=fe, logging=lg, backend=be, global_opts=g_opts), - rendered_obj) - - def test_render_template_l7policies(self): - fe = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:80\n" - " mode http\n" - " acl sample_l7rule_id_1 path -m beg /api\n" - " use_backend sample_pool_id_2 if sample_l7rule_id_1\n" - " acl sample_l7rule_id_2 req.hdr(Some-header) -m sub " - "This\\ string\\\\\\ with\\ stuff\n" - " acl sample_l7rule_id_3 req.cook(some-cookie) -m reg " - "this.*|that\n" - " redirect code 302 location http://www.example.com if " - "!sample_l7rule_id_2 sample_l7rule_id_3\n" - " acl sample_l7rule_id_4 path_end -m str jpg\n" - " acl sample_l7rule_id_5 req.hdr(host) -i -m end " - ".example.com\n" - " http-request deny if sample_l7rule_id_4 " - "sample_l7rule_id_5\n" - " acl sample_l7rule_id_2 req.hdr(Some-header) -m sub " - "This\\ string\\\\\\ with\\ stuff\n" - " acl sample_l7rule_id_3 req.cook(some-cookie) -m reg " - "this.*|that\n" - " redirect code 302 prefix https://example.com if " - "!sample_l7rule_id_2 sample_l7rule_id_3\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 check " - "inter 30s fall 3 rise 2 cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 check " - "inter 30s fall 3 rise 2 cookie sample_member_id_2\n" - "\n" - "backend sample_pool_id_2\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /healthmon.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " 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").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple(l7=True)) - self.assertEqual(sample_configs_split.sample_base_expected_config( - frontend=fe, backend=be), rendered_obj) - - def test_render_template_http_xff(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " option forwardfor\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - insert_headers={'X-Forwarded-For': 'true'})) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_http_xff_xfport(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " option forwardfor\n" - " http-request set-header X-Forwarded-Port %[dst_port]\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - insert_headers={'X-Forwarded-For': 'true', - 'X-Forwarded-Port': 'true'})) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_pool_proxy_protocol(self): - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1 send-proxy\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2 send-proxy\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - be_proto='PROXY')) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_pool_cert(self): - cert_file_path = os.path.join(self.jinja_cfg.base_crt_dir, - 'sample_listener_id_1', 'fake path') - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie sample_member_id_1 " - "{opts}\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie sample_member_id_2 " - "{opts}\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN, - opts="ssl crt %s verify none sni ssl_fc_sni" % cert_file_path) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - pool_cert=True, tls_enabled=True), - pool_tls_certs={ - 'sample_pool_id_1': - {'client_cert': cert_file_path, - 'ca_cert': None, 'crl': None}}) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_render_template_with_full_pool_cert(self): - pool_client_cert = '/foo/cert.pem' - pool_ca_cert = '/foo/ca.pem' - pool_crl = '/foo/crl.pem' - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie sample_member_id_1 " - "{opts}\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie sample_member_id_2 " - "{opts}\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN, - opts="%s %s %s %s %s %s" % ( - "ssl", "crt", pool_client_cert, - "ca-file %s" % pool_ca_cert, - "crl-file %s" % pool_crl, - "verify required sni ssl_fc_sni")) - rendered_obj = self.jinja_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple( - pool_cert=True, pool_ca_cert=True, pool_crl=True, - tls_enabled=True), - pool_tls_certs={ - 'sample_pool_id_1': - {'client_cert': pool_client_cert, - 'ca_cert': pool_ca_cert, - 'crl': pool_crl}}) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_transform_session_persistence(self): - in_persistence = ( - sample_configs_split.sample_session_persistence_tuple()) - ret = self.jinja_cfg._transform_session_persistence( - in_persistence, {}) - self.assertEqual(sample_configs_split.RET_PERSISTENCE, ret) - - def test_transform_health_monitor(self): - in_persistence = sample_configs_split.sample_health_monitor_tuple() - ret = self.jinja_cfg._transform_health_monitor(in_persistence, {}) - self.assertEqual(sample_configs_split.RET_MONITOR_1, ret) - - def test_transform_member(self): - in_member = sample_configs_split.sample_member_tuple( - 'sample_member_id_1', '10.0.0.99') - ret = self.jinja_cfg._transform_member(in_member, {}) - self.assertEqual(sample_configs_split.RET_MEMBER_1, ret) - - def test_transform_pool(self): - in_pool = sample_configs_split.sample_pool_tuple() - ret = self.jinja_cfg._transform_pool(in_pool, {}) - self.assertEqual(sample_configs_split.RET_POOL_1, ret) - - def test_transform_pool_2(self): - in_pool = sample_configs_split.sample_pool_tuple(sample_pool=2) - ret = self.jinja_cfg._transform_pool(in_pool, {}) - self.assertEqual(sample_configs_split.RET_POOL_2, ret) - - def test_transform_pool_http_reuse(self): - in_pool = sample_configs_split.sample_pool_tuple(sample_pool=2) - ret = self.jinja_cfg._transform_pool( - in_pool, {constants.HTTP_REUSE: True}) - expected_config = copy.copy(sample_configs_split.RET_POOL_2) - expected_config[constants.HTTP_REUSE] = True - self.assertEqual(expected_config, ret) - - def test_transform_pool_cert(self): - in_pool = sample_configs_split.sample_pool_tuple(pool_cert=True) - cert_path = os.path.join(self.jinja_cfg.base_crt_dir, - 'test_listener_id', 'pool_cert.pem') - ret = self.jinja_cfg._transform_pool( - in_pool, {}, pool_tls_certs={'client_cert': cert_path}) - expected_config = copy.copy(sample_configs_split.RET_POOL_1) - expected_config['client_cert'] = cert_path - self.assertEqual(expected_config, ret) - - def test_transform_listener(self): - in_listener = sample_configs_split.sample_listener_tuple() - ret = self.jinja_cfg._transform_listener(in_listener, {}, - in_listener.load_balancer) - self.assertEqual(sample_configs_split.RET_LISTENER, ret) - - def test_transform_listener_with_l7(self): - in_listener = sample_configs_split.sample_listener_tuple(l7=True) - ret = self.jinja_cfg._transform_listener(in_listener, {}, - in_listener.load_balancer) - self.assertEqual(sample_configs_split.RET_LISTENER_L7, ret) - - def test_transform_loadbalancer(self): - in_amphora = sample_configs_split.sample_amphora_tuple() - in_listener = sample_configs_split.sample_listener_tuple() - ret = self.jinja_cfg._transform_loadbalancer( - in_amphora, in_listener.load_balancer, in_listener, {}) - self.assertEqual(sample_configs_split.RET_LB, ret) - - def test_transform_amphora(self): - in_amphora = sample_configs_split.sample_amphora_tuple() - ret = self.jinja_cfg._transform_amphora(in_amphora, {}) - self.assertEqual(sample_configs_split.RET_AMPHORA, ret) - - def test_transform_loadbalancer_with_l7(self): - in_amphora = sample_configs_split.sample_amphora_tuple() - in_listener = sample_configs_split.sample_listener_tuple(l7=True) - ret = self.jinja_cfg._transform_loadbalancer( - in_amphora, in_listener.load_balancer, in_listener, {}) - self.assertEqual(sample_configs_split.RET_LB_L7, ret) - - def test_transform_l7policy(self): - in_l7policy = sample_configs_split.sample_l7policy_tuple( - 'sample_l7policy_id_1') - ret = self.jinja_cfg._transform_l7policy(in_l7policy, {}) - self.assertEqual(sample_configs_split.RET_L7POLICY_1, ret) - - def test_transform_l7policy_2_8(self): - in_l7policy = sample_configs_split.sample_l7policy_tuple( - 'sample_l7policy_id_2', sample_policy=2) - ret = self.jinja_cfg._transform_l7policy(in_l7policy, {}) - self.assertEqual(sample_configs_split.RET_L7POLICY_2, ret) - - # test invalid action without redirect_http_code - in_l7policy = sample_configs_split.sample_l7policy_tuple( - 'sample_l7policy_id_8', sample_policy=2, redirect_http_code=None) - ret = self.jinja_cfg._transform_l7policy(in_l7policy, {}) - self.assertEqual(sample_configs_split.RET_L7POLICY_8, ret) - - def test_transform_l7policy_disabled_rule(self): - in_l7policy = sample_configs_split.sample_l7policy_tuple( - 'sample_l7policy_id_6', sample_policy=6) - ret = self.jinja_cfg._transform_l7policy(in_l7policy, {}) - self.assertEqual(sample_configs_split.RET_L7POLICY_6, ret) - - def test_escape_haproxy_config_string(self): - self.assertEqual(self.jinja_cfg._escape_haproxy_config_string( - 'string_with_none'), 'string_with_none') - self.assertEqual(self.jinja_cfg._escape_haproxy_config_string( - 'string with spaces'), 'string\\ with\\ spaces') - self.assertEqual(self.jinja_cfg._escape_haproxy_config_string( - 'string\\with\\backslashes'), 'string\\\\with\\\\backslashes') - self.assertEqual(self.jinja_cfg._escape_haproxy_config_string( - 'string\\ with\\ all'), 'string\\\\\\ with\\\\\\ all') - - def test_render_template_no_log(self): - j_cfg = jinja_cfg.JinjaTemplater( - base_amp_path='/var/lib/octavia', - base_crt_dir='/var/lib/octavia/certs', - connection_logging=False) - defaults = ("defaults\n" - " no log\n" - " retries 3\n" - " option redispatch\n" - " option splice-request\n" - " option splice-response\n" - " option http-keep-alive\n\n") - rendered_obj = j_cfg.render_loadbalancer_obj( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple() - ) - self.assertEqual( - sample_configs_split.sample_base_expected_config( - defaults=defaults, logging="\n"), - rendered_obj) - - def test_http_reuse(self): - j_cfg = jinja_cfg.JinjaTemplater( - base_amp_path='/var/lib/octavia', - base_crt_dir='/var/lib/octavia/certs') - - # With http-reuse - be = ("backend sample_pool_id_1\n" - " mode http\n" - " http-reuse safe\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1 send-proxy\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2 send-proxy\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = j_cfg.build_config( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple(be_proto='PROXY'), - haproxy_versions=("1", "8", "1")) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - # Without http-reuse - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_1 send-proxy\n" - " server sample_member_id_2 10.0.0.98:82 " - "weight 13 check inter 30s fall 3 rise 2 " - "cookie sample_member_id_2 send-proxy\n\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - rendered_obj = j_cfg.build_config( - sample_configs_split.sample_amphora_tuple(), - sample_configs_split.sample_listener_tuple(be_proto='PROXY'), - haproxy_versions=("1", "5", "18")) - self.assertEqual( - sample_configs_split.sample_base_expected_config(backend=be), - rendered_obj) - - def test_ssl_types_l7rules(self): - j_cfg = jinja_cfg.JinjaTemplater( - base_amp_path='/var/lib/octavia', - base_crt_dir='/var/lib/octavia/certs') - fe = ("frontend sample_listener_id_1\n" - " maxconn 1000000\n" - " redirect scheme https if !{ ssl_fc }\n" - " bind 10.0.0.2:443\n" - " mode http\n" - " acl sample_l7rule_id_1 path -m beg /api\n" - " use_backend sample_pool_id_2 if sample_l7rule_id_1\n" - " acl sample_l7rule_id_2 req.hdr(Some-header) -m sub " - "This\\ string\\\\\\ with\\ stuff\n" - " acl sample_l7rule_id_3 req.cook(some-cookie) -m reg " - "this.*|that\n" - " redirect code 302 location http://www.example.com " - "if !sample_l7rule_id_2 sample_l7rule_id_3\n" - " acl sample_l7rule_id_4 path_end -m str jpg\n" - " acl sample_l7rule_id_5 req.hdr(host) -i -m end " - ".example.com\n" - " http-request deny " - "if sample_l7rule_id_4 sample_l7rule_id_5\n" - " acl sample_l7rule_id_2 req.hdr(Some-header) -m sub " - "This\\ string\\\\\\ with\\ stuff\n" - " acl sample_l7rule_id_3 req.cook(some-cookie) -m reg " - "this.*|that\n" - " redirect code 302 prefix https://example.com " - "if !sample_l7rule_id_2 sample_l7rule_id_3\n" - " acl sample_l7rule_id_7 ssl_c_used\n" - " acl sample_l7rule_id_8 ssl_c_verify eq 1\n" - " acl sample_l7rule_id_9 ssl_c_s_dn(STREET) -m reg " - "^STREET.*NO\\\\.$\n" - " acl sample_l7rule_id_10 ssl_c_s_dn(OU-3) -m beg " - "Orgnization\\ Bala\n" - " acl sample_l7rule_id_11 path -m beg /api\n" - " redirect code 302 location " - "http://www.ssl-type-l7rule-test.com " - "if sample_l7rule_id_7 !sample_l7rule_id_8 !sample_l7rule_id_9 " - "!sample_l7rule_id_10 sample_l7rule_id_11\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n") - be = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn 1000000\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 check " - "inter 30s fall 3 rise 2 cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 check " - "inter 30s fall 3 rise 2 cookie sample_member_id_2\n\n" - "backend sample_pool_id_2\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /healthmon.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn 1000000\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " 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") - sample_listener = sample_configs_split.sample_listener_tuple( - proto=constants.PROTOCOL_TERMINATED_HTTPS, l7=True, - ssl_type_l7=True) - rendered_obj = j_cfg.build_config( - sample_configs_split.sample_amphora_tuple(), - sample_listener, - haproxy_versions=("1", "5", "18")) - self.assertEqual( - sample_configs_split.sample_base_expected_config( - frontend=fe, backend=be), - rendered_obj) diff --git a/octavia/tests/unit/common/sample_configs/sample_configs_split.py b/octavia/tests/unit/common/sample_configs/sample_configs_split.py deleted file mode 100644 index 5ccfa805f6..0000000000 --- a/octavia/tests/unit/common/sample_configs/sample_configs_split.py +++ /dev/null @@ -1,1139 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import collections - -from oslo_config import cfg - -from octavia.common import constants -from octavia.tests.common import sample_certs - -CONF = cfg.CONF - - -class AmphoraTuple(collections.namedtuple( - 'amphora', 'id, lb_network_ip, vrrp_ip, ha_ip, vrrp_port_id, ' - 'ha_port_id, role, status, vrrp_interface,' - 'vrrp_priority, api_version')): - def to_dict(self): - return self._asdict() - - -def sample_amphora_tuple(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, api_version='0.5'): - return AmphoraTuple( - id=id, - lb_network_ip=lb_network_ip, - vrrp_ip=vrrp_ip, - ha_ip=ha_ip, - vrrp_port_id=vrrp_port_id, - ha_port_id=ha_port_id, - role=role, - status=status, - vrrp_interface=vrrp_interface, - vrrp_priority=vrrp_priority, - api_version=api_version) - - -RET_PERSISTENCE = { - 'type': 'HTTP_COOKIE', - 'cookie_name': None} - -RET_MONITOR_1 = { - 'id': 'sample_monitor_id_1', - 'type': 'HTTP', - 'delay': 30, - 'timeout': 31, - 'fall_threshold': 3, - 'rise_threshold': 2, - 'http_method': 'GET', - 'url_path': '/index.html', - 'expected_codes': '418', - 'enabled': True, - 'http_version': 1.0, - 'domain_name': None} - -RET_MONITOR_2 = { - 'id': 'sample_monitor_id_2', - 'type': 'HTTP', - 'delay': 30, - 'timeout': 31, - 'fall_threshold': 3, - 'rise_threshold': 2, - 'http_method': 'GET', - 'url_path': '/healthmon.html', - 'expected_codes': '418', - 'enabled': True, - 'http_version': 1.0, - 'domain_name': None} - -RET_MEMBER_1 = { - 'id': 'sample_member_id_1', - 'address': '10.0.0.99', - 'protocol_port': 82, - 'weight': 13, - 'subnet_id': '10.0.0.1/24', - 'enabled': True, - 'operating_status': 'ACTIVE', - 'monitor_address': None, - 'monitor_port': None, - 'backup': False} - -RET_MEMBER_2 = { - 'id': 'sample_member_id_2', - 'address': '10.0.0.98', - 'protocol_port': 82, - 'weight': 13, - 'subnet_id': '10.0.0.1/24', - 'enabled': True, - 'operating_status': 'ACTIVE', - 'monitor_address': None, - 'monitor_port': None, - 'backup': False} - -RET_MEMBER_3 = { - 'id': 'sample_member_id_3', - 'address': '10.0.0.97', - 'protocol_port': 82, - 'weight': 13, - 'subnet_id': '10.0.0.1/24', - 'enabled': True, - 'operating_status': 'ACTIVE', - 'monitor_address': None, - 'monitor_port': None, - 'backup': False} - -RET_POOL_1 = { - 'id': 'sample_pool_id_1', - 'protocol': 'http', - 'lb_algorithm': 'roundrobin', - 'members': [RET_MEMBER_1, RET_MEMBER_2], - 'health_monitor': RET_MONITOR_1, - 'session_persistence': RET_PERSISTENCE, - 'enabled': True, - 'operating_status': 'ACTIVE', - 'stick_size': '10k', - constants.HTTP_REUSE: False, - 'ca_tls_path': '', - 'crl_path': '', - 'tls_enabled': False} - -RET_POOL_2 = { - 'id': 'sample_pool_id_2', - 'protocol': 'http', - 'lb_algorithm': 'roundrobin', - 'members': [RET_MEMBER_3], - 'health_monitor': RET_MONITOR_2, - 'session_persistence': RET_PERSISTENCE, - 'enabled': True, - 'operating_status': 'ACTIVE', - 'stick_size': '10k', - constants.HTTP_REUSE: False, - 'ca_tls_path': '', - 'crl_path': '', - 'tls_enabled': False} - - -RET_DEF_TLS_CONT = {'id': 'cont_id_1', 'allencompassingpem': 'imapem', - 'primary_cn': 'FakeCn'} -RET_SNI_CONT_1 = {'id': 'cont_id_2', 'allencompassingpem': 'imapem2', - 'primary_cn': 'FakeCn'} -RET_SNI_CONT_2 = {'id': 'cont_id_3', 'allencompassingpem': 'imapem3', - 'primary_cn': 'FakeCn2'} - -RET_L7RULE_1 = { - 'id': 'sample_l7rule_id_1', - 'type': constants.L7RULE_TYPE_PATH, - 'compare_type': constants.L7RULE_COMPARE_TYPE_STARTS_WITH, - 'key': None, - 'value': '/api', - 'invert': False, - 'enabled': True} - -RET_L7RULE_2 = { - 'id': 'sample_l7rule_id_2', - 'type': constants.L7RULE_TYPE_HEADER, - 'compare_type': constants.L7RULE_COMPARE_TYPE_CONTAINS, - 'key': 'Some-header', - 'value': 'This\\ string\\\\\\ with\\ stuff', - 'invert': True, - 'enabled': True} - -RET_L7RULE_3 = { - 'id': 'sample_l7rule_id_3', - 'type': constants.L7RULE_TYPE_COOKIE, - 'compare_type': constants.L7RULE_COMPARE_TYPE_REGEX, - 'key': 'some-cookie', - 'value': 'this.*|that', - 'invert': False, - 'enabled': True} - -RET_L7RULE_4 = { - 'id': 'sample_l7rule_id_4', - 'type': constants.L7RULE_TYPE_FILE_TYPE, - 'compare_type': constants.L7RULE_COMPARE_TYPE_EQUAL_TO, - 'key': None, - 'value': 'jpg', - 'invert': False, - 'enabled': True} - -RET_L7RULE_5 = { - 'id': 'sample_l7rule_id_5', - 'type': constants.L7RULE_TYPE_HOST_NAME, - 'compare_type': constants.L7RULE_COMPARE_TYPE_ENDS_WITH, - 'key': None, - 'value': '.example.com', - 'invert': False, - 'enabled': True} - -RET_L7RULE_6 = { - 'id': 'sample_l7rule_id_6', - 'type': constants.L7RULE_TYPE_HOST_NAME, - 'compare_type': constants.L7RULE_COMPARE_TYPE_ENDS_WITH, - 'key': None, - 'value': '.example.com', - 'invert': False, - 'enabled': False} - -RET_L7POLICY_1 = { - 'id': 'sample_l7policy_id_1', - 'action': constants.L7POLICY_ACTION_REDIRECT_TO_POOL, - 'redirect_pool': RET_POOL_2, - 'redirect_url': None, - 'redirect_prefix': None, - 'enabled': True, - 'l7rules': [RET_L7RULE_1], - 'redirect_http_code': None} - -RET_L7POLICY_2 = { - 'id': 'sample_l7policy_id_2', - 'action': constants.L7POLICY_ACTION_REDIRECT_TO_URL, - 'redirect_pool': None, - 'redirect_url': 'http://www.example.com', - 'redirect_prefix': None, - 'enabled': True, - 'l7rules': [RET_L7RULE_2, RET_L7RULE_3], - 'redirect_http_code': 302} - -RET_L7POLICY_3 = { - 'id': 'sample_l7policy_id_3', - 'action': constants.L7POLICY_ACTION_REJECT, - 'redirect_pool': None, - 'redirect_url': None, - 'redirect_prefix': None, - 'enabled': True, - 'l7rules': [RET_L7RULE_4, RET_L7RULE_5], - 'redirect_http_code': None} - -RET_L7POLICY_4 = { - 'id': 'sample_l7policy_id_4', - 'action': constants.L7POLICY_ACTION_REJECT, - 'redirect_pool': None, - 'redirect_url': None, - 'redirect_prefix': None, - 'enabled': True, - 'l7rules': [], - 'redirect_http_code': None} - -RET_L7POLICY_5 = { - 'id': 'sample_l7policy_id_5', - 'action': constants.L7POLICY_ACTION_REJECT, - 'redirect_pool': None, - 'redirect_url': None, - 'redirect_prefix': None, - 'enabled': False, - 'l7rules': [RET_L7RULE_5], - 'redirect_http_code': None} - -RET_L7POLICY_6 = { - 'id': 'sample_l7policy_id_6', - 'action': constants.L7POLICY_ACTION_REJECT, - 'redirect_pool': None, - 'redirect_url': None, - 'redirect_prefix': None, - 'enabled': True, - 'l7rules': [], - 'redirect_http_code': None} - -RET_L7POLICY_7 = { - 'id': 'sample_l7policy_id_7', - 'action': constants.L7POLICY_ACTION_REDIRECT_PREFIX, - 'redirect_pool': None, - 'redirect_url': None, - 'redirect_prefix': 'https://example.com', - 'enabled': True, - 'l7rules': [RET_L7RULE_2, RET_L7RULE_3], - 'redirect_http_code': 302} - -RET_L7POLICY_8 = { - 'id': 'sample_l7policy_id_8', - 'action': constants.L7POLICY_ACTION_REDIRECT_TO_URL, - 'redirect_pool': None, - 'redirect_url': 'http://www.example.com', - 'redirect_prefix': None, - 'enabled': True, - 'l7rules': [RET_L7RULE_2, RET_L7RULE_3], - 'redirect_http_code': None} - -RET_LISTENER = { - 'id': 'sample_listener_id_1', - 'protocol_port': '80', - 'protocol': 'HTTP', - 'protocol_mode': 'http', - 'default_pool': RET_POOL_1, - 'connection_limit': constants.HAPROXY_MAX_MAXCONN, - 'amphorae': [sample_amphora_tuple()], - 'peer_port': 1024, - 'topology': 'SINGLE', - 'user_log_format': '12345\\ sample_loadbalancer_id_1\\ %f\\ %ci\\ %cp\\ ' - '%t\\ %{+Q}r\\ %ST\\ %B\\ %U\\ %[ssl_c_verify]\\ ' - '%{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ %tsc', - 'pools': [RET_POOL_1], - 'l7policies': [], - 'enabled': True, - 'insert_headers': {}, - 'timeout_client_data': 50000, - 'timeout_member_connect': 5000, - 'timeout_member_data': 50000, - 'timeout_tcp_inspect': 0, -} - -RET_LISTENER_L7 = { - 'id': 'sample_listener_id_1', - 'protocol_port': '80', - 'protocol': 'HTTP', - 'protocol_mode': 'http', - 'default_pool': RET_POOL_1, - 'connection_limit': constants.HAPROXY_MAX_MAXCONN, - 'amphorae': [sample_amphora_tuple()], - 'peer_port': 1024, - 'topology': 'SINGLE', - 'user_log_format': '12345\\ sample_loadbalancer_id_1\\ %f\\ %ci\\ %cp\\ ' - '%t\\ %{+Q}r\\ %ST\\ %B\\ %U\\ %[ssl_c_verify]\\ ' - '%{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ %tsc', - 'pools': [RET_POOL_1, RET_POOL_2], - 'l7policies': [RET_L7POLICY_1, RET_L7POLICY_2, RET_L7POLICY_3, - RET_L7POLICY_4, RET_L7POLICY_5, RET_L7POLICY_6, - RET_L7POLICY_7], - 'enabled': True, - 'insert_headers': {}, - 'timeout_client_data': 50000, - 'timeout_member_connect': 5000, - 'timeout_member_data': 50000, - 'timeout_tcp_inspect': 0, -} - -RET_LISTENER_TLS = { - 'id': 'sample_listener_id_1', - 'protocol_port': '443', - 'protocol': 'TERMINATED_HTTPS', - 'protocol_mode': 'http', - 'default_pool': RET_POOL_1, - 'connection_limit': constants.HAPROXY_MAX_MAXCONN, - 'tls_certificate_id': 'cont_id_1', - 'default_tls_path': '/etc/ssl/sample_loadbalancer_id_1/fakeCN.pem', - 'default_tls_container': RET_DEF_TLS_CONT, - 'pools': [RET_POOL_1], - 'l7policies': [], - 'enabled': True, - 'insert_headers': {}} - -RET_LISTENER_TLS_SNI = { - 'id': 'sample_listener_id_1', - 'protocol_port': '443', - 'protocol': 'TERMINATED_HTTPS', - 'default_pool': RET_POOL_1, - 'connection_limit': constants.HAPROXY_MAX_MAXCONN, - 'tls_certificate_id': 'cont_id_1', - 'default_tls_path': '/etc/ssl/sample_loadbalancer_id_1/fakeCN.pem', - 'default_tls_container': RET_DEF_TLS_CONT, - 'crt_dir': '/v2/sample_loadbalancer_id_1', - 'sni_container_ids': ['cont_id_2', 'cont_id_3'], - 'sni_containers': [RET_SNI_CONT_1, RET_SNI_CONT_2], - 'pools': [RET_POOL_1], - 'l7policies': [], - '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 = { - 'additional_vips': [], - 'host_amphora': RET_AMPHORA, - 'id': 'sample_loadbalancer_id_1', - 'vip_address': '10.0.0.2', - 'listener': RET_LISTENER, - 'topology': 'SINGLE', - 'enabled': True, - 'global_connection_limit': constants.HAPROXY_MAX_MAXCONN} - -RET_LB_L7 = { - 'additional_vips': [], - 'host_amphora': RET_AMPHORA, - 'id': 'sample_loadbalancer_id_1', - 'vip_address': '10.0.0.2', - 'listener': RET_LISTENER_L7, - 'topology': 'SINGLE', - 'enabled': True, - 'global_connection_limit': constants.HAPROXY_MAX_MAXCONN} - -UDP_SOURCE_IP_BODY = { - 'type': constants.SESSION_PERSISTENCE_SOURCE_IP, - 'persistence_timeout': 33, - 'persistence_granularity': '255.0.0.0' -} - -RET_UDP_HEALTH_MONITOR = { - 'id': 'sample_monitor_id_1', - 'type': constants.HEALTH_MONITOR_UDP_CONNECT, - 'delay': 30, - 'timeout': 31, - 'enabled': True, - 'fall_threshold': 3, - 'check_script_path': (CONF.haproxy_amphora.base_path + - '/lvs/check/udp_check.sh') -} - -UDP_HEALTH_MONITOR_NO_SCRIPT = { - 'id': 'sample_monitor_id_1', - 'check_script_path': None, - 'delay': 30, - 'enabled': True, - 'fall_threshold': 3, - 'timeout': 31, - 'type': 'UDP' -} - -RET_UDP_MEMBER = { - 'id': 'member_id_1', - 'address': '192.0.2.10', - 'protocol_port': 82, - 'weight': 13, - 'enabled': True, - 'monitor_address': None, - 'monitor_port': None -} - -RET_UDP_MEMBER_MONITOR_IP_PORT = { - 'id': 'member_id_1', - 'address': '192.0.2.10', - 'protocol_port': 82, - 'weight': 13, - 'enabled': True, - 'monitor_address': '192.168.1.1', - 'monitor_port': 9000 -} - -UDP_MEMBER_1 = { - 'id': 'sample_member_id_1', - 'address': '10.0.0.99', - 'enabled': True, - 'protocol_port': 82, - 'weight': 13, - 'monitor_address': None, - 'monitor_port': None -} - -UDP_MEMBER_2 = { - 'id': 'sample_member_id_2', - 'address': '10.0.0.98', - 'enabled': True, - 'protocol_port': 82, - 'weight': 13, - 'monitor_address': None, - 'monitor_port': None -} - -RET_UDP_POOL = { - 'id': 'sample_pool_id_1', - 'enabled': True, - 'health_monitor': UDP_HEALTH_MONITOR_NO_SCRIPT, - 'lb_algorithm': 'rr', - 'members': [UDP_MEMBER_1, UDP_MEMBER_2], - 'protocol': 'udp', - 'session_persistence': UDP_SOURCE_IP_BODY -} - -RET_UDP_LISTENER = { - 'connection_limit': 98, - 'default_pool': { - 'id': 'sample_pool_id_1', - 'enabled': True, - 'health_monitor': RET_UDP_HEALTH_MONITOR, - 'lb_algorithm': 'rr', - 'members': [UDP_MEMBER_1, UDP_MEMBER_2], - 'protocol': 'udp', - 'session_persistence': UDP_SOURCE_IP_BODY - }, - 'enabled': True, - 'id': 'sample_listener_id_1', - 'protocol_mode': 'udp', - 'protocol_port': '80' -} - - -def sample_loadbalancer_tuple(proto=None, monitor=True, persistence=True, - persistence_type=None, tls=False, sni=False, - topology=None, l7=False, enabled=True): - proto = 'HTTP' if proto is None else proto - topology = 'SINGLE' if topology is None else topology - in_lb = collections.namedtuple( - 'load_balancer', 'id, name, protocol, vip, listeners, amphorae,' - ' enabled') - return in_lb( - id='sample_loadbalancer_id_1', - name='test-lb', - protocol=proto, - vip=sample_vip_tuple(), - topology=topology, - listeners=[sample_listener_tuple(proto=proto, monitor=monitor, - persistence=persistence, - persistence_type=persistence_type, - tls=tls, - sni=sni, - l7=l7, - enabled=enabled)], - enabled=enabled - ) - - -def sample_listener_loadbalancer_tuple(proto=None, topology=None, - enabled=True, additional_vips=False): - proto = 'HTTP' if proto is None else proto - if topology and topology in ['ACTIVE_STANDBY', 'ACTIVE_ACTIVE']: - more_amp = True - else: - more_amp = False - topology = constants.TOPOLOGY_SINGLE - in_lb = collections.namedtuple( - 'load_balancer', 'id, name, protocol, vip, amphorae, topology, ' - 'listeners, enabled, project_id, additional_vips') - return in_lb( - id='sample_loadbalancer_id_1', - name='test-lb', - protocol=proto, - vip=sample_vip_tuple(), - amphorae=[sample_amphora_tuple(role=constants.ROLE_MASTER), - sample_amphora_tuple( - id='sample_amphora_id_2', - lb_network_ip='10.0.1.2', - vrrp_ip='10.1.1.2', - role=constants.ROLE_BACKUP)] - if more_amp else [sample_amphora_tuple()], - topology=topology, - listeners=[], - enabled=enabled, - project_id='12345', - additional_vips=[sample_vip_tuple('10.0.1.2'), - sample_vip_tuple('2001:db8::2')] - if additional_vips else [] - ) - - -def sample_lb_with_udp_listener_tuple( - proto=None, topology=None, enabled=True, pools=None): - proto = 'HTTP' if proto is None else proto - if topology and topology in ['ACTIVE_STANDBY', 'ACTIVE_ACTIVE']: - more_amp = True - else: - more_amp = False - topology = constants.TOPOLOGY_SINGLE - listeners = [sample_listener_tuple( - proto=constants.PROTOCOL_UDP, - persistence_type=constants.SESSION_PERSISTENCE_SOURCE_IP, - persistence_timeout=33, - persistence_granularity='255.255.0.0', - monitor_proto=constants.HEALTH_MONITOR_UDP_CONNECT)] - - in_lb = collections.namedtuple( - 'load_balancer', 'id, name, protocol, vip, amphorae, topology, ' - 'pools, enabled, project_id, listeners') - return in_lb( - id='sample_loadbalancer_id_1', - name='test-lb', - protocol=proto, - vip=sample_vip_tuple(), - amphorae=[sample_amphora_tuple(role=constants.ROLE_MASTER), - sample_amphora_tuple( - id='sample_amphora_id_2', - lb_network_ip='10.0.1.2', - vrrp_ip='10.1.1.2', - role=constants.ROLE_BACKUP)] - if more_amp else [sample_amphora_tuple()], - topology=topology, - listeners=listeners, - pools=pools or [], - enabled=enabled, - project_id='12345' - ) - - -def sample_vrrp_group_tuple(): - in_vrrp_group = collections.namedtuple( - 'vrrp_group', 'load_balancer_id, vrrp_auth_type, vrrp_auth_pass, ' - 'advert_int, smtp_server, smtp_connect_timeout, ' - 'vrrp_group_name') - return in_vrrp_group( - vrrp_group_name='sample_loadbalancer_id_1', - load_balancer_id='sample_loadbalancer_id_1', - vrrp_auth_type='PASS', - vrrp_auth_pass='123', - advert_int='1', - smtp_server='', - smtp_connect_timeout='') - - -def sample_vip_tuple(ip_address='10.0.0.2', subnet_id='vip_subnet_uuid'): - vip = collections.namedtuple('vip', ('ip_address', 'subnet_id')) - return vip(ip_address=ip_address, subnet_id=subnet_id) - - -def sample_listener_tuple(proto=None, monitor=True, alloc_default_pool=True, - persistence=True, persistence_type=None, - persistence_cookie=None, persistence_timeout=None, - persistence_granularity=None, - tls=False, sni=False, peer_port=None, topology=None, - l7=False, enabled=True, insert_headers=None, - be_proto=None, monitor_ip_port=False, - monitor_proto=None, monitor_expected_codes=None, - backup_member=False, disabled_member=False, - connection_limit=-1, - timeout_client_data=50000, - timeout_member_connect=5000, - timeout_member_data=50000, - timeout_tcp_inspect=0, - client_ca_cert=False, client_crl_cert=False, - ssl_type_l7=False, pool_cert=False, - pool_ca_cert=False, pool_crl=False, - tls_enabled=False, hm_host_http_check=False, - id='sample_listener_id_1', recursive_nest=False, - provisioning_status=constants.ACTIVE, - additional_vips=False): - proto = 'HTTP' if proto is None else proto - if be_proto is None: - be_proto = 'HTTP' if proto == 'TERMINATED_HTTPS' else proto - topology = 'SINGLE' if topology is None else topology - port = '443' if proto in ['HTTPS', 'TERMINATED_HTTPS'] else '80' - peer_port = 1024 if peer_port is None else peer_port - insert_headers = insert_headers or {} - in_listener = collections.namedtuple( - 'listener', 'id, project_id, protocol_port, protocol, default_pool, ' - 'connection_limit, tls_certificate_id, ' - 'sni_container_ids, default_tls_container, ' - 'sni_containers, load_balancer, peer_port, pools, ' - 'l7policies, enabled, insert_headers, timeout_client_data,' - 'timeout_member_connect, timeout_member_data, ' - 'timeout_tcp_inspect, client_ca_tls_certificate_id, ' - 'client_ca_tls_certificate, client_authentication, ' - 'client_crl_container_id, provisioning_status') - if l7: - pools = [ - sample_pool_tuple( - proto=be_proto, monitor=monitor, persistence=persistence, - persistence_type=persistence_type, - persistence_cookie=persistence_cookie, - monitor_ip_port=monitor_ip_port, monitor_proto=monitor_proto, - pool_cert=pool_cert, pool_ca_cert=pool_ca_cert, - pool_crl=pool_crl, tls_enabled=tls_enabled, - hm_host_http_check=hm_host_http_check), - sample_pool_tuple( - proto=be_proto, monitor=monitor, persistence=persistence, - persistence_type=persistence_type, - persistence_cookie=persistence_cookie, sample_pool=2, - monitor_ip_port=monitor_ip_port, monitor_proto=monitor_proto, - pool_cert=pool_cert, pool_ca_cert=pool_ca_cert, - pool_crl=pool_crl, tls_enabled=tls_enabled, - hm_host_http_check=hm_host_http_check)] - l7policies = [ - sample_l7policy_tuple('sample_l7policy_id_1', sample_policy=1), - sample_l7policy_tuple('sample_l7policy_id_2', sample_policy=2), - sample_l7policy_tuple('sample_l7policy_id_3', sample_policy=3), - sample_l7policy_tuple('sample_l7policy_id_4', sample_policy=4), - sample_l7policy_tuple('sample_l7policy_id_5', sample_policy=5), - sample_l7policy_tuple('sample_l7policy_id_6', sample_policy=6), - sample_l7policy_tuple('sample_l7policy_id_7', sample_policy=7)] - if ssl_type_l7: - l7policies.append(sample_l7policy_tuple( - 'sample_l7policy_id_8', sample_policy=8)) - else: - pools = [ - sample_pool_tuple( - proto=be_proto, monitor=monitor, persistence=persistence, - persistence_type=persistence_type, - persistence_cookie=persistence_cookie, - monitor_ip_port=monitor_ip_port, monitor_proto=monitor_proto, - backup_member=backup_member, disabled_member=disabled_member, - pool_cert=pool_cert, pool_ca_cert=pool_ca_cert, - pool_crl=pool_crl, tls_enabled=tls_enabled, - hm_host_http_check=hm_host_http_check)] - l7policies = [] - listener = in_listener( - id=id, - project_id='12345', - protocol_port=port, - protocol=proto, - load_balancer=sample_listener_loadbalancer_tuple( - proto=proto, topology=topology, additional_vips=additional_vips), - peer_port=peer_port, - default_pool=sample_pool_tuple( - proto=be_proto, monitor=monitor, persistence=persistence, - persistence_type=persistence_type, - persistence_cookie=persistence_cookie, - persistence_timeout=persistence_timeout, - persistence_granularity=persistence_granularity, - monitor_ip_port=monitor_ip_port, - monitor_proto=monitor_proto, - monitor_expected_codes=monitor_expected_codes, - pool_cert=pool_cert, - pool_ca_cert=pool_ca_cert, - pool_crl=pool_crl, - tls_enabled=tls_enabled, - hm_host_http_check=hm_host_http_check - ) if alloc_default_pool else '', - connection_limit=connection_limit, - tls_certificate_id='cont_id_1' if tls else '', - sni_container_ids=['cont_id_2', 'cont_id_3'] if sni else [], - default_tls_container=sample_tls_container_tuple( - id='cont_id_1', certificate=sample_certs.X509_CERT, - private_key=sample_certs.X509_CERT_KEY, - intermediates=sample_certs.X509_IMDS_LIST, - primary_cn=sample_certs.X509_CERT_CN - ) if tls else '', - sni_containers=[ - sample_tls_sni_container_tuple( - tls_container_id='cont_id_2', - tls_container=sample_tls_container_tuple( - id='cont_id_2', certificate=sample_certs.X509_CERT_2, - private_key=sample_certs.X509_CERT_KEY_2, - intermediates=sample_certs.X509_IMDS_LIST, - primary_cn=sample_certs.X509_CERT_CN_2)), - sample_tls_sni_container_tuple( - tls_container_id='cont_id_3', - tls_container=sample_tls_container_tuple( - id='cont_id_3', certificate=sample_certs.X509_CERT_3, - private_key=sample_certs.X509_CERT_KEY_3, - intermediates=sample_certs.X509_IMDS_LIST, - primary_cn=sample_certs.X509_CERT_CN_3))] - if sni else [], - pools=pools, - l7policies=l7policies, - enabled=enabled, - insert_headers=insert_headers, - timeout_client_data=timeout_client_data, - timeout_member_connect=timeout_member_connect, - timeout_member_data=timeout_member_data, - timeout_tcp_inspect=timeout_tcp_inspect, - client_ca_tls_certificate_id='cont_id_ca' if client_ca_cert else '', - client_ca_tls_certificate=sample_tls_container_tuple( - id='cont_id_ca', certificate=sample_certs.X509_CA_CERT, - primary_cn=sample_certs.X509_CA_CERT_CN - ) if client_ca_cert else '', - client_authentication=( - constants.CLIENT_AUTH_MANDATORY if client_ca_cert else - constants.CLIENT_AUTH_NONE), - client_crl_container_id='cont_id_crl' if client_crl_cert else '', - provisioning_status=provisioning_status, - ) - if recursive_nest: - listener.load_balancer.listeners.append(listener) - return listener - - -def sample_tls_sni_container_tuple(tls_container_id=None, tls_container=None): - sc = collections.namedtuple('sni_container', 'tls_container_id, ' - 'tls_container') - return sc(tls_container_id=tls_container_id, tls_container=tls_container) - - -def sample_tls_sni_containers_tuple(tls_container_id=None, tls_container=None): - sc = collections.namedtuple('sni_containers', 'tls_container_id, ' - 'tls_container') - return [sc(tls_container_id=tls_container_id, tls_container=tls_container)] - - -def sample_tls_container_tuple(id='cont_id_1', certificate=None, - private_key=None, intermediates=None, - primary_cn=None): - sc = collections.namedtuple( - 'tls_container', - 'id, certificate, private_key, intermediates, primary_cn') - return sc(id=id, certificate=certificate, private_key=private_key, - intermediates=intermediates or [], primary_cn=primary_cn) - - -def sample_pool_tuple(proto=None, monitor=True, persistence=True, - persistence_type=None, persistence_cookie=None, - persistence_timeout=None, persistence_granularity=None, - sample_pool=1, monitor_ip_port=False, - monitor_proto=None, monitor_expected_codes=None, - backup_member=False, - disabled_member=False, has_http_reuse=True, - pool_cert=False, pool_ca_cert=False, pool_crl=False, - tls_enabled=False, hm_host_http_check=False, - provisioning_status=constants.ACTIVE): - proto = 'HTTP' if proto is None else proto - monitor_proto = proto if monitor_proto is None else monitor_proto - in_pool = collections.namedtuple( - 'pool', 'id, protocol, lb_algorithm, members, health_monitor, ' - 'session_persistence, enabled, operating_status, ' - 'tls_certificate_id, ca_tls_certificate_id, ' - 'crl_container_id, tls_enabled, provisioning_status, ' + - constants.HTTP_REUSE) - if (proto == constants.PROTOCOL_UDP and - persistence_type == constants.SESSION_PERSISTENCE_SOURCE_IP): - kwargs = {'persistence_type': persistence_type, - 'persistence_timeout': persistence_timeout, - 'persistence_granularity': persistence_granularity} - else: - kwargs = {'persistence_type': persistence_type, - 'persistence_cookie': persistence_cookie} - persis = sample_session_persistence_tuple(**kwargs) - mon = None - if sample_pool == 1: - id = 'sample_pool_id_1' - members = [sample_member_tuple('sample_member_id_1', '10.0.0.99', - monitor_ip_port=monitor_ip_port), - sample_member_tuple('sample_member_id_2', '10.0.0.98', - monitor_ip_port=monitor_ip_port, - backup=backup_member, - enabled=not disabled_member)] - if monitor is True: - mon = sample_health_monitor_tuple( - proto=monitor_proto, - host_http_check=hm_host_http_check, - expected_codes=monitor_expected_codes) - elif sample_pool == 2: - id = 'sample_pool_id_2' - members = [sample_member_tuple('sample_member_id_3', '10.0.0.97', - monitor_ip_port=monitor_ip_port)] - if monitor is True: - mon = sample_health_monitor_tuple( - proto=monitor_proto, sample_hm=2, - host_http_check=hm_host_http_check, - expected_codes=monitor_expected_codes) - - return in_pool( - id=id, - protocol=proto, - lb_algorithm='ROUND_ROBIN', - members=members, - health_monitor=mon, - session_persistence=persis if persistence is True else None, - enabled=True, - operating_status='ACTIVE', has_http_reuse=has_http_reuse, - tls_certificate_id='pool_cont_1' if pool_cert else None, - ca_tls_certificate_id='pool_ca_1' if pool_ca_cert else None, - crl_container_id='pool_crl' if pool_crl else None, - tls_enabled=tls_enabled, provisioning_status=provisioning_status) - - -def sample_member_tuple(id, ip, enabled=True, - operating_status=constants.ACTIVE, - provisioning_status=constants.ACTIVE, - monitor_ip_port=False, backup=False): - in_member = collections.namedtuple('member', - 'id, ip_address, protocol_port, ' - 'weight, subnet_id, ' - 'enabled, operating_status, ' - 'monitor_address, monitor_port, ' - 'backup, provisioning_status') - monitor_address = '192.168.1.1' if monitor_ip_port else None - monitor_port = 9000 if monitor_ip_port else None - return in_member( - id=id, - ip_address=ip, - protocol_port=82, - weight=13, - subnet_id='10.0.0.1/24', - enabled=enabled, - operating_status=operating_status, - monitor_address=monitor_address, - monitor_port=monitor_port, - backup=backup, provisioning_status=provisioning_status) - - -def sample_session_persistence_tuple(persistence_type=None, - persistence_cookie=None, - persistence_timeout=None, - persistence_granularity=None): - spersistence = collections.namedtuple('SessionPersistence', - 'type, cookie_name, ' - 'persistence_timeout, ' - 'persistence_granularity') - pt = 'HTTP_COOKIE' if persistence_type is None else persistence_type - return spersistence(type=pt, - cookie_name=persistence_cookie, - persistence_timeout=persistence_timeout, - persistence_granularity=persistence_granularity) - - -def sample_health_monitor_tuple(proto='HTTP', sample_hm=1, - host_http_check=False, expected_codes=None, - provisioning_status=constants.ACTIVE): - proto = 'HTTP' if proto == 'TERMINATED_HTTPS' else proto - monitor = collections.namedtuple( - 'monitor', 'id, type, delay, timeout, fall_threshold, rise_threshold,' - 'http_method, url_path, expected_codes, enabled, ' - 'check_script_path, http_version, domain_name, ' - 'provisioning_status') - - if sample_hm == 1: - id = 'sample_monitor_id_1' - url_path = '/index.html' - elif sample_hm == 2: - id = 'sample_monitor_id_2' - url_path = '/healthmon.html' - kwargs = { - 'id': id, - 'type': proto, - 'delay': 30, - 'timeout': 31, - 'fall_threshold': 3, - 'rise_threshold': 2, - 'http_method': 'GET', - 'url_path': url_path, - 'expected_codes': '418', - 'enabled': True, - 'provisioning_status': provisioning_status, - } - if host_http_check: - kwargs.update({'http_version': 1.1, 'domain_name': 'testlab.com'}) - else: - kwargs.update({'http_version': 1.0, 'domain_name': None}) - if expected_codes: - kwargs.update({'expected_codes': expected_codes}) - if proto == constants.HEALTH_MONITOR_UDP_CONNECT: - kwargs['check_script_path'] = (CONF.haproxy_amphora.base_path + - 'lvs/check/' + 'udp_check.sh') - else: - kwargs['check_script_path'] = None - return monitor(**kwargs) - - -def sample_l7policy_tuple(id, - action=constants.L7POLICY_ACTION_REJECT, - redirect_pool=None, redirect_url=None, - redirect_prefix=None, - enabled=True, redirect_http_code=302, - sample_policy=1, - provisioning_status=constants.ACTIVE): - in_l7policy = collections.namedtuple('l7policy', - 'id, action, redirect_pool, ' - 'redirect_url, redirect_prefix, ' - 'l7rules, enabled, ' - 'redirect_http_code, ' - 'provisioning_status') - l7rules = [] - if sample_policy == 1: - action = constants.L7POLICY_ACTION_REDIRECT_TO_POOL - redirect_pool = sample_pool_tuple(sample_pool=2) - l7rules = [sample_l7rule_tuple('sample_l7rule_id_1')] - elif sample_policy == 2: - action = constants.L7POLICY_ACTION_REDIRECT_TO_URL - redirect_url = 'http://www.example.com' - l7rules = [sample_l7rule_tuple('sample_l7rule_id_2', sample_rule=2), - sample_l7rule_tuple('sample_l7rule_id_3', sample_rule=3)] - elif sample_policy == 3: - action = constants.L7POLICY_ACTION_REJECT - l7rules = [sample_l7rule_tuple('sample_l7rule_id_4', sample_rule=4), - sample_l7rule_tuple('sample_l7rule_id_5', sample_rule=5)] - elif sample_policy == 4: - action = constants.L7POLICY_ACTION_REJECT - elif sample_policy == 5: - action = constants.L7POLICY_ACTION_REJECT - enabled = False - l7rules = [sample_l7rule_tuple('sample_l7rule_id_5', sample_rule=5)] - elif sample_policy == 6: - action = constants.L7POLICY_ACTION_REJECT - l7rules = [sample_l7rule_tuple('sample_l7rule_id_6', sample_rule=6)] - elif sample_policy == 7: - action = constants.L7POLICY_ACTION_REDIRECT_PREFIX - redirect_prefix = 'https://example.com' - l7rules = [sample_l7rule_tuple('sample_l7rule_id_2', sample_rule=2), - sample_l7rule_tuple('sample_l7rule_id_3', sample_rule=3)] - elif sample_policy == 8: - action = constants.L7POLICY_ACTION_REDIRECT_TO_URL - redirect_url = 'http://www.ssl-type-l7rule-test.com' - l7rules = [sample_l7rule_tuple('sample_l7rule_id_7', sample_rule=7), - sample_l7rule_tuple('sample_l7rule_id_8', sample_rule=8), - sample_l7rule_tuple('sample_l7rule_id_9', sample_rule=9), - sample_l7rule_tuple('sample_l7rule_id_10', sample_rule=10), - sample_l7rule_tuple('sample_l7rule_id_11', sample_rule=11)] - return in_l7policy( - id=id, - action=action, - redirect_pool=redirect_pool, - redirect_url=redirect_url, - redirect_prefix=redirect_prefix, - l7rules=l7rules, - enabled=enabled, - redirect_http_code=redirect_http_code - if (action in [constants.L7POLICY_ACTION_REDIRECT_TO_URL, - constants.L7POLICY_ACTION_REDIRECT_PREFIX] and - redirect_http_code) else None, - provisioning_status=provisioning_status) - - -def sample_l7rule_tuple(id, - type=constants.L7RULE_TYPE_PATH, - compare_type=constants.L7RULE_COMPARE_TYPE_STARTS_WITH, - key=None, value='/api', - invert=False, enabled=True, - sample_rule=1, provisioning_status=constants.ACTIVE): - in_l7rule = collections.namedtuple('l7rule', - 'id, type, compare_type, ' - 'key, value, invert, enabled, ' - 'provisioning_status') - if sample_rule == 2: - type = constants.L7RULE_TYPE_HEADER - compare_type = constants.L7RULE_COMPARE_TYPE_CONTAINS - key = 'Some-header' - value = 'This string\\ with stuff' - invert = True - enabled = True - if sample_rule == 3: - type = constants.L7RULE_TYPE_COOKIE - compare_type = constants.L7RULE_COMPARE_TYPE_REGEX - key = 'some-cookie' - value = 'this.*|that' - invert = False - enabled = True - if sample_rule == 4: - type = constants.L7RULE_TYPE_FILE_TYPE - compare_type = constants.L7RULE_COMPARE_TYPE_EQUAL_TO - key = None - value = 'jpg' - invert = False - enabled = True - if sample_rule == 5: - type = constants.L7RULE_TYPE_HOST_NAME - compare_type = constants.L7RULE_COMPARE_TYPE_ENDS_WITH - key = None - value = '.example.com' - invert = False - enabled = True - if sample_rule == 6: - type = constants.L7RULE_TYPE_HOST_NAME - compare_type = constants.L7RULE_COMPARE_TYPE_ENDS_WITH - key = None - value = '.example.com' - invert = False - enabled = False - if sample_rule == 7: - type = constants.L7RULE_TYPE_SSL_CONN_HAS_CERT - compare_type = constants.L7RULE_COMPARE_TYPE_EQUAL_TO - key = None - value = 'tRuE' - invert = False - enabled = True - if sample_rule == 8: - type = constants.L7RULE_TYPE_SSL_VERIFY_RESULT - compare_type = constants.L7RULE_COMPARE_TYPE_EQUAL_TO - key = None - value = '1' - invert = True - enabled = True - if sample_rule == 9: - type = constants.L7RULE_TYPE_SSL_DN_FIELD - compare_type = constants.L7RULE_COMPARE_TYPE_REGEX - key = 'STREET' - value = r'^STREET.*NO\.$' - invert = True - enabled = True - if sample_rule == 10: - type = constants.L7RULE_TYPE_SSL_DN_FIELD - compare_type = constants.L7RULE_COMPARE_TYPE_STARTS_WITH - key = 'OU-3' - value = 'Orgnization Bala' - invert = True - enabled = True - return in_l7rule( - id=id, - type=type, - compare_type=compare_type, - key=key, - value=value, - invert=invert, - enabled=enabled, provisioning_status=provisioning_status) - - -def sample_base_expected_config(frontend=None, logging=None, backend=None, - peers=None, global_opts=None, defaults=None): - if frontend is None: - frontend = ("frontend sample_listener_id_1\n" - " maxconn {maxconn}\n" - " bind 10.0.0.2:80\n" - " mode http\n" - " default_backend sample_pool_id_1\n" - " timeout client 50000\n").format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - if logging is None: - logging = (" log-format 12345\\ sample_loadbalancer_id_1\\ %f\\ " - "%ci\\ %cp\\ %t\\ %{+Q}r\\ %ST\\ %B\\ %U\\ " - "%[ssl_c_verify]\\ %{+Q}[ssl_c_s_dn]\\ %b\\ %s\\ %Tt\\ " - "%tsc\n\n") - if backend is None: - backend = ("backend sample_pool_id_1\n" - " mode http\n" - " balance roundrobin\n" - " cookie SRV insert indirect nocache\n" - " timeout check 31s\n" - " option httpchk GET /index.html HTTP/1.0\\r\\n\n" - " http-check expect rstatus 418\n" - " fullconn {maxconn}\n" - " option allbackups\n" - " timeout connect 5000\n" - " timeout server 50000\n" - " server sample_member_id_1 10.0.0.99:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie sample_member_id_1\n" - " server sample_member_id_2 10.0.0.98:82 weight 13 " - "check inter 30s fall 3 rise 2 cookie sample_member_id_2\n" - "\n").format(maxconn=constants.HAPROXY_MAX_MAXCONN) - - if peers is None: - peers = "\n\n" - if global_opts is None: - global_opts = " maxconn {maxconn}\n\n".format( - maxconn=constants.HAPROXY_MAX_MAXCONN) - if defaults is None: - defaults = ("defaults\n" - " log global\n" - " retries 3\n" - " option redispatch\n" - " option splice-request\n" - " option splice-response\n" - " option http-keep-alive\n\n") - return ("# Configuration for loadbalancer sample_loadbalancer_id_1\n" - "global\n" - " daemon\n" - " user nobody\n" - " log /run/rsyslog/octavia/log local0\n" - " log /run/rsyslog/octavia/log local1 notice\n" - " stats socket /var/lib/octavia/sample_listener_id_1.sock" - " mode 0666 level user\n" + - global_opts + defaults + peers + frontend + logging + backend) diff --git a/releasenotes/notes/remove-split-listeners-6a4ccdf66fe7b683.yaml b/releasenotes/notes/remove-split-listeners-6a4ccdf66fe7b683.yaml new file mode 100644 index 0000000000..6a3f6c4b9e --- /dev/null +++ b/releasenotes/notes/remove-split-listeners-6a4ccdf66fe7b683.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - | + Amphora load balancers support single process mode only now. Split listener + configuration, which was used up to API version 0.5, has been + removed from the codebase.