# All Rights Reserved. # # 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. """ Version 1 of the Magnum API NOTE: IN PROGRESS AND NOT FULLY IMPLEMENTED. """ from oslo_log import log as logging import pecan from wsme import types as wtypes from magnum.api.controllers import base as controllers_base from magnum.api.controllers import link from magnum.api.controllers.v1 import bay from magnum.api.controllers.v1 import baymodel from magnum.api.controllers.v1 import certificate from magnum.api.controllers.v1 import cluster from magnum.api.controllers.v1 import cluster_template from magnum.api.controllers.v1 import magnum_services from magnum.api.controllers.v1 import stats from magnum.api.controllers import versions as ver from magnum.api import expose from magnum.api import http_error from magnum.i18n import _ LOG = logging.getLogger(__name__) BASE_VERSION = 1 MIN_VER_STR = '%s %s' % (ver.Version.service_string, ver.BASE_VER) MAX_VER_STR = '%s %s' % (ver.Version.service_string, ver.CURRENT_MAX_VER) MIN_VER = ver.Version({ver.Version.string: MIN_VER_STR}, MIN_VER_STR, MAX_VER_STR) MAX_VER = ver.Version({ver.Version.string: MAX_VER_STR}, MIN_VER_STR, MAX_VER_STR) class MediaType(controllers_base.APIBase): """A media type representation.""" base = wtypes.text type = wtypes.text def __init__(self, base, type): self.base = base self.type = type class V1(controllers_base.APIBase): """The representation of the version 1 of the API.""" id = wtypes.text """The ID of the version, also acts as the release number""" media_types = [MediaType] """An array of supcontainersed media types for this version""" links = [link.Link] """Links that point to a specific URL for this version and documentation""" baymodels = [link.Link] """Links to the baymodels resource""" bays = [link.Link] """Links to the bays resource""" clustertemplates = [link.Link] """Links to the clustertemplates resource""" clusters = [link.Link] """Links to the clusters resource""" certificates = [link.Link] """Links to the certificates resource""" mservices = [link.Link] """Links to the magnum-services resource""" stats = [link.Link] """Links to the stats resource""" @staticmethod def convert(): v1 = V1() v1.id = "v1" v1.links = [link.Link.make_link('self', pecan.request.host_url, 'v1', '', bookmark=True), link.Link.make_link('describedby', 'http://docs.openstack.org', 'developer/magnum/dev', 'api-spec-v1.html', bookmark=True, type='text/html')] v1.media_types = [MediaType('application/json', 'application/vnd.openstack.magnum.v1+json')] v1.baymodels = [link.Link.make_link('self', pecan.request.host_url, 'baymodels', ''), link.Link.make_link('bookmark', pecan.request.host_url, 'baymodels', '', bookmark=True)] v1.bays = [link.Link.make_link('self', pecan.request.host_url, 'bays', ''), link.Link.make_link('bookmark', pecan.request.host_url, 'bays', '', bookmark=True)] v1.clustertemplates = [link.Link.make_link('self', pecan.request.host_url, 'clustertemplates', ''), link.Link.make_link('bookmark', pecan.request.host_url, 'clustertemplates', '', bookmark=True)] v1.clusters = [link.Link.make_link('self', pecan.request.host_url, 'clusters', ''), link.Link.make_link('bookmark', pecan.request.host_url, 'clusters', '', bookmark=True)] v1.certificates = [link.Link.make_link('self', pecan.request.host_url, 'certificates', ''), link.Link.make_link('bookmark', pecan.request.host_url, 'certificates', '', bookmark=True)] v1.mservices = [link.Link.make_link('self', pecan.request.host_url, 'mservices', ''), link.Link.make_link('bookmark', pecan.request.host_url, 'mservices', '', bookmark=True)] v1.stats = [link.Link.make_link('self', pecan.request.host_url, 'stats', ''), link.Link.make_link('bookmark', pecan.request.host_url, 'stats', '', bookmark=True)] return v1 class Controller(controllers_base.Controller): """Version 1 API controller root.""" bays = bay.BaysController() baymodels = baymodel.BayModelsController() clusters = cluster.ClustersController() clustertemplates = cluster_template.ClusterTemplatesController() certificates = certificate.CertificateController() mservices = magnum_services.MagnumServiceController() stats = stats.StatsController() @expose.expose(V1) def get(self): # NOTE: The reason why convert() it's being called for every # request is because we need to get the host url from # the request object to make the links. return V1.convert() def _check_version(self, version, headers=None): if headers is None: headers = {} # ensure that major version in the URL matches the header if version.major != BASE_VERSION: raise http_error.HTTPNotAcceptableAPIVersion(_( "Mutually exclusive versions requested. Version %(ver)s " "requested but not supported by this service." "The supported version range is: " "[%(min)s, %(max)s].") % {'ver': version, 'min': MIN_VER_STR, 'max': MAX_VER_STR}, headers=headers, max_version=str(MAX_VER), min_version=str(MIN_VER)) # ensure the minor version is within the supported range if version < MIN_VER or version > MAX_VER: raise http_error.HTTPNotAcceptableAPIVersion(_( "Version %(ver)s was requested but the minor version is not " "supported by this service. The supported version range is: " "[%(min)s, %(max)s].") % {'ver': version, 'min': MIN_VER_STR, 'max': MAX_VER_STR}, headers=headers, max_version=str(MAX_VER), min_version=str(MIN_VER)) @pecan.expose() def _route(self, args): version = ver.Version( pecan.request.headers, MIN_VER_STR, MAX_VER_STR) # Always set the basic version headers pecan.response.headers[ver.Version.min_string] = MIN_VER_STR pecan.response.headers[ver.Version.max_string] = MAX_VER_STR pecan.response.headers[ver.Version.string] = " ".join( [ver.Version.service_string, str(version)]) pecan.response.headers["vary"] = ver.Version.string # assert that requested version is supported self._check_version(version, pecan.response.headers) pecan.request.version = version if pecan.request.body: msg = ("Processing request: url: %(url)s, %(method)s, " "body: %(body)s" % {'url': pecan.request.url, 'method': pecan.request.method, 'body': pecan.request.body}) LOG.debug(msg) return super(Controller, self)._route(args) __all__ = (Controller)