Add Octavia OVN provider driver support
For use cases that do not require TLS termination or load balancing based on higher layer characteristics, there is a Octavia OVN provider driver that delegates load balancing to the network itself and does not require VMs to handle the traffic. Use the common ``parts/section-keystone-authtoken`` for keystone auth in templates. Change-Id: I1b9704c9e040eef821cef1e4f16faa0b18dce85e
This commit is contained in:
parent
c1e86dcb4a
commit
5127093946
|
@ -7,6 +7,7 @@ includes:
|
||||||
- interface:neutron-load-balancer
|
- interface:neutron-load-balancer
|
||||||
- interface:neutron-plugin
|
- interface:neutron-plugin
|
||||||
- interface:ovsdb-subordinate
|
- interface:ovsdb-subordinate
|
||||||
|
- interface:ovsdb-cms
|
||||||
options:
|
options:
|
||||||
basic:
|
basic:
|
||||||
use_venv: True
|
use_venv: True
|
||||||
|
|
|
@ -346,6 +346,25 @@ class OctaviaCharm(ch_plugins.PolicydOverridePlugin,
|
||||||
policyd_service_name = 'octavia'
|
policyd_service_name = 'octavia'
|
||||||
policyd_restart_on_change = True
|
policyd_restart_on_change = True
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
if reactive.is_flag_set('charm.octavia.enable-ovn-driver'):
|
||||||
|
self.services.extend(['octavia-driver-agent'])
|
||||||
|
# NOTE(fnordahl): This is a tactical workaround for missing init
|
||||||
|
# script and systemd service in the package, this must be removed
|
||||||
|
# before release. LP: #1861671
|
||||||
|
self.restart_map.update({
|
||||||
|
'/etc/init.d/octavia-driver-agent': [],
|
||||||
|
'/lib/systemd/system/octavia-driver-agent.service': [
|
||||||
|
'octavia-driver-agent']
|
||||||
|
})
|
||||||
|
self.permission_override_map = {
|
||||||
|
'/etc/init.d/octavia-driver-agent': 0o755,
|
||||||
|
}
|
||||||
|
# NOTE(fnordahl): For Ussuri and onwards this will be provided by
|
||||||
|
# a new ``ovn-octavia-provider`` package.
|
||||||
|
self.packages.extend(['python3-networking-ovn'])
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def install(self):
|
def install(self):
|
||||||
"""Custom install function.
|
"""Custom install function.
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ requires:
|
||||||
ovsdb-subordinate:
|
ovsdb-subordinate:
|
||||||
interface: ovsdb-subordinate
|
interface: ovsdb-subordinate
|
||||||
scope: container
|
scope: container
|
||||||
|
ovsdb-cms:
|
||||||
|
interface: ovsdb-cms
|
||||||
resources:
|
resources:
|
||||||
policyd-override:
|
policyd-override:
|
||||||
type: file
|
type: file
|
||||||
|
|
|
@ -55,6 +55,21 @@ def sdn_broken():
|
||||||
reactive.clear_flag('sdn-subordinate.connected')
|
reactive.clear_flag('sdn-subordinate.connected')
|
||||||
|
|
||||||
|
|
||||||
|
@reactive.when_not('ovsdb-subordinate.available')
|
||||||
|
def disable_ovn_driver():
|
||||||
|
reactive.clear_flag('charm.octavia.enable-ovn-driver')
|
||||||
|
|
||||||
|
|
||||||
|
@reactive.when('ovsdb-subordinate.available')
|
||||||
|
def maybe_enable_ovn_driver():
|
||||||
|
ovsdb = reactive.endpoint_from_flag('ovsdb-subordinate.available')
|
||||||
|
if ovsdb.ovn_configured:
|
||||||
|
reactive.set_flag('charm.octavia.enable-ovn-driver')
|
||||||
|
with charm.provide_charm_instance() as charm_instance:
|
||||||
|
charm_instance.install()
|
||||||
|
charm_instance.assess_status()
|
||||||
|
|
||||||
|
|
||||||
@reactive.when('identity-service.connected')
|
@reactive.when('identity-service.connected')
|
||||||
def setup_endpoint_connection(keystone):
|
def setup_endpoint_connection(keystone):
|
||||||
"""Custom register endpoint function for Octavia.
|
"""Custom register endpoint function for Octavia.
|
||||||
|
@ -174,7 +189,12 @@ def render(*args):
|
||||||
api_crud.create_nova_keypair(identity_service, amp_key_name)
|
api_crud.create_nova_keypair(identity_service, amp_key_name)
|
||||||
|
|
||||||
with charm.provide_charm_instance() as octavia_charm:
|
with charm.provide_charm_instance() as octavia_charm:
|
||||||
octavia_charm.render_with_interfaces(args)
|
octavia_charm.render_with_interfaces(
|
||||||
|
charm.optional_interfaces(
|
||||||
|
args,
|
||||||
|
'ovsdb-subordinate.available',
|
||||||
|
'ovsdb-cms.available',
|
||||||
|
))
|
||||||
octavia_charm.configure_ssl()
|
octavia_charm.configure_ssl()
|
||||||
octavia_charm.enable_webserver_site()
|
octavia_charm.enable_webserver_site()
|
||||||
octavia_charm.assess_status()
|
octavia_charm.assess_status()
|
||||||
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
#!/bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: octavia-driver-agent
|
||||||
|
# Required-Start: $network $local_fs $remote_fs $syslog
|
||||||
|
# Required-Stop: $remote_fs
|
||||||
|
# Should-Start: postgresql mysql keystone rabbitmq-server ntp
|
||||||
|
# Should-Stop: postgresql mysql keystone rabbitmq-server ntp
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: Octavia LBaaS Driver agent
|
||||||
|
# Description: Octavia Driver agent
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
# Author: Michal Arbet <michal.arbet@ultimum.io>
|
||||||
|
|
||||||
|
DESC="OpenStack Octavia Driver Agent (octavia-driver-agent)"
|
||||||
|
PROJECT_NAME=octavia
|
||||||
|
NAME=${PROJECT_NAME}-driver-agent
|
||||||
|
#!/bin/sh
|
||||||
|
# The content after this line comes from openstack-pkg-tools
|
||||||
|
# and has been automatically added to a .init.in script, which
|
||||||
|
# contains only the descriptive part for the daemon. Everything
|
||||||
|
# else is standardized as a single unique script.
|
||||||
|
|
||||||
|
# Author: Thomas Goirand <zigo@debian.org>
|
||||||
|
# Author: Ondřej Nový <novy@ondrej.org>
|
||||||
|
# Author: Frode Nordahl <frode.nordahl@canonical.com>
|
||||||
|
|
||||||
|
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||||
|
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||||
|
|
||||||
|
if [ -n "${UWSGI_PORT}" ] && [ -n "${UWSGI_INI_PATH}" ] && [ -n "${UWSGI_INI_APP}" ] ; then
|
||||||
|
if ! [ -f "${UWSGI_INI_APP}" ] ; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [ -d /etc/${PROJECT_NAME}/ssl/private ] ; then
|
||||||
|
KEY_FILE=$(find /etc/${PROJECT_NAME}/ssl/private -type f -iname '*.pem' 2>/dev/null | head -n 1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e /usr/local/share/ca-certificates/puppet_openstack.crt ] ; then
|
||||||
|
# This is needed for puppet...
|
||||||
|
CERT_FILE=/usr/local/share/ca-certificates/puppet_openstack.crt
|
||||||
|
else
|
||||||
|
if [ -d /etc/${PROJECT_NAME}/ssl/public ] ; then
|
||||||
|
CERT_FILE=$(find /etc/${PROJECT_NAME}/ssl/public -type f -iname '*.crt' 2>/dev/null | head -n 1)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sid doesn't have /usr/bin/uwsgi_python3, so we need
|
||||||
|
# to search for a more specific daemon name. For stretch
|
||||||
|
# /usr/bin/uwsgi_python3 is fine.
|
||||||
|
for i in 3 35 36 37 38 39 ; do
|
||||||
|
if [ -x /usr/bin/uwsgi_python${i} ] ; then
|
||||||
|
DAEMON=/usr/bin/uwsgi_python${i}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "${KEY_FILE}" ] && [ -n "${CERT_FILE}" ] ; then
|
||||||
|
DAEMON_ARGS="--https-socket [::]:${UWSGI_PORT},${CERT_FILE},${KEY_FILE}"
|
||||||
|
else
|
||||||
|
DAEMON_ARGS="--http-socket [::]:${UWSGI_PORT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
DAEMON_ARGS="${DAEMON_ARGS} --ini ${UWSGI_INI_PATH}"
|
||||||
|
NO_OPENSTACK_CONFIG_FILE_DAEMON_ARG=yes
|
||||||
|
NO_OPENSTACK_LOGFILE_DAEMON_ARG=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${DAEMON}" ] ; then
|
||||||
|
DAEMON=/usr/bin/${NAME}
|
||||||
|
fi
|
||||||
|
PIDFILE=/var/run/${PROJECT_NAME}/${NAME}.pid
|
||||||
|
if [ -z "${SCRIPTNAME}" ] ; then
|
||||||
|
SCRIPTNAME=/etc/init.d/${NAME}
|
||||||
|
fi
|
||||||
|
if [ -z "${SYSTEM_USER}" ] ; then
|
||||||
|
SYSTEM_USER=${PROJECT_NAME}
|
||||||
|
fi
|
||||||
|
if [ -z "${SYSTEM_GROUP}" ] ; then
|
||||||
|
SYSTEM_GROUP=${PROJECT_NAME}
|
||||||
|
fi
|
||||||
|
if [ "${SYSTEM_USER}" != "root" ] ; then
|
||||||
|
STARTDAEMON_CHUID="--chuid ${SYSTEM_USER}:${SYSTEM_GROUP}"
|
||||||
|
fi
|
||||||
|
if [ -z "${CONFIG_FILE}" ] ; then
|
||||||
|
CONFIG_FILE=/etc/${PROJECT_NAME}/${PROJECT_NAME}.conf
|
||||||
|
fi
|
||||||
|
LOGFILE=/var/log/${PROJECT_NAME}/${NAME}.log
|
||||||
|
if [ -z "${NO_OPENSTACK_CONFIG_FILE_DAEMON_ARG}" ] ; then
|
||||||
|
DAEMON_ARGS="--config-file=${CONFIG_FILE} ${DAEMON_ARGS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit if the package is not installed
|
||||||
|
[ -x $DAEMON ] || exit 0
|
||||||
|
|
||||||
|
# If ran as root, create /var/lock/X, /var/run/X and /var/cache/X as needed
|
||||||
|
if [ `whoami` = "root" ] ; then
|
||||||
|
for i in lock run cache ; do
|
||||||
|
mkdir -p /var/$i/${PROJECT_NAME}
|
||||||
|
chown ${SYSTEM_USER}:${SYSTEM_GROUP} /var/$i/${PROJECT_NAME}
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This defines support functions which we use later on
|
||||||
|
. /lib/lsb/init-functions
|
||||||
|
|
||||||
|
RET=0
|
||||||
|
|
||||||
|
# Manage log options: logfile and/or syslog, depending on user's choosing
|
||||||
|
[ -r /etc/default/openstack ] && . /etc/default/openstack
|
||||||
|
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||||
|
[ "x$USE_SYSLOG" = "xyes" ] && DAEMON_ARGS="$DAEMON_ARGS --use-syslog"
|
||||||
|
if [ -z "${NO_OPENSTACK_LOGFILE_DAEMON_ARG}" ] ; then
|
||||||
|
[ "x$USE_LOGFILE" != "xno" ] && DAEMON_ARGS="$DAEMON_ARGS --log-file=$LOGFILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
do_start() {
|
||||||
|
start-stop-daemon \
|
||||||
|
--start \
|
||||||
|
--quiet \
|
||||||
|
--background ${STARTDAEMON_CHUID} \
|
||||||
|
--make-pidfile --pidfile ${PIDFILE} \
|
||||||
|
--chdir /var/lib/${PROJECT_NAME} \
|
||||||
|
--startas $DAEMON \
|
||||||
|
--test > /dev/null \
|
||||||
|
|| return 1
|
||||||
|
if [ -n "${PYARGV}" ] ; then
|
||||||
|
start-stop-daemon \
|
||||||
|
--start \
|
||||||
|
--quiet \
|
||||||
|
--background ${STARTDAEMON_CHUID} \
|
||||||
|
--make-pidfile --pidfile ${PIDFILE} \
|
||||||
|
--chdir /var/lib/${PROJECT_NAME} \
|
||||||
|
--startas $DAEMON \
|
||||||
|
-- $DAEMON_ARGS --pyargv "${PYARGV}" \
|
||||||
|
|| return 2
|
||||||
|
else
|
||||||
|
start-stop-daemon \
|
||||||
|
--start \
|
||||||
|
--quiet \
|
||||||
|
--background ${STARTDAEMON_CHUID} \
|
||||||
|
--make-pidfile --pidfile ${PIDFILE} \
|
||||||
|
--chdir /var/lib/${PROJECT_NAME} \
|
||||||
|
--startas $DAEMON \
|
||||||
|
-- $DAEMON_ARGS \
|
||||||
|
|| return 2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
do_stop() {
|
||||||
|
start-stop-daemon \
|
||||||
|
--stop \
|
||||||
|
--quiet \
|
||||||
|
--retry=TERM/30/KILL/5 \
|
||||||
|
--pidfile $PIDFILE
|
||||||
|
RETVAL=$?
|
||||||
|
rm -f $PIDFILE
|
||||||
|
return "$RETVAL"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_systemd_start() {
|
||||||
|
if [ -n "${PYARGV}" ] ; then
|
||||||
|
exec $DAEMON $DAEMON_ARGS --pyargv "${PYARGV}"
|
||||||
|
else
|
||||||
|
exec $DAEMON $DAEMON_ARGS
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
log_daemon_msg "Starting $DESC" "$NAME"
|
||||||
|
do_start
|
||||||
|
case $? in
|
||||||
|
0|1) log_end_msg 0 ; RET=$? ;;
|
||||||
|
2) log_end_msg 1 ; RET=$? ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
log_daemon_msg "Stopping $DESC" "$NAME"
|
||||||
|
do_stop
|
||||||
|
case $? in
|
||||||
|
0|1) log_end_msg 0 ; RET=$? ;;
|
||||||
|
2) log_end_msg 1 ; RET=$? ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status_of_proc "$DAEMON" "$NAME"
|
||||||
|
RET=$?
|
||||||
|
;;
|
||||||
|
systemd-start)
|
||||||
|
do_systemd_start
|
||||||
|
;;
|
||||||
|
show-args)
|
||||||
|
if [ -n "${PYARGV}" ] ; then
|
||||||
|
echo $DAEMON $DAEMON_ARGS --pyargv \"${PYARGV}\"
|
||||||
|
else
|
||||||
|
echo $DAEMON $DAEMON_ARGS
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
restart|force-reload)
|
||||||
|
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||||
|
do_stop
|
||||||
|
case $? in
|
||||||
|
0|1)
|
||||||
|
do_start
|
||||||
|
case $? in
|
||||||
|
0) log_end_msg 0 ; RET=$? ;;
|
||||||
|
1) log_end_msg 1 ; RET=$? ;; # Old process is still running
|
||||||
|
*) log_end_msg 1 ; RET=$? ;; # Failed to start
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*) log_end_msg 1 ; RET=$? ;; # Failed to stop
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload|systemd-start}" >&2
|
||||||
|
RET=3
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $RET
|
|
@ -0,0 +1,22 @@
|
||||||
|
[Unit]
|
||||||
|
Description=OpenStack Octavia Driver agent (octavia-driver-agent)
|
||||||
|
After=postgresql.service mysql.service keystone.service rabbitmq-server.service ntp.service
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=octavia
|
||||||
|
Group=octavia
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=~
|
||||||
|
RuntimeDirectory=octavia lock/octavia
|
||||||
|
CacheDirectory=octavia
|
||||||
|
ExecStart=/etc/init.d/octavia-driver-agent systemd-start
|
||||||
|
Restart=on-failure
|
||||||
|
LimitNOFILE=65535
|
||||||
|
TimeoutStopSec=15
|
||||||
|
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
|
@ -79,14 +79,7 @@ client_cert = {{ options.controller_cert }}
|
||||||
{% include "parts/section-database" %}
|
{% include "parts/section-database" %}
|
||||||
|
|
||||||
[service_auth]
|
[service_auth]
|
||||||
auth_type = password
|
auth_section = keystone_authtoken
|
||||||
auth_uri = {{ identity_service.service_protocol }}://{{ identity_service.service_host }}:{{ identity_service.service_port }}
|
|
||||||
auth_url = {{ identity_service.auth_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}
|
|
||||||
project_domain_name = {{ identity_service.service_domain }}
|
|
||||||
user_domain_name = {{ identity_service.service_domain }}
|
|
||||||
project_name = {{ identity_service.service_tenant }}
|
|
||||||
username = {{ identity_service.service_username }}
|
|
||||||
password = {{ identity_service.service_password }}
|
|
||||||
|
|
||||||
{% include "parts/section-keystone-authtoken" %}
|
{% include "parts/section-keystone-authtoken" %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
[DEFAULT]
|
||||||
|
debug = {{ options.debug }}
|
||||||
|
|
||||||
|
{% include "parts/section-transport-url" %}
|
||||||
|
|
||||||
|
{% if ovsdb_subordinate and ovsdb_subordinate.ovn_configured and ovsdb_cms -%}
|
||||||
|
[api_settings]
|
||||||
|
enabled_provider_drivers = amphora:The Octavia Amphora driver,ovn:Octavia OVN driver
|
||||||
|
|
||||||
|
[ovn]
|
||||||
|
ovn_nb_connection={{ ','.join(ovsdb_cms.db_nb_connection_strs) }}
|
||||||
|
ovn_nb_private_key=/etc/apache2/ssl/{{ options.service_name }}/key_{{ ovsdb_subordinate.chassis_name }}
|
||||||
|
ovn_nb_certificate=/etc/apache2/ssl/{{ options.service_name }}/cert_{{ ovsdb_subordinate.chassis_name }}
|
||||||
|
ovn_nb_ca_cert=/etc/ssl/certs/ca-certificates.crt
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
[health_manager]
|
||||||
|
{% if options.health_manager_bind_ip -%}
|
||||||
|
bind_ip = {{ options.health_manager_bind_ip }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if options.controller_ip_port_list -%}
|
||||||
|
controller_ip_port_list = {{ options.controller_ip_port_list }}
|
||||||
|
{% endif -%}
|
||||||
|
heartbeat_key = {{ options.heartbeat_key }}
|
||||||
|
|
||||||
|
[house_keeping]
|
||||||
|
{% if options.spare_amphora_pool_size -%}
|
||||||
|
spare_amphora_pool_size = {{ options.spare_amphora_pool_size }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
[controller_worker]
|
||||||
|
{% if options.amp_ssh_key_name %}
|
||||||
|
amp_ssh_key_name = {{ options.amp_ssh_key_name }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if options.amp_image_owner_id -%}
|
||||||
|
amp_image_owner_id = {{ options.amp_image_owner_id }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if options.amp_secgroup_list -%}
|
||||||
|
amp_secgroup_list = {{ options.amp_secgroup_list }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if options.amp_flavor_id -%}
|
||||||
|
amp_flavor_id = {{ options.amp_flavor_id }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if options.amp_boot_network_list -%}
|
||||||
|
amp_boot_network_list = {{ options.amp_boot_network_list }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if options.amp_image_tag -%}
|
||||||
|
amp_image_tag = {{ options.amp_image_tag }}
|
||||||
|
{% endif -%}
|
||||||
|
amp_active_retries = 180
|
||||||
|
# This certificate is installed on the ``Amphorae`` and used for validating
|
||||||
|
# the authenticity of the ``Octavia`` controller.
|
||||||
|
client_ca = {{ options.controller_cacert }}
|
||||||
|
network_driver = allowed_address_pairs_driver
|
||||||
|
compute_driver = compute_nova_driver
|
||||||
|
amphora_driver = amphora_haproxy_rest_driver
|
||||||
|
loadbalancer_topology = {{ options.loadbalancer_topology }}
|
||||||
|
|
||||||
|
[certificates]
|
||||||
|
# NOTE(fnordahl) certificates for authentication between Octavia controllers
|
||||||
|
# and its Amphorae instances are issued locally on the Octavia controller.
|
||||||
|
#
|
||||||
|
# At the time of this writing this is the only supported alternative upstream
|
||||||
|
# after the retirement of the Anchor project [0].
|
||||||
|
#
|
||||||
|
# Note that these certificates are not used for any load balancer payload data
|
||||||
|
#
|
||||||
|
# 0: https://review.opendev.org/#/c/597022/
|
||||||
|
cert_generator = local_cert_generator
|
||||||
|
# This certificate is used to issue individual certificates for each
|
||||||
|
# ``Amphora`` and to validate their authenticity when they connect to the
|
||||||
|
# ``Octavia`` controller.
|
||||||
|
ca_certificate = {{ options.issuing_cacert }}
|
||||||
|
ca_private_key = {{ options.issuing_ca_private_key }}
|
||||||
|
ca_private_key_passphrase = {{ options.issuing_ca_private_key_passphrase }}
|
||||||
|
|
||||||
|
cert_manager = barbican_cert_manager
|
||||||
|
{% if options.region -%}
|
||||||
|
region_name = {{ options.region }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
[haproxy_amphora]
|
||||||
|
# This certificate is used by the ``Octavia`` controller to validate the
|
||||||
|
# authenticity of the ``Amphorae`` connecting to it.
|
||||||
|
server_ca = {{ options.issuing_cacert }}
|
||||||
|
# This certificate is used by the ``Octavia`` controller when it takes on the
|
||||||
|
# role as a "client" connecting to the ``Amphorae``.
|
||||||
|
client_cert = {{ options.controller_cert }}
|
||||||
|
|
||||||
|
{% include "parts/section-database" %}
|
||||||
|
|
||||||
|
[service_auth]
|
||||||
|
auth_section = keystone_authtoken
|
||||||
|
|
||||||
|
{% include "parts/section-keystone-authtoken" %}
|
||||||
|
|
||||||
|
[oslo_messaging]
|
||||||
|
topic = octavia
|
||||||
|
|
||||||
|
[nova]
|
||||||
|
{% if options.region -%}
|
||||||
|
region_name = {{ options.region }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
[cinder]
|
||||||
|
{% if options.region -%}
|
||||||
|
region_name = {{ options.region }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
[glance]
|
||||||
|
{% if options.region -%}
|
||||||
|
region_name = {{ options.region }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
[neutron]
|
||||||
|
{% if options.region -%}
|
||||||
|
region_name = {{ options.region }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% include "parts/section-oslo-messaging-rabbit" %}
|
||||||
|
|
||||||
|
{% include "parts/section-oslo-middleware" %}
|
|
@ -63,6 +63,8 @@ relations:
|
||||||
- nova-compute:neutron-plugin
|
- nova-compute:neutron-plugin
|
||||||
- - ovn-chassis:ovsdb-subordinate
|
- - ovn-chassis:ovsdb-subordinate
|
||||||
- octavia:ovsdb-subordinate
|
- octavia:ovsdb-subordinate
|
||||||
|
- - ovn-central:ovsdb-cms
|
||||||
|
- octavia:ovsdb-cms
|
||||||
- - ovn-chassis:certificates
|
- - ovn-chassis:certificates
|
||||||
- vault:certificates
|
- vault:certificates
|
||||||
- - ovn-chassis:ovsdb
|
- - ovn-chassis:ovsdb
|
||||||
|
|
|
@ -121,13 +121,30 @@ class TestOctaviaCharmConfigProperties(Helper):
|
||||||
|
|
||||||
class TestOctaviaCharm(Helper):
|
class TestOctaviaCharm(Helper):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.patch_object(octavia.reactive, 'is_flag_set', return_value=False)
|
||||||
|
self.target = octavia.OctaviaCharm()
|
||||||
|
# remove the 'is_flag_set' patch so the tests can use it
|
||||||
|
self._patches['is_flag_set'].stop()
|
||||||
|
setattr(self, 'is_flag_set', None)
|
||||||
|
del(self._patches['is_flag_set'])
|
||||||
|
del(self._patches_start['is_flag_set'])
|
||||||
|
|
||||||
|
def test_optional_ovn_provider_driver(self):
|
||||||
|
self.assertFalse('python3-networking-ovn' in self.target.packages)
|
||||||
|
self.assertFalse('octavia-driver-agent' in self.target.services)
|
||||||
|
self.patch_object(octavia.reactive, 'is_flag_set', return_value=True)
|
||||||
|
c = octavia.OctaviaCharm()
|
||||||
|
self.assertTrue('python3-networking-ovn' in c.packages)
|
||||||
|
self.assertTrue('octavia-driver-agent' in c.services)
|
||||||
|
|
||||||
def test_install(self):
|
def test_install(self):
|
||||||
# we do not care about the internals of the function we are overriding
|
# we do not care about the internals of the function we are overriding
|
||||||
# and expanding so mock out the call to super()
|
# and expanding so mock out the call to super()
|
||||||
self.patch('builtins.super', 'super')
|
self.patch('builtins.super', 'super')
|
||||||
self.patch_object(octavia.ch_core, 'host')
|
self.patch_object(octavia.ch_core, 'host')
|
||||||
c = octavia.OctaviaCharm()
|
self.target.install()
|
||||||
c.install()
|
|
||||||
self.super.assert_called()
|
self.super.assert_called()
|
||||||
self.host.add_user_to_group.assert_called_once_with('systemd-network',
|
self.host.add_user_to_group.assert_called_once_with('systemd-network',
|
||||||
'octavia')
|
'octavia')
|
||||||
|
@ -146,8 +163,7 @@ class TestOctaviaCharm(Helper):
|
||||||
override_relation: 'something-we-are-replacing',
|
override_relation: 'something-we-are-replacing',
|
||||||
}
|
}
|
||||||
self.super().states_to_check.return_value = states_to_check
|
self.super().states_to_check.return_value = states_to_check
|
||||||
c = octavia.OctaviaCharm()
|
self.target.states_to_check()
|
||||||
c.states_to_check()
|
|
||||||
self.super().states_to_check.assert_called_once_with(None)
|
self.super().states_to_check.assert_called_once_with(None)
|
||||||
self.leader_get.assert_called_once_with(
|
self.leader_get.assert_called_once_with(
|
||||||
'amp-boot-network-list')
|
'amp-boot-network-list')
|
||||||
|
@ -156,13 +172,11 @@ class TestOctaviaCharm(Helper):
|
||||||
self.super.assert_called()
|
self.super.assert_called()
|
||||||
|
|
||||||
def test_get_amqp_credentials(self):
|
def test_get_amqp_credentials(self):
|
||||||
c = octavia.OctaviaCharm()
|
result = self.target.get_amqp_credentials()
|
||||||
result = c.get_amqp_credentials()
|
|
||||||
self.assertEqual(result, ('octavia', 'openstack'))
|
self.assertEqual(result, ('octavia', 'openstack'))
|
||||||
|
|
||||||
def test_get_database_setup(self):
|
def test_get_database_setup(self):
|
||||||
c = octavia.OctaviaCharm()
|
result = self.target.get_database_setup()
|
||||||
result = c.get_database_setup()
|
|
||||||
self.assertEqual(result, [{'database': 'octavia',
|
self.assertEqual(result, [{'database': 'octavia',
|
||||||
'username': 'octavia'}])
|
'username': 'octavia'}])
|
||||||
|
|
||||||
|
@ -173,8 +187,7 @@ class TestOctaviaCharm(Helper):
|
||||||
self.patch('charmhelpers.core.host.service_reload', 'service_reload')
|
self.patch('charmhelpers.core.host.service_reload', 'service_reload')
|
||||||
self.exists.return_value = True
|
self.exists.return_value = True
|
||||||
self.sp_call.return_value = True
|
self.sp_call.return_value = True
|
||||||
c = octavia.OctaviaCharm()
|
self.target.enable_webserver_site()
|
||||||
c.enable_webserver_site()
|
|
||||||
self.exists.assert_called_with(
|
self.exists.assert_called_with(
|
||||||
'/etc/apache2/sites-available/octavia-api.conf')
|
'/etc/apache2/sites-available/octavia-api.conf')
|
||||||
self.sp_call.assert_called_with(['a2query', '-s', 'octavia-api'])
|
self.sp_call.assert_called_with(['a2query', '-s', 'octavia-api'])
|
||||||
|
@ -183,14 +196,13 @@ class TestOctaviaCharm(Helper):
|
||||||
'apache2', restart_on_failure=True)
|
'apache2', restart_on_failure=True)
|
||||||
|
|
||||||
def test_local_address(self):
|
def test_local_address(self):
|
||||||
c = octavia.OctaviaCharm()
|
|
||||||
configuration_class = mock.MagicMock()
|
configuration_class = mock.MagicMock()
|
||||||
c.configuration_class = configuration_class
|
self.target.configuration_class = configuration_class
|
||||||
self.assertEqual(c.local_address, configuration_class().local_address)
|
self.assertEqual(self.target.local_address,
|
||||||
|
configuration_class().local_address)
|
||||||
|
|
||||||
def test_local_unit_name(self):
|
def test_local_unit_name(self):
|
||||||
c = octavia.OctaviaCharm()
|
|
||||||
configuration_class = mock.MagicMock()
|
configuration_class = mock.MagicMock()
|
||||||
c.configuration_class = configuration_class
|
self.target.configuration_class = configuration_class
|
||||||
self.assertEqual(c.local_unit_name,
|
self.assertEqual(self.target.local_unit_name,
|
||||||
configuration_class().local_unit_name)
|
configuration_class().local_unit_name)
|
||||||
|
|
|
@ -60,6 +60,8 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks):
|
||||||
'amqp.available',),
|
'amqp.available',),
|
||||||
'setup_endpoint_connection': (
|
'setup_endpoint_connection': (
|
||||||
'identity-service.connected',),
|
'identity-service.connected',),
|
||||||
|
'maybe_enable_ovn_driver': (
|
||||||
|
'ovsdb-subordinate.available',),
|
||||||
},
|
},
|
||||||
'when_any': {
|
'when_any': {
|
||||||
'sdn_joined': ('neutron-openvswitch.connected',
|
'sdn_joined': ('neutron-openvswitch.connected',
|
||||||
|
@ -73,6 +75,7 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks):
|
||||||
'init_db': ('db.synced',),
|
'init_db': ('db.synced',),
|
||||||
'cluster_connected': ('ha.available',),
|
'cluster_connected': ('ha.available',),
|
||||||
'generate_heartbeat_key': ('leadership.set.heartbeat-key',),
|
'generate_heartbeat_key': ('leadership.set.heartbeat-key',),
|
||||||
|
'disable_ovn_driver': ('ovsdb-subordinate.available',),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
# test that the hooks were registered via the
|
# test that the hooks were registered via the
|
||||||
|
@ -188,3 +191,23 @@ class TestOctaviaHandlers(test_utils.PatchHelper):
|
||||||
self.octavia_charm.configure_ha_resources.assert_called_once_with(
|
self.octavia_charm.configure_ha_resources.assert_called_once_with(
|
||||||
hacluster)
|
hacluster)
|
||||||
self.octavia_charm.assess_status.assert_called_once_with()
|
self.octavia_charm.assess_status.assert_called_once_with()
|
||||||
|
|
||||||
|
def test_disable_ovn_driver(self):
|
||||||
|
self.patch_object(octavia.reactive, 'clear_flag')
|
||||||
|
handlers.disable_ovn_driver()
|
||||||
|
self.clear_flag.assert_called_once_with(
|
||||||
|
'charm.octavia.enable-ovn-driver')
|
||||||
|
|
||||||
|
def test_maybe_enable_ovn_driver(self):
|
||||||
|
ovsdb = mock.MagicMock()
|
||||||
|
ovsdb.ovn_configured = True
|
||||||
|
self.patch_object(octavia.reactive, 'endpoint_from_flag')
|
||||||
|
self.endpoint_from_flag.return_value = ovsdb
|
||||||
|
self.patch_object(octavia.reactive, 'set_flag')
|
||||||
|
handlers.maybe_enable_ovn_driver()
|
||||||
|
self.endpoint_from_flag.assert_called_once_with(
|
||||||
|
'ovsdb-subordinate.available')
|
||||||
|
self.set_flag.assert_called_once_with(
|
||||||
|
'charm.octavia.enable-ovn-driver')
|
||||||
|
self.octavia_charm.install.assert_called_once_with()
|
||||||
|
self.octavia_charm.assess_status.assert_called_once_with()
|
||||||
|
|
Loading…
Reference in New Issue