|
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:
|