AIM Policy Driver - Part 5 - L3 Policies (implicit)
L3 Policy is mapped to Address Scope and Subnetpool. This patch implements the implicit workflow to create these mapped resources. Implements blueprint: address-scope-mapping Change-Id: I4309ada6f26c23a11232a858ff4e36bd5d03e25a
This commit is contained in:
@@ -284,35 +284,38 @@ class LocalAPI(object):
|
|||||||
except n_exc.NetworkNotFound:
|
except n_exc.NetworkNotFound:
|
||||||
LOG.warning(_LW('Network %s already deleted'), network_id)
|
LOG.warning(_LW('Network %s already deleted'), network_id)
|
||||||
|
|
||||||
def _get_router(self, plugin_context, router_id):
|
def _get_router(self, plugin_context, router_id, clean_session=True):
|
||||||
return self._get_resource(self._l3_plugin, plugin_context, 'router',
|
return self._get_resource(self._l3_plugin, plugin_context, 'router',
|
||||||
router_id)
|
router_id, clean_session=clean_session)
|
||||||
|
|
||||||
def _get_routers(self, plugin_context, filters=None):
|
def _get_routers(self, plugin_context, filters=None, clean_session=True):
|
||||||
filters = filters or {}
|
filters = filters or {}
|
||||||
return self._get_resources(self._l3_plugin, plugin_context, 'routers',
|
return self._get_resources(self._l3_plugin, plugin_context, 'routers',
|
||||||
filters)
|
filters, clean_session=clean_session)
|
||||||
|
|
||||||
def _create_router(self, plugin_context, attrs):
|
def _create_router(self, plugin_context, attrs, clean_session=True):
|
||||||
return self._create_resource(self._l3_plugin, plugin_context, 'router',
|
return self._create_resource(self._l3_plugin, plugin_context, 'router',
|
||||||
attrs)
|
attrs, clean_session=clean_session)
|
||||||
|
|
||||||
def _update_router(self, plugin_context, router_id, attrs):
|
def _update_router(self, plugin_context, router_id, attrs,
|
||||||
|
clean_session=True):
|
||||||
return self._update_resource(self._l3_plugin, plugin_context, 'router',
|
return self._update_resource(self._l3_plugin, plugin_context, 'router',
|
||||||
router_id, attrs)
|
router_id, attrs,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
def _add_router_interface(self, plugin_context, router_id, interface_info):
|
def _add_router_interface(self, plugin_context, router_id, interface_info):
|
||||||
self._l3_plugin.add_router_interface(plugin_context,
|
self._l3_plugin.add_router_interface(plugin_context,
|
||||||
router_id, interface_info)
|
router_id, interface_info)
|
||||||
|
|
||||||
def _remove_router_interface(self, plugin_context, router_id,
|
def _remove_router_interface(self, plugin_context, router_id,
|
||||||
interface_info):
|
interface_info, clean_session=True):
|
||||||
# To detach Router interface either port ID or Subnet ID is mandatory
|
# To detach Router interface either port ID or Subnet ID is mandatory
|
||||||
key = 'port_id' if 'port_id' in interface_info else 'subnet_id'
|
key = 'port_id' if 'port_id' in interface_info else 'subnet_id'
|
||||||
fixed_ips_filter = {key: [interface_info.get(key)]}
|
fixed_ips_filter = {key: [interface_info.get(key)]}
|
||||||
filters = {'device_id': [router_id],
|
filters = {'device_id': [router_id],
|
||||||
'fixed_ips': fixed_ips_filter}
|
'fixed_ips': fixed_ips_filter}
|
||||||
ports = self._get_ports(plugin_context, filters=filters)
|
ports = self._get_ports(plugin_context, filters=filters,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._l3_plugin.remove_router_interface(plugin_context, router_id,
|
self._l3_plugin.remove_router_interface(plugin_context, router_id,
|
||||||
@@ -330,21 +333,22 @@ class LocalAPI(object):
|
|||||||
{'port': ports[0]},
|
{'port': ports[0]},
|
||||||
'port' + '.delete.end')
|
'port' + '.delete.end')
|
||||||
|
|
||||||
def _add_router_gw_interface(self, plugin_context, router_id, gw_info):
|
def _add_router_gw_interface(self, plugin_context, router_id, gw_info,
|
||||||
|
clean_session=True):
|
||||||
return self._l3_plugin.update_router(
|
return self._l3_plugin.update_router(
|
||||||
plugin_context, router_id,
|
plugin_context, router_id,
|
||||||
{'router': {'external_gateway_info': gw_info}})
|
{'router': {'external_gateway_info': gw_info}})
|
||||||
|
|
||||||
def _remove_router_gw_interface(self, plugin_context, router_id,
|
def _remove_router_gw_interface(self, plugin_context, router_id,
|
||||||
interface_info):
|
interface_info, clean_session=True):
|
||||||
self._l3_plugin.update_router(
|
self._l3_plugin.update_router(
|
||||||
plugin_context, router_id,
|
plugin_context, router_id,
|
||||||
{'router': {'external_gateway_info': None}})
|
{'router': {'external_gateway_info': None}})
|
||||||
|
|
||||||
def _delete_router(self, plugin_context, router_id):
|
def _delete_router(self, plugin_context, router_id, clean_session=True):
|
||||||
try:
|
try:
|
||||||
self._delete_resource(self._l3_plugin, plugin_context, 'router',
|
self._delete_resource(self._l3_plugin, plugin_context, 'router',
|
||||||
router_id)
|
router_id, clean_session=clean_session)
|
||||||
except l3.RouterNotFound:
|
except l3.RouterNotFound:
|
||||||
LOG.warning(_LW('Router %s already deleted'), router_id)
|
LOG.warning(_LW('Router %s already deleted'), router_id)
|
||||||
|
|
||||||
@@ -436,6 +440,75 @@ class LocalAPI(object):
|
|||||||
except l3.FloatingIPNotFound:
|
except l3.FloatingIPNotFound:
|
||||||
LOG.warning(_LW('Floating IP %s Already deleted'), fip_id)
|
LOG.warning(_LW('Floating IP %s Already deleted'), fip_id)
|
||||||
|
|
||||||
|
def _get_address_scope(self, plugin_context, address_scope_id,
|
||||||
|
clean_session=True):
|
||||||
|
return self._get_resource(self._core_plugin, plugin_context,
|
||||||
|
'address_scope', address_scope_id,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _get_address_scopes(self, plugin_context, filters=None,
|
||||||
|
clean_session=True):
|
||||||
|
filters = filters or {}
|
||||||
|
return self._get_resources(self._core_plugin, plugin_context,
|
||||||
|
'address_scopes', filters,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _create_address_scope(self, plugin_context, attrs,
|
||||||
|
clean_session=True):
|
||||||
|
return self._create_resource(self._core_plugin, plugin_context,
|
||||||
|
'address_scope', attrs,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _update_address_scope(self, plugin_context, address_scope_id, attrs,
|
||||||
|
clean_session=True):
|
||||||
|
return self._update_resource(self._core_plugin, plugin_context,
|
||||||
|
'address_scope', address_scope_id, attrs,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _delete_address_scope(self, plugin_context, address_scope_id,
|
||||||
|
clean_session=True):
|
||||||
|
try:
|
||||||
|
self._delete_resource(self._core_plugin, plugin_context,
|
||||||
|
'address_scope', address_scope_id,
|
||||||
|
clean_session=clean_session)
|
||||||
|
except n_exc.AddressScopeNotFound:
|
||||||
|
LOG.warning(_LW('Address Scope %s already deleted'),
|
||||||
|
address_scope_id)
|
||||||
|
|
||||||
|
def _get_subnetpool(self, plugin_context, subnetpool_id,
|
||||||
|
clean_session=True):
|
||||||
|
return self._get_resource(self._core_plugin, plugin_context,
|
||||||
|
'subnetpool', subnetpool_id,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _get_subnetpools(self, plugin_context, filters=None,
|
||||||
|
clean_session=True):
|
||||||
|
filters = filters or {}
|
||||||
|
return self._get_resources(self._core_plugin, plugin_context,
|
||||||
|
'subnetpools', filters,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _create_subnetpool(self, plugin_context, attrs,
|
||||||
|
clean_session=True):
|
||||||
|
return self._create_resource(self._core_plugin, plugin_context,
|
||||||
|
'subnetpool', attrs,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _update_subnetpool(self, plugin_context, subnetpool_id, attrs,
|
||||||
|
clean_session=True):
|
||||||
|
return self._update_resource(self._core_plugin, plugin_context,
|
||||||
|
'subnetpool', subnetpool_id, attrs,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _delete_subnetpool(self, plugin_context, subnetpool_id,
|
||||||
|
clean_session=True):
|
||||||
|
try:
|
||||||
|
self._delete_resource(self._core_plugin, plugin_context,
|
||||||
|
'subnetpool', subnetpool_id,
|
||||||
|
clean_session=clean_session)
|
||||||
|
except n_exc.SubnetpoolNotFound:
|
||||||
|
LOG.warning(_LW('Subnetpool %s already deleted'), subnetpool_id)
|
||||||
|
|
||||||
def _get_l2_policy(self, plugin_context, l2p_id, clean_session=True):
|
def _get_l2_policy(self, plugin_context, l2p_id, clean_session=True):
|
||||||
return self._get_resource(self._group_policy_plugin, plugin_context,
|
return self._get_resource(self._group_policy_plugin, plugin_context,
|
||||||
'l2_policy', l2p_id,
|
'l2_policy', l2p_id,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from neutron.common import exceptions as nexc
|
||||||
from neutron.db import model_base
|
from neutron.db import model_base
|
||||||
from oslo_log import helpers as log
|
from oslo_log import helpers as log
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
@@ -25,6 +26,10 @@ from gbpservice.neutron.services.grouppolicy.common import exceptions
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class AddressScopeUpdateForL3PNotSupported(nexc.BadRequest):
|
||||||
|
message = _("Address Scope update for L3 Policy is not supported.")
|
||||||
|
|
||||||
|
|
||||||
class PolicyTargetMapping(gpdb.PolicyTarget):
|
class PolicyTargetMapping(gpdb.PolicyTarget):
|
||||||
"""Mapping of PolicyTarget to Neutron Port."""
|
"""Mapping of PolicyTarget to Neutron Port."""
|
||||||
__table_args__ = {'extend_existing': True}
|
__table_args__ = {'extend_existing': True}
|
||||||
@@ -71,12 +76,40 @@ class L3PolicyRouterAssociation(model_base.BASEV2):
|
|||||||
primary_key=True)
|
primary_key=True)
|
||||||
|
|
||||||
|
|
||||||
|
class L3PolicySubnetpoolV4Association(model_base.BASEV2):
|
||||||
|
"""Models one to many relation between a L3Policy and v4 Subnetpools."""
|
||||||
|
__tablename__ = 'gp_l3_policy_subnetpool_v4_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 L3PolicySubnetpoolV6Association(model_base.BASEV2):
|
||||||
|
"""Models one to many relation between a L3Policy and v6 Subnetpools."""
|
||||||
|
__tablename__ = 'gp_l3_policy_subnetpool_v6_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):
|
class L3PolicyMapping(gpdb.L3Policy):
|
||||||
"""Mapping of L3Policy to set of Neutron Routers."""
|
"""Mapping of L3Policy to set of Neutron Resources."""
|
||||||
__table_args__ = {'extend_existing': True}
|
__table_args__ = {'extend_existing': True}
|
||||||
__mapper_args__ = {'polymorphic_identity': 'mapping'}
|
__mapper_args__ = {'polymorphic_identity': 'mapping'}
|
||||||
routers = orm.relationship(L3PolicyRouterAssociation,
|
routers = orm.relationship(L3PolicyRouterAssociation,
|
||||||
cascade='all', lazy="joined")
|
cascade='all', lazy="joined")
|
||||||
|
address_scope_v4_id = sa.Column(
|
||||||
|
sa.String(36), sa.ForeignKey('address_scopes.id'),
|
||||||
|
nullable=True, unique=True)
|
||||||
|
address_scope_v6_id = sa.Column(
|
||||||
|
sa.String(36), sa.ForeignKey('address_scopes.id'),
|
||||||
|
nullable=True, unique=True)
|
||||||
|
subnetpools_v4 = orm.relationship(L3PolicySubnetpoolV4Association,
|
||||||
|
cascade='all', lazy="joined")
|
||||||
|
subnetpools_v6 = orm.relationship(L3PolicySubnetpoolV6Association,
|
||||||
|
cascade='all', lazy="joined")
|
||||||
|
|
||||||
|
|
||||||
class ExternalSegmentMapping(gpdb.ExternalSegment):
|
class ExternalSegmentMapping(gpdb.ExternalSegment):
|
||||||
@@ -122,6 +155,10 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
|
|||||||
res = super(GroupPolicyMappingDbPlugin,
|
res = super(GroupPolicyMappingDbPlugin,
|
||||||
self)._make_l3_policy_dict(l3p)
|
self)._make_l3_policy_dict(l3p)
|
||||||
res['routers'] = [router.router_id for router in l3p.routers]
|
res['routers'] = [router.router_id for router in l3p.routers]
|
||||||
|
res['address_scope_v4_id'] = l3p.address_scope_v4_id
|
||||||
|
res['address_scope_v6_id'] = l3p.address_scope_v6_id
|
||||||
|
res['subnetpools_v4'] = [sp.subnetpool_id for sp in l3p.subnetpools_v4]
|
||||||
|
res['subnetpools_v6'] = [sp.subnetpool_id for sp in l3p.subnetpools_v6]
|
||||||
return self._fields(res, fields)
|
return self._fields(res, fields)
|
||||||
|
|
||||||
def _make_external_segment_dict(self, es, fields=None):
|
def _make_external_segment_dict(self, es, fields=None):
|
||||||
@@ -171,6 +208,98 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
|
|||||||
l2p_db = self._get_l2_policy(context, l2p_id)
|
l2p_db = self._get_l2_policy(context, l2p_id)
|
||||||
l2p_db.network_id = network_id
|
l2p_db.network_id = network_id
|
||||||
|
|
||||||
|
def _set_address_scope_for_l3_policy(self, context, l3p_id,
|
||||||
|
address_scope_id, ip_version=4):
|
||||||
|
if not address_scope_id:
|
||||||
|
return
|
||||||
|
# TODO(Sumit): address_scope_id validation
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
l3p_db = self._get_l3_policy(context, l3p_id)
|
||||||
|
if ip_version == 4:
|
||||||
|
l3p_db.address_scope_v4_id = address_scope_id
|
||||||
|
else:
|
||||||
|
l3p_db.address_scope_v6_id = address_scope_id
|
||||||
|
|
||||||
|
def _add_subnetpool_to_l3_policy(self, context, l3p_id,
|
||||||
|
subnetpool_id, ip_version=4):
|
||||||
|
# TODO(Sumit): subnetpool_id validation
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
l3p_db = self._get_l3_policy(context, l3p_id)
|
||||||
|
if ip_version == 4:
|
||||||
|
assoc = L3PolicySubnetpoolV4Association(
|
||||||
|
l3_policy_id=l3p_id, subnetpool_id=subnetpool_id)
|
||||||
|
l3p_db.subnetpools_v4.append(assoc)
|
||||||
|
else:
|
||||||
|
assoc = L3PolicySubnetpoolV6Association(
|
||||||
|
l3_policy_id=l3p_id, subnetpool_id=subnetpool_id)
|
||||||
|
l3p_db.subnetpools_v6.append(assoc)
|
||||||
|
return {4: [sp.subnetpool_id for sp in l3p_db.subnetpools_v4],
|
||||||
|
6: [sp.subnetpool_id for sp in l3p_db.subnetpools_v6]}
|
||||||
|
|
||||||
|
def _add_subnetpools_to_l3_policy(self, context, l3p_id,
|
||||||
|
subnetpools, ip_version=4):
|
||||||
|
for sp in subnetpools or []:
|
||||||
|
self._add_subnetpool_to_l3_policy(
|
||||||
|
context, l3p_id, sp, ip_version=ip_version)
|
||||||
|
|
||||||
|
def _remove_subnetpool_from_l3_policy(self, context, l3p_id,
|
||||||
|
subnetpool_id, ip_version=4):
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
l3p_db = self._get_l3_policy(context, l3p_id)
|
||||||
|
if ip_version == 4:
|
||||||
|
assoc = (context.session.query(
|
||||||
|
L3PolicySubnetpoolV4Association).filter_by(
|
||||||
|
l3_policy_id=l3p_id,
|
||||||
|
subnetpool_id=subnetpool_id).one())
|
||||||
|
l3p_db.subnetpools_v4.remove(assoc)
|
||||||
|
else:
|
||||||
|
assoc = (context.session.query(
|
||||||
|
L3PolicySubnetpoolV6Association).filter_by(
|
||||||
|
l3_policy_id=l3p_id,
|
||||||
|
subnetpool_id=subnetpool_id).one())
|
||||||
|
l3p_db.subnetpools_v6.remove(assoc)
|
||||||
|
context.session.delete(assoc)
|
||||||
|
return {4: [sp.subnetpool_id for sp in l3p_db.subnetpools_v4],
|
||||||
|
6: [sp.subnetpool_id for sp in l3p_db.subnetpools_v6]}
|
||||||
|
|
||||||
|
def _update_subnetpools_for_l3_policy(self, context, l3p_id,
|
||||||
|
subnetpools, ip_version=4):
|
||||||
|
# Add/remove associations for changes in subnetpools
|
||||||
|
# TODO(Sumit): Before disassociating a subnetpool, check that
|
||||||
|
# there is no PT present on a subnet which belongs to that subnetpool
|
||||||
|
if not subnetpools:
|
||||||
|
return
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
l3p_db = self._get_l3_policy(context, l3p_id)
|
||||||
|
new_subnetpools = set(subnetpools)
|
||||||
|
if ip_version == 4:
|
||||||
|
old_subnetpools = set(sp.subnetpool_id
|
||||||
|
for sp in l3p_db.subnetpools_v4)
|
||||||
|
else:
|
||||||
|
old_subnetpools = set(sp.subnetpool_id
|
||||||
|
for sp in l3p_db.subnetpools_v6)
|
||||||
|
for sp in new_subnetpools - old_subnetpools:
|
||||||
|
if ip_version == 4:
|
||||||
|
assoc = L3PolicySubnetpoolV4Association(
|
||||||
|
l3_policy_id=l3p_id, subnetpool_id=sp)
|
||||||
|
l3p_db.subnetpools_v4.append(assoc)
|
||||||
|
else:
|
||||||
|
assoc = L3PolicySubnetpoolV6Association(
|
||||||
|
l3_policy_id=l3p_id, subnetpool_id=sp)
|
||||||
|
l3p_db.subnetpools_v6.append(assoc)
|
||||||
|
for sp in old_subnetpools - new_subnetpools:
|
||||||
|
if ip_version == 4:
|
||||||
|
assoc = (context.session.query(
|
||||||
|
L3PolicySubnetpoolV4Association).filter_by(
|
||||||
|
l3_policy_id=l3p_id, subnetpool_id=sp).one())
|
||||||
|
l3p_db.subnetpools_v4.remove(assoc)
|
||||||
|
else:
|
||||||
|
assoc = (context.session.query(
|
||||||
|
L3PolicySubnetpoolV6Association).filter_by(
|
||||||
|
l3_policy_id=l3p_id, subnetpool_id=sp).one())
|
||||||
|
l3p_db.subnetpools_v6.remove(assoc)
|
||||||
|
context.session.delete(assoc)
|
||||||
|
|
||||||
def _add_router_to_l3_policy(self, context, l3p_id, router_id):
|
def _add_router_to_l3_policy(self, context, l3p_id, router_id):
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
l3p_db = self._get_l3_policy(context, l3p_id)
|
l3p_db = self._get_l3_policy(context, l3p_id)
|
||||||
@@ -424,6 +553,18 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
|
|||||||
l3p['subnet_prefix_length'],
|
l3p['subnet_prefix_length'],
|
||||||
description=l3p['description'],
|
description=l3p['description'],
|
||||||
shared=l3p.get('shared', False))
|
shared=l3p.get('shared', False))
|
||||||
|
|
||||||
|
self._set_address_scope_for_l3_policy(
|
||||||
|
context, l3p_db['id'], l3p.get('address_scope_v4_id'),
|
||||||
|
ip_version=4)
|
||||||
|
self._set_address_scope_for_l3_policy(
|
||||||
|
context, l3p_db['id'], l3p.get('address_scope_v6_id'),
|
||||||
|
ip_version=6)
|
||||||
|
self._add_subnetpools_to_l3_policy(
|
||||||
|
context, l3p_db['id'], l3p.get('subnetpools_v4'), ip_version=4)
|
||||||
|
self._add_subnetpools_to_l3_policy(
|
||||||
|
context, l3p_db['id'], l3p.get('subnetpools_v6'), ip_version=6)
|
||||||
|
|
||||||
if 'routers' in l3p:
|
if 'routers' in l3p:
|
||||||
for router in l3p['routers']:
|
for router in l3p['routers']:
|
||||||
assoc = L3PolicyRouterAssociation(
|
assoc = L3PolicyRouterAssociation(
|
||||||
@@ -440,12 +581,27 @@ class GroupPolicyMappingDbPlugin(gpdb.GroupPolicyDbPlugin):
|
|||||||
@log.log_method_call
|
@log.log_method_call
|
||||||
def update_l3_policy(self, context, l3_policy_id, l3_policy):
|
def update_l3_policy(self, context, l3_policy_id, l3_policy):
|
||||||
l3p = l3_policy['l3_policy']
|
l3p = l3_policy['l3_policy']
|
||||||
|
|
||||||
|
if 'address_scope_v4_id' in l3p or 'address_scope_v6_id' in l3p:
|
||||||
|
raise AddressScopeUpdateForL3PNotSupported()
|
||||||
|
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
l3p_db = self._get_l3_policy(context, l3_policy_id)
|
l3p_db = self._get_l3_policy(context, l3_policy_id)
|
||||||
|
|
||||||
|
self._update_subnetpools_for_l3_policy(context, l3_policy_id,
|
||||||
|
l3p.get('subnetpools_v4'),
|
||||||
|
ip_version=4)
|
||||||
|
l3p.pop('subnetpools_v4', None)
|
||||||
|
self._update_subnetpools_for_l3_policy(context, l3_policy_id,
|
||||||
|
l3p.get('subnetpools_v6'),
|
||||||
|
ip_version=4)
|
||||||
|
l3p.pop('subnetpools_v6', None)
|
||||||
|
|
||||||
if 'subnet_prefix_length' in l3p:
|
if 'subnet_prefix_length' in l3p:
|
||||||
self.validate_subnet_prefix_length(l3p_db.ip_version,
|
self.validate_subnet_prefix_length(l3p_db.ip_version,
|
||||||
l3p['subnet_prefix_length'],
|
l3p['subnet_prefix_length'],
|
||||||
l3p_db.ip_pool)
|
l3p_db.ip_pool)
|
||||||
|
|
||||||
if 'routers' in l3p:
|
if 'routers' in l3p:
|
||||||
# Add/remove associations for changes in routers.
|
# Add/remove associations for changes in routers.
|
||||||
new_routers = set(l3p['routers'])
|
new_routers = set(l3p['routers'])
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
7afacef00d31
|
d4bb487a81b8
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
"""address_scope and subnetpool mapping for l3_policies
|
||||||
|
|
||||||
|
Revision ID: d4bb487a81b8
|
||||||
|
Revises: c1aab79622fe
|
||||||
|
Create Date: 2016-08-28 11:35:32.724952
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'd4bb487a81b8'
|
||||||
|
down_revision = '7afacef00d31'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
|
||||||
|
op.create_table(
|
||||||
|
'gp_l3_policy_subnetpool_v4_associations',
|
||||||
|
sa.Column('l3_policy_id', sa.String(length=36), nullable=False),
|
||||||
|
sa.Column('subnetpool_id', sa.String(length=36), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['l3_policy_id'], ['gp_l3_policies.id'],
|
||||||
|
name='gpm_l3p_subnetpool_v4_assoc_fk_l3pid'),
|
||||||
|
sa.ForeignKeyConstraint(['subnetpool_id'], ['subnetpools.id'],
|
||||||
|
name='gpm_l3p_subnetpool_v4_assoc_fk_spid'),
|
||||||
|
sa.PrimaryKeyConstraint('l3_policy_id', 'subnetpool_id')
|
||||||
|
)
|
||||||
|
|
||||||
|
op.create_table(
|
||||||
|
'gp_l3_policy_subnetpool_v6_associations',
|
||||||
|
sa.Column('l3_policy_id', sa.String(length=36), nullable=False),
|
||||||
|
sa.Column('subnetpool_id', sa.String(length=36), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['l3_policy_id'], ['gp_l3_policies.id'],
|
||||||
|
name='gpm_l3p_subnetpool_v6_assoc_fk_l3pid'),
|
||||||
|
sa.ForeignKeyConstraint(['subnetpool_id'], ['subnetpools.id'],
|
||||||
|
name='gpm_l3p_subnetpool_v6_assoc_fk_spid'),
|
||||||
|
sa.PrimaryKeyConstraint('l3_policy_id', 'subnetpool_id')
|
||||||
|
)
|
||||||
|
|
||||||
|
op.add_column(
|
||||||
|
'gp_l3_policies',
|
||||||
|
sa.Column('address_scope_v4_id', sa.String(length=36), nullable=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
op.add_column(
|
||||||
|
'gp_l3_policies',
|
||||||
|
sa.Column('address_scope_v6_id', sa.String(length=36), nullable=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
op.create_unique_constraint('gpm_l3p_addr_scope_v4_uq',
|
||||||
|
'gp_l3_policies', ['address_scope_v4_id'])
|
||||||
|
op.create_unique_constraint('gpm_l3p_addr_scope_v6_uq',
|
||||||
|
'gp_l3_policies', ['address_scope_v6_id'])
|
||||||
|
op.create_foreign_key('gpm_l3p_addr_scope_v4_fk',
|
||||||
|
source='gp_l3_policies', referent='address_scopes',
|
||||||
|
local_cols=['address_scope_v4_id'],
|
||||||
|
remote_cols=['id'])
|
||||||
|
op.create_foreign_key('gpm_l3p_addr_scope_v6_fk',
|
||||||
|
source='gp_l3_policies', referent='address_scopes',
|
||||||
|
local_cols=['address_scope_v6_id'],
|
||||||
|
remote_cols=['id'])
|
||||||
|
|
||||||
|
op.create_table(
|
||||||
|
'gpm_owned_address_scopes',
|
||||||
|
sa.Column('address_scope_id', sa.String(length=36), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
['address_scope_id'], ['address_scopes.id'],
|
||||||
|
name='rmd_addr_scope_owned_fk', ondelete='CASCADE'),
|
||||||
|
sa.PrimaryKeyConstraint('address_scope_id')
|
||||||
|
)
|
||||||
|
|
||||||
|
op.create_table(
|
||||||
|
'gpm_owned_subnetpools',
|
||||||
|
sa.Column('subnetpool_id', sa.String(length=36), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['subnetpool_id'], ['subnetpools.id'],
|
||||||
|
name='rmd_subnetpool_owned_fk',
|
||||||
|
ondelete='CASCADE'),
|
||||||
|
sa.PrimaryKeyConstraint('subnetpool_id')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
pass
|
||||||
@@ -41,6 +41,20 @@ EXTENDED_ATTRIBUTES_2_0 = {
|
|||||||
'is_visible': True, 'default': None},
|
'is_visible': True, 'default': None},
|
||||||
},
|
},
|
||||||
gp.L3_POLICIES: {
|
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},
|
||||||
|
'convert_to': attr.convert_none_to_empty_list,
|
||||||
|
'is_visible': True, 'default': None},
|
||||||
|
'subnetpools_v6': {'allow_post': True, 'allow_put': True,
|
||||||
|
'validate': {'type:uuid_list': None},
|
||||||
|
'convert_to': attr.convert_none_to_empty_list,
|
||||||
|
'is_visible': True, 'default': None},
|
||||||
'routers': {'allow_post': True, 'allow_put': True,
|
'routers': {'allow_post': True, 'allow_put': True,
|
||||||
'validate': {'type:uuid_list': None},
|
'validate': {'type:uuid_list': None},
|
||||||
'convert_to': attr.convert_none_to_empty_list,
|
'convert_to': attr.convert_none_to_empty_list,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from gbpservice.neutron.plugins.ml2plus.drivers.apic_aim import model
|
|||||||
from gbpservice.neutron.services.grouppolicy.common import (
|
from gbpservice.neutron.services.grouppolicy.common import (
|
||||||
constants as gp_const)
|
constants as gp_const)
|
||||||
from gbpservice.neutron.services.grouppolicy.common import constants as g_const
|
from gbpservice.neutron.services.grouppolicy.common import constants as g_const
|
||||||
|
from gbpservice.neutron.services.grouppolicy.common import exceptions as exc
|
||||||
from gbpservice.neutron.services.grouppolicy.drivers import (
|
from gbpservice.neutron.services.grouppolicy.drivers import (
|
||||||
neutron_resources as nrd)
|
neutron_resources as nrd)
|
||||||
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
|
from gbpservice.neutron.services.grouppolicy.drivers.cisco.apic import (
|
||||||
@@ -41,6 +42,7 @@ REVERSE = 'Reverse'
|
|||||||
FILTER_DIRECTIONS = {FORWARD: False, REVERSE: True}
|
FILTER_DIRECTIONS = {FORWARD: False, REVERSE: True}
|
||||||
FORWARD_FILTER_ENTRIES = 'Forward-FilterEntries'
|
FORWARD_FILTER_ENTRIES = 'Forward-FilterEntries'
|
||||||
REVERSE_FILTER_ENTRIES = 'Reverse-FilterEntries'
|
REVERSE_FILTER_ENTRIES = 'Reverse-FilterEntries'
|
||||||
|
ADDR_SCOPE_KEYS = ['address_scope_v4_id', 'address_scope_v6_id']
|
||||||
|
|
||||||
# Definitions duplicated from apicapi lib
|
# Definitions duplicated from apicapi lib
|
||||||
APIC_OWNED = 'apic_owned_'
|
APIC_OWNED = 'apic_owned_'
|
||||||
@@ -82,6 +84,76 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
|||||||
def aim_display_name(self, name):
|
def aim_display_name(self, name):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
@log.log_method_call
|
||||||
|
def create_l3_policy_precommit(self, context):
|
||||||
|
l3p = context.current
|
||||||
|
l3p_db = context._plugin._get_l3_policy(
|
||||||
|
context._plugin_context, l3p['id'])
|
||||||
|
ascp = 'address_scope_v4_id' if l3p['ip_version'] == 4 else (
|
||||||
|
'address_scope_v6_id')
|
||||||
|
if not l3p[ascp]:
|
||||||
|
# REVISIT: For dual stack.
|
||||||
|
# This logic assumes either 4 or 6 but not both
|
||||||
|
self._use_implicit_address_scope(context, clean_session=False)
|
||||||
|
l3p_db[ascp] = l3p[ascp]
|
||||||
|
subpool = 'subnetpools_v4' if l3p['ip_version'] == 4 else (
|
||||||
|
'subnetpools_v6')
|
||||||
|
if not l3p[subpool]:
|
||||||
|
# REVISIT: For dual stack.
|
||||||
|
# This logic assumes either 4 or 6 but not both
|
||||||
|
self._use_implicit_subnetpool(
|
||||||
|
context, address_scope_id=l3p_db[ascp],
|
||||||
|
ip_version=l3p['ip_version'], clean_session=False)
|
||||||
|
# REVISIT: Check if the following constraint still holds
|
||||||
|
if len(l3p['routers']) > 1:
|
||||||
|
raise exc.L3PolicyMultipleRoutersNotSupported()
|
||||||
|
# REVISIT: Validate non overlapping IPs in the same tenant.
|
||||||
|
# Currently this validation is not required for the
|
||||||
|
# AIM driver, and since the AIM driver is the only
|
||||||
|
# driver inheriting from this driver, we are okay
|
||||||
|
# without the check.
|
||||||
|
self._reject_invalid_router_access(context, clean_session=False)
|
||||||
|
if not l3p['routers']:
|
||||||
|
self._use_implicit_router(context, clean_session=False)
|
||||||
|
|
||||||
|
@log.log_method_call
|
||||||
|
def update_l3_policy_precommit(self, context):
|
||||||
|
if context.current['routers'] != context.original['routers']:
|
||||||
|
raise exc.L3PolicyRoutersUpdateNotSupported()
|
||||||
|
# Currently there is no support for router update in l3p update.
|
||||||
|
# Added this check just in case it is supported in future.
|
||||||
|
self._reject_invalid_router_access(context, clean_session=False)
|
||||||
|
# TODO(Sumit): For extra safety add validation for address_scope change
|
||||||
|
|
||||||
|
@log.log_method_call
|
||||||
|
def delete_l3_policy_precommit(self, context):
|
||||||
|
l3p_db = context._plugin._get_l3_policy(
|
||||||
|
context._plugin_context, context.current['id'])
|
||||||
|
v4v6subpools = {4: l3p_db.subnetpools_v4, 6: l3p_db.subnetpools_v6}
|
||||||
|
for k, v in v4v6subpools.iteritems():
|
||||||
|
subpools = [sp.subnetpool_id for sp in v]
|
||||||
|
for sp_id in subpools:
|
||||||
|
self._db_plugin(
|
||||||
|
context._plugin)._remove_subnetpool_from_l3_policy(
|
||||||
|
context._plugin_context, l3p_db['id'], sp_id,
|
||||||
|
ip_version=k)
|
||||||
|
self._cleanup_subnetpool(context._plugin_context, sp_id,
|
||||||
|
clean_session=False)
|
||||||
|
for ascp in ADDR_SCOPE_KEYS:
|
||||||
|
if l3p_db[ascp]:
|
||||||
|
ascp_id = l3p_db[ascp]
|
||||||
|
l3p_db.update({ascp: None})
|
||||||
|
self._cleanup_address_scope(context._plugin_context, ascp_id,
|
||||||
|
clean_session=False)
|
||||||
|
routers = [router.router_id for router in l3p_db.routers]
|
||||||
|
for router_id in routers:
|
||||||
|
self._db_plugin(context._plugin)._remove_router_from_l3_policy(
|
||||||
|
context._plugin_context, l3p_db['id'], router_id)
|
||||||
|
self._cleanup_router(context._plugin_context, router_id,
|
||||||
|
clean_session=False)
|
||||||
|
|
||||||
|
# TODO(Sumit): Implement get_l3_policy_status()
|
||||||
|
|
||||||
@log.log_method_call
|
@log.log_method_call
|
||||||
def create_l2_policy_precommit(self, context):
|
def create_l2_policy_precommit(self, context):
|
||||||
super(AIMMappingDriver, self).create_l2_policy_precommit(context)
|
super(AIMMappingDriver, self).create_l2_policy_precommit(context)
|
||||||
@@ -117,6 +189,8 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
|||||||
context, context.current, default_epg_dn)
|
context, context.current, default_epg_dn)
|
||||||
super(AIMMappingDriver, self).delete_l2_policy_precommit(context)
|
super(AIMMappingDriver, self).delete_l2_policy_precommit(context)
|
||||||
|
|
||||||
|
# TODO(Sumit): Implement get_l2_policy_status()
|
||||||
|
|
||||||
@log.log_method_call
|
@log.log_method_call
|
||||||
def create_policy_target_group_precommit(self, context):
|
def create_policy_target_group_precommit(self, context):
|
||||||
if context.current['subnets']:
|
if context.current['subnets']:
|
||||||
@@ -208,6 +282,7 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
|||||||
for subnet_id in subnet_ids:
|
for subnet_id in subnet_ids:
|
||||||
if not context._plugin._get_ptgs_for_subnet(
|
if not context._plugin._get_ptgs_for_subnet(
|
||||||
context._plugin_context, subnet_id):
|
context._plugin_context, subnet_id):
|
||||||
|
# TODO(Sumit): pass router_id of default router
|
||||||
self._cleanup_subnet(plugin_context, subnet_id,
|
self._cleanup_subnet(plugin_context, subnet_id,
|
||||||
clean_session=False)
|
clean_session=False)
|
||||||
|
|
||||||
@@ -258,11 +333,6 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
|||||||
if pt_db['port_id']:
|
if pt_db['port_id']:
|
||||||
self._cleanup_port(context._plugin_context, pt_db['port_id'])
|
self._cleanup_port(context._plugin_context, pt_db['port_id'])
|
||||||
|
|
||||||
@log.log_method_call
|
|
||||||
def delete_l3_policy_precommit(self, context):
|
|
||||||
# TODO(Sumit): Implement
|
|
||||||
pass
|
|
||||||
|
|
||||||
@log.log_method_call
|
@log.log_method_call
|
||||||
def update_policy_classifier_precommit(self, context):
|
def update_policy_classifier_precommit(self, context):
|
||||||
o_dir = context.original['direction']
|
o_dir = context.original['direction']
|
||||||
@@ -694,12 +764,14 @@ class AIMMappingDriver(nrd.CommonNeutronBase):
|
|||||||
context._plugin_context, l2p_id)
|
context._plugin_context, l2p_id)
|
||||||
name = APIC_OWNED + l2p['name']
|
name = APIC_OWNED + l2p['name']
|
||||||
added = super(
|
added = super(
|
||||||
AIMMappingDriver, self)._use_implicit_subnet(
|
AIMMappingDriver,
|
||||||
|
self)._use_implicit_subnet_from_subnetpool(
|
||||||
context, subnet_specifics={'name': name},
|
context, subnet_specifics={'name': name},
|
||||||
is_proxy=False, clean_session=clean_session)
|
clean_session=clean_session)
|
||||||
context.add_subnets(subs - set(context.current['subnets']))
|
context.add_subnets(subs - set(context.current['subnets']))
|
||||||
for subnet in added:
|
for subnet in added:
|
||||||
self._sync_ptg_subnets(context, l2p)
|
self._sync_ptg_subnets(context, l2p)
|
||||||
|
# TODO(Sumit): This subnet needs to added to the default router
|
||||||
|
|
||||||
def _create_implicit_contracts_and_configure_default_epg(
|
def _create_implicit_contracts_and_configure_default_epg(
|
||||||
self, context, l2p, epg_dn):
|
self, context, l2p, epg_dn):
|
||||||
|
|||||||
@@ -44,8 +44,13 @@ class CommonNeutronBase(ipd.ImplicitPolicyBase, rmd.OwnedResourcesOperations,
|
|||||||
if not context.current['l3_policy_id']:
|
if not context.current['l3_policy_id']:
|
||||||
self._create_implicit_l3_policy(context, clean_session=False)
|
self._create_implicit_l3_policy(context, clean_session=False)
|
||||||
l2p_db['l3_policy_id'] = context.current['l3_policy_id']
|
l2p_db['l3_policy_id'] = context.current['l3_policy_id']
|
||||||
|
l3p_db = context._plugin._get_l3_policy(
|
||||||
|
context._plugin_context, l2p_db['l3_policy_id'])
|
||||||
if not context.current['network_id']:
|
if not context.current['network_id']:
|
||||||
self._use_implicit_network(context, clean_session=False)
|
self._use_implicit_network(
|
||||||
|
context, address_scope_v4=l3p_db['address_scope_v4_id'],
|
||||||
|
address_scope_v6=l3p_db['address_scope_v6_id'],
|
||||||
|
clean_session=False)
|
||||||
l2p_db['network_id'] = context.current['network_id']
|
l2p_db['network_id'] = context.current['network_id']
|
||||||
|
|
||||||
@log.log_method_call
|
@log.log_method_call
|
||||||
|
|||||||
@@ -85,6 +85,26 @@ class OwnedNetwork(model_base.BASEV2):
|
|||||||
nullable=False, primary_key=True)
|
nullable=False, primary_key=True)
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
class OwnedRouter(model_base.BASEV2):
|
class OwnedRouter(model_base.BASEV2):
|
||||||
"""A Router owned by the resource_mapping driver."""
|
"""A Router owned by the resource_mapping driver."""
|
||||||
|
|
||||||
@@ -115,6 +135,10 @@ class CidrInUse(exc.GroupPolicyInternalError):
|
|||||||
|
|
||||||
class OwnedResourcesOperations(object):
|
class OwnedResourcesOperations(object):
|
||||||
|
|
||||||
|
# TODO(Sumit): All the following operations can be condensed into
|
||||||
|
# a single _mark_resource_owned() and _resource_is_owned() method,
|
||||||
|
# by creating a resource to DB class name mapping.
|
||||||
|
|
||||||
def _mark_port_owned(self, session, port_id):
|
def _mark_port_owned(self, session, port_id):
|
||||||
with session.begin(subtransactions=True):
|
with session.begin(subtransactions=True):
|
||||||
owned = OwnedPort(port_id=port_id)
|
owned = OwnedPort(port_id=port_id)
|
||||||
@@ -159,9 +183,89 @@ class OwnedResourcesOperations(object):
|
|||||||
filter_by(router_id=router_id).
|
filter_by(router_id=router_id).
|
||||||
first() is not None)
|
first() is not None)
|
||||||
|
|
||||||
|
def _mark_address_scope_owned(self, session, address_scope_id):
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
owned = OwnedAddressScope(address_scope_id=address_scope_id)
|
||||||
|
session.add(owned)
|
||||||
|
|
||||||
|
def _address_scope_is_owned(self, session, address_scope_id):
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
return (session.query(OwnedAddressScope).
|
||||||
|
filter_by(address_scope_id=address_scope_id).
|
||||||
|
first() is not None)
|
||||||
|
|
||||||
|
def _mark_subnetpool_owned(self, session, subnetpool_id):
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
owned = OwnedSubnetpool(subnetpool_id=subnetpool_id)
|
||||||
|
session.add(owned)
|
||||||
|
|
||||||
|
def _subnetpool_is_owned(self, session, subnetpool_id):
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
return (session.query(OwnedSubnetpool).
|
||||||
|
filter_by(subnetpool_id=subnetpool_id).
|
||||||
|
first() is not None)
|
||||||
|
|
||||||
|
|
||||||
class ImplicitResourceOperations(local_api.LocalAPI):
|
class ImplicitResourceOperations(local_api.LocalAPI):
|
||||||
|
|
||||||
|
def _create_implicit_address_scope(self, context, clean_session=True,
|
||||||
|
**kwargs):
|
||||||
|
attrs = {'tenant_id': context.current['tenant_id'],
|
||||||
|
'name': context.current['name'], 'ip_version':
|
||||||
|
context.current['ip_version'],
|
||||||
|
'shared': context.current.get('shared', False)}
|
||||||
|
attrs.update(**kwargs)
|
||||||
|
address_scope = self._create_address_scope(
|
||||||
|
context._plugin_context, attrs, clean_session)
|
||||||
|
as_id = address_scope['id']
|
||||||
|
self._mark_address_scope_owned(context._plugin_context.session, as_id)
|
||||||
|
return address_scope
|
||||||
|
|
||||||
|
def _use_implicit_address_scope(self, context, clean_session=True):
|
||||||
|
address_scope = self._create_implicit_address_scope(
|
||||||
|
context, clean_session, name='l3p_' + context.current['name'])
|
||||||
|
context.set_address_scope_id(address_scope['id'])
|
||||||
|
|
||||||
|
def _cleanup_address_scope(self, plugin_context, address_scope_id,
|
||||||
|
clean_session=True):
|
||||||
|
if self._address_scope_is_owned(plugin_context.session,
|
||||||
|
address_scope_id):
|
||||||
|
self._delete_address_scope(plugin_context, address_scope_id,
|
||||||
|
clean_session)
|
||||||
|
|
||||||
|
def _create_implicit_subnetpool(self, context, clean_session=True,
|
||||||
|
**kwargs):
|
||||||
|
attrs = {'tenant_id': context.current['tenant_id'],
|
||||||
|
'name': context.current['name'], 'ip_version':
|
||||||
|
context.current['ip_version'],
|
||||||
|
'default_prefixlen': context.current['subnet_prefix_length'],
|
||||||
|
'prefixes': [context.current['ip_pool']],
|
||||||
|
'shared': context.current.get('shared', False),
|
||||||
|
# Per current understanding, is_default is used for
|
||||||
|
# auto_allocation and is a per-tenant setting.
|
||||||
|
'is_default': False}
|
||||||
|
attrs.update(**kwargs)
|
||||||
|
subnetpool = self._create_subnetpool(
|
||||||
|
context._plugin_context, attrs, clean_session)
|
||||||
|
sp_id = subnetpool['id']
|
||||||
|
self._mark_subnetpool_owned(context._plugin_context.session, sp_id)
|
||||||
|
return subnetpool
|
||||||
|
|
||||||
|
def _use_implicit_subnetpool(self, context, address_scope_id, ip_version,
|
||||||
|
clean_session=True):
|
||||||
|
subnetpool = self._create_implicit_subnetpool(
|
||||||
|
context, clean_session, name='l3p_' + context.current['name'],
|
||||||
|
address_scope_id=address_scope_id)
|
||||||
|
context.add_subnetpool(subnetpool_id=subnetpool['id'],
|
||||||
|
ip_version=ip_version)
|
||||||
|
|
||||||
|
def _cleanup_subnetpool(self, plugin_context, subnetpool_id,
|
||||||
|
clean_session=True):
|
||||||
|
if self._subnetpool_is_owned(plugin_context.session,
|
||||||
|
subnetpool_id):
|
||||||
|
self._delete_subnetpool(plugin_context, subnetpool_id,
|
||||||
|
clean_session)
|
||||||
|
|
||||||
def _create_implicit_network(self, context, clean_session=True, **kwargs):
|
def _create_implicit_network(self, context, clean_session=True, **kwargs):
|
||||||
attrs = {'tenant_id': context.current['tenant_id'],
|
attrs = {'tenant_id': context.current['tenant_id'],
|
||||||
'name': context.current['name'], 'admin_state_up': True,
|
'name': context.current['name'], 'admin_state_up': True,
|
||||||
@@ -173,9 +277,12 @@ class ImplicitResourceOperations(local_api.LocalAPI):
|
|||||||
self._mark_network_owned(context._plugin_context.session, network_id)
|
self._mark_network_owned(context._plugin_context.session, network_id)
|
||||||
return network
|
return network
|
||||||
|
|
||||||
def _use_implicit_network(self, context, clean_session=True):
|
def _use_implicit_network(self, context, address_scope_v4=None,
|
||||||
|
address_scope_v6=None, clean_session=True):
|
||||||
network = self._create_implicit_network(
|
network = self._create_implicit_network(
|
||||||
context, clean_session, name='l2p_' + context.current['name'])
|
context, clean_session, name='l2p_' + context.current['name'],
|
||||||
|
ipv4_address_scope=address_scope_v4,
|
||||||
|
ipv6_address_scope=address_scope_v6)
|
||||||
context.set_network_id(network['id'])
|
context.set_network_id(network['id'])
|
||||||
|
|
||||||
def _cleanup_network(self, plugin_context, network_id, clean_session=True):
|
def _cleanup_network(self, plugin_context, network_id, clean_session=True):
|
||||||
@@ -363,6 +470,53 @@ class ImplicitResourceOperations(local_api.LocalAPI):
|
|||||||
context, is_proxy, prefix_len, subnet_specifics, l2p, l3p,
|
context, is_proxy, prefix_len, subnet_specifics, l2p, l3p,
|
||||||
clean_session=clean_session)
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
def _use_implicit_subnet_from_subnetpool(
|
||||||
|
self, context, subnet_specifics=None, clean_session=True):
|
||||||
|
# If a subnet needs to be created with a prefix_length other than
|
||||||
|
# the subnet_prefix_length set for the l3_policy, a 'prefixlen' can be
|
||||||
|
# passed explicitly in the subnet_specifics dict.
|
||||||
|
# If a subnet with a specific CIDR needs to be created, the 'cidr' can
|
||||||
|
# be passed explicitly in the subnet_specifics dict.
|
||||||
|
# Note that either 'prefixlen' or 'cidr' can be requested, not both.
|
||||||
|
# If a 'subnetpool_id' other than the one considered default is to be
|
||||||
|
# used, it can be passed explicitly in the subnet_specifics dict.
|
||||||
|
subnet_specifics = subnet_specifics or {}
|
||||||
|
l2p_id = context.current['l2_policy_id']
|
||||||
|
l2p = context._plugin.get_l2_policy(context._plugin_context, l2p_id)
|
||||||
|
l3p_id = l2p['l3_policy_id']
|
||||||
|
l3p_db = context._plugin.get_l3_policy(context._plugin_context, l3p_id)
|
||||||
|
# REVISIT: For dual stack
|
||||||
|
# Current assumption is that either v4 or v6 subnet needs to be
|
||||||
|
# allocated, but not both
|
||||||
|
if l3p_db['address_scope_v4_id']:
|
||||||
|
# Since this is implicit assignment, the first subnetpool
|
||||||
|
# is considered as the default and always used (here and in
|
||||||
|
# the v6 case below)
|
||||||
|
subnetpool_id = l3p_db['subnetpools_v4'][0]
|
||||||
|
ip_version = 4
|
||||||
|
else:
|
||||||
|
subnetpool_id = l3p_db['subnetpools_v6'][0]
|
||||||
|
ip_version = 6
|
||||||
|
attrs = {'tenant_id': context.current['tenant_id'],
|
||||||
|
'name': 'ptg_' + context.current['name'],
|
||||||
|
'network_id': l2p['network_id'],
|
||||||
|
'ip_version': ip_version,
|
||||||
|
'subnetpool_id': subnetpool_id,
|
||||||
|
'cidr': attributes.ATTR_NOT_SPECIFIED,
|
||||||
|
'prefixlen': attributes.ATTR_NOT_SPECIFIED,
|
||||||
|
'enable_dhcp': True,
|
||||||
|
'gateway_ip': attributes.ATTR_NOT_SPECIFIED,
|
||||||
|
'allocation_pools': attributes.ATTR_NOT_SPECIFIED,
|
||||||
|
'dns_nameservers': (
|
||||||
|
cfg.CONF.resource_mapping.dns_nameservers or
|
||||||
|
attributes.ATTR_NOT_SPECIFIED),
|
||||||
|
'host_routes': attributes.ATTR_NOT_SPECIFIED}
|
||||||
|
attrs.update(subnet_specifics)
|
||||||
|
subnet = self._create_subnet(context._plugin_context, attrs,
|
||||||
|
clean_session=clean_session)
|
||||||
|
self._mark_subnet_owned(context._plugin_context.session, subnet['id'])
|
||||||
|
return [subnet]
|
||||||
|
|
||||||
def _cleanup_subnet(self, plugin_context, subnet_id, router_id=None,
|
def _cleanup_subnet(self, plugin_context, subnet_id, router_id=None,
|
||||||
clean_session=True):
|
clean_session=True):
|
||||||
interface_info = {'subnet_id': subnet_id}
|
interface_info = {'subnet_id': subnet_id}
|
||||||
@@ -431,6 +585,48 @@ class ImplicitResourceOperations(local_api.LocalAPI):
|
|||||||
except n_exc.PortNotFound:
|
except n_exc.PortNotFound:
|
||||||
LOG.warning(_LW("Port %s is missing") % port_id)
|
LOG.warning(_LW("Port %s is missing") % port_id)
|
||||||
|
|
||||||
|
def _reject_invalid_router_access(self, context, clean_session=True):
|
||||||
|
# Validate if the explicit router(s) belong to the tenant.
|
||||||
|
# Are routers shared across tenants ??
|
||||||
|
# How to check if admin and if admin can access all routers ??
|
||||||
|
for router_id in context.current['routers']:
|
||||||
|
router = None
|
||||||
|
try:
|
||||||
|
router = self._get_router(context._plugin_context, router_id,
|
||||||
|
clean_session=clean_session)
|
||||||
|
except n_exc.NotFound:
|
||||||
|
raise exc.InvalidRouterAccess(
|
||||||
|
msg="Can't access other tenants router",
|
||||||
|
router_id=router_id,
|
||||||
|
tenant_id=context.current['tenant_id'])
|
||||||
|
|
||||||
|
if router:
|
||||||
|
tenant_id_of_explicit_router = router['tenant_id']
|
||||||
|
curr_tenant_id = context.current['tenant_id']
|
||||||
|
if tenant_id_of_explicit_router != curr_tenant_id:
|
||||||
|
raise exc.InvalidRouterAccess(
|
||||||
|
msg="Can't access other tenants router",
|
||||||
|
router_id=router_id,
|
||||||
|
tenant_id=context.current['tenant_id'])
|
||||||
|
|
||||||
|
def _use_implicit_router(self, context, router_name=None,
|
||||||
|
clean_session=True):
|
||||||
|
attrs = {'tenant_id': context.current['tenant_id'],
|
||||||
|
'name': router_name or ('l3p_' + context.current['name']),
|
||||||
|
'external_gateway_info': None,
|
||||||
|
'admin_state_up': True}
|
||||||
|
router = self._create_router(context._plugin_context, attrs,
|
||||||
|
clean_session=clean_session)
|
||||||
|
router_id = router['id']
|
||||||
|
self._mark_router_owned(context._plugin_context.session, router_id)
|
||||||
|
context.add_router(router_id)
|
||||||
|
return router_id
|
||||||
|
|
||||||
|
def _cleanup_router(self, plugin_context, router_id, clean_session=True):
|
||||||
|
if self._router_is_owned(plugin_context.session, router_id):
|
||||||
|
self._delete_router(plugin_context, router_id,
|
||||||
|
clean_session=clean_session)
|
||||||
|
|
||||||
|
|
||||||
class ResourceMappingDriver(api.PolicyDriver, ImplicitResourceOperations,
|
class ResourceMappingDriver(api.PolicyDriver, ImplicitResourceOperations,
|
||||||
nsp_manager.NetworkServicePolicyMappingMixin,
|
nsp_manager.NetworkServicePolicyMappingMixin,
|
||||||
@@ -531,29 +727,6 @@ class ResourceMappingDriver(api.PolicyDriver, ImplicitResourceOperations,
|
|||||||
network_id=context.current['network_id'],
|
network_id=context.current['network_id'],
|
||||||
tenant_id=context.current['tenant_id'])
|
tenant_id=context.current['tenant_id'])
|
||||||
|
|
||||||
def _reject_invalid_router_access(self, context):
|
|
||||||
# Validate if the explicit router(s) belong to the tenant.
|
|
||||||
# Are routers shared across tenants ??
|
|
||||||
# How to check if admin and if admin can access all routers ??
|
|
||||||
for router_id in context.current['routers']:
|
|
||||||
router = None
|
|
||||||
try:
|
|
||||||
router = self._get_router(context._plugin_context, router_id)
|
|
||||||
except n_exc.NotFound:
|
|
||||||
raise exc.InvalidRouterAccess(
|
|
||||||
msg="Can't access other tenants router",
|
|
||||||
router_id=router_id,
|
|
||||||
tenant_id=context.current['tenant_id'])
|
|
||||||
|
|
||||||
if router:
|
|
||||||
tenant_id_of_explicit_router = router['tenant_id']
|
|
||||||
curr_tenant_id = context.current['tenant_id']
|
|
||||||
if tenant_id_of_explicit_router != curr_tenant_id:
|
|
||||||
raise exc.InvalidRouterAccess(
|
|
||||||
msg="Can't access other tenants router",
|
|
||||||
router_id=router_id,
|
|
||||||
tenant_id=context.current['tenant_id'])
|
|
||||||
|
|
||||||
@log.log_method_call
|
@log.log_method_call
|
||||||
def create_policy_target_precommit(self, context):
|
def create_policy_target_precommit(self, context):
|
||||||
self._check_create_policy_target(context)
|
self._check_create_policy_target(context)
|
||||||
@@ -1794,21 +1967,6 @@ class ResourceMappingDriver(api.PolicyDriver, ImplicitResourceOperations,
|
|||||||
self._delete_subnet(context._plugin_context, subnet_id)
|
self._delete_subnet(context._plugin_context, subnet_id)
|
||||||
raise exc.GroupPolicyInternalError()
|
raise exc.GroupPolicyInternalError()
|
||||||
|
|
||||||
def _use_implicit_router(self, context, router_name=None):
|
|
||||||
attrs = {'tenant_id': context.current['tenant_id'],
|
|
||||||
'name': router_name or ('l3p_' + context.current['name']),
|
|
||||||
'external_gateway_info': None,
|
|
||||||
'admin_state_up': True}
|
|
||||||
router = self._create_router(context._plugin_context, attrs)
|
|
||||||
router_id = router['id']
|
|
||||||
self._mark_router_owned(context._plugin_context.session, router_id)
|
|
||||||
context.add_router(router_id)
|
|
||||||
return router_id
|
|
||||||
|
|
||||||
def _cleanup_router(self, plugin_context, router_id):
|
|
||||||
if self._router_is_owned(plugin_context.session, router_id):
|
|
||||||
self._delete_router(plugin_context, router_id)
|
|
||||||
|
|
||||||
def _create_policy_rule_set_sg(self, context, sg_name_prefix):
|
def _create_policy_rule_set_sg(self, context, sg_name_prefix):
|
||||||
return self._create_gbp_sg(
|
return self._create_gbp_sg(
|
||||||
context._plugin_context, context.current['tenant_id'],
|
context._plugin_context, context.current['tenant_id'],
|
||||||
|
|||||||
@@ -130,6 +130,29 @@ class L3PolicyContext(GroupPolicyContext, api.L3PolicyContext):
|
|||||||
def original(self):
|
def original(self):
|
||||||
return self._original_l3_policy
|
return self._original_l3_policy
|
||||||
|
|
||||||
|
def set_address_scope_id(self, address_scope_id, version=4):
|
||||||
|
self._plugin._set_address_scope_for_l3_policy(
|
||||||
|
self._plugin_context, self._l3_policy['id'], address_scope_id,
|
||||||
|
ip_version=version)
|
||||||
|
if version == 4:
|
||||||
|
self._l3_policy['address_scope_v4_id'] = address_scope_id
|
||||||
|
else:
|
||||||
|
self._l3_policy['address_scope_v6_id'] = address_scope_id
|
||||||
|
|
||||||
|
def add_subnetpool(self, subnetpool_id, ip_version=4):
|
||||||
|
subnetpools = self._plugin._add_subnetpool_to_l3_policy(
|
||||||
|
self._plugin_context, self._l3_policy['id'], subnetpool_id,
|
||||||
|
ip_version=ip_version)
|
||||||
|
self._l3_policy['subnetpools_v4'] = subnetpools[4]
|
||||||
|
self._l3_policy['subnetpools_v6'] = subnetpools[6]
|
||||||
|
|
||||||
|
def remove_subnetpool(self, subnetpool_id, ip_version=4):
|
||||||
|
subnetpools = self._plugin._remove_subnetpool_to_l3_policy(
|
||||||
|
self._plugin_context, self._l3_policy['id'], subnetpool_id,
|
||||||
|
ip_version=ip_version)
|
||||||
|
self._l3_policy['subnetpools_v4'] = subnetpools[4]
|
||||||
|
self._l3_policy['subnetpools_v6'] = subnetpools[6]
|
||||||
|
|
||||||
def add_router(self, router_id):
|
def add_router(self, router_id):
|
||||||
routers = self._plugin._add_router_to_l3_policy(
|
routers = self._plugin._add_router_to_l3_policy(
|
||||||
self._plugin_context, self._l3_policy['id'], router_id)
|
self._plugin_context, self._l3_policy['id'], router_id)
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ class GroupPolicyDbTestCase(GroupPolicyDBTestBase,
|
|||||||
plugins = manager.NeutronManager.get_service_plugins()
|
plugins = manager.NeutronManager.get_service_plugins()
|
||||||
self._gbp_plugin = plugins.get(constants.GROUP_POLICY)
|
self._gbp_plugin = plugins.get(constants.GROUP_POLICY)
|
||||||
self._sc_plugin = plugins.get(constants.SERVICECHAIN)
|
self._sc_plugin = plugins.get(constants.SERVICECHAIN)
|
||||||
|
self._l3_plugin = plugins.get(constants.L3_ROUTER_NAT)
|
||||||
|
|
||||||
|
|
||||||
class TestGroupResources(GroupPolicyDbTestCase):
|
class TestGroupResources(GroupPolicyDbTestCase):
|
||||||
|
|||||||
@@ -220,6 +220,99 @@ class TestAIMStatus(AIMBaseTestCase):
|
|||||||
self.aim_mgr.get_status = orig_get_status
|
self.aim_mgr.get_status = orig_get_status
|
||||||
|
|
||||||
|
|
||||||
|
class TestL3Policy(AIMBaseTestCase):
|
||||||
|
|
||||||
|
def test_create_l3_policy_lifecycle_implicit_address_scope(self):
|
||||||
|
# Create L3 policy with implicit router.
|
||||||
|
l3p = self.create_l3_policy(name="l3p1")['l3_policy']
|
||||||
|
l3p_id = l3p['id']
|
||||||
|
self.assertIsNone(l3p['address_scope_v6_id'])
|
||||||
|
ascp_id = l3p['address_scope_v4_id']
|
||||||
|
self.assertEqual(len(l3p['subnetpools_v4']), 1)
|
||||||
|
sp_id = l3p['subnetpools_v4'][0]
|
||||||
|
self.assertIsNotNone(ascp_id)
|
||||||
|
routers = l3p['routers']
|
||||||
|
self.assertIsNotNone(routers)
|
||||||
|
self.assertEqual(len(routers), 1)
|
||||||
|
router_id = routers[0]
|
||||||
|
"""
|
||||||
|
# TODO(Sumit): Address-scope retrieval is creating issues, requires
|
||||||
|
# some fixing in the UT setup
|
||||||
|
req = self.new_show_request('address-scopes', ascp_id, fmt=self.fmt)
|
||||||
|
res = self.deserialize(self.fmt, req.get_response(self.api))
|
||||||
|
ascope = res['address_scope']
|
||||||
|
"""
|
||||||
|
req = self.new_show_request('subnetpools', sp_id, fmt=self.fmt)
|
||||||
|
res = self.deserialize(self.fmt, req.get_response(self.api))
|
||||||
|
subpool = res['subnetpool']
|
||||||
|
self.assertEqual(l3p['ip_pool'], subpool['prefixes'][0])
|
||||||
|
self.assertEqual(l3p['subnet_prefix_length'],
|
||||||
|
int(subpool['default_prefixlen']))
|
||||||
|
self.assertEqual(l3p['ip_version'],
|
||||||
|
subpool['ip_version'])
|
||||||
|
router = self._get_object('routers', router_id, self.ext_api)['router']
|
||||||
|
self.assertEqual('l3p_l3p1', router['name'])
|
||||||
|
|
||||||
|
# TODO(Sumit): Test update of relevant attributes
|
||||||
|
|
||||||
|
req = self.new_delete_request('l3_policies', l3p_id)
|
||||||
|
res = req.get_response(self.ext_api)
|
||||||
|
self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int)
|
||||||
|
req = self.new_show_request('subnetpools', sp_id, fmt=self.fmt)
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
||||||
|
req = self.new_show_request('address_scopes', ascp_id, fmt=self.fmt)
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
||||||
|
req = self.new_show_request('routers', router_id, fmt=self.fmt)
|
||||||
|
res = req.get_response(self.ext_api)
|
||||||
|
self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int)
|
||||||
|
|
||||||
|
|
||||||
|
class TestL3PolicyRollback(AIMBaseTestCase):
|
||||||
|
|
||||||
|
def test_l3_policy_create_fail(self):
|
||||||
|
orig_func = self.dummy.create_l3_policy_precommit
|
||||||
|
self.dummy.create_l3_policy_precommit = mock.Mock(
|
||||||
|
side_effect=Exception)
|
||||||
|
self.create_l3_policy(name="l3p1", expected_res_status=500)
|
||||||
|
self.assertEqual([], self._plugin.get_address_scopes(self._context))
|
||||||
|
self.assertEqual([], self._plugin.get_subnetpools(self._context))
|
||||||
|
self.assertEqual([], self._l3_plugin.get_routers(self._context))
|
||||||
|
self.assertEqual([], self._gbp_plugin.get_l3_policies(self._context))
|
||||||
|
# restore mock
|
||||||
|
self.dummy.create_l3_policy_precommit = orig_func
|
||||||
|
|
||||||
|
def test_l3_policy_update_fail(self):
|
||||||
|
orig_func = self.dummy.update_l3_policy_precommit
|
||||||
|
self.dummy.update_l3_policy_precommit = mock.Mock(
|
||||||
|
side_effect=Exception)
|
||||||
|
l3p = self.create_l3_policy(name="l3p1")['l3_policy']
|
||||||
|
l3p_id = l3p['id']
|
||||||
|
self.update_l3_policy(l3p_id, expected_res_status=500,
|
||||||
|
name="new name")
|
||||||
|
new_l3p = self.show_l3_policy(l3p_id, expected_res_status=200)
|
||||||
|
self.assertEqual(l3p['name'],
|
||||||
|
new_l3p['l3_policy']['name'])
|
||||||
|
# restore mock
|
||||||
|
self.dummy.update_l3_policy_precommit = orig_func
|
||||||
|
|
||||||
|
def test_l3_policy_delete_fail(self):
|
||||||
|
orig_func = self.dummy.delete_l3_policy_precommit
|
||||||
|
self.dummy.delete_l3_policy_precommit = mock.Mock(
|
||||||
|
side_effect=Exception)
|
||||||
|
l3p = self.create_l3_policy(name="l3p1")['l3_policy']
|
||||||
|
l3p_id = l3p['id']
|
||||||
|
self.delete_l3_policy(l3p_id, expected_res_status=500)
|
||||||
|
self.show_l3_policy(l3p_id, expected_res_status=200)
|
||||||
|
self.assertEqual(
|
||||||
|
1, len(self._plugin.get_address_scopes(self._context)))
|
||||||
|
self.assertEqual(1, len(self._plugin.get_subnetpools(self._context)))
|
||||||
|
self.assertEqual(1, len(self._l3_plugin.get_routers(self._context)))
|
||||||
|
# restore mock
|
||||||
|
self.dummy.delete_l3_policy_precommit = orig_func
|
||||||
|
|
||||||
|
|
||||||
class TestL2PolicyBase(test_nr_base.TestL2Policy, AIMBaseTestCase):
|
class TestL2PolicyBase(test_nr_base.TestL2Policy, AIMBaseTestCase):
|
||||||
|
|
||||||
def _validate_implicit_contracts_exist(self, l2p):
|
def _validate_implicit_contracts_exist(self, l2p):
|
||||||
@@ -366,7 +459,7 @@ class TestL2Policy(TestL2PolicyBase):
|
|||||||
class TestL2PolicyRollback(TestL2PolicyBase):
|
class TestL2PolicyRollback(TestL2PolicyBase):
|
||||||
|
|
||||||
def test_l2_policy_create_fail(self):
|
def test_l2_policy_create_fail(self):
|
||||||
orig_func = self.dummy.create_policy_target_group_precommit
|
orig_func = self.dummy.create_l2_policy_precommit
|
||||||
self.dummy.create_l2_policy_precommit = mock.Mock(
|
self.dummy.create_l2_policy_precommit = mock.Mock(
|
||||||
side_effect=Exception)
|
side_effect=Exception)
|
||||||
self.create_l2_policy(name="l2p1", expected_res_status=500)
|
self.create_l2_policy(name="l2p1", expected_res_status=500)
|
||||||
@@ -474,9 +567,14 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
|
|||||||
|
|
||||||
l2p = self.show_l2_policy(ptg['l2_policy_id'],
|
l2p = self.show_l2_policy(ptg['l2_policy_id'],
|
||||||
expected_res_status=200)['l2_policy']
|
expected_res_status=200)['l2_policy']
|
||||||
|
l3p = self.show_l3_policy(l2p['l3_policy_id'],
|
||||||
|
expected_res_status=200)['l3_policy']
|
||||||
req = self.new_show_request('subnets', ptg['subnets'][0], fmt=self.fmt)
|
req = self.new_show_request('subnets', ptg['subnets'][0], fmt=self.fmt)
|
||||||
res = self.deserialize(self.fmt, req.get_response(self.api))
|
subnet = self.deserialize(self.fmt,
|
||||||
self.assertIsNotNone(res['subnet']['id'])
|
req.get_response(self.api))['subnet']
|
||||||
|
self.assertIsNotNone(subnet['id'])
|
||||||
|
self.assertEqual(l3p['subnetpools_v4'][0],
|
||||||
|
subnet['subnetpool_id'])
|
||||||
ptg_name = ptg['name']
|
ptg_name = ptg['name']
|
||||||
aim_epg_name = str(self.name_mapper.policy_target_group(
|
aim_epg_name = str(self.name_mapper.policy_target_group(
|
||||||
self._neutron_context.session, ptg_id, ptg_name))
|
self._neutron_context.session, ptg_id, ptg_name))
|
||||||
@@ -602,6 +700,17 @@ class TestPolicyTargetGroup(AIMBaseTestCase):
|
|||||||
self.assertIsNotNone(res['subnet']['id'])
|
self.assertIsNotNone(res['subnet']['id'])
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(Sumit): Add tests here which tests different scenarios for subnet
|
||||||
|
# allocation for PTGs
|
||||||
|
# 1. Multiple PTGs share the subnets associated with the l2_policy
|
||||||
|
# 2. Associated subnets are correctly used for IP address allocation
|
||||||
|
# 3. New subnets are created when the last available is exhausted
|
||||||
|
# 4. If multiple subnets are present, all are deleted at the time of
|
||||||
|
# l2_policy deletion
|
||||||
|
# 5. 'prefixlen', 'cidr', and 'subnetpool_id' overrides as a part of
|
||||||
|
# the subnet_specifics dictionary
|
||||||
|
|
||||||
|
|
||||||
class TestPolicyTargetGroupRollback(AIMBaseTestCase):
|
class TestPolicyTargetGroupRollback(AIMBaseTestCase):
|
||||||
|
|
||||||
def test_policy_target_group_create_fail(self):
|
def test_policy_target_group_create_fail(self):
|
||||||
|
|||||||
@@ -103,16 +103,26 @@ class GroupPolicyMappingExtTestCase(tgp.GroupPolicyExtensionTestCase):
|
|||||||
|
|
||||||
def get_create_l3_policy_default_attrs(self):
|
def get_create_l3_policy_default_attrs(self):
|
||||||
attrs = cm.get_create_l3_policy_default_attrs()
|
attrs = cm.get_create_l3_policy_default_attrs()
|
||||||
|
attrs.update({'address_scope_v4_id': None})
|
||||||
|
attrs.update({'address_scope_v6_id': None})
|
||||||
|
attrs.update({'subnetpools_v4': []})
|
||||||
|
attrs.update({'subnetpools_v6': []})
|
||||||
attrs.update({'routers': []})
|
attrs.update({'routers': []})
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def get_create_l3_policy_attrs(self):
|
def get_create_l3_policy_attrs(self):
|
||||||
attrs = cm.get_create_l3_policy_attrs()
|
attrs = cm.get_create_l3_policy_attrs()
|
||||||
|
attrs.update({'address_scope_v4_id': tgp._uuid()})
|
||||||
|
attrs.update({'address_scope_v6_id': tgp._uuid()})
|
||||||
|
attrs.update({'subnetpools_v4': [tgp._uuid(), tgp._uuid()]})
|
||||||
|
attrs.update({'subnetpools_v6': [tgp._uuid(), tgp._uuid()]})
|
||||||
attrs.update({'routers': [tgp._uuid(), tgp._uuid()]})
|
attrs.update({'routers': [tgp._uuid(), tgp._uuid()]})
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def get_update_l3_policy_attrs(self):
|
def get_update_l3_policy_attrs(self):
|
||||||
attrs = cm.get_update_l3_policy_attrs()
|
attrs = cm.get_update_l3_policy_attrs()
|
||||||
|
attrs.update({'subnetpools_v4': [tgp._uuid(), tgp._uuid()]})
|
||||||
|
attrs.update({'subnetpools_v6': [tgp._uuid(), tgp._uuid()]})
|
||||||
attrs.update({'routers': [tgp._uuid(), tgp._uuid()]})
|
attrs.update({'routers': [tgp._uuid(), tgp._uuid()]})
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user