neutron/neutron/services/tag/tag_plugin.py

125 lines
5.0 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 functools
from oslo_db import api as oslo_db_api
from oslo_db import exception as db_exc
from oslo_log import helpers as log_helpers
from sqlalchemy.orm import exc
from neutron.api.v2 import attributes
from neutron.db import api as db_api
from neutron.db import common_db_mixin
from neutron.db import models_v2
from neutron.db import tag_db as tag_model
from neutron.extensions import tag as tag_ext
resource_model_map = {
attributes.NETWORKS: models_v2.Network,
# other resources can be added
}
def _extend_tags_dict(plugin, response_data, db_data):
tags = [tag_db.tag for tag_db in db_data.standard_attr.tags]
response_data['tags'] = tags
class TagPlugin(common_db_mixin.CommonDbMixin, tag_ext.TagPluginBase):
"""Implementation of the Neutron Tag Service Plugin."""
supported_extension_aliases = ['tag']
def _get_resource(self, context, resource, resource_id):
model = resource_model_map[resource]
try:
return self._get_by_id(context, model, resource_id)
except exc.NoResultFound:
raise tag_ext.TagResourceNotFound(resource=resource,
resource_id=resource_id)
@log_helpers.log_method_call
def get_tags(self, context, resource, resource_id):
res = self._get_resource(context, resource, resource_id)
tags = [tag_db.tag for tag_db in res.standard_attr.tags]
return dict(tags=tags)
@log_helpers.log_method_call
def get_tag(self, context, resource, resource_id, tag):
res = self._get_resource(context, resource, resource_id)
if not any(tag == tag_db.tag for tag_db in res.standard_attr.tags):
raise tag_ext.TagNotFound(tag=tag)
@log_helpers.log_method_call
@oslo_db_api.wrap_db_retry(
max_retries=db_api.MAX_RETRIES,
exception_checker=lambda e: isinstance(e, db_exc.DBDuplicateEntry))
def update_tags(self, context, resource, resource_id, body):
res = self._get_resource(context, resource, resource_id)
new_tags = set(body['tags'])
old_tags = {tag_db.tag for tag_db in res.standard_attr.tags}
tags_added = new_tags - old_tags
tags_removed = old_tags - new_tags
with context.session.begin(subtransactions=True):
for tag_db in res.standard_attr.tags:
if tag_db.tag in tags_removed:
context.session.delete(tag_db)
for tag in tags_added:
tag_db = tag_model.Tag(standard_attr_id=res.standard_attr_id,
tag=tag)
context.session.add(tag_db)
return body
@log_helpers.log_method_call
def update_tag(self, context, resource, resource_id, tag):
res = self._get_resource(context, resource, resource_id)
if any(tag == tag_db.tag for tag_db in res.standard_attr.tags):
return
try:
with context.session.begin(subtransactions=True):
tag_db = tag_model.Tag(standard_attr_id=res.standard_attr_id,
tag=tag)
context.session.add(tag_db)
except db_exc.DBDuplicateEntry:
pass
@log_helpers.log_method_call
def delete_tags(self, context, resource, resource_id):
res = self._get_resource(context, resource, resource_id)
with context.session.begin(subtransactions=True):
query = context.session.query(tag_model.Tag)
query = query.filter_by(standard_attr_id=res.standard_attr_id)
query.delete()
@log_helpers.log_method_call
def delete_tag(self, context, resource, resource_id, tag):
res = self._get_resource(context, resource, resource_id)
with context.session.begin(subtransactions=True):
query = context.session.query(tag_model.Tag)
query = query.filter_by(tag=tag,
standard_attr_id=res.standard_attr_id)
if not query.delete():
raise tag_ext.TagNotFound(tag=tag)
# support only _apply_dict_extend_functions supported resources
# at the moment.
for resource, model in resource_model_map.items():
common_db_mixin.CommonDbMixin.register_dict_extend_funcs(
resource, [_extend_tags_dict])
common_db_mixin.CommonDbMixin.register_model_query_hook(
model, "tag", None, None,
functools.partial(tag_model.apply_tag_filters, model))