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

« back to all changes in this revision

Viewing changes to cinder/volume/drivers/xenapi/lib.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 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
import contextlib
 
20
 
 
21
 
 
22
class XenAPIException(Exception):
 
23
    def __init__(self, original_exception):
 
24
        super(XenAPIException, self).__init__(str(original_exception))
 
25
        self.original_exception = original_exception
 
26
 
 
27
 
 
28
class OperationsBase(object):
 
29
    def __init__(self, xenapi_session):
 
30
        self.session = xenapi_session
 
31
 
 
32
    def call_xenapi(self, method, *args):
 
33
        return self.session.call_xenapi(method, *args)
 
34
 
 
35
 
 
36
class PbdOperations(OperationsBase):
 
37
    def get_all(self):
 
38
        return self.call_xenapi('PBD.get_all')
 
39
 
 
40
    def unplug(self, pbd_ref):
 
41
        self.call_xenapi('PBD.unplug', pbd_ref)
 
42
 
 
43
    def create(self, host_ref, sr_ref, device_config):
 
44
        return self.call_xenapi(
 
45
            'PBD.create',
 
46
            dict(
 
47
                host=host_ref,
 
48
                SR=sr_ref,
 
49
                device_config=device_config
 
50
            )
 
51
        )
 
52
 
 
53
    def plug(self, pbd_ref):
 
54
        self.call_xenapi('PBD.plug', pbd_ref)
 
55
 
 
56
 
 
57
class SrOperations(OperationsBase):
 
58
    def get_all(self):
 
59
        return self.call_xenapi('SR.get_all')
 
60
 
 
61
    def get_record(self, sr_ref):
 
62
        return self.call_xenapi('SR.get_record', sr_ref)
 
63
 
 
64
    def forget(self, sr_ref):
 
65
        self.call_xenapi('SR.forget', sr_ref)
 
66
 
 
67
    def scan(self, sr_ref):
 
68
        self.call_xenapi('SR.scan', sr_ref)
 
69
 
 
70
    def create(self, host_ref, device_config, name_label, name_description,
 
71
                  sr_type, physical_size=None, content_type=None,
 
72
                  shared=False, sm_config=None):
 
73
        return self.call_xenapi(
 
74
            'SR.create',
 
75
            host_ref,
 
76
            device_config,
 
77
            physical_size or '0',
 
78
            name_label or '',
 
79
            name_description or '',
 
80
            sr_type,
 
81
            content_type or '',
 
82
            shared,
 
83
            sm_config or dict()
 
84
        )
 
85
 
 
86
    def introduce(self, sr_uuid, name_label, name_description, sr_type,
 
87
                     content_type=None, shared=False, sm_config=None):
 
88
        return self.call_xenapi(
 
89
            'SR.introduce',
 
90
            sr_uuid,
 
91
            name_label or '',
 
92
            name_description or '',
 
93
            sr_type,
 
94
            content_type or '',
 
95
            shared,
 
96
            sm_config or dict()
 
97
        )
 
98
 
 
99
    def get_uuid(self, sr_ref):
 
100
        return self.get_record(sr_ref)['uuid']
 
101
 
 
102
    def get_name_label(self, sr_ref):
 
103
        return self.get_record(sr_ref)['name_label']
 
104
 
 
105
    def get_name_description(self, sr_ref):
 
106
        return self.get_record(sr_ref)['name_description']
 
107
 
 
108
    def destroy(self, sr_ref):
 
109
        self.call_xenapi('SR.destroy', sr_ref)
 
110
 
 
111
 
 
112
class VdiOperations(OperationsBase):
 
113
    def get_all(self):
 
114
        return self.call_xenapi('VDI.get_all')
 
115
 
 
116
    def get_record(self, vdi_ref):
 
117
        return self.call_xenapi('VDI.get_record', vdi_ref)
 
118
 
 
119
    def get_by_uuid(self, vdi_uuid):
 
120
        return self.call_xenapi('VDI.get_by_uuid', vdi_uuid)
 
121
 
 
122
    def get_uuid(self, vdi_ref):
 
123
        return self.get_record(vdi_ref)['uuid']
 
