Correlate address scope with network
With address scope being enabled, networks now are in one ipv4 address scope and one ipv6 address scope. This patch adds derived attributes to the network as part of the address scopes extension that will show related address scopes when viewing a network through the API. APIImpact Change-Id: Ib1657636033ad2c0009d50ebe7c5ae4f72f6b175 Closes-Bug: #1547380
This commit is contained in:
parent
643a53da06
commit
635581912f
@ -18,6 +18,8 @@ from sqlalchemy.orm import exc
|
||||
|
||||
from neutron._i18n import _
|
||||
from neutron.api.v2 import attributes as attr
|
||||
from neutron.common import constants
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import model_base
|
||||
from neutron.extensions import address_scope as ext_address_scope
|
||||
|
||||
@ -124,3 +126,22 @@ class AddressScopeDbMixin(ext_address_scope.AddressScopePluginBase):
|
||||
raise ext_address_scope.AddressScopeInUse(address_scope_id=id)
|
||||
address_scope = self._get_address_scope(context, id)
|
||||
context.session.delete(address_scope)
|
||||
|
||||
def _extend_network_dict_address_scope(self, network_res, network_db):
|
||||
network_res[ext_address_scope.IPV4_ADDRESS_SCOPE] = None
|
||||
network_res[ext_address_scope.IPV6_ADDRESS_SCOPE] = None
|
||||
subnetpools = {subnet.subnetpool for subnet in network_db.subnets
|
||||
if subnet.subnetpool}
|
||||
for subnetpool in subnetpools:
|
||||
# A network will be constrained to only one subnetpool per address
|
||||
# family. Retrieve the address scope of subnetpools as the address
|
||||
# scopes of network.
|
||||
as_id = subnetpool[ext_address_scope.ADDRESS_SCOPE_ID]
|
||||
if subnetpool['ip_version'] == constants.IP_VERSION_4:
|
||||
network_res[ext_address_scope.IPV4_ADDRESS_SCOPE] = as_id
|
||||
if subnetpool['ip_version'] == constants.IP_VERSION_6:
|
||||
network_res[ext_address_scope.IPV6_ADDRESS_SCOPE] = as_id
|
||||
return network_res
|
||||
|
||||
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
|
||||
attr.NETWORKS, ['_extend_network_dict_address_scope'])
|
||||
|
@ -183,6 +183,13 @@ class Subnet(model_base.HasStandardAttributes, model_base.BASEV2,
|
||||
name = sa.Column(sa.String(attr.NAME_MAX_LEN))
|
||||
network_id = sa.Column(sa.String(36), sa.ForeignKey('networks.id'))
|
||||
subnetpool_id = sa.Column(sa.String(36), index=True)
|
||||
# NOTE: Explicitly specify join conditions for the relationship because
|
||||
# subnetpool_id in subnet might be 'prefix_delegation' when the IPv6 Prefix
|
||||
# Delegation is enabled
|
||||
subnetpool = orm.relationship(
|
||||
'SubnetPool', lazy='joined',
|
||||
foreign_keys='Subnet.subnetpool_id',
|
||||
primaryjoin='Subnet.subnetpool_id==SubnetPool.id')
|
||||
ip_version = sa.Column(sa.Integer, nullable=False)
|
||||
cidr = sa.Column(sa.String(64), nullable=False)
|
||||
gateway_ip = sa.Column(sa.String(64))
|
||||
|
@ -26,6 +26,8 @@ from neutron import manager
|
||||
ADDRESS_SCOPE = 'address_scope'
|
||||
ADDRESS_SCOPES = '%ss' % ADDRESS_SCOPE
|
||||
ADDRESS_SCOPE_ID = 'address_scope_id'
|
||||
IPV4_ADDRESS_SCOPE = 'ipv4_%s' % ADDRESS_SCOPE
|
||||
IPV6_ADDRESS_SCOPE = 'ipv6_%s' % ADDRESS_SCOPE
|
||||
|
||||
# Attribute Map
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
@ -63,6 +65,14 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'default': attr.ATTR_NOT_SPECIFIED,
|
||||
'validate': {'type:uuid_or_none': None},
|
||||
'is_visible': True}
|
||||
},
|
||||
attr.NETWORKS: {
|
||||
IPV4_ADDRESS_SCOPE: {'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True},
|
||||
IPV6_ADDRESS_SCOPE: {'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,6 +430,52 @@ class TestSubnetPoolsWithAddressScopes(AddressScopeTestCase):
|
||||
def test_not_update_subnetpool_address_scope_not_notify(self):
|
||||
self._test_update_subnetpool_address_scope_notify(False)
|
||||
|
||||
def test_network_create_contain_address_scope_attr(self):
|
||||
with self.network() as network:
|
||||
result = self._show('networks', network['network']['id'])
|
||||
keys = [ext_address_scope.IPV4_ADDRESS_SCOPE,
|
||||
ext_address_scope.IPV6_ADDRESS_SCOPE]
|
||||
for k in keys:
|
||||
# Correlated address scopes should initially be None
|
||||
self.assertIsNone(result['network'][k])
|
||||
|
||||
def test_correlate_network_with_address_scope(self):
|
||||
with self.address_scope(name='v4-as') as v4_addr_scope, \
|
||||
self.address_scope(
|
||||
name='v6-as',
|
||||
ip_version=constants.IP_VERSION_6) as v6_addr_scope, \
|
||||
self.network() as network:
|
||||
v4_as_id = v4_addr_scope['address_scope']['id']
|
||||
subnet = netaddr.IPNetwork('10.10.10.0/24')
|
||||
v4_subnetpool = self._test_create_subnetpool(
|
||||
[subnet.cidr], name='v4-sp',
|
||||
min_prefixlen='24', address_scope_id=v4_as_id)
|
||||
v4_subnetpool_id = v4_subnetpool['subnetpool']['id']
|
||||
v6_as_id = v6_addr_scope['address_scope']['id']
|
||||
subnet = netaddr.IPNetwork('fd5c:6ee1:c7ae::/64')
|
||||
v6_subnetpool = self._test_create_subnetpool(
|
||||
[subnet.cidr], name='v6-sp',
|
||||
min_prefixlen='64', address_scope_id=v6_as_id)
|
||||
v6_subnetpool_id = v6_subnetpool['subnetpool']['id']
|
||||
data = {'subnet': {
|
||||
'network_id': network['network']['id'],
|
||||
'subnetpool_id': v4_subnetpool_id,
|
||||
'ip_version': 4,
|
||||
'tenant_id': network['network']['tenant_id']}}
|
||||
req = self.new_create_request('subnets', data)
|
||||
self.deserialize(self.fmt, req.get_response(self.api))
|
||||
data['subnet']['subnetpool_id'] = v6_subnetpool_id
|
||||
data['subnet']['ip_version'] = 6
|
||||
req = self.new_create_request('subnets', data)
|
||||
self.deserialize(self.fmt, req.get_response(self.api))
|
||||
result = self._show('networks', network['network']['id'])
|
||||
self.assertEqual(
|
||||
v4_as_id,
|
||||
result['network'][ext_address_scope.IPV4_ADDRESS_SCOPE])
|
||||
self.assertEqual(
|
||||
v6_as_id,
|
||||
result['network'][ext_address_scope.IPV6_ADDRESS_SCOPE])
|
||||
|
||||
def test_delete_address_scope_in_use(self):
|
||||
with self.address_scope(name='foo-address-scope') as addr_scope:
|
||||
address_scope_id = addr_scope['address_scope']['id']
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- Add derived attributes to the network to tell users which address scopes
|
||||
the network is in.
|
Loading…
Reference in New Issue
Block a user