Files
zaza-openstack-tests/zaza/openstack/charm_tests/octavia/setup.py
Frode Nordahl 3b6a2de1ca octavia: Conditionally use DVR specific flags
The current test code for octavia requires DVR extensions to be
present on the Neutron API server.

We need to conditionally enable this based on enabled extensions to
allow the test to operate on multiple deployment configurations.
2020-01-17 16:07:00 +01:00

176 lines
6.5 KiB
Python

# Copyright 2018 Canonical Ltd.
#
# 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.
"""Code for configuring octavia."""
import os
import base64
import logging
import zaza.openstack.utilities.cert as cert
import zaza.charm_lifecycle.utils
import zaza.openstack.charm_tests.test_utils
import zaza.openstack.charm_tests.glance.setup as glance_setup
import zaza.openstack.utilities.openstack as openstack
import zaza.openstack.configure.guest
def add_amphora_image(image_url=None):
"""Add Octavia ``amphora`` test image to glance.
:param image_url: URL where image resides
:type image_url: str
"""
image_name = 'amphora-x64-haproxy'
if not image_url:
image_url = (
os.environ.get('FUNCTEST_AMPHORA_LOCATION', None) or
'http://tarballs.openstack.org/octavia/test-images/'
'test-only-amphora-x64-haproxy-ubuntu-xenial.qcow2')
glance_setup.add_image(
image_url,
image_name=image_name,
tags=['octavia-amphora'])
def configure_octavia():
"""Do mandatory post deployment configuration of Octavia."""
# Tell Octavia charm it is safe to create cloud resources
logging.info('Running `configure-resources` action on Octavia leader unit')
zaza.model.run_action_on_leader(
'octavia',
'configure-resources',
action_params={})
# Generate certificates for controller/load balancer instance communication
(issuing_cakey, issuing_cacert) = cert.generate_cert(
'OSCI Zaza Issuer',
password='zaza',
generate_ca=True)
(controller_cakey, controller_cacert) = cert.generate_cert(
'OSCI Zaza Octavia Controller',
generate_ca=True)
(controller_key, controller_cert) = cert.generate_cert(
'*.serverstack',
issuer_name='OSCI Zaza Octavia Controller',
signing_key=controller_cakey)
controller_bundle = controller_cert + controller_key
cert_config = {
'lb-mgmt-issuing-cacert': base64.b64encode(
issuing_cacert).decode('utf-8'),
'lb-mgmt-issuing-ca-private-key': base64.b64encode(
issuing_cakey).decode('utf-8'),
'lb-mgmt-issuing-ca-key-passphrase': 'zaza',
'lb-mgmt-controller-cacert': base64.b64encode(
controller_cacert).decode('utf-8'),
'lb-mgmt-controller-cert': base64.b64encode(
controller_bundle).decode('utf-8'),
}
logging.info('Configuring certificates for mandatory Octavia '
'client/server authentication '
'(client being the ``Amphorae`` load balancer instances)')
# Our expected workload status will change after we have configured the
# certificates
test_config = zaza.charm_lifecycle.utils.get_charm_config()
del test_config['target_deploy_status']['octavia']
_singleton = zaza.openstack.charm_tests.test_utils.OpenStackBaseTest()
_singleton.setUpClass()
with _singleton.config_change(cert_config, cert_config):
# wait for configuration to be applied then return
pass
def prepare_payload_instance():
"""Prepare a instance we can use as payload test."""
session = openstack.get_overcloud_keystone_session()
keystone = openstack.get_keystone_session_client(session)
neutron = openstack.get_neutron_session_client(session)
project_id = openstack.get_project_id(
keystone, 'admin', domain_name='admin_domain')
openstack.add_neutron_secgroup_rules(
neutron,
project_id,
[{'protocol': 'tcp',
'port_range_min': '80',
'port_range_max': '80',
'direction': 'ingress'}])
zaza.openstack.configure.guest.launch_instance(
glance_setup.LTS_IMAGE_NAME,
userdata='#cloud-config\npackages:\n - apache2\n')
def centralized_fip_network():
"""Create network with centralized router for connecting lb and fips.
There are currently a few outstanding upstream issues with connecting a
Octavia loadbalancer to the outside world through a Floating IP when used
in conjunction with Neutron DVR [0][1][2][3][4][5].
Although there are some fixes provided in the referenced material, the
current implementation still show issues and appearas to limit how we can
model a DVR deployment.
A approach to work around this is to create a separate non-distributed
network for hosting the load balancer VIP and connecting it to a FIP.
The payload- and loadbalancer- instances can stay in a distributed
network, only the VIP must be in a non-distributed network.
(although the actual hosting of said router can be on a compute host
acting as a "centralized" snat router in a DVR deployment.)
0: https://bit.ly/30LgX4T
1: https://bugs.launchpad.net/neutron/+bug/1583694
2: https://bugs.launchpad.net/neutron/+bug/1667877
3: https://review.opendev.org/#/c/437970/
4: https://review.opendev.org/#/c/437986/
5: https://review.opendev.org/#/c/466434/
"""
if not openstack.dvr_enabled():
logging.info('DVR not enabled, skip.')
return
keystone_session = openstack.get_overcloud_keystone_session()
neutron_client = openstack.get_neutron_session_client(
keystone_session)
resp = neutron_client.create_network(
{'network': {'name': 'private_lb_fip_network'}})
network = resp['network']
resp = neutron_client.create_subnet(
{
'subnets': [
{
'name': 'private_lb_fip_subnet',
'network_id': network['id'],
'ip_version': 4,
'cidr': '10.42.0.0/24',
},
],
})
subnet = resp['subnets'][0]
resp = neutron_client.create_router(
{
'router': {
'name': 'lb_fip_router',
'external_gateway_info': {
'network_id': openstack.get_net_uuid(
neutron_client, 'ext_net'),
},
'distributed': False,
},
})
router = resp['router']
neutron_client.add_interface_router(
router['id'], {'subnet_id': subnet['id']})