124
 
 
125
    def create(self, sr_ref, size, vdi_type,
 
126
                   sharable=False, read_only=False, other_config=None):
 
127
        return self.call_xenapi('VDI.create',
 
128
            dict(
 
129
                SR=sr_ref,
 
130
                virtual_size=str(size),
 
131
                type=vdi_type,
 
132
                sharable=sharable,
 
133
                read_only=read_only,
 
134
                other_config=other_config or dict()
 
135
            )
 
136
        )
 
137
 
 
138
    def destroy(self, vdi_ref):
 
139
        self.call_xenapi('VDI.destroy', vdi_ref)
 
140
 
 
141
 
 
142
class HostOperations(OperationsBase):
 
143
    def get_record(self, host_ref):
 
144
        return self.call_xenapi('host.get_record', host_ref)
 
145
 
 
146
    def get_uuid(self, host_ref):
 
147
        return self.get_record(host_ref)['uuid']
 
148
 
 
149
 
 
150
class XenAPISession(object):
 
151
    def __init__(self, session, exception_to_convert):
 
152
        self._session = session
 
153
        self._exception_to_convert = exception_to_convert
 
154
        self.handle = self._session.handle
 
155
        self.PBD = PbdOperations(self)
 
156
        self.SR = SrOperations(self)
 
157
        self.VDI = VdiOperations(self)
 
158
        self.host = HostOperations(self)
 
159
 
 
160
    def close(self):
 
161
        return self.call_xenapi('logout')
 
162
 
 
163
    def call_xenapi(self, method, *args):
 
164
        try:
 
165
            return self._session.xenapi_request(method, args)
 
166
        except self._exception_to_convert as e:
 
167
            raise XenAPIException(e)
 
168
 
 
169
    def get_pool(self):
 
170
        return self.call_xenapi('session.get_pool', self.handle)
 
171
 
 
172
    def get_this_host(self):
 
173
        return self.call_xenapi('session.get_this_host', self.handle)
 
174
 
 
175
 
 
176
class CompoundOperations(object):
 
177
    def unplug_pbds_from_sr(self, sr_ref):
 
178
        sr_rec = self.SR.get_record(sr_ref)
 
179
        for pbd_ref in sr_rec.get('PBDs', []):
 
180
            self.PBD.unplug(pbd_ref)
 
181
 
 
182
    def unplug_pbds_and_forget_sr(self, sr_ref):
 
183
        self.unplug_pbds_from_sr(sr_ref)
 
184
        self.SR.forget(sr_ref)
 
185
 
 
186
    def create_new_vdi(self, sr_ref, size_in_gigabytes):
 
187
        return self.VDI.create(
 
188
                sr_ref,
 
189
                to_bytes(size_in_gigabytes),
 
190
                'User',
 
191
        )
 
192
 
 
193
 
 
194
def to_bytes(size_in_gigs):
 
195
    return size_in_gigs * 1024 * 1024 * 1024
 
196
 
 
197
 
 
198
class NFSOperationsMixIn(CompoundOperations):
 
199
    def is_nfs_sr(self, sr_ref):
 
200
        return self.SR.get_record(sr_ref).get('type') == 'nfs'
 
201
 
 
202
    @contextlib.contextmanager
 
203
    def new_sr_on_nfs(self, host_ref, server, serverpath,
 
204
                      name_label=None, name_description=None):
 
205
 
 
206
        device_config = dict(
 
207
            server=server,
 
208
            serverpath=serverpath
 
209
        )
 
210
        name_label = name_label or ''
 
211
        name_description = name_description or ''
 
212
        sr_type = 'nfs'
 
213
 
 
214
        sr_ref = self.SR.create(
 
215
            host_ref,
 
216
            device_config,
 
217
            name_label,
 
218
            name_description,
 
219
            sr_type,
 
220
        )
 
221
        yield sr_ref
 
222
 
 
223
        self.unplug_pbds_and_forget_sr(sr_ref)
 
224
 
 
225
    def plug_nfs_sr(self, host_ref, server, serverpath, sr_uuid,
 
226
                    name_label=None, name_description=None):
 
227
 
 
228
        device_config = dict(
 
229
            server=server,
 
230
            serverpath=serverpath
 
231
        )
 
232
        sr_type = 'nfs'
 
