neutron/neutron/tests/common/l3_test_common.py

408 lines
15 KiB
Python

# Copyright (c) 2015 OpenStack Foundation
#
# 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 copy
import netaddr
from neutron_lib import constants as lib_constants
from neutron_lib.services.qos import constants as qos_consts
from oslo_utils import uuidutils
from neutron.common import ipv6_utils
_uuid = uuidutils.generate_uuid
class FakeDev(object):
def __init__(self, name):
self.name = name
def get_ha_interface(ip='169.254.192.1', mac='12:34:56:78:2b:5d'):
subnet_id = _uuid()
return {'admin_state_up': True,
'device_id': _uuid(),
'device_owner': lib_constants.DEVICE_OWNER_ROUTER_HA_INTF,
'fixed_ips': [{'ip_address': ip,
'prefixlen': 18,
'subnet_id': subnet_id}],
'id': _uuid(),
'mac_address': mac,
'name': u'L3 HA Admin port 0',
'mtu': 1500,
'network_id': _uuid(),
'status': u'ACTIVE',
'subnets': [{'cidr': '169.254.192.0/18',
'gateway_ip': '169.254.255.254',
'id': subnet_id}],
'tenant_id': '',
'agent_id': _uuid(),
'agent_host': 'aaa',
'priority': 1}
def prepare_router_data(ip_version=lib_constants.IP_VERSION_4,
enable_snat=None, num_internal_ports=1,
enable_floating_ip=False, enable_ha=False,
extra_routes=False, dual_stack=False, enable_gw=True,
v6_ext_gw_with_sub=True,
snat_bound_fip=False,
enable_pf_floating_ip=False,
vrrp_id=None,
**kwargs):
fixed_ips = []
subnets = []
gateway_mac = kwargs.get('gateway_mac', 'ca:fe:de:ad:be:ee')
extra_subnets = []
for loop_version in (lib_constants.IP_VERSION_4,
lib_constants.IP_VERSION_6):
if (loop_version == lib_constants.IP_VERSION_4 and
(ip_version == lib_constants.IP_VERSION_4 or dual_stack)):
ip_address = kwargs.get('ip_address', '19.4.4.4')
prefixlen = 24
subnet_cidr = kwargs.get('subnet_cidr', '19.4.4.0/24')
gateway_ip = kwargs.get('gateway_ip', '19.4.4.1')
_extra_subnet = {'cidr': '9.4.5.0/24'}
elif (loop_version == lib_constants.IP_VERSION_6 and
(ip_version == lib_constants.IP_VERSION_6 or dual_stack) and
v6_ext_gw_with_sub):
ip_address = kwargs.get('ip_address', 'fd00::4')
prefixlen = 64
subnet_cidr = kwargs.get('subnet_cidr', 'fd00::/64')
gateway_ip = kwargs.get('gateway_ip', 'fd00::1')
_extra_subnet = {'cidr': 'fd01::/64'}
else:
continue
subnet_id = _uuid()
fixed_ips.append({'ip_address': ip_address,
'subnet_id': subnet_id,
'prefixlen': prefixlen})
subnets.append({'id': subnet_id,
'cidr': subnet_cidr,
'gateway_ip': gateway_ip})
extra_subnets.append(_extra_subnet)
if not fixed_ips and v6_ext_gw_with_sub:
raise ValueError("Invalid ip_version: %s" % ip_version)
router_id = _uuid()
ex_gw_port = {}
if enable_gw:
ex_gw_port = {'id': _uuid(),
'mac_address': gateway_mac,
'mtu': 1500,
'network_id': _uuid(),
'fixed_ips': fixed_ips,
'subnets': subnets,
'extra_subnets': extra_subnets}
external_gateway_info = {"qos_policy_id": kwargs.get('qos_policy_id')}
routes = []
if extra_routes:
routes = [{'destination': '8.8.8.0/24', 'nexthop': '19.4.4.4'}]
router = {
'id': router_id,
'distributed': False,
lib_constants.INTERFACE_KEY: [],
'routes': routes,
'gw_port': ex_gw_port,
'external_gateway_info': external_gateway_info}
router_fips = router.get(lib_constants.FLOATINGIP_KEY, [])
if enable_floating_ip:
fip = {'id': _uuid(),
'port_id': _uuid(),
'status': 'DOWN',
'floating_ip_address': '19.4.4.2',
'fixed_ip_address': '10.0.0.1'}
qos_policy_id = kwargs.get(qos_consts.QOS_POLICY_ID)
if qos_policy_id:
fip[qos_consts.QOS_POLICY_ID] = qos_policy_id
router_fips.append(fip)
if snat_bound_fip:
fip = {'id': _uuid(),
'port_id': _uuid(),
'status': 'DOWN',
'floating_ip_address': '19.4.4.3',
'fixed_ip_address': '10.0.0.2'}
qos_policy_id = kwargs.get(qos_consts.QOS_POLICY_ID)
if qos_policy_id:
fip[qos_consts.QOS_POLICY_ID] = qos_policy_id
router_fips.append(fip)
router[lib_constants.FLOATINGIP_KEY] = router_fips
pf_fips = []
if enable_pf_floating_ip:
fip = {'id': _uuid(),
'port_id': _uuid(),
'status': 'DOWN',
'floating_ip_address': '19.4.4.4',
'fixed_ip_address': '10.0.0.3'}
qos_policy_id = kwargs.get(qos_consts.QOS_POLICY_ID)
if qos_policy_id:
fip[qos_consts.QOS_POLICY_ID] = qos_policy_id
pf_fips.append(fip)
router['_pf_floatingips'] = pf_fips
router_append_interface(router, count=num_internal_ports,
ip_version=ip_version, dual_stack=dual_stack)
if enable_ha:
ha_port_ip = kwargs.get('ha_port_ip', '169.254.192.1')
ha_port_mac = kwargs.get('ha_port_mac', '12:34:56:78:2b:aa')
router['ha'] = True
router['ha_vr_id'] = vrrp_id or 1
router[lib_constants.HA_INTERFACE_KEY] = (
get_ha_interface(ip=ha_port_ip,
mac=ha_port_mac))
if enable_snat is not None:
router['enable_snat'] = enable_snat
return router
def get_subnet_id(port):
return port['fixed_ips'][0]['subnet_id']
def router_append_interface(router, count=1,
ip_version=lib_constants.IP_VERSION_4,
ra_mode=None, addr_mode=None, dual_stack=False,
same_port=False):
interfaces = router[lib_constants.INTERFACE_KEY]
current = sum(
[netaddr.IPNetwork(subnet['cidr']).version == ip_version
for p in interfaces for subnet in p['subnets']])
# If dual_stack=True, create IPv4 and IPv6 subnets on each port
# If same_port=True, create ip_version number of subnets on a single port
# Else create just an ip_version subnet on each port
if dual_stack:
ip_versions = [lib_constants.IP_VERSION_4, lib_constants.IP_VERSION_6]
elif same_port:
ip_versions = [ip_version] * count
count = 1
else:
ip_versions = [ip_version]
mac_address = netaddr.EUI('ca:fe:de:ad:be:ef')
mac_address.dialect = netaddr.mac_unix
for i in range(current, current + count):
fixed_ips = []
subnets = []
for loop_version in ip_versions:
if (loop_version == lib_constants.IP_VERSION_4 and
(ip_version == lib_constants.IP_VERSION_4 or dual_stack)):
ip_pool = '35.4.%i.4'
cidr_pool = '35.4.%i.0/24'
prefixlen = 24
gw_pool = '35.4.%i.1'
elif (loop_version == lib_constants.IP_VERSION_6 and
(ip_version == lib_constants.IP_VERSION_6 or dual_stack)):
ip_pool = 'fd01:%x:1::6'
cidr_pool = 'fd01:%x:1::/64'
prefixlen = 64
gw_pool = 'fd01:%x:1::1'
else:
continue
subnet_id = _uuid()
fixed_ips.append({'ip_address': ip_pool % i,
'subnet_id': subnet_id,
'prefixlen': prefixlen})
subnets.append({'id': subnet_id,
'cidr': cidr_pool % i,
'gateway_ip': gw_pool % i,
'ipv6_ra_mode': ra_mode,
'ipv6_address_mode': addr_mode})
if not fixed_ips:
raise ValueError("Invalid ip_version: %s" % ip_version)
interfaces.append(
{'id': _uuid(),
'mtu': 1500,
'network_id': _uuid(),
'admin_state_up': True,
'fixed_ips': fixed_ips,
'mac_address': str(mac_address),
'subnets': subnets})
mac_address.value += 1
def router_append_subnet(router, count=1,
ip_version=lib_constants.IP_VERSION_4,
ipv6_subnet_modes=None, interface_id=None,
dns_nameservers=None, network_mtu=0):
if ip_version == lib_constants.IP_VERSION_6:
subnet_mode_none = {'ra_mode': None, 'address_mode': None}
if not ipv6_subnet_modes:
ipv6_subnet_modes = [subnet_mode_none] * count
elif len(ipv6_subnet_modes) != count:
ipv6_subnet_modes.extend([subnet_mode_none for i in
range(len(ipv6_subnet_modes), count)])
if ip_version == lib_constants.IP_VERSION_4:
ip_pool = '35.4.%i.4'
cidr_pool = '35.4.%i.0/24'
prefixlen = 24
gw_pool = '35.4.%i.1'
elif ip_version == lib_constants.IP_VERSION_6:
ip_pool = 'fd01:%x::6'
cidr_pool = 'fd01:%x::/64'
prefixlen = 64
gw_pool = 'fd01:%x::1'
else:
raise ValueError("Invalid ip_version: %s" % ip_version)
interfaces = copy.deepcopy(router.get(lib_constants.INTERFACE_KEY, []))
if interface_id:
try:
interface = next(i for i in interfaces
if i['id'] == interface_id)
except StopIteration:
raise ValueError("interface_id not found")
fixed_ips, subnets = interface['fixed_ips'], interface['subnets']
else:
interface = None
fixed_ips, subnets = [], []
num_existing_subnets = len(subnets)
for i in range(count):
subnet_id = _uuid()
fixed_ips.append(
{'ip_address': ip_pool % (i + num_existing_subnets),
'subnet_id': subnet_id,
'prefixlen': prefixlen})
subnets.append(
{'id': subnet_id,
'cidr': cidr_pool % (i + num_existing_subnets),
'gateway_ip': gw_pool % (i + num_existing_subnets),
'dns_nameservers': dns_nameservers,
'ipv6_ra_mode': ipv6_subnet_modes[i]['ra_mode'],
'ipv6_address_mode': ipv6_subnet_modes[i]['address_mode']})
if interface:
# Update old interface
index = interfaces.index(interface)
interfaces[index].update({'fixed_ips': fixed_ips, 'subnets': subnets})
else:
# New interface appended to interfaces list
mac_address = netaddr.EUI('ca:fe:de:ad:be:ef')
mac_address.dialect = netaddr.mac_unix
interfaces.append(
{'id': _uuid(),
'mtu': network_mtu,
'network_id': _uuid(),
'admin_state_up': True,
'mac_address': str(mac_address),
'fixed_ips': fixed_ips,
'subnets': subnets})
router[lib_constants.INTERFACE_KEY] = interfaces
def router_append_pd_enabled_subnet(router, count=1, prefix=None):
if not prefix:
prefix = lib_constants.PROVISIONAL_IPV6_PD_PREFIX
interfaces = router[lib_constants.INTERFACE_KEY]
current = sum(netaddr.IPNetwork(subnet['cidr']).version == 6
for p in interfaces for subnet in p['subnets'])
mac_address = netaddr.EUI('ca:fe:de:ad:be:ef')
mac_address.dialect = netaddr.mac_unix
pd_intfs = []
for i in range(current, current + count):
subnet_id = _uuid()
intf = {'id': _uuid(),
'mtu': 1500,
'network_id': _uuid(),
'admin_state_up': True,
'fixed_ips': [{'ip_address': '::1',
'prefixlen': 64,
'subnet_id': subnet_id}],
'mac_address': str(mac_address),
'subnets': [{'id': subnet_id,
'cidr': prefix,
'gateway_ip': '::1',
'ipv6_ra_mode': lib_constants.IPV6_SLAAC,
'subnetpool_id': lib_constants.IPV6_PD_POOL_ID}]}
interfaces.append(intf)
pd_intfs.append(intf)
mac_address.value += 1
def get_unassigned_pd_interfaces(router):
pd_intfs = []
for intf in router[lib_constants.INTERFACE_KEY]:
for subnet in intf['subnets']:
if (ipv6_utils.is_ipv6_pd_enabled(subnet) and
subnet['cidr'] ==
lib_constants.PROVISIONAL_IPV6_PD_PREFIX):
pd_intfs.append(intf)
return pd_intfs
def get_assigned_pd_interfaces(router):
pd_intfs = []
for intf in router[lib_constants.INTERFACE_KEY]:
for subnet in intf['subnets']:
if (ipv6_utils.is_ipv6_pd_enabled(subnet) and
subnet['cidr'] !=
lib_constants.PROVISIONAL_IPV6_PD_PREFIX):
pd_intfs.append(intf)
return pd_intfs
def assign_prefix_for_pd_interfaces(router):
pd_intfs = []
for ifno, intf in enumerate(router[lib_constants.INTERFACE_KEY]):
for subnet in intf['subnets']:
if (ipv6_utils.is_ipv6_pd_enabled(subnet) and
subnet['cidr'] ==
lib_constants.PROVISIONAL_IPV6_PD_PREFIX):
subnet['cidr'] = "2001:db8:%d::/64" % ifno
pd_intfs.append(intf)
return pd_intfs
def prepare_ext_gw_test(context, ri, dual_stack=False):
subnet_id = _uuid()
fixed_ips = [{'subnet_id': subnet_id,
'ip_address': '20.0.0.30',
'prefixlen': 24}]
subnets = [{'id': subnet_id,
'cidr': '20.0.0.0/24',
'gateway_ip': '20.0.0.1'}]
if dual_stack:
subnet_id_v6 = _uuid()
fixed_ips.append({'subnet_id': subnet_id_v6,
'ip_address': '2001:192:168:100::2',
'prefixlen': 64})
subnets.append({'id': subnet_id_v6,
'cidr': '2001:192:168:100::/64',
'gateway_ip': '2001:192:168:100::1'})
ex_gw_port = {'fixed_ips': fixed_ips,
'subnets': subnets,
'extra_subnets': [{'cidr': '172.16.0.0/24'}],
'id': _uuid(),
'mtu': 1500,
'network_id': _uuid(),
'mac_address': 'ca:fe:de:ad:be:ef'}
interface_name = ri.get_external_device_name(ex_gw_port['id'])
context.device_exists.return_value = True
return interface_name, ex_gw_port