32 |
32 |
from ganeti import constants
|
33 |
33 |
from ganeti import errors
|
34 |
34 |
from ganeti import http
|
|
35 |
from ganeti import daemon
|
35 |
36 |
from ganeti import ssconf
|
36 |
37 |
from ganeti import utils
|
37 |
38 |
from ganeti.rapi import connector
|
38 |
39 |
|
39 |
40 |
|
40 |
|
class RESTRequestHandler(http.HTTPRequestHandler):
|
|
41 |
class RemoteApiHttpServer(http.HttpServer):
|
41 |
42 |
"""REST Request Handler Class.
|
42 |
43 |
|
43 |
44 |
"""
|
44 |
|
def setup(self):
|
45 |
|
super(RESTRequestHandler, self).setup()
|
|
45 |
def __init__(self, *args, **kwargs):
|
|
46 |
http.HttpServer.__init__(self, *args, **kwargs)
|
46 |
47 |
self._resmap = connector.Mapper()
|
47 |
48 |
|
48 |
|
def HandleRequest(self):
|
49 |
|
""" Handels a request.
|
|
49 |
def HandleRequest(self, req):
|
|
50 |
"""Handles a request.
|
50 |
51 |
|
51 |
52 |
"""
|
52 |
|
(HandlerClass, items, args) = self._resmap.getController(self.path)
|
53 |
|
handler = HandlerClass(self, items, args, self.post_data)
|
|
53 |
(HandlerClass, items, args) = self._resmap.getController(req.request_path)
|
|
54 |
handler = HandlerClass(items, args, req.request_post_data)
|
54 |
55 |
|
55 |
|
command = self.command.upper()
|
|
56 |
method = req.request_method.upper()
|
56 |
57 |
try:
|
57 |
|
fn = getattr(handler, command)
|
|
58 |
fn = getattr(handler, method)
|
58 |
59 |
except AttributeError, err:
|
59 |
60 |
raise http.HTTPBadRequest()
|
60 |
61 |
|
61 |
62 |
try:
|
62 |
|
try:
|
63 |
|
result = fn()
|
64 |
|
except:
|
65 |
|
logging.exception("Error while handling the %s request", command)
|
66 |
|
raise
|
67 |
|
|
68 |
|
except errors.OpPrereqError, err:
|
69 |
|
# TODO: "Not found" is not always the correct error. Ganeti's core must
|
70 |
|
# differentiate between different error types.
|
71 |
|
raise http.HTTPNotFound(message=str(err))
|
|
63 |
result = fn()
|
|
64 |
except:
|
|
65 |
logging.exception("Error while handling the %s request", method)
|
|
66 |
raise
|
72 |
67 |
|
73 |
68 |
return result
|
74 |
69 |
|
75 |
70 |
|
76 |
|
class RESTHttpServer(http.HTTPServer):
|
77 |
|
def serve_forever(self):
|
78 |
|
"""Handle one request at a time until told to quit."""
|
79 |
|
sighandler = utils.SignalHandler([signal.SIGINT, signal.SIGTERM])
|
80 |
|
try:
|
81 |
|
while not sighandler.called:
|
82 |
|
self.handle_request()
|
83 |
|
finally:
|
84 |
|
sighandler.Reset()
|
85 |
|
|
86 |
|
|
87 |
71 |
def ParseOptions():
|
88 |
72 |
"""Parse the command line options.
|
89 |
73 |
|
... | ... | |
144 |
128 |
stderr_logging=not options.fork)
|
145 |
129 |
|
146 |
130 |
utils.WritePidFile(constants.RAPI_PID)
|
147 |
|
|
148 |
|
log_fd = open(constants.LOG_RAPIACCESS, 'a')
|
149 |
131 |
try:
|
150 |
|
apache_log = http.ApacheLogfile(log_fd)
|
151 |
|
httpd = RESTHttpServer(("", options.port), RESTRequestHandler,
|
152 |
|
httplog=apache_log)
|
|
132 |
mainloop = daemon.Mainloop()
|
|
133 |
server = RemoteApiHttpServer(mainloop, ("", options.port))
|
|
134 |
server.Start()
|
153 |
135 |
try:
|
154 |
|
httpd.serve_forever()
|
|
136 |
mainloop.Run()
|
155 |
137 |
finally:
|
156 |
|
httpd.server_close()
|
157 |
|
utils.RemovePidFile(constants.RAPI_PID)
|
158 |
|
|
|
138 |
server.Stop()
|
159 |
139 |
finally:
|
160 |
|
log_fd.close()
|
161 |
|
|
162 |
|
sys.exit(0)
|
|
140 |
utils.RemovePidFile(constants.RAPI_PID)
|
163 |
141 |
|
164 |
142 |
|
165 |
143 |
if __name__ == '__main__':
|