Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-rapi @ c54784d9

History | View | Annotate | Download (4.7 kB)

1 8c229cc7 Oleksiy Mishchenko
#!/usr/bin/python
2 8c229cc7 Oleksiy Mishchenko
#
3 8c229cc7 Oleksiy Mishchenko
4 8c229cc7 Oleksiy Mishchenko
# Copyright (C) 2006, 2007 Google Inc.
5 8c229cc7 Oleksiy Mishchenko
#
6 8c229cc7 Oleksiy Mishchenko
# This program is free software; you can redistribute it and/or modify
7 8c229cc7 Oleksiy Mishchenko
# it under the terms of the GNU General Public License as published by
8 8c229cc7 Oleksiy Mishchenko
# the Free Software Foundation; either version 2 of the License, or
9 8c229cc7 Oleksiy Mishchenko
# (at your option) any later version.
10 8c229cc7 Oleksiy Mishchenko
#
11 8c229cc7 Oleksiy Mishchenko
# This program is distributed in the hope that it will be useful, but
12 8c229cc7 Oleksiy Mishchenko
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 8c229cc7 Oleksiy Mishchenko
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 8c229cc7 Oleksiy Mishchenko
# General Public License for more details.
15 8c229cc7 Oleksiy Mishchenko
#
16 8c229cc7 Oleksiy Mishchenko
# You should have received a copy of the GNU General Public License
17 8c229cc7 Oleksiy Mishchenko
# along with this program; if not, write to the Free Software
18 8c229cc7 Oleksiy Mishchenko
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 8c229cc7 Oleksiy Mishchenko
# 02110-1301, USA.
20 8c229cc7 Oleksiy Mishchenko
21 8c229cc7 Oleksiy Mishchenko
""" Ganeti Remote API master script.
22 8c229cc7 Oleksiy Mishchenko
"""
23 8c229cc7 Oleksiy Mishchenko
24 8c229cc7 Oleksiy Mishchenko
import glob
25 441e7cfd Oleksiy Mishchenko
import logging
26 8c229cc7 Oleksiy Mishchenko
import optparse
27 8c229cc7 Oleksiy Mishchenko
import sys
28 8c229cc7 Oleksiy Mishchenko
import os
29 cfe3c70f Michael Hanselmann
import signal
30 8c229cc7 Oleksiy Mishchenko
31 441e7cfd Oleksiy Mishchenko
from ganeti import logger
32 8c229cc7 Oleksiy Mishchenko
from ganeti import constants
33 3cd62121 Michael Hanselmann
from ganeti import errors
34 3cd62121 Michael Hanselmann
from ganeti import http
35 5675cd1f Iustin Pop
from ganeti import ssconf
36 8c229cc7 Oleksiy Mishchenko
from ganeti import utils
37 3cd62121 Michael Hanselmann
from ganeti.rapi import connector
38 3cd62121 Michael Hanselmann
39 3cd62121 Michael Hanselmann
40 3cd62121 Michael Hanselmann
class RESTRequestHandler(http.HTTPRequestHandler):
41 3cd62121 Michael Hanselmann
  """REST Request Handler Class.
42 3cd62121 Michael Hanselmann
43 3cd62121 Michael Hanselmann
  """
44 3cd62121 Michael Hanselmann
  def setup(self):
45 3cd62121 Michael Hanselmann
    super(RESTRequestHandler, self).setup()
46 3cd62121 Michael Hanselmann
    self._resmap = connector.Mapper()
47 3cd62121 Michael Hanselmann
48 3cd62121 Michael Hanselmann
  def HandleRequest(self):
49 3cd62121 Michael Hanselmann
    """ Handels a request.
50 3cd62121 Michael Hanselmann
51 3cd62121 Michael Hanselmann
    """
52 3cd62121 Michael Hanselmann
    (HandlerClass, items, args) = self._resmap.getController(self.path)
53 441e7cfd Oleksiy Mishchenko
    handler = HandlerClass(self, items, args, self.post_data)
54 3cd62121 Michael Hanselmann
55 3cd62121 Michael Hanselmann
    command = self.command.upper()
56 3cd62121 Michael Hanselmann
    try:
57 3cd62121 Michael Hanselmann
      fn = getattr(handler, command)
58 3cd62121 Michael Hanselmann
    except AttributeError, err:
59 3cd62121 Michael Hanselmann
      raise http.HTTPBadRequest()
60 3cd62121 Michael Hanselmann
61 3cd62121 Michael Hanselmann
    try:
62 441e7cfd Oleksiy Mishchenko
      try:
63 441e7cfd Oleksiy Mishchenko
        result = fn()
64 441e7cfd Oleksiy Mishchenko
      except:
65 441e7cfd Oleksiy Mishchenko
        logging.exception("Error while handling the %s request", command)
66 441e7cfd Oleksiy Mishchenko
        raise
67 3cd62121 Michael Hanselmann
68 3cd62121 Michael Hanselmann
    except errors.OpPrereqError, err:
69 3cd62121 Michael Hanselmann
      # TODO: "Not found" is not always the correct error. Ganeti's core must
70 3cd62121 Michael Hanselmann
      # differentiate between different error types.
71 3cd62121 Michael Hanselmann
      raise http.HTTPNotFound(message=str(err))
72 3cd62121 Michael Hanselmann
73 3cd62121 Michael Hanselmann
    return result
74 8c229cc7 Oleksiy Mishchenko
75 8c229cc7 Oleksiy Mishchenko
76 cfe3c70f Michael Hanselmann
class RESTHttpServer(http.HTTPServer):
77 cfe3c70f Michael Hanselmann
  def serve_forever(self):
78 cfe3c70f Michael Hanselmann
    """Handle one request at a time until told to quit."""
79 cfe3c70f Michael Hanselmann
    sighandler = utils.SignalHandler([signal.SIGINT, signal.SIGTERM])
80 cfe3c70f Michael Hanselmann
    try:
81 cfe3c70f Michael Hanselmann
      while not sighandler.called:
82 cfe3c70f Michael Hanselmann
        self.handle_request()
83 cfe3c70f Michael Hanselmann
    finally:
84 cfe3c70f Michael Hanselmann
      sighandler.Reset()
85 cfe3c70f Michael Hanselmann
86 cfe3c70f Michael Hanselmann
87 8c229cc7 Oleksiy Mishchenko
def ParseOptions():
88 8c229cc7 Oleksiy Mishchenko
  """Parse the command line options.
89 8c229cc7 Oleksiy Mishchenko
90 8c229cc7 Oleksiy Mishchenko
  Returns:
91 8c229cc7 Oleksiy Mishchenko
    (options, args) as from OptionParser.parse_args()
92 8c229cc7 Oleksiy Mishchenko
93 8c229cc7 Oleksiy Mishchenko
  """
94 8c229cc7 Oleksiy Mishchenko
  parser = optparse.OptionParser(description="Ganeti Remote API",
95 8c229cc7 Oleksiy Mishchenko
                    usage="%prog [-d] [-p port]",
96 8c229cc7 Oleksiy Mishchenko
                    version="%%prog (ganeti) %s" %
97 8c229cc7 Oleksiy Mishchenko
                                 constants.RAPI_VERSION)
98 8c229cc7 Oleksiy Mishchenko
  parser.add_option("-d", "--debug", dest="debug",
99 8c229cc7 Oleksiy Mishchenko
                    help="Enable some debug messages",
100 8c229cc7 Oleksiy Mishchenko
                    default=False, action="store_true")
101 8c229cc7 Oleksiy Mishchenko
  parser.add_option("-p", "--port", dest="port",
102 8c229cc7 Oleksiy Mishchenko
                    help="Port to run API (%s default)." %
103 8c229cc7 Oleksiy Mishchenko
                                 constants.RAPI_PORT,
104 8c229cc7 Oleksiy Mishchenko
                    default=constants.RAPI_PORT, type="int")
105 8c229cc7 Oleksiy Mishchenko
  parser.add_option("-S", "--https", dest="ssl",
106 8c229cc7 Oleksiy Mishchenko
                    help="Secure HTTP protocol with SSL",
107 8c229cc7 Oleksiy Mishchenko
                    default=False, action="store_true")
108 8c229cc7 Oleksiy Mishchenko
  parser.add_option("-K", "--ssl-key", dest="ssl_key",
109 8c229cc7 Oleksiy Mishchenko
                    help="SSL key",
110 8c229cc7 Oleksiy Mishchenko
                    default=None, type="string")
