XenAPI 1.2__tar.gz → 23.8.0__tar.gz
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-23.8.0/Makefile +12 -0
- XenAPI-23.8.0/PKG-INFO +37 -0
- XenAPI-23.8.0/README.md +19 -0
- {XenAPI-1.2 → XenAPI-23.8.0/XenAPI}/XenAPI.py +79 -48
- XenAPI-23.8.0/XenAPI/__init__.py +1 -0
- XenAPI-23.8.0/XenAPI.egg-info/PKG-INFO +37 -0
- XenAPI-23.8.0/XenAPI.egg-info/SOURCES.txt +21 -0
- XenAPI-23.8.0/XenAPIPlugin.py +54 -0
- XenAPI-23.8.0/echo.py +15 -0
- XenAPI-23.8.0/exportimport.py +142 -0
- XenAPI-23.8.0/inventory.py +32 -0
- XenAPI-23.8.0/lvhd-api-test.py +29 -0
- XenAPI-23.8.0/mini-xenrt.py +142 -0
- XenAPI-23.8.0/monitor-unwanted-domains.py +89 -0
- XenAPI-23.8.0/provision.py +111 -0
- XenAPI-23.8.0/pyproject.toml +6 -0
- XenAPI-23.8.0/renameif.py +169 -0
- XenAPI-23.8.0/setup.cfg +30 -0
- XenAPI-23.8.0/shell.py +118 -0
- XenAPI-23.8.0/xva.py +117 -0
- XenAPI-1.2/PKG-INFO +0 -13
- XenAPI-1.2/README +0 -7
- XenAPI-1.2/XenAPI.egg-info/PKG-INFO +0 -13
- XenAPI-1.2/XenAPI.egg-info/SOURCES.txt +0 -7
- XenAPI-1.2/setup.cfg +0 -5
- XenAPI-1.2/setup.py +0 -15
- {XenAPI-1.2 → XenAPI-23.8.0}/XenAPI.egg-info/dependency_links.txt +0 -0
- {XenAPI-1.2 → XenAPI-23.8.0}/XenAPI.egg-info/top_level.txt +0 -0
XenAPI-23.8.0/Makefile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
PROFILE=release
|
|
2
|
+
SETUPTOOLS_SCM_PRETEND_VERSION ?= ""
|
|
3
|
+
|
|
4
|
+
.PHONY: build clean
|
|
5
|
+
|
|
6
|
+
build:
|
|
7
|
+
SETUPTOOLS_SCM_PRETEND_VERSION=$(XAPI_VERSION) python -m build --wheel .
|
|
8
|
+
SETUPTOOLS_SCM_PRETEND_VERSION=$(XAPI_VERSION) python -m build --sdist .
|
|
9
|
+
|
|
10
|
+
clean:
|
|
11
|
+
dune clean
|
|
12
|
+
rm -rf dist/ build/ XenAPI.egg-info/
|
XenAPI-23.8.0/PKG-INFO
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: XenAPI
|
|
3
|
+
Version: 23.8.0
|
|
4
|
+
Summary: XenAPI SDK, for communication with XenServer.
|
|
5
|
+
Home-page: https://www.citrix.com/community/citrix-developer/citrix-hypervisor-developer/
|
|
6
|
+
Author: Citrix Systems, Inc.
|
|
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: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,<4,>=2.7
|
|
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`)
|
|
29
|
+
|
|
30
|
+
Packaging
|
|
31
|
+
=========
|
|
32
|
+
|
|
33
|
+
`setup.py` is generated using an ocaml binary that fetches the api version string from xapi. An opam switch with the [xs-opam](https://github.com/xapi-project/xs-opam) repository is needed in order to build the binary.
|
|
34
|
+
|
|
35
|
+
To build the package `setuptools>=38.6.0` and `wheel` need to be installed in the system or in the active python virtualenv.
|
|
36
|
+
|
|
37
|
+
To build, use the command `make`.
|
XenAPI-23.8.0/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Usage
|
|
2
|
+
=====
|
|
3
|
+
|
|
4
|
+
To install the package, enable the virtual environment where it's going to be used and run
|
|
5
|
+
`$ pip install XenAPI`
|
|
6
|
+
|
|
7
|
+
Examples
|
|
8
|
+
--------
|
|
9
|
+
|
|
10
|
+
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`)
|
|
11
|
+
|
|
12
|
+
Packaging
|
|
13
|
+
=========
|
|
14
|
+
|
|
15
|
+
`setup.py` is generated using an ocaml binary that fetches the api version string from xapi. An opam switch with the [xs-opam](https://github.com/xapi-project/xs-opam) repository is needed in order to build the binary.
|
|
16
|
+
|
|
17
|
+
To build the package `setuptools>=38.6.0` and `wheel` need to be installed in the system or in the active python virtualenv.
|
|
18
|
+
|
|
19
|
+
To build, use the command `make`.
|
|
@@ -1,20 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
#
|
|
3
|
-
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
|
4
|
-
# License as published by the Free Software Foundation.
|
|
1
|
+
# Copyright (c) Citrix Systems, Inc.
|
|
2
|
+
# All rights reserved.
|
|
5
3
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# Lesser General Public License for more details.
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions are
|
|
6
|
+
# met:
|
|
10
7
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
14
|
-
#============================================================================
|
|
15
|
-
# Copyright (C) 2006-2007 XenSource Inc.
|
|
16
|
-
#============================================================================
|
|
8
|
+
# 1) Redistributions of source code must retain the above copyright
|
|
9
|
+
# notice, this list of conditions and the following disclaimer.
|
|
17
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
|
+
# --------------------------------------------------------------------
|
|
18
28
|
# Parts of this file are based upon xmlrpclib.py, the XML-RPC client
|
|
19
29
|
# interface included in the Python distribution.
|
|
20
30
|
#
|
|
@@ -45,9 +55,16 @@
|
|
|
45
55
|
# --------------------------------------------------------------------
|
|
46
56
|
|
|
47
57
|
import gettext
|
|
48
|
-
import xmlrpclib
|
|
49
|
-
import httplib
|
|
50
58
|
import socket
|
|
59
|
+
import sys
|
|
60
|
+
|
|
61
|
+
if sys.version_info[0] == 2:
|
|
62
|
+
import httplib as httplib
|
|
63
|
+
import xmlrpclib as xmlrpclib
|
|
64
|
+
else:
|
|
65
|
+
import http.client as httplib
|
|
66
|
+
import xmlrpc.client as xmlrpclib
|
|
67
|
+
|
|
51
68
|
|
|
52
69
|
translation = gettext.translation('xen-xm', fallback = True)
|
|
53
70
|
|
|
@@ -61,17 +78,18 @@ class Failure(Exception):
|
|
|
61
78
|
def __str__(self):
|
|
62
79
|
try:
|
|
63
80
|
return str(self.details)
|
|
64
|
-
except Exception
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return
|
|
81
|
+
except Exception as exn:
|
|
82
|
+
msg = "Xen-API failure: %s" % exn
|
|
83
|
+
sys.stderr.write(msg)
|
|
84
|
+
return msg
|
|
68
85
|
|
|
69
86
|
def _details_map(self):
|
|
70
87
|
return dict([(str(i), self.details[i])
|
|
71
88
|
for i in range(len(self.details))])
|
|
72
89
|
|
|
73
90
|
|
|
74
|
-
|
|
91
|
+
# Just a "constant" that we use to decide whether to retry the RPC
|
|
92
|
+
_RECONNECT_AND_RETRY = object()
|
|
75
93
|
|
|
76
94
|
class UDSHTTPConnection(httplib.HTTPConnection):
|
|
77
95
|
"""HTTPConnection subclass to allow HTTP over Unix domain sockets. """
|
|
@@ -80,22 +98,15 @@ class UDSHTTPConnection(httplib.HTTPConnection):
|
|
|
80
98
|
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
81
99
|
self.sock.connect(path)
|
|
82
100
|
|
|
83
|
-
class UDSHTTP(httplib.HTTP):
|
|
84
|
-
_connection_class = UDSHTTPConnection
|
|
85
|
-
|
|
86
101
|
class UDSTransport(xmlrpclib.Transport):
|
|
87
|
-
def __init__(self, use_datetime=0):
|
|
88
|
-
self._use_datetime = use_datetime
|
|
89
|
-
self._extra_headers=[]
|
|
90
102
|
def add_extra_header(self, key, value):
|
|
91
103
|
self._extra_headers += [ (key,value) ]
|
|
92
104
|
def make_connection(self, host):
|
|
93
|
-
return
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
105
|
+
return UDSHTTPConnection(host)
|
|
106
|
+
|
|
107
|
+
def notimplemented(name, *args, **kwargs):
|
|
108
|
+
raise NotImplementedError("XMLRPC proxies do not support python magic methods", name, *args, **kwargs)
|
|
109
|
+
|
|
99
110
|
class Session(xmlrpclib.ServerProxy):
|
|
100
111
|
"""A server proxy and session manager for communicating with xapi using
|
|
101
112
|
the Xen-API.
|
|
@@ -103,15 +114,25 @@ class Session(xmlrpclib.ServerProxy):
|
|
|
103
114
|
Example:
|
|
104
115
|
|
|
105
116
|
session = Session('http://localhost/')
|
|
106
|
-
session.login_with_password('me', 'mypassword')
|
|
117
|
+
session.login_with_password('me', 'mypassword', '1.0', 'xen-api-scripts-xenapi.py')
|
|
107
118
|
session.xenapi.VM.start(vm_uuid)
|
|
108
119
|
session.xenapi.session.logout()
|
|
109
120
|
"""
|
|
110
121
|
|
|
111
122
|
def __init__(self, uri, transport=None, encoding=None, verbose=0,
|
|
112
|
-
allow_none=1):
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
allow_none=1, ignore_ssl=False):
|
|
124
|
+
|
|
125
|
+
# Fix for CA-172901 (+ Python 2.4 compatibility)
|
|
126
|
+
# Fix for context=ctx ( < Python 2.7.9 compatibility)
|
|
127
|
+
if not (sys.version_info[0] <= 2 and sys.version_info[1] <= 7 and sys.version_info[2] <= 9 ) \
|
|
128
|
+
and ignore_ssl:
|
|
129
|
+
import ssl
|
|
130
|
+
ctx = ssl._create_unverified_context()
|
|
131
|
+
xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
|
|
132
|
+
verbose, allow_none, context=ctx)
|
|
133
|
+
else:
|
|
134
|
+
xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
|
|
135
|
+
verbose, allow_none)
|
|
115
136
|
self.transport = transport
|
|
116
137
|
self._session = None
|
|
117
138
|
self.last_login_method = None
|
|
@@ -131,7 +152,7 @@ class Session(xmlrpclib.ServerProxy):
|
|
|
131
152
|
while retry_count < 3:
|
|
132
153
|
full_params = (self._session,) + params
|
|
133
154
|
result = _parse_result(getattr(self, methodname)(*full_params))
|
|
134
|
-
if result
|
|
155
|
+
if result is _RECONNECT_AND_RETRY:
|
|
135
156
|
retry_count += 1
|
|
136
157
|
if self.last_login_method:
|
|
137
158
|
self._login(self.last_login_method,
|
|
@@ -143,16 +164,22 @@ class Session(xmlrpclib.ServerProxy):
|
|
|
143
164
|
raise xmlrpclib.Fault(
|
|
144
165
|
500, 'Tried 3 times to get a valid session, but failed')
|
|
145
166
|
|
|
146
|
-
|
|
147
167
|
def _login(self, method, params):
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
168
|
+
try:
|
|
169
|
+
result = _parse_result(
|
|
170
|
+
getattr(self, 'session.%s' % method)(*params))
|
|
171
|
+
if result is _RECONNECT_AND_RETRY:
|
|
172
|
+
raise xmlrpclib.Fault(
|
|
173
|
+
500, 'Received SESSION_INVALID when logging in')
|
|
174
|
+
self._session = result
|
|
175
|
+
self.last_login_method = method
|
|
176
|
+
self.last_login_params = params
|
|
177
|
+
self.API_version = self._get_api_version()
|
|
178
|
+
except socket.error as e:
|
|
179
|
+
if e.errno == socket.errno.ETIMEDOUT:
|
|
180
|
+
raise xmlrpclib.Fault(504, 'The connection timed out')
|
|
181
|
+
else:
|
|
182
|
+
raise e
|
|
156
183
|
|
|
157
184
|
def _logout(self):
|
|
158
185
|
try:
|
|
@@ -180,11 +207,15 @@ class Session(xmlrpclib.ServerProxy):
|
|
|
180
207
|
return _Dispatcher(self.API_version, self.xenapi_request, None)
|
|
181
208
|
elif name.startswith('login') or name.startswith('slave_local'):
|
|
182
209
|
return lambda *params: self._login(name, params)
|
|
210
|
+
elif name == 'logout':
|
|
211
|
+
return _Dispatcher(self.API_version, self.xenapi_request, "logout")
|
|
212
|
+
elif name.startswith('__') and name.endswith('__'):
|
|
213
|
+
return lambda *args, **kwargs: notimplemented(name, args, kwargs)
|
|
183
214
|
else:
|
|
184
215
|
return xmlrpclib.ServerProxy.__getattr__(self, name)
|
|
185
216
|
|
|
186
217
|
def xapi_local():
|
|
187
|
-
return Session("http://
|
|
218
|
+
return Session("http://_var_lib_xcp_xapi/", transport=UDSTransport())
|
|
188
219
|
|
|
189
220
|
def _parse_result(result):
|
|
190
221
|
if type(result) != dict or 'Status' not in result:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .XenAPI import *
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: XenAPI
|
|
3
|
+
Version: 23.8.0
|
|
4
|
+
Summary: XenAPI SDK, for communication with XenServer.
|
|
5
|
+
Home-page: https://www.citrix.com/community/citrix-developer/citrix-hypervisor-developer/
|
|
6
|
+
Author: Citrix Systems, Inc.
|
|
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: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,<4,>=2.7
|
|
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`)
|
|
29
|
+
|
|
30
|
+
Packaging
|
|
31
|
+
=========
|
|
32
|
+
|
|
33
|
+
`setup.py` is generated using an ocaml binary that fetches the api version string from xapi. An opam switch with the [xs-opam](https://github.com/xapi-project/xs-opam) repository is needed in order to build the binary.
|
|
34
|
+
|
|
35
|
+
To build the package `setuptools>=38.6.0` and `wheel` need to be installed in the system or in the active python virtualenv.
|
|
36
|
+
|
|
37
|
+
To build, use the command `make`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Makefile
|
|
2
|
+
README.md
|
|
3
|
+
XenAPIPlugin.py
|
|
4
|
+
echo.py
|
|
5
|
+
exportimport.py
|
|
6
|
+
inventory.py
|
|
7
|
+
lvhd-api-test.py
|
|
8
|
+
mini-xenrt.py
|
|
9
|
+
monitor-unwanted-domains.py
|
|
10
|
+
provision.py
|
|
11
|
+
pyproject.toml
|
|
12
|
+
renameif.py
|
|
13
|
+
setup.cfg
|
|
14
|
+
shell.py
|
|
15
|
+
xva.py
|
|
16
|
+
XenAPI/XenAPI.py
|
|
17
|
+
XenAPI/__init__.py
|
|
18
|
+
XenAPI.egg-info/PKG-INFO
|
|
19
|
+
XenAPI.egg-info/SOURCES.txt
|
|
20
|
+
XenAPI.egg-info/dependency_links.txt
|
|
21
|
+
XenAPI.egg-info/top_level.txt
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
|
|
3
|
+
# XenAPI python plugin boilerplate code
|
|
4
|
+
|
|
5
|
+
from __future__ import print_function
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
import XenAPI
|
|
10
|
+
|
|
11
|
+
if sys.version_info[0] == 2:
|
|
12
|
+
import xmlrpclib as xmlrpclib
|
|
13
|
+
else:
|
|
14
|
+
import xmlrpc.client as xmlrpclib
|
|
15
|
+
|
|
16
|
+
class Failure(Exception):
|
|
17
|
+
"""Provide compatibilty with plugins written against XenServer 5.5 API"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, code, params):
|
|
20
|
+
Exception.__init__(self)
|
|
21
|
+
self.params = [ code ] + params
|
|
22
|
+
def __str__(self):
|
|
23
|
+
return str(self.params)
|
|
24
|
+
|
|
25
|
+
def success_message(result):
|
|
26
|
+
rpcparams = { 'Status': 'Success', 'Value': result }
|
|
27
|
+
return xmlrpclib.dumps((rpcparams, ), '', True)
|
|
28
|
+
|
|
29
|
+
def failure_message(description):
|
|
30
|
+
rpcparams = { 'Status': 'Failure', 'ErrorDescription': description }
|
|
31
|
+
return xmlrpclib.dumps((rpcparams, ), '', True)
|
|
32
|
+
|
|
33
|
+
def dispatch(fn_table):
|
|
34
|
+
if len(sys.argv) != 2:
|
|
35
|
+
raise Exception("Incorrect number of commandline arguments")
|
|
36
|
+
params, methodname = xmlrpclib.loads(sys.argv[1])
|
|
37
|
+
session_id = params[0]
|
|
38
|
+
args = params[1]
|
|
39
|
+
if methodname in fn_table:
|
|
40
|
+
x = XenAPI.xapi_local()
|
|
41
|
+
x._session = session_id
|
|
42
|
+
try:
|
|
43
|
+
result = fn_table[methodname](x, args)
|
|
44
|
+
print(success_message(result))
|
|
45
|
+
except SystemExit:
|
|
46
|
+
# SystemExit should not be caught, as it is handled elsewhere in the plugin system.
|
|
47
|
+
raise
|
|
48
|
+
except Failure as e:
|
|
49
|
+
print(failure_message(e.params))
|
|
50
|
+
except Exception as e:
|
|
51
|
+
print(failure_message(['XENAPI_PLUGIN_FAILURE',
|
|
52
|
+
methodname, e.__class__.__name__, str(e)]))
|
|
53
|
+
else:
|
|
54
|
+
print(failure_message(['UNKNOWN_XENAPI_PLUGIN_FUNCTION', methodname]))
|
XenAPI-23.8.0/echo.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# Simple XenAPI plugin
|
|
4
|
+
import XenAPIPlugin, time
|
|
5
|
+
|
|
6
|
+
def main(session, args):
|
|
7
|
+
if "sleep" in args:
|
|
8
|
+
secs = int(args["sleep"])
|
|
9
|
+
time.sleep(secs)
|
|
10
|
+
return "args were: %s" % (repr(args))
|
|
11
|
+
|
|
12
|
+
if __name__ == "__main__":
|
|
13
|
+
XenAPIPlugin.dispatch({"main": main})
|
|
14
|
+
|
|
15
|
+
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2014 Citrix, Inc.
|
|
4
|
+
#
|
|
5
|
+
# Permission to use, copy, modify, and distribute this software for any
|
|
6
|
+
# purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
# copyright notice and this permission notice appear in all copies.
|
|
8
|
+
#
|
|
9
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
|
|
17
|
+
# Demonstrate how to
|
|
18
|
+
# - export raw disk images
|
|
19
|
+
# - import raw disk images
|
|
20
|
+
# - connect an export to an import to copy a raw disk image
|
|
21
|
+
|
|
22
|
+
from __future__ import print_function
|
|
23
|
+
import sys, os, socket, urllib2, urlparse, XenAPI, traceback, ssl, time
|
|
24
|
+
|
|
25
|
+
def exportimport(url, xapi, session, src_vdi, dst_vdi):
|
|
26
|
+
# If an HTTP operation fails then it will record the error on the task
|
|
27
|
+
# object. Note you can't use the HTTP response code for this because
|
|
28
|
+
# it must be sent *before* the stream is processed.
|
|
29
|
+
import_task = xapi.xenapi.task.create("import " + dst_vdi, "")
|
|
30
|
+
export_task = xapi.xenapi.task.create("export " + src_vdi, "")
|
|
31
|
+
try:
|
|
32
|
+
# an HTTP GET of this will export a disk:
|
|
33
|
+
get_url = "/export_raw_vdi?session_id=%s&vdi=%s&task_id=%s" % (session, src_vdi, export_task)
|
|
34
|
+
# an HTTP PUT to this will import a disk:
|
|
35
|
+
put_url = "/import_raw_vdi?session_id=%s&vdi=%s&task_id=%s" % (session, dst_vdi, import_task)
|
|
36
|
+
|
|
37
|
+
# 'data' is the stream of raw data:
|
|
38
|
+
data = urllib2.urlopen(url + get_url)
|
|
39
|
+
|
|
40
|
+
# python's builtin library doesn't support HTTP PUT very well
|
|
41
|
+
# so we do it manually. Note xapi doesn't support Transfer-encoding:
|
|
42
|
+
# chunked so we must send the data raw.
|
|
43
|
+
url = urlparse.urlparse(url)
|
|
44
|
+
host = url.netloc.split(":")[0] # assume port 443
|
|
45
|
+
if url.scheme != "https":
|
|
46
|
+
print("Sorry, this example only supports HTTPS (not HTTP)", file=sys.stderr)
|
|
47
|
+
print("Plaintext HTTP has the following problems:", file=sys.stderr)
|
|
48
|
+
print(" - the data can be captured by other programs on the network", file=sys.stderr)
|
|
49
|
+
print(" - some network middleboxes will mangle the data", file=sys.stderr)
|
|
50
|
+
# time wasted debugging a problem caused by a middlebox: 3hrs
|
|
51
|
+
# Just use HTTPS!
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
55
|
+
output = ssl.wrap_socket(s)
|
|
56
|
+
output.connect((host, 443))
|
|
57
|
+
|
|
58
|
+
# HTTP/1.0 with no transfer-encoding
|
|
59
|
+
headers = [
|
|
60
|
+
"PUT %s HTTP/1.0" % put_url,
|
|
61
|
+
"Connection:close",
|
|
62
|
+
""
|
|
63
|
+
]
|
|
64
|
+
print("Sending HTTP request:")
|
|
65
|
+
for h in headers:
|
|
66
|
+
output.send("%s\r\n" % h)
|
|
67
|
+
print("%s\r\n" % h)
|
|
68
|
+
result = output.recv(1024)
|
|
69
|
+
print("Received HTTP response:")
|
|
70
|
+
print(result)
|
|
71
|
+
if "200 OK" not in result:
|
|
72
|
+
print("Expected an HTTP 200, got %s" % result, file=sys.stderr)
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
# Copy the raw bytes, signal completion by closing the socket
|
|
76
|
+
virtual_size = long(xapi.xenapi.VDI.get_virtual_size(src_vdi))
|
|
77
|
+
print("Copying %Ld bytes" % virtual_size)
|
|
78
|
+
left = virtual_size
|
|
79
|
+
while left > 0:
|
|
80
|
+
block = data.read(min(65536, left))
|
|
81
|
+
if block is None:
|
|
82
|
+
break
|
|
83
|
+
output.send(block)
|
|
84
|
+
left = left - len(block)
|
|
85
|
+
output.close()
|
|
86
|
+
|
|
87
|
+
# Wait for the tasks to complete and check whether they both
|
|
88
|
+
# succeeded. It takes a few seconds to detach the disk etc.
|
|
89
|
+
finished = False
|
|
90
|
+
while not finished:
|
|
91
|
+
import_status = xapi.xenapi.task.get_status(import_task)
|
|
92
|
+
export_status = xapi.xenapi.task.get_status(export_task)
|
|
93
|
+
finished = import_status != "pending" and export_task != "pending"
|
|
94
|
+
time.sleep(1)
|
|
95
|
+
if import_status == "success" and export_status == "success":
|
|
96
|
+
print("OK")
|
|
97
|
+
else:
|
|
98
|
+
print("FAILED")
|
|
99
|
+
if import_status != "success":
|
|
100
|
+
print("The import task failed with: ", " ".join(xapi.xenapi.task.get_error_info(import_task)))
|
|
101
|
+
if export_status != "success":
|
|
102
|
+
print("The export task failed with: ", " ".join(xapi.xenapi.task.get_error_info(export_task)))
|
|
103
|
+
|
|
104
|
+
finally:
|
|
105
|
+
# The task creator has to destroy them at the end:
|
|
106
|
+
xapi.xenapi.task.destroy(import_task)
|
|
107
|
+
xapi.xenapi.task.destroy(export_task)
|
|
108
|
+
|
|
109
|
+
if __name__ == "__main__":
|
|
110
|
+
if len(sys.argv) != 5:
|
|
111
|
+
print("Usage:")
|
|
112
|
+
print(sys.argv[0], " <url> <username> <password> <vdi-uuid>")
|
|
113
|
+
print(" -- creates a fresh VDI and streams the contents of <vdi-uuid> into it.")
|
|
114
|
+
print()
|
|
115
|
+
print("Example:")
|
|
116
|
+
print("SR=$(xe pool-list params=default-SR --minimal)")
|
|
117
|
+
print("VDI=$(xe vdi-create sr-uuid=$SR name-label=test virtual-size=128MiB type=user)")
|
|
118
|
+
print(sys.argv[0], "https://localhost password $VDI")
|
|
119
|
+
sys.exit(1)
|
|
120
|
+
url = sys.argv[1]
|
|
121
|
+
username = sys.argv[2]
|
|
122
|
+
password = sys.argv[3]
|
|
123
|
+
vdi_uuid = sys.argv[4]
|
|
124
|
+
# First acquire a valid session by logging in:
|
|
125
|
+
xapi = XenAPI.Session(url)
|
|
126
|
+
xapi.xenapi.login_with_password(username, password, '1.0', 'xen-api-scripts-exportimport.py')
|
|
127
|
+
dst_vdi = None
|
|
128
|
+
try:
|
|
129
|
+
src_vdi = xapi.xenapi.VDI.get_by_uuid(vdi_uuid)
|
|
130
|
+
sr = xapi.xenapi.VDI.get_SR(src_vdi)
|
|
131
|
+
# Create an empty VDI with the same initial parameters (e.g. size)
|
|
132
|
+
# to upload into
|
|
133
|
+
vdi_args = xapi.xenapi.VDI.get_record(src_vdi)
|
|
134
|
+
dst_vdi = xapi.xenapi.VDI.create(vdi_args)
|
|
135
|
+
exportimport(url, xapi, xapi._session, src_vdi, dst_vdi)
|
|
136
|
+
except Exception as e:
|
|
137
|
+
print("Caught %s: trying to clean up" % str(e))
|
|
138
|
+
traceback.print_exc()
|
|
139
|
+
if dst_vdi:
|
|
140
|
+
xapi.xenapi.VDI.destroy(dst_vdi)
|
|
141
|
+
finally:
|
|
142
|
+
xapi.xenapi.logout()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Simple functions to read the constants from the xensource-inventory file
|
|
2
|
+
|
|
3
|
+
INVENTORY="@INVENTORY@"
|
|
4
|
+
INSTALLATION_UUID="INSTALLATION_UUID"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def read_kvpairs(filename):
|
|
8
|
+
"""Read in a file of key-value pairs in the format used by the inventory file"""
|
|
9
|
+
f = open(filename)
|
|
10
|
+
all_entries = {}
|
|
11
|
+
try:
|
|
12
|
+
for line in f.readlines():
|
|
13
|
+
equals = line.index("=")
|
|
14
|
+
key = line[0:equals]
|
|
15
|
+
value = line[equals+1:].strip().strip("'")
|
|
16
|
+
all_entries[key] = value
|
|
17
|
+
finally:
|
|
18
|
+
f.close()
|
|
19
|
+
return all_entries
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def parse():
|
|
23
|
+
"""Return the contents of the xensource inventory file as a dictionary"""
|
|
24
|
+
try:
|
|
25
|
+
return read_kvpairs(INVENTORY)
|
|
26
|
+
except:
|
|
27
|
+
return {}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_localhost_uuid():
|
|
31
|
+
"""Return the UUID of the local host"""
|
|
32
|
+
return parse()[INSTALLATION_UUID]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from __future__ import print_function
|
|
4
|
+
import XenAPI, sys
|
|
5
|
+
|
|
6
|
+
def go(x, name):
|
|
7
|
+
vm = x.xenapi.VM.get_by_name_label(name)[0]
|
|
8
|
+
vbds = x.xenapi.VM.get_VBDs(vm)
|
|
9
|
+
non_empty = filter(lambda y:not(x.xenapi.VBD.get_empty(y)), vbds)
|
|
10
|
+
vdis = map(lambda y:x.xenapi.VBD.get_VDI(y), non_empty)
|
|
11
|
+
|
|
12
|
+
print("Calling API call on %s" % (repr(vdis)))
|
|
13
|
+
result = x.xenapi.SR.lvhd_stop_using_these_vdis_and_call_script(vdis, "echo", "main", { "hello": "there", "sleep": "10" })
|
|
14
|
+
print(repr(result))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
if len(sys.argv) != 2:
|
|
19
|
+
print("Usage:", file=sys.stderr)
|
|
20
|
+
print(" %s <VM name-label>" % (sys.argv[0]), file=sys.stderr)
|
|
21
|
+
print(" -- Call SR.lvhd_stop_using_these_vdis_and_call_script with all VDIs with VBDs (attached or not) linking to specified VM", file=sys.stderr)
|
|
22
|
+
sys.exit(1)
|
|
23
|
+
name = sys.argv[1]
|
|
24
|
+
x = XenAPI.xapi_local()
|
|
25
|
+
x.xenapi.login_with_password("root", "", "1.0", "xen-api-scripts-lvhd-api-test.py")
|
|
26
|
+
try:
|
|
27
|
+
go(x, name)
|
|
28
|
+
finally:
|
|
29
|
+
x.xenapi.logout()
|