rapi.client, http.client: Format url correctly when using IPv6
[ganeti-local] / lib / http / __init__.py
index d0db1ce..203e0d5 100644 (file)
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2007, 2008 Google Inc.
+# Copyright (C) 2007, 2008, 2010 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -32,7 +32,6 @@ import errno
 from cStringIO import StringIO
 
 from ganeti import constants
-from ganeti import serializer
 from ganeti import utils
 
 
@@ -66,6 +65,9 @@ HTTP_AUTHORIZATION = "Authorization"
 HTTP_AUTHENTICATION_INFO = "Authentication-Info"
 HTTP_ALLOW = "Allow"
 
+HTTP_APP_OCTET_STREAM = "application/octet-stream"
+HTTP_APP_JSON = "application/json"
+
 _SSL_UNEXPECTED_EOF = "Unexpected EOF"
 
 # Socket operations
@@ -178,6 +180,17 @@ class HttpMethodNotAllowed(HttpException):
   code = 405
 
 
+class HttpNotAcceptable(HttpException):
+  """406 Not Acceptable
+
+  RFC2616, 10.4.7: The resource identified by the request is only capable of
+  generating response entities which have content characteristics not
+  acceptable according to the accept headers sent in the request.
+
+  """
+  code = 406
+
+
 class HttpRequestTimeout(HttpException):
   """408 Request Timeout
 
@@ -235,6 +248,17 @@ class HttpPreconditionFailed(HttpException):
   code = 412
 
 
+class HttpUnsupportedMediaType(HttpException):
+  """415 Unsupported Media Type
+
+  RFC2616, 10.4.16: The server is refusing to service the request because the
+  entity of the request is in a format not supported by the requested resource
+  for the requested method.
+
+  """
+  code = 415
+
+
 class HttpInternalServerError(HttpException):
   """500 Internal Server Error
 
@@ -299,18 +323,6 @@ class HttpVersionNotSupported(HttpException):
   code = 505
 
 
-class HttpJsonConverter: # pylint: disable-msg=W0232
-  CONTENT_TYPE = "application/json"
-
-  @staticmethod
-  def Encode(data):
-    return serializer.DumpJson(data)
-
-  @staticmethod
-  def Decode(data):
-    return serializer.LoadJson(data)
-
-
 def SocketOperation(sock, op, arg1, timeout):
   """Wrapper around socket functions.
 
@@ -361,7 +373,7 @@ def SocketOperation(sock, op, arg1, timeout):
       else:
         wait_for_event = event_poll
 
-      event = utils.WaitForSocketCondition(sock, wait_for_event, timeout)
+      event = utils.WaitForFdCondition(sock, wait_for_event, timeout)
       if event is None:
         raise HttpSocketTimeout()
 
@@ -558,7 +570,7 @@ class HttpBase(object):
     self._ssl_key = None
     self._ssl_cert = None
 
-  def _CreateSocket(self, ssl_params, ssl_verify_peer):
+  def _CreateSocket(self, ssl_params, ssl_verify_peer, family):
     """Creates a TCP socket and initializes SSL if needed.
 
     @type ssl_params: HttpSslParams
@@ -566,11 +578,14 @@ class HttpBase(object):
     @type ssl_verify_peer: bool
     @param ssl_verify_peer: Whether to require client certificate
         and compare it with our certificate
+    @type family: int
+    @param family: socket.AF_INET | socket.AF_INET6
 
     """
-    self._ssl_params = ssl_params
+    assert family in (socket.AF_INET, socket.AF_INET6)
 
-    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    self._ssl_params = ssl_params
+    sock = socket.socket(family, socket.SOCK_STREAM)
 
     # Should we enable SSL?
     self.using_ssl = ssl_params is not None
@@ -583,6 +598,7 @@ class HttpBase(object):
 
     ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
     ctx.set_options(OpenSSL.SSL.OP_NO_SSLv2)
+    ctx.set_cipher_list(constants.OPENSSL_CIPHERS)
 
     ctx.use_privatekey(self._ssl_key)
     ctx.use_certificate(self._ssl_cert)
@@ -618,7 +634,6 @@ class HttpMessage(object):
     self.start_line = None
     self.headers = None
     self.body = None
-    self.decoded_body = None
 
 
 class HttpClientToServerStartLine(object):
@@ -777,7 +792,7 @@ class HttpMessageReader(object):
       buf = self._ContinueParsing(buf, eof)
 
       # Must be done only after the buffer has been evaluated
-      # TODO: Connection-length < len(data read) and connection closed
+      # TODO: Content-Length < len(data read) and connection closed
       if (eof and
           self.parser_status in (self.PS_START_LINE,
                                  self.PS_HEADERS)):
@@ -789,17 +804,9 @@ class HttpMessageReader(object):
     assert self.parser_status == self.PS_COMPLETE
     assert not buf, "Parser didn't read full response"
 
+    # Body is complete
     msg.body = self.body_buffer.getvalue()
 
-    # TODO: Content-type, error handling
-    if msg.body:
-      msg.decoded_body = HttpJsonConverter().Decode(msg.body)
-    else:
-      msg.decoded_body = None
-
-    if msg.decoded_body:
-      logging.debug("Message body: %s", msg.decoded_body)
-
   def _ContinueParsing(self, buf, eof):
     """Main function for HTTP message state machine.