111 8c229cc7 Oleksiy Mishchenko
  parser.add_option("-C", "--ssl-cert", dest="ssl_cert",
112 8c229cc7 Oleksiy Mishchenko
                    help="SSL certificate",
113 8c229cc7 Oleksiy Mishchenko
                    default=None, type="string")
114 8c229cc7 Oleksiy Mishchenko
  parser.add_option("-f", "--foreground", dest="fork",
115 8c229cc7 Oleksiy Mishchenko
                    help="Don't detach from the current terminal",
116 8c229cc7 Oleksiy Mishchenko
                    default=True, action="store_false")
117 8c229cc7 Oleksiy Mishchenko
118 8c229cc7 Oleksiy Mishchenko
  options, args = parser.parse_args()
119 8c229cc7 Oleksiy Mishchenko
120 8c229cc7 Oleksiy Mishchenko
  if len(args) != 0:
121 8c229cc7 Oleksiy Mishchenko
    print >> sys.stderr, "Usage: %s [-d] [-p port]" % sys.argv[0]
122 8c229cc7 Oleksiy Mishchenko
    sys.exit(1)
123 8c229cc7 Oleksiy Mishchenko
124 8c229cc7 Oleksiy Mishchenko
  if options.ssl and not (options.ssl_cert and options.ssl_key):
125 8c229cc7 Oleksiy Mishchenko
    print >> sys.stderr, ("For secure mode please provide "
126 8c229cc7 Oleksiy Mishchenko
                         "--ssl-key and --ssl-cert arguments")
127 8c229cc7 Oleksiy Mishchenko
    sys.exit(1)
128 8c229cc7 Oleksiy Mishchenko
129 8c229cc7 Oleksiy Mishchenko
  return options, args
130 8c229cc7 Oleksiy Mishchenko
131 8c229cc7 Oleksiy Mishchenko
132 8c229cc7 Oleksiy Mishchenko
def main():
133 8c229cc7 Oleksiy Mishchenko
  """Main function.
134 8c229cc7 Oleksiy Mishchenko
135 8c229cc7 Oleksiy Mishchenko
  """
136 8c229cc7 Oleksiy Mishchenko
  options, args = ParseOptions()
137 3cd62121 Michael Hanselmann
138 5675cd1f Iustin Pop
  ssconf.CheckMaster(options.debug)
139 5675cd1f Iustin Pop
140 8c229cc7 Oleksiy Mishchenko
  if options.fork:
141 8c229cc7 Oleksiy Mishchenko
    utils.Daemonize(logfile=constants.LOG_RAPISERVER)
142 3cd62121 Michael Hanselmann
143 441e7cfd Oleksiy Mishchenko
  logger.SetupLogging(constants.LOG_RAPISERVER, debug=options.debug,
144 441e7cfd Oleksiy Mishchenko
                     stderr_logging=not options.fork)
145 441e7cfd Oleksiy Mishchenko
146 99e88451 Iustin Pop
  utils.WritePidFile(constants.RAPI_PID)
147 f71245a0 Iustin Pop
148 3cd62121 Michael Hanselmann
  log_fd = open(constants.LOG_RAPIACCESS, 'a')
149 3cd62121 Michael Hanselmann
  try:
150 3cd62121 Michael Hanselmann
    apache_log = http.ApacheLogfile(log_fd)
151 cfe3c70f Michael Hanselmann
    httpd = RESTHttpServer(("", options.port), RESTRequestHandler,
152 cfe3c70f Michael Hanselmann
                           httplog=apache_log)
153 3cd62121 Michael Hanselmann
    try:
154 3cd62121 Michael Hanselmann
      httpd.serve_forever()
155 3cd62121 Michael Hanselmann
    finally:
156 3cd62121 Michael Hanselmann
      httpd.server_close()
157 99e88451 Iustin Pop
      utils.RemovePidFile(constants.RAPI_PID)
158 3cd62121 Michael Hanselmann
159 3cd62121 Michael Hanselmann
  finally:
160 3cd62121 Michael Hanselmann
    log_fd.close()
161 3cd62121 Michael Hanselmann
162 8c229cc7 Oleksiy Mishchenko
  sys.exit(0)
163 8c229cc7 Oleksiy Mishchenko
164 8c229cc7 Oleksiy Mishchenko
165 8c229cc7 Oleksiy Mishchenko
if __name__ == '__main__':
166 441e7cfd Oleksiy Mishchenko
  
167 8c229cc7 Oleksiy Mishchenko
  main()