| ========================================= |
| Design for replacing Ganeti's HTTP server |
| ========================================= |
| |
| .. contents:: :depth: 4 |
| |
| .. _http-srv-shortcomings: |
| |
| Current state and shortcomings |
| ------------------------------ |
| |
| The :doc:`new design for import/export <design-impexp2>` depends on an |
| HTTP server. Ganeti includes a home-grown HTTP server based on Python's |
| ``BaseHTTPServer``. While it served us well so far, it only implements |
| the very basics of the HTTP protocol. It is, for example, not structured |
| well enough to support chunked transfers (:rfc:`2616`, section 3.6.1), |
| which would have some advantages. In addition, it has not been designed |
| for sending large responses. |
| |
| In the case of the node daemon the HTTP server can not easily be |
| separated from the actual backend code and therefore must run as "root". |
| The RAPI daemon does request parsing in the same process as talking to |
| the master daemon via LUXI. |
| |
| |
| Proposed changes |
| ---------------- |
| |
| The proposal is to start using a full-fledged HTTP server in Ganeti and |
| to run Ganeti's code as `FastCGI <http://www.fastcgi.com/>`_ |
| applications. Reasons: |
| |
| - Simplify Ganeti's code by delegating the details of HTTP and SSL to |
| another piece of software |
| - Run HTTP frontend and handler backend as separate processes and users |
| (esp. useful for node daemon, but also import/export and Remote API) |
| - Allows implementation of :ref:`rpc-feedback` |
| |
| |
| Software choice |
| +++++++++++++++ |
| |
| Theoretically any server able of speaking FastCGI to a backend process |
| could be used. However, to keep the number of steps required for setting |
| up a new cluster at roughly the same level, the implementation will be |
| geared for one specific HTTP server at the beginning. Support for other |
| HTTP servers can still be implemented. |
| |
| After a rough selection of available HTTP servers `lighttpd |
| <http://www.lighttpd.net/>`_ and `nginx <http://www.nginx.org/>`_ were |
| the most likely candidates. Both are `widely used`_ and tested. |
| |
| .. _widely used: http://news.netcraft.com/archives/2011/01/12/ |
| january-2011-web-server-survey-4.html |
| |
| Nginx' `original documentation <http://sysoev.ru/nginx/docs/>`_ is in |
| Russian, translations are `available in a Wiki |
| <http://wiki.nginx.org/>`_. Nginx does not support old-style CGI |
| programs. |
| |
| The author found `lighttpd's documentation |
| <http://redmine.lighttpd.net/wiki/lighttpd>`_ easier to understand and |
| was able to configure a test server quickly. This, together with the |
| support for more technologies, made deciding easier. |
| |
| With its use as a public-facing web server on a large number of websites |
| (and possibly more behind proxies), lighttpd should be a safe choice. |
| Unlike other webservers, such as the Apache HTTP Server, lighttpd's |
| codebase is of manageable size. |
| |
| Initially the HTTP server would only be used for import/export |
| transfers, but its use can be expanded to the Remote API and node |
| daemon (see :ref:`rpc-feedback`). |
| |
| To reduce the attack surface, an option will be provided to configure |
| services (e.g. import/export) to only listen on certain network |
| interfaces. |
| |
| |
| .. _rpc-feedback: |
| |
| RPC feedback |
| ++++++++++++ |
| |
| HTTP/1.1 supports chunked transfers (:rfc:`2616`, section 3.6.1). They |
| could be used to provide feedback from node daemons to the master, |
| similar to the feedback from jobs. A good use would be to provide |
| feedback to the user during long-running operations, e.g. downloading an |
| instance's data from another cluster. |
| |
| .. _requirement: http://www.python.org/dev/peps/pep-0333/ |
| #buffering-and-streaming |
| |
| WSGI 1.0 (:pep:`333`) includes the following `requirement`_: |
| |
| WSGI servers, gateways, and middleware **must not** delay the |
| transmission of any block; they **must** either fully transmit the |
| block to the client, or guarantee that they will continue transmission |
| even while the application is producing its next block |
| |
| This behaviour was confirmed to work with lighttpd and the |
| :ref:`flup <http-software-req>` library. FastCGI by itself has no such |
| guarantee; webservers with buffering might require artificial padding to |
| force the message to be transmitted. |
| |
| The node daemon can send JSON-encoded messages back to the master daemon |
| by separating them using a predefined character (see :ref:`LUXI |
| <luxi>`). The final message contains the method's result. pycURL passes |
| each received chunk to the callback set as ``CURLOPT_WRITEFUNCTION``. |
| Once a message is complete, the master daemon can pass it to a callback |
| function inside the job, which then decides on what to do (e.g. forward |
| it as job feedback to the user). |
| |
| A more detailed design may have to be written before deciding whether to |
| implement RPC feedback. |
| |
| |
| .. _http-software-req: |
| |
| Software requirements |
| +++++++++++++++++++++ |
| |
| - lighttpd 1.4.24 or above built with OpenSSL support (earlier versions |
| `don't support SSL client certificates |
| <http://redmine.lighttpd.net/issues/1288>`_) |
| - `flup <http://trac.saddi.com/flup>`_ for FastCGI |
| |
| |
| Lighttpd SSL configuration |
| ++++++++++++++++++++++++++ |
| |
| .. highlight:: lighttpd |
| |
| The following sample shows how to configure SSL with client certificates |
| in Lighttpd:: |
| |
| $SERVER["socket"] == ":443" { |
| ssl.engine = "enable" |
| ssl.pemfile = "server.pem" |
| ssl.ca-file = "ca.pem" |
| ssl.use-sslv2 = "disable" |
| ssl.cipher-list = "HIGH:-DES:-3DES:-EXPORT:-ADH" |
| ssl.verifyclient.activate = "enable" |
| ssl.verifyclient.enforce = "enable" |
| ssl.verifyclient.exportcert = "enable" |
| ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN" |
| } |
| |
| |
| .. vim: set textwidth=72 : |
| .. Local Variables: |
| .. mode: rst |
| .. fill-column: 72 |
| .. End: |