1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright 2010 United States Government as represented by the
4
# Administrator of the National Aeronautics and Space Administration.
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
11
# http://www.apache.org/licenses/LICENSE-2.0
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
22
class XenAPIException(Exception):
23
def __init__(self, original_exception):
24
super(XenAPIException, self).__init__(str(original_exception))
25
self.original_exception = original_exception
28
class OperationsBase(object):
29
def __init__(self, xenapi_session):
30
self.session = xenapi_session
32
def call_xenapi(self, method, *args):
33
return self.session.call_xenapi(method, *args)
36
class PbdOperations(OperationsBase):
38
return self.call_xenapi('PBD.get_all')
40
def unplug(self, pbd_ref):
41
self.call_xenapi('PBD.unplug', pbd_ref)
43
def create(self, host_ref, sr_ref, device_config):
44
return self.call_xenapi(
49
device_config=device_config
53
def plug(self, pbd_ref):
54
self.call_xenapi('PBD.plug', pbd_ref)
57
class SrOperations(OperationsBase):
59
return self.call_xenapi('SR.get_all')
61
def get_record(self, sr_ref):
62
return self.call_xenapi('SR.get_record', sr_ref)
64
def forget(self, sr_ref):
65
self.call_xenapi('SR.forget', sr_ref)
67
def scan(self, sr_ref):
68
self.call_xenapi('SR.scan', sr_ref)
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(
79
name_description or '',
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(
92
name_description or '',
99
def get_uuid(self, sr_ref):
100
return self.get_record(sr_ref)['uuid']
102
def get_name_label(self, sr_ref):
103
return self.get_record(sr_ref)['name_label']
105
def get_name_description(self, sr_ref):
106
return self.get_record(sr_ref)['name_description']
108
def destroy(self, sr_ref):
109
self.call_xenapi('SR.destroy', sr_ref)
112
class VdiOperations(OperationsBase):
114
return self.call_xenapi('VDI.get_all')
116
def get_record(self, vdi_ref):
117
return self.call_xenapi('VDI.get_record', vdi_ref)
119
def get_by_uuid(self, vdi_uuid):
120
return self.call_xenapi('VDI.get_by_uuid', vdi_uuid)
122
def get_uuid(self, vdi_ref):
123
return self.get_record(vdi_ref)['uuid']
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',
130
virtual_size=str(size),
134
other_config=other_config or dict()
138
def destroy(self, vdi_ref):
139
self.call_xenapi('VDI.destroy', vdi_ref)
142
class HostOperations(OperationsBase):
143
def get_record(self, host_ref):
144
return self.call_xenapi('host.get_record', host_ref)
146
def get_uuid(self, host_ref):
147
return self.get_record(host_ref)['uuid']
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)
161
return self.call_xenapi('logout')
163
def call_xenapi(self, method, *args):
165
return self._session.xenapi_request(method, args)
166
except self._exception_to_convert as e:
167
raise XenAPIException(e)
170
return self.call_xenapi('session.get_pool', self.handle)
172
def get_this_host(self):
173
return self.call_xenapi('session.get_this_host', self.handle)
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)
182
def unplug_pbds_and_forget_sr(self, sr_ref):
183
self.unplug_pbds_from_sr(sr_ref)
184
self.SR.forget(sr_ref)
186
def create_new_vdi(self, sr_ref, size_in_gigabytes):
187
return self.VDI.create(
189
to_bytes(size_in_gigabytes),
194
def to_bytes(size_in_gigs):
195
return size_in_gigs * 1024 * 1024 * 1024
198
class NFSOperationsMixIn(CompoundOperations):
199
def is_nfs_sr(self, sr_ref):
200
return self.SR.get_record(sr_ref).get('type') == 'nfs'
202
@contextlib.contextmanager
203
def new_sr_on_nfs(self, host_ref, server, serverpath,
204
name_label=None, name_description=None):
206
device_config = dict(
208
serverpath=serverpath
210
name_label = name_label or ''
211
name_description = name_description or ''
214
sr_ref = self.SR.create(
223
self.unplug_pbds_and_forget_sr(sr_ref)
225
def plug_nfs_sr(self, host_ref, server, serverpath, sr_uuid,
226
name_label=None, name_description=None):
228
device_config = dict(
230
serverpath=serverpath
234
sr_ref = self.SR.introduce(
241
pbd_ref = self.PBD.create(
247
self.PBD.plug(pbd_ref)
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(
260
vdi_ref = self.VDI.get_by_uuid(vdi_uuid)
261
return dict(sr_ref=sr_ref, vdi_ref=vdi_ref)
264
class ContextAwareSession(XenAPISession):
268
def __exit__(self, exc_type, exc_value, traceback):
272
class OpenStackXenAPISession(ContextAwareSession,
277
def connect(url, user, password):
279
session = XenAPI.Session(url)
280
session.login_with_password(user, password)
281
return OpenStackXenAPISession(session, XenAPI.Failure)
284
class SessionFactory(object):
285
def __init__(self, url, user, password):
288
self.password = password
290
def get_session(self):
291
return connect(self.url, self.user, self.password)
294
class NFSBasedVolumeOperations(object):
295
def __init__(self, session_factory):
296
self._session_factory = session_factory
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)
307
sr_uuid=session.SR.get_uuid(sr_ref),
308
vdi_uuid=session.VDI.get_uuid(vdi_ref)
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)
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)
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)
326
return session.VDI.get_uuid(refs['vdi_ref'])
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)