You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
391 lines
15 KiB
Python
391 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 six import moves
|
|
|
|
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,
|
|
**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
|
|
|
|
router_append_interface(router, count=num_internal_ports,
|
|
ip_version=ip_version, dual_stack=dual_stack)
|
|
if enable_ha:
|
|
router['ha'] = True
|
|
router['ha_vr_id'] = 1
|
|
router[lib_constants.HA_INTERFACE_KEY] = (get_ha_interface())
|
|
|
|
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
|
|
moves.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 moves.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
|