Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-rapi @ a2f92677

History | View | Annotate | Download (4.7 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2006, 2007 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21
""" Ganeti Remote API master script.
22
"""
23

    
24
import glob
25
import logging
26
import optparse
27
import sys
28
import os
29
import signal
30

    
31
from ganeti import logger
32
from ganeti import constants
33
from ganeti import errors
34
from ganeti import http
35
from ganeti import ssconf
36
from ganeti import utils
37
from ganeti.rapi import connector
38

    
39

    
40
class RESTRequestHandler(http.HTTPRequestHandler):
41
  """REST Request Handler Class.
42

    
43
  """
44
  def setup(self):
45
    super(RESTRequestHandler, self).setup()
46
    self._resmap = connector.Mapper()
47

    
48
  def HandleRequest(self):
49
    """ Handels a request.
50

    
51
    """
52
    (HandlerClass, items, args) = self._resmap.getController(self.path)
53
    handler = HandlerClass(self, items, args, self.post_data)
54

    
55
    command = self.command.upper()
56
    try:
57
      fn = getattr(handler, command)
58
    except AttributeError, err:
59
      raise http.HTTPBadRequest()
60

    
61
    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))
72

    
73
    return result
74

    
75

    
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
def ParseOptions():
88
  """Parse the command line options.
89

    
90
  Returns:
91
    (options, args) as from OptionParser.parse_args()
92

    
93
  """
94
  parser = optparse.OptionParser(description="Ganeti Remote API",
95
                    usage="%prog [-d] [-p port]",
96
                    version="%%prog (ganeti) %s" %
97
                                 constants.RAPI_VERSION)
98
  parser.add_option("-d", "--debug", dest="debug",
99
                    help="Enable some debug messages",
100
                    default=False, action="store_true")
101
  parser.add_option("-p", "--port", dest="port",
102
                    help="Port to run API (%s default)." %
103
                                 constants.RAPI_PORT,
104
                    default=constants.RAPI_PORT, type="int")
105
  parser.add_option("-S", "--https", dest="ssl",
106
                    help="Secure HTTP protocol with SSL",
107
                    default=False, action="store_true")
108
  parser.add_option("-K", "--ssl-key", dest="ssl_key",
109
                    help="SSL key",
110
                    default=None, type="string")
111
  parser.add_option("-C", "--ssl-cert", dest="ssl_cert",
112
                    help="SSL certificate",
113
                    default=None, type="string")
114
  parser.add_option("-f", "--foreground", dest="fork",
115
                    help="Don't detach from the current terminal",
116
                    default=True, action="store_false")
117

    
118
  options, args = parser.parse_args()
119

    
120
  if len(args) != 0:
121
    print >> sys.stderr, "Usage: %s [-d] [-p port]" % sys.argv[0]
122
    sys.exit(1)
123

    
124
  if options.ssl and not (options.ssl_cert and options.ssl_key):
125
    print >> sys.stderr, ("For secure mode please provide "
126
                         "--ssl-key and --ssl-cert arguments")
127
    sys.exit(1)
128

    
129
  return options, args
130

    
131

    
132
def main():
133
  """Main function.
134

    
135
  """
136
  options, args = ParseOptions()
137

    
138
  ssconf.CheckMaster(options.debug)
139

    
140
  if options.fork:
141
    utils.Daemonize(logfile=constants.LOG_RAPISERVER)
142

    
143
  logger.SetupLogging(constants.LOG_RAPISERVER, debug=options.debug,
144
                     stderr_logging=not options.fork)
145

    
146
  utils.WritePidFile(constants.RAPI_PID)
147

    
148
  log_fd = open(constants.LOG_RAPIACCESS, 'a')
149
  try:
150
    apache_log = http.ApacheLogfile(log_fd)
151
    httpd = RESTHttpServer(("", options.port), RESTRequestHandler,
152
                           httplog=apache_log)
153
    try:
154
      httpd.serve_forever()
155
    finally:
156
      httpd.server_close()
157
      utils.RemovePidFile(constants.RAPI_PID)
158

    
159
  finally:
160
    log_fd.close()
161

    
162
  sys.exit(0)
163

    
164

    
165
if __name__ == '__main__':
166
  main()