Dynamic routing services for OpenStack Neutron.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

372 lines
15 KiB

# Copyright (C) 2016 VA Linux Systems Japan K.K.
# Copyright (C) 2016 Fumihiko Kakuma <kakuma at valinux co jp>
# 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 collections
import threading
import time
import netaddr
from tempest.common import utils
from tempest import config
from neutron_tempest_plugin.api import base
from ryu.tests.integrated.common import docker_base as ctn_base
from neutron_dynamic_routing.tests.tempest import bgp_client
CONF = config.CONF
Scope = collections.namedtuple('Scope', 'name')
Pool = collections.namedtuple('Pool', 'name, prefixlen, prefixes')
Net = collections.namedtuple('Net', 'name, net, mask, cidr, router')
SubNet = collections.namedtuple('SubNet', 'name, cidr, mask')
Router = collections.namedtuple('Router', 'name, gw')
AS = collections.namedtuple('AS', 'asn, router_id, adv_net')
CHECKTIME = 180
CHECKTIME_INFO = 60
CHECKTIME_INT = 1
BRIDGE_TYPE = ctn_base.BRIDGE_TYPE_DOCKER
def _setup_client_args(auth_provider):
"""Set up ServiceClient arguments using config settings. """
service = CONF.network.catalog_type or 'network'
region = CONF.network.region or 'regionOne'
endpoint_type = CONF.network.endpoint_type
build_interval = CONF.network.build_interval
build_timeout = CONF.network.build_timeout
# The disable_ssl appears in identity
disable_ssl_certificate_validation = (
CONF.identity.disable_ssl_certificate_validation)
ca_certs = None
# Trace in debug section
trace_requests = CONF.debug.trace_requests
return [auth_provider, service, region, endpoint_type,
build_interval, build_timeout,
disable_ssl_certificate_validation, ca_certs,
trace_requests]
class BgpSpeakerScenarioTestJSONBase(base.BaseAdminNetworkTest):
def setUp(self):
self.addCleanup(self.net_resource_cleanup)
super(BgpSpeakerScenarioTestJSONBase, self).setUp()
@classmethod
def _setup_bgp_non_admin_client(cls):
mgr = cls.get_client_manager()
auth_provider = mgr.auth_provider
client_args = _setup_client_args(auth_provider)
cls.bgp_client = bgp_client.BgpSpeakerClientJSON(*client_args)
@classmethod
def _setup_bgp_admin_client(cls):
mgr = cls.get_client_manager(credential_type='admin')
auth_provider = mgr.auth_provider
client_args = _setup_client_args(auth_provider)
cls.bgp_adm_client = bgp_client.BgpSpeakerClientJSON(*client_args)
@classmethod
def resource_setup(cls):
super(BgpSpeakerScenarioTestJSONBase, cls).resource_setup()
if not utils.is_extension_enabled('bgp', 'network'):
msg = "BGP Speaker extension is not enabled."
raise cls.skipException(msg)
cls.images = []
cls.containers = []
cls.r_ass = []
cls.r_as_ip = []
cls.bridges = []
cls.admin_routerports = []
cls.admin_floatingips = []
cls.admin_routers = []
cls.admin_router_ip = []
cls.resource_setup_container()
cls._setup_bgp_admin_client()
cls._setup_bgp_non_admin_client()
cls.lock = threading.Lock()
@classmethod
def resource_cleanup(cls):
for ctn in cls.containers:
try:
ctn.stop()
except ctn_base.CommandError:
pass
ctn.remove()
for br in cls.bridges:
br.delete()
super(BgpSpeakerScenarioTestJSONBase, cls).resource_cleanup()
@classmethod
def get_subnet(self, start='10.10.1.0', end='10.10.255.0', step=256):
subnet_gen = netaddr.iter_iprange(start, end, step=step)
i = 1
while True:
with self.lock:
try:
yield (i, str(subnet_gen.next()))
except StopIteration:
subnet_gen = netaddr.iter_iprange(start, end, step=step)
yield (i, str(subnet_gen.next()))
i += 1
def net_resource_cleanup(self):
for floatingip in self.admin_floatingips:
self._try_delete_resource(self.admin_client.delete_floatingip,
floatingip['id'])
for routerport in self.admin_routerports:
self._try_delete_resource(
self.admin_client.remove_router_interface_with_subnet_id,
routerport['router_id'], routerport['subnet_id'])
for router in self.admin_routers:
self._try_delete_resource(self.admin_client.delete_router,
router['id'])
def create_bgp_speaker(self, auto_delete=True, **args):
data = {'bgp_speaker': args}
bgp_speaker = self.bgp_adm_client.create_bgp_speaker(data)
bgp_speaker_id = bgp_speaker['bgp_speaker']['id']
if auto_delete:
self.addCleanup(self.bgp_adm_client.delete_bgp_speaker,
bgp_speaker_id)
return bgp_speaker['bgp_speaker']
def delete_bgp_speaker(self, id):
return self.bgp_adm_client.delete_bgp_speaker(id)
def create_bgp_peer(self, auto_delete=True, **args):
bgp_peer = self.bgp_adm_client.create_bgp_peer({'bgp_peer': args})
bgp_peer_id = bgp_peer['bgp_peer']['id']
if auto_delete:
self.addCleanup(self.bgp_adm_client.delete_bgp_peer,
bgp_peer_id)
return bgp_peer['bgp_peer']
def delete_bgp_peer(self, id):
return self.bgp_adm_client.delete_bgp_peer(id)
def get_dragent_id(self):
agents = self.admin_client.list_agents(
agent_type="BGP dynamic routing agent")
self.assertTrue(agents['agents'][0]['alive'])
return agents['agents'][0]['id']
def add_bgp_speaker_to_dragent(self, agent_id, speaker_id):
self.bgp_adm_client.add_bgp_speaker_to_dragent(agent_id, speaker_id)
# tnets[[net1, subnet1, router1], [net2, subnet2, router2], ...]
def create_bgp_network(self, ip_version, scope,
exnet, expool, exsubnet,
tpool, tnets):
addr_scope = self.create_address_scope(scope.name,
ip_version=ip_version)
# external network
ext_net = self.create_shared_network(**{'router:external': True})
ext_net_id = ext_net['id']
ext_subnetpool = self.create_subnetpool(
expool.name,
is_admin=True,
default_prefixlen=expool.prefixlen,
address_scope_id=addr_scope['id'],
prefixes=expool.prefixes)
self.create_subnet(
{'id': ext_net_id},
cidr=netaddr.IPNetwork(exsubnet.cidr),
mask_bits=exsubnet.mask,
ip_version=ip_version,
client=self.admin_client,
subnetpool_id=ext_subnetpool['id'],
reserve_cidr=False)
# tenant network
tenant_subnetpool = self.create_subnetpool(
tpool.name,
default_prefixlen=tpool.prefixlen,
address_scope_id=addr_scope['id'],
prefixes=tpool.prefixes)
for tnet, tsubnet, router in tnets:
tenant_net = self.create_network()
tenant_subnet = self.create_subnet(
{'id': tenant_net['id']},
cidr=netaddr.IPNetwork(tsubnet.cidr),
mask_bits=tsubnet.mask,
ip_version=ip_version,
subnetpool_id=tenant_subnetpool['id'],
reserve_cidr=False)
# router
ext_gw_info = {'network_id': ext_net_id}
router_cr = self.admin_client.create_router(
router.name,
external_gateway_info=ext_gw_info)['router']
self.admin_routers.append(router_cr)
self.admin_client.add_router_interface_with_subnet_id(
router_cr['id'],
tenant_subnet['id'])
self.admin_routerports.append({'router_id': router_cr['id'],
'subnet_id': tenant_subnet['id']})
router = self.admin_client.show_router(router_cr['id'])['router']
fixed_ips = router['external_gateway_info']['external_fixed_ips']
self.admin_router_ip.append(fixed_ips[0]['ip_address'])
return ext_net_id
def create_and_add_peers_to_speaker(self, ext_net_id,
speaker_info, peer_infos,
auto_delete=True):
speaker = self.create_bgp_speaker(auto_delete=auto_delete,
**speaker_info)
speaker_id = speaker['id']
self.bgp_adm_client.add_bgp_gateway_network(speaker_id,
ext_net_id)
peer_ids = []
for peer_args in peer_infos:
peer = self.create_bgp_peer(auto_delete=auto_delete,
**peer_args)
peer_id = peer['id']
peer_ids.append(peer_id)
self.bgp_adm_client.add_bgp_peer_with_id(speaker_id,
peer_id)
return (speaker_id, peer_ids)
def get_remote_as_state(self, l_as, r_as,
expected_state,
init_state=ctn_base.BGP_FSM_IDLE,
checktime=CHECKTIME,
checktime_int=CHECKTIME_INT):
neighbor_state = init_state
for i in range(0, checktime):
neighbor_state = r_as.get_neighbor_state(l_as)
if neighbor_state == expected_state:
break
time.sleep(checktime_int)
return neighbor_state
def check_remote_as_state(self, l_as, r_as,
expected_state,
init_state=ctn_base.BGP_FSM_IDLE,
checktime=CHECKTIME,
checktime_int=CHECKTIME_INT):
neighbor_state = self.get_remote_as_state(l_as, r_as,
expected_state,
init_state=init_state,
checktime=checktime,
checktime_int=checktime_int)
self.assertEqual(neighbor_state, expected_state)
def get_remote_as_of_state_ok(self, l_as, r_ass,
expected_state,
init_state=ctn_base.BGP_FSM_IDLE,
checktime=CHECKTIME,
checktime_int=CHECKTIME_INT):
neighbor_state = init_state
ras_list = []
ras_max = len(r_ass)
for r_as in r_ass:
ras_list.append({'as': r_as, 'check': False})
ok_ras = []
for i in range(0, checktime):
for ras in ras_list:
if ras['check']:
continue
neighbor_state = ras['as'].get_neighbor_state(l_as)
if neighbor_state == expected_state:
ras['check'] = True
ok_ras.append(ras['as'])
if len(ok_ras) >= ras_max:
break
time.sleep(checktime_int)
return ok_ras
def check_multi_remote_as_state(self, l_as, r_ass,
expected_state,
init_state=ctn_base.BGP_FSM_IDLE,
checktime=CHECKTIME,
checktime_int=CHECKTIME_INT):
ok_ras = self.get_remote_as_of_state_ok(
l_as, r_ass,
expected_state,
init_state=init_state,
checktime=checktime,
checktime_int=checktime_int)
self.assertEqual(len(ok_ras), len(r_ass))
def get_remote_as_rib(self, r_as, prefix, rf, key, expected_item,
checktime=CHECKTIME_INFO,
checktime_int=CHECKTIME_INT):
item = None
for i in range(0, checktime):
rib = r_as.get_global_rib(prefix=prefix, rf=rf)
if rib and key in rib[0]:
if expected_item == rib[0][key]:
item = rib[0][key]
break
time.sleep(checktime_int)
return item
def check_remote_as_rib(self, r_as, prefix, rf, key, expected_item,
checktime=CHECKTIME_INFO,
checktime_int=CHECKTIME_INT):
item = self.get_remote_as_rib(r_as=r_as, prefix=prefix, rf=rf,
key=key, expected_item=expected_item,
checktime=checktime,
checktime_int=checktime_int)
self.assertEqual(expected_item, item)
def get_remote_as_of_rib_ok(self, r_ass, prefix, rf, key, expected_item,
checktime=CHECKTIME_INFO,
checktime_int=CHECKTIME_INT):
ras_list = []
ras_max = len(r_ass)
for r_as in r_ass:
ras_list.append({'as': r_as, 'check': False})
ok_ras = []
for i in range(0, checktime):
for ras in ras_list:
if ras['check']:
continue
rib = r_as.get_global_rib(prefix=prefix, rf=rf)
if rib and key in rib[0]:
if expected_item == rib[0][key]:
ras['check'] = True
ok_ras.append(ras['as'])
if len(ok_ras) >= ras_max:
break
time.sleep(checktime_int)
return ok_ras
def check_multi_remote_as_rib(self, r_ass, prefix, rf, key, expected_item,
checktime=CHECKTIME_INFO,
checktime_int=CHECKTIME_INT):
ok_ras = self.get_remote_as_of_rib_ok(
r_ass=r_ass, prefix=prefix, rf=rf,
key=key, expected_item=expected_item,
checktime=checktime,
checktime_int=checktime_int)
self.assertEqual(len(ok_ras), len(r_ass))
def get_next_hop(self, speaker_id, dest_addr):
routes = self.bgp_adm_client.get_bgp_advertised_routes(speaker_id)
next_hop = ''
for route in routes['advertised_routes']:
if route['destination'] == dest_addr:
next_hop = route['next_hop']
break
return next_hop