Add monitoring-query-format.rst to $(docinput)
[ganeti-local] / doc / design-http-server.rst
1 =========================================
2 Design for replacing Ganeti's HTTP server
3 =========================================
4
5 .. contents:: :depth: 4
6
7 .. _http-srv-shortcomings:
8
9 Current state and shortcomings
10 ------------------------------
11
12 The :doc:`new design for import/export <design-impexp2>` depends on an
13 HTTP server. Ganeti includes a home-grown HTTP server based on Python's
14 ``BaseHTTPServer``. While it served us well so far, it only implements
15 the very basics of the HTTP protocol. It is, for example, not structured
16 well enough to support chunked transfers (:rfc:`2616`, section 3.6.1),
17 which would have some advantages. In addition, it has not been designed
18 for sending large responses.
19
20 In the case of the node daemon the HTTP server can not easily be
21 separated from the actual backend code and therefore must run as "root".
22 The RAPI daemon does request parsing in the same process as talking to
23 the master daemon via LUXI.
24
25
26 Proposed changes
27 ----------------
28
29 The proposal is to start using a full-fledged HTTP server in Ganeti and
30 to run Ganeti's code as `FastCGI <http://www.fastcgi.com/>`_
31 applications. Reasons:
32
33 - Simplify Ganeti's code by delegating the details of HTTP and SSL to
34   another piece of software
35 - Run HTTP frontend and handler backend as separate processes and users
36   (esp. useful for node daemon, but also import/export and Remote API)
37 - Allows implementation of :ref:`rpc-feedback`
38
39
40 Software choice
41 +++++++++++++++
42
43 Theoretically any server able of speaking FastCGI to a backend process
44 could be used. However, to keep the number of steps required for setting
45 up a new cluster at roughly the same level, the implementation will be
46 geared for one specific HTTP server at the beginning. Support for other
47 HTTP servers can still be implemented.
48
49 After a rough selection of available HTTP servers `lighttpd
50 <http://www.lighttpd.net/>`_ and `nginx <http://www.nginx.org/>`_ were
51 the most likely candidates. Both are `widely used`_ and tested.
52
53 .. _widely used: http://news.netcraft.com/archives/2011/01/12/
54   january-2011-web-server-survey-4.html
55
56 Nginx' `original documentation <http://sysoev.ru/nginx/docs/>`_ is in
57 Russian, translations are `available in a Wiki
58 <http://wiki.nginx.org/>`_. Nginx does not support old-style CGI
59 programs.
60
61 The author found `lighttpd's documentation
62 <http://redmine.lighttpd.net/wiki/lighttpd>`_ easier to understand and
63 was able to configure a test server quickly. This, together with the
64 support for more technologies, made deciding easier.
65
66 With its use as a public-facing web server on a large number of websites
67 (and possibly more behind proxies), lighttpd should be a safe choice.
68 Unlike other webservers, such as the Apache HTTP Server, lighttpd's
69 codebase is of manageable size.
70
71 Initially the HTTP server would only be used for import/export
72 transfers, but its use can be expanded to the Remote API and node
73 daemon (see :ref:`rpc-feedback`).
74
75 To reduce the attack surface, an option will be provided to configure
76 services (e.g. import/export) to only listen on certain network
77 interfaces.
78
79
80 .. _rpc-feedback:
81
82 RPC feedback
83 ++++++++++++
84
85 HTTP/1.1 supports chunked transfers (:rfc:`2616`, section 3.6.1). They
86 could be used to provide feedback from node daemons to the master,
87 similar to the feedback from jobs. A good use would be to provide
88 feedback to the user during long-running operations, e.g. downloading an
89 instance's data from another cluster.
90
91 .. _requirement: http://www.python.org/dev/peps/pep-0333/
92   #buffering-and-streaming
93
94 WSGI 1.0 (:pep:`333`) includes the following `requirement`_:
95
96   WSGI servers, gateways, and middleware **must not** delay the
97   transmission of any block; they **must** either fully transmit the
98   block to the client, or guarantee that they will continue transmission
99   even while the application is producing its next block
100
101 This behaviour was confirmed to work with lighttpd and the
102 :ref:`flup <http-software-req>` library. FastCGI by itself has no such
103 guarantee; webservers with buffering might require artificial padding to
104 force the message to be transmitted.
105
106 The node daemon can send JSON-encoded messages back to the master daemon
107 by separating them using a predefined character (see :ref:`LUXI
108 <luxi>`). The final message contains the method's result. pycURL passes
109 each received chunk to the callback set as ``CURLOPT_WRITEFUNCTION``.
110 Once a message is complete, the master daemon can pass it to a callback
111 function inside the job, which then decides on what to do (e.g. forward
112 it as job feedback to the user).
113
114 A more detailed design may have to be written before deciding whether to
115 implement RPC feedback.
116
117
118 .. _http-software-req:
119
120 Software requirements
121 +++++++++++++++++++++
122
123 - lighttpd 1.4.24 or above built with OpenSSL support (earlier versions
124   `don't support SSL client certificates
125   <http://redmine.lighttpd.net/issues/1288>`_)
126 - `flup <http://trac.saddi.com/flup>`_ for FastCGI
127
128
129 Lighttpd SSL configuration
130 ++++++++++++++++++++++++++
131
132 .. highlight:: lighttpd
133
134 The following sample shows how to configure SSL with client certificates
135 in Lighttpd::
136
137   $SERVER["socket"] == ":443" {
138     ssl.engine = "enable"
139     ssl.pemfile = "server.pem"
140     ssl.ca-file = "ca.pem"
141     ssl.use-sslv2  = "disable"
142     ssl.cipher-list = "HIGH:-DES:-3DES:-EXPORT:-ADH"
143     ssl.verifyclient.activate = "enable"
144     ssl.verifyclient.enforce = "enable"
145     ssl.verifyclient.exportcert = "enable"
146     ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN"
147   }
148
149
150 .. vim: set textwidth=72 :
151 .. Local Variables:
152 .. mode: rst
153 .. fill-column: 72
154 .. End: