~ubuntu-branches/ubuntu/raring/nova/raring-proposed

« back to all changes in this revision

Viewing changes to nova/api/openstack/volume/snapshots.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-11-23 09:04:58 UTC
  • mfrom: (1.1.66)
  • Revision ID: package-import@ubuntu.com-20121123090458-91565o7aev1i1h71
Tags: 2013.1~g1-0ubuntu1
[ Adam Gandelman ]
* debian/control: Ensure novaclient is upgraded with nova,
  require python-keystoneclient >= 1:2.9.0. (LP: #1073289)
* debian/patches/{ubuntu/*, rbd-security.patch}: Dropped, applied
  upstream.
* debian/control: Add python-testtools to Build-Depends.

[ Chuck Short ]
* New upstream version.
* Refreshed debian/patches/avoid_setuptools_git_dependency.patch.
* debian/rules: FTBFS if missing binaries.
* debian/nova-scheudler.install: Add missing rabbit-queues and
  nova-rpc-zmq-receiver.
* Remove nova-volume since it doesnt exist anymore, transition to cinder-*.
* debian/rules: install apport hook in the right place.
* debian/patches/ubuntu-show-tests.patch: Display test failures.
* debian/control: Add depends on genisoimage
* debian/control: Suggest guestmount.
* debian/control: Suggest websockify. (LP: #1076442)
* debian/nova.conf: Disable nova-volume service.
* debian/control: Depend on xen-system-* rather than the hypervisor.
* debian/control, debian/mans/nova-conductor.8, debian/nova-conductor.init,
  debian/nova-conductor.install, debian/nova-conductor.logrotate
  debian/nova-conductor.manpages, debian/nova-conductor.postrm
  debian/nova-conductor.upstart.in: Add nova-conductor service.
* debian/control: Add python-fixtures as a build deps.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2011 Justin Santa Barbara
2
 
# All Rights Reserved.
3
 
#
4
 
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
5
 
#    not use this file except in compliance with the License. You may obtain
6
 
#    a copy of the License at
7
 
#
8
 
#         http://www.apache.org/licenses/LICENSE-2.0
9
 
#
10
 
#    Unless required by applicable law or agreed to in writing, software
11
 
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
 
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
 
#    License for the specific language governing permissions and limitations
14
 
#    under the License.
15
 
 
16
 
"""The volumes snapshots api."""
17
 
 
18
 
import webob
19
 
from webob import exc
20
 
 
21
 
from nova.api.openstack import common
22
 
from nova.api.openstack import wsgi
23
 
from nova.api.openstack import xmlutil
24
 
from nova import exception
25
 
from nova import flags
26
 
from nova.openstack.common import log as logging
27
 
from nova import utils
28
 
from nova import volume
29
 
 
30
 
 
31
 
LOG = logging.getLogger(__name__)
32
 
 
33
 
 
34
 
FLAGS = flags.FLAGS
35
 
 
36
 
 
37
 
def _translate_snapshot_detail_view(context, vol):
38
 
    """Maps keys for snapshots details view."""
39
 
 
40
 
    d = _translate_snapshot_summary_view(context, vol)
41
 
 
42
 
    # NOTE(gagupta): No additional data / lookups at the moment
43
 
    return d
44
 
 
45
 
 
46
 
def _translate_snapshot_summary_view(context, vol):
47
 
    """Maps keys for snapshots summary view."""
48
 
    d = {}
49
 
 
50
 
    # TODO(bcwaldon): remove str cast once we use uuids
51
 
    d['id'] = str(vol['id'])
52
 
    d['volume_id'] = str(vol['volume_id'])
53
 
    d['status'] = vol['status']
54
 
    # NOTE(gagupta): We map volume_size as the snapshot size
55
 
    d['size'] = vol['volume_size']
56
 
    d['created_at'] = vol['created_at']
57
 
    d['display_name'] = vol['display_name']
58
 
    d['display_description'] = vol['display_description']
59
 
    return d
60
 
 
61
 
 
62
 
def make_snapshot(elem):
63
 
    elem.set('id')
64
 
    elem.set('status')
65
 
    elem.set('size')
66
 
    elem.set('created_at')
67
 
    elem.set('display_name')
68
 
    elem.set('display_description')
69
 
    elem.set('volume_id')
70
 
 
71
 
 
72
 
class SnapshotTemplate(xmlutil.TemplateBuilder):
73
 
    def construct(self):
74
 
        root = xmlutil.TemplateElement('snapshot', selector='snapshot')
75
 
        make_snapshot(root)
76
 
        return xmlutil.MasterTemplate(root, 1)
77
 
 
78
 
 
79
 
class SnapshotsTemplate(xmlutil.TemplateBuilder):
80
 
    def construct(self):
81
 
        root = xmlutil.TemplateElement('snapshots')
82
 
        elem = xmlutil.SubTemplateElement(root, 'snapshot',
83
 
                                          selector='snapshots')
84
 
        make_snapshot(elem)
85
 
        return xmlutil.MasterTemplate(root, 1)
86
 
 
87
 
 
88
 
class SnapshotsController(wsgi.Controller):
89
 
    """The Volumes API controller for the OpenStack API."""
90
 
 
91
 
    def __init__(self, ext_mgr=None):
92
 
        self.volume_api = volume.API()
93
 
        self.ext_mgr = ext_mgr
94
 
        super(SnapshotsController, self).__init__()
95
 
 
96
 
    @wsgi.serializers(xml=SnapshotTemplate)
97
 
    def show(self, req, id):
98
 
        """Return data about the given snapshot."""
99
 
        context = req.environ['nova.context']
100
 
 
101
 
        try:
102
 
            vol = self.volume_api.get_snapshot(context, id)
103
 
        except exception.NotFound:
104
 
            raise exc.HTTPNotFound()
105
 
 
106
 
        return {'snapshot': _translate_snapshot_detail_view(context, vol)}
107
 
 
108
 
    def delete(self, req, id):
109
 
        """Delete a snapshot."""
110
 
        context = req.environ['nova.context']
111
 
 
112
 
        LOG.audit(_("Delete snapshot with id: %s"), id, context=context)
113
 
 
114
 
        try:
115
 
            snapshot = self.volume_api.get_snapshot(context, id)
116
 
            self.volume_api.delete_snapshot(context, snapshot)
117
 
        except exception.NotFound:
118
 
            raise exc.HTTPNotFound()
119
 
        return webob.Response(status_int=202)
120
 
 
121
 
    @wsgi.serializers(xml=SnapshotsTemplate)
122
 
    def index(self, req):
123
 
        """Returns a summary list of snapshots."""
124
 
        return self._items(req, entity_maker=_translate_snapshot_summary_view)
125
 
 
126
 
    @wsgi.serializers(xml=SnapshotsTemplate)
127
 
    def detail(self, req):
128
 
        """Returns a detailed list of snapshots."""
129
 
        return self._items(req, entity_maker=_translate_snapshot_detail_view)
130
 
 
131
 
    def _items(self, req, entity_maker):
132
 
        """Returns a list of snapshots, transformed through entity_maker."""
133
 
        context = req.environ['nova.context']
134
 
 
135
 
        search_opts = {}
136
 
        search_opts.update(req.GET)
137
 
 
138
 
        snapshots = self.volume_api.get_all_snapshots(context,
139
 
                                                      search_opts=search_opts)
140
 
        limited_list = common.limited(snapshots, req)
141
 
        res = [entity_maker(context, snapshot) for snapshot in limited_list]
142
 
        return {'snapshots': res}
143
 
 
144
 
    @wsgi.serializers(xml=SnapshotTemplate)
145
 
    def create(self, req, body):
146
 
        """Creates a new snapshot."""
147
 
        context = req.environ['nova.context']
148
 
 
149
 
        if not self.is_valid_body(body, 'snapshot'):
150
 
            raise exc.HTTPUnprocessableEntity()
151
 
 
152
 
        snapshot = body['snapshot']
153
 
        volume_id = snapshot['volume_id']
154
 
        volume = self.volume_api.get(context, volume_id)
155
 
        force = snapshot.get('force', False)
156
 
        msg = _("Create snapshot from volume %s")
157
 
        LOG.audit(msg, volume_id, context=context)
158
 
 
159
 
        if not utils.is_valid_boolstr(force):
160
 
            msg = _("Invalid value '%s' for force. ") % force
161
 
            raise exception.InvalidParameterValue(err=msg)
162
 
 
163
 
        if utils.bool_from_str(force):
164
 
            new_snapshot = self.volume_api.create_snapshot_force(context,
165
 
                                        volume,
166
 
                                        snapshot.get('display_name'),
167
 
                                        snapshot.get('display_description'))
168
 
        else:
169
 
            new_snapshot = self.volume_api.create_snapshot(context,
170
 
                                        volume,
171
 
                                        snapshot.get('display_name'),
172
 
                                        snapshot.get('display_description'))
173
 
 
174
 
        retval = _translate_snapshot_detail_view(context, new_snapshot)
175
 
 
176
 
        return {'snapshot': retval}
177
 
 
178
 
 
179
 
def create_resource(ext_mgr):
180
 
    return wsgi.Resource(SnapshotsController(ext_mgr))