Revision 278ddaa9

b/Makefile.am
274 274
	doc/design-oob.rst \
275 275
	doc/design-query2.rst \
276 276
	doc/design-x509-ca.rst \
277
	doc/design-http-server.rst \
277 278
	doc/cluster-merge.rst \
278 279
	doc/design-shared-storage.rst \
279 280
	doc/devnotes.rst \
b/doc/design-draft.rst
6 6
   :maxdepth: 2
7 7

  
8 8
   design-x509-ca.rst
9
   design-http-server.rst
9 10

  
10 11
.. vim: set textwidth=72 :
11 12
.. Local Variables:
b/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:

Also available in: Unified diff