~ubuntu-branches/ubuntu/trusty/cinder/trusty

« back to all changes in this revision

Viewing changes to cinder/api/versions.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-11-23 08:39:28 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20121123083928-xvzet603cjfj9p1t
Tags: 2013.1~g1-0ubuntu1
* New upstream release.
* debian/patches/avoid_setuptools_git_dependency.patch:
  Avoid git installation. (LP: #1075948) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2010 OpenStack LLC.
 
4
# All Rights Reserved.
 
5
#
 
6
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
7
#    not use this file except in compliance with the License. You may obtain
 
8
#    a copy of the License at
 
9
#
 
10
#         http://www.apache.org/licenses/LICENSE-2.0
 
11
#
 
12
#    Unless required by applicable law or agreed to in writing, software
 
13
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
14
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
15
#    License for the specific language governing permissions and limitations
 
16
#    under the License.
 
17
 
 
18
import datetime
 
19
from lxml import etree
 
20
 
 
21
from cinder.api.openstack import wsgi
 
22
from cinder.api.views import versions as views_versions
 
23
from cinder.api import xmlutil
 
24
 
 
25
 
 
26
VERSIONS = {
 
27
    "v2.0": {
 
28
        "id": "v2.0",
 
29
        "status": "CURRENT",
 
30
        "updated": "2012-11-21T11:33:21Z",
 
31
        "links": [
 
32
            {
 
33
                "rel": "describedby",
 
34
                "type": "application/pdf",
 
35
                "href": "http://jorgew.github.com/block-storage-api/"
 
36
                        "content/os-block-storage-1.0.pdf",
 
37
            },
 
38
            {
 
39
                "rel": "describedby",
 
40
                "type": "application/vnd.sun.wadl+xml",
 
41
                #(anthony) FIXME
 
42
                "href": "http://docs.rackspacecloud.com/"
 
43
                        "servers/api/v1.1/application.wadl",
 
44
            },
 
45
        ],
 
46
        "media-types": [
 
47
            {
 
48
                "base": "application/xml",
 
49
                "type": "application/vnd.openstack.volume+xml;version=1",
 
50
            },
 
51
            {
 
52
                "base": "application/json",
 
53
                "type": "application/vnd.openstack.volume+json;version=1",
 
54
            }
 
55
        ],
 
56
    },
 
57
    "v1.0": {
 
58
        "id": "v1.0",
 
59
        "status": "CURRENT",
 
60
        "updated": "2012-01-04T11:33:21Z",
 
61
        "links": [
 
62
            {
 
63
                "rel": "describedby",
 
64
                "type": "application/pdf",
 
65
                "href": "http://jorgew.github.com/block-storage-api/"
 
66
                        "content/os-block-storage-1.0.pdf",
 
67
            },
 
68
            {
 
69
                "rel": "describedby",
 
70
                "type": "application/vnd.sun.wadl+xml",
 
71
                #(anthony) FIXME
 
72
                "href": "http://docs.rackspacecloud.com/"
 
73
                        "servers/api/v1.1/application.wadl",
 
74
            },
 
75
        ],
 
76
        "media-types": [
 
77
            {
 
78
                "base": "application/xml",
 
79
                "type": "application/vnd.openstack.volume+xml;version=1",
 
80
            },
 
81
            {
 
82
                "base": "application/json",
 
83
                "type": "application/vnd.openstack.volume+json;version=1",
 
84
            }
 
85
        ],
 
86
    }
 
87
 
 
88
}
 
89
 
 
90
 
 
91
class MediaTypesTemplateElement(xmlutil.TemplateElement):
 
92
    def will_render(self, datum):
 
93
        return 'media-types' in datum
 
94
 
 
95
 
 
96
def make_version(elem):
 
97
    elem.set('id')
 
98
    elem.set('status')
 
99
    elem.set('updated')
 
100
 
 
101
    mts = MediaTypesTemplateElement('media-types')
 
102
    elem.append(mts)
 
103
 
 
104
    mt = xmlutil.SubTemplateElement(mts, 'media-type', selector='media-types')
 
105
    mt.set('base')
 
106
    mt.set('type')
 
107
 
 
108
    xmlutil.make_links(elem, 'links')
 
109
 
 
110
 
 
111
version_nsmap = {None: xmlutil.XMLNS_COMMON_V10, 'atom': xmlutil.XMLNS_ATOM}
 
112
 
 
113
 
 
114
class VersionTemplate(xmlutil.TemplateBuilder):
 
115
    def construct(self):
 
116
        root = xmlutil.TemplateElement('version', selector='version')
 
117
        make_version(root)
 
118
        return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap)
 
119
 
 
120
 
 
121
class VersionsTemplate(xmlutil.TemplateBuilder):
 
122
    def construct(self):
 
123
        root = xmlutil.TemplateElement('versions')
 
124
        elem = xmlutil.SubTemplateElement(root, 'version', selector='versions')
 
125
        make_version(elem)
 
126
        return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap)
 
127
 
 
128
 
 
129
class ChoicesTemplate(xmlutil.TemplateBuilder):
 
130
    def construct(self):
 
131
        root = xmlutil.TemplateElement('choices')
 
132
        elem = xmlutil.SubTemplateElement(root, 'version', selector='choices')
 
133
        make_version(elem)
 
134
        return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap)
 
135
 
 
136
 
 
137
class AtomSerializer(wsgi.XMLDictSerializer):
 
138
 
 
139
    NSMAP = {None: xmlutil.XMLNS_ATOM}
 
