XenAPI 2.14__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 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`.
@@ -7,7 +7,7 @@ To install the package, enable the virtual environment where it's going to be us
7
7
  Examples
8
8
  --------
9
9
 
10
- The examples now will not work unless they have been placed in the same directory as `XenAPI.py` or `XenAPI` package from PyPI has been installed (`pip installed XenAPI`)
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
11
 
12
12
  Packaging
13
13
  =========
@@ -55,11 +55,17 @@
55
55
  # --------------------------------------------------------------------
56
56
 
57
57
  import gettext
58
- import six.moves.xmlrpc_client as xmlrpclib
59
- import six.moves.http_client as httplib
60
58
  import socket
61
59
  import sys
62
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
+
68
+
63
69
  translation = gettext.translation('xen-xm', fallback = True)
64
70
 
65
71
  API_VERSION_1_1 = '1.1'
@@ -92,26 +98,14 @@ class UDSHTTPConnection(httplib.HTTPConnection):
92
98
  self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
93
99
  self.sock.connect(path)
94
100
 
95
- class UDSHTTP(httplib.HTTPConnection):
96
- _connection_class = UDSHTTPConnection
97
-
98
101
  class UDSTransport(xmlrpclib.Transport):
99
- def __init__(self, use_datetime=0):
100
- self._use_datetime = use_datetime
101
- self._extra_headers=[]
102
- self._connection = (None, None)
103
102
  def add_extra_header(self, key, value):
104
103
  self._extra_headers += [ (key,value) ]
105
104
  def make_connection(self, host):
106
- # Python 2.4 compatibility
107
- if sys.version_info[0] <= 2 and sys.version_info[1] < 7:
108
- return UDSHTTP(host)
109
- else:
110
- return UDSHTTPConnection(host)
111
- def send_request(self, connection, handler, request_body):
112
- connection.putrequest("POST", handler)
113
- for key, value in self._extra_headers:
114
- connection.putheader(key, value)
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)
115
109
 
116
110
  class Session(xmlrpclib.ServerProxy):
117
111
  """A server proxy and session manager for communicating with xapi using
@@ -215,6 +209,8 @@ class Session(xmlrpclib.ServerProxy):
215
209
  return lambda *params: self._login(name, params)
216
210
  elif name == 'logout':
217
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)
218
214
  else:
219
215
  return xmlrpclib.ServerProxy.__getattr__(self, name)
220
216
 
@@ -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()
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env python
2
+
3
+ # Receive multiple VMs
4
+ # Issue parallel loops of: reboot, suspend/resume, migrate
5
+
6
+ from __future__ import print_function
7
+ import xmlrpclib
8
+ from threading import Thread
9
+ import time, sys
10
+
11
+ iso8601 = "%Y%m%dT%H:%M:%SZ"
12
+
13
+ stop_on_first_failure = True
14
+ stop = False
15
+
16
+ class Operation:
17
+ def __init__(self):
18
+ raise "this is supposed to be abstract, dummy"
19
+ def execute(self, server, session_id):
20
+ raise "this is supposed to be abstract, dummy"
21
+
22
+ class Reboot(Operation):
23
+ def __init__(self, vm):
24
+ self.vm = vm
25
+ def execute(self, server, session_id):
26
+ return server.VM.clean_reboot(session_id, self.vm)
27
+ def __str__(self):
28
+ return "clean_reboot(%s)" % self.vm
29
+
30
+ class SuspendResume(Operation):
31
+ def __init__(self, vm):
32
+ self.vm = vm
33
+ def execute(self, server, session_id):
34
+ x = { "ErrorDescription": [ "VM_MISSING_PV_DRIVERS" ] }
35
+ while "ErrorDescription" in x and x["ErrorDescription"][0] == "VM_MISSING_PV_DRIVERS":
36
+ x = server.VM.suspend(session_id, self.vm)
37
+ if "ErrorDescription" in x:
38
+ time.sleep(1)
39
+ if x["Status"] != "Success":
40
+ return x
41
+ return server.VM.resume(session_id, self.vm, False, False)
42
+ def __str__(self):
43
+ return "suspendresume(%s)" % self.vm
44
+
45
+ class ShutdownStart(Operation):
46
+ def __init__(self, vm):
47
+ self.vm = vm
48
+ def execute(self, server, session_id):
49
+ x = server.VM.clean_shutdown(session_id, self.vm)
50
+ if x["Status"] != "Success":
51
+ return x
52
+ return server.VM.start(session_id, self.vm, False, False)
53
+ #return { "Status": "bad", "ErrorDescription": "foo" }
54
+ def __str__(self):
55
+ return "shutdownstart(%s)" % self.vm
56
+
57
+ class LocalhostMigrate(Operation):
58
+ def __init__(self, vm):
59
+ self.vm = vm
60
+ def execute(self, server, session_id):
61
+ return server.VM.pool_migrate(session_id, self.vm, server.VM.get_resident_on(session_id, self.vm)["Value"], { "live": "true" } )
62
+ def __str__(self):
63
+ return "localhostmigrate(%s)" % self.vm
64
+
65
+ # Use this to give each thread a different ID
66
+ worker_count = 0
67
+
68
+ class Worker(Thread):
69
+ def __init__(self, server, session_id, operations):
70
+ Thread.__init__(self)
71
+ self.server = server
72
+ self.session_id = session_id
73
+ self.operations = operations
74
+ self.num_successes = 0
75
+ self.num_failures = 0
76
+ global worker_count
77
+ self.id = worker_count
78
+ worker_count = worker_count + 1
79
+ def run(self):
80
+ global iso8601
81
+ global stop_on_first_failure, stop
82
+ for op in self.operations:
83
+ description = str(op)
84
+
85
+ if stop:
86
+ return
87
+
88
+ start = time.strftime(iso8601, time.gmtime(time.time ()))
89
+ result = op.execute(self.server, self.session_id)
90
+ end = time.strftime(iso8601, time.gmtime(time.time ()))
91
+
92
+ if result["Status"] == "Success":
93
+ print("SUCCESS %d %s %s %s" % (self.id, start, end, description))
94
+ self.num_successes = self.num_successes + 1
95
+ else:
96
+ error_descr = result["ErrorDescription"]
97
+ print("FAILURE %d %s %s %s %s" % (self.id, start, end, error_descr[0], description))
98
+ self.num_failures = self.num_failures + 1
99
+ if stop_on_first_failure:
100
+ stop = True
101
+
102
+ def make_operation_list(vm):
103
+ return [ Reboot(vm), SuspendResume(vm), LocalhostMigrate(vm) ] * 100
104
+
105
+ if __name__ == "__main__":
106
+ if len(sys.argv) != 3:
107
+ print("Usage:")
108
+ print(" %s <URL> <other-config key>" % (sys.argv[0]))
109
+ print(" -- performs parallel operations on VMs with the specified other-config key")
110
+ sys.exit(1)
111
+
112
+ x = xmlrpclib.Server(sys.argv[1])
113
+ key = sys.argv[2]
114
+ session = x.session.login_with_password("root", "xenroot", "1.0", "xen-api-scripts-minixenrt.py")["Value"]
115
+ vms = x.VM.get_all_records(session)["Value"]
116
+
117
+ workers = []
118
+ for vm in vms.keys():
119
+ if key in vms[vm]["other_config"]:
120
+ allowed_ops = vms[vm]["allowed_operations"]
121
+ for op in [ "clean_reboot", "suspend", "pool_migrate" ]:
122
+ if op not in allowed_ops:
123
+ raise "VM %s is not in a state where it can %s" % (vms[vm]["name_label"], op)
124
+ workers.append(Worker(x, session, make_operation_list(vm)))
125
+ for w in workers:
126
+ w.start()
127
+ for w in workers:
128
+ w.join()
129
+ successes = 0
130
+ failures = 0
131
+ for w in workers:
132
+ successes = successes + w.num_successes
133
+ failures = failures + w.num_failures
134
+ print("Total successes = %d" % successes)
135
+ print("Total failures = %d" % failures)
136
+ if failures == 0:
137
+ print("PASS")
138
+ sys.exit(0)
139
+ else:
140
+ print("FAIL")
141
+ sys.exit(1)
142
+