diff --git a/neutron/api/v2/router.py b/neutron/api/v2/router.py deleted file mode 100644 index f1b5787d9..000000000 --- a/neutron/api/v2/router.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation. -# -# 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. - -from oslo.config import cfg -import routes as routes_mapper -import six.moves.urllib.parse as urlparse -import webob -import webob.dec -import webob.exc - -from neutron.api import extensions -from neutron.api.v2 import attributes -from neutron.api.v2 import base -from neutron import manager -from neutron.openstack.common import log as logging -from neutron import wsgi - - -LOG = logging.getLogger(__name__) - -RESOURCES = {'network': 'networks', - 'subnet': 'subnets', - 'port': 'ports'} -SUB_RESOURCES = {} -COLLECTION_ACTIONS = ['index', 'create'] -MEMBER_ACTIONS = ['show', 'update', 'delete'] -REQUIREMENTS = {'id': attributes.UUID_PATTERN, 'format': 'xml|json'} - - -class Index(wsgi.Application): - def __init__(self, resources): - self.resources = resources - - @webob.dec.wsgify(RequestClass=wsgi.Request) - def __call__(self, req): - metadata = {'application/xml': {'attributes': { - 'resource': ['name', 'collection'], - 'link': ['href', 'rel']}}} - - layout = [] - for name, collection in self.resources.iteritems(): - href = urlparse.urljoin(req.path_url, collection) - resource = {'name': name, - 'collection': collection, - 'links': [{'rel': 'self', - 'href': href}]} - layout.append(resource) - response = dict(resources=layout) - content_type = req.best_match_content_type() - body = wsgi.Serializer(metadata=metadata).serialize(response, - content_type) - return webob.Response(body=body, content_type=content_type) - - -class APIRouter(wsgi.Router): - - @classmethod - def factory(cls, global_config, **local_config): - return cls(**local_config) - - def __init__(self, **local_config): - mapper = routes_mapper.Mapper() - plugin = manager.NeutronManager.get_plugin() - ext_mgr = extensions.PluginAwareExtensionManager.get_instance() - ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP) - - col_kwargs = dict(collection_actions=COLLECTION_ACTIONS, - member_actions=MEMBER_ACTIONS) - - def _map_resource(collection, resource, params, parent=None): - allow_bulk = cfg.CONF.allow_bulk - allow_pagination = cfg.CONF.allow_pagination - allow_sorting = cfg.CONF.allow_sorting - controller = base.create_resource( - collection, resource, plugin, params, allow_bulk=allow_bulk, - parent=parent, allow_pagination=allow_pagination, - allow_sorting=allow_sorting) - path_prefix = None - if parent: - path_prefix = "/%s/{%s_id}/%s" % (parent['collection_name'], - parent['member_name'], - collection) - mapper_kwargs = dict(controller=controller, - requirements=REQUIREMENTS, - path_prefix=path_prefix, - **col_kwargs) - return mapper.collection(collection, resource, - **mapper_kwargs) - - mapper.connect('index', '/', controller=Index(RESOURCES)) - for resource in RESOURCES: - _map_resource(RESOURCES[resource], resource, - attributes.RESOURCE_ATTRIBUTE_MAP.get( - RESOURCES[resource], dict())) - - for resource in SUB_RESOURCES: - _map_resource(SUB_RESOURCES[resource]['collection_name'], resource, - attributes.RESOURCE_ATTRIBUTE_MAP.get( - SUB_RESOURCES[resource]['collection_name'], - dict()), - SUB_RESOURCES[resource]['parent']) - - super(APIRouter, self).__init__(mapper) diff --git a/neutron/api/__init__.py b/tacker/api/__init__.py similarity index 100% rename from neutron/api/__init__.py rename to tacker/api/__init__.py diff --git a/neutron/api/api_common.py b/tacker/api/api_common.py similarity index 97% rename from neutron/api/api_common.py rename to tacker/api/api_common.py index e370e2e5a..ee943e0b8 100644 --- a/neutron/api/api_common.py +++ b/tacker/api/api_common.py @@ -18,9 +18,9 @@ import urllib from oslo.config import cfg from webob import exc -from neutron.common import constants -from neutron.common import exceptions -from neutron.openstack.common import log as logging +from tacker.common import constants +from tacker.common import exceptions +from tacker.openstack.common import log as logging LOG = logging.getLogger(__name__) @@ -290,14 +290,14 @@ class NoSortingHelper(SortingHelper): pass -class NeutronController(object): - """Base controller class for Neutron API.""" +class TackerController(object): + """Base controller class for Tacker API.""" # _resource_name will be redefined in sub concrete controller _resource_name = None def __init__(self, plugin): self._plugin = plugin - super(NeutronController, self).__init__() + super(TackerController, self).__init__() def _prepare_request_body(self, body, params): """Verifies required parameters are in request body. diff --git a/neutron/api/extensions.py b/tacker/api/extensions.py similarity index 88% rename from neutron/api/extensions.py rename to tacker/api/extensions.py index 4f9988e01..350c841c3 100644 --- a/neutron/api/extensions.py +++ b/tacker/api/extensions.py @@ -16,7 +16,6 @@ import abc import imp -import itertools import os from oslo.config import cfg @@ -25,13 +24,12 @@ import six import webob.dec import webob.exc -from neutron.api.v2 import attributes -from neutron.common import exceptions -import neutron.extensions -from neutron import manager -from neutron.openstack.common import log as logging -from neutron import policy -from neutron import wsgi +from tacker.api.v1 import attributes +from tacker.common import exceptions +import tacker.extensions +from tacker.openstack.common import log as logging +from tacker import policy +from tacker import wsgi LOG = logging.getLogger(__name__) @@ -384,10 +382,10 @@ class ExtensionMiddleware(wsgi.Middleware): return app -def plugin_aware_extension_middleware_factory(global_config, **local_config): +def extension_middleware_factory(global_config, **local_config): """Paste factory.""" def _factory(app): - ext_mgr = PluginAwareExtensionManager.get_instance() + ext_mgr = ExtensionManager.get_instance() return ExtensionMiddleware(app, ext_mgr=ext_mgr) return _factory @@ -399,6 +397,14 @@ class ExtensionManager(object): example extension implementation. """ + _instance = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = cls(get_extensions_path()) + return cls._instance + def __init__(self, path): LOG.info(_('Initializing extension manager.')) self.path = path @@ -539,7 +545,7 @@ class ExtensionManager(object): def _load_all_extensions_from_path(self, path): # Sorting the extension list makes the order in which they # are loaded predictable across a cluster of load-balanced - # Neutron Servers + # Tacker Servers for f in sorted(os.listdir(path)): try: LOG.debug(_('Loading extension file: %s'), f) @@ -574,68 +580,11 @@ class ExtensionManager(object): self.extensions[alias] = ext -class PluginAwareExtensionManager(ExtensionManager): - - _instance = None - - def __init__(self, path, plugins): - self.plugins = plugins - super(PluginAwareExtensionManager, self).__init__(path) - self.check_if_plugin_extensions_loaded() - - def _check_extension(self, extension): - """Check if an extension is supported by any plugin.""" - extension_is_valid = super(PluginAwareExtensionManager, - self)._check_extension(extension) - return (extension_is_valid and - self._plugins_support(extension) and - self._plugins_implement_interface(extension)) - - def _plugins_support(self, extension): - alias = extension.get_alias() - supports_extension = any((hasattr(plugin, - "supported_extension_aliases") and - alias in plugin.supported_extension_aliases) - for plugin in self.plugins.values()) - if not supports_extension: - LOG.warn(_("Extension %s not supported by any of loaded plugins"), - alias) - return supports_extension - - def _plugins_implement_interface(self, extension): - if(not hasattr(extension, "get_plugin_interface") or - extension.get_plugin_interface() is None): - return True - for plugin in self.plugins.values(): - if isinstance(plugin, extension.get_plugin_interface()): - return True - LOG.warn(_("Loaded plugins do not implement extension %s interface"), - extension.get_alias()) - return False - - @classmethod - def get_instance(cls): - if cls._instance is None: - cls._instance = cls(get_extensions_path(), - manager.NeutronManager.get_service_plugins()) - return cls._instance - - def check_if_plugin_extensions_loaded(self): - """Check if an extension supported by a plugin has been loaded.""" - plugin_extensions = set(itertools.chain.from_iterable([ - getattr(plugin, "supported_extension_aliases", []) - for plugin in self.plugins.values()])) - missing_aliases = plugin_extensions - set(self.extensions) - if missing_aliases: - raise exceptions.ExtensionsNotFound( - extensions=list(missing_aliases)) - - class RequestExtension(object): - """Extend requests and responses of core Neutron OpenStack API controllers. + """Extend requests and responses of core Tacker OpenStack API controllers. Provide a way to add data to responses and handle custom request data - that is sent to core Neutron OpenStack API controllers. + that is sent to core Tacker OpenStack API controllers. """ def __init__(self, method, url_route, handler): @@ -646,7 +595,7 @@ class RequestExtension(object): class ActionExtension(object): - """Add custom actions to core Neutron OpenStack API controllers.""" + """Add custom actions to core Tacker OpenStack API controllers.""" def __init__(self, collection, action_name, handler): self.collection = collection @@ -655,7 +604,7 @@ class ActionExtension(object): class ResourceExtension(object): - """Add top level resources to the OpenStack API in Neutron.""" + """Add top level resources to the OpenStack API in Tacker.""" def __init__(self, collection, controller, parent=None, path_prefix="", collection_actions={}, member_actions={}, attr_map={}): @@ -669,9 +618,9 @@ class ResourceExtension(object): # Returns the extension paths from a config entry and the __path__ -# of neutron.extensions +# of tacker.extensions def get_extensions_path(): - paths = ':'.join(neutron.extensions.__path__) + paths = ':'.join(tacker.extensions.__path__) if cfg.CONF.api_extensions_path: paths = ':'.join([cfg.CONF.api_extensions_path, paths]) diff --git a/neutron/api/v2/__init__.py b/tacker/api/v1/__init__.py similarity index 100% rename from neutron/api/v2/__init__.py rename to tacker/api/v1/__init__.py diff --git a/neutron/api/v2/attributes.py b/tacker/api/v1/attributes.py similarity index 72% rename from neutron/api/v2/attributes.py rename to tacker/api/v1/attributes.py index 5c4479f23..480775de3 100644 --- a/neutron/api/v2/attributes.py +++ b/tacker/api/v1/attributes.py @@ -18,10 +18,10 @@ import netaddr import re -from neutron.common import constants -from neutron.common import exceptions as n_exc -from neutron.openstack.common import log as logging -from neutron.openstack.common import uuidutils +from tacker.common import constants +from tacker.common import exceptions as n_exc +from tacker.openstack.common import log as logging +from tacker.openstack.common import uuidutils LOG = logging.getLogger(__name__) @@ -580,12 +580,7 @@ validators = {'type:dict': _validate_dict, 'type:boolean': _validate_boolean} # Define constants for base resource name -NETWORK = 'network' -NETWORKS = '%ss' % NETWORK -PORT = 'port' -PORTS = '%ss' % PORT -SUBNET = 'subnet' -SUBNETS = '%ss' % SUBNET + # Note: a default of ATTR_NOT_SPECIFIED indicates that an # attribute is not required, but will be generated by the plugin # if it is not specified. Particularly, a value of ATTR_NOT_SPECIFIED @@ -609,156 +604,11 @@ SUBNETS = '%ss' % SUBNET # enforce_policy: the attribute is actively part of the policy enforcing # mechanism, ie: there might be rules which refer to this attribute. -RESOURCE_ATTRIBUTE_MAP = { - NETWORKS: { - 'id': {'allow_post': False, 'allow_put': False, - 'validate': {'type:uuid': None}, - 'is_visible': True, - 'primary_key': True}, - 'name': {'allow_post': True, 'allow_put': True, - 'validate': {'type:string': None}, - 'default': '', 'is_visible': True}, - 'subnets': {'allow_post': False, 'allow_put': False, - 'default': [], - 'is_visible': True}, - 'admin_state_up': {'allow_post': True, 'allow_put': True, - 'default': True, - 'convert_to': convert_to_boolean, - 'is_visible': True}, - 'status': {'allow_post': False, 'allow_put': False, - 'is_visible': True}, - 'tenant_id': {'allow_post': True, 'allow_put': False, - 'validate': {'type:string': None}, - 'required_by_policy': True, - 'is_visible': True}, - SHARED: {'allow_post': True, - 'allow_put': True, - 'default': False, - 'convert_to': convert_to_boolean, - 'is_visible': True, - 'required_by_policy': True, - 'enforce_policy': True}, - }, - PORTS: { - 'id': {'allow_post': False, 'allow_put': False, - 'validate': {'type:uuid': None}, - 'is_visible': True, - 'primary_key': True}, - 'name': {'allow_post': True, 'allow_put': True, 'default': '', - 'validate': {'type:string': None}, - 'is_visible': True}, - 'network_id': {'allow_post': True, 'allow_put': False, - 'required_by_policy': True, - 'validate': {'type:uuid': None}, - 'is_visible': True}, - 'admin_state_up': {'allow_post': True, 'allow_put': True, - 'default': True, - 'convert_to': convert_to_boolean, - 'is_visible': True}, - 'mac_address': {'allow_post': True, 'allow_put': False, - 'default': ATTR_NOT_SPECIFIED, - 'validate': {'type:mac_address': None}, - 'enforce_policy': True, - 'is_visible': True}, - 'fixed_ips': {'allow_post': True, 'allow_put': True, - 'default': ATTR_NOT_SPECIFIED, - 'convert_list_to': convert_kvp_list_to_dict, - 'validate': {'type:fixed_ips': None}, - 'enforce_policy': True, - 'is_visible': True}, - 'device_id': {'allow_post': True, 'allow_put': True, - 'validate': {'type:string': None}, - 'default': '', - 'is_visible': True}, - 'device_owner': {'allow_post': True, 'allow_put': True, - 'validate': {'type:string': None}, - 'default': '', - 'is_visible': True}, - 'tenant_id': {'allow_post': True, 'allow_put': False, - 'validate': {'type:string': None}, - 'required_by_policy': True, - 'is_visible': True}, - 'status': {'allow_post': False, 'allow_put': False, - 'is_visible': True}, - }, - SUBNETS: { - 'id': {'allow_post': False, 'allow_put': False, - 'validate': {'type:uuid': None}, - 'is_visible': True, - 'primary_key': True}, - 'name': {'allow_post': True, 'allow_put': True, 'default': '', - 'validate': {'type:string': None}, - 'is_visible': True}, - 'ip_version': {'allow_post': True, 'allow_put': False, - 'convert_to': convert_to_int, - 'validate': {'type:values': [4, 6]}, - 'is_visible': True}, - 'network_id': {'allow_post': True, 'allow_put': False, - 'required_by_policy': True, - 'validate': {'type:uuid': None}, - 'is_visible': True}, - 'cidr': {'allow_post': True, 'allow_put': False, - 'validate': {'type:subnet': None}, - 'is_visible': True}, - 'gateway_ip': {'allow_post': True, 'allow_put': True, - 'default': ATTR_NOT_SPECIFIED, - 'validate': {'type:ip_address_or_none': None}, - 'is_visible': True}, - 'allocation_pools': {'allow_post': True, 'allow_put': True, - 'default': ATTR_NOT_SPECIFIED, - 'validate': {'type:ip_pools': None}, - 'is_visible': True}, - 'dns_nameservers': {'allow_post': True, 'allow_put': True, - 'convert_to': convert_none_to_empty_list, - 'default': ATTR_NOT_SPECIFIED, - 'validate': {'type:nameservers': None}, - 'is_visible': True}, - 'host_routes': {'allow_post': True, 'allow_put': True, - 'convert_to': convert_none_to_empty_list, - 'default': ATTR_NOT_SPECIFIED, - 'validate': {'type:hostroutes': None}, - 'is_visible': True}, - 'tenant_id': {'allow_post': True, 'allow_put': False, - 'validate': {'type:string': None}, - 'required_by_policy': True, - 'is_visible': True}, - 'enable_dhcp': {'allow_post': True, 'allow_put': True, - 'default': True, - 'convert_to': convert_to_boolean, - 'is_visible': True}, - 'ipv6_ra_mode': {'allow_post': True, 'allow_put': True, - 'default': ATTR_NOT_SPECIFIED, - 'validate': {'type:values': constants.IPV6_MODES}, - 'is_visible': True}, - 'ipv6_address_mode': {'allow_post': True, 'allow_put': True, - 'default': ATTR_NOT_SPECIFIED, - 'validate': {'type:values': - constants.IPV6_MODES}, - 'is_visible': True}, - SHARED: {'allow_post': False, - 'allow_put': False, - 'default': False, - 'convert_to': convert_to_boolean, - 'is_visible': False, - 'required_by_policy': True, - 'enforce_policy': True}, - } -} - # Identify the attribute used by a resource to reference another resource -RESOURCE_FOREIGN_KEYS = { - NETWORKS: 'network_id' -} +RESOURCE_ATTRIBUTE_MAP = {} -PLURALS = {NETWORKS: NETWORK, - PORTS: PORT, - SUBNETS: SUBNET, - 'dns_nameservers': 'dns_nameserver', - 'host_routes': 'host_route', - 'allocation_pools': 'allocation_pool', - 'fixed_ips': 'fixed_ip', - 'extensions': 'extension'} +PLURALS = {'extensions': 'extension'} EXT_NSES = {} # Namespaces to be added for backward compatibility diff --git a/neutron/api/v2/base.py b/tacker/api/v1/base.py similarity index 86% rename from neutron/api/v2/base.py rename to tacker/api/v1/base.py index 89ef47ed6..4b01c59d1 100644 --- a/neutron/api/v2/base.py +++ b/tacker/api/v1/base.py @@ -15,22 +15,18 @@ # License for the specific language governing permissions and limitations # under the License. -import copy import netaddr import webob.exc from oslo.config import cfg -from neutron.api import api_common -from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api -from neutron.api.v2 import attributes -from neutron.api.v2 import resource as wsgi_resource -from neutron.common import constants as const -from neutron.common import exceptions -from neutron.common import rpc as n_rpc -from neutron.openstack.common import log as logging -from neutron import policy -from neutron import quota +from tacker.api import api_common +from tacker.api.v1 import attributes +from tacker.api.v1 import resource as wsgi_resource +from tacker.common import exceptions +from tacker.common import rpc as n_rpc +from tacker.openstack.common import log as logging +from tacker import policy LOG = logging.getLogger(__name__) @@ -70,15 +66,9 @@ class Controller(object): self._policy_attrs = [name for (name, info) in self._attr_info.items() if info.get('required_by_policy')] self._notifier = n_rpc.get_notifier('network') - # use plugin's dhcp notifier, if this is already instantiated - agent_notifiers = getattr(plugin, 'agent_notifiers', {}) - self._dhcp_agent_notifier = ( - agent_notifiers.get(const.AGENT_TYPE_DHCP) or - dhcp_rpc_agent_api.DhcpAgentNotifyAPI() - ) - if cfg.CONF.notify_nova_on_port_data_changes: - from neutron.notifiers import nova - self._nova_notifier = nova.Notifier() + # if cfg.CONF.notify_nova_on_port_data_changes: + # from tacker.notifiers import nova + # self._nova_notifier = nova.Notifier() self._member_actions = member_actions self._primary_key = self._get_primary_key() if self._allow_pagination and self._native_pagination: @@ -153,7 +143,7 @@ class Controller(object): def _view(self, context, data, fields_to_strip=None): """Build a view of an API resource. - :param context: the neutron context + :param context: the tacker context :param data: the object for which a view is being created :param fields_to_strip: attributes to remove from the view @@ -288,19 +278,6 @@ class Controller(object): policy.enforce(request.context, action, obj) return obj - def _send_dhcp_notification(self, context, data, methodname): - if cfg.CONF.dhcp_agent_notification: - if self._collection in data: - for body in data[self._collection]: - item = {self._resource: body} - self._dhcp_agent_notifier.notify(context, item, methodname) - else: - self._dhcp_agent_notifier.notify(context, data, methodname) - - def _send_nova_notification(self, action, orig, returned): - if hasattr(self, '_nova_notifier'): - self._nova_notifier.send_network_change(action, orig, returned) - def index(self, request, **kwargs): """Returns a list of the requested entity.""" parent_id = kwargs.get(self._parent_id_name) @@ -383,46 +360,20 @@ class Controller(object): if self._collection in body: # Have to account for bulk create items = body[self._collection] - deltas = {} - bulk = True else: items = [body] - bulk = False # Ensure policy engine is initialized policy.init() for item in items: - self._validate_network_tenant_ownership(request, - item[self._resource]) policy.enforce(request.context, action, item[self._resource]) - try: - tenant_id = item[self._resource]['tenant_id'] - count = quota.QUOTAS.count(request.context, self._resource, - self._plugin, self._collection, - tenant_id) - if bulk: - delta = deltas.get(tenant_id, 0) + 1 - deltas[tenant_id] = delta - else: - delta = 1 - kwargs = {self._resource: count + delta} - except exceptions.QuotaResourceUnknown as e: - # We don't want to quota this resource - LOG.debug(e) - else: - quota.QUOTAS.limit_check(request.context, - item[self._resource]['tenant_id'], - **kwargs) def notify(create_result): notifier_method = self._resource + '.create.end' self._notifier.info(request.context, notifier_method, create_result) - self._send_dhcp_notification(request.context, - create_result, - notifier_method) return create_result kwargs = {self._parent_id_name: parent_id} if parent_id else {} @@ -447,8 +398,6 @@ class Controller(object): else: kwargs.update({self._resource: body}) obj = obj_creator(request.context, **kwargs) - self._send_nova_notification(action, {}, - {self._resource: obj}) return notify({self._resource: self._view(request.context, obj)}) @@ -479,11 +428,6 @@ class Controller(object): self._notifier.info(request.context, notifier_method, {self._resource + '_id': id}) - result = {self._resource: self._view(request.context, obj)} - self._send_nova_notification(action, {}, result) - self._send_dhcp_notification(request.context, - result, - notifier_method) def update(self, request, id, body=None, **kwargs): """Updates the specified entity's attributes.""" @@ -512,7 +456,6 @@ class Controller(object): policy.init() orig_obj = self._item(request, id, field_list=field_list, parent_id=parent_id) - orig_object_copy = copy.copy(orig_obj) orig_obj.update(body[self._resource]) try: policy.enforce(request.context, @@ -532,10 +475,6 @@ class Controller(object): result = {self._resource: self._view(request.context, obj)} notifier_method = self._resource + '.update.end' self._notifier.info(request.context, notifier_method, result) - self._send_dhcp_notification(request.context, - result, - notifier_method) - self._send_nova_notification(action, orig_object_copy, result) return result @staticmethod @@ -644,29 +583,6 @@ class Controller(object): msg = _("Unrecognized attribute(s) '%s'") % ', '.join(extra_keys) raise webob.exc.HTTPBadRequest(msg) - def _validate_network_tenant_ownership(self, request, resource_item): - # TODO(salvatore-orlando): consider whether this check can be folded - # in the policy engine - if (request.context.is_admin or - self._resource not in ('port', 'subnet')): - return - network = self._plugin.get_network( - request.context, - resource_item['network_id']) - # do not perform the check on shared networks - if network.get('shared'): - return - - network_owner = network['tenant_id'] - - if network_owner != resource_item['tenant_id']: - msg = _("Tenant %(tenant_id)s not allowed to " - "create %(resource)s on this network") - raise webob.exc.HTTPForbidden(msg % { - "tenant_id": resource_item['tenant_id'], - "resource": self._resource, - }) - def create_resource(collection, resource, plugin, params, allow_bulk=False, member_actions=None, parent=None, allow_pagination=False, diff --git a/neutron/api/v2/resource.py b/tacker/api/v1/resource.py similarity index 91% rename from neutron/api/v2/resource.py rename to tacker/api/v1/resource.py index c76b9e6b2..45e142c56 100644 --- a/neutron/api/v2/resource.py +++ b/tacker/api/v1/resource.py @@ -24,11 +24,11 @@ import six import webob.dec import webob.exc -from neutron.api.v2 import attributes -from neutron.common import exceptions -from neutron.openstack.common import gettextutils -from neutron.openstack.common import log as logging -from neutron import wsgi +from tacker.api.v1 import attributes +from tacker.common import exceptions +from tacker.openstack.common import gettextutils +from tacker.openstack.common import log as logging +from tacker import wsgi LOG = logging.getLogger(__name__) @@ -85,7 +85,7 @@ def Resource(controller, faults=None, deserializers=None, serializers=None): method = getattr(controller, action) result = method(request=request, **args) - except (exceptions.NeutronException, + except (exceptions.TackerException, netaddr.AddrFormatError) as e: for fault in faults: if isinstance(e, fault): @@ -99,17 +99,17 @@ def Resource(controller, faults=None, deserializers=None, serializers=None): else: LOG.exception(_('%s failed'), action) e = translate(e, language) - # following structure is expected by python-neutronclient + # following structure is expected by python-tackerclient err_data = {'type': e.__class__.__name__, 'message': e, 'detail': ''} - body = serializer.serialize({'NeutronError': err_data}) + body = serializer.serialize({'TackerError': err_data}) kwargs = {'body': body, 'content_type': content_type} raise mapped_exc(**kwargs) except webob.exc.HTTPException as e: type_, value, tb = sys.exc_info() LOG.exception(_('%s failed'), action) translate(e, language) - value.body = serializer.serialize({'NeutronError': e}) + value.body = serializer.serialize({'TackerError': e}) value.content_type = content_type six.reraise(type_, value, tb) except NotImplementedError as e: @@ -131,7 +131,7 @@ def Resource(controller, faults=None, deserializers=None, serializers=None): msg = _('Request Failed: internal server error while ' 'processing your request.') msg = translate(msg, language) - body = serializer.serialize({'NeutronError': msg}) + body = serializer.serialize({'TackerError': msg}) kwargs = {'body': body, 'content_type': content_type} raise webob.exc.HTTPInternalServerError(**kwargs) @@ -161,7 +161,7 @@ def translate(translatable, locale): was not translated """ localize = gettextutils.translate - if isinstance(translatable, exceptions.NeutronException): + if isinstance(translatable, exceptions.TackerException): translatable.msg = localize(translatable.msg, locale) elif isinstance(translatable, webob.exc.HTTPError): translatable.detail = localize(translatable.detail, locale) diff --git a/neutron/api/v2/resource_helper.py b/tacker/api/v1/resource_helper.py similarity index 84% rename from neutron/api/v2/resource_helper.py rename to tacker/api/v1/resource_helper.py index ab90bd683..da2e1c4d2 100644 --- a/neutron/api/v2/resource_helper.py +++ b/tacker/api/v1/resource_helper.py @@ -16,11 +16,10 @@ from oslo.config import cfg -from neutron.api import extensions -from neutron.api.v2 import base -from neutron import manager -from neutron.plugins.common import constants -from neutron import quota +from tacker.api import extensions +from tacker.api.v1 import base +from tacker import manager +from tacker.plugins.common import constants def build_plural_mappings(special_mappings, resource_map): @@ -38,7 +37,7 @@ def build_plural_mappings(special_mappings, resource_map): def build_resource_info(plural_mappings, resource_map, which_service, - action_map=None, register_quota=False, + action_map=None, translate_name=False, allow_bulk=False): """Build resources for advanced services. @@ -55,8 +54,6 @@ def build_resource_info(plural_mappings, resource_map, which_service, It can be set to None or "CORE"to create WSGI resources for the the core plugin :param action_map: custom resource actions - :param register_quota: it can be set to True to register quotas for the - resource(s) being created :param translate_name: replaces underscores with dashes :param allow_bulk: True if bulk create are allowed """ @@ -65,17 +62,12 @@ def build_resource_info(plural_mappings, resource_map, which_service, which_service = constants.CORE if action_map is None: action_map = {} - if which_service != constants.CORE: - plugin = manager.NeutronManager.get_service_plugins()[which_service] - else: - plugin = manager.NeutronManager.get_plugin() + plugin = manager.TackerManager.get_service_plugins()[which_service] for collection_name in resource_map: resource_name = plural_mappings[collection_name] params = resource_map.get(collection_name, {}) if translate_name: collection_name = collection_name.replace('_', '-') - if register_quota: - quota.QUOTAS.register_resource_by_name(resource_name) member_actions = action_map.get(resource_name, {}) controller = base.create_resource( collection_name, resource_name, plugin, params, diff --git a/tacker/api/v1/router.py b/tacker/api/v1/router.py new file mode 100644 index 000000000..3f53618e2 --- /dev/null +++ b/tacker/api/v1/router.py @@ -0,0 +1,65 @@ +# Copyright (c) 2012 OpenStack Foundation. +# +# 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 routes as routes_mapper +import six.moves.urllib.parse as urlparse +import webob +import webob.dec +import webob.exc + +from tacker.api import extensions +from tacker.api.v1 import attributes +from tacker.openstack.common import log as logging +from tacker import wsgi + +LOG = logging.getLogger(__name__) + + +class Index(wsgi.Application): + def __init__(self, resources): + self.resources = resources + + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + metadata = {'application/xml': {'attributes': { + 'resource': ['name', 'collection'], + 'link': ['href', 'rel']}}} + + layout = [] + for name, collection in self.resources.iteritems(): + href = urlparse.urljoin(req.path_url, collection) + resource = {'name': name, + 'collection': collection, + 'links': [{'rel': 'self', + 'href': href}]} + layout.append(resource) + response = dict(resources=layout) + content_type = req.best_match_content_type() + body = wsgi.Serializer(metadata=metadata).serialize(response, + content_type) + return webob.Response(body=body, content_type=content_type) + + +class APIRouter(wsgi.Router): + + @classmethod + def factory(cls, global_config, **local_config): + return cls(**local_config) + + def __init__(self, **local_config): + mapper = routes_mapper.Mapper() + ext_mgr = extensions.ExtensionManager.get_instance() + ext_mgr.extend_resources("1.0", attributes.RESOURCE_ATTRIBUTE_MAP) + super(APIRouter, self).__init__(mapper) diff --git a/neutron/api/versions.py b/tacker/api/versions.py similarity index 87% rename from neutron/api/versions.py rename to tacker/api/versions.py index cdfa1e081..8b7926018 100644 --- a/neutron/api/versions.py +++ b/tacker/api/versions.py @@ -15,10 +15,10 @@ import webob.dec -from neutron.api.views import versions as versions_view -from neutron.openstack.common import gettextutils -from neutron.openstack.common import log as logging -from neutron import wsgi +from tacker.api.views import versions as versions_view +from tacker.openstack.common import gettextutils +from tacker.openstack.common import log as logging +from tacker import wsgi LOG = logging.getLogger(__name__) @@ -32,10 +32,10 @@ class Versions(object): @webob.dec.wsgify(RequestClass=wsgi.Request) def __call__(self, req): - """Respond to a request for all Neutron API versions.""" + """Respond to a request for all Tacker API versions.""" version_objs = [ { - "id": "v2.0", + "id": "v1.0", "status": "CURRENT", }, ] diff --git a/neutron/api/views/__init__.py b/tacker/api/views/__init__.py similarity index 100% rename from neutron/api/views/__init__.py rename to tacker/api/views/__init__.py diff --git a/neutron/api/views/versions.py b/tacker/api/views/versions.py similarity index 100% rename from neutron/api/views/versions.py rename to tacker/api/views/versions.py