XenAPI 24.27.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- XenAPI/XenAPI.py +296 -0
- XenAPI/__init__.py +1 -0
- XenAPI-24.27.0.dist-info/METADATA +28 -0
- XenAPI-24.27.0.dist-info/RECORD +6 -0
- XenAPI-24.27.0.dist-info/WHEEL +5 -0
- XenAPI-24.27.0.dist-info/top_level.txt +1 -0
XenAPI/XenAPI.py
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# Copyright (c) Citrix Systems, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions are
|
|
6
|
+
# met:
|
|
7
|
+
#
|
|
8
|
+
# 1) Redistributions of source code must retain the above copyright
|
|
9
|
+
# notice, this list of conditions and the following disclaimer.
|
|
10
|
+
#
|
|
11
|
+
# 2) Redistributions in binary form must reproduce the above copyright
|
|
12
|
+
# notice, this list of conditions and the following disclaimer in
|
|
13
|
+
# the documentation and/or other materials provided with the
|
|
14
|
+
# distribution.
|
|
15
|
+
#
|
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
17
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
18
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
19
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
20
|
+
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
21
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
22
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
23
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
24
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
25
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
# --------------------------------------------------------------------
|
|
28
|
+
# Parts of this file are based upon xmlrpclib.py, the XML-RPC client
|
|
29
|
+
# interface included in the Python distribution.
|
|
30
|
+
#
|
|
31
|
+
# Copyright (c) 1999-2002 by Secret Labs AB
|
|
32
|
+
# Copyright (c) 1999-2002 by Fredrik Lundh
|
|
33
|
+
#
|
|
34
|
+
# By obtaining, using, and/or copying this software and/or its
|
|
35
|
+
# associated documentation, you agree that you have read, understood,
|
|
36
|
+
# and will comply with the following terms and conditions:
|
|
37
|
+
#
|
|
38
|
+
# Permission to use, copy, modify, and distribute this software and
|
|
39
|
+
# its associated documentation for any purpose and without fee is
|
|
40
|
+
# hereby granted, provided that the above copyright notice appears in
|
|
41
|
+
# all copies, and that both that copyright notice and this permission
|
|
42
|
+
# notice appear in supporting documentation, and that the name of
|
|
43
|
+
# Secret Labs AB or the author not be used in advertising or publicity
|
|
44
|
+
# pertaining to distribution of the software without specific, written
|
|
45
|
+
# prior permission.
|
|
46
|
+
#
|
|
47
|
+
# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
|
48
|
+
# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
|
|
49
|
+
# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
|
|
50
|
+
# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
|
|
51
|
+
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
52
|
+
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
53
|
+
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
54
|
+
# OF THIS SOFTWARE.
|
|
55
|
+
# --------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
import gettext
|
|
58
|
+
import os
|
|
59
|
+
import socket
|
|
60
|
+
import sys
|
|
61
|
+
import http.client as httplib
|
|
62
|
+
import xmlrpc.client as xmlrpclib
|
|
63
|
+
|
|
64
|
+
otel = False
|
|
65
|
+
try:
|
|
66
|
+
if os.environ["OTEL_SDK_DISABLED"] == "false":
|
|
67
|
+
from opentelemetry import propagate
|
|
68
|
+
from opentelemetry.trace.propagation import set_span_in_context, get_current_span
|
|
69
|
+
otel = True
|
|
70
|
+
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
translation = gettext.translation('xen-xm', fallback = True)
|
|
75
|
+
|
|
76
|
+
API_VERSION_1_1 = '1.1'
|
|
77
|
+
API_VERSION_1_2 = '1.2'
|
|
78
|
+
|
|
79
|
+
class Failure(Exception):
|
|
80
|
+
def __init__(self, details):
|
|
81
|
+
self.details = details
|
|
82
|
+
|
|
83
|
+
def __str__(self):
|
|
84
|
+
try:
|
|
85
|
+
return str(self.details)
|
|
86
|
+
except Exception as exn:
|
|
87
|
+
msg = "Xen-API failure: %s" % exn
|
|
88
|
+
sys.stderr.write(msg)
|
|
89
|
+
return msg
|
|
90
|
+
|
|
91
|
+
def _details_map(self):
|
|
92
|
+
return dict([(str(i), self.details[i])
|
|
93
|
+
for i in range(len(self.details))])
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# Just a "constant" that we use to decide whether to retry the RPC
|
|
97
|
+
_RECONNECT_AND_RETRY = object()
|
|
98
|
+
|
|
99
|
+
class UDSHTTPConnection(httplib.HTTPConnection):
|
|
100
|
+
"""HTTPConnection subclass to allow HTTP over Unix domain sockets. """
|
|
101
|
+
def connect(self):
|
|
102
|
+
path = self.host.replace("_", "/")
|
|
103
|
+
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
104
|
+
self.sock.connect(path)
|
|
105
|
+
|
|
106
|
+
class UDSTransport(xmlrpclib.Transport):
|
|
107
|
+
def add_extra_header(self, key, value):
|
|
108
|
+
self._extra_headers += [ (key,value) ]
|
|
109
|
+
def with_tracecontext(self):
|
|
110
|
+
if otel:
|
|
111
|
+
headers = {}
|
|
112
|
+
# pylint: disable=possibly-used-before-assignment
|
|
113
|
+
ctx = set_span_in_context(get_current_span())
|
|
114
|
+
# pylint: disable=possibly-used-before-assignment
|
|
115
|
+
propagators = propagate.get_global_textmap()
|
|
116
|
+
propagators.inject(headers, ctx)
|
|
117
|
+
self._extra_headers = []
|
|
118
|
+
for k, v in headers.items():
|
|
119
|
+
self.add_extra_header(k, v)
|
|
120
|
+
def make_connection(self, host):
|
|
121
|
+
self.with_tracecontext()
|
|
122
|
+
|
|
123
|
+
# compatibility with parent xmlrpclib.Transport HTTP/1.1 support
|
|
124
|
+
if self._connection and host == self._connection[0]:
|
|
125
|
+
return self._connection[1]
|
|
126
|
+
|
|
127
|
+
self._connection = host, UDSHTTPConnection(host)
|
|
128
|
+
return self._connection[1]
|
|
129
|
+
|
|
130
|
+
def notimplemented(name, *args, **kwargs):
|
|
131
|
+
raise NotImplementedError("XMLRPC proxies do not support python magic methods", name, *args, **kwargs)
|
|
132
|
+
|
|
133
|
+
class Session(xmlrpclib.ServerProxy):
|
|
134
|
+
"""A server proxy and session manager for communicating with xapi using
|
|
135
|
+
the Xen-API.
|
|
136
|
+
|
|
137
|
+
Example:
|
|
138
|
+
|
|
139
|
+
session = Session('http://localhost/')
|
|
140
|
+
session.login_with_password('me', 'mypassword', '1.0', 'xen-api-scripts-xenapi.py')
|
|
141
|
+
session.xenapi.VM.start(vm_uuid)
|
|
142
|
+
session.xenapi.session.logout()
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def __init__(self, uri, transport=None, encoding=None, verbose=False,
|
|
146
|
+
allow_none=True, ignore_ssl=False):
|
|
147
|
+
|
|
148
|
+
verbose = bool(verbose)
|
|
149
|
+
allow_none = bool(allow_none)
|
|
150
|
+
|
|
151
|
+
if ignore_ssl:
|
|
152
|
+
import ssl
|
|
153
|
+
ctx = ssl._create_unverified_context()
|
|
154
|
+
xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
|
|
155
|
+
verbose, allow_none, context=ctx)
|
|
156
|
+
else:
|
|
157
|
+
xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
|
|
158
|
+
verbose, allow_none)
|
|
159
|
+
self.transport = transport
|
|
160
|
+
self._session = None
|
|
161
|
+
self.last_login_method = None
|
|
162
|
+
self.last_login_params = None
|
|
163
|
+
self._API_version = API_VERSION_1_1
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def xenapi_request(self, methodname, params):
|
|
167
|
+
if methodname.startswith('login'):
|
|
168
|
+
self._login(methodname, params)
|
|
169
|
+
return None
|
|
170
|
+
elif methodname == 'logout' or methodname == 'session.logout':
|
|
171
|
+
self._logout()
|
|
172
|
+
return None
|
|
173
|
+
else:
|
|
174
|
+
retry_count = 0
|
|
175
|
+
while retry_count < 3:
|
|
176
|
+
full_params = (self._session,) + params
|
|
177
|
+
result = _parse_result(getattr(self, methodname)(*full_params))
|
|
178
|
+
if result is _RECONNECT_AND_RETRY:
|
|
179
|
+
retry_count += 1
|
|
180
|
+
if self.last_login_method:
|
|
181
|
+
self._login(self.last_login_method,
|
|
182
|
+
self.last_login_params)
|
|
183
|
+
else:
|
|
184
|
+
raise xmlrpclib.Fault(401, 'You must log in')
|
|
185
|
+
else:
|
|
186
|
+
return result
|
|
187
|
+
raise xmlrpclib.Fault(
|
|
188
|
+
500, 'Tried 3 times to get a valid session, but failed')
|
|
189
|
+
|
|
190
|
+
def _login(self, method, params):
|
|
191
|
+
try:
|
|
192
|
+
result = _parse_result(
|
|
193
|
+
getattr(self, 'session.%s' % method)(*params))
|
|
194
|
+
if result is _RECONNECT_AND_RETRY:
|
|
195
|
+
raise xmlrpclib.Fault(
|
|
196
|
+
500, 'Received SESSION_INVALID when logging in')
|
|
197
|
+
self._session = result
|
|
198
|
+
self.last_login_method = method
|
|
199
|
+
self.last_login_params = params
|
|
200
|
+
|
|
201
|
+
# This was initialized to 1.1 in the constructor.
|
|
202
|
+
# Now that we are logged in, the next time API_version() is run
|
|
203
|
+
# it can fetch the real version.
|
|
204
|
+
# However nothing in this script actually needs that, so don't call it immediately.
|
|
205
|
+
self._API_version = None
|
|
206
|
+
except socket.error as e:
|
|
207
|
+
# pytype false positive: there is a socket.errno in both py2 and py3
|
|
208
|
+
if e.errno == socket.errno.ETIMEDOUT: # pytype: disable=module-attr
|
|
209
|
+
raise xmlrpclib.Fault(504, 'The connection timed out')
|
|
210
|
+
raise e
|
|
211
|
+
|
|
212
|
+
def _logout(self):
|
|
213
|
+
try:
|
|
214
|
+
if self.last_login_method.startswith("slave_local"):
|
|
215
|
+
# Proxied function, pytype can't see it
|
|
216
|
+
# pytype: disable=attribute-error
|
|
217
|
+
return _parse_result(self.session.local_logout(self._session))
|
|
218
|
+
# pytype: enable=attribute-error
|
|
219
|
+
else:
|
|
220
|
+
return _parse_result(self.session.logout(self._session))
|
|
221
|
+
finally:
|
|
222
|
+
self._session = None
|
|
223
|
+
self.last_login_method = None
|
|
224
|
+
self.last_login_params = None
|
|
225
|
+
self._API_version = API_VERSION_1_1
|
|
226
|
+
|
|
227
|
+
def _get_api_version(self):
|
|
228
|
+
pool = self.xenapi.pool.get_all()[0]
|
|
229
|
+
host = self.xenapi.pool.get_master(pool)
|
|
230
|
+
major = self.xenapi.host.get_API_version_major(host)
|
|
231
|
+
minor = self.xenapi.host.get_API_version_minor(host)
|
|
232
|
+
return "%s.%s"%(major,minor)
|
|
233
|
+
|
|
234
|
+
@property
|
|
235
|
+
def API_version(self):
|
|
236
|
+
if not self._API_version:
|
|
237
|
+
self._API_version = self._get_api_version()
|
|
238
|
+
return self._API_version
|
|
239
|
+
|
|
240
|
+
def __getattr__(self, name):
|
|
241
|
+
if name == 'handle':
|
|
242
|
+
return self._session
|
|
243
|
+
elif name == 'xenapi':
|
|
244
|
+
return _Dispatcher(self.xenapi_request, None)
|
|
245
|
+
elif name.startswith('login') or name.startswith('slave_local'):
|
|
246
|
+
return lambda *params: self._login(name, params)
|
|
247
|
+
elif name == 'logout':
|
|
248
|
+
return _Dispatcher(self.xenapi_request, "logout")
|
|
249
|
+
elif name.startswith('__') and name.endswith('__'):
|
|
250
|
+
return lambda *args, **kwargs: notimplemented(name, args, kwargs)
|
|
251
|
+
else:
|
|
252
|
+
return xmlrpclib.ServerProxy.__getattr__(self, name)
|
|
253
|
+
|
|
254
|
+
def xapi_local():
|
|
255
|
+
return Session("http://_var_lib_xcp_xapi/", transport=UDSTransport())
|
|
256
|
+
|
|
257
|
+
def _parse_result(result):
|
|
258
|
+
if type(result) != dict or 'Status' not in result:
|
|
259
|
+
raise xmlrpclib.Fault(500, 'Missing Status in response from server' + result)
|
|
260
|
+
if result['Status'] == 'Success':
|
|
261
|
+
if 'Value' in result:
|
|
262
|
+
return result['Value']
|
|
263
|
+
else:
|
|
264
|
+
raise xmlrpclib.Fault(500,
|
|
265
|
+
'Missing Value in response from server')
|
|
266
|
+
else:
|
|
267
|
+
if 'ErrorDescription' in result:
|
|
268
|
+
if result['ErrorDescription'][0] == 'SESSION_INVALID':
|
|
269
|
+
return _RECONNECT_AND_RETRY
|
|
270
|
+
else:
|
|
271
|
+
raise Failure(result['ErrorDescription'])
|
|
272
|
+
else:
|
|
273
|
+
raise xmlrpclib.Fault(
|
|
274
|
+
500, 'Missing ErrorDescription in response from server')
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
# Based upon _Method from xmlrpclib.
|
|
278
|
+
class _Dispatcher:
|
|
279
|
+
def __init__(self, send, name):
|
|
280
|
+
self.__send = send
|
|
281
|
+
self.__name = name
|
|
282
|
+
|
|
283
|
+
def __repr__(self):
|
|
284
|
+
if self.__name:
|
|
285
|
+
return '<XenAPI._Dispatcher for %s>' % self.__name
|
|
286
|
+
else:
|
|
287
|
+
return '<XenAPI._Dispatcher>'
|
|
288
|
+
|
|
289
|
+
def __getattr__(self, name):
|
|
290
|
+
if self.__name is None:
|
|
291
|
+
return _Dispatcher(self.__send, name)
|
|
292
|
+
else:
|
|
293
|
+
return _Dispatcher(self.__send, "%s.%s" % (self.__name, name))
|
|
294
|
+
|
|
295
|
+
def __call__(self, *args):
|
|
296
|
+
return self.__send(self.__name, args)
|
XenAPI/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .XenAPI import *
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: XenAPI
|
|
3
|
+
Version: 24.27.0
|
|
4
|
+
Summary: XenAPI SDK, for communication with XenServer.
|
|
5
|
+
Home-page: https://xapi-project.github.io/
|
|
6
|
+
Author: Xapi project developers and maintainers
|
|
7
|
+
Author-email: xen-api@lists.xenproject.org
|
|
8
|
+
License: BSD-2-Clause
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/xapi-project/xen-api/issues
|
|
10
|
+
Project-URL: Source Code, https://github.com/xapi-project/xen-api
|
|
11
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
12
|
+
Classifier: Development Status :: 6 - Mature
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Topic :: System :: Systems Administration
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: <4,>=3.6
|
|
17
|
+
Description-Content-Type: text/markdown; charset=UTF-8
|
|
18
|
+
|
|
19
|
+
Usage
|
|
20
|
+
=====
|
|
21
|
+
|
|
22
|
+
To install the package, enable the virtual environment where it's going to be used and run
|
|
23
|
+
`$ pip install XenAPI`
|
|
24
|
+
|
|
25
|
+
Examples
|
|
26
|
+
--------
|
|
27
|
+
|
|
28
|
+
The [examples](https://github.com/xapi-project/xen-api/tree/master/scripts/examples/python) will not work unless they have been placed in the same directory as `XenAPI.py` or `XenAPI` package from PyPI has been installed (`pip install XenAPI`)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
XenAPI/XenAPI.py,sha256=JtJGwrExHK9X5VVtO1rrqzP1i50EbtcO6R3VwD4CubQ,11644
|
|
2
|
+
XenAPI/__init__.py,sha256=58DJ3PHe4tbq6UHWUPAjRMxmNxeBgT_oHns_74jUDYs,22
|
|
3
|
+
XenAPI-24.27.0.dist-info/METADATA,sha256=J56ENOWdpGMA26PmlSSQDa56O_bxzImvajrkqQqCcRg,1142
|
|
4
|
+
XenAPI-24.27.0.dist-info/WHEEL,sha256=uCRv0ZEik_232NlR4YDw4Pv3Ajt5bKvMH13NUU7hFuI,91
|
|
5
|
+
XenAPI-24.27.0.dist-info/top_level.txt,sha256=tvxbFet2eYhQ7TC6hcBSV9ow0ymHuRsIM1I5Je6qmlE,7
|
|
6
|
+
XenAPI-24.27.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
XenAPI
|