233
 
 
234
        sr_ref = self.SR.introduce(
 
235
            sr_uuid,
 
236
            name_label,
 
237
            name_description,
 
238
            sr_type,
 
239
        )
 
240
 
 
241
        pbd_ref = self.PBD.create(
 
242
            host_ref,
 
243
            sr_ref,
 
244
            device_config
 
245
        )
 
246
 
 
247
        self.PBD.plug(pbd_ref)
 
248
 
 
249
        return sr_ref
 
250
 
 
251
    def connect_volume(self, server, serverpath, sr_uuid, vdi_uuid):
 
252
        host_ref = self.get_this_host()
 
253
        sr_ref = self.plug_nfs_sr(
 
254
            host_ref,
 
255
            server,
 
256
            serverpath,
 
257
            sr_uuid
 
258
        )
 
259
        self.SR.scan(sr_ref)
 
260
        vdi_ref = self.VDI.get_by_uuid(vdi_uuid)
 
261
        return dict(sr_ref=sr_ref, vdi_ref=vdi_ref)
 
262
 
 
263
 
 
264
class ContextAwareSession(XenAPISession):
 
265
    def __enter__(self):
 
266
        return self
 
267
 
 
268
    def __exit__(self, exc_type, exc_value, traceback):
 
269
        self.close()
 
270
 
 
271
 
 
272
class OpenStackXenAPISession(ContextAwareSession,
 
273
                             NFSOperationsMixIn):
 
274
    pass
 
275
 
 
276
 
 
277
def connect(url, user, password):
 
278
    import XenAPI
 
279
    session = XenAPI.Session(url)
 
280
    session.login_with_password(user, password)
 
281
    return OpenStackXenAPISession(session, XenAPI.Failure)
 
282
 
 
283
 
 
284
class SessionFactory(object):
 
285
    def __init__(self, url, user, password):
 
286
        self.url = url
 
287
        self.user = user
 
288
        self.password = password
 
289
 
 
290
    def get_session(self):
 
291
        return connect(self.url, self.user, self.password)
 
292
 
 
293
 
 
294
class NFSBasedVolumeOperations(object):
 
295
    def __init__(self, session_factory):
 
296
        self._session_factory = session_factory
 
297
 
 
298
    def create_volume(self, server, serverpath, size,
 
299
                      name=None, description=None):
 
300
        with self._session_factory.get_session() as session:
 
301
            host_ref = session.get_this_host()
 
302
            with session.new_sr_on_nfs(host_ref, server, serverpath,
 
303
                                       name, description) as sr_ref:
 
304
                vdi_ref = session.create_new_vdi(sr_ref, size)
 
305
 
 
306
                return dict(
 
307
                    sr_uuid=session.SR.get_uuid(sr_ref),
 
308
                    vdi_uuid=session.VDI.get_uuid(vdi_ref)
 
309
                )
 
310
 
 
311
    def delete_volume(self, server, serverpath, sr_uuid, vdi_uuid):
 
312
        with self._session_factory.get_session() as session:
 
313
            refs = session.connect_volume(
 
314
                server, serverpath, sr_uuid, vdi_uuid)
 
315
 
 
316
            session.VDI.destroy(refs['vdi_ref'])
 
317
            sr_ref = refs['sr_ref']
 
318
            session.unplug_pbds_from_sr(sr_ref)
 
319
            session.SR.destroy(sr_ref)
 
320
 
 
321
    def connect_volume(self, server, serverpath, sr_uuid, vdi_uuid):
 
322
        with self._session_factory.get_session() as session:
 
323
            refs = session.connect_volume(
 
324
                server, serverpath, sr_uuid, vdi_uuid)
 
325
 
 
326
            return session.VDI.get_uuid(refs['vdi_ref'])
 
327
 
 
328
    def disconnect_volume(self, vdi_uuid):
 
329
        with self._session_factory.get_session() as session:
 
330
            vdi_ref = session.VDI.get_by_uuid(vdi_uuid)
 
331
            vdi_rec = session.VDI.get_record(vdi_ref)
 
332
            sr_ref = vdi_rec['SR']
 
333
            session.unplug_pbds_and_forget_sr(sr_ref)