From: Nirmal Ranganathan Date: Thu, 3 May 2012 19:54:27 +0000 (-0500) Subject: Removed cinder/api/openstack/compute and moved the relevant pieces under X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=4c202523890d805c8e42802117d85d6f6e2cddae;p=openstack-build%2Fcinder-build.git Removed cinder/api/openstack/compute and moved the relevant pieces under cinder/api/openstack/volume. Fixes bug 994177. Change-Id: I1b953a96a1d69a62ad312d381cead4cd231a3998 --- diff --git a/cinder/api/openstack/compute/__init__.py b/cinder/api/openstack/compute/__init__.py deleted file mode 100644 index 7372b0c97..000000000 --- a/cinder/api/openstack/compute/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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. - -""" -WSGI middleware for OpenStack Compute API. -""" - -from cinder.api.openstack.compute import versions diff --git a/cinder/api/openstack/compute/versions.py b/cinder/api/openstack/compute/versions.py deleted file mode 100644 index d5108c0cf..000000000 --- a/cinder/api/openstack/compute/versions.py +++ /dev/null @@ -1,244 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# 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. - -import datetime - -from lxml import etree - -from cinder.api.openstack.compute.views import versions as views_versions -from cinder.api.openstack import wsgi -from cinder.api.openstack import xmlutil - - -LINKS = { - 'v2.0': { - 'pdf': 'http://docs.openstack.org/' - 'api/openstack-compute/1.1/os-compute-devguide-1.1.pdf', - 'wadl': 'http://docs.openstack.org/' - 'api/openstack-compute/1.1/wadl/os-compute-1.1.wadl', - }, -} - - -VERSIONS = { - "v2.0": { - "id": "v2.0", - "status": "CURRENT", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "describedby", - "type": "application/pdf", - "href": LINKS['v2.0']['pdf'], - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": LINKS['v2.0']['wadl'], - }, - ], - "media-types": [ - { - "base": "application/xml", - "type": "application/vnd.openstack.compute+xml;version=2", - }, - { - "base": "application/json", - "type": "application/vnd.openstack.compute+json;version=2", - } - ], - } -} - - -class MediaTypesTemplateElement(xmlutil.TemplateElement): - def will_render(self, datum): - return 'media-types' in datum - - -def make_version(elem): - elem.set('id') - elem.set('status') - elem.set('updated') - - mts = MediaTypesTemplateElement('media-types') - elem.append(mts) - - mt = xmlutil.SubTemplateElement(mts, 'media-type', selector='media-types') - mt.set('base') - mt.set('type') - - xmlutil.make_links(elem, 'links') - - -version_nsmap = {None: xmlutil.XMLNS_COMMON_V10, 'atom': xmlutil.XMLNS_ATOM} - - -class VersionTemplate(xmlutil.TemplateBuilder): - def construct(self): - root = xmlutil.TemplateElement('version', selector='version') - make_version(root) - return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) - - -class VersionsTemplate(xmlutil.TemplateBuilder): - def construct(self): - root = xmlutil.TemplateElement('versions') - elem = xmlutil.SubTemplateElement(root, 'version', selector='versions') - make_version(elem) - return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) - - -class ChoicesTemplate(xmlutil.TemplateBuilder): - def construct(self): - root = xmlutil.TemplateElement('choices') - elem = xmlutil.SubTemplateElement(root, 'version', selector='choices') - make_version(elem) - return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) - - -class AtomSerializer(wsgi.XMLDictSerializer): - - NSMAP = {None: xmlutil.XMLNS_ATOM} - - def __init__(self, metadata=None, xmlns=None): - self.metadata = metadata or {} - if not xmlns: - self.xmlns = wsgi.XMLNS_ATOM - else: - self.xmlns = xmlns - - def _get_most_recent_update(self, versions): - recent = None - for version in versions: - updated = datetime.datetime.strptime(version['updated'], - '%Y-%m-%dT%H:%M:%SZ') - if not recent: - recent = updated - elif updated > recent: - recent = updated - - return recent.strftime('%Y-%m-%dT%H:%M:%SZ') - - def _get_base_url(self, link_href): - # Make sure no trailing / - link_href = link_href.rstrip('/') - return link_href.rsplit('/', 1)[0] + '/' - - def _create_feed(self, versions, feed_title, feed_id): - feed = etree.Element('feed', nsmap=self.NSMAP) - title = etree.SubElement(feed, 'title') - title.set('type', 'text') - title.text = feed_title - - # Set this updated to the most recently updated version - recent = self._get_most_recent_update(versions) - etree.SubElement(feed, 'updated').text = recent - - etree.SubElement(feed, 'id').text = feed_id - - link = etree.SubElement(feed, 'link') - link.set('rel', 'self') - link.set('href', feed_id) - - author = etree.SubElement(feed, 'author') - etree.SubElement(author, 'name').text = 'Rackspace' - etree.SubElement(author, 'uri').text = 'http://www.rackspace.com/' - - for version in versions: - feed.append(self._create_version_entry(version)) - - return feed - - def _create_version_entry(self, version): - entry = etree.Element('entry') - etree.SubElement(entry, 'id').text = version['links'][0]['href'] - title = etree.SubElement(entry, 'title') - title.set('type', 'text') - title.text = 'Version %s' % version['id'] - etree.SubElement(entry, 'updated').text = version['updated'] - - for link in version['links']: - link_elem = etree.SubElement(entry, 'link') - link_elem.set('rel', link['rel']) - link_elem.set('href', link['href']) - if 'type' in link: - link_elem.set('type', link['type']) - - content = etree.SubElement(entry, 'content') - content.set('type', 'text') - content.text = 'Version %s %s (%s)' % (version['id'], - version['status'], - version['updated']) - return entry - - -class VersionsAtomSerializer(AtomSerializer): - def default(self, data): - versions = data['versions'] - feed_id = self._get_base_url(versions[0]['links'][0]['href']) - feed = self._create_feed(versions, 'Available API Versions', feed_id) - return self._to_xml(feed) - - -class VersionAtomSerializer(AtomSerializer): - def default(self, data): - version = data['version'] - feed_id = version['links'][0]['href'] - feed = self._create_feed([version], 'About This Version', feed_id) - return self._to_xml(feed) - - -class Versions(wsgi.Resource): - def __init__(self): - super(Versions, self).__init__(None) - - @wsgi.serializers(xml=VersionsTemplate, - atom=VersionsAtomSerializer) - def index(self, req): - """Return all versions.""" - builder = views_versions.get_view_builder(req) - return builder.build_versions(VERSIONS) - - @wsgi.serializers(xml=ChoicesTemplate) - @wsgi.response(300) - def multi(self, req): - """Return multiple choices.""" - builder = views_versions.get_view_builder(req) - return builder.build_choices(VERSIONS, req) - - def get_action_args(self, request_environment): - """Parse dictionary created by routes library.""" - args = {} - if request_environment['PATH_INFO'] == '/': - args['action'] = 'index' - else: - args['action'] = 'multi' - - return args - - -class VersionV2(object): - @wsgi.serializers(xml=VersionTemplate, - atom=VersionAtomSerializer) - def show(self, req): - builder = views_versions.get_view_builder(req) - return builder.build_version(VERSIONS['v2.0']) - - -def create_resource(): - return wsgi.Resource(VersionV2()) diff --git a/cinder/api/openstack/compute/views/__init__.py b/cinder/api/openstack/compute/views/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/cinder/api/openstack/compute/views/versions.py b/cinder/api/openstack/compute/views/versions.py deleted file mode 100644 index cb2fd9f4a..000000000 --- a/cinder/api/openstack/compute/views/versions.py +++ /dev/null @@ -1,94 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010-2011 OpenStack LLC. -# 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. - -import copy -import os - - -def get_view_builder(req): - base_url = req.application_url - return ViewBuilder(base_url) - - -class ViewBuilder(object): - - def __init__(self, base_url): - """ - :param base_url: url of the root wsgi application - """ - self.base_url = base_url - - def build_choices(self, VERSIONS, req): - version_objs = [] - for version in VERSIONS: - version = VERSIONS[version] - version_objs.append({ - "id": version['id'], - "status": version['status'], - "links": [ - { - "rel": "self", - "href": self.generate_href(req.path), - }, - ], - "media-types": version['media-types'], - }) - - return dict(choices=version_objs) - - def build_versions(self, versions): - version_objs = [] - for version in sorted(versions.keys()): - version = versions[version] - version_objs.append({ - "id": version['id'], - "status": version['status'], - "updated": version['updated'], - "links": self._build_links(version), - }) - - return dict(versions=version_objs) - - def build_version(self, version): - reval = copy.deepcopy(version) - reval['links'].insert(0, { - "rel": "self", - "href": self.base_url.rstrip('/') + '/', - }) - return dict(version=reval) - - def _build_links(self, version_data): - """Generate a container of links that refer to the provided version.""" - href = self.generate_href() - - links = [ - { - "rel": "self", - "href": href, - }, - ] - - return links - - def generate_href(self, path=None): - """Create an url that refers to a specific version_number.""" - version_number = 'v2' - if path: - path = path.strip('/') - return os.path.join(self.base_url, version_number, path) - else: - return os.path.join(self.base_url, version_number) + '/' diff --git a/cinder/api/openstack/compute/schemas/atom-link.rng b/cinder/api/openstack/volume/schemas/atom-link.rng similarity index 100% rename from cinder/api/openstack/compute/schemas/atom-link.rng rename to cinder/api/openstack/volume/schemas/atom-link.rng diff --git a/cinder/api/openstack/compute/schemas/v1.1/extension.rng b/cinder/api/openstack/volume/schemas/v1.1/extension.rng similarity index 100% rename from cinder/api/openstack/compute/schemas/v1.1/extension.rng rename to cinder/api/openstack/volume/schemas/v1.1/extension.rng diff --git a/cinder/api/openstack/compute/schemas/v1.1/extensions.rng b/cinder/api/openstack/volume/schemas/v1.1/extensions.rng similarity index 100% rename from cinder/api/openstack/compute/schemas/v1.1/extensions.rng rename to cinder/api/openstack/volume/schemas/v1.1/extensions.rng diff --git a/cinder/api/openstack/compute/schemas/v1.1/metadata.rng b/cinder/api/openstack/volume/schemas/v1.1/metadata.rng similarity index 100% rename from cinder/api/openstack/compute/schemas/v1.1/metadata.rng rename to cinder/api/openstack/volume/schemas/v1.1/metadata.rng diff --git a/cinder/api/openstack/volume/versions.py b/cinder/api/openstack/volume/versions.py index 7dcfdbe6c..a3cc91f9b 100644 --- a/cinder/api/openstack/volume/versions.py +++ b/cinder/api/openstack/volume/versions.py @@ -15,10 +15,13 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime + +from lxml import etree -from cinder.api.openstack.compute import versions from cinder.api.openstack.volume.views import versions as views_versions from cinder.api.openstack import wsgi +from cinder.api.openstack import xmlutil VERSIONS = { @@ -55,25 +58,177 @@ VERSIONS = { } -class Versions(versions.Versions): - @wsgi.serializers(xml=versions.VersionsTemplate, - atom=versions.VersionsAtomSerializer) +class MediaTypesTemplateElement(xmlutil.TemplateElement): + def will_render(self, datum): + return 'media-types' in datum + + +def make_version(elem): + elem.set('id') + elem.set('status') + elem.set('updated') + + mts = MediaTypesTemplateElement('media-types') + elem.append(mts) + + mt = xmlutil.SubTemplateElement(mts, 'media-type', selector='media-types') + mt.set('base') + mt.set('type') + + xmlutil.make_links(elem, 'links') + + +version_nsmap = {None: xmlutil.XMLNS_COMMON_V10, 'atom': xmlutil.XMLNS_ATOM} + + +class VersionTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('version', selector='version') + make_version(root) + return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) + + +class VersionsTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('versions') + elem = xmlutil.SubTemplateElement(root, 'version', selector='versions') + make_version(elem) + return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) + + +class ChoicesTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('choices') + elem = xmlutil.SubTemplateElement(root, 'version', selector='choices') + make_version(elem) + return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) + + +class AtomSerializer(wsgi.XMLDictSerializer): + + NSMAP = {None: xmlutil.XMLNS_ATOM} + + def __init__(self, metadata=None, xmlns=None): + self.metadata = metadata or {} + if not xmlns: + self.xmlns = wsgi.XMLNS_ATOM + else: + self.xmlns = xmlns + + def _get_most_recent_update(self, versions): + recent = None + for version in versions: + updated = datetime.datetime.strptime(version['updated'], + '%Y-%m-%dT%H:%M:%SZ') + if not recent: + recent = updated + elif updated > recent: + recent = updated + + return recent.strftime('%Y-%m-%dT%H:%M:%SZ') + + def _get_base_url(self, link_href): + # Make sure no trailing / + link_href = link_href.rstrip('/') + return link_href.rsplit('/', 1)[0] + '/' + + def _create_feed(self, versions, feed_title, feed_id): + feed = etree.Element('feed', nsmap=self.NSMAP) + title = etree.SubElement(feed, 'title') + title.set('type', 'text') + title.text = feed_title + + # Set this updated to the most recently updated version + recent = self._get_most_recent_update(versions) + etree.SubElement(feed, 'updated').text = recent + + etree.SubElement(feed, 'id').text = feed_id + + link = etree.SubElement(feed, 'link') + link.set('rel', 'self') + link.set('href', feed_id) + + author = etree.SubElement(feed, 'author') + etree.SubElement(author, 'name').text = 'Rackspace' + etree.SubElement(author, 'uri').text = 'http://www.rackspace.com/' + + for version in versions: + feed.append(self._create_version_entry(version)) + + return feed + + def _create_version_entry(self, version): + entry = etree.Element('entry') + etree.SubElement(entry, 'id').text = version['links'][0]['href'] + title = etree.SubElement(entry, 'title') + title.set('type', 'text') + title.text = 'Version %s' % version['id'] + etree.SubElement(entry, 'updated').text = version['updated'] + + for link in version['links']: + link_elem = etree.SubElement(entry, 'link') + link_elem.set('rel', link['rel']) + link_elem.set('href', link['href']) + if 'type' in link: + link_elem.set('type', link['type']) + + content = etree.SubElement(entry, 'content') + content.set('type', 'text') + content.text = 'Version %s %s (%s)' % (version['id'], + version['status'], + version['updated']) + return entry + + +class VersionsAtomSerializer(AtomSerializer): + def default(self, data): + versions = data['versions'] + feed_id = self._get_base_url(versions[0]['links'][0]['href']) + feed = self._create_feed(versions, 'Available API Versions', feed_id) + return self._to_xml(feed) + + +class VersionAtomSerializer(AtomSerializer): + def default(self, data): + version = data['version'] + feed_id = version['links'][0]['href'] + feed = self._create_feed([version], 'About This Version', feed_id) + return self._to_xml(feed) + + +class Versions(wsgi.Resource): + + def __init__(self): + super(Versions, self).__init__(None) + + @wsgi.serializers(xml=VersionsTemplate, + atom=VersionsAtomSerializer) def index(self, req): """Return all versions.""" builder = views_versions.get_view_builder(req) return builder.build_versions(VERSIONS) - @wsgi.serializers(xml=versions.ChoicesTemplate) + @wsgi.serializers(xml=ChoicesTemplate) @wsgi.response(300) def multi(self, req): """Return multiple choices.""" builder = views_versions.get_view_builder(req) return builder.build_choices(VERSIONS, req) + def get_action_args(self, request_environment): + """Parse dictionary created by routes library.""" + args = {} + if request_environment['PATH_INFO'] == '/': + args['action'] = 'index' + else: + args['action'] = 'multi' + + return args + class VolumeVersionV1(object): - @wsgi.serializers(xml=versions.VersionTemplate, - atom=versions.VersionAtomSerializer) + @wsgi.serializers(xml=VersionTemplate, + atom=VersionAtomSerializer) def show(self, req): builder = views_versions.get_view_builder(req) return builder.build_version(VERSIONS['v1.0']) diff --git a/cinder/api/openstack/volume/views/versions.py b/cinder/api/openstack/volume/views/versions.py index a4bd164b2..f551382b9 100644 --- a/cinder/api/openstack/volume/views/versions.py +++ b/cinder/api/openstack/volume/views/versions.py @@ -15,17 +15,74 @@ # License for the specific language governing permissions and limitations # under the License. +import copy import os -from cinder.api.openstack.compute.views import versions as compute_views - def get_view_builder(req): base_url = req.application_url return ViewBuilder(base_url) -class ViewBuilder(compute_views.ViewBuilder): +class ViewBuilder(object): + def __init__(self, base_url): + """ + :param base_url: url of the root wsgi application + """ + self.base_url = base_url + + def build_choices(self, VERSIONS, req): + version_objs = [] + for version in VERSIONS: + version = VERSIONS[version] + version_objs.append({ + "id": version['id'], + "status": version['status'], + "links": [ + { + "rel": "self", + "href": self.generate_href(req.path), + }, + ], + "media-types": version['media-types'], + }) + + return dict(choices=version_objs) + + def build_versions(self, versions): + version_objs = [] + for version in sorted(versions.keys()): + version = versions[version] + version_objs.append({ + "id": version['id'], + "status": version['status'], + "updated": version['updated'], + "links": self._build_links(version), + }) + + return dict(versions=version_objs) + + def build_version(self, version): + reval = copy.deepcopy(version) + reval['links'].insert(0, { + "rel": "self", + "href": self.base_url.rstrip('/') + '/', + }) + return dict(version=reval) + + def _build_links(self, version_data): + """Generate a container of links that refer to the provided version.""" + href = self.generate_href() + + links = [ + { + "rel": "self", + "href": href, + }, + ] + + return links + def generate_href(self, path=None): """Create an url that refers to a specific version_number.""" version_number = 'v1' diff --git a/cinder/api/openstack/xmlutil.py b/cinder/api/openstack/xmlutil.py index 5dfe0c122..b8461ca5e 100644 --- a/cinder/api/openstack/xmlutil.py +++ b/cinder/api/openstack/xmlutil.py @@ -32,9 +32,9 @@ XMLNS_VOLUME_V1 = 'http://docs.openstack.org/volume/api/v1' def validate_schema(xml, schema_name): if isinstance(xml, str): xml = etree.fromstring(xml) - base_path = 'cinder/api/openstack/compute/schemas/v1.1/' + base_path = 'cinder/api/openstack/volume/schemas/v1.1/' if schema_name in ('atom', 'atom-link'): - base_path = 'cinder/api/openstack/compute/schemas/' + base_path = 'cinder/api/openstack/volume/schemas/' schema_path = os.path.join(utils.cinderdir(), '%s%s.rng' % (base_path, schema_name)) schema_doc = etree.parse(schema_path) diff --git a/cinder/tests/api/openstack/fakes.py b/cinder/tests/api/openstack/fakes.py index 8d97fca89..b3896d52c 100644 --- a/cinder/tests/api/openstack/fakes.py +++ b/cinder/tests/api/openstack/fakes.py @@ -26,7 +26,7 @@ from cinder.api import auth as api_auth from cinder.api import openstack as openstack_api from cinder.api.openstack import auth from cinder.api.openstack import urlmap -from cinder.api.openstack.compute import versions +from cinder.api.openstack.volume import versions from cinder.api.openstack import wsgi as os_wsgi from cinder import context from cinder.db.sqlalchemy import models