ia64/xen-unstable

view tools/python/xen/xm/XenAPI.py @ 13229:974fb31dcbe9

(temporarily) revert cset 13174:766eec31afab since it seems to break 64-bit;
a proper fix will arrive in the new year.

Signed-off-by: Steven Hand <steven@xensource.com>
author Steven Hand <steven@xensource.com>
date Fri Dec 29 18:17:56 2006 +0000 (2006-12-29)
parents 766eec31afab
children 444315d1ca5a
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
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.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2006 XenSource Inc.
16 #============================================================================
17 #
18 # Parts of this file are based upon xmlrpclib.py, the XML-RPC client
19 # interface included in the Python distribution.
20 #
21 # Copyright (c) 1999-2002 by Secret Labs AB
22 # Copyright (c) 1999-2002 by Fredrik Lundh
23 #
24 # By obtaining, using, and/or copying this software and/or its
25 # associated documentation, you agree that you have read, understood,
26 # and will comply with the following terms and conditions:
27 #
28 # Permission to use, copy, modify, and distribute this software and
29 # its associated documentation for any purpose and without fee is
30 # hereby granted, provided that the above copyright notice appears in
31 # all copies, and that both that copyright notice and this permission
32 # notice appear in supporting documentation, and that the name of
33 # Secret Labs AB or the author not be used in advertising or publicity
34 # pertaining to distribution of the software without specific, written
35 # prior permission.
36 #
37 # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
38 # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
39 # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
40 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
41 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
43 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
44 # OF THIS SOFTWARE.
45 # --------------------------------------------------------------------
47 import gettext
48 import xmlrpclib
50 import xen.util.xmlrpclib2
53 gettext.install('xen-xm')
55 class Failure(Exception):
56 def __init__(self, details):
57 try:
58 # If this failure is MESSAGE_PARAMETER_COUNT_MISMATCH, then we
59 # correct the return values here, to account for the fact that we
60 # transparently add the session handle as the first argument.
61 if details[0] == 'MESSAGE_PARAMETER_COUNT_MISMATCH':
62 details[2] = str(int(details[2]) - 1)
63 details[3] = str(int(details[3]) - 1)
65 self.details = details
66 except Exception, exn:
67 self.details = ['INTERNAL_ERROR', 'Client-side: ' + str(exn)]
69 def __str__(self):
70 try:
71 return _(self.details[0]) % self._details_map()
72 except TypeError, exn:
73 return "Message database broken: %s.\nXen-API failure: %s" % \
74 (exn, str(self.details))
75 except Exception, exn:
76 import sys
77 print >>sys.stderr, exn
78 return "Xen-API failure: %s" % str(self.details)
80 def _details_map(self):
81 return dict([(str(i), self.details[i])
82 for i in range(len(self.details))])
85 _RECONNECT_AND_RETRY = (lambda _ : ())
88 class Session(xen.util.xmlrpclib2.ServerProxy):
89 """A server proxy and session manager for communicating with Xend using
90 the Xen-API.
92 Example:
94 session = Session('http://localhost:9363/')
95 session.login_with_password('me', 'mypassword')
96 session.xenapi.VM.start(vm_uuid)
97 session.xenapi.session.logout()
99 For now, this class also supports the legacy XML-RPC API, using
100 session.xend.domain('Domain-0') and similar. This support will disappear
101 once there is a working Xen-API replacement for every call in the legacy
102 API.
103 """
105 def __init__(self, uri, transport=None, encoding=None, verbose=0,
106 allow_none=1):
107 xen.util.xmlrpclib2.ServerProxy.__init__(self, uri, transport,
108 encoding, verbose,
109 allow_none)
110 self._session = None
113 def xenapi_request(self, methodname, params):
114 if methodname.startswith('login'):
115 self._login(methodname, params)
116 return None
117 else:
118 retry_count = 0
119 while retry_count < 3:
120 full_params = (self._session,) + params
121 result = _parse_result(getattr(self, methodname)(*full_params))
122 if result == _RECONNECT_AND_RETRY:
123 retry_count += 1
124 self._login(self.last_login_method, self.last_login_params)
125 else:
126 return result
127 raise xmlrpclib.Fault(
128 500, 'Tried 3 times to get a valid session, but failed')
131 def _login(self, method, params):
132 result = _parse_result(getattr(self, 'session.%s' % method)(*params))
133 if result == _RECONNECT_AND_RETRY:
134 raise xmlrpclib.Fault(
135 500, 'Received SESSION_INVALID when logging in')
136 self._session = result
137 self.last_login_method = method
138 self.last_login_params = params
141 def __getattr__(self, name):
142 if name == 'xenapi':
143 return _Dispatcher(self.xenapi_request, None)
144 elif name.startswith('login'):
145 return lambda *params: self._login(name, params)
146 else:
147 return xen.util.xmlrpclib2.ServerProxy.__getattr__(self, name)
150 def _parse_result(result):
151 if type(result) != dict or 'Status' not in result:
152 raise xmlrpclib.Fault(500, 'Missing Status in response from server')
153 if result['Status'] == 'Success':
154 if 'Value' in result:
155 return result['Value']
156 else:
157 raise xmlrpclib.Fault(500,
158 'Missing Value in response from server')
159 else:
160 if 'ErrorDescription' in result:
161 if result['ErrorDescription'][0] == 'SESSION_INVALID':
162 return _RECONNECT_AND_RETRY
163 else:
164 raise Failure(result['ErrorDescription'])
165 else:
166 raise xmlrpclib.Fault(
167 500, 'Missing ErrorDescription in response from server')
170 # Based upon _Method from xmlrpclib.
171 class _Dispatcher:
172 def __init__(self, send, name):
173 self.__send = send
174 self.__name = name
175 def __getattr__(self, name):
176 if self.__name is None:
177 return _Dispatcher(self.__send, name)
178 else:
179 return _Dispatcher(self.__send, "%s.%s" % (self.__name, name))
180 def __call__(self, *args):
181 return self.__send(self.__name, args)