140
 
 
141
    def __init__(self, metadata=None, xmlns=None):
 
142
        self.metadata = metadata or {}
 
143
        if not xmlns:
 
144
            self.xmlns = wsgi.XMLNS_ATOM
 
145
        else:
 
146
            self.xmlns = xmlns
 
147
 
 
148
    def _get_most_recent_update(self, versions):
 
149
        recent = None
 
150
        for version in versions:
 
151
            updated = datetime.datetime.strptime(version['updated'],
 
152
                                                 '%Y-%m-%dT%H:%M:%SZ')
 
153
            if not recent:
 
154
                recent = updated
 
155
            elif updated > recent:
 
156
                recent = updated
 
157
 
 
158
        return recent.strftime('%Y-%m-%dT%H:%M:%SZ')
 
159
 
 
160
    def _get_base_url(self, link_href):
 
161
        # Make sure no trailing /
 
162
        link_href = link_href.rstrip('/')
 
163
        return link_href.rsplit('/', 1)[0] + '/'
 
164
 
 
165
    def _create_feed(self, versions, feed_title, feed_id):
 
166
        feed = etree.Element('feed', nsmap=self.NSMAP)
 
167
        title = etree.SubElement(feed, 'title')
 
168
        title.set('type', 'text')
 
169
        title.text = feed_title
 
170
 
 
171
        # Set this updated to the most recently updated version
 
172
        recent = self._get_most_recent_update(versions)
 
173
        etree.SubElement(feed, 'updated').text = recent
 
174
 
 
175
        etree.SubElement(feed, 'id').text = feed_id
 
176
 
 
177
        link = etree.SubElement(feed, 'link')
 
178
        link.set('rel', 'self')
 
179
        link.set('href', feed_id)
 
180
 
 
181
        author = etree.SubElement(feed, 'author')
 
182
        etree.SubElement(author, 'name').text = 'Rackspace'
 
183
        etree.SubElement(author, 'uri').text = 'http://www.rackspace.com/'
 
184
 
 
185
        for version in versions:
 
186
            feed.append(self._create_version_entry(version))
 
187
 
 
188
        return feed
 
189
 
 
190
    def _create_version_entry(self, version):
 
191
        entry = etree.Element('entry')
 
192
        etree.SubElement(entry, 'id').text = version['links'][0]['href']
 
193
        title = etree.SubElement(entry, 'title')
 
194
        title.set('type', 'text')
 
195
        title.text = 'Version %s' % version['id']
 
196
        etree.SubElement(entry, 'updated').text = version['updated']
 
197
 
 
198
        for link in version['links']:
 
199
            link_elem = etree.SubElement(entry, 'link')
 
200
            link_elem.set('rel', link['rel'])
 
201
            link_elem.set('href', link['href'])
 
202
            if 'type' in link:
 
203
                link_elem.set('type', link['type'])
 
204
 
 
205
        content = etree.SubElement(entry, 'content')
 
206
        content.set('type', 'text')
 
207
        content.text = 'Version %s %s (%s)' % (version['id'],
 
208
                                               version['status'],
 
209
                                               version['updated'])
 
210
        return entry
 
211
 
 
212
 
 
213
class VersionsAtomSerializer(AtomSerializer):
 
214
    def default(self, data):
 
215
        versions = data['versions']
 
216
        feed_id = self._get_base_url(versions[0]['links'][0]['href'])
 
217
        feed = self._create_feed(versions, 'Available API Versions', feed_id)
 
218
        return self._to_xml(feed)
 
219
 
 
220
 
 
221
class VersionAtomSerializer(AtomSerializer):
 
222
    def default(self, data):
 
223
        version = data['version']
 
224
        feed_id = version['links'][0]['href']
 
225
        feed = self._create_feed([version], 'About This Version', feed_id)
 
226
        return self._to_xml(feed)
 
227
 
 
228
 
 
229
class Versions(wsgi.Resource):
 
230
 
 
231
    def __init__(self):
 
232
        super(Versions, self).__init__(None)
 
233
 
 
234
    @wsgi.serializers(xml=VersionsTemplate,
 
235
                      atom=VersionsAtomSerializer)
 
236
    def index(self, req):
 
237
        """Return all versions."""
 
238
        builder = views_versions.get_view_builder(req)
 
239
        return builder.build_versions(VERSIONS)
 
240
 
 
241
    @wsgi.serializers(xml=ChoicesTemplate)
 
242
    @wsgi.response(300)
 
243
    def multi(self, req):
 
244
        """Return multiple choices."""
 
245
        builder = views_versions.get_view_builder(req)
 
246
        return builder.build_choices(VERSIONS, req)
 
247
 
 
248
    def get_action_args(self, request_environment):
 
249
        """Parse dictionary created by routes library."""
 
250
        args = {}
 
251
        if request_environment['PATH_INFO'] == '/':
 
252
            args['action'] = 'index'
 
253
        else:
 
254
            args['action'] = 'multi'
 
255
 
 
256
        return args
 
257
 
 
258
 
 
259
class VolumeVersionV1(object):
 
260
    @wsgi.serializers(xml=VersionTemplate,
 
261
                      atom=VersionAtomSerializer)
 
262
    def show(self, req):
 
263
        builder = views_versions.get_view_builder(req)
 
264
        return builder.build_version(VERSIONS['v1.0'])
 
265
 
 
266
 
 
267
def create_resource():
 
268
    return wsgi.Resource(VolumeVersionV1())