Dual-stack L3-Policy mapping
The initial spec for address scope and subnetpool support mentioned support for dual-stack. This commit extends the existing spec to define that support. Change-Id: I0966d200c75c1d571a15687062020528e97648da Partially-implements: blueprint address-scope-mapping
This commit is contained in:
parent
449643f905
commit
6134fb3ffc
@ -30,50 +30,104 @@ Proposed change
|
|||||||
The current mapping of GBP l3_policy to a list of Neutron routers will be
|
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
|
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
|
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
|
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
|
model constructs to support this are addressed in this spec.
|
||||||
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
|
The ip_version attribute of GBP's l3_policy is extended to allow specifying
|
||||||
be a 1-1 mapping between GBP l3_policy and the Neutron address_scope,
|
dual-stack support. Currently allowed values for ip_version are 4 for IPv4
|
||||||
and 1-many mapping between GBP l3_policy and Neutron subnetpools. The 1-many
|
and 6 for IPv6. The value 46 may now be used to enable dual-stack support.
|
||||||
|
|
||||||
|
For each address family (IPv4 and/or IPv6) indicated by an l3_policy, there
|
||||||
|
will be a 1-1 mapping between GBP l3_policy and a Neutron address_scope,
|
||||||
|
and a 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
|
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.
|
across tenants, while the subnetpool is created per tenant and not shared.
|
||||||
|
|
||||||
The subnetpools that are explicitly associated with the l3_policy, need to
|
The ip_pool parameter now allows comma-delimited prefixes, as well just a
|
||||||
belong to the same address_scope that is associated with that l3_policy. GBP
|
single prefix. CIDRs from different address families may be used together
|
||||||
|
in the same ip_pool parameter. The ip_pool parameter may also be None,
|
||||||
|
which is intended for use with the default subnetpool Neutron extension.
|
||||||
|
|
||||||
|
The default subnetpool Neutron extension is used to control the desired behavior
|
||||||
|
when an implicit workflow is used on L3 policies with mapping drivers [#]_.
|
||||||
|
Default subnetpools are only used when the ip_version requests a given address
|
||||||
|
family (IPv4 or IPv6) and the user hasn't explicitly provided any CIDRs for
|
||||||
|
that address family (e.g. via the ip_pool parameter or a subnetpool).
|
||||||
|
|
||||||
|
Within each indicated address family, the subnetpools that are explicitly
|
||||||
|
associated with the l3_policy must all belong to the same address_scope. GBP
|
||||||
will allocate subnets only from the subnetpools that are associated with the
|
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
|
corresponding l3_policy. The list of subnets associated with the l3_policy can
|
||||||
be updated by adding or removing subnetpools (subnetpools which are currently
|
be updated by adding or removing subnetpools (subnetpools which are currently
|
||||||
being used cannot be removed).
|
being used cannot be removed), or by updating the prefixes attribute of
|
||||||
|
subnetpools already associated with the l3_policy
|
||||||
|
|
||||||
|
The definition of the subnet_prefix_length is modified to refine it's use.
|
||||||
|
The subnet_prefix_length now only applies to IPv4 prefixes. It also is
|
||||||
|
used as the default subnet prefix length for all subnets allocated from
|
||||||
|
IPv4 subnetpools for the given l3_policy. In order to help backward-
|
||||||
|
compatibilty, values longer than 30 will now be ignored. IPv6 subnets
|
||||||
|
that are allocated will always use a prefix length of 64.
|
||||||
|
|
||||||
|
Two properties of address scopes are address namespace and routability.
|
||||||
|
Address namespace simply means that addresses are guaranteed to be unique
|
||||||
|
within an address scope. Routability means that a neutron router may only
|
||||||
|
forward between interfaces that have subnets which were allocated from
|
||||||
|
subnetpools with the same address scope (note: forwarding is still possible
|
||||||
|
via NAT when they aren't in the same scope). It's worth pointing out that
|
||||||
|
since address scopes can span multiple l3_policies, the address uniqueness is
|
||||||
|
applied across the l3_policies. However, even though sharing a common address
|
||||||
|
scope implies routability across l3_policies, actual connectivity between
|
||||||
|
l3_policies is not implied because each l3_policy maps to a distinct neutron
|
||||||
|
router. In GBP, connectivity between l3_policies remains subject to a PTG
|
||||||
|
providing a PRS that is consumed by an external_policy and a PTG in the
|
||||||
|
other l3_policy consuming that external_policy.
|
||||||
|
|
||||||
Let's consider the various combinations that are possible based on the choice
|
Let's consider the various combinations that are possible based on the choice
|
||||||
of implicit and explicit arguments.
|
of implicit and explicit arguments.
|
||||||
|
|
||||||
#. A l3_policy is created with an ip_pool, ip_version, and
|
#. 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
|
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
|
this case an address_scope for each address family specified by ip_version
|
||||||
created implicitly, and a subnetpool with the ip_pool CIDR will be created
|
is created, and a subnetpool with prefixes for each CIDR for that address
|
||||||
in that address_scope. If the l3_policy is shared, the implcitily create
|
family found in ip_pool is created in that address_scope. If the l3_policy
|
||||||
address_scope and subnetpool will also be shared. The ip_version of the
|
is shared, the implcitily created address_scope and subnetpool will also be
|
||||||
l3_policy will be used for the address_scope and the subnetpool. The
|
shared. The default_prefixlen for IPv4 subnetpools will be set to the
|
||||||
default_prefixlen, will be set to the subnet_prefix_length of the l3_policy.
|
subnet_prefix_length of the l3_policy, and for IPv6 subnetpools it will be
|
||||||
(The min_prefixlen, and max_prefixlen of the subnetpool will default to 8
|
set to 64 (the min_prefixlen and max_prefixlen of the IPv4 subnetpool will
|
||||||
and 32 as defined in Neutron.)
|
default to 8 and 32, and to 64 and 128 for the IPv6 subnetpool, as defined
|
||||||
|
in Neutron).
|
||||||
|
|
||||||
#. A l3_policy is created with an ip_pool, ip_version, subnet_prefix_length,
|
#. A l3_policy is created with an ip_version and subnet_prefix_length
|
||||||
and address_scope, but no subnetpools are provided. In this case the
|
(IPv4 only), but no address_scope, subnetpool(s), or prefix in ip_pool
|
||||||
ip_version of the l3_policy is ignored, and the subnetpool is created in
|
are provided for that address family. There are two possibilities in this
|
||||||
this address_scope as before. If both, v4 and v6, address_scopes are
|
scenario:
|
||||||
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
|
* A default subnetpool (defined in neutron) exists for an address family
|
||||||
ip_version is already defined for the address_scope and the CIDR and prefix
|
indicated by ip_version. In this case the default subnetpool and its
|
||||||
lengths are defined for the subnetpool(s), the ip_version, ip_pool and
|
address scope are associated with the l3_policy.
|
||||||
subnet_prefix_length of the l3_policy will be ignored if provided.
|
|
||||||
|
* A default subnetpool does not exist for an address family indicated
|
||||||
|
by ip_version. In this case, an exception is raised.
|
||||||
|
|
||||||
|
#. A l3_policy is created with an address_scope of the indicated address
|
||||||
|
family, but no subnetpools of that address family are provided. If there
|
||||||
|
are CIDRs in ip_pool from the same address family, then they are used as
|
||||||
|
prefixes to create a new subnetpool within the specified address scope.
|
||||||
|
If a subnetpool already exists in this address_scope, and overlaps with
|
||||||
|
the CIDR of the ip_pool, an exception will be raised. If no CIDRs from the
|
||||||
|
same address family are found, a check is made to see if a default
|
||||||
|
subnetpool sharing the same address scope exists. If it does, then that
|
||||||
|
subnetpool is associated with the l3_policy. If none exists, then an
|
||||||
|
exception is raised.
|
||||||
|
|
||||||
|
#. A l3_policy is created with an address_scope and subnetpool(s). Since the
|
||||||
|
supplied subnetpool(s) define how subnets will be allocated, any supplied
|
||||||
|
ip_pool for that address family is ignored. The ip_pool value returned
|
||||||
|
from any l3_policy API call will contain the set of prefixes used for
|
||||||
|
allocating subnets for all address families specified in ip_version. In
|
||||||
|
this case, that will be the aggregate prefixes from the explicitly
|
||||||
|
passed subnetpools.
|
||||||
|
|
||||||
#. A l3_policy is created with one or more subnetpools. The address_scope
|
#. 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
|
associated with the subnetpool(s) is associated with the l3_policy. If
|
||||||
@ -87,9 +141,9 @@ 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
|
that is associated with a l3_policy, they will be considered for subnet
|
||||||
allocation only if they are explicitly associated with the l3_policy.
|
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
|
A minor variation of all the above cases is the one where either or both of
|
||||||
ip_pool, ip_version, and subnet_prefix_length are not provided. In such cases
|
the ip_pool and subnet_prefix_length are not provided. In such cases the GBP
|
||||||
the GBP defaults for these attributes will be used (but overridden by the
|
defaults for these attributes will be used (but overridden by the
|
||||||
corresponding attributes in the address_scope and subnetpools if any of those
|
corresponding attributes in the address_scope and subnetpools if any of those
|
||||||
are explicitly provided).
|
are explicitly provided).
|
||||||
|
|
||||||
@ -105,16 +159,8 @@ subnetpool was implicitly created by GBP.
|
|||||||
It should be noted that the ip_pool, subnet_prefix_length, and ip_version
|
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
|
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
|
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
|
to a comma delimited string consisting of a list of CIDRs made up of the
|
||||||
subnetpool currently present in the address_scope. To preserve API backward
|
prefixes attribute values of all subnetpools associated with the l3_policy.
|
||||||
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
|
Data model impact
|
||||||
@ -152,7 +198,7 @@ backward incompatible DB change and a script will be provided to migrate data
|
|||||||
from existing deployments to this new structure. The script will essentially
|
from existing deployments to this new structure. The script will essentially
|
||||||
create an address_scope and subnetpool for each existing l3_policy.
|
create an address_scope and subnetpool for each existing l3_policy.
|
||||||
|
|
||||||
In addition, additional tables will be added to track the Neutron address_scope
|
Additional tables will be added to track the Neutron address_scope
|
||||||
and subnetpool resources created by GBP.
|
and subnetpool resources created by GBP.
|
||||||
|
|
||||||
::
|
::
|
||||||
@ -177,6 +223,43 @@ and subnetpool resources created by GBP.
|
|||||||
nullable=False, primary_key=True)
|
nullable=False, primary_key=True)
|
||||||
|
|
||||||
|
|
||||||
|
The size of the ip_pool column in the L3Policy table is increased from
|
||||||
|
64 to 256 in order to account for more than a single prefix. Once all
|
||||||
|
policy drivers use subnetpools, this column could be removed from
|
||||||
|
the DB.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
class L3Policy(model_base.BASEV2, BaseSharedGbpResource):
|
||||||
|
"""Represents a L3 Policy with a non-overlapping IP address space."""
|
||||||
|
__tablename__ = 'gp_l3_policies'
|
||||||
|
type = sa.Column(sa.String(15))
|
||||||
|
__mapper_args__ = {
|
||||||
|
'polymorphic_on': type,
|
||||||
|
'polymorphic_identity': 'base'
|
||||||
|
}
|
||||||
|
ip_version = sa.Column(sa.Integer, nullable=False)
|
||||||
|
ip_pool = sa.Column(sa.String(256))
|
||||||
|
subnet_prefix_length = sa.Column(sa.Integer)
|
||||||
|
l2_policies = orm.relationship(L2Policy, backref='l3_policy')
|
||||||
|
external_segments = orm.relationship(
|
||||||
|
ESToL3PAssociation, backref='l3_policies',
|
||||||
|
cascade='all, delete-orphan')
|
||||||
|
|
||||||
|
A similar increase (64 to 256) is needed to the proxy_ip_pool parameter in the
|
||||||
|
DB for that extension, as well as the ability to make the field nullable:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
class ProxyIPPoolMapping(model_base.BASEV2):
|
||||||
|
__tablename__ = 'gp_proxy_ip_pool_mapping'
|
||||||
|
|
||||||
|
l3_policy_id = sa.Column(
|
||||||
|
sa.String(36), sa.ForeignKey('gp_l3_policies.id', ondelete="CASCADE"),
|
||||||
|
primary_key=True)
|
||||||
|
proxy_ip_pool = sa.Column(sa.String(256), nullable=True)
|
||||||
|
proxy_subnet_prefix_length = sa.Column(sa.Integer, nullable=False)
|
||||||
|
|
||||||
REST API impact
|
REST API impact
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
@ -204,6 +287,63 @@ extension definition
|
|||||||
'is_visible': True, 'default': None},
|
'is_visible': True, 'default': None},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
In addition, the l3_policy itself needs modifications to support:
|
||||||
|
|
||||||
|
* the new value 46 for ip_version:
|
||||||
|
* a type change for ip_pool (subnet to string)
|
||||||
|
|
||||||
|
the defaultt value for ip_pool is defined in a new config file
|
||||||
|
variable. The variable has the same value as the old default, which
|
||||||
|
ensures backwards-compatibility, but also allows for the default
|
||||||
|
value to be something else (e.g. dual-stack prefixes, empty prefix,
|
||||||
|
IPv6 prefix only, etc.).
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
L3_POLICIES: {
|
||||||
|
'id': {'allow_post': False, 'allow_put': False,
|
||||||
|
'validate': {'type:uuid': None}, 'is_visible': True,
|
||||||
|
'primary_key': True},
|
||||||
|
'name': {'allow_post': True, 'allow_put': True,
|
||||||
|
'validate': {'type:gbp_resource_name': None},
|
||||||
|
'default': '', 'is_visible': True},
|
||||||
|
'description': {'allow_post': True, 'allow_put': True,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'is_visible': True, 'default': ''},
|
||||||
|
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'required_by_policy': True, 'is_visible': True},
|
||||||
|
'status': {'allow_post': False, 'allow_put': False,
|
||||||
|
'is_visible': True},
|
||||||
|
'status_details': {'allow_post': False, 'allow_put': False,
|
||||||
|
'is_visible': True},
|
||||||
|
'ip_version': {'allow_post': True, 'allow_put': False,
|
||||||
|
'convert_to': conv.convert_to_int,
|
||||||
|
'validate': {'type:values': [4, 6, 46]},
|
||||||
|
'default': 4, 'is_visible': True},
|
||||||
|
'ip_pool': {'allow_post': True, 'allow_put': False,
|
||||||
|
'validate': {'type:string_or_none': None},
|
||||||
|
'default': GBP_CONF.default_ip_pool, 'is_visible': True},
|
||||||
|
'subnet_prefix_length': {'allow_post': True, 'allow_put': True,
|
||||||
|
'convert_to': conv.convert_to_int,
|
||||||
|
# This parameter only applies to ipv4
|
||||||
|
# prefixes. For IPv4 legal values are
|
||||||
|
# 2 to 30. For ipv6, this parameter
|
||||||
|
# is ignored
|
||||||
|
'default': 24, 'is_visible': True},
|
||||||
|
'l2_policies': {'allow_post': False, 'allow_put': False,
|
||||||
|
'validate': {'type:uuid_list': None},
|
||||||
|
'convert_to': conv.convert_none_to_empty_list,
|
||||||
|
'default': None, 'is_visible': True},
|
||||||
|
attr.SHARED: {'allow_post': True, 'allow_put': True,
|
||||||
|
'default': False, 'convert_to': conv.convert_to_boolean,
|
||||||
|
'is_visible': True, 'required_by_policy': True,
|
||||||
|
'enforce_policy': True},
|
||||||
|
'external_segments': {
|
||||||
|
'allow_post': True, 'allow_put': True, 'default': None,
|
||||||
|
'validate': {'type:external_dict': None},
|
||||||
|
'convert_to': conv.convert_none_to_empty_dict, 'is_visible': True},
|
||||||
|
},
|
||||||
|
|
||||||
Security impact
|
Security impact
|
||||||
---------------
|
---------------
|
||||||
@ -320,3 +460,4 @@ References
|
|||||||
==========
|
==========
|
||||||
|
|
||||||
.. [#] http://docs.openstack.org/developer/neutron/devref/address_scopes.html
|
.. [#] http://docs.openstack.org/developer/neutron/devref/address_scopes.html
|
||||||
|
.. [#] https://review.openstack.org/#/c/282021/
|
||||||
|
Loading…
Reference in New Issue
Block a user