Consume ovn-octavia-provider package on Ussuri and Focal
Remove tactical workarounds for missing binary packages that are now present in both Ussuri UCA and Focal. Update test-requirements and improve mocking, unpin flake8 to allow lint to run on Python 3.8 systems. Change-Id: I195c8c796a52eadf288f0927f2f41166a5768640
This commit is contained in:
parent
8592fb9ecb
commit
167d7d9cd0
|
@ -305,12 +305,13 @@ def spare_amphora_pool_size(cls):
|
|||
|
||||
|
||||
# note plugin comes first to override the config_changed method as a mixin
|
||||
class OctaviaCharm(ch_plugins.PolicydOverridePlugin,
|
||||
charms_openstack.charm.HAOpenStackCharm):
|
||||
"""Charm class for the Octavia charm."""
|
||||
class BaseOctaviaCharm(ch_plugins.PolicydOverridePlugin,
|
||||
charms_openstack.charm.HAOpenStackCharm):
|
||||
"""Base charm class for the Octavia charm."""
|
||||
abstract_class = True
|
||||
|
||||
# layer-openstack-api uses service_type as service name in endpoint catalog
|
||||
name = service_type = 'octavia'
|
||||
release = 'rocky'
|
||||
packages = ['octavia-api', 'octavia-health-manager',
|
||||
'octavia-housekeeping', 'octavia-worker',
|
||||
'apache2', 'libapache2-mod-wsgi-py3']
|
||||
|
@ -346,25 +347,6 @@ class OctaviaCharm(ch_plugins.PolicydOverridePlugin,
|
|||
policyd_service_name = 'octavia'
|
||||
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):
|
||||
"""Custom install function.
|
||||
|
||||
|
@ -477,3 +459,25 @@ class OctaviaCharm(ch_plugins.PolicydOverridePlugin,
|
|||
def local_unit_name(self):
|
||||
"""Return local unit name as provided by our ConfigurationClass."""
|
||||
return self.configuration_class().local_unit_name
|
||||
|
||||
|
||||
class RockyOctaviaCharm(BaseOctaviaCharm):
|
||||
"""Charm class for the Octavia charm on Rocky and newer releases."""
|
||||
release = 'rocky'
|
||||
|
||||
|
||||
class UssuriOctaviaCharm(BaseOctaviaCharm):
|
||||
"""Charm class for the Octavia charm on Ussuri and newer releases."""
|
||||
release = 'ussuri'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
# NOTE(fnordahl): We probably should have a more generic harness for
|
||||
# these kinds of extensions, there might be more SDNs that want support
|
||||
# in the charm.
|
||||
if reactive.is_flag_set('charm.octavia.enable-ovn-driver'):
|
||||
self.packages.extend([
|
||||
'octavia-driver-agent',
|
||||
'python3-ovn-octavia-provider'
|
||||
])
|
||||
self.services.extend(['octavia-driver-agent'])
|
||||
super().__init__(**kwargs)
|
||||
|
|
|
@ -20,6 +20,7 @@ tags:
|
|||
series:
|
||||
- bionic
|
||||
- eoan
|
||||
- focal
|
||||
subordinate: false
|
||||
requires:
|
||||
neutron-api:
|
||||
|
|
|
@ -1,221 +0,0 @@
|
|||
#!/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
|
|
@ -1,22 +0,0 @@
|
|||
[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
|
||||
|
|
@ -1,23 +1,12 @@
|
|||
# This file is managed centrally by release-tools and should not be modified
|
||||
# within individual charm repos. See the 'global' dir contents for available
|
||||
# choices of *requirements.txt files for OpenStack Charms:
|
||||
# https://github.com/openstack-charmers/release-tools
|
||||
# This file is managed centrally. If you find the need to modify this as a
|
||||
# one-off, please don't. Intead, consult #openstack-charms and ask about
|
||||
# requirements management in charms via bot-control. Thank you.
|
||||
#
|
||||
# Lint and unit test requirements
|
||||
flake8>=2.2.4,<=2.4.1
|
||||
stestr>=2.2.0
|
||||
requests>=2.18.4
|
||||
charms.reactive
|
||||
mock>=1.2
|
||||
nose>=1.3.7
|
||||
coverage>=3.6
|
||||
mock>=1.2
|
||||
pep8>=1.7.0
|
||||
flake8>=2.2.4
|
||||
os-testr>=0.4.1
|
||||
|
||||
git+https://github.com/openstack/charms.openstack.git#egg=charms.openstack
|
||||
#
|
||||
# Revisit for removal / mock improvement:
|
||||
netifaces # vault
|
||||
psycopg2-binary # vault
|
||||
tenacity # vault
|
||||
pbr # vault
|
||||
cryptography # vault, keystone-saml-mellon
|
||||
lxml # keystone-saml-mellon
|
||||
hvac # vault, barbican-vault
|
||||
|
|
|
@ -22,18 +22,51 @@ import charms_openstack.test_mocks # noqa
|
|||
charms_openstack.test_mocks.mock_charmhelpers()
|
||||
|
||||
import mock
|
||||
import charms
|
||||
|
||||
|
||||
class _fake_decorator(object):
|
||||
|
||||
def __init__(self, *args):
|
||||
pass
|
||||
|
||||
def __call__(self, f):
|
||||
return f
|
||||
|
||||
|
||||
charms = mock.MagicMock()
|
||||
sys.modules['charms'] = charms
|
||||
charms.leadership = mock.MagicMock()
|
||||
keystoneauth1 = mock.MagicMock()
|
||||
neutronclient = mock.MagicMock()
|
||||
sys.modules['charms.leadership'] = charms.leadership
|
||||
charms.reactive = mock.MagicMock()
|
||||
charms.reactive.when = _fake_decorator
|
||||
charms.reactive.when_all = _fake_decorator
|
||||
charms.reactive.when_any = _fake_decorator
|
||||
charms.reactive.when_not = _fake_decorator
|
||||
charms.reactive.when_none = _fake_decorator
|
||||
charms.reactive.when_not_all = _fake_decorator
|
||||
charms.reactive.not_unless = _fake_decorator
|
||||
charms.reactive.when_file_changed = _fake_decorator
|
||||
charms.reactive.collect_metrics = _fake_decorator
|
||||
charms.reactive.meter_status_changed = _fake_decorator
|
||||
charms.reactive.only_once = _fake_decorator
|
||||
charms.reactive.hook = _fake_decorator
|
||||
charms.reactive.bus = mock.MagicMock()
|
||||
charms.reactive.flags = mock.MagicMock()
|
||||
charms.reactive.relations = mock.MagicMock()
|
||||
sys.modules['charms.reactive'] = charms.reactive
|
||||
sys.modules['charms.reactive.bus'] = charms.reactive.bus
|
||||
sys.modules['charms.reactive.bus'] = charms.reactive.decorators
|
||||
sys.modules['charms.reactive.flags'] = charms.reactive.flags
|
||||
sys.modules['charms.reactive.relations'] = charms.reactive.relations
|
||||
keystoneauth1 = mock.MagicMock()
|
||||
novaclient = mock.MagicMock()
|
||||
neutron_lib = mock.MagicMock()
|
||||
sys.modules['charms.leadership'] = charms.leadership
|
||||
sys.modules['keystoneauth1'] = keystoneauth1
|
||||
netaddr = mock.MagicMock()
|
||||
sys.modules['netaddr'] = netaddr
|
||||
novaclient = mock.MagicMock()
|
||||
sys.modules['novaclient'] = novaclient
|
||||
sys.modules['neutronclient'] = neutronclient
|
||||
sys.modules['neutronclient.v2_0'] = neutronclient.v2_0
|
||||
neutron_lib = mock.MagicMock()
|
||||
sys.modules['neutron_lib'] = neutron_lib
|
||||
sys.modules['neutron_lib.constants'] = neutron_lib.constants
|
||||
neutronclient = mock.MagicMock()
|
||||
sys.modules['neutronclient'] = neutronclient
|
||||
sys.modules['neutronclient.v2_0'] = neutronclient.v2_0
|
||||
|
|
|
@ -26,7 +26,7 @@ class Helper(test_utils.PatchHelper):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.patch_release(octavia.OctaviaCharm.release)
|
||||
self.patch_release(octavia.RockyOctaviaCharm.release)
|
||||
|
||||
|
||||
class TestOctaviaCharmConfigProperties(Helper):
|
||||
|
@ -124,7 +124,7 @@ class TestOctaviaCharm(Helper):
|
|||
def setUp(self):
|
||||
super().setUp()
|
||||
self.patch_object(octavia.reactive, 'is_flag_set', return_value=False)
|
||||
self.target = octavia.OctaviaCharm()
|
||||
self.target = octavia.RockyOctaviaCharm()
|
||||
# remove the 'is_flag_set' patch so the tests can use it
|
||||
self._patches['is_flag_set'].stop()
|
||||
setattr(self, 'is_flag_set', None)
|
||||
|
@ -132,11 +132,13 @@ class TestOctaviaCharm(Helper):
|
|||
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.assertFalse('octavia-driver-agent' in self.target.packages)
|
||||
self.assertFalse(
|
||||
'python3-ovn-octavia-provider' in self.target.packages)
|
||||
self.patch_object(octavia.reactive, 'is_flag_set', return_value=True)
|
||||
c = octavia.OctaviaCharm()
|
||||
self.assertTrue('python3-networking-ovn' in c.packages)
|
||||
c = octavia.UssuriOctaviaCharm()
|
||||
self.assertTrue('octavia-driver-agent' in c.packages)
|
||||
self.assertTrue('python3-ovn-octavia-provider' in c.packages)
|
||||
self.assertTrue('octavia-driver-agent' in c.services)
|
||||
|
||||
def test_install(self):
|
||||
|
|
|
@ -87,7 +87,7 @@ class TestOctaviaHandlers(test_utils.PatchHelper):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.patch_release(octavia.OctaviaCharm.release)
|
||||
self.patch_release(octavia.RockyOctaviaCharm.release)
|
||||
self.octavia_charm = mock.MagicMock()
|
||||
self.patch_object(handlers.charm, 'provide_charm_instance',
|
||||
new=mock.MagicMock())
|
||||
|
@ -169,9 +169,14 @@ class TestOctaviaHandlers(test_utils.PatchHelper):
|
|||
def test_render(self):
|
||||
self.patch('charms.reactive.set_state', 'set_state')
|
||||
self.patch_object(handlers.api_crud, 'create_nova_keypair')
|
||||
self.patch_object(handlers.charm, 'optional_interfaces')
|
||||
self.optional_interfaces.return_value = ('fake', 'interface', 'list')
|
||||
handlers.render('arg1', 'arg2')
|
||||
self.octavia_charm.render_with_interfaces.assert_called_once_with(
|
||||
('arg1', 'arg2'))
|
||||
('fake', 'interface', 'list'))
|
||||
self.optional_interfaces.assert_called_once_with(
|
||||
('arg1', 'arg2'), 'ovsdb-subordinate.available',
|
||||
'ovsdb-cms.available')
|
||||
self.octavia_charm.configure_ssl.assert_called_once_with()
|
||||
self.octavia_charm.enable_webserver_site.assert_called_once_with()
|
||||
self.octavia_charm.assess_status.assert_called_once_with()
|
||||
|
|
Loading…
Reference in New Issue