group-based-policy/gbpservice/neutron/db/grouppolicy/group_policy_db.py

1936 lines
89 KiB
Python

# 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.
import netaddr
from neutron.db import api as db_api
from neutron.db import common_db_mixin
from neutron_lib.api import validators
from neutron_lib import constants
from neutron_lib import context
from neutron_lib.db import model_base
from oslo_log import helpers as log
from oslo_utils import uuidutils
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.orm import exc
from gbpservice.neutron.extensions import group_policy as gpolicy
from gbpservice.neutron.services.grouppolicy.common import (
constants as gp_constants)
from gbpservice.neutron.services.grouppolicy.common import utils
MAX_IPV4_SUBNET_PREFIX_LENGTH = 31
MAX_IPV6_SUBNET_PREFIX_LENGTH = 127
ADDRESS_NOT_SPECIFIED = ''
class BaseGbpResource(model_base.HasId, model_base.HasProject):
name = sa.Column(sa.String(255))
description = sa.Column(sa.String(255))
status = sa.Column(sa.String(length=16), nullable=True)
status_details = sa.Column(sa.String(length=4096), nullable=True)
class BaseSharedGbpResource(BaseGbpResource):
shared = sa.Column(sa.Boolean)
class PolicyTarget(model_base.BASEV2, BaseGbpResource):
"""Lowest unit of abstraction on which a policy is applied."""
__tablename__ = 'gp_policy_targets'
type = sa.Column(sa.String(15))
__mapper_args__ = {
'polymorphic_on': type,
'polymorphic_identity': 'base'
}
policy_target_group_id = sa.Column(sa.String(36),
sa.ForeignKey(
'gp_policy_target_groups.id'),
nullable=True)
cluster_id = sa.Column(sa.String(255))
class PTGToPRSProvidingAssociation(model_base.BASEV2):
"""Many to many providing relation between PTGs and Policy Rule Sets."""
__tablename__ = 'gp_ptg_to_prs_providing_associations'
policy_rule_set_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_rule_sets.id'),
primary_key=True)
policy_target_group_id = sa.Column(sa.String(36),
sa.ForeignKey(
'gp_policy_target_groups.id'),
primary_key=True)
class PTGToPRSConsumingAssociation(model_base.BASEV2):
"""Many to many consuming relation between PTGs and Policy Rule Sets."""
__tablename__ = 'gp_ptg_to_prs_consuming_associations'
policy_rule_set_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_rule_sets.id'),
primary_key=True)
policy_target_group_id = sa.Column(sa.String(36),
sa.ForeignKey(
'gp_policy_target_groups.id'),
primary_key=True)
class PolicyTargetGroup(model_base.BASEV2, BaseSharedGbpResource):
"""It is a collection of policy_targets."""
__tablename__ = 'gp_policy_target_groups'
type = sa.Column(sa.String(15))
__mapper_args__ = {
'polymorphic_on': type,
'polymorphic_identity': 'base'
}
policy_targets = orm.relationship(PolicyTarget,
backref='policy_target_group')
application_policy_group_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_application_policy_groups.id'),
nullable=True)
l2_policy_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_l2_policies.id'),
nullable=True)
network_service_policy_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_network_service_policies.id'),
nullable=True)
provided_policy_rule_sets = orm.relationship(
PTGToPRSProvidingAssociation,
backref='providing_policy_target_group', cascade='all, delete-orphan')
consumed_policy_rule_sets = orm.relationship(
PTGToPRSConsumingAssociation,
backref='consuming_policy_target_group', cascade='all, delete-orphan')
service_management = sa.Column(sa.Boolean)
class ApplicationPolicyGroup(model_base.BASEV2, BaseSharedGbpResource):
"""It is a collection of policy_targets."""
__tablename__ = 'gp_application_policy_groups'
policy_target_groups = orm.relationship(
PolicyTargetGroup, backref='application_policy_group')
class L2Policy(model_base.BASEV2, BaseSharedGbpResource):
"""Represents a L2 Policy for a collection of policy_target_groups."""
__tablename__ = 'gp_l2_policies'
type = sa.Column(sa.String(15))
__mapper_args__ = {
'polymorphic_on': type,
'polymorphic_identity': 'base'
}
policy_target_groups = orm.relationship(PolicyTargetGroup,
backref='l2_policy')
l3_policy_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_l3_policies.id'),
nullable=True)
inject_default_route = sa.Column(sa.Boolean, default=True,
server_default=sa.sql.true())
class ESToL3PAssociation(model_base.BASEV2):
"""Many to many consuming relation between ESs and L3Ps."""
__tablename__ = 'gp_es_to_l3p_associations'
l3_policy_id = sa.Column(sa.String(36), sa.ForeignKey('gp_l3_policies.id'),
primary_key=True)
external_segment_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_external_segments.id'),
primary_key=True)
allocated_address = sa.Column(sa.String(64), nullable=False,
primary_key=True)
class L3Policy(model_base.BASEV2, BaseSharedGbpResource):
"""Represents a L3 Policy with a non-overlapping IP address space."""
__tablename__ = 'gp_l3_policies'
type = sa.Column(sa.String(15))
__mapper_args__ = {
'polymorphic_on': type,
'polymorphic_identity': 'base'
}
ip_version = sa.Column(sa.Integer, nullable=False)
ip_pool = sa.Column(sa.String(255))
subnet_prefix_length = sa.Column(sa.Integer)
l2_policies = orm.relationship(L2Policy, backref='l3_policy')
external_segments = orm.relationship(
ESToL3PAssociation, backref='l3_policies',
cascade='all, delete-orphan')
class NetworkServiceParam(model_base.BASEV2, model_base.HasId):
"""Represents a network service param used in a NetworkServicePolicy."""
__tablename__ = 'gp_network_service_params'
param_type = sa.Column(sa.String(50), nullable=False)
param_name = sa.Column(sa.String(50), nullable=False)
param_value = sa.Column(sa.String(50), nullable=False)
network_service_policy_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_network_service_policies.id'),
nullable=False)
class NetworkServicePolicy(model_base.BASEV2, BaseSharedGbpResource):
"""Represents a Network Service Policy."""
__tablename__ = 'gp_network_service_policies'
policy_target_groups = orm.relationship(PolicyTargetGroup,
backref='network_service_policy')
network_service_params = orm.relationship(
NetworkServiceParam, backref='network_service_policy',
cascade='all, delete-orphan')
class PRSToPRAssociation(model_base.BASEV2):
"""Many to many relation between Policy Rule Set and Policy rules."""
__tablename__ = 'gp_prs_to_pr_associations'
policy_rule_set_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_rule_sets.id'),
primary_key=True)
policy_rule_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_rules.id'),
primary_key=True)
class PolicyRuleActionAssociation(model_base.BASEV2):
"""Many to many relation between PolicyRules and PolicyActions."""
__tablename__ = 'gp_policy_rule_action_associations'
policy_rule_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_rules.id'),
primary_key=True)
policy_action_id = sa.Column(sa.String(36),
sa.ForeignKey(
'gp_policy_actions.id'),
primary_key=True)
class PolicyRule(model_base.BASEV2, BaseSharedGbpResource):
"""Represents a Group Policy Rule."""
__tablename__ = 'gp_policy_rules'
enabled = sa.Column(sa.Boolean)
policy_classifier_id = sa.Column(sa.String(36),
sa.ForeignKey(
'gp_policy_classifiers.id'),
nullable=False)
policy_actions = orm.relationship(PolicyRuleActionAssociation,
backref='gp_policy_rules',
cascade='all', lazy="joined")
policy_rule_sets = orm.relationship(PRSToPRAssociation,
backref='policy_rule', lazy="joined",
cascade='all, delete-orphan')
class PolicyClassifier(model_base.BASEV2, BaseSharedGbpResource):
"""Represents a Group Policy Classifier."""
__tablename__ = 'gp_policy_classifiers'
protocol = sa.Column(sa.String(50), nullable=True)
port_range_min = sa.Column(sa.Integer)
port_range_max = sa.Column(sa.Integer)
direction = sa.Column(sa.Enum(gp_constants.GP_DIRECTION_IN,
gp_constants.GP_DIRECTION_OUT,
gp_constants.GP_DIRECTION_BI,
name='direction'))
policy_rules = orm.relationship(PolicyRule,
backref='gp_policy_classifiers')
class PolicyAction(model_base.BASEV2, BaseSharedGbpResource):
"""Represents a Group Policy Action."""
__tablename__ = 'gp_policy_actions'
action_type = sa.Column(sa.Enum(gp_constants.GP_ACTION_ALLOW,
gp_constants.GP_ACTION_REDIRECT,
name='action_type'))
# Default action_value would be Null when action_type is allow
# however, value is required if something meaningful needs to be done
# for redirect
action_value = sa.Column(sa.String(36), nullable=True)
policy_rules = orm.relationship(PolicyRuleActionAssociation,
cascade='all', backref='gp_policy_actions')
class EPToPRSProvidingAssociation(model_base.BASEV2):
"""Many to many providing relation between EPs and Policy Rule Sets."""
__tablename__ = 'gp_ep_to_prs_providing_associations'
policy_rule_set_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_rule_sets.id'),
primary_key=True)
external_policy_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_external_policies.id'),
primary_key=True)
class EPToPRSConsumingAssociation(model_base.BASEV2):
"""Many to many consuming relation between EPs and Policy Rule Sets."""
__tablename__ = 'gp_ep_to_prs_consuming_associations'
policy_rule_set_id = sa.Column(sa.String(36),
sa.ForeignKey('gp_policy_rule_sets.id'),
primary_key=True)
external_policy_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_external_policies.id'),
primary_key=True)
class PolicyRuleSet(model_base.BASEV2, model_base.HasProject):
"""It is a collection of Policy rules."""
__tablename__ = 'gp_policy_rule_sets'
id = sa.Column(sa.String(36), primary_key=True,
default=uuidutils.generate_uuid)
name = sa.Column(sa.String(255))
description = sa.Column(sa.String(255))
parent_id = sa.Column(sa.String(255),
sa.ForeignKey('gp_policy_rule_sets.id'),
nullable=True)
child_policy_rule_sets = orm.relationship(
'PolicyRuleSet', backref=orm.backref('parent', remote_side=[id]))
policy_rules = orm.relationship(PRSToPRAssociation,
backref='policy_rule_set', lazy="joined",
cascade='all, delete-orphan')
providing_policy_target_groups = orm.relationship(
PTGToPRSProvidingAssociation,
backref='provided_policy_rule_set', lazy="joined", cascade='all')
consuming_policy_target_groups = orm.relationship(
PTGToPRSConsumingAssociation,
backref='consumed_policy_rule_set', lazy="joined", cascade='all')
providing_external_policies = orm.relationship(
EPToPRSProvidingAssociation,
backref='provided_policy_rule_set', lazy="joined", cascade='all')
consuming_external_policies = orm.relationship(
EPToPRSConsumingAssociation,
backref='consumed_policy_rule_set', lazy="joined", cascade='all')
shared = sa.Column(sa.Boolean)
status = sa.Column(sa.String(length=16), nullable=True)
status_details = sa.Column(sa.String(length=4096), nullable=True)
class NATPool(model_base.BASEV2, BaseSharedGbpResource):
__tablename__ = 'gp_nat_pools'
type = sa.Column(sa.String(15))
__mapper_args__ = {
'polymorphic_on': type,
'polymorphic_identity': 'base'
}
ip_version = sa.Column(sa.Integer, nullable=False)
ip_pool = sa.Column(sa.String(64), nullable=False)
external_segment_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_external_segments.id'))
class ExternalRoute(model_base.BASEV2):
__tablename__ = 'gp_external_routes'
external_segment_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_external_segments.id',
ondelete='CASCADE'),
primary_key=True)
destination = sa.Column(sa.String(64), nullable=False, primary_key=True)
nexthop = sa.Column(sa.String(64), primary_key=True)
class EPToESAssociation(model_base.BASEV2):
"""Many to many consuming relation between ESs and EPs."""
__tablename__ = 'gp_es_to_ep_associations'
external_policy_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_external_policies.id'),
primary_key=True)
external_segment_id = sa.Column(
sa.String(36), sa.ForeignKey('gp_external_segments.id'),
primary_key=True)
class ExternalSegment(model_base.BASEV2, BaseSharedGbpResource):
__tablename__ = 'gp_external_segments'
type = sa.Column(sa.String(15))
__mapper_args__ = {
'polymorphic_on': type,
'polymorphic_identity': 'base'
}
ip_version = sa.Column(sa.Integer, nullable=False)
cidr = sa.Column(sa.String(64), nullable=False)
port_address_translation = sa.Column(sa.Boolean)
nat_pools = orm.relationship(NATPool, backref='external_segment')
external_policies = orm.relationship(
EPToESAssociation, backref='external_segments',
cascade='all, delete-orphan')
l3_policies = orm.relationship(
ESToL3PAssociation, backref='external_segments',
cascade='all, delete-orphan')
external_routes = orm.relationship(
ExternalRoute, backref='external_segment',
cascade='all, delete-orphan')
class ExternalPolicy(model_base.BASEV2, BaseSharedGbpResource):
__tablename__ = 'gp_external_policies'
external_segments = orm.relationship(
EPToESAssociation,
backref='external_policies', cascade='all, delete-orphan')
provided_policy_rule_sets = orm.relationship(
EPToPRSProvidingAssociation,
backref='providing_external_policies',
cascade='all, delete-orphan')
consumed_policy_rule_sets = orm.relationship(
EPToPRSConsumingAssociation,
backref='consuming_external_policies',
cascade='all, delete-orphan')
class GroupPolicyDbPlugin(gpolicy.GroupPolicyPluginBase,
common_db_mixin.CommonDbMixin):
"""GroupPolicy plugin interface implementation using SQLAlchemy models."""
# TODO(Sumit): native bulk support
__native_bulk_support = False
__native_pagination_support = True
__native_sorting_support = True
def __init__(self, *args, **kwargs):
super(GroupPolicyDbPlugin, self).__init__(*args, **kwargs)
def _find_gbp_resource(self, context, type, id, on_fail=None):
try:
return self._get_by_id(context, type, id)
except exc.NoResultFound:
if on_fail:
raise on_fail(id=id)
def _get_policy_target(self, context, policy_target_id):
try:
return self._get_by_id(context, PolicyTarget, policy_target_id)
except exc.NoResultFound:
raise gpolicy.PolicyTargetNotFound(
policy_target_id=policy_target_id)
def _get_policy_target_group(self, context, policy_target_group_id):
try:
return self._get_by_id(
context, PolicyTargetGroup, policy_target_group_id)
except exc.NoResultFound:
raise gpolicy.PolicyTargetGroupNotFound(
policy_target_group_id=policy_target_group_id)
def _get_application_policy_group(self, context,
application_policy_group_id):
try:
return self._get_by_id(
context, ApplicationPolicyGroup, application_policy_group_id)
except exc.NoResultFound:
raise gpolicy.ApplicationPolicyGroupNotFound(
application_policy_group_id=application_policy_group_id)
def _get_l2_policy(self, context, l2_policy_id):
try:
return self._get_by_id(context, L2Policy, l2_policy_id)
except exc.NoResultFound:
raise gpolicy.L2PolicyNotFound(l2_policy_id=l2_policy_id)
def _get_l3_policy(self, context, l3_policy_id):
try:
return self._get_by_id(context, L3Policy, l3_policy_id)
except exc.NoResultFound:
raise gpolicy.L3PolicyNotFound(l3_policy_id=l3_policy_id)
def _get_network_service_policy(self, context, network_service_policy_id):
try:
return self._get_by_id(context, NetworkServicePolicy,
network_service_policy_id)
except exc.NoResultFound:
raise gpolicy.NetworkServicePolicyNotFound(
network_service_policy_id=network_service_policy_id)
def _get_policy_classifier(self, context, policy_classifier_id):
try:
return self._get_by_id(context, PolicyClassifier,
policy_classifier_id)
except exc.NoResultFound:
raise gpolicy.PolicyClassifierNotFound(
policy_classifier_id=policy_classifier_id)
def _get_policy_action(self, context, policy_action_id):
try:
policy_action = self._get_by_id(context, PolicyAction,
policy_action_id)
except exc.NoResultFound:
raise gpolicy.PolicyActionNotFound(
policy_action_id=policy_action_id)
return policy_action
def _get_policy_rule(self, context, policy_rule_id):
try:
policy_rule = self._get_by_id(context, PolicyRule,
policy_rule_id)
except exc.NoResultFound:
raise gpolicy.PolicyRuleNotFound(
policy_rule_id=policy_rule_id)
return policy_rule
def _get_policy_rule_set(self, context, policy_rule_set_id):
try:
policy_rule_set = self._get_by_id(
context, PolicyRuleSet, policy_rule_set_id)
except exc.NoResultFound:
raise gpolicy.PolicyRuleSetNotFound(
policy_rule_set_id=policy_rule_set_id)
return policy_rule_set
def _get_external_policy(self, context, external_policy_id):
return self._find_gbp_resource(
context, ExternalPolicy, external_policy_id,
gpolicy.ExternalPolicyNotFound)
def _get_external_segment(self, context, external_segment_id):
return self._find_gbp_resource(
context, ExternalSegment, external_segment_id,
gpolicy.ExternalSegmentNotFound)
def _get_nat_pool(self, context, nat_pool_id):
return self._find_gbp_resource(
context, NATPool, nat_pool_id,
gpolicy.NATPoolNotFound)
@staticmethod
def _get_min_max_ports_from_range(port_range):
if not port_range:
return [None, None]
min_port, sep, max_port = port_range.partition(":")
if not max_port:
max_port = min_port
return [int(min_port), int(max_port)]
def _get_port_range_from_min_max_ports(self, min_port, max_port):
if not min_port:
return None
if min_port == max_port:
return str(min_port)
else:
return '%d:%d' % (min_port, max_port)
def _set_actions_for_rule(self, context, policy_rule_db, action_id_list):
pr_db = policy_rule_db
if not action_id_list:
pr_db.policy_actions = []
return
with context.session.begin(subtransactions=True):
# We will first check if the new list of actions is valid
filters = {'id': [a_id for a_id in action_id_list]}
actions_in_db = self._get_collection_query(context, PolicyAction,
filters=filters)
actions_set = set(a_db['id'] for a_db in actions_in_db)
for action_id in action_id_list:
if action_id not in actions_set:
# If we find an invalid action in the list we
# do not perform the update
raise gpolicy.PolicyActionNotFound(
policy_action_id=action_id)
# New list of actions is valid so we will first reset the existing
# list and then add each action in order.
# Note that the list could be empty in which case we interpret
# it as clering existing rules.
for pr_action_assoc in context.session.query(
PolicyRuleActionAssociation).filter_by(
policy_rule_id=pr_db.id):
context.session.delete(pr_action_assoc)
pr_db.policy_actions = []
for action_id in action_id_list:
assoc = PolicyRuleActionAssociation(policy_rule_id=pr_db.id,
policy_action_id=action_id)
pr_db.policy_actions.append(assoc)
def _validate_policy_rule_set_list(self, context,
policy_rule_sets_id_list):
with context.session.begin(subtransactions=True):
filters = {'id': [c_id for c_id in policy_rule_sets_id_list]}
policy_rule_sets_in_db = self._get_collection_query(
context, PolicyRuleSet, filters=filters)
existing_policy_rule_set_ids = set(
c_db['id'] for c_db in policy_rule_sets_in_db)
for policy_rule_set_id in policy_rule_sets_id_list:
if policy_rule_set_id not in existing_policy_rule_set_ids:
# If we find an invalid policy_rule_set id in the list we
# dont process the entire list
raise gpolicy.PolicyRuleSetNotFound(
policy_rule_set_id=policy_rule_set_id)
return policy_rule_sets_in_db
def _set_providers_or_consumers_for_policy_target_group(
self, context, ptg_db, policy_rule_sets_dict, provider=True):
assoc_table = (PTGToPRSProvidingAssociation if provider else
PTGToPRSConsumingAssociation)
self._set_providers_or_consumers_for_res(
context, 'policy_target_group', ptg_db, policy_rule_sets_dict,
assoc_table, provider=provider)
def _set_providers_or_consumers_for_ep(
self, context, ep_db, policy_rule_sets_dict, provider=True):
assoc_table = (EPToPRSProvidingAssociation if provider else
EPToPRSConsumingAssociation)
self._set_providers_or_consumers_for_res(
context, 'external_policy', ep_db, policy_rule_sets_dict,
assoc_table, provider=provider)
def _set_providers_or_consumers_for_res(
self, context, type, db_res, policy_rule_sets_dict, assoc_table,
provider=True):
# TODO(Sumit): Check that the same policy_rule_set ID does not belong
# to provider and consumer dicts
if not policy_rule_sets_dict:
if provider:
db_res.provided_policy_rule_sets = []
return
else:
db_res.consumed_policy_rule_sets = []
return
with context.session.begin(subtransactions=True):
policy_rule_sets_id_list = policy_rule_sets_dict.keys()
# We will first check if the new list of policy_rule_sets is valid
self._validate_policy_rule_set_list(
context, policy_rule_sets_id_list)
# New list of policy_rule_sets is valid so we will first reset the
# existing list and then add each policy_rule_set.
# Note that the list could be empty in which case we interpret
# it as clering existing rules.
if provider:
db_res.provided_policy_rule_sets = []
else:
db_res.consumed_policy_rule_sets = []
for policy_rule_set_id in policy_rule_sets_id_list:
kwargs = {type + '_id': db_res.id,
'policy_rule_set_id': policy_rule_set_id}
assoc = assoc_table(**kwargs)
if provider:
db_res.provided_policy_rule_sets.append(assoc)
else:
db_res.consumed_policy_rule_sets.append(assoc)
def _set_children_for_policy_rule_set(self, context,
policy_rule_set_db, child_id_list):
if not child_id_list:
policy_rule_set_db.child_policy_rule_sets = []
return
if policy_rule_set_db['parent_id']:
# Only one hierarchy level allowed for now
raise gpolicy.ThreeLevelPolicyRuleSetHierarchyNotSupported(
policy_rule_set_id=policy_rule_set_db['id'])
with context.session.begin(subtransactions=True):
# We will first check if the new list of policy_rule_sets is valid
policy_rule_sets_in_db = self._validate_policy_rule_set_list(
context, child_id_list)
for child in policy_rule_sets_in_db:
if (child['child_policy_rule_sets'] or
child['id'] == policy_rule_set_db['id']):
# Only one level policy_rule_set relationship supported for
# now. No loops allowed
raise gpolicy.BadPolicyRuleSetRelationship(
parent_id=policy_rule_set_db['id'],
child_id=child['id'])
# New list of child policy_rule_sets is valid so we will first
# reset the existing list and then add each policy_rule_set.
# Note that the list could be empty in which case we interpret
# it as clering existing child policy_rule_sets.
policy_rule_set_db.child_policy_rule_sets = []
for child in policy_rule_sets_in_db:
policy_rule_set_db.child_policy_rule_sets.append(child)
def _set_rules_for_policy_rule_set(self, context,
policy_rule_set_db, rule_id_list):
prs_db = policy_rule_set_db
if not rule_id_list:
prs_db.policy_rules = []
return
with context.session.begin(subtransactions=True):
# We will first check if the new list of rules is valid
filters = {'id': [r_id for r_id in rule_id_list]}
rules_in_db = self._get_collection_query(context, PolicyRule,
filters=filters)
rule_ids = set(r_db['id'] for r_db in rules_in_db)
for rule_id in rule_id_list:
if rule_id not in rule_ids:
# If we find an invalid rule in the list we
# do not perform the update
raise gpolicy.PolicyRuleNotFound(policy_rule_id=rule_id)
# New list of rules is valid so we will first reset the existing
# list and then add each rule in order.
# Note that the list could be empty in which case we interpret
# it as clering existing rules.
prs_db.policy_rules = []
for rule_id in rule_id_list:
prs_rule_db = PRSToPRAssociation(
policy_rule_id=rule_id,
policy_rule_set_id=prs_db.id)
prs_db.policy_rules.append(prs_rule_db)
def _process_policy_rule_sets_for_ptg(self, context, db_res, ptg):
if 'provided_policy_rule_sets' in ptg:
self._set_providers_or_consumers_for_policy_target_group(
context, db_res, ptg['provided_policy_rule_sets'])
del ptg['provided_policy_rule_sets']
if 'consumed_policy_rule_sets' in ptg:
self._set_providers_or_consumers_for_policy_target_group(
context, db_res, ptg['consumed_policy_rule_sets'], False)
del ptg['consumed_policy_rule_sets']
return ptg
def _process_policy_rule_sets_for_ep(self, context, db_res, res):
if 'provided_policy_rule_sets' in res:
self._set_providers_or_consumers_for_ep(
context, db_res, res['provided_policy_rule_sets'])
del res['provided_policy_rule_sets']
if 'consumed_policy_rule_sets' in res:
self._set_providers_or_consumers_for_ep(
context, db_res, res['consumed_policy_rule_sets'], False)
del res['consumed_policy_rule_sets']
return res
def _set_l3_policy_for_l2_policy(self, context, l2p_id, l3p_id):
with context.session.begin(subtransactions=True):
l2p_db = self._get_l2_policy(context, l2p_id)
l2p_db.l3_policy_id = l3p_id
def _set_l2_policy_for_policy_target_group(self, context, ptg_id, l2p_id):
with context.session.begin(subtransactions=True):
ptg_db = self._get_policy_target_group(context, ptg_id)
ptg_db.l2_policy_id = l2p_id
def _set_application_policy_group_for_policy_target_group(
self, context, ptg_id, apg_id):
with context.session.begin(subtransactions=True):
ptg_db = self._get_policy_target_group(context, ptg_id)
ptg_db.application_policy_group_id = apg_id
def _set_network_service_policy_for_policy_target_group(
self, context, ptg_id, nsp_id):
with context.session.begin(subtransactions=True):
ptg_db = self._get_policy_target_group(context, ptg_id)
ptg_db.network_service_policy_id = nsp_id
def _set_params_for_network_service_policy(
self, context, network_service_policy_db, network_service_policy):
nsp_db = network_service_policy_db
params = network_service_policy['network_service_params']
if not params:
nsp_db.network_service_params = []
return
with context.session.begin(subtransactions=True):
nsp_db.network_service_params = []
for param in params:
param_db = NetworkServiceParam(
param_type=param['type'],
param_name=param['name'],
param_value=param['value'])
nsp_db.network_service_params.append(param_db)
del network_service_policy['network_service_params']
def _set_ess_for_ep(self, context, ep_db, es_id_list):
if not es_id_list:
ep_db.external_segments = []
return
with context.session.begin(subtransactions=True):
filters = {'id': es_id_list}
eps_in_db = self._get_collection_query(
context, ExternalSegment, filters=filters)
not_found = set(es_id_list) - set(ep['id'] for ep in eps_in_db)
if not_found:
raise gpolicy.ExternalSegmentNotFound(
id=not_found.pop())
ep_db.external_segments = []
for ep_id in es_id_list:
assoc = EPToESAssociation(
external_policy_id=ep_db.id,
external_segment_id=ep_id)
ep_db.external_segments.append(assoc)
def _process_segment_ers(self, context, es_db, es):
if es['external_routes'] is not constants.ATTR_NOT_SPECIFIED:
es_db.external_routes = []
for rt in es['external_routes']:
target = ExternalRoute(
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):
if es_dict is constants.ATTR_NOT_SPECIFIED:
return
if not es_dict:
l3p_db.external_segments = []
return
with context.session.begin(subtransactions=True):
# Validate ESs exist
es_set = set(es_dict.keys())
filters = {'id': es_set}
es_in_db = self._get_collection_query(
context, ExternalSegment, filters=filters)
not_found = es_set - set(es['id'] for es in es_in_db)
if not_found:
raise gpolicy.ExternalSegmentNotFound(
id=not_found.pop())
l3p_db.external_segments = []
for es in es_in_db:
ips = [x for x in es_dict[es['id']] if x]
if not ips:
assoc = ESToL3PAssociation(
external_segment_id=es['id'],
l3_policy_id=l3p_db['id'],
allocated_address=ADDRESS_NOT_SPECIFIED)
l3p_db.external_segments.append(assoc)
else:
# Create address allocation
existing = context.session.query(
ESToL3PAssociation).filter_by(
external_segment_id=es['id']).filter(
ESToL3PAssociation.allocated_address.in_(
ips)).all()
if existing:
raise gpolicy.IpAddressOverlappingInExternalSegment(
es_id=es['id'])
for ip in es_dict[es['id']]:
assoc = ESToL3PAssociation(
external_segment_id=es['id'],
l3_policy_id=l3p_db['id'], allocated_address=ip)
l3p_db.external_segments.append(assoc)
def _populate_common_fields_in_dict(self, db_ref):
res = {'id': db_ref['id'],
'tenant_id': db_ref['tenant_id'],
'name': db_ref['name'],
'description': db_ref['description'],
'status': db_ref['status'],
'status_details': db_ref['status_details'],
'shared': db_ref.get('shared', False)}
return res
def _make_policy_target_dict(self, pt, fields=None):
res = {'id': pt['id'],
'tenant_id': pt['tenant_id'],
'name': pt['name'],
'description': pt['description'],
'status': pt['status'],
'status_details': pt['status_details'],
'policy_target_group_id': pt['policy_target_group_id'],
'cluster_id': pt['cluster_id']}
return self._fields(res, fields)
def _make_policy_target_group_dict(self, ptg, fields=None):
res = self._populate_common_fields_in_dict(ptg)
res['l2_policy_id'] = ptg['l2_policy_id']
res['application_policy_group_id'] = ptg.get(
'application_policy_group_id', None)
res['network_service_policy_id'] = ptg['network_service_policy_id']
res['service_management'] = ptg.get('service_management', False)
res['policy_targets'] = [
pt['id'] for pt in ptg['policy_targets']]
res['provided_policy_rule_sets'] = (
[pprs['policy_rule_set_id'] for pprs in ptg[
'provided_policy_rule_sets']])
res['consumed_policy_rule_sets'] = (
[cprs['policy_rule_set_id'] for cprs in ptg[
'consumed_policy_rule_sets']])
return self._fields(res, fields)
def _make_application_policy_group_dict(self, apg, fields=None):
res = self._populate_common_fields_in_dict(apg)
res['policy_target_groups'] = [
ptg['id'] for ptg in apg['policy_target_groups']]
return self._fields(res, fields)
def _make_l2_policy_dict(self, l2p, fields=None):
res = self._populate_common_fields_in_dict(l2p)
res['l3_policy_id'] = l2p['l3_policy_id']
res['inject_default_route'] = l2p.get('inject_default_route', True)
res['policy_target_groups'] = [
ptg['id'] for ptg in l2p['policy_target_groups']]
return self._fields(res, fields)
def _make_l3_policy_dict(self, l3p, fields=None):
res = self._populate_common_fields_in_dict(l3p)
res['ip_version'] = l3p['ip_version']
res['ip_pool'] = l3p['ip_pool']
res['subnet_prefix_length'] = l3p['subnet_prefix_length']
res['l2_policies'] = [l2p['id']
for l2p in l3p['l2_policies']]
es_dict = {}
for es in l3p['external_segments']:
es_id = es['external_segment_id']
if es_id not in es_dict:
es_dict[es_id] = []
es_dict[es_id].append(es['allocated_address'])
res['external_segments'] = es_dict
return self._fields(res, fields)
def _make_network_service_policy_dict(self, nsp, fields=None):
res = self._populate_common_fields_in_dict(nsp)
res['policy_target_groups'] = [
ptg['id'] for ptg in nsp['policy_target_groups']]
params = []
for param in nsp['network_service_params']:
params.append({
gp_constants.GP_NETWORK_SVC_PARAM_TYPE: param['param_type'],
gp_constants.GP_NETWORK_SVC_PARAM_NAME: param['param_name'],
gp_constants.GP_NETWORK_SVC_PARAM_VALUE: param['param_value']})
res['network_service_params'] = params
return self._fields(res, fields)
def _make_policy_classifier_dict(self, pc, fields=None):
res = self._populate_common_fields_in_dict(pc)
port_range = self._get_port_range_from_min_max_ports(
pc['port_range_min'],
pc['port_range_max'])
res['protocol'] = pc['protocol']
res['port_range'] = port_range
res['direction'] = pc['direction']
res['policy_rules'] = [pr['id']
for pr in pc['policy_rules']]
return self._fields(res, fields)
def _make_policy_action_dict(self, pa, fields=None):
res = self._populate_common_fields_in_dict(pa)
res['action_type'] = pa['action_type']
res['action_value'] = pa['action_value']
res['policy_rules'] = [pr['policy_rule_id'] for
pr in pa['policy_rules']]
return self._fields(res, fields)
def _make_policy_rule_dict(self, pr, fields=None):
res = self._populate_common_fields_in_dict(pr)
res['enabled'] = pr['enabled']
res['policy_classifier_id'] = pr['policy_classifier_id']
res['policy_actions'] = [pa['policy_action_id']
for pa in pr['policy_actions']]
res['policy_rule_sets'] = [prs['policy_rule_set_id'] for prs in
pr['policy_rule_sets']]
return self._fields(res, fields)
def _make_policy_rule_set_dict(self, prs, fields=None):
res = self._populate_common_fields_in_dict(prs)
if prs['parent']:
res['parent_id'] = prs['parent']['id']
else:
res['parent_id'] = None
ctx = context.get_admin_context()
if 'child_policy_rule_sets' in prs:
# They have been updated
res['child_policy_rule_sets'] = [
child_prs['id'] for child_prs in prs['child_policy_rule_sets']]
else:
with ctx.session.begin(subtransactions=True):
filters = {'parent_id': [prs['id']]}
child_prs_in_db = self._get_collection_query(
ctx, PolicyRuleSet, filters=filters)
res['child_policy_rule_sets'] = [child_prs['id']
for child_prs
in child_prs_in_db]
res['policy_rules'] = [pr['policy_rule_id']
for pr in prs['policy_rules']]
res['providing_policy_target_groups'] = [
ptg['policy_target_group_id']
for ptg in prs['providing_policy_target_groups']]
res['consuming_policy_target_groups'] = [
ptg['policy_target_group_id']
for ptg in prs['consuming_policy_target_groups']]
res['providing_external_policies'] = [
ptg['external_policy_id']
for ptg in prs['providing_external_policies']]
res['consuming_external_policies'] = [
ptg['external_policy_id']
for ptg in prs['consuming_external_policies']]
return self._fields(res, fields)
def _make_external_segment_dict(self, es, fields=None):
res = self._populate_common_fields_in_dict(es)
res['ip_version'] = es['ip_version']
res['cidr'] = es['cidr']
res['port_address_translation'] = es['port_address_translation']
res['external_routes'] = [{'destination': er['destination'],
'nexthop': er['nexthop']} for er in
es['external_routes']]
res['nat_pools'] = [np['id'] for np in es['nat_pools']]
res['external_policies'] = [
ep['external_policy_id']
for ep in es['external_policies']]
res['l3_policies'] = [
l3p['l3_policy_id'] for l3p in es['l3_policies']]
return self._fields(res, fields)
def _make_external_policy_dict(self, ep, fields=None):
res = self._populate_common_fields_in_dict(ep)
res['external_segments'] = [
es['external_segment_id']
for es in ep['external_segments']]
res['provided_policy_rule_sets'] = [
pprs['policy_rule_set_id'] for pprs in
ep['provided_policy_rule_sets']]
res['consumed_policy_rule_sets'] = [
cprs['policy_rule_set_id'] for cprs in
ep['consumed_policy_rule_sets']]
return self._fields(res, fields)
def _make_nat_pool_dict(self, np, fields=None):
res = self._populate_common_fields_in_dict(np)
res['ip_version'] = np['ip_version']
res['ip_pool'] = np['ip_pool']
res['external_segment_id'] = np['external_segment_id']
return self._fields(res, fields)
def _get_ptgs_for_providing_policy_rule_set(self, context,
policy_rule_set_id):
return [x['policy_target_group_id'] for x in
context.session.query(PTGToPRSProvidingAssociation).filter_by(
policy_rule_set_id=policy_rule_set_id)]
def _get_ptgs_for_consuming_policy_rule_set(self, context,
policy_rule_set_id):
return [x['policy_target_group_id'] for x in
context.session.query(PTGToPRSConsumingAssociation).filter_by(
policy_rule_set_id=policy_rule_set_id)]
def _get_eps_for_providing_policy_rule_set(self, context,
policy_rule_set_id):
return [x['external_policy_id'] for x in
context.session.query(EPToPRSProvidingAssociation).filter_by(
policy_rule_set_id=policy_rule_set_id)]
def _get_eps_for_consuming_policy_rule_set(self, context,
policy_rule_set_id):
return [x['external_policy_id'] for x in
context.session.query(EPToPRSConsumingAssociation).filter_by(
policy_rule_set_id=policy_rule_set_id)]
def _get_policy_rule_policy_rule_sets(self, context, policy_rule_id):
return [x['policy_rule_set_id'] for x in
context.session.query(PRSToPRAssociation).filter_by(
policy_rule_id=policy_rule_id)]
def _get_policy_classifier_rules(self, context, policy_classifier_id):
return [x['id'] for x in
context.session.query(PolicyRule).filter_by(
policy_classifier_id=policy_classifier_id)]
def _get_policy_action_rules(self, context, policy_action_id):
return [x['policy_rule_id'] for x in
context.session.query(PolicyRuleActionAssociation).filter_by(
policy_action_id=policy_action_id)]
def _get_external_segment_external_policies(self, context, es_id):
return [x['external_policy_id'] for x in
context.session.query(EPToESAssociation).filter_by(
external_segment_id=es_id)]
def _get_l3p_ptgs(self, context, l3p_id, l3p_klass=L3Policy,
ptg_klass=PolicyTargetGroup, l2p_klass=L2Policy):
return [self._make_policy_target_group_dict(x) for x in
context.session.query(ptg_klass).join(
l2p_klass).join(l3p_klass).filter(
l2p_klass.l3_policy_id == l3p_id).all()]
def _get_attribute(self, attrs, key):
value = attrs.get(key)
if value is constants.ATTR_NOT_SPECIFIED:
value = None
return value
def _validate_service_management_ptg(self, context, tenant_id):
# Verify whether a Management PTG already exists for this tenant
if self.get_policy_target_groups(
context, {'tenant_id': [tenant_id],
'service_management': [True]}):
raise gpolicy.ManagementPolicyTargetGroupExists()
@staticmethod
def validate_ip_pool(ip_pool, ip_version):
# An empty pool is allowed, as it can be used
# with the default subnetpools extension
if not ip_pool:
return
if ip_version == 46:
valid_versions = [4, 6]
else:
valid_versions = [ip_version]
ip_pool_list = utils.convert_ip_pool_string_to_list(ip_pool)
for pool in ip_pool_list:
validators.validate_subnet(pool)
ip_net = netaddr.IPNetwork(pool)
if ip_net.version not in valid_versions:
raise gpolicy.InvalidIpPoolVersion(ip_pool=pool,
version=ip_version)
if (ip_net.size <= 3):
err_msg = "Too few available IPs in the pool."
raise gpolicy.InvalidIpPoolSize(ip_pool=pool, err_msg=err_msg,
size=ip_net.size)
if (ip_net.prefixlen == 0):
err_msg = "Prefix length of 0 is invalid."
raise gpolicy.InvalidIpPoolPrefixLength(ip_pool=pool,
err_msg=err_msg,
prefixlen=ip_net.prefixlen)
@staticmethod
def validate_subnet_prefix_length(ip_version, new_prefix_length,
ip_pool=None):
if (ip_version == 4 or ip_version == 46) and ((new_prefix_length >
MAX_IPV4_SUBNET_PREFIX_LENGTH) or (new_prefix_length < 2)):
raise gpolicy.InvalidDefaultSubnetPrefixLength(
length=new_prefix_length, protocol=ip_version)
ip_pool_list = utils.convert_ip_pool_string_to_list(ip_pool)
for pool in ip_pool_list:
# Check if subnet_prefix_length is smaller
# than size of the ip_pool's subnet.
if netaddr.IPNetwork(pool).version == 4:
ip_pool_prefix_length = netaddr.IPNetwork(pool).prefixlen
if(ip_pool_prefix_length > new_prefix_length):
raise gpolicy.SubnetPrefixLengthExceedsIpPool(
ip_pool=pool, subnet_size=new_prefix_length)
def start_rpc_listeners(self):
pass
@log.log_method_call
def create_policy_target(self, context, policy_target):
pt = policy_target['policy_target']
tenant_id = self._get_tenant_id_for_create(context, pt)
with db_api.context_manager.writer.using(context):
pt_db = PolicyTarget(
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
name=pt['name'], description=pt['description'],
policy_target_group_id=pt['policy_target_group_id'],
cluster_id=pt['cluster_id'],
status=pt.get('status'),
status_details=pt.get('status_details'))
context.session.add(pt_db)
return self._make_policy_target_dict(pt_db)
@log.log_method_call
def update_policy_target(self, context, policy_target_id, policy_target):
pt = policy_target['policy_target']
with db_api.context_manager.writer.using(context):
pt_db = self._get_policy_target(context, policy_target_id)
pt_db.update(pt)
return self._make_policy_target_dict(pt_db)
@log.log_method_call
def delete_policy_target(self, context, policy_target_id):
with db_api.context_manager.writer.using(context):
pt_db = self._get_policy_target(context, policy_target_id)
context.session.delete(pt_db)
@log.log_method_call
def get_policy_target(self, context, policy_target_id, fields=None):
pt = self._get_policy_target(context, policy_target_id)
return self._make_policy_target_dict(pt, fields)
@log.log_method_call
def get_policy_targets(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = self._get_marker_obj(context, 'policy_target', limit,
marker)
return self._get_collection(context, PolicyTarget,
self._make_policy_target_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_policy_targets_count(self, context, filters=None):
return self._get_collection_count(context, PolicyTarget,
filters=filters)
@log.log_method_call
def create_policy_target_group(self, context, policy_target_group):
ptg = policy_target_group['policy_target_group']
tenant_id = self._get_tenant_id_for_create(context, ptg)
with db_api.context_manager.writer.using(context):
if ptg['service_management']:
self._validate_service_management_ptg(context, tenant_id)
ptg_db = PolicyTargetGroup(
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
name=ptg['name'], description=ptg['description'],
l2_policy_id=ptg['l2_policy_id'],
application_policy_group_id=ptg.get(
'application_policy_group_id', None),
network_service_policy_id=ptg['network_service_policy_id'],
shared=ptg.get('shared', False),
service_management=ptg.get('service_management', False),
status=ptg.get('status'),
status_details=ptg.get('status_details'))
context.session.add(ptg_db)
self._process_policy_rule_sets_for_ptg(context, ptg_db, ptg)
return self._make_policy_target_group_dict(ptg_db)
@log.log_method_call
def update_policy_target_group(self, context, policy_target_group_id,
policy_target_group):
ptg = policy_target_group['policy_target_group']
with db_api.context_manager.writer.using(context):
ptg_db = self._get_policy_target_group(
context, policy_target_group_id)
ptg = self._process_policy_rule_sets_for_ptg(context, ptg_db, ptg)
ptg_db.update(ptg)
return self._make_policy_target_group_dict(ptg_db)
@log.log_method_call
def delete_policy_target_group(self, context, policy_target_group_id):
with db_api.context_manager.writer.using(context):
ptg_db = self._get_policy_target_group(
context, policy_target_group_id)
# REVISIT(rkukura): An exception should be raised here if
# the PTG is referenced by any PTs, but code added to
# GroupPolicyPlugin.delete_policy_target_group() in
# https://review.openstack.org/#/c/144214/ handles this
# based on whether the PTs referencing it have ports. Note
# that the ports are only removed from the PTs due to
# https://bugs.launchpad.net/nova/+bug/1158684. Once that
# bug is fixed, Nova will no longer be deleting the ports,
# we'll need some way to delete the PTs from Horizon, and
# then we might as well check for in-use EPGs here as with
# other resources.
context.session.delete(ptg_db)
@log.log_method_call
def get_policy_target_group(self, context, policy_target_group_id,
fields=None):
ptg = self._get_policy_target_group(context, policy_target_group_id)
return self._make_policy_target_group_dict(ptg, fields)
@log.log_method_call
def get_policy_target_groups(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = self._get_marker_obj(
context, 'policy_target_group', limit, marker)
return self._get_collection(context, PolicyTargetGroup,
self._make_policy_target_group_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_policy_target_groups_count(self, context, filters=None):
return self._get_collection_count(context, PolicyTargetGroup,
filters=filters)
@log.log_method_call
def create_application_policy_group(self, context,
application_policy_group):
apg = application_policy_group['application_policy_group']
tenant_id = self._get_tenant_id_for_create(context, apg)
with db_api.context_manager.writer.using(context):
apg_db = ApplicationPolicyGroup(
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
name=apg['name'], description=apg['description'],
shared=apg.get('shared', False),
status=apg.get('status'),
status_details=apg.get('status_details'))
context.session.add(apg_db)
return self._make_application_policy_group_dict(apg_db)
@log.log_method_call
def update_application_policy_group(self, context,
application_policy_group_id,
application_policy_group):
apg = application_policy_group['application_policy_group']
with db_api.context_manager.writer.using(context):
apg_db = self._get_application_policy_group(
context, application_policy_group_id)
apg_db.update(apg)
return self._make_application_policy_group_dict(apg_db)
@log.log_method_call
def delete_application_policy_group(self, context,
application_policy_group_id):
with db_api.context_manager.writer.using(context):
apg_db = self._get_application_policy_group(
context, application_policy_group_id)
context.session.delete(apg_db)
@log.log_method_call
def get_application_policy_group(self, context,
application_policy_group_id, fields=None):
apg = self._get_application_policy_group(context,
application_policy_group_id)
return self._make_application_policy_group_dict(apg, fields)
@log.log_method_call
def get_application_policy_groups(self, context, filters=None,
fields=None, sorts=None, limit=None,
marker=None, page_reverse=False):
marker_obj = self._get_marker_obj(
context, 'application_policy_group', limit, marker)
return self._get_collection(context, ApplicationPolicyGroup,
self._make_application_policy_group_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_application_policy_groups_count(self, context, filters=None):
return self._get_collection_count(context, ApplicationPolicyGroup,
filters=filters)
@log.log_method_call
def create_l2_policy(self, context, l2_policy):
l2p = l2_policy['l2_policy']
tenant_id = self._get_tenant_id_for_create(context, l2p)
with db_api.context_manager.writer.using(context):
l2p_db = L2Policy(id=uuidutils.generate_uuid(),
tenant_id=tenant_id, name=l2p['name'],
description=l2p['description'],
l3_policy_id=l2p.get('l3_policy_id'),
inject_default_route=l2p.get(
'inject_default_route', True),
shared=l2p.get('shared', False),
status=l2p.get('status'),
status_details=l2p.get('status_details'))
context.session.add(l2p_db)
return self._make_l2_policy_dict(l2p_db)
@log.log_method_call
def update_l2_policy(self, context, l2_policy_id, l2_policy):
l2p = l2_policy['l2_policy']
with db_api.context_manager.writer.using(context):
l2p_db = self._get_l2_policy(context, l2_policy_id)
l2p_db.update(l2p)
return self._make_l2_policy_dict(l2p_db)
@log.log_method_call
def delete_l2_policy(self, context, l2_policy_id):
with db_api.context_manager.writer.using(context):
l2p_db = self._get_l2_policy(context, l2_policy_id)
# When delete_l2_policy is called implicitly (as a
# side effect of the last PTG deletion), the L2P's
# backref to PTGs is not getting reflected correctly
# here (at least in the UTs). This is fixed by the explicit
# call to refresh.
context.session.refresh(l2p_db)
if l2p_db.policy_target_groups:
raise gpolicy.L2PolicyInUse(l2_policy_id=l2_policy_id)
context.session.delete(l2p_db)
@log.log_method_call
def get_l2_policy(self, context, l2_policy_id, fields=None):
l2p = self._get_l2_policy(context, l2_policy_id)
return self._make_l2_policy_dict(l2p, fields)
@log.log_method_call
def get_l2_policies(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = self._get_marker_obj(context, 'l2_policy', limit,
marker)
return self._get_collection(context, L2Policy,
self._make_l2_policy_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_l2_policies_count(self, context, filters=None):
return self._get_collection_count(context, L2Policy,
filters=filters)
@log.log_method_call
def create_l3_policy(self, context, l3_policy):
l3p = l3_policy['l3_policy']
tenant_id = self._get_tenant_id_for_create(context, l3p)
self.validate_ip_pool(l3p.get('ip_pool', None), l3p['ip_version'])
self.validate_subnet_prefix_length(
l3p['ip_version'], l3p['subnet_prefix_length'],
l3p.get('ip_pool', None))
with db_api.context_manager.writer.using(context):
l3p_db = L3Policy(
id=uuidutils.generate_uuid(),
tenant_id=tenant_id, name=l3p['name'],
description=l3p['description'],
ip_version=l3p['ip_version'],
ip_pool=l3p['ip_pool'],
subnet_prefix_length=l3p['subnet_prefix_length'],
shared=l3p.get('shared', False),
status=l3p.get('status'),
status_details=l3p.get('status_details'))
if 'external_segments' in l3p:
self._set_ess_for_l3p(context, l3p_db,
l3p['external_segments'])
context.session.add(l3p_db)
return self._make_l3_policy_dict(l3p_db)
@log.log_method_call
def update_l3_policy(self, context, l3_policy_id, l3_policy):
l3p = l3_policy['l3_policy']
with db_api.context_manager.writer.using(context):
l3p_db = self._get_l3_policy(context, l3_policy_id)
if 'subnet_prefix_length' in l3p:
self.validate_subnet_prefix_length(
l3p_db.ip_version,
l3p['subnet_prefix_length'], l3p_db.ip_pool)
if 'external_segments' in l3p:
self._set_ess_for_l3p(context, l3p_db,
l3p['external_segments'])
del l3p['external_segments']
l3p_db.update(l3p)
return self._make_l3_policy_dict(l3p_db)
@log.log_method_call
def delete_l3_policy(self, context, l3_policy_id):
with db_api.context_manager.writer.using(context):
l3p_db = self._get_l3_policy(context, l3_policy_id)
if l3p_db.l2_policies:
raise gpolicy.L3PolicyInUse(l3_policy_id=l3_policy_id)
context.session.delete(l3p_db)
@log.log_method_call
def get_l3_policy(self, context, l3_policy_id, fields=None):
l3p = self._get_l3_policy(context, l3_policy_id)
return self._make_l3_policy_dict(l3p, fields)
@log.log_method_call
def get_l3_policies(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = self._get_marker_obj(context, 'l2_policy', limit,
marker)
return self._get_collection(context, L3Policy,
self._make_l3_policy_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_l3_policies_count(self, context, filters=None):
return self._get_collection_count(context, L3Policy,
filters=filters)
@log.log_method_call
def create_network_service_policy(self, context, network_service_policy):
nsp = network_service_policy['network_service_policy']
tenant_id = self._get_tenant_id_for_create(context, nsp)
with db_api.context_manager.writer.using(context):
nsp_db = NetworkServicePolicy(id=uuidutils.generate_uuid(),
tenant_id=tenant_id,
name=nsp['name'],
description=nsp['description'],
shared=nsp.get('shared', False),
status=nsp.get('status'),
status_details=
nsp.get('status_details'))
context.session.add(nsp_db)
self._set_params_for_network_service_policy(
context, nsp_db, nsp)
return self._make_network_service_policy_dict(nsp_db)
@log.log_method_call
def update_network_service_policy(
self, context, network_service_policy_id, network_service_policy):
nsp = network_service_policy['network_service_policy']
with db_api.context_manager.writer.using(context):
nsp_db = self._get_network_service_policy(
context, network_service_policy_id)
if 'network_service_params' in network_service_policy:
self._set_params_for_network_service_policy(
context, nsp_db, nsp)
nsp_db.update(nsp)
return self._make_network_service_policy_dict(nsp_db)
@log.log_method_call
def delete_network_service_policy(
self, context, network_service_policy_id):
with db_api.context_manager.writer.using(context):
nsp_db = self._get_network_service_policy(
context, network_service_policy_id)
if nsp_db.policy_target_groups:
raise gpolicy.NetworkServicePolicyInUse(
network_service_policy_id=network_service_policy_id)
context.session.delete(nsp_db)
@log.log_method_call
def get_network_service_policy(
self, context, network_service_policy_id, fields=None):
nsp = self._get_network_service_policy(
context, network_service_policy_id)
return self._make_network_service_policy_dict(nsp, fields)
@log.log_method_call
def get_network_service_policies(
self, context, filters=None, fields=None, sorts=None, limit=None,
marker=None, page_reverse=False):
marker_obj = self._get_marker_obj(
context, 'network_service_policy', limit, marker)
return self._get_collection(context, NetworkServicePolicy,
self._make_network_service_policy_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_network_service_policies_count(self, context, filters=None):
return self._get_collection_count(context, NetworkServicePolicy,
filters=filters)
@log.log_method_call
def create_policy_classifier(self, context, policy_classifier):
pc = policy_classifier['policy_classifier']
tenant_id = self._get_tenant_id_for_create(context, pc)
port_min, port_max = GroupPolicyDbPlugin._get_min_max_ports_from_range(
pc['port_range'])
with db_api.context_manager.writer.using(context):
pc_db = PolicyClassifier(id=uuidutils.generate_uuid(),
tenant_id=tenant_id,
name=pc['name'],
description=pc['description'],
protocol=pc['protocol'],
port_range_min=port_min,
port_range_max=port_max,
direction=pc['direction'],
shared=pc.get('shared', False),
status=pc.get('status'),
status_details=
pc.get('status_details'))
context.session.add(pc_db)
return self._make_policy_classifier_dict(pc_db)
@log.log_method_call
def update_policy_classifier(self, context, policy_classifier_id,
policy_classifier):
pc = policy_classifier['policy_classifier']
with db_api.context_manager.writer.using(context):
pc_db = self._get_policy_classifier(context, policy_classifier_id)
if 'port_range' in pc:
port_min, port_max = (GroupPolicyDbPlugin.
_get_min_max_ports_from_range(
pc['port_range']))
pc.update({'port_range_min': port_min,
'port_range_max': port_max})
del pc['port_range']
pc_db.update(pc)
return self._make_policy_classifier_dict(pc_db)
@log.log_method_call
def delete_policy_classifier(self, context, policy_classifier_id):
with db_api.context_manager.writer.using(context):
pc_db = self._get_policy_classifier(context, policy_classifier_id)
pc_ids = self._get_policy_classifier_rules(context,
policy_classifier_id)
if pc_ids:
raise gpolicy.PolicyClassifierInUse(
policy_classifier_id=policy_classifier_id)
context.session.delete(pc_db)
@log.log_method_call
def get_policy_classifier(self, context, policy_classifier_id,
fields=None):
pc = self._get_policy_classifier(context, policy_classifier_id)
return self._make_policy_classifier_dict(pc, fields)
@log.log_method_call
def get_policy_classifiers(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = self._get_marker_obj(context, 'policy_classifier', limit,
marker)
return self._get_collection(context, PolicyClassifier,
self._make_policy_classifier_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_policy_classifiers_count(self, context, filters=None):
return self._get_collection_count(context, PolicyClassifier,
filters=filters)
@log.log_method_call
def create_policy_action(self, context, policy_action):
pa = policy_action['policy_action']
tenant_id = self._get_tenant_id_for_create(context, pa)
with db_api.context_manager.writer.using(context):
pa_db = PolicyAction(id=uuidutils.generate_uuid(),
tenant_id=tenant_id,
name=pa['name'],
description=pa['description'],
action_type=pa['action_type'],
action_value=pa['action_value'],
shared=pa.get('shared', False),
status=pa.get('status'),
status_details=
pa.get('status_details'))
context.session.add(pa_db)
return self._make_policy_action_dict(pa_db)
@log.log_method_call
def update_policy_action(self, context, policy_action_id, policy_action):
pa = policy_action['policy_action']
with db_api.context_manager.writer.using(context):
pa_db = self._get_policy_action(context, policy_action_id)
pa_db.update(pa)
return self._make_policy_action_dict(pa_db)
@log.log_method_call
def delete_policy_action(self, context, policy_action_id):
with db_api.context_manager.writer.using(context):
pa_db = self._get_policy_action(context, policy_action_id)
pa_ids = self._get_policy_action_rules(context, policy_action_id)
if pa_ids:
raise gpolicy.PolicyActionInUse(
policy_action_id=policy_action_id)
context.session.delete(pa_db)
@log.log_method_call
def get_policy_action(self, context, id, fields=None):
pa = self._get_policy_action(context, id)
return self._make_policy_action_dict(pa, fields)
@log.log_method_call
def get_policy_actions(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = self._get_marker_obj(context, 'policy_action', limit,
marker)
return self._get_collection(context, PolicyAction,
self._make_policy_action_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_policy_actions_count(self, context, filters=None):
return self._get_collection_count(context, PolicyAction,
filters=filters)
@log.log_method_call
def create_policy_rule(self, context, policy_rule):
pr = policy_rule['policy_rule']
tenant_id = self._get_tenant_id_for_create(context, pr)
with db_api.context_manager.writer.using(context):
pr_db = PolicyRule(id=uuidutils.generate_uuid(),
tenant_id=tenant_id, name=pr['name'],
description=pr['description'],
enabled=pr['enabled'],
policy_classifier_id=pr['policy_classifier_id'],
shared=pr.get('shared', False),
status=pr.get('status'),
status_details=pr.get('status_details'))
context.session.add(pr_db)
self._set_actions_for_rule(context, pr_db,
pr['policy_actions'])
return self._make_policy_rule_dict(pr_db)
@log.log_method_call
def update_policy_rule(self, context, policy_rule_id, policy_rule):
pr = policy_rule['policy_rule']
with db_api.context_manager.writer.using(context):
pr_db = self._get_policy_rule(context, policy_rule_id)
if 'policy_actions' in pr:
self._set_actions_for_rule(context, pr_db,
pr['policy_actions'])
del pr['policy_actions']
pr_db.update(pr)
return self._make_policy_rule_dict(pr_db)
@log.log_method_call
def delete_policy_rule(self, context, policy_rule_id):
with db_api.context_manager.writer.using(context):
pr_db = self._get_policy_rule(context, policy_rule_id)
prs_ids = self._get_policy_rule_policy_rule_sets(context,
policy_rule_id)
if prs_ids:
raise gpolicy.PolicyRuleInUse(policy_rule_id=policy_rule_id)
context.session.delete(pr_db)
@log.log_method_call
def get_policy_rule(self, context, policy_rule_id, fields=None):
pr = self._get_policy_rule(context, policy_rule_id)
return self._make_policy_rule_dict(pr, fields)
@log.log_method_call
def get_policy_rules(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = self._get_marker_obj(context, 'policy_rule', limit,
marker)
return self._get_collection(context, PolicyRule,
self._make_policy_rule_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_policy_rules_count(self, context, filters=None):
return self._get_collection_count(context, PolicyRule,
filters=filters)
@log.log_method_call
def create_policy_rule_set(self, context, policy_rule_set):
prs = policy_rule_set['policy_rule_set']
tenant_id = self._get_tenant_id_for_create(context, prs)
with db_api.context_manager.writer.using(context):
prs_db = PolicyRuleSet(id=uuidutils.generate_uuid(),
tenant_id=tenant_id,
name=prs['name'],
description=prs['description'],
shared=prs.get('shared', False),
status=prs.get('status'),
status_details=prs.get('status_details'))
context.session.add(prs_db)
self._set_rules_for_policy_rule_set(context, prs_db,
prs['policy_rules'])
self._set_children_for_policy_rule_set(
context, prs_db, prs['child_policy_rule_sets'])
return self._make_policy_rule_set_dict(prs_db)
@log.log_method_call
def update_policy_rule_set(self, context, policy_rule_set_id,
policy_rule_set):
prs = policy_rule_set['policy_rule_set']
with db_api.context_manager.writer.using(context):
prs_db = self._get_policy_rule_set(context, policy_rule_set_id)
if 'policy_rules' in prs:
self._set_rules_for_policy_rule_set(
context, prs_db, prs['policy_rules'])
del prs['policy_rules']
if 'child_policy_rule_sets' in prs:
self._set_children_for_policy_rule_set(
context, prs_db, prs['child_policy_rule_sets'])
del prs['child_policy_rule_sets']
prs_db.update(prs)
return self._make_policy_rule_set_dict(prs_db)
@log.log_method_call
def delete_policy_rule_set(self, context, policy_rule_set_id):
with db_api.context_manager.writer.using(context):
prs_db = self._get_policy_rule_set(context, policy_rule_set_id)
prs_ids = (
self._get_ptgs_for_providing_policy_rule_set(
context, policy_rule_set_id) or
self._get_ptgs_for_consuming_policy_rule_set(
context, policy_rule_set_id) or
self._get_eps_for_providing_policy_rule_set(
context, policy_rule_set_id) or
self._get_eps_for_consuming_policy_rule_set(
context, policy_rule_set_id))
if prs_ids:
raise gpolicy.PolicyRuleSetInUse(policy_rule_set_id=
policy_rule_set_id)
context.session.delete(prs_db)
@log.log_method_call
def get_policy_rule_set(self, context, policy_rule_set_id, fields=None):
prs = self._get_policy_rule_set(context, policy_rule_set_id)
return self._make_policy_rule_set_dict(prs, fields)
@log.log_method_call
def get_policy_rule_sets(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
marker_obj = self._get_marker_obj(context, 'policy_rule_set', limit,
marker)
return self._get_collection(context, PolicyRuleSet,
self._make_policy_rule_set_dict,
filters=filters, fields=fields,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_policy_rule_sets_count(self, context, filters=None):
return self._get_collection_count(context, PolicyRuleSet,
filters=filters)
@log.log_method_call
def create_external_policy(self, context, external_policy):
ep = external_policy['external_policy']
tenant_id = self._get_tenant_id_for_create(context, ep)
with db_api.context_manager.writer.using(context):
ep_db = ExternalPolicy(
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
name=ep['name'], description=ep['description'],
shared=ep.get('shared', False),
status=ep.get('status'),
status_details=ep.get('status_details'))
context.session.add(ep_db)
if 'external_segments' in ep:
self._set_ess_for_ep(context, ep_db,
ep['external_segments'])
self._process_policy_rule_sets_for_ep(context, ep_db, ep)
return self._make_external_policy_dict(ep_db)
@log.log_method_call
def update_external_policy(self, context, external_policy_id,
external_policy):
ep = external_policy['external_policy']
with db_api.context_manager.writer.using(context):
ep_db = self._get_external_policy(
context, external_policy_id)
if 'external_segments' in ep:
self._set_ess_for_ep(context, ep_db,
ep['external_segments'])
del ep['external_segments']
self._process_policy_rule_sets_for_ep(context, ep_db, ep)
ep_db.update(ep)
return self._make_external_policy_dict(ep_db)
@log.log_method_call
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,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_external_policies_count(self, context, filters=None):
return self._get_collection_count(context, ExternalPolicy,
filters=filters)
@log.log_method_call
def get_external_policy(self, context, external_policy_id, fields=None):
ep = self._get_external_policy(
context, external_policy_id)
return self._make_external_policy_dict(ep, fields)
@log.log_method_call
def delete_external_policy(self, context, external_policy_id):
with db_api.context_manager.writer.using(context):
ep_db = self._get_external_policy(
context, external_policy_id)
context.session.delete(ep_db)
@log.log_method_call
def create_external_segment(self, context, external_segment):
es = external_segment['external_segment']
tenant_id = self._get_tenant_id_for_create(context, es)
with db_api.context_manager.writer.using(context):
es_db = ExternalSegment(
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
name=es['name'], description=es['description'],
shared=es.get('shared', False), ip_version=es['ip_version'],
cidr=es['cidr'],
port_address_translation=es['port_address_translation'],
status=es.get('status'),
status_details=es.get('status_details'))
context.session.add(es_db)
if 'external_routes' in es:
self._process_segment_ers(context, es_db, es)
return self._make_external_segment_dict(es_db)
@log.log_method_call
def update_external_segment(self, context, external_segment_id,
external_segment):
es = external_segment['external_segment']
with db_api.context_manager.writer.using(context):
es_db = self._get_external_segment(
context, external_segment_id)
if 'external_routes' in es:
self._process_segment_ers(context, es_db, es)
del es['external_routes']
es_db.update(es)
return self._make_external_segment_dict(es_db)
@log.log_method_call
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,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_external_segments_count(self, context, filters=None):
return self._get_collection_count(context, ExternalSegment,
filters=filters)
@log.log_method_call
def get_external_segment(self, context, external_segment_id, fields=None):
es = self._get_external_segment(
context, external_segment_id)
return self._make_external_segment_dict(es, fields)
@log.log_method_call
def delete_external_segment(self, context, external_segment_id):
with db_api.context_manager.writer.using(context):
es_db = self._get_external_segment(
context, external_segment_id)
context.session.delete(es_db)
@log.log_method_call
def create_nat_pool(self, context, nat_pool):
np = nat_pool['nat_pool']
tenant_id = self._get_tenant_id_for_create(context, np)
with db_api.context_manager.writer.using(context):
np_db = NATPool(
id=uuidutils.generate_uuid(), tenant_id=tenant_id,
name=np['name'], description=np['description'],
shared=np.get('shared', False), ip_version=np['ip_version'],
ip_pool=np['ip_pool'],
external_segment_id=np['external_segment_id'],
status=np.get('status'),
status_details=np.get('status_details'))
context.session.add(np_db)
return self._make_nat_pool_dict(np_db)
@log.log_method_call
def update_nat_pool(self, context, nat_pool_id, nat_pool):
np = nat_pool['nat_pool']
with db_api.context_manager.writer.using(context):
np_db = self._get_nat_pool(
context, nat_pool_id)
np_db.update(np)
return self._make_nat_pool_dict(np_db)
@log.log_method_call
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,
sorts=sorts, limit=limit,
marker_obj=marker_obj,
page_reverse=page_reverse)
@log.log_method_call
def get_nat_pools_count(self, context, filters=None):
return self._get_collection_count(context, NATPool, filters=filters)
@log.log_method_call
def get_nat_pool(self, context, nat_pool_id, fields=None):
np = self._get_nat_pool(context, nat_pool_id)
return self._make_nat_pool_dict(np, fields)
@log.log_method_call
def delete_nat_pool(self, context, nat_pool_id):
with db_api.context_manager.writer.using(context):
np_db = self._get_nat_pool(context, nat_pool_id)
context.session.delete(np_db)