L3-Policy mapping to Address Scope & Subnetpool

Starting in the Mitaka release Neutron defines and supports the use of Address
Scopes. Subnet-pools were defined in the earlier Kilo release and can now be
used within Address Scopes. The notion of an address scope has existed in GBP
in the form of L3-Policy. The GBP L3-Policy manages the address-scope and
subnet-pools with its own home-grown implementation. It would be preferable to
leverage the Neutron address-scopes and subnet-pools instead.

Change-Id: I9e4335073dc8ec0cb85db909560c49e0dddefe82
Defines: blueprint address-scope-mapping
This commit is contained in:
Sumit Naiksatam 2016-07-18 14:22:35 -07:00
parent 6a51744761
commit 20ecc759fc
1 changed files with 322 additions and 0 deletions

View File

@ -0,0 +1,322 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
===================================================
L3 Policy Mapping to Address-Scope and Subnet-Pools
===================================================
Launchpad blueprint:
https://blueprints.launchpad.net/group-based-policy/+spec/address-scope-mapping
Problem description
===================
Starting from the Mitaka release, Neutron defines and supports the use of
Address Scopes [#]_. Subnetpools were defined in the earlier Kilo release and
can now be used within Address Scopes. The notion of an address scope has
existed in GBP in the form of L3-Policy. The GBP L3-Policy manages the address
scope and subnet pools with its own home-grown implementation. It would be
preferable to leverage the Neutron Address Scope and Subnetpool instead.
Proposed change
===============
The current mapping of GBP l3_policy to a list of Neutron routers will be
augmented with the mapping to a Neutron address_scope (one each for IPv4 and
IPv6) and subnetpools. This spec attempts to lay the foundation for the use
of IPv6, and dual-stack (both IPv4 and IPv6) in the l3_policy. The API and DB
model constructs to support this are being addressed in this spec. The details
for IPv6 implementation are not addresed in this spec and will be laid out in
a forthcoming complementary spec.
For each address family (IPv4 and/or IPv6) the l3_policy supports, there will
be a 1-1 mapping between GBP l3_policy and the Neutron address_scope,
and 1-many mapping between GBP l3_policy and Neutron subnetpools. The 1-many
mapping allows for use cases where the l3_policy (and address_scope) is shared
across tenants, while the subnetpool is created per tenant and not shared.
The subnetpools that are explicitly associated with the l3_policy, need to
belong to the same address_scope that is associated with that l3_policy. GBP
will allocate subnets only from the subnetpools that are associated with the
corresponding l3_policy. The list of subnets associated with the l3_policy can
be updated by adding or removing subnetpools (subnetpools which are currently
being used cannot be removed).
Let's consider the various combinations that are possible based on the choice
of implicit and explicit arguments.
#. A l3_policy is created with an ip_pool, ip_version, and
subnet_prefix_length but no address_scope or subnetpool(s) are provided. In
this case an address_scope with the address family of the ip_version will be
created implicitly, and a subnetpool with the ip_pool CIDR will be created
in that address_scope. If the l3_policy is shared, the implcitily create
address_scope and subnetpool will also be shared. The ip_version of the
l3_policy will be used for the address_scope and the subnetpool. The
default_prefixlen, will be set to the subnet_prefix_length of the l3_policy.
(The min_prefixlen, and max_prefixlen of the subnetpool will default to 8
and 32 as defined in Neutron.)
#. A l3_policy is created with an ip_pool, ip_version, subnet_prefix_length,
and address_scope, but no subnetpools are provided. In this case the
ip_version of the l3_policy is ignored, and the subnetpool is created in
this address_scope as before. If both, v4 and v6, address_scopes are
provided, a subnetpool will be created for each family. If a subnetpool
already exists in this address_scope, and overlaps with the CIDR of the
ip_pool, an exception will be raised.
#. A l3_policy is created with an address_scope, and subnetpool(s). Since the
ip_version is already defined for the address_scope and the CIDR and prefix
lengths are defined for the subnetpool(s), the ip_version, ip_pool and
subnet_prefix_length of the l3_policy will be ignored if provided.
#. A l3_policy is created with one or more subnetpools. The address_scope
associated with the subnetpool(s) is associated with the l3_policy. If
no address_scope is associated with the subnetpool(s), an exception will
be raised. Similarly, it would not be valid to change the address_scope
(or unset it) for a subnetpool associated with a l3_policy. An enforcement
mechanism, most likely in the form of a Neutron mechanism driver that
prevents such invalid configuration, will be needed.
In all of the above cases, if subnetpools are associated with an address_scope
that is associated with a l3_policy, they will be considered for subnet
allocation only if they are explicitly associated with the l3_policy.
A minor variation of all the above cases is the one where either or all of
ip_pool, ip_version, and subnet_prefix_length are not provided. In such cases
the GBP defaults for these attributes will be used (but overridden by the
corresponding attributes in the address_scope and subnetpools if any of those
are explicitly provided).
In the cases where address_scope is being explicitly provided (either directly
or via its association to subnetpools), the shared attribute of the
address_scope will be validated for consistency with the shared attribute of
the l3_policy during the creation of the l3_policy. If they are inconsistent,
an exception will be raised, and l3_policy creation will fail. If the shared
attribute of the l3_policy is subsequently updated, the shared attribute of the
address_scope and the subnetpool will be updated if the address_scope and
subnetpool was implicitly created by GBP.
It should be noted that the ip_pool, subnet_prefix_length, and ip_version
attributes of the l3_policy may only have effect at the l3_policy creation
time. In the body of response for GET l3_policy call, the ip_pool will be set
to a comma separated string consisting of a list of CIDRs corresponding to each
subnetpool currently present in the address_scope. To preserve API backward
compatibility (i.e. to not immediately break existing clients and integration
tests), the subnet_prefix_length and ip_version will be set to the
corresponding subnet_prefix_length and ip_version when only one CIDR is
present. If more than one CIDR is present, these will be set to null. In the
case where multiple CIDRs are present, more details like the prefix length of
the subnets that are drawn from the subnetpools corresponding to these CIDRs
can be obtained by navigating the resource relationship from l3_policy to
address_scope to subnetpool.
Data model impact
-----------------
The mapping for the l3_policy will be modeled in the DB as follows:
::
class L3PolicySubnetpoolAssociation(model_base.BASEV2):
"""Models the 1 to many relation between L3Policies and Subnetpools."""
__tablename__ = 'gp_l3_policy_subnetpool_associations'
l3_policy_id = sa.Column(sa.String(36), sa.ForeignKey('gp_l3_policies.id'),
primary_key=True)
subnetpool_id = sa.Column(sa.String(36), sa.ForeignKey('subnetpools.id'),
primary_key=True)
class L3PolicyMapping(gpdb.L3Policy):
"""Mapping of L3Policy to set of Neutron Routers."""
__table_args__ = {'extend_existing': True}
__mapper_args__ = {'polymorphic_identity': 'mapping'}
address_scope_v4_id = sa.Column(
sa.String(36), sa.ForeignKey('address_scopes.id'), unique=True)
address_scope_v6_id = sa.Column(
sa.String(36), sa.ForeignKey('address_scopes.id'), unique=True)
subnetpools = orm.relationship(L3PolicySubnetpoolAssociation,
cascade='all', lazy="joined")
routers = orm.relationship(L3PolicyRouterAssociation,
cascade='all', lazy="joined")
Note that address_scope_id and subnetpools are not nullable. It is either
created implicitly or provided explicitly, but is always required. This is a
backward incompatible DB change and a script will be provided to migrate data
from existing deployments to this new structure. The script will essentially
create an address_scope and subnetpool for each existing l3_policy.
In addition, additional tables will be added to track the Neutron address_scope
and subnetpool resources created by GBP.
::
class OwnedAddressScope(model_base.BASEV2):
"""An Address Scope owned by the resource_mapping driver."""
__tablename__ = 'gpm_owned_address_scopes'
address_scope_id = sa.Column(sa.String(36),
sa.ForeignKey('address_scopes.id',
ondelete='CASCADE'),
nullable=False, primary_key=True)
class OwnedSubnetpool(model_base.BASEV2):
"""A Subnetpool owned by the resource_mapping driver."""
__tablename__ = 'gpm_owned_subnetpools'
subnetpool_id = sa.Column(sa.String(36),
sa.ForeignKey('subnetpools.id',
ondelete='CASCADE'),
nullable=False, primary_key=True)
REST API impact
---------------
This is how the udpated l3_Policy mapping would look like in terms of the mapping
extension definition
::
gp.L3_POLICIES: {
'address_scope_v4_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:uuid_or_none': None},
'is_visible': True, 'default': None},
'address_scope_v6_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:uuid_or_none': None},
'is_visible': True, 'default': None},
'subnetpools_v4': {'allow_post': True, 'allow_put': True,
'validate': {'type:uuid_list': None},
'is_visible': True, 'default': None},
'subnetpools_v6': {'allow_post': True, 'allow_put': True,
'validate': {'type:uuid_list': None},
'is_visible': True, 'default': None},
'routers': {'allow_post': True, 'allow_put': True,
'validate': {'type:uuid_list': None},
'convert_to': attr.convert_none_to_empty_list,
'is_visible': True, 'default': None},
},
Security impact
---------------
None
Notifications impact
--------------------
None
Other end user impact
---------------------
The l3_policy creation workflow has optional address_scope and subnetpools
arguments.This new workflow will be reflected in all clients and UI.
Performance impact
------------------
Better performance is expected on account of the change in the strategy to
allocate subnets that comes with the subnetpool resoure use.
Other deployer impact
---------------------
Deployers need to be aware of the new mapping, both, from an API usage
perspective, and also from debugging and troubleshooting.
Developer impact
----------------
The l3_policy Mapping API changes as indicated before.
Community impact
----------------
Better mapping between GBP and Neutron.
Alternatives
------------
Existing implementation
Implementation
==============
GBP service side implementation will cover updates to the API, DB, implicit,
and resource mapping drivers.
Client will be updated to return the mapped attributes. Updates to UI and Heat
will also be performed as follow up patches.
Assignee(s)
-----------
snaiksat + GBP team
Work items
----------
API, DB, and driver layer updates to GBP Resources.
Dependencies
============
None
Testing
=======
Relevant UTs will be added.
Tempest Tests
-------------
None
Functional Tests
----------------
The exisiting functional tests should cover that there are no regressions.
Some changes might be required to test that the mapped Neutron resources are
created and deleted.
API Tests
---------
UTs
Documentation impact
====================
User Documentation
------------------
Developer Documentation
-----------------------
Devref document will be added.
References
==========
.. [#] http://docs.openstack.org/developer/neutron/devref/address_scopes.html