Mention RAPI client in documentation
[ganeti-local] / lib / http / server.py
index b3e5b78..14e9ff7 100644 (file)
@@ -26,13 +26,13 @@ import BaseHTTPServer
 import cgi
 import logging
 import os
-import select
 import socket
 import time
 import signal
 import asyncore
 
 from ganeti import http
+from ganeti import utils
 
 
 WEEKDAYNAME = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
@@ -74,12 +74,12 @@ class _HttpServerRequest(object):
   """Data structure for HTTP request on server side.
 
   """
-  def __init__(self, request_msg):
+  def __init__(self, method, path, headers, body):
     # Request attributes
-    self.request_method = request_msg.start_line.method
-    self.request_path = request_msg.start_line.path
-    self.request_headers = request_msg.headers
-    self.request_body = request_msg.decoded_body
+    self.request_method = method
+    self.request_path = path
+    self.request_headers = headers
+    self.request_body = body
 
     # Response attributes
     self.resp_headers = {}
@@ -88,6 +88,14 @@ class _HttpServerRequest(object):
     # authentication)
     self.private = None
 
+  def __repr__(self):
+    status = ["%s.%s" % (self.__class__.__module__, self.__class__.__name__),
+              self.request_method, self.request_path,
+              "headers=%r" % str(self.request_headers),
+              "body=%r" % (self.request_body, )]
+
+    return "<%s at %#x>" % (" ".join(status), id(self))
+
 
 class _HttpServerToClientMessageWriter(http.HttpMessageWriter):
   """Writes an HTTP response to client.
@@ -308,7 +316,12 @@ class HttpServerRequestExecutor(object):
     """Calls the handler function for the current request.
 
     """
-    handler_context = _HttpServerRequest(self.request_msg)
+    handler_context = _HttpServerRequest(self.request_msg.start_line.method,
+                                         self.request_msg.start_line.path,
+                                         self.request_msg.headers,
+                                         self.request_msg.decoded_body)
+
+    logging.debug("Handling request %r", handler_context)
 
     try:
       try:
@@ -504,7 +517,7 @@ class HttpServer(http.HttpBase, asyncore.dispatcher):
 
     for child in self._children:
       try:
-        pid, status = os.waitpid(child, os.WNOHANG)
+        pid, _ = os.waitpid(child, os.WNOHANG)
       except os.error:
         pid = None
       if pid and pid in self._children:
@@ -514,6 +527,7 @@ class HttpServer(http.HttpBase, asyncore.dispatcher):
     """Called for each incoming connection
 
     """
+    # pylint: disable-msg=W0212
     (connection, client_addr) = self.socket.accept()
 
     self._CollectChildren(False)
@@ -522,8 +536,21 @@ class HttpServer(http.HttpBase, asyncore.dispatcher):
     if pid == 0:
       # Child process
       try:
+        # The client shouldn't keep the listening socket open. If the parent
+        # process is restarted, it would fail when there's already something
+        # listening (in this case its own child from a previous run) on the
+        # same port.
+        try:
+          self.socket.close()
+        except socket.error:
+          pass
+        self.socket = None
+
+        # In case the handler code uses temporary files
+        utils.ResetTempfileModule()
+
         self.request_executor(self, connection, client_addr)
-      except Exception:
+      except Exception: # pylint: disable-msg=W0703
         logging.exception("Error while handling request from %s:%s",
                           client_addr[0], client_addr[1])
         os._exit(1)