ovn-octavia-provider/ovn_octavia_provider/tests/functional/test_agent.py

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(TestOvnOctaviaProviderAgent, self).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())