Advertisement
Guest User

Untitled

a guest
Sep 9th, 2011
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.85 KB | None | 0 0
  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-2007 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. # --------------------------------------------------------------------
  46.  
  47. import gettext
  48. import xmlrpclib
  49. import httplib
  50. import socket
  51.  
  52. translation = gettext.translation('xen-xm', fallback = True)
  53.  
  54. API_VERSION_1_1 = '1.1'
  55. API_VERSION_1_2 = '1.2'
  56.  
  57. class Failure(Exception):
  58. def __init__(self, details):
  59. self.details = details
  60.  
  61. def __str__(self):
  62. try:
  63. return str(self.details)
  64. except Exception, exn:
  65. import sys
  66. print >>sys.stderr, exn
  67. return "Xen-API failure: %s" % str(self.details)
  68.  
  69. def _details_map(self):
  70. return dict([(str(i), self.details[i])
  71. for i in range(len(self.details))])
  72.  
  73.  
  74. _RECONNECT_AND_RETRY = (lambda _ : ())
  75.  
  76. class UDSHTTPConnection(httplib.HTTPConnection):
  77. """HTTPConnection subclass to allow HTTP over Unix domain sockets. """
  78. def connect(self):
  79. path = self.host.replace("_", "/")
  80. self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
  81. self.sock.connect(path)
  82.  
  83. class UDSHTTP(httplib.HTTP):
  84. _connection_class = UDSHTTPConnection
  85.  
  86. class UDSTransport(xmlrpclib.Transport):
  87. def __init__(self, use_datetime=0):
  88. self._use_datetime = use_datetime
  89. self._extra_headers=[]
  90. def add_extra_header(self, key, value):
  91. self._extra_headers += [ (key,value) ]
  92. def make_connection(self, host):
  93. return UDSHTTP(host)
  94. def send_request(self, connection, handler, request_body):
  95. connection.putrequest("POST", handler)
  96. for key, value in self._extra_headers:
  97. connection.putheader(key, value)
  98.  
  99. class Session(xmlrpclib.ServerProxy):
  100. """A server proxy and session manager for communicating with xapi using
  101. the Xen-API.
  102.  
  103. Example:
  104.  
  105. session = Session('http://localhost/')
  106. session.login_with_password('me', 'mypassword')
  107. session.xenapi.VM.start(vm_uuid)
  108. session.xenapi.session.logout()
  109. """
  110.  
  111. def __init__(self, uri, transport=None, encoding=None, verbose=0,
  112. allow_none=1):
  113. xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
  114. verbose, allow_none)
  115. self.transport = transport
  116. self._session = None
  117. self.last_login_method = None
  118. self.last_login_params = None
  119. self.API_version = API_VERSION_1_1
  120.  
  121.  
  122. def xenapi_request(self, methodname, params):
  123. if methodname.startswith('login'):
  124. self._login(methodname, params)
  125. return None
  126. elif methodname == 'logout' or methodname == 'session.logout':
  127. self._logout()
  128. return None
  129. else:
  130. retry_count = 0
  131. while retry_count < 3:
  132. full_params = (self._session,) + params
  133. result = _parse_result(getattr(self, methodname)(*full_params))
  134. if result == _RECONNECT_AND_RETRY:
  135. retry_count += 1
  136. if self.last_login_method:
  137. self._login(self.last_login_method,
  138. self.last_login_params)
  139. else:
  140. raise xmlrpclib.Fault(401, 'You must log in')
  141. else:
  142. return result
  143. raise xmlrpclib.Fault(
  144. 500, 'Tried 3 times to get a valid session, but failed')
  145.  
  146.  
  147. def _login(self, method, params):
  148. result = _parse_result(getattr(self, 'session.%s' % method)(*params))
  149. if result == _RECONNECT_AND_RETRY:
  150. raise xmlrpclib.Fault(
  151. 500, 'Received SESSION_INVALID when logging in')
  152. self._session = result
  153. self.last_login_method = method
  154. self.last_login_params = params
  155. self.API_version = self._get_api_version()
  156.  
  157. def _logout(self):
  158. try:
  159. if self.last_login_method.startswith("slave_local"):
  160. return _parse_result(self.session.local_logout(self._session))
  161. else:
  162. return _parse_result(self.session.logout(self._session))
  163. finally:
  164. self._session = None
  165. self.last_login_method = None
  166. self.last_login_params = None
  167. self.API_version = API_VERSION_1_1
  168.  
  169. def _get_api_version(self):
  170. pool = self.xenapi.pool.get_all()[0]
  171. host = self.xenapi.pool.get_master(pool)
  172. major = self.xenapi.host.get_API_version_major(host)
  173. minor = self.xenapi.host.get_API_version_minor(host)
  174. return "%s.%s"%(major,minor)
  175.  
  176. def __getattr__(self, name):
  177. if name == 'handle':
  178. return self._session
  179. elif name == 'xenapi':
  180. return _Dispatcher(self.API_version, self.xenapi_request, None)
  181. elif name.startswith('login') or name.startswith('slave_local'):
  182. return lambda *params: self._login(name, params)
  183. else:
  184. return xmlrpclib.ServerProxy.__getattr__(self, name)
  185.  
  186. def xapi_local():
  187. return Session("http://_var_xapi_xapi/", transport=UDSTransport())
  188.  
  189. def _parse_result(result):
  190. if type(result) != dict or 'Status' not in result:
  191. raise xmlrpclib.Fault(500, 'Missing Status in response from server' + result)
  192. if result['Status'] == 'Success':
  193. if 'Value' in result:
  194. return result['Value']
  195. else:
  196. raise xmlrpclib.Fault(500,
  197. 'Missing Value in response from server')
  198. else:
  199. if 'ErrorDescription' in result:
  200. if result['ErrorDescription'][0] == 'SESSION_INVALID':
  201. return _RECONNECT_AND_RETRY
  202. else:
  203. raise Failure(result['ErrorDescription'])
  204. else:
  205. raise xmlrpclib.Fault(
  206. 500, 'Missing ErrorDescription in response from server')
  207.  
  208.  
  209. # Based upon _Method from xmlrpclib.
  210. class _Dispatcher:
  211. def __init__(self, API_version, send, name):
  212. self.__API_version = API_version
  213. self.__send = send
  214. self.__name = name
  215.  
  216. def __repr__(self):
  217. if self.__name:
  218. return '<XenAPI._Dispatcher for %s>' % self.__name
  219. else:
  220. return '<XenAPI._Dispatcher>'
  221.  
  222. def __getattr__(self, name):
  223. if self.__name is None:
  224. return _Dispatcher(self.__API_version, self.__send, name)
  225. else:
  226. return _Dispatcher(self.__API_version, self.__send, "%s.%s" % (self.__name, name))
  227.  
  228. def __call__(self, *args):
  229. return self.__send(self.__name, args)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement