Represent External Connectivity in GBP: PLUGIN
Today, the GBP model only represents east-west traffic policies. This new API and reference implementation allows north-south traffic in a GBP enabled cloud partial implements blueprint external-connectivity Change-Id: I6feac27f89efdc2ad61dad2fc39bf62e280ee2c6
This commit is contained in:
@@ -738,6 +738,7 @@ class GroupPolicyDbPlugin(gpolicy.GroupPolicyPluginBase,
|
||||
external_segment_id=es_db.id,
|
||||
destination=rt['destination'],
|
||||
nexthop=rt['nexthop'] or ADDRESS_NOT_SPECIFIED)
|
||||
|
||||
es_db.external_routes.append(target)
|
||||
|
||||
def _set_ess_for_l3p(self, context, l3p_db, es_dict):
|
||||
@@ -1555,10 +1556,17 @@ class GroupPolicyDbPlugin(gpolicy.GroupPolicyPluginBase,
|
||||
return self._make_external_policy_dict(ep_db)
|
||||
|
||||
@log.log
|
||||
def get_external_policies(self, context, filters=None, fields=None):
|
||||
def get_external_policies(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
marker_obj = self._get_marker_obj(context, 'external_policy', limit,
|
||||
marker)
|
||||
return self._get_collection(context, ExternalPolicy,
|
||||
self._make_external_policy_dict,
|
||||
filters=filters, fields=fields)
|
||||
filters=filters, fields=fields,
|
||||
sorts=sorts, limit=limit,
|
||||
marker_obj=marker_obj,
|
||||
page_reverse=page_reverse)
|
||||
|
||||
@log.log
|
||||
def get_external_policies_count(self, context, filters=None):
|
||||
@@ -1608,10 +1616,17 @@ class GroupPolicyDbPlugin(gpolicy.GroupPolicyPluginBase,
|
||||
return self._make_external_segment_dict(es_db)
|
||||
|
||||
@log.log
|
||||
def get_external_segments(self, context, filters=None, fields=None):
|
||||
def get_external_segments(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
marker_obj = self._get_marker_obj(context, 'external_segment', limit,
|
||||
marker)
|
||||
return self._get_collection(context, ExternalSegment,
|
||||
self._make_external_segment_dict,
|
||||
filters=filters, fields=fields)
|
||||
filters=filters, fields=fields,
|
||||
sorts=sorts, limit=limit,
|
||||
marker_obj=marker_obj,
|
||||
page_reverse=page_reverse)
|
||||
|
||||
@log.log
|
||||
def get_external_segments_count(self, context, filters=None):
|
||||
@@ -1655,10 +1670,17 @@ class GroupPolicyDbPlugin(gpolicy.GroupPolicyPluginBase,
|
||||
return self._make_nat_pool_dict(np_db)
|
||||
|
||||
@log.log
|
||||
def get_nat_pools(self, context, filters=None, fields=None):
|
||||
def get_nat_pools(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
marker_obj = self._get_marker_obj(context, 'nat_pool', limit,
|
||||
marker)
|
||||
return self._get_collection(context, NATPool,
|
||||
self._make_nat_pool_dict,
|
||||
filters=filters, fields=fields)
|
||||
filters=filters, fields=fields,
|
||||
sorts=sorts, limit=limit,
|
||||
marker_obj=marker_obj,
|
||||
page_reverse=page_reverse)
|
||||
|
||||
@log.log
|
||||
def get_nat_pools_count(self, context, filters=None):
|
||||
|
||||
@@ -108,3 +108,23 @@ class InvalidSharedAttributeUpdate(GroupPolicyBadRequest):
|
||||
message = _("Invalid shared attribute update. Shared resource %(id)s is"
|
||||
"referenced by %(rid)s, which is either shared or owned by a "
|
||||
"different tenant.")
|
||||
|
||||
|
||||
class ExternalRouteOverlapsWithL3PIpPool(GroupPolicyBadRequest):
|
||||
message = _("Destination %(destination)s for ES %(es_id)s overlaps with "
|
||||
"L3P %(l3p_id)s.")
|
||||
|
||||
|
||||
class ExternalSegmentSubnetOverlapsWithL3PIpPool(GroupPolicyBadRequest):
|
||||
message = _("Subnet %(subnet)s for ES %(es_id)s overlaps with "
|
||||
"L3P %(l3p_id)s.")
|
||||
|
||||
|
||||
class ExternalRouteNextHopNotInExternalSegment(GroupPolicyBadRequest):
|
||||
message = _("One or more external routes' nexthop are not part of "
|
||||
"subnet %(cidr)s.")
|
||||
|
||||
|
||||
class InvalidL3PExternalIPAddress(GroupPolicyBadRequest):
|
||||
message = _("Address %(ip)s allocated for l3p %(l3p_id)s on segment "
|
||||
"%(es_id)s doesn't belong to the segment subnet %(es_cidr)s")
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
# Copyright (c) 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
# 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
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# 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.
|
||||
# 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.
|
||||
|
||||
from neutron.openstack.common import log
|
||||
from oslo.config import cfg
|
||||
@@ -209,3 +207,48 @@ class ExtensionManager(stevedore.named.NamedExtensionManager):
|
||||
"""Call all extension drivers to extend NSP dictionary."""
|
||||
for driver in self.ordered_ext_drivers:
|
||||
driver.obj.extend_network_service_policy_dict(session, result)
|
||||
|
||||
def process_create_external_segment(self, session, data, result):
|
||||
"""Call all extension drivers during EP creation."""
|
||||
self._call_on_ext_drivers("process_create_external_segment",
|
||||
session, data, result)
|
||||
|
||||
def process_update_external_segment(self, session, data, result):
|
||||
"""Call all extension drivers during EP update."""
|
||||
self._call_on_ext_drivers("process_update_external_segment",
|
||||
session, data, result)
|
||||
|
||||
def extend_external_segment_dict(self, session, result):
|
||||
"""Call all extension drivers to extend EP dictionary."""
|
||||
for driver in self.ordered_ext_drivers:
|
||||
driver.obj.extend_external_segment_dict(session, result)
|
||||
|
||||
def process_create_external_policy(self, session, data, result):
|
||||
"""Call all extension drivers during EP creation."""
|
||||
self._call_on_ext_drivers("process_create_external_policy",
|
||||
session, data, result)
|
||||
|
||||
def process_update_external_policy(self, session, data, result):
|
||||
"""Call all extension drivers during EP update."""
|
||||
self._call_on_ext_drivers("process_update_external_policy",
|
||||
session, data, result)
|
||||
|
||||
def extend_external_policy_dict(self, session, result):
|
||||
"""Call all extension drivers to extend EP dictionary."""
|
||||
for driver in self.ordered_ext_drivers:
|
||||
driver.obj.extend_external_policy_dict(session, result)
|
||||
|
||||
def process_create_nat_pool(self, session, data, result):
|
||||
"""Call all extension drivers during NP creation."""
|
||||
self._call_on_ext_drivers("process_create_nat_pool",
|
||||
session, data, result)
|
||||
|
||||
def process_update_nat_pool(self, session, data, result):
|
||||
"""Call all extension drivers during NP update."""
|
||||
self._call_on_ext_drivers("process_update_nat_pool",
|
||||
session, data, result)
|
||||
|
||||
def extend_nat_pool_dict(self, session, result):
|
||||
"""Call all extension drivers to extend NP dictionary."""
|
||||
for driver in self.ordered_ext_drivers:
|
||||
driver.obj.extend_nat_pool_dict(session, result)
|
||||
@@ -20,6 +20,21 @@ class GroupPolicyContext(object):
|
||||
self._plugin_context = plugin_context
|
||||
|
||||
|
||||
class BaseResouceContext(GroupPolicyContext):
|
||||
def __init__(self, plugin, plugin_context, resource, original=None):
|
||||
super(BaseResouceContext, self).__init__(plugin, plugin_context)
|
||||
self._resource = resource
|
||||
self._original = original
|
||||
|
||||
@property
|
||||
def current(self):
|
||||
return self._resource
|
||||
|
||||
@property
|
||||
def original(self):
|
||||
return self._original
|
||||
|
||||
|
||||
class PolicyTargetContext(GroupPolicyContext, api.PolicyTargetContext):
|
||||
|
||||
def __init__(self, plugin, plugin_context, policy_target,
|
||||
@@ -211,3 +226,15 @@ class PolicyRuleSetContext(GroupPolicyContext, api.PolicyRuleSetContext):
|
||||
@property
|
||||
def original(self):
|
||||
return self._original_policy_rule_set
|
||||
|
||||
|
||||
class ExternalSegmentContext(BaseResouceContext, api.ExternalSegmentContext):
|
||||
pass
|
||||
|
||||
|
||||
class ExternalPolicyContext(BaseResouceContext, api.ExternalPolicyContext):
|
||||
pass
|
||||
|
||||
|
||||
class NatPoolContext(BaseResouceContext, api.NatPoolContext):
|
||||
pass
|
||||
@@ -357,6 +357,102 @@ class PolicyRuleSetContext(object):
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ExternalSegmentContext(object):
|
||||
|
||||
"""Context passed to policy engine for external_segment resource.
|
||||
|
||||
A ExternalSegmentContext instance wraps an external_segment
|
||||
resource.
|
||||
It provides helper methods for accessing other relevant information.
|
||||
Results from expensive operations are cached for convenient access.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def current(self):
|
||||
"""Return the current state of the external_segment.
|
||||
|
||||
Return the current state of the external_segment, as defined by
|
||||
GroupPolicyPlugin.create_external_segment.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractproperty
|
||||
def original(self):
|
||||
"""Return the original state of the external_segment.
|
||||
|
||||
Return the original state of the external_segment, prior to a
|
||||
call to update_external_segment. Method is only valid within
|
||||
calls to update_external_segment_precommit and
|
||||
update_external_segment_postcommit.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ExternalPolicyContext(object):
|
||||
|
||||
"""Context passed to policy engine for external_policy resource.
|
||||
|
||||
A ExternalPolicyContext instance wraps an external_policy
|
||||
resource.
|
||||
It provides helper methods for accessing other relevant information.
|
||||
Results from expensive operations are cached for convenient access.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def current(self):
|
||||
"""Return the current state of the external_policy.
|
||||
|
||||
Return the current state of the external_policy, as defined by
|
||||
GroupPolicyPlugin.create_external_policy.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractproperty
|
||||
def original(self):
|
||||
"""Return the original state of the external_policy.
|
||||
|
||||
Return the original state of the external_policy, prior to a
|
||||
call to update_external_policy. Method is only valid within
|
||||
calls to update_external_policy_precommit and
|
||||
update_external_policy_postcommit.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class NatPoolContext(object):
|
||||
|
||||
"""Context passed to policy engine for nat_pool resource.
|
||||
|
||||
A NatPoolContext instance wraps an nat_pool
|
||||
resource.
|
||||
It provides helper methods for accessing other relevant information.
|
||||
Results from expensive operations are cached for convenient access.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def current(self):
|
||||
"""Return the current state of the nat_pool.
|
||||
|
||||
Return the current state of the nat_pool, as defined by
|
||||
GroupPolicyPlugin.create_nat_pool.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractproperty
|
||||
def original(self):
|
||||
"""Return the original state of the nat_pool.
|
||||
|
||||
Return the original state of the nat_pool, prior to a
|
||||
call to update_nat_pool. Method is only valid within
|
||||
calls to update_nat_pool_precommit and
|
||||
update_nat_pool_postcommit.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class PolicyDriver(object):
|
||||
"""Define stable abstract interface for Group Policy drivers.
|
||||
@@ -843,6 +939,162 @@ class PolicyDriver(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def create_external_segment_precommit(self, context):
|
||||
"""Allocate resources for a new network service policy.
|
||||
|
||||
:param context: ExternalSegmentContext instance describing the
|
||||
new network service policy.
|
||||
"""
|
||||
pass
|
||||
|
||||
def create_external_segment_postcommit(self, context):
|
||||
"""Create a network service policy.
|
||||
|
||||
:param context: ExternalSegmentContext instance describing the
|
||||
new network service policy.
|
||||
"""
|
||||
pass
|
||||
|
||||
def update_external_segment_precommit(self, context):
|
||||
"""Update resources of a network service policy.
|
||||
|
||||
:param context: ExternalSegmentContext instance describing the
|
||||
new state of the ExternalSegment, as well as the original state
|
||||
prior to the update_external_segment call.
|
||||
"""
|
||||
pass
|
||||
|
||||
def update_external_segment_postcommit(self, context):
|
||||
"""Update a network service policy.
|
||||
|
||||
:param context: ExternalSegmentContext instance describing the
|
||||
new state of the ExternalSegment, as well as the original state
|
||||
prior to the update_external_segment call.
|
||||
"""
|
||||
pass
|
||||
|
||||
def delete_external_segment_precommit(self, context):
|
||||
"""Delete resources for a network service policy.
|
||||
|
||||
:param context: ExternalSegmentContext instance describing the
|
||||
current state of the ExternalSegment, prior to the call to
|
||||
delete it.
|
||||
"""
|
||||
pass
|
||||
|
||||
def delete_external_segment_postcommit(self, context):
|
||||
"""Delete a network service policy.
|
||||
|
||||
:param context: ExternalSegmentContext instance describing the
|
||||
current state of the ExternalSegment, prior to the call to
|
||||
delete it.
|
||||
"""
|
||||
pass
|
||||
|
||||
def create_external_policy_precommit(self, context):
|
||||
"""Allocate resources for a new network service policy.
|
||||
|
||||
:param context: ExternalPolicyContext instance describing the
|
||||
new network service policy.
|
||||
"""
|
||||
pass
|
||||
|
||||
def create_external_policy_postcommit(self, context):
|
||||
"""Create a network service policy.
|
||||
|
||||
:param context: ExternalPolicyContext instance describing the
|
||||
new network service policy.
|
||||
"""
|
||||
pass
|
||||
|
||||
def update_external_policy_precommit(self, context):
|
||||
"""Update resources of a network service policy.
|
||||
|
||||
:param context: ExternalPolicyContext instance describing the
|
||||
new state of the ExternalPolicy, as well as the original state
|
||||
prior to the update_external_policy call.
|
||||
"""
|
||||
pass
|
||||
|
||||
def update_external_policy_postcommit(self, context):
|
||||
"""Update a network service policy.
|
||||
|
||||
:param context: ExternalPolicyContext instance describing the
|
||||
new state of the ExternalPolicy, as well as the original state
|
||||
prior to the update_external_policy call.
|
||||
"""
|
||||
pass
|
||||
|
||||
def delete_external_policy_precommit(self, context):
|
||||
"""Delete resources for a network service policy.
|
||||
|
||||
:param context: ExternalPolicyContext instance describing the
|
||||
current state of the ExternalPolicy, prior to the call to
|
||||
delete it.
|
||||
"""
|
||||
pass
|
||||
|
||||
def delete_external_policy_postcommit(self, context):
|
||||
"""Delete a network service policy.
|
||||
|
||||
:param context: ExternalPolicyContext instance describing the
|
||||
current state of the ExternalPolicy, prior to the call to
|
||||
delete it.
|
||||
"""
|
||||
pass
|
||||
|
||||
def create_nat_pool_precommit(self, context):
|
||||
"""Allocate resources for a new network service policy.
|
||||
|
||||
:param context: NatPoolContext instance describing the
|
||||
new network service policy.
|
||||
"""
|
||||
pass
|
||||
|
||||
def create_nat_pool_postcommit(self, context):
|
||||
"""Create a network service policy.
|
||||
|
||||
:param context: NatPoolContext instance describing the
|
||||
new network service policy.
|
||||
"""
|
||||
pass
|
||||
|
||||
def update_nat_pool_precommit(self, context):
|
||||
"""Update resources of a network service policy.
|
||||
|
||||
:param context: NatPoolContext instance describing the
|
||||
new state of the NatPool, as well as the original state
|
||||
prior to the update_nat_pool call.
|
||||
"""
|
||||
pass
|
||||
|
||||
def update_nat_pool_postcommit(self, context):
|
||||
"""Update a network service policy.
|
||||
|
||||
:param context: NatPoolContext instance describing the
|
||||
new state of the NatPool, as well as the original state
|
||||
prior to the update_nat_pool call.
|
||||
"""
|
||||
pass
|
||||
|
||||
def delete_nat_pool_precommit(self, context):
|
||||
"""Delete resources for a network service policy.
|
||||
|
||||
:param context: NatPoolContext instance describing the
|
||||
current state of the NatPool, prior to the call to
|
||||
delete it.
|
||||
"""
|
||||
pass
|
||||
|
||||
def delete_nat_pool_postcommit(self, context):
|
||||
"""Delete a network service policy.
|
||||
|
||||
:param context: NatPoolContext instance describing the
|
||||
current state of the NatPool, prior to the call to
|
||||
delete it.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ExtensionDriver(object):
|
||||
@@ -1248,3 +1500,129 @@ class ExtensionDriver(object):
|
||||
network_service_policy operation.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_create_external_segment(self, session, data, result):
|
||||
"""Process extended attributes for external_segment creation.
|
||||
|
||||
:param session: database session
|
||||
:param data: dictionary of incoming external_segment data
|
||||
:param result: external_segment dictionary to extend
|
||||
|
||||
Called inside transaction context on session to validate and
|
||||
persist any extended external_segment attributes defined
|
||||
by this driver. Extended attribute values must also be added
|
||||
to result.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_update_external_segment(self, session, data, result):
|
||||
"""Process extended attributes for external_segment update.
|
||||
|
||||
:param session: database session
|
||||
:param data: dictionary of incoming external_segment data
|
||||
:param result: external_segment dictionary to extend
|
||||
|
||||
Called inside transaction context on session to validate and
|
||||
update any extended external_segment attributes defined by this
|
||||
driver. Extended attribute values, whether updated or not,
|
||||
must also be added to result.
|
||||
"""
|
||||
pass
|
||||
|
||||
def extend_external_segment_dict(self, session, result):
|
||||
"""Add extended attributes to external_segment dictionary.
|
||||
|
||||
:param session: database session
|
||||
:param result: external_segment dictionary to extend
|
||||
|
||||
Called inside transaction context on session to add any
|
||||
extended attributes defined by this driver to a
|
||||
external_segment dictionary to be used for mechanism
|
||||
driver calls and/or returned as the result of a
|
||||
external_segment operation.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_create_external_policy(self, session, data, result):
|
||||
"""Process extended attributes for external_policy creation.
|
||||
|
||||
:param session: database session
|
||||
:param data: dictionary of incoming external_policy data
|
||||
:param result: external_policy dictionary to extend
|
||||
|
||||
Called inside transaction context on session to validate and
|
||||
persist any extended external_policy attributes defined
|
||||
by this driver. Extended attribute values must also be added
|
||||
to result.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_update_external_policy(self, session, data, result):
|
||||
"""Process extended attributes for external_policy update.
|
||||
|
||||
:param session: database session
|
||||
:param data: dictionary of incoming external_policy data
|
||||
:param result: external_policy dictionary to extend
|
||||
|
||||
Called inside transaction context on session to validate and
|
||||
update any extended external_policy attributes defined by this
|
||||
driver. Extended attribute values, whether updated or not,
|
||||
must also be added to result.
|
||||
"""
|
||||
pass
|
||||
|
||||
def extend_external_policy_dict(self, session, result):
|
||||
"""Add extended attributes to external_policy dictionary.
|
||||
|
||||
:param session: database session
|
||||
:param result: external_policy dictionary to extend
|
||||
|
||||
Called inside transaction context on session to add any
|
||||
extended attributes defined by this driver to a
|
||||
external_policy dictionary to be used for mechanism
|
||||
driver calls and/or returned as the result of a
|
||||
external_policy operation.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_create_nat_pool(self, session, data, result):
|
||||
"""Process extended attributes for nat_pool creation.
|
||||
|
||||
:param session: database session
|
||||
:param data: dictionary of incoming nat_pool data
|
||||
:param result: nat_pool dictionary to extend
|
||||
|
||||
Called inside transaction context on session to validate and
|
||||
persist any extended nat_pool attributes defined
|
||||
by this driver. Extended attribute values must also be added
|
||||
to result.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_update_nat_pool(self, session, data, result):
|
||||
"""Process extended attributes for nat_pool update.
|
||||
|
||||
:param session: database session
|
||||
:param data: dictionary of incoming nat_pool data
|
||||
:param result: nat_pool dictionary to extend
|
||||
|
||||
Called inside transaction context on session to validate and
|
||||
update any extended nat_pool attributes defined by this
|
||||
driver. Extended attribute values, whether updated or not,
|
||||
must also be added to result.
|
||||
"""
|
||||
pass
|
||||
|
||||
def extend_nat_pool_dict(self, session, result):
|
||||
"""Add extended attributes to nat_pool dictionary.
|
||||
|
||||
:param session: database session
|
||||
:param result: nat_pool dictionary to extend
|
||||
|
||||
Called inside transaction context on session to add any
|
||||
extended attributes defined by this driver to a
|
||||
nat_pool dictionary to be used for mechanism
|
||||
driver calls and/or returned as the result of a
|
||||
nat_pool operation.
|
||||
"""
|
||||
pass
|
||||
@@ -10,11 +10,14 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import netaddr
|
||||
|
||||
from neutron.api.v2 import attributes as nattr
|
||||
from neutron.common import log
|
||||
from neutron.openstack.common import excutils
|
||||
from neutron.openstack.common import log as logging
|
||||
|
||||
from gbp.neutron.db.grouppolicy import group_policy_db as gdb
|
||||
from gbp.neutron.db.grouppolicy import group_policy_mapping_db
|
||||
from gbp.neutron.services.grouppolicy.common import exceptions as gp_exc
|
||||
from gbp.neutron.services.grouppolicy import extension_manager as ext_manager
|
||||
@@ -54,7 +57,8 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
||||
# <attribute> is the field on the <to_check> dictionary that can be used
|
||||
# to retrieve the UUID/s of the specific object <type>
|
||||
|
||||
usage_graph = {'l3_policy': {},
|
||||
usage_graph = {'l3_policy': {'external_segments':
|
||||
'external_segment'},
|
||||
'l2_policy': {'l3_policy_id': 'l3_policy'},
|
||||
'policy_target_group': {
|
||||
'network_service_policy_id': 'network_service_policy',
|
||||
@@ -70,6 +74,13 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
||||
'policy_rule_set': {
|
||||
'parent_id': 'policy_rule_set',
|
||||
'policy_rules': 'policy_rule'},
|
||||
'external_segment': {},
|
||||
'external_policy': {
|
||||
'external_segments': 'external_segment',
|
||||
'provided_policy_rule_sets': 'policy_rule_set',
|
||||
'consumed_policy_rule_sets': 'policy_rule_set'},
|
||||
'nat_pool': {'external_segment_id':
|
||||
'external_segment'}
|
||||
}
|
||||
_plurals = None
|
||||
|
||||
@@ -101,7 +112,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
||||
def _validate_shared_update(self, context, original, updated, identity):
|
||||
if updated.get('shared'):
|
||||
# Even though the shared attribute may not be changed, the objects
|
||||
# it is referring to might. For this reason we run the reference
|
||||
# it is referring to might. For this reson we run the reference
|
||||
# validation every time a shared resource is updated
|
||||
# TODO(ivar): run only when relevant updates happen
|
||||
self._validate_shared_create(context, updated, identity)
|
||||
@@ -139,6 +150,10 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
||||
context, obj, self.get_policy_target_groups, 'id',
|
||||
obj['providing_policy_target_groups'] +
|
||||
obj['consuming_policy_target_groups'])
|
||||
self._check_shared_or_different_tenant(
|
||||
context, obj, self.get_external_policies, 'id',
|
||||
obj['providing_external_policies'] +
|
||||
obj['consuming_external_policies'])
|
||||
|
||||
def _validate_policy_classifier_unshare(self, context, obj):
|
||||
self._check_shared_or_different_tenant(
|
||||
@@ -154,6 +169,85 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
||||
self._check_shared_or_different_tenant(
|
||||
context, obj, self.get_policy_rules, 'id', r_ids)
|
||||
|
||||
def _validate_external_segment_unshare(self, context, obj):
|
||||
self._check_shared_or_different_tenant(
|
||||
context, obj, self.get_l3_policies, 'id', obj['l3_policies'])
|
||||
self._check_shared_or_different_tenant(
|
||||
context, obj, self.get_external_policies, 'id',
|
||||
obj['external_policies'])
|
||||
self._check_shared_or_different_tenant(
|
||||
context, obj, self.get_nat_pools, 'external_segment_id')
|
||||
|
||||
def _validate_external_policy_unshare(self, context, obj):
|
||||
pass
|
||||
|
||||
def _validate_nat_pool_unshare(self, context, obj):
|
||||
pass
|
||||
|
||||
def _validate_routes(self, context, current, original=None):
|
||||
if original:
|
||||
added = (set((x['destination'], x['nexthop']) for x in
|
||||
current['external_routes']) -
|
||||
set((x['destination'], x['nexthop']) for x in
|
||||
original['external_routes']))
|
||||
else:
|
||||
added = set((x['destination'], x['nexthop']) for x in
|
||||
current['external_routes'])
|
||||
if added:
|
||||
# Verify new ones don't overlap with the existing L3P
|
||||
added_dest = set(x[0] for x in added)
|
||||
# Remove default routes
|
||||
added_dest.discard('0.0.0.0/0')
|
||||
added_dest.discard('::/0')
|
||||
added_ipset = netaddr.IPSet(added_dest)
|
||||
if current['l3_policies']:
|
||||
l3ps = self.get_l3_policies(
|
||||
context, filters={'id': current['l3_policies']})
|
||||
for l3p in l3ps:
|
||||
if netaddr.IPSet([l3p['ip_pool']]) & added_ipset:
|
||||
raise gp_exc.ExternalRouteOverlapsWithL3PIpPool(
|
||||
destination=added_dest, l3p_id=l3p['id'],
|
||||
es_id=current['id'])
|
||||
# Verify NH in ES pool
|
||||
added_nexthop = netaddr.IPSet(x[1] for x in added if x[1])
|
||||
es_subnet = netaddr.IPSet([current['cidr']])
|
||||
if added_nexthop & es_subnet != added_nexthop:
|
||||
raise gp_exc.ExternalRouteNextHopNotInExternalSegment(
|
||||
cidr=current['cidr'])
|
||||
|
||||
def _validate_l3p_es(self, context, current, original=None):
|
||||
if original:
|
||||
added = (set(current['external_segments'].keys()) -
|
||||
set(original['external_segments'].keys()))
|
||||
else:
|
||||
added = set(current['external_segments'].keys())
|
||||
if added:
|
||||
es_list = self.get_external_segments(context,
|
||||
filters={'id': added})
|
||||
l3p_ipset = netaddr.IPSet([current['ip_pool']])
|
||||
for es in es_list:
|
||||
# Verify no route overlap
|
||||
dest_set = set(x['destination'] for x in
|
||||
es['external_routes'])
|
||||
dest_set.discard('0.0.0.0/0')
|
||||
dest_set.discard('::/0')
|
||||
if l3p_ipset & netaddr.IPSet(dest_set):
|
||||
raise gp_exc.ExternalRouteOverlapsWithL3PIpPool(
|
||||
destination=dest_set, l3p_id=current['id'],
|
||||
es_id=es['id'])
|
||||
# Verify segment CIDR doesn't overlap with L3P's
|
||||
if l3p_ipset & netaddr.IPSet([es['cidr']]):
|
||||
raise gp_exc.ExternalSegmentSubnetOverlapsWithL3PIpPool(
|
||||
subnet=es['cidr'], l3p_id=current['id'],
|
||||
es_id=current['id'])
|
||||
# Verify allocated address correctly in subnet
|
||||
for addr in current['external_segments'][es['id']]:
|
||||
if addr != gdb.ADDRESS_NOT_SPECIFIED:
|
||||
if addr not in netaddr.IPNetwork(es['cidr']):
|
||||
raise gp_exc.InvalidL3PExternalIPAddress(
|
||||
ip=addr, es_id=es['id'], l3p_id=current['id'],
|
||||
es_cidr=es['cidr'])
|
||||
|
||||
def __init__(self):
|
||||
self.extension_manager = ext_manager.ExtensionManager()
|
||||
self.policy_driver_manager = manager.PolicyDriverManager()
|
||||
@@ -547,6 +641,7 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
||||
self.extension_manager.process_create_l3_policy(
|
||||
session, l3_policy, result)
|
||||
self._validate_shared_create(context, result, 'l3_policy')
|
||||
self._validate_l3p_es(context, result)
|
||||
policy_context = p_context.L3PolicyContext(self, context,
|
||||
result)
|
||||
self.policy_driver_manager.create_l3_policy_precommit(
|
||||
@@ -575,6 +670,8 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
||||
session, l3_policy, updated_l3_policy)
|
||||
self._validate_shared_update(context, original_l3_policy,
|
||||
updated_l3_policy, 'l3_policy')
|
||||
self._validate_l3p_es(context, updated_l3_policy,
|
||||
original_l3_policy)
|
||||
policy_context = p_context.L3PolicyContext(
|
||||
self, context, updated_l3_policy,
|
||||
original_l3_policy=original_l3_policy)
|
||||
@@ -995,3 +1092,291 @@ class GroupPolicyPlugin(group_policy_mapping_db.GroupPolicyMappingDbPlugin):
|
||||
self.extension_manager.extend_policy_rule_set_dict(
|
||||
session, result)
|
||||
return [self._fields(result, fields) for result in results]
|
||||
|
||||
@log.log
|
||||
def create_external_segment(self, context, external_segment):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
result = super(GroupPolicyPlugin,
|
||||
self).create_external_segment(context,
|
||||
external_segment)
|
||||
self.extension_manager.process_create_external_segment(
|
||||
session, external_segment, result)
|
||||
self._validate_shared_create(context, result,
|
||||
'external_segment')
|
||||
self._validate_routes(context, result)
|
||||
policy_context = p_context.ExternalSegmentContext(
|
||||
self, context, result)
|
||||
(self.policy_driver_manager.
|
||||
create_external_segment_precommit(policy_context))
|
||||
|
||||
try:
|
||||
(self.policy_driver_manager.
|
||||
create_external_segment_postcommit(policy_context))
|
||||
except gp_exc.GroupPolicyDriverError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("create_external_segment_postcommit "
|
||||
"failed, deleting external_segment "
|
||||
"'%s'"), result['id'])
|
||||
self.delete_external_segment(context, result['id'])
|
||||
|
||||
return result
|
||||
|
||||
@log.log
|
||||
def update_external_segment(self, context, external_segment_id,
|
||||
external_segment):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
original_external_segment = super(
|
||||
GroupPolicyPlugin, self).get_external_segment(
|
||||
context, external_segment_id)
|
||||
updated_external_segment = super(
|
||||
GroupPolicyPlugin, self).update_external_segment(
|
||||
context, external_segment_id,
|
||||
external_segment)
|
||||
self.extension_manager.process_update_external_segment(
|
||||
session, external_segment, updated_external_segment)
|
||||
self._validate_shared_update(
|
||||
context, original_external_segment,
|
||||
updated_external_segment, 'external_segment')
|
||||
self._validate_routes(context, updated_external_segment,
|
||||
original_external_segment)
|
||||
# TODO(ivar): Validate Routes' GW in es subnet
|
||||
policy_context = p_context.ExternalSegmentContext(
|
||||
self, context, updated_external_segment,
|
||||
original_external_segment)
|
||||
(self.policy_driver_manager.
|
||||
update_external_segment_precommit(policy_context))
|
||||
|
||||
self.policy_driver_manager.update_external_segment_postcommit(
|
||||
policy_context)
|
||||
return updated_external_segment
|
||||
|
||||
@log.log
|
||||
def delete_external_segment(self, context, external_segment_id):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
es = self.get_external_segment(context, external_segment_id)
|
||||
if es['l3_policies'] or es['nat_pools'] or es['external_policies']:
|
||||
return False
|
||||
policy_context = p_context.ExternalSegmentContext(
|
||||
self, context, es)
|
||||
(self.policy_driver_manager.
|
||||
delete_external_segment_precommit(policy_context))
|
||||
super(GroupPolicyPlugin, self).delete_external_segment(
|
||||
context, external_segment_id)
|
||||
|
||||
try:
|
||||
(self.policy_driver_manager.
|
||||
delete_external_segment_postcommit(policy_context))
|
||||
except gp_exc.GroupPolicyDriverError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("delete_external_segment_postcommit "
|
||||
"failed, deleting external_segment '%s'"),
|
||||
external_segment_id)
|
||||
return True
|
||||
|
||||
def get_external_segment(self, context, external_segment_id, fields=None):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
result = super(GroupPolicyPlugin, self).get_external_segment(
|
||||
context, external_segment_id, None)
|
||||
self.extension_manager.extend_external_segment_dict(session,
|
||||
result)
|
||||
return self._fields(result, fields)
|
||||
|
||||
def get_external_segments(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
results = super(GroupPolicyPlugin, self).get_external_segments(
|
||||
context, filters, None, sorts, limit, marker, page_reverse)
|
||||
for result in results:
|
||||
self.extension_manager.extend_external_segment_dict(
|
||||
session, result)
|
||||
return [self._fields(result, fields) for result in results]
|
||||
|
||||
@log.log
|
||||
def create_external_policy(self, context, external_policy):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
result = super(GroupPolicyPlugin,
|
||||
self).create_external_policy(
|
||||
context, external_policy)
|
||||
self.extension_manager.process_create_external_policy(
|
||||
session, external_policy, result)
|
||||
self._validate_shared_create(context, result,
|
||||
'external_policy')
|
||||
policy_context = p_context.ExternalPolicyContext(
|
||||
self, context, result)
|
||||
(self.policy_driver_manager.
|
||||
create_external_policy_precommit(policy_context))
|
||||
|
||||
try:
|
||||
(self.policy_driver_manager.
|
||||
create_external_policy_postcommit(policy_context))
|
||||
except gp_exc.GroupPolicyDriverError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("create_external_policy_postcommit "
|
||||
"failed, deleting external_policy "
|
||||
"'%s'"), result['id'])
|
||||
self.delete_external_policy(context, result['id'])
|
||||
|
||||
return result
|
||||
|
||||
@log.log
|
||||
def update_external_policy(self, context, external_policy_id,
|
||||
external_policy):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
original_external_policy = super(
|
||||
GroupPolicyPlugin, self).get_external_policy(
|
||||
context, external_policy_id)
|
||||
updated_external_policy = super(
|
||||
GroupPolicyPlugin, self).update_external_policy(
|
||||
context, external_policy_id,
|
||||
external_policy)
|
||||
self.extension_manager.process_update_external_policy(
|
||||
session, external_policy, updated_external_policy)
|
||||
self._validate_shared_update(
|
||||
context, original_external_policy,
|
||||
updated_external_policy, 'external_policy')
|
||||
policy_context = p_context.ExternalPolicyContext(
|
||||
self, context, updated_external_policy,
|
||||
original_external_policy)
|
||||
(self.policy_driver_manager.
|
||||
update_external_policy_precommit(policy_context))
|
||||
|
||||
self.policy_driver_manager.update_external_policy_postcommit(
|
||||
policy_context)
|
||||
return updated_external_policy
|
||||
|
||||
@log.log
|
||||
def delete_external_policy(self, context, external_policy_id,
|
||||
check_unused=False):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
es = self.get_external_policy(context, external_policy_id)
|
||||
policy_context = p_context.ExternalPolicyContext(
|
||||
self, context, es)
|
||||
(self.policy_driver_manager.
|
||||
delete_external_policy_precommit(policy_context))
|
||||
super(GroupPolicyPlugin, self).delete_external_policy(
|
||||
context, external_policy_id)
|
||||
|
||||
try:
|
||||
(self.policy_driver_manager.
|
||||
delete_external_policy_postcommit(policy_context))
|
||||
except gp_exc.GroupPolicyDriverError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("delete_external_policy_postcommit "
|
||||
"failed, deleting external_policy '%s'"),
|
||||
external_policy_id)
|
||||
return True
|
||||
|
||||
def get_external_policy(self, context, external_policy_id, fields=None):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
result = super(GroupPolicyPlugin, self).get_external_policy(
|
||||
context, external_policy_id, None)
|
||||
self.extension_manager.extend_external_policy_dict(session,
|
||||
result)
|
||||
return self._fields(result, fields)
|
||||
|
||||
def get_external_policies(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
results = super(GroupPolicyPlugin, self).get_external_policies(
|
||||
context, filters, None, sorts, limit, marker, page_reverse)
|
||||
for result in results:
|
||||
self.extension_manager.extend_external_policy_dict(
|
||||
session, result)
|
||||
return [self._fields(result, fields) for result in results]
|
||||
|
||||
@log.log
|
||||
def create_nat_pool(self, context, nat_pool):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
result = super(GroupPolicyPlugin, self).create_nat_pool(
|
||||
context, nat_pool)
|
||||
self.extension_manager.process_create_nat_pool(session, nat_pool,
|
||||
result)
|
||||
self._validate_shared_create(context, result, 'nat_pool')
|
||||
policy_context = p_context.NatPoolContext(self, context, result)
|
||||
(self.policy_driver_manager.
|
||||
create_nat_pool_precommit(policy_context))
|
||||
|
||||
try:
|
||||
(self.policy_driver_manager.
|
||||
create_nat_pool_postcommit(policy_context))
|
||||
except gp_exc.GroupPolicyDriverError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("create_nat_pool_postcommit failed, deleting "
|
||||
"nat_pool '%s'"), result['id'])
|
||||
self.delete_nat_pool(context, result['id'])
|
||||
|
||||
return result
|
||||
|
||||
@log.log
|
||||
def update_nat_pool(self, context, nat_pool_id, nat_pool):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
original_nat_pool = super(
|
||||
GroupPolicyPlugin, self).get_nat_pool(context, nat_pool_id)
|
||||
updated_nat_pool = super(
|
||||
GroupPolicyPlugin, self).update_nat_pool(context, nat_pool_id,
|
||||
nat_pool)
|
||||
self.extension_manager.process_update_nat_pool(
|
||||
session, nat_pool, updated_nat_pool)
|
||||
self._validate_shared_update(context, original_nat_pool,
|
||||
updated_nat_pool, 'nat_pool')
|
||||
policy_context = p_context.NatPoolContext(
|
||||
self, context, updated_nat_pool, original_nat_pool)
|
||||
(self.policy_driver_manager.
|
||||
update_nat_pool_precommit(policy_context))
|
||||
|
||||
self.policy_driver_manager.update_nat_pool_postcommit(policy_context)
|
||||
return updated_nat_pool
|
||||
|
||||
@log.log
|
||||
def delete_nat_pool(self, context, nat_pool_id, check_unused=False):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
es = self.get_nat_pool(context, nat_pool_id)
|
||||
policy_context = p_context.NatPoolContext(self, context, es)
|
||||
(self.policy_driver_manager.delete_nat_pool_precommit(
|
||||
policy_context))
|
||||
super(GroupPolicyPlugin, self).delete_nat_pool(context,
|
||||
nat_pool_id)
|
||||
|
||||
try:
|
||||
(self.policy_driver_manager.
|
||||
delete_nat_pool_postcommit(policy_context))
|
||||
except gp_exc.GroupPolicyDriverError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("delete_nat_pool_postcommit failed, deleting "
|
||||
"nat_pool '%s'"), nat_pool_id)
|
||||
return True
|
||||
|
||||
def get_nat_pool(self, context, nat_pool_id, fields=None):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
result = super(GroupPolicyPlugin, self).get_nat_pool(
|
||||
context, nat_pool_id, None)
|
||||
self.extension_manager.extend_nat_pool_dict(session, result)
|
||||
return self._fields(result, fields)
|
||||
|
||||
def get_nat_pools(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None,
|
||||
page_reverse=False):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
results = super(GroupPolicyPlugin, self).get_nat_pools(
|
||||
context, filters, None, sorts, limit, marker, page_reverse)
|
||||
for result in results:
|
||||
self.extension_manager.extend_nat_pool_dict(
|
||||
session, result)
|
||||
return [self._fields(result, fields) for result in results]
|
||||
@@ -310,3 +310,70 @@ class PolicyDriverManager(stevedore.named.NamedExtensionManager):
|
||||
def delete_policy_rule_set_postcommit(self, context):
|
||||
self._call_on_drivers("delete_policy_rule_set_postcommit", context,
|
||||
continue_on_failure=True)
|
||||
|
||||
def create_external_segment_precommit(self, context):
|
||||
self._call_on_drivers("create_external_segment_precommit",
|
||||
context)
|
||||
|
||||
def create_external_segment_postcommit(self, context):
|
||||
self._call_on_drivers("create_external_segment_postcommit",
|
||||
context)
|
||||
|
||||
def update_external_segment_precommit(self, context):
|
||||
self._call_on_drivers("update_external_segment_precommit",
|
||||
context)
|
||||
|
||||
def update_external_segment_postcommit(self, context):
|
||||
self._call_on_drivers("update_external_segment_postcommit",
|
||||
context)
|
||||
|
||||
def delete_external_segment_precommit(self, context):
|
||||
self._call_on_drivers("delete_external_segment_precommit",
|
||||
context)
|
||||
|
||||
def delete_external_segment_postcommit(self, context):
|
||||
self._call_on_drivers("delete_external_segment_postcommit",
|
||||
context, continue_on_failure=True)
|
||||
|
||||
def create_external_policy_precommit(self, context):
|
||||
self._call_on_drivers("create_external_policy_precommit",
|
||||
context)
|
||||
|
||||
def create_external_policy_postcommit(self, context):
|
||||
self._call_on_drivers("create_external_policy_postcommit",
|
||||
context)
|
||||
|
||||
def update_external_policy_precommit(self, context):
|
||||
self._call_on_drivers("update_external_policy_precommit",
|
||||
context)
|
||||
|
||||
def update_external_policy_postcommit(self, context):
|
||||
self._call_on_drivers("update_external_policy_postcommit",
|
||||
context)
|
||||
|
||||
def delete_external_policy_precommit(self, context):
|
||||
self._call_on_drivers("delete_external_policy_precommit",
|
||||
context)
|
||||
|
||||
def delete_external_policy_postcommit(self, context):
|
||||
self._call_on_drivers("delete_external_policy_postcommit",
|
||||
context, continue_on_failure=True)
|
||||
|
||||
def create_nat_pool_precommit(self, context):
|
||||
self._call_on_drivers("create_nat_pool_precommit", context)
|
||||
|
||||
def create_nat_pool_postcommit(self, context):
|
||||
self._call_on_drivers("create_nat_pool_postcommit", context)
|
||||
|
||||
def update_nat_pool_precommit(self, context):
|
||||
self._call_on_drivers("update_nat_pool_precommit", context)
|
||||
|
||||
def update_nat_pool_postcommit(self, context):
|
||||
self._call_on_drivers("update_nat_pool_postcommit", context)
|
||||
|
||||
def delete_nat_pool_precommit(self, context):
|
||||
self._call_on_drivers("delete_nat_pool_precommit", context)
|
||||
|
||||
def delete_nat_pool_postcommit(self, context):
|
||||
self._call_on_drivers("delete_nat_pool_postcommit", context,
|
||||
continue_on_failure=True)
|
||||
@@ -80,6 +80,27 @@ EXTENDED_ATTRIBUTES_2_0 = {
|
||||
'is_visible': True,
|
||||
'enforce_policy': True},
|
||||
},
|
||||
gp.EXTERNAL_SEGMENTS: {
|
||||
'es_extension': {'allow_post': True,
|
||||
'allow_put': True,
|
||||
'default': attr.ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True,
|
||||
'enforce_policy': True},
|
||||
},
|
||||
gp.EXTERNAL_POLICIES: {
|
||||
'ep_extension': {'allow_post': True,
|
||||
'allow_put': True,
|
||||
'default': attr.ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True,
|
||||
'enforce_policy': True},
|
||||
},
|
||||
gp.NAT_POOLS: {
|
||||
'np_extension': {'allow_post': True,
|
||||
'allow_put': True,
|
||||
'default': attr.ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True,
|
||||
'enforce_policy': True},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -373,6 +373,55 @@ class ExtensionDriverTestCase(
|
||||
val = res['network_service_policy']['nsp_extension']
|
||||
self.assertEqual("def", val)
|
||||
|
||||
def test_es_attr(self):
|
||||
self._test_attr('external_segment')
|
||||
|
||||
def test_ep_attr(self):
|
||||
self._test_attr('external_policy')
|
||||
|
||||
def test_np_attr(self):
|
||||
self._test_attr('nat_pool')
|
||||
|
||||
def _test_attr(self, type):
|
||||
# Test create with default value.
|
||||
acronim = _acronim(type)
|
||||
plural = self._get_resource_plural(type)
|
||||
obj = getattr(self, 'create_%s' % type)()
|
||||
id = obj[type]['id']
|
||||
val = obj[type][acronim + '_extension']
|
||||
self.assertEqual("", val)
|
||||
req = self.new_show_request(plural, id)
|
||||
res = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
val = res[type][acronim + '_extension']
|
||||
self.assertEqual("", val)
|
||||
|
||||
# Test list.
|
||||
res = self._list(plural)
|
||||
val = res[plural][0][acronim + '_extension']
|
||||
self.assertEqual("", val)
|
||||
|
||||
# Test create with explict value.
|
||||
kwargs = {acronim + '_extension': "abc"}
|
||||
obj = getattr(self, 'create_%s' % type)(**kwargs)
|
||||
id = obj[type]['id']
|
||||
val = obj[type][acronim + '_extension']
|
||||
self.assertEqual("abc", val)
|
||||
req = self.new_show_request(plural, id)
|
||||
res = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
val = res[type][acronim + '_extension']
|
||||
self.assertEqual("abc", val)
|
||||
|
||||
# Test update.
|
||||
data = {type: {acronim + '_extension': "def"}}
|
||||
req = self.new_update_request(plural, data, id)
|
||||
res = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
val = res[type][acronim + '_extension']
|
||||
self.assertEqual("def", val)
|
||||
req = self.new_show_request(plural, id)
|
||||
res = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
val = res[type][acronim + '_extension']
|
||||
self.assertEqual("def", val)
|
||||
|
||||
|
||||
class TestPolicyTargetExtension(model_base.BASEV2):
|
||||
__tablename__ = 'test_policy_target_extension'
|
||||
@@ -455,6 +504,33 @@ class TestNetworkServicePolicyExtension(model_base.BASEV2):
|
||||
value = sa.Column(sa.String(64))
|
||||
|
||||
|
||||
class TestExternalSegmentExtension(model_base.BASEV2):
|
||||
__tablename__ = 'test_external_segment_extension'
|
||||
es_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('gp_external_segments.id',
|
||||
ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
value = sa.Column(sa.String(64))
|
||||
|
||||
|
||||
class TestExternalPolicyExtension(model_base.BASEV2):
|
||||
__tablename__ = 'test_external_policy_extension'
|
||||
ep_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('gp_external_policies.id',
|
||||
ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
value = sa.Column(sa.String(64))
|
||||
|
||||
|
||||
class TestNatPoolExtension(model_base.BASEV2):
|
||||
__tablename__ = 'test_nat_pool_extension'
|
||||
np_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('gp_nat_pools.id',
|
||||
ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
value = sa.Column(sa.String(64))
|
||||
|
||||
|
||||
class TestExtensionDriver(api.ExtensionDriver):
|
||||
_supported_extension_alias = 'test_extension'
|
||||
|
||||
@@ -677,3 +753,67 @@ class TestExtensionDriver(api.ExtensionDriver):
|
||||
filter_by(nsp_id=result['id']).
|
||||
one())
|
||||
result['nsp_extension'] = record.value
|
||||
|
||||
def process_create_external_segment(self, session, data, result):
|
||||
self._process_create(session, data, result, 'external_segment',
|
||||
TestExternalSegmentExtension)
|
||||
|
||||
def process_update_external_segment(self, session, data, result):
|
||||
self._process_update(session, data, result, 'external_segment',
|
||||
TestExternalSegmentExtension)
|
||||
|
||||
def extend_external_segment_dict(self, session, result):
|
||||
self._extend(session, result, 'external_segment',
|
||||
TestExternalSegmentExtension)
|
||||
|
||||
def process_create_external_policy(self, session, data, result):
|
||||
self._process_create(session, data, result, 'external_policy',
|
||||
TestExternalPolicyExtension)
|
||||
|
||||
def process_update_external_policy(self, session, data, result):
|
||||
self._process_update(session, data, result, 'external_policy',
|
||||
TestExternalPolicyExtension)
|
||||
|
||||
def extend_external_policy_dict(self, session, result):
|
||||
self._extend(session, result, 'external_policy',
|
||||
TestExternalPolicyExtension)
|
||||
|
||||
def process_create_nat_pool(self, session, data, result):
|
||||
self._process_create(session, data, result, 'nat_pool',
|
||||
TestNatPoolExtension)
|
||||
|
||||
def process_update_nat_pool(self, session, data, result):
|
||||
self._process_update(session, data, result, 'nat_pool',
|
||||
TestNatPoolExtension)
|
||||
|
||||
def extend_nat_pool_dict(self, session, result):
|
||||
self._extend(session, result, 'nat_pool', TestNatPoolExtension)
|
||||
|
||||
def _process_create(self, session, data, result, type, klass):
|
||||
acronim = _acronim(type)
|
||||
value = data[type][acronim + '_extension']
|
||||
if not attributes.is_attr_set(value):
|
||||
value = ''
|
||||
kwargs = {acronim + '_id': result['id'], 'value': value}
|
||||
record = klass(**kwargs)
|
||||
session.add(record)
|
||||
result[acronim + '_extension'] = value
|
||||
|
||||
def _process_update(self, session, data, result, type, klass):
|
||||
acronim = _acronim(type)
|
||||
kwargs = {acronim + '_id': result['id']}
|
||||
record = session.query(klass).filter_by(**kwargs).one()
|
||||
value = data[type].get(acronim + '_extension')
|
||||
if value and value != record.value:
|
||||
record.value = value
|
||||
result[acronim + '_extension'] = record.value
|
||||
|
||||
def _extend(self, session, result, type, klass):
|
||||
acronim = _acronim(type)
|
||||
kwargs = {acronim + '_id': result['id']}
|
||||
record = session.query(klass).filter_by(**kwargs).one()
|
||||
result[acronim + '_extension'] = record.value
|
||||
|
||||
|
||||
def _acronim(type):
|
||||
return ''.join([x[0] for x in type.split('_')])
|
||||
@@ -90,8 +90,20 @@ class GroupPolicyPluginTestCase(tgpmdb.GroupPolicyMappingDbTestCase):
|
||||
return self.create_policy_rule_set(policy_rules=[pr['id']],
|
||||
**kwargs)['policy_rule_set']
|
||||
|
||||
def _update_gbp_resource(self, id, type, plural, expected_res_status=None,
|
||||
**kwargs):
|
||||
def _create_external_policy_on_shared(self, **kwargs):
|
||||
es = self.create_external_segment(shared=True)
|
||||
return self.create_external_policy(
|
||||
external_segments=[es['external_segment']['id']],
|
||||
**kwargs)['external_policy']
|
||||
|
||||
def _create_nat_pool_on_shared(self, **kwargs):
|
||||
es = self.create_external_segment(shared=True)
|
||||
return self.create_nat_pool(
|
||||
external_segment_id=es['external_segment']['id'],
|
||||
**kwargs)['nat_pool']
|
||||
|
||||
def _update_gbp_resource_full_response(
|
||||
self, id, type, plural, expected_res_status=None, **kwargs):
|
||||
data = {type: kwargs}
|
||||
# Create PT with bound port
|
||||
req = self.new_update_request(plural, data, id, self.fmt)
|
||||
@@ -101,11 +113,20 @@ class GroupPolicyPluginTestCase(tgpmdb.GroupPolicyMappingDbTestCase):
|
||||
self.assertEqual(res.status_int, expected_res_status)
|
||||
elif res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(code=res.status_int)
|
||||
return self.deserialize(self.fmt, res).get(type)
|
||||
return self.deserialize(self.fmt, res)
|
||||
|
||||
def _update_gbp_resource(self, id, type, plural, expected_res_status=None,
|
||||
**kwargs):
|
||||
return self._update_gbp_resource_full_response(
|
||||
id, type, plural, expected_res_status=expected_res_status,
|
||||
**kwargs).get(type)
|
||||
|
||||
|
||||
class TestL3Policy(GroupPolicyPluginTestCase):
|
||||
|
||||
def _get_es_dict(self, es, addr=None):
|
||||
return {es['external_segment']['id']: addr or []}
|
||||
|
||||
def test_shared_l3_policy_create(self):
|
||||
# Verify default is False
|
||||
l3p = self.create_l3_policy()
|
||||
@@ -114,6 +135,30 @@ class TestL3Policy(GroupPolicyPluginTestCase):
|
||||
l3p = self.create_l3_policy(shared=True)
|
||||
self.assertEqual(True, l3p['l3_policy']['shared'])
|
||||
|
||||
def test_shared_l3p_create_with_es(self):
|
||||
def combination(l3p, es):
|
||||
return {'l3p': l3p, 'es': es}
|
||||
allowed = [combination(False, False), combination(True, True),
|
||||
combination(False, True)]
|
||||
for shared in allowed:
|
||||
es = self.create_external_segment(
|
||||
cidr='172.0.0.0/8', shared=shared['es'])
|
||||
es_dict = self._get_es_dict(es, ['172.0.0.2', '172.0.0.3'])
|
||||
l3p = self.create_l3_policy(
|
||||
external_segments=es_dict, shared=shared['l3p'],
|
||||
expected_res_status=201)['l3_policy']
|
||||
# Verify create successful
|
||||
self.assertEqual(es_dict, l3p['external_segments'])
|
||||
|
||||
def test_shared_l3p_create_with_es_negative(self):
|
||||
# Not allowed: Unshared ES with shared L3P
|
||||
es = self.create_external_segment(cidr='172.0.0.0/8')
|
||||
es_dict = self._get_es_dict(es, ['172.0.0.2', '172.0.0.3'])
|
||||
res = self.create_l3_policy(external_segments=es_dict,
|
||||
shared=True, expected_res_status=400)
|
||||
self.assertEqual('SharedResourceReferenceError',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
def test_shared_l3_policy_update(self):
|
||||
l3p = self.create_l3_policy()['l3_policy']
|
||||
# Accept share if nothing referenced
|
||||
@@ -124,6 +169,36 @@ class TestL3Policy(GroupPolicyPluginTestCase):
|
||||
self.create_l2_policy(l3_policy_id=l3p['id'])
|
||||
self._update_gbp_resource(l3p['id'], 'l3_policy', 'l3_policies',
|
||||
expected_res_status=200, shared=False)
|
||||
es = self.create_external_segment(cidr='172.0.0.0/8')
|
||||
es_dict = self._get_es_dict(es, ['172.0.0.2', '172.0.0.3'])
|
||||
# Set ES
|
||||
l3p = self._update_gbp_resource(l3p['id'], 'l3_policy', 'l3_policies',
|
||||
expected_res_status=200,
|
||||
external_segments=es_dict)
|
||||
self.assertEqual(es_dict, l3p['external_segments'])
|
||||
|
||||
# Share ES
|
||||
self._update_gbp_resource(
|
||||
es['external_segment']['id'], 'external_segment',
|
||||
'external_segments', expected_res_status=200, shared=True)
|
||||
|
||||
# Verify sharing/unsharing successful
|
||||
for shared in [True, False]:
|
||||
self._update_gbp_resource(l3p['id'], 'l3_policy', 'l3_policies',
|
||||
expected_res_status=200, shared=shared)
|
||||
|
||||
# Remove ES
|
||||
l3p = self._update_gbp_resource(l3p['id'], 'l3_policy', 'l3_policies',
|
||||
expected_res_status=200,
|
||||
external_segments={})
|
||||
self.assertEqual({}, l3p['external_segments'])
|
||||
# Verify ES update with sharing successful
|
||||
l3p = self._update_gbp_resource(l3p['id'], 'l3_policy', 'l3_policies',
|
||||
expected_res_status=200,
|
||||
external_segments=es_dict,
|
||||
shared=True)
|
||||
# Verify ES correctly set
|
||||
self.assertEqual(es_dict, l3p['external_segments'])
|
||||
|
||||
def test_shared_l3_policy_update_negative(self):
|
||||
l3p = self.create_l3_policy(shared=True)['l3_policy']
|
||||
@@ -140,6 +215,69 @@ class TestL3Policy(GroupPolicyPluginTestCase):
|
||||
self._update_gbp_resource(l3p['id'], 'l3_policy', 'l3_policies',
|
||||
expected_res_status=400, shared=False)
|
||||
|
||||
es = self.create_external_segment(cidr='172.0.0.0/8')
|
||||
es_dict = self._get_es_dict(es, ['172.0.0.2', '172.0.0.3'])
|
||||
res = self._update_gbp_resource_full_response(
|
||||
l3p['id'], 'l3_policy', 'l3_policies', expected_res_status=400,
|
||||
external_segments=es_dict, shared=True)
|
||||
self.assertEqual('SharedResourceReferenceError',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
def test_create_with_es_negative(self):
|
||||
attrs = {'external_routes': [{'destination': '10.160.0.0/16',
|
||||
'nexthop': '172.1.1.1'}],
|
||||
'cidr': '172.1.1.0/24'}
|
||||
es = self.create_external_segment(**attrs)['external_segment']
|
||||
# Overlapping pool
|
||||
attrs = {'ip_pool': '172.1.1.0/20',
|
||||
'external_segments': {es['id']: ['172.1.1.2']}}
|
||||
res = self.create_l3_policy(expected_res_status=400, **attrs)
|
||||
self.assertEqual('ExternalSegmentSubnetOverlapsWithL3PIpPool',
|
||||
res['NeutronError']['type'])
|
||||
# Overlapping route
|
||||
attrs['ip_pool'] = '10.160.1.0/24'
|
||||
res = self.create_l3_policy(expected_res_status=400, **attrs)
|
||||
self.assertEqual('ExternalRouteOverlapsWithL3PIpPool',
|
||||
res['NeutronError']['type'])
|
||||
# Allocated address not in pool
|
||||
attrs = {'ip_pool': '192.168.0.0/24',
|
||||
'external_segments': {es['id']: ['172.1.2.2']}}
|
||||
res = self.create_l3_policy(expected_res_status=400, **attrs)
|
||||
self.assertEqual('InvalidL3PExternalIPAddress',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
def test_update_with_es_negative(self):
|
||||
attrs = {'external_routes': [{'destination': '10.160.0.0/16',
|
||||
'nexthop': '172.1.1.1'}],
|
||||
'cidr': '172.1.1.0/24'}
|
||||
es = self.create_external_segment(**attrs)['external_segment']
|
||||
|
||||
# Overlapping pool
|
||||
l3p = self.create_l3_policy(ip_pool='172.1.1.0/20')['l3_policy']
|
||||
attrs = {'external_segments': {es['id']: ['172.1.1.2']}}
|
||||
res = self._update_gbp_resource_full_response(
|
||||
l3p['id'], 'l3_policy', 'l3_policies', expected_res_status=400,
|
||||
**attrs)
|
||||
self.assertEqual('ExternalSegmentSubnetOverlapsWithL3PIpPool',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
# Overlapping route
|
||||
l3p = self.create_l3_policy(ip_pool='10.160.1.0/24')['l3_policy']
|
||||
res = self._update_gbp_resource_full_response(
|
||||
l3p['id'], 'l3_policy', 'l3_policies', expected_res_status=400,
|
||||
**attrs)
|
||||
self.assertEqual('ExternalRouteOverlapsWithL3PIpPool',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
# Allocated address not in pool
|
||||
l3p = self.create_l3_policy(ip_pool='192.168.0.0/24')['l3_policy']
|
||||
attrs = {'external_segments': {es['id']: ['172.1.2.2']}}
|
||||
res = self._update_gbp_resource_full_response(
|
||||
l3p['id'], 'l3_policy', 'l3_policies', expected_res_status=400,
|
||||
**attrs)
|
||||
self.assertEqual('InvalidL3PExternalIPAddress',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
|
||||
class TestL2Policy(GroupPolicyPluginTestCase):
|
||||
|
||||
@@ -474,6 +612,184 @@ class TestPolicyTargetGroup(GroupPolicyPluginTestCase):
|
||||
expected_res_status=201)
|
||||
|
||||
|
||||
class TestExternalSegment(GroupPolicyPluginTestCase):
|
||||
|
||||
def test_shared_es_create(self):
|
||||
# Verify default is False
|
||||
es = self.create_external_segment()
|
||||
self.assertEqual(False, es['external_segment']['shared'])
|
||||
# Verify shared True created without errors
|
||||
es = self.create_external_segment(shared=True)
|
||||
self.assertEqual(True, es['external_segment']['shared'])
|
||||
|
||||
def test_shared_es_update(self):
|
||||
es = self.create_external_segment()['external_segment']
|
||||
for shared in [True, False]:
|
||||
self._update_gbp_resource(
|
||||
es['id'], 'external_segment',
|
||||
'external_segments', expected_res_status=200,
|
||||
shared=shared)
|
||||
|
||||
def test_create_routes(self):
|
||||
attrs = {'external_routes': [{'destination': '0.0.0.0/0',
|
||||
'nexthop': '172.1.0.1'}],
|
||||
'cidr': '172.1.0.0/24'}
|
||||
self.create_external_segment(expected_res_status=201, **attrs)
|
||||
|
||||
def test_routes_negative(self):
|
||||
# Verify wrong NH
|
||||
attrs = {'external_routes': [{'destination': '0.0.0.0/0',
|
||||
'nexthop': '172.1.1.1'}],
|
||||
'cidr': '172.1.0.0/24'}
|
||||
res = self.create_external_segment(expected_res_status=400, **attrs)
|
||||
self.assertEqual('ExternalRouteNextHopNotInExternalSegment',
|
||||
res['NeutronError']['type'])
|
||||
attrs['cidr'] = '172.1.1.0/24'
|
||||
es = self.create_external_segment(**attrs)['external_segment']
|
||||
self.create_l3_policy(
|
||||
ip_pool='192.160.0.0/16',
|
||||
external_segments={es['id']: ['172.1.1.2']})['l3_policy']
|
||||
|
||||
# Verify refused because overlapping with L3P
|
||||
attrs = {'external_routes': [{'destination': '192.168.2.0/0',
|
||||
'nexthop': '172.1.1.1'}]}
|
||||
res = self._update_gbp_resource_full_response(
|
||||
es['id'], 'external_segment', 'external_segments',
|
||||
expected_res_status=400, **attrs)
|
||||
self.assertEqual('ExternalRouteOverlapsWithL3PIpPool',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
|
||||
class TestExternalPolicy(GroupPolicyPluginTestCase):
|
||||
|
||||
def test_shared_ep_create(self):
|
||||
es = self.create_external_segment(
|
||||
shared=True)['external_segment']
|
||||
esns = self.create_external_segment(
|
||||
)['external_segment']
|
||||
|
||||
prs = self._create_policy_rule_set_on_shared(shared=True)
|
||||
prsns = self._create_policy_rule_set_on_shared()
|
||||
|
||||
# Verify non-shared ep providing and consuming shared and non shared
|
||||
# policy_rule_sets
|
||||
ep = self.create_external_policy(
|
||||
external_segments=[es['id']], expected_res_status=201)
|
||||
self.assertEqual(False, ep['external_policy']['shared'])
|
||||
ep = self.create_external_policy(
|
||||
external_segments=[es['id']],
|
||||
provided_policy_rule_sets={prs['id']: '', prsns['id']: ''},
|
||||
consumed_policy_rule_sets={prs['id']: '', prsns['id']: ''},
|
||||
expected_res_status=201)
|
||||
self.assertEqual(False, ep['external_policy']['shared'])
|
||||
|
||||
# Verify shared True created without errors by providing/consuming
|
||||
# shared policy_rule_sets
|
||||
ep = self.create_external_policy(
|
||||
external_segments=[es['id']], shared=True,
|
||||
expected_res_status=201)
|
||||
self.assertEqual(True, ep['external_policy']['shared'])
|
||||
ep = self.create_external_policy(
|
||||
external_segments=[es['id']],
|
||||
provided_policy_rule_sets={prs['id']: ''},
|
||||
consumed_policy_rule_sets={prs['id']: ''}, shared=True,
|
||||
expected_res_status=201)
|
||||
self.assertEqual(True, ep['external_policy']['shared'])
|
||||
|
||||
# Verify not shared created without error on not shared es
|
||||
self.create_external_policy(
|
||||
external_segments=[esns['id']], expected_res_status=201)
|
||||
|
||||
def test_shared_ep_update(self):
|
||||
ep = self._create_external_policy_on_shared()
|
||||
self._update_gbp_resource(
|
||||
ep['id'], 'external_policy', 'external_policies',
|
||||
expected_res_status=200, shared=True)
|
||||
self._update_gbp_resource(
|
||||
ep['id'], 'external_policy', 'external_policies',
|
||||
expected_res_status=200, shared=False)
|
||||
|
||||
def test_shared_ep_create_negative(self):
|
||||
es = self.create_external_segment()['external_segment']
|
||||
prs = self._create_policy_rule_set_on_shared()
|
||||
# Verify shared EP fails on non-shared es
|
||||
res = self.create_external_policy(
|
||||
external_segments=[es['id']], shared=True,
|
||||
expected_res_status=400)
|
||||
self.assertEqual('SharedResourceReferenceError',
|
||||
res['NeutronError']['type'])
|
||||
# Verify shared EP fails to provide/consume non shared
|
||||
# policy_rule_sets
|
||||
res = self.create_external_policy(
|
||||
shared=True, provided_policy_rule_sets={prs['id']: ''},
|
||||
consumed_policy_rule_sets={prs['id']: ''},
|
||||
expected_res_status=400)
|
||||
self.assertEqual('SharedResourceReferenceError',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
def test_shared_ep_update_negative(self):
|
||||
ep = self._create_external_policy_on_shared(shared=True)
|
||||
# Verify update to non shared ES fails
|
||||
es = self.create_external_segment()['external_segment']
|
||||
self._update_gbp_resource(
|
||||
ep['id'], 'external_policy', 'external_policies',
|
||||
expected_res_status=400, external_segments=[es['id']])
|
||||
|
||||
# Verify update to non shared provided PRS fails
|
||||
prs = self._create_policy_rule_set_on_shared()
|
||||
self._update_gbp_resource(
|
||||
ep['id'], 'external_policy', 'external_policies',
|
||||
expected_res_status=400,
|
||||
provided_policy_rule_sets={prs['id']: ''})
|
||||
# Verify update to non shared consumed PRS fails
|
||||
self._update_gbp_resource(
|
||||
ep['id'], 'external_policy', 'external_policies',
|
||||
expected_res_status=400,
|
||||
consumed_policy_rule_sets={prs['id']: ''})
|
||||
|
||||
|
||||
class TestNatPool(GroupPolicyPluginTestCase):
|
||||
|
||||
def test_nat_pool_shared_create(self):
|
||||
def combination(np, es):
|
||||
return {'np': np, 'es': es}
|
||||
allowed = [combination(False, False), combination(True, True),
|
||||
combination(False, True)]
|
||||
for shared in allowed:
|
||||
es = self.create_external_segment(
|
||||
shared=shared['es'])['external_segment']
|
||||
self.create_nat_pool(external_segment_id=es['id'],
|
||||
shared=shared['np'], expected_res_status=201)
|
||||
|
||||
def test_nat_pool_shared_create_negative(self):
|
||||
es = self.create_external_segment(
|
||||
shared=False)['external_segment']
|
||||
res = self.create_nat_pool(external_segment_id=es['id'],
|
||||
shared=True, expected_res_status=400)
|
||||
self.assertEqual('SharedResourceReferenceError',
|
||||
res['NeutronError']['type'])
|
||||
|
||||
def test_nat_pool_shared_update(self):
|
||||
np = self.create_nat_pool(shared=False)['nat_pool']
|
||||
for shared in [False, True]:
|
||||
es = self.create_external_segment(
|
||||
shared=shared)['external_segment']
|
||||
self._update_gbp_resource(
|
||||
np['id'], 'nat_pool', 'nat_pools', expected_res_status=200,
|
||||
external_segment_id=es['id'])
|
||||
np = self.create_nat_pool(shared=True)['nat_pool']
|
||||
es = self.create_external_segment(
|
||||
shared=True)['external_segment']
|
||||
# Verify shared NP on shared ES
|
||||
self._update_gbp_resource(
|
||||
np['id'], 'nat_pool', 'nat_pools', expected_res_status=200,
|
||||
external_segment_id=es['id'])
|
||||
# Verify unshare NP
|
||||
self._update_gbp_resource(
|
||||
np['id'], 'nat_pool', 'nat_pools', expected_res_status=200,
|
||||
shared=False)
|
||||
|
||||
|
||||
class TestGroupPolicyPluginGroupResources(
|
||||
GroupPolicyPluginTestCase, tgpdb.TestGroupResources):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user