62576cabf7
neutron-lib now contains the API definitions for neutron's core resources. This patch removes the constant core resource and collection variables and uses them from lib. Subsequent patches will consume the actual core resource attribute definitions. NeutronLibImpact Change-Id: Ia9afdf620cd538b2aa420593277d6403a45c996b
240 lines
8.1 KiB
Python
240 lines
8.1 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 abc
|
|
|
|
from neutron_lib.api.definitions import network
|
|
from neutron_lib.api import extensions as api_extensions
|
|
from neutron_lib.api import validators
|
|
from neutron_lib import exceptions
|
|
from neutron_lib.plugins import directory
|
|
from neutron_lib.services import base as service_base
|
|
import six
|
|
import webob.exc
|
|
|
|
from neutron._i18n import _
|
|
from neutron.api import extensions
|
|
from neutron.api.v2 import base
|
|
from neutron.api.v2 import resource as api_resource
|
|
from neutron.common import rpc as n_rpc
|
|
|
|
|
|
TAG = 'tag'
|
|
TAGS = TAG + 's'
|
|
MAX_TAG_LEN = 60
|
|
TAG_PLUGIN_TYPE = 'TAG'
|
|
|
|
TAG_SUPPORTED_RESOURCES = {
|
|
# We shouldn't add new resources here. If more resources need to be tagged,
|
|
# we must add them in new extension.
|
|
network.COLLECTION_NAME: network.RESOURCE_NAME,
|
|
}
|
|
|
|
TAG_ATTRIBUTE_MAP = {
|
|
TAGS: {'allow_post': False, 'allow_put': False, 'is_visible': True}
|
|
}
|
|
|
|
|
|
class TagResourceNotFound(exceptions.NotFound):
|
|
message = _("Resource %(resource)s %(resource_id)s could not be found.")
|
|
|
|
|
|
class TagNotFound(exceptions.NotFound):
|
|
message = _("Tag %(tag)s could not be found.")
|
|
|
|
|
|
def validate_tag(tag):
|
|
msg = validators.validate_string(tag, MAX_TAG_LEN)
|
|
if msg:
|
|
raise exceptions.InvalidInput(error_message=msg)
|
|
|
|
|
|
def validate_tags(body):
|
|
if 'tags' not in body:
|
|
raise exceptions.InvalidInput(error_message=_("Invalid tags body"))
|
|
msg = validators.validate_list_of_unique_strings(body['tags'], MAX_TAG_LEN)
|
|
if msg:
|
|
raise exceptions.InvalidInput(error_message=msg)
|
|
|
|
|
|
def notify_tag_action(context, action, parent, parent_id, tags=None):
|
|
notifier = n_rpc.get_notifier('network')
|
|
tag_event = 'tag.%s' % action
|
|
# TODO(hichihara): Add 'updated_at' into payload
|
|
payload = {'parent_resource': parent,
|
|
'parent_resource_id': parent_id}
|
|
if tags is not None:
|
|
payload['tags'] = tags
|
|
notifier.info(context, tag_event, payload)
|
|
|
|
|
|
class TagController(object):
|
|
def __init__(self):
|
|
self.plugin = directory.get_plugin(TAG_PLUGIN_TYPE)
|
|
self.supported_resources = TAG_SUPPORTED_RESOURCES
|
|
|
|
def _get_parent_resource_and_id(self, kwargs):
|
|
for key in kwargs:
|
|
for resource in self.supported_resources:
|
|
if key == self.supported_resources[resource] + '_id':
|
|
return resource, kwargs[key]
|
|
return None, None
|
|
|
|
def index(self, request, **kwargs):
|
|
# GET /v2.0/networks/{network_id}/tags
|
|
parent, parent_id = self._get_parent_resource_and_id(kwargs)
|
|
return self.plugin.get_tags(request.context, parent, parent_id)
|
|
|
|
def show(self, request, id, **kwargs):
|
|
# GET /v2.0/networks/{network_id}/tags/{tag}
|
|
# id == tag
|
|
validate_tag(id)
|
|
parent, parent_id = self._get_parent_resource_and_id(kwargs)
|
|
return self.plugin.get_tag(request.context, parent, parent_id, id)
|
|
|
|
def create(self, request, **kwargs):
|
|
# not supported
|
|
# POST /v2.0/networks/{network_id}/tags
|
|
raise webob.exc.HTTPNotFound("not supported")
|
|
|
|
def update(self, request, id, **kwargs):
|
|
# PUT /v2.0/networks/{network_id}/tags/{tag}
|
|
# id == tag
|
|
validate_tag(id)
|
|
parent, parent_id = self._get_parent_resource_and_id(kwargs)
|
|
notify_tag_action(request.context, 'create.start',
|
|
parent, parent_id, [id])
|
|
result = self.plugin.update_tag(request.context, parent, parent_id, id)
|
|
notify_tag_action(request.context, 'create.end',
|
|
parent, parent_id, [id])
|
|
return result
|
|
|
|
def update_all(self, request, body, **kwargs):
|
|
# PUT /v2.0/networks/{network_id}/tags
|
|
# body: {"tags": ["aaa", "bbb"]}
|
|
validate_tags(body)
|
|
parent, parent_id = self._get_parent_resource_and_id(kwargs)
|
|
notify_tag_action(request.context, 'update.start',
|
|
parent, parent_id, body['tags'])
|
|
result = self.plugin.update_tags(request.context, parent,
|
|
parent_id, body)
|
|
notify_tag_action(request.context, 'update.end',
|
|
parent, parent_id, body['tags'])
|
|
return result
|
|
|
|
def delete(self, request, id, **kwargs):
|
|
# DELETE /v2.0/networks/{network_id}/tags/{tag}
|
|
# id == tag
|
|
validate_tag(id)
|
|
parent, parent_id = self._get_parent_resource_and_id(kwargs)
|
|
notify_tag_action(request.context, 'delete.start',
|
|
parent, parent_id, [id])
|
|
result = self.plugin.delete_tag(request.context, parent, parent_id, id)
|
|
notify_tag_action(request.context, 'delete.end',
|
|
parent, parent_id, [id])
|
|
return result
|
|
|
|
def delete_all(self, request, **kwargs):
|
|
# DELETE /v2.0/networks/{network_id}/tags
|
|
parent, parent_id = self._get_parent_resource_and_id(kwargs)
|
|
notify_tag_action(request.context, 'delete_all.start',
|
|
parent, parent_id)
|
|
result = self.plugin.delete_tags(request.context, parent, parent_id)
|
|
notify_tag_action(request.context, 'delete_all.end',
|
|
parent, parent_id)
|
|
return result
|
|
|
|
|
|
class Tag(api_extensions.ExtensionDescriptor):
|
|
"""Extension class supporting tags."""
|
|
|
|
@classmethod
|
|
def get_name(cls):
|
|
return "Tag support"
|
|
|
|
@classmethod
|
|
def get_alias(cls):
|
|
return "tag"
|
|
|
|
@classmethod
|
|
def get_description(cls):
|
|
return "Enables to set tag on resources."
|
|
|
|
@classmethod
|
|
def get_updated(cls):
|
|
return "2016-01-01T00:00:00-00:00"
|
|
|
|
@classmethod
|
|
def get_resources(cls):
|
|
"""Returns Ext Resources."""
|
|
exts = []
|
|
action_status = {'index': 200, 'show': 204, 'update': 201,
|
|
'update_all': 200, 'delete': 204, 'delete_all': 204}
|
|
controller = api_resource.Resource(TagController(),
|
|
base.FAULT_MAP,
|
|
action_status=action_status)
|
|
collection_methods = {"delete_all": "DELETE",
|
|
"update_all": "PUT"}
|
|
exts = []
|
|
for collection_name, member_name in TAG_SUPPORTED_RESOURCES.items():
|
|
parent = {'member_name': member_name,
|
|
'collection_name': collection_name}
|
|
exts.append(extensions.ResourceExtension(
|
|
TAGS, controller, parent,
|
|
collection_methods=collection_methods))
|
|
return exts
|
|
|
|
def get_extended_resources(self, version):
|
|
if version != "2.0":
|
|
return {}
|
|
EXTENDED_ATTRIBUTES_2_0 = {}
|
|
for collection_name in TAG_SUPPORTED_RESOURCES:
|
|
EXTENDED_ATTRIBUTES_2_0[collection_name] = TAG_ATTRIBUTE_MAP
|
|
return EXTENDED_ATTRIBUTES_2_0
|
|
|
|
|
|
@six.add_metaclass(abc.ABCMeta)
|
|
class TagPluginBase(service_base.ServicePluginBase):
|
|
"""REST API to operate the Tag."""
|
|
|
|
def get_plugin_description(self):
|
|
return "Tag support"
|
|
|
|
@classmethod
|
|
def get_plugin_type(cls):
|
|
return TAG_PLUGIN_TYPE
|
|
|
|
@abc.abstractmethod
|
|
def get_tags(self, context, resource, resource_id):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_tag(self, context, resource, resource_id, tag):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def update_tags(self, context, resource, resource_id, body):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def update_tag(self, context, resource, resource_id, tag):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def delete_tags(self, context, resource, resource_id):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def delete_tag(self, context, resource, resource_id, tag):
|
|
pass
|