~ubuntu-cloud-archive/ubuntu/precise/nova/trunk

« back to all changes in this revision

Viewing changes to nova/volume/cinder.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-07-06 10:18:33 UTC
  • mfrom: (1.1.58)
  • Revision ID: package-import@ubuntu.com-20120706101833-wp2nv392mpe9re8p
Tags: 2012.2~f2-0ubuntu1
[ Adam Gandelman ]
* Use new rootwrap configuration structure:
  - debian/nova-{compute, network, volume}.{pyinstall, pyremove}: Dropped.
  - debian/nova-common.dirs: Add /etc/nova/rootwrap.d/.
  - debian/nova-common.install: Install /etc/nova/rootwrap.conf.
  - debian/debian/nova.conf: Reference rootwrap.conf in calls to
    nova-rootwrap.
  - debian/nova-{compute, network, volume}.install: Install corresponding
    filter in /etc/nova/rootwrap.d/
* debian/rules: Install logging_sample.conf to /etc/nova/logging.conf
  as part of nova-common.
* debian/pydist-overrides: Add setuptools-git.
* debian/control: Add python-setuptools-git as a Build-Depends.
* debian/rules: Do not remove nova.egg-info during auto_clean.  Now that
  upstream has moved to setuptools-git, doing so results in missing files
  from built package.

[ Chuck Short ]
* New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2010 United States Government as represented by the
 
4
# Administrator of the National Aeronautics and Space Administration.
 
5
# All Rights Reserved.
 
6
#
 
7
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
8
#    not use this file except in compliance with the License. You may obtain
 
9
#    a copy of the License at
 
10
#
 
11
#         http://www.apache.org/licenses/LICENSE-2.0
 
12
#
 
13
#    Unless required by applicable law or agreed to in writing, software
 
14
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
15
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
16
#    License for the specific language governing permissions and limitations
 
17
#    under the License.
 
18
 
 
19
"""
 
20
Handles all requests relating to volumes + cinder.
 
21
"""
 
22
 
 
23
 
 
24
from cinderclient import service_catalog
 
25
from cinderclient.v1 import client as cinder_client
 
26
 
 
27
from nova.db import base
 
28
from nova import exception
 
29
from nova import flags
 
30
from nova.openstack.common import log as logging
 
31
 
 
32
FLAGS = flags.FLAGS
 
33
 
 
34
LOG = logging.getLogger(__name__)
 
35
 
 
36
 
 
37
def cinderclient(context):
 
38
 
 
39
    # FIXME: the cinderclient ServiceCatalog object is mis-named.
 
40
    #        It actually contains the entire access blob.
 
41
    compat_catalog = {
 
42
        'access': {'serviceCatalog': context.service_catalog}
 
43
    }
 
44
    sc = service_catalog.ServiceCatalog(compat_catalog)
 
45
    url = sc.url_for(service_type='volume', service_name='cinder')
 
46
 
 
47
    LOG.debug('cinderclient connection created using token "%s" and url "%s"' %
 
48
              (context.auth_token, url))
 
49
 
 
50
    c = cinder_client.Client(context.user_id,
 
51
                             context.auth_token,
 
52
                             project_id=context.project_id,
 
53
                             auth_url=url)
 
54
    c.client.auth_token = context.auth_token
 
55
    c.client.management_url = url
 
56
    return c
 
57
 
 
58
 
 
59
def _untranslate_volume_summary_view(context, vol):
 
60
    """Maps keys for volumes summary view."""
 
61
    d = {}
 
62
 
 
63
    d['id'] = vol.id
 
64
    d['status'] = vol.status
 
65
    d['size'] = vol.size
 
66
    d['availability_zone'] = vol.availability_zone
 
67
    d['created_at'] = vol.created_at
 
68
 
 
69
    # TODO(jdg): The calling code expects attach_time and
 
70
    #            mountpoint to be set. When the calling
 
71
    #            code is more defensive this can be
 
72
    #            removed.
 
73
    d['attach_time'] = ""
 
74
    d['mountpoint'] = ""
 
75
 
 
76
    if vol.attachments:
 
77
        att = vol.attachments[0]
 
78
        d['attach_status'] = 'attached'
 
79
        d['instance_uuid'] = att['server_id']
 
80
        d['mountpoint'] = att['device']
 
81
    else:
 
82
        d['attach_status'] = 'detached'
 
83
 
 
84
    d['display_name'] = vol.display_name
 
85
    d['display_description'] = vol.display_description
 
86
 
 
87
    # TODO(jdg): Information may be lost in this translation
 
88
    d['volume_type_id'] = vol.volume_type
 
89
    d['snapshot_id'] = vol.snapshot_id
 
90
 
 
91
    d['vol_metadata'] = []
 
92
    for k, v in vol.metadata:
 
93
        item = {}
 
94
        item['key'] = k
 
95
        item['value'] = v
 
96
        d['vol_metadata'].append(item)
 
97
 
 
98
    return d
 
99
 
 
100
 
 
101
def _untranslate_snapshot_summary_view(context, snapshot):
 
102
    """Maps keys for snapshots summary view."""
 
103
    d = {}
 
104
 
 
105
    d['id'] = snapshot.id
 
106
    d['status'] = snapshot.status
 
107
    d['progress'] = snapshot.progress
 
108
    d['size'] = snapshot.size
 
109
    d['created_at'] = snapshot.created_at
 
110
    d['display_name'] = snapshot.display_name
 
111
    d['display_description'] = snapshot.display_description
 
112
    d['volume_id'] = snapshot.volume_id
 
113
    d['project_id'] = snapshot.project_id
 
114
    d['volume_size'] = snapshot.size
 
115
 
 
116
    return d
 
117
 
 
118
 
 
119
class API(base.Base):
 
120
    """API for interacting with the volume manager."""
 
121
 
 
122
    def get(self, context, volume_id):
 
123
        item = cinderclient(context).volumes.get(volume_id)
 
124
        return _untranslate_volume_summary_view(context, item)
 
125
 
 
126
    def get_all(self, context, search_opts={}):
 
127
        items = cinderclient(context).volumes.list(detailed=True)
 
128
        rval = []
 
129
 
 
130
        for item in items:
 
131
            rval.append(_untranslate_volume_summary_view(context, item))
 
132
 
 
133
        return rval
 
134
 
 
135
    def check_attach(self, context, volume):
 
136
        # TODO(vish): abstract status checking?
 
137
        if volume['status'] != "available":
 
138
            msg = _("status must be available")
 
139
            raise exception.InvalidVolume(reason=msg)
 
140
        if volume['attach_status'] == "attached":
 
141
            msg = _("already attached")
 
142
            raise exception.InvalidVolume(reason=msg)
 
143
 
 
144
    def check_detach(self, context, volume):
 
145
        # TODO(vish): abstract status checking?
 
146
        if volume['status'] == "available":
 
147
            msg = _("already detached")
 
148
            raise exception.InvalidVolume(reason=msg)
 
149
 
 
150
    def reserve_volume(self, context, volume):
 
151
        cinderclient(context).volumes.reserve(volume['id'])
 
152
 
 
153
    def unreserve_volume(self, context, volume):
 
154
        cinderclient(context).volumes.reserve(volume['id'])
 
155
 
 
156
    def attach(self, context, volume, instance_uuid, mountpoint):
 
157
        cinderclient(context).volumes.attach(volume['id'],
 
158
                                             instance_uuid,
 
159
                                             mountpoint)
 
160
 
 
161
    def detach(self, context, volume):
 
162
        cinderclient(context).volumes.detach(volume['id'])
 
163
 
 
164
    def initialize_connection(self, context, volume, connector):
 
165
        return cinderclient(context).\
 
166
                 volumes.initialize_connection(volume['id'], connector)
 
167
 
 
168
    def terminate_connection(self, context, volume, connector):
 
169
        return cinderclient(context).\
 
170
                 volumes.terminate_connection(volume['id'], connector)
 
171
 
 
172
    def create(self, context, size, name, description, snapshot=None,
 
173
                     volume_type=None, metadata=None, availability_zone=None):
 
174
 
 
175
        item = cinderclient(context).volumes.create(size, snapshot,
 
176
                                                    name, description,
 
177
                                                    volume_type)
 
178
 
 
179
        volume = _untranslate_volume_summary_view(context, item)
 
180
        return _untranslate_volume_summary_view(context, item)
 
181
 
 
182
    def delete(self, context, volume):
 
183
        cinderclient(context).volumes.delete(volume['id'])
 
184
 
 
185
    def update(self, context, volume, fields):
 
186
        raise NotImplementedError()
 
187
 
 
188
    def get_snapshot(self, context, snapshot_id):
 
189
        item = cinderclient(context).volume_snapshots.get(snapshot_id)
 
190
        return _untranslate_snapshot_summary_view(context, item)
 
191
 
 
192
    def get_all_snapshots(self, context):
 
193
        items = cinderclient(context).volume_snapshots.list(detailed=True)
 
194
        rvals = []
 
195
 
 
196
        for item in items:
 
197
            rvals.append(_untranslate_snapshot_summary_view(context, item))
 
198
 
 
199
        return rvals
 
200
 
 
201
    def create_snapshot(self, context, volume, name, description):
 
202
        item = cinderclient(context).volume_snapshots.create(volume['id'],
 
203
                                                             False,
 
204
                                                             name,
 
205
                                                             description)
 
206
        return _untranslate_snapshot_summary_view(context, item)
 
207
 
 
208
    def create_snapshot_force(self, context, volume, name, description):
 
209
        item = cinderclient(context).volume_snapshots.create(volume['id'],
 
210
                                                             True,
 
211
                                                             name,
 
212
                                                             description)
 
213
 
 
214
        return _untranslate_snapshot_summary_view(context, item)
 
215
 
 
216
    def delete_snapshot(self, context, snapshot):
 
217
        cinderclient(context).volume_snapshots.delete(snapshot['id'])
 
218
 
 
219
    def get_volume_metadata(self, context, volume):
 
220
        raise NotImplementedError()
 
221
 
 
222
    def delete_volume_metadata(self, context, volume, key):
 
223
        raise NotImplementedError()
 
224
 
 
225
    def update_volume_metadata(self, context, volume, metadata, delete=False):
 
226
        raise NotImplementedError()
 
227
 
 
228
    def get_volume_metadata_value(self, volume, key):
 
229
        raise NotImplementedError()