group-based-policy/gbpservice/neutron/db/implicitsubnetpool_db.py

147 lines
6.2 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 sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy import sql
from neutron.api.v2 import attributes as attr
from neutron.db import db_base_plugin_v2
from neutron.db import models_v2
from neutron_lib.api import validators
from neutron_lib.db import model_base
from neutron_lib import exceptions as n_exc
class ImplicitSubnetpool(model_base.BASEV2):
__tablename__ = "implicit_subnetpools"
subnetpool_id = sa.Column(sa.String(36),
sa.ForeignKey('subnetpools.id',
ondelete="CASCADE"),
primary_key=True)
is_implicit = sa.Column(sa.Boolean, nullable=False,
server_default=sql.false())
subnetpool = orm.relationship(
models_v2.SubnetPool,
backref=orm.backref("implicit",
lazy="joined", cascade="delete"))
class ImplicitSubnetpoolMixin(object):
"""Mixin class for implicit subnetpool."""
def get_implicit_subnetpool_id(self, context, tenant=None, ip_version="4"):
pool = self.get_implicit_subnetpool(context, tenant=tenant,
ip_version=ip_version)
return pool['id'] if pool else None
def get_implicit_subnetpool(self, context, tenant=None, ip_version="4"):
pools = self._get_implicit_subnetpools(context, tenant=tenant,
ip_version=ip_version)
return pools[0] if pools else None
def _get_implicit_subnetpools(self, context, tenant=None, ip_version="4"):
admin_context = context.elevated()
filters = {"is_implicit": [True],
"ip_version": ip_version}
if tenant:
filters["tenant_id"] = [tenant]
else:
filters["shared"] = [True]
with context.session.begin(subtransactions=True):
return self.get_subnetpools(admin_context, filters)
def _get_implicit_subnetpool(self, context, subnetpool_id):
return (context.session.query(ImplicitSubnetpool).
filter_by(subnetpool_id=subnetpool_id)).first()
def _subnetpool_model_hook(self, context, original_model, query):
query = query.outerjoin(ImplicitSubnetpool,
(original_model.id ==
ImplicitSubnetpool.subnetpool_id))
return query
def _subnetpool_filter_hook(self, context, original_model, conditions):
return conditions
def _subnetpool_result_filter_hook(self, query, filters):
vals = filters and filters.get('is_implicit', [])
if not vals:
return query
return query.filter(
(ImplicitSubnetpool.is_implicit.in_(vals)))
db_base_plugin_v2.NeutronDbPluginV2.register_model_query_hook(
models_v2.SubnetPool,
"implicit_subnetpool",
'_subnetpool_model_hook',
'_subnetpool_filter_hook',
'_subnetpool_result_filter_hook')
def _extend_subnetpool_dict_implicit(self, subnetpool_res,
subnetpool_db):
try:
subnetpool_res["is_implicit"] = (
subnetpool_db.implicit[0].is_implicit)
except (IndexError, AttributeError):
# is_implicit is not created yet when subnetpool is first added
# to the database
pass
return subnetpool_res
# Register dict extend functions for ports
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
attr.SUBNETPOOLS, ['_extend_subnetpool_dict_implicit'])
def update_implicit_subnetpool(self, context, subnetpool):
is_implicit = False
if validators.is_attr_set(subnetpool.get('is_implicit')):
is_implicit = subnetpool['is_implicit']
with context.session.begin(subtransactions=True):
if is_implicit:
# Verify feasibility. Only one implicit SP must exist per
# tenant (or global)
msg = _('There can be at most one implicit '
'subnetpool per address family per tenant.')
self._validate_implicit_subnetpool(
context, subnetpool['id'], tenant=subnetpool['tenant_id'],
msg=msg, ip_version=subnetpool['ip_version'])
if subnetpool['shared']:
# Check globally too
msg = _('There can be at most one global implicit '
'subnetpool per address family.')
self._validate_implicit_subnetpool(
context, subnetpool['id'],
tenant=None,
msg=msg, ip_version=subnetpool['ip_version'])
db_obj = self._get_implicit_subnetpool(
context, subnetpool['id'])
if db_obj:
db_obj.is_implicit = is_implicit
db_obj = db_obj or ImplicitSubnetpool(
subnetpool_id=subnetpool['id'],
is_implicit=is_implicit)
context.session.add(db_obj)
return is_implicit
def _validate_implicit_subnetpool(self, context, subnetpool_id,
tenant=None, msg=None, ip_version="4"):
current_implicit_sp = self._get_implicit_subnetpools(
context, tenant=tenant, ip_version=ip_version)
if len(current_implicit_sp) > 1:
raise n_exc.BadRequest(resource='subnetpools', msg=msg)
if (len(current_implicit_sp) == 1 and
current_implicit_sp[0]['id'] != subnetpool_id):
raise n_exc.BadRequest(resource='subnetpools', msg=msg)