246 lines
9.9 KiB
Python
246 lines
9.9 KiB
Python
# Copyright 2018 Red Hat, Inc.
|
|
# 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 atexit
|
|
import multiprocessing as mp
|
|
|
|
from neutron.common import utils as n_utils
|
|
|
|
from ovn_octavia_provider import agent as ovn_agent
|
|
from ovn_octavia_provider.common import constants as ovn_const
|
|
from ovn_octavia_provider import event as ovn_event
|
|
from ovn_octavia_provider import helper as ovn_helper
|
|
from ovn_octavia_provider.ovsdb import impl_idl_ovn
|
|
from ovn_octavia_provider.tests.functional import base as ovn_base
|
|
|
|
|
|
class TestOvnOctaviaProviderAgent(ovn_base.TestOvnOctaviaBase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self._initialize_ovn_da()
|
|
|
|
def _initialize_ovn_da(self):
|
|
# NOTE(mjozefcz): In theory this is separate process
|
|
# with IDL running, but to make it easier for now
|
|
# we can initialize this IDL here instead spawning
|
|
# another process.
|
|
da_helper = ovn_helper.OvnProviderHelper()
|
|
events = [ovn_event.LogicalRouterPortEvent(da_helper),
|
|
ovn_event.LogicalSwitchPortUpdateEvent(da_helper)]
|
|
ovn_nb_idl_for_events = impl_idl_ovn.OvnNbIdlForLb(
|
|
event_lock_name='func_test')
|
|
ovn_nb_idl_for_events.notify_handler.watch_events(events)
|
|
ovn_nb_idl_for_events.start()
|
|
atexit.register(da_helper.shutdown)
|
|
|
|
def _test_lrp_event_handler(self, cascade=False):
|
|
# Create Network N1 on router R1 and LBA on N1
|
|
lba_data = self._create_load_balancer_and_validate(
|
|
{'vip_network': 'N1',
|
|
'cidr': '10.0.0.0/24'})
|
|
router_id = lba_data[ovn_const.LB_EXT_IDS_LR_REF_KEY][
|
|
len(ovn_const.LR_REF_KEY_HEADER):]
|
|
# Create Network N2, connect it to R1
|
|
nw_info = self._create_net("N2", "10.0.1.0/24", router_id)
|
|
|
|
# Check if LBA exists in N2 LS
|
|
n_utils.wait_until_true(
|
|
lambda: self._is_lb_associated_to_ls(
|
|
lba_data['model'].loadbalancer_id,
|
|
ovn_const.LR_REF_KEY_HEADER + nw_info[0]),
|
|
timeout=10)
|
|
|
|
# Create Network N3
|
|
lbb_data = self._create_load_balancer_and_validate(
|
|
{'vip_network': 'N3',
|
|
'cidr': '10.0.2.0/24'}, create_router=False, multiple_lb=True)
|
|
# Add N3 to R1
|
|
self.l3_plugin.add_router_interface(
|
|
self.context, lba_data[
|
|
ovn_const.LB_EXT_IDS_LR_REF_KEY][
|
|
len(ovn_const.LR_REF_KEY_HEADER):],
|
|
{'subnet_id': lbb_data['vip_net_info'][1]})
|
|
|
|
# Check LBB exists on R1
|
|
n_utils.wait_until_true(
|
|
lambda: self._is_lb_associated_to_lr(
|
|
lbb_data['model'].loadbalancer_id,
|
|
lba_data[ovn_const.LB_EXT_IDS_LR_REF_KEY]),
|
|
timeout=10)
|
|
# Check LBA connected to N3
|
|
n_utils.wait_until_true(
|
|
lambda: self._is_lb_associated_to_ls(
|
|
lba_data['model'].loadbalancer_id,
|
|
ovn_const.LR_REF_KEY_HEADER + lbb_data['vip_net_info'][0]),
|
|
timeout=10)
|
|
# Check LBB connected to N1
|
|
n_utils.wait_until_true(
|
|
lambda: self._is_lb_associated_to_ls(
|
|
lbb_data['model'].loadbalancer_id,
|
|
ovn_const.LR_REF_KEY_HEADER + lba_data['vip_net_info'][0]),
|
|
timeout=10)
|
|
# Check LBB connected to N2
|
|
n_utils.wait_until_true(
|
|
lambda: self._is_lb_associated_to_ls(
|
|
lbb_data['model'].loadbalancer_id,
|
|
ovn_const.LR_REF_KEY_HEADER + nw_info[0]),
|
|
timeout=10)
|
|
|
|
lbb_id = lbb_data['model'].loadbalancer_id
|
|
if not cascade:
|
|
# N3 removed from R1
|
|
self.l3_plugin.remove_router_interface(
|
|
self.context, lba_data[
|
|
ovn_const.LB_EXT_IDS_LR_REF_KEY][
|
|
len(ovn_const.LR_REF_KEY_HEADER):],
|
|
{'subnet_id': lbb_data['vip_net_info'][1]})
|
|
else:
|
|
# Delete LBB Cascade
|
|
self._delete_load_balancer_and_validate(lbb_data, cascade=True,
|
|
multiple_lb=True)
|
|
|
|
# Check LBB doesn't exists on R1
|
|
n_utils.wait_until_true(
|
|
lambda: not self._is_lb_associated_to_lr(
|
|
lbb_id, lba_data[ovn_const.LB_EXT_IDS_LR_REF_KEY]),
|
|
timeout=10)
|
|
# Check LBB not connected to N1
|
|
n_utils.wait_until_true(
|
|
lambda: not self._is_lb_associated_to_ls(
|
|
lbb_id,
|
|
ovn_const.LR_REF_KEY_HEADER + lba_data['vip_net_info'][0]),
|
|
timeout=10)
|
|
# Check LBB not connected to N2
|
|
n_utils.wait_until_true(
|
|
lambda: not self._is_lb_associated_to_ls(
|
|
lbb_id, ovn_const.LR_REF_KEY_HEADER + nw_info[0]),
|
|
timeout=10)
|
|
|
|
def test_lrp_event_handler_with_interface_delete(self):
|
|
self._test_lrp_event_handler()
|
|
|
|
def test_lrp_event_handler_with_loadbalancer_cascade_delete(self):
|
|
self._test_lrp_event_handler(cascade=True)
|
|
|
|
def test_lrp_event_handler_lrp_with_external_gateway(self):
|
|
# Create Network N1 on router R1 and LBA on N1
|
|
lba_data = self._create_load_balancer_and_validate(
|
|
{'vip_network': 'N1',
|
|
'cidr': '10.0.0.0/24'})
|
|
router_id = lba_data[ovn_const.LB_EXT_IDS_LR_REF_KEY][
|
|
len(ovn_const.LR_REF_KEY_HEADER):]
|
|
|
|
# Create provider network N2, connect it to R1
|
|
provider_net, provider_subnet = self._create_provider_network()
|
|
self.l3_plugin.update_router(
|
|
self.context,
|
|
router_id,
|
|
{'router': {
|
|
'id': router_id,
|
|
'external_gateway_info': {
|
|
'enable_snat': True,
|
|
'network_id': provider_net['network']['id'],
|
|
'external_fixed_ips': [
|
|
{'ip_address': '100.0.0.2',
|
|
'subnet_id': provider_subnet['subnet']['id']}]}}})
|
|
|
|
# Check if LBA doesn't exist in provider network LS
|
|
n_utils.wait_until_true(
|
|
lambda: not self._is_lb_associated_to_ls(
|
|
lba_data['model'].loadbalancer_id,
|
|
ovn_const.LR_REF_KEY_HEADER + provider_net['network']['id']),
|
|
timeout=10)
|
|
|
|
def test_fip_on_lb_vip(self):
|
|
"""This test checks if FIP on LB VIP is configured.
|
|
|
|
This test validates if Load_Balancer VIP field
|
|
consist Floating IP address that is configured
|
|
on LB VIP port.
|
|
"""
|
|
# Create LB
|
|
lb_data = self._create_load_balancer_and_validate(
|
|
{'vip_network': 'vip_network',
|
|
'cidr': '10.0.0.0/24'})
|
|
# Create a pool
|
|
self._create_pool_and_validate(lb_data, "p1")
|
|
pool_id = lb_data['pools'][0].pool_id
|
|
# Create listener
|
|
self._create_listener_and_validate(lb_data, pool_id, 80)
|
|
# Create Member-1 and associate it with lb_data
|
|
self._create_member_and_validate(
|
|
lb_data, pool_id, lb_data['vip_net_info'][1],
|
|
lb_data['vip_net_info'][0], '10.0.0.10')
|
|
|
|
# Create provider network.
|
|
e1, e1_s1 = self._create_provider_network()
|
|
|
|
# Configure external_gateway for router
|
|
router_id = lb_data['lr_ref'][8::]
|
|
self.l3_plugin.update_router(
|
|
self.context,
|
|
router_id,
|
|
{'router': {
|
|
'id': router_id,
|
|
'external_gateway_info': {
|
|
'enable_snat': True,
|
|
'network_id': e1['network']['id'],
|
|
'external_fixed_ips': [
|
|
{'ip_address': '100.0.0.2',
|
|
'subnet_id': e1_s1['subnet']['id']}]}}})
|
|
|
|
# Create floating IP on LB VIP port
|
|
vip_port_id = lb_data['model'].vip_port_id
|
|
vip_port = self.core_plugin.get_ports(
|
|
self.context, filters={'id': [vip_port_id]})[0]
|
|
self.l3_plugin.create_floatingip(
|
|
self.context, {'floatingip': {
|
|
'tenant_id': self._tenant_id,
|
|
'floating_network_id': e1['network']['id'],
|
|
'subnet_id': None,
|
|
'floating_ip_address': '100.0.0.20',
|
|
'port_id': vip_port['id']}})
|
|
|
|
# Validate if FIP is stored as VIP in LB
|
|
lbs = self._get_loadbalancers()
|
|
expected_vips = {
|
|
'%s:80' % vip_port['fixed_ips'][0]['ip_address']: '10.0.0.10:80',
|
|
'100.0.0.20:80': '10.0.0.10:80'}
|
|
self.assertDictEqual(expected_vips,
|
|
lbs[0].get('vips'))
|
|
|
|
provider_net = 'neutron-%s' % e1['network']['id']
|
|
tenant_net = 'neutron-%s' % lb_data['model'].vip_network_id
|
|
for ls in self.nb_api.tables['Logical_Switch'].rows.values():
|
|
if ls.name == tenant_net:
|
|
# Make sure that LB1 is added to tenant network
|
|
self.assertIn(
|
|
lb_data['model'].loadbalancer_id,
|
|
[lb.name for lb in ls.load_balancer])
|
|
elif ls.name == provider_net:
|
|
# Make sure that LB1 is not added to provider net - e1 LS
|
|
self.assertListEqual([], ls.load_balancer)
|
|
|
|
def test_agent_exit(self):
|
|
exit_event = mp.Event()
|
|
agent = mp.Process(target=ovn_agent.OvnProviderAgent,
|
|
args=[exit_event])
|
|
agent.start()
|
|
self.assertTrue(agent.is_alive())
|
|
exit_event.set()
|
|
agent.join()
|
|
self.assertFalse(agent.is_alive())
|