Add extensions for API v2 controllers
Controllers (and API endpoints) should be able to be selected using configuration flags, as we do for plugins TODO: - Extra Hooks to be configured using stevedore Implements blueprint: pecan-wsme Implements blueprint: api-extensions Change-Id: I12f1bc1accbc870aacb0d1e08c9e0d08223c4b18
This commit is contained in:
parent
954f5034ce
commit
23e327f79c
@ -16,24 +16,58 @@
|
||||
"""Version 2 of the API.
|
||||
"""
|
||||
|
||||
from oslo.config import cfg
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from stevedore import enabled
|
||||
|
||||
from climate.api.v2.controllers import host
|
||||
from climate.api.v2.controllers import lease
|
||||
from climate.openstack.common.gettextutils import _ # noqa
|
||||
from climate import exceptions
|
||||
from climate.openstack.common.gettextutils import _
|
||||
from climate.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
api_opts = [
|
||||
cfg.ListOpt('api_v2_controllers',
|
||||
default=['oshosts', 'leases'],
|
||||
help='API extensions to use'),
|
||||
]
|
||||
|
||||
class V2Controller(pecan.rest.RestController):
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(api_opts, 'api')
|
||||
|
||||
|
||||
class V2Controller(rest.RestController):
|
||||
"""Version 2 API controller root."""
|
||||
|
||||
_routes = {'os-hosts': 'oshosts',
|
||||
'oshosts': 'None'}
|
||||
_routes = {}
|
||||
|
||||
leases = lease.LeasesController()
|
||||
oshosts = host.HostsController()
|
||||
def _log_missing_plugins(self, names):
|
||||
for name in names:
|
||||
if name not in self.extension_manager.names():
|
||||
LOG.error(_("API Plugin %s was not loaded") % name)
|
||||
|
||||
def __init__(self):
|
||||
extensions = []
|
||||
|
||||
self.extension_manager = enabled.EnabledExtensionManager(
|
||||
check_func=lambda ext: ext.name in CONF.api.api_v2_controllers,
|
||||
namespace='climate.api.v2.controllers.extensions',
|
||||
invoke_on_load=True
|
||||
)
|
||||
self._log_missing_plugins(CONF.api.api_v2_controllers)
|
||||
|
||||
for ext in self.extension_manager.extensions:
|
||||
try:
|
||||
setattr(self, ext.obj.name, ext.obj)
|
||||
except TypeError:
|
||||
raise exceptions.ClimateException(
|
||||
_("API name must be specified for "
|
||||
"extension {0}").format(ext.name))
|
||||
self._routes.update(ext.obj.extra_routes)
|
||||
extensions.append(ext.obj.name)
|
||||
|
||||
LOG.debug(_("Loaded extensions: {0}").format(extensions))
|
||||
|
||||
@pecan.expose()
|
||||
def _route(self, args):
|
||||
@ -44,7 +78,12 @@ class V2Controller(pecan.rest.RestController):
|
||||
"""
|
||||
|
||||
try:
|
||||
args[0] = self._routes.get(args[0], args[0])
|
||||
route = self._routes.get(args[0], args[0])
|
||||
if route is None:
|
||||
# NOTE(sbauza): Route must map to a non-existing controller
|
||||
args[0] = 'http404-nonexistingcontroller'
|
||||
else:
|
||||
args[0] = route
|
||||
except IndexError:
|
||||
LOG.error(_("No args found on V2 controller"))
|
||||
return super(V2Controller, self)._route(args)
|
||||
|
63
climate/api/v2/controllers/extensions/__init__.py
Normal file
63
climate/api/v2/controllers/extensions/__init__.py
Normal file
@ -0,0 +1,63 @@
|
||||
# Copyright (c) 2014 Bull.
|
||||
#
|
||||
# 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 oslo.config import cfg
|
||||
from pecan import rest
|
||||
|
||||
from climate.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class BaseController(rest.RestController):
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
"""Mandatory API method name."""
|
||||
name = None
|
||||
|
||||
"""Optional extra routes to add.
|
||||
Dict of key/value pairs, where :
|
||||
key : API method name redirect (public URL)
|
||||
value : redirect target (can be None for routing to HTTP 404)
|
||||
"""
|
||||
extra_routes = {}
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_one(self, resource_id):
|
||||
"""Get a single resource."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_all(self):
|
||||
"""Get all resources."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def post(self, resource):
|
||||
"""Create a resource."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def put(self, resource):
|
||||
"""Update a resource."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete(self, resource_id):
|
||||
"""Delete a single resource."""
|
||||
pass
|
@ -14,11 +14,11 @@
|
||||
# limitations under the License.
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from climate.api.v2.controllers import base
|
||||
from climate.api.v2.controllers import extensions
|
||||
from climate.api.v2.controllers import types
|
||||
from climate import exceptions
|
||||
from climate.openstack.common.gettextutils import _ # noqa
|
||||
@ -95,10 +95,14 @@ class Host(base._Base):
|
||||
)
|
||||
|
||||
|
||||
class HostsController(rest.RestController):
|
||||
class HostsController(extensions.BaseController):
|
||||
"""Manages operations on hosts.
|
||||
"""
|
||||
|
||||
name = 'oshosts'
|
||||
extra_routes = {'os-hosts': 'oshosts',
|
||||
'oshosts': None}
|
||||
|
||||
@policy.authorize('oshosts', 'get')
|
||||
@wsme_pecan.wsexpose(Host, types.IntegerType())
|
||||
def get_one(self, id):
|
@ -14,11 +14,11 @@
|
||||
# limitations under the License.
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from climate.api.v2.controllers import base
|
||||
from climate.api.v2.controllers import extensions
|
||||
from climate.api.v2.controllers import types
|
||||
from climate import exceptions
|
||||
from climate.manager import service
|
||||
@ -87,10 +87,12 @@ class Lease(base._Base):
|
||||
)
|
||||
|
||||
|
||||
class LeasesController(rest.RestController):
|
||||
class LeasesController(extensions.BaseController):
|
||||
"""Manages operations on leases.
|
||||
"""
|
||||
|
||||
name = 'leases'
|
||||
|
||||
@policy.authorize('leases', 'get')
|
||||
@wsme_pecan.wsexpose(Lease, types.UuidType())
|
||||
def get_one(self, id):
|
@ -104,6 +104,8 @@ function configure_climate() {
|
||||
|
||||
iniset $CLIMATE_CONF_FILE manager plugins basic.vm.plugin,physical.host.plugin
|
||||
|
||||
iniset $CLIMATE_CONF_FILE api api_v2_controllers oshosts,leases
|
||||
|
||||
iniset $CLIMATE_CONF_FILE database connection `database_connection_url climate`
|
||||
|
||||
iniset $CLIMATE_CONF_FILE DEFAULT use_syslog $SYSLOG
|
||||
|
@ -35,10 +35,10 @@ Lease is the main abstraction for the user in the Climate case. Lease means
|
||||
some kind of contract where start time, end time and resources to be reserved
|
||||
are mentioned.
|
||||
|
||||
.. rest-controller:: climate.api.v2.controllers.lease:LeasesController
|
||||
.. rest-controller:: climate.api.v2.controllers.extensions.lease:LeasesController
|
||||
:webprefix: /v2/leases
|
||||
|
||||
.. autotype:: climate.api.v2.controllers.lease.Lease
|
||||
.. autotype:: climate.api.v2.controllers.extensions.lease.Lease
|
||||
:members:
|
||||
|
||||
|
||||
@ -50,8 +50,8 @@ are mentioned.
|
||||
Host is the abstraction for a computehost in the Climate case. Host means
|
||||
a specific type of resource to be allocated.
|
||||
|
||||
.. rest-controller:: climate.api.v2.controllers.host:HostsController
|
||||
.. rest-controller:: climate.api.v2.controllers.extensions.host:HostsController
|
||||
:webprefix: /v2/os-hosts
|
||||
|
||||
.. autotype:: climate.api.v2.controllers.host.Host
|
||||
.. autotype:: climate.api.v2.controllers.extensions.host.Host
|
||||
:members:
|
||||
|
@ -448,6 +448,16 @@
|
||||
#image_prefix=reserved_
|
||||
|
||||
|
||||
[api]
|
||||
|
||||
#
|
||||
# Options defined in climate.api.v2.controllers
|
||||
#
|
||||
|
||||
# API extensions to use (list value)
|
||||
#api_v2_controllers=oshosts,leases
|
||||
|
||||
|
||||
[database]
|
||||
|
||||
#
|
||||
|
@ -37,6 +37,10 @@ climate.resource.plugins =
|
||||
physical.host.plugin=climate.plugins.oshosts.host_plugin:PhysicalHostPlugin
|
||||
basic.vm.plugin=climate.plugins.instances.vm_plugin:VMPlugin
|
||||
|
||||
climate.api.v2.controllers.extensions =
|
||||
oshosts=climate.api.v2.controllers.extensions.host:HostsController
|
||||
leases=climate.api.v2.controllers.extensions.lease:LeasesController
|
||||
|
||||
[build_sphinx]
|
||||
all_files = 1
|
||||
build-dir = doc/build
|
||||
|
Loading…
Reference in New Issue
Block a user