RemoteApiHandler: Add support for mocked LUXI client
[ganeti-local] / lib / server / rapi.py
index 5e8cfa1..9157889 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#
 #
 
 # Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc.
@@ -22,7 +22,7 @@
 
 """
 
-# pylint: disable-msg=C0103,W0142
+# pylint: disable=C0103,W0142
 
 # C0103: Invalid name ganeti-watcher
 
@@ -34,7 +34,7 @@ import os.path
 import errno
 
 try:
-  from pyinotify import pyinotify # pylint: disable-msg=E0611
+  from pyinotify import pyinotify # pylint: disable=E0611
 except ImportError:
   import pyinotify
 
@@ -49,7 +49,7 @@ from ganeti import compat
 from ganeti import utils
 from ganeti.rapi import connector
 
-import ganeti.http.auth   # pylint: disable-msg=W0611
+import ganeti.http.auth   # pylint: disable=W0611
 import ganeti.http.server
 
 
@@ -64,36 +64,19 @@ class RemoteApiRequestContext(object):
     self.body_data = None
 
 
-class JsonErrorRequestExecutor(http.server.HttpServerRequestExecutor):
-  """Custom Request Executor class that formats HTTP errors in JSON.
-
-  """
-  error_content_type = http.HTTP_APP_JSON
-
-  def _FormatErrorMessage(self, values):
-    """Formats the body of an error message.
-
-    @type values: dict
-    @param values: dictionary with keys code, message and explain.
-    @rtype: string
-    @return: the body of the message
-
-    """
-    return serializer.DumpJson(values, indent=True)
-
-
-class RemoteApiHttpServer(http.auth.HttpServerRequestAuthentication,
-                          http.server.HttpServer):
+class RemoteApiHandler(http.auth.HttpServerRequestAuthentication,
+                       http.server.HttpServerHandler):
   """REST Request Handler Class.
 
   """
   AUTH_REALM = "Ganeti Remote API"
 
-  def __init__(self, *args, **kwargs):
-    # pylint: disable-msg=W0233
+  def __init__(self, _client_cls=None):
+    # pylint: disable=W0233
     # it seems pylint doesn't see the second parent class there
-    http.server.HttpServer.__init__(self, *args, **kwargs)
+    http.server.HttpServerHandler.__init__(self)
     http.auth.HttpServerRequestAuthentication.__init__(self)
+    self._client_cls = _client_cls
     self._resmap = connector.Mapper()
     self._users = None
 
@@ -118,7 +101,7 @@ class RemoteApiHttpServer(http.auth.HttpServerRequestAuthentication,
 
       users = http.auth.ParsePasswordFile(contents)
 
-    except Exception, err: # pylint: disable-msg=W0703
+    except Exception, err: # pylint: disable=W0703
       # We don't care about the type of exception
       logging.error("Error while parsing %s: %s", filename, err)
       return False
@@ -127,6 +110,18 @@ class RemoteApiHttpServer(http.auth.HttpServerRequestAuthentication,
 
     return True
 
+  @staticmethod
+  def FormatErrorMessage(values):
+    """Formats the body of an error message.
+
+    @type values: dict
+    @param values: dictionary with keys C{code}, C{message} and C{explain}.
+    @rtype: tuple; (string, string)
+    @return: Content-type and response body
+
+    """
+    return (http.HTTP_APP_JSON, serializer.DumpJson(values))
+
   def _GetRequestContext(self, req):
     """Returns the context for a request.
 
@@ -138,7 +133,7 @@ class RemoteApiHttpServer(http.auth.HttpServerRequestAuthentication,
                      self._resmap.getController(req.request_path)
 
       ctx = RemoteApiRequestContext()
-      ctx.handler = HandlerClass(items, args, req)
+      ctx.handler = HandlerClass(items, args, req, _client_cls=self._client_cls)
 
       method = req.request_method.upper()
       try:
@@ -308,27 +303,24 @@ def PrepRapi(options, _):
   """Prep remote API function, executed with the PID file held.
 
   """
-
   mainloop = daemon.Mainloop()
-  server = RemoteApiHttpServer(mainloop, options.bind_address, options.port,
-                               ssl_params=options.ssl_params,
-                               ssl_verify_peer=False,
-                               request_executor_class=JsonErrorRequestExecutor)
+  handler = RemoteApiHandler()
 
   # Setup file watcher (it'll be driven by asyncore)
   SetupFileWatcher(constants.RAPI_USERS_FILE,
-                   compat.partial(server.LoadUsers, constants.RAPI_USERS_FILE))
+                   compat.partial(handler.LoadUsers, constants.RAPI_USERS_FILE))
 
-  server.LoadUsers(constants.RAPI_USERS_FILE)
+  handler.LoadUsers(constants.RAPI_USERS_FILE)
 
-  # pylint: disable-msg=E1101
-  # it seems pylint doesn't see the second parent class there
+  server = \
+    http.server.HttpServer(mainloop, options.bind_address, options.port,
+      handler, ssl_params=options.ssl_params, ssl_verify_peer=False)
   server.Start()
 
   return (mainloop, server)
 
 
-def ExecRapi(options, args, prep_data): # pylint: disable-msg=W0613
+def ExecRapi(options, args, prep_data): # pylint: disable=W0613
   """Main remote API function, executed with the PID file held.
 
   """