group-based-policy-specs/specs/newton/address-scope-subnet-pool-m...

12 KiB

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 Scopes1. 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.

  1. 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.)
  2. 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.
  3. 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.
  4. 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


  1. http://docs.openstack.org/developer/neutron/devref/address_scopes.html↩︎