summaryrefslogtreecommitdiffstats
path: root/ipa-server/ipa-gui/ipa_webgui
blob: 677fc9a5bce4cb92e34ecae5e6548373bbaa0f1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#! /usr/bin/python -E
#
# Copyright (C) 2007  Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; version 2 only
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

import os, sys, pwd, grp
from optparse import OptionParser
import traceback
import logging
import signal

def usage():
    print "ipa_webgui [-f|--foreground] [-d|--debug]"
    sys.exit(1)

def parse_options():
    parser = OptionParser()
    parser.add_option("-f", "--foreground", dest="foreground",
                      action="store_true", default=False,
                      help="Remain in the foreground")
    parser.add_option("-d", "--debug", dest="debug", action="store_true",
                      default=False,
                      help="Increase the amount of logging information")
    parser.add_option("--usage", action="store_true",
                      help="Program usage")

    options, args = parser.parse_args(sys.argv)

    return options, args

def daemonize():
    # fork once so the parent can exit
    try:
        pid = os.fork()
    except OSError, e:
        raise Exception, "%s [%d]" % (e.strerror, e.errno)

    if pid != 0:
        os._exit(0)

    # become session leader
    os.setsid()
    
    # fork again to reparent to init
    try:
        pid = os.fork()
    except OSError, e:
        raise Exception, "%s [%d]" % (e.strerror, e.errno)

    if pid != 0:
        os._exit(0)

    os.chdir("/")
    os.umask(0)

    import resource
    maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
    if (maxfd == resource.RLIM_INFINITY):
        maxfd = 1024
      
    # close all file descriptors
    for fd in range(0, maxfd):
        try:
            os.close(fd)
        except OSError:
            pass

    # stdin
    os.open("/dev/null", os.O_RDWR)
    # stdout
    os.open("/dev/null", os.O_RDWR)
    # stderr
    os.open("/dev/null", os.O_RDWR)

def main():
    options, args = parse_options()

    foreground = options.foreground

    if options.debug:
        loglevel = logging.DEBUG
    else:
        loglevel = logging.WARN
    
    # To make development easier, we detect if we are in the development
    # environment to load a different configuration and avoid becoming
    # a daemon
    devel = False
    if os.path.exists(os.path.join(os.path.dirname(__file__), "Makefile.am")):
        devel = True
        foreground = True

    if not foreground:
        try:
            daemonize()
        except Exception, e:
            sys.stderr.write("error becoming daemon: " + str(e))
            sys.exit(1)

    if not foreground:
        try:
            daemonize()
        except Exception, e:
            sys.stderr.write("error becoming daemon: " + str(e))
            sys.exit(1)

    # Drop privileges and write our pid file only if we're running as root
    if os.getuid() == 0:
        # Write out our pid file
        pidfile = open("/var/run/ipa_webgui.pid", "w")
        pidfile.write(str(os.getpid()))
        pidfile.close()

        # Drop privs
        apache_uid = pwd.getpwnam("apache")[2]
        apache_gid = grp.getgrnam("apache")[2]

        try:
            os.setgid(apache_gid)
        except OSError, e:
            log.error("Could not set effective group id: %s" % e)

        try:
            os.setuid(apache_uid)
        except OSError, e:
            log.error("Could not set effective user id: %s" % e)

    if foreground:
        logging.basicConfig(level=loglevel,
                            format='%(asctime)s %(name)s %(levelname)s %(message)s',
                            stream=sys.stderr)
    else:
        # This log file name needs to be kept in sync with the one in
        # ipa_webgui.cfg
        logging.basicConfig(level=loglevel,
                            format='%(asctime)s %(name)s %(levelname)s %(message)s',
                            filename='/var/log/ipa_error.log')

    sys.path.append("/usr/share/ipa")

    # this must be after sys.path is changed to work correctly
    import pkg_resources
    pkg_resources.require("TurboGears")
    pkg_resources.require("ipa_gui")

    from turbogears import update_config, start_server
    from turbogears.config import update
    import cherrypy
    cherrypy.lowercase_api = True

    try:
        if hasattr(signal, "SIGTERM"):
            def SIGTERM(signum=None, frame=None):
                cherrypy.server.stop()
            signal.signal(signal.SIGTERM, SIGTERM)
    except ValueError, _signal_exc:
        if _signal_exc.args[0] != "signal only works in main thread":
            raise


    # Shut down the logging set up here so that CherryPy logging can take
    # over. TurboGears configuration errors will not be caught.
    if not foreground:
        logging.shutdown()

    # Load the config - look for a local file first for development
    # and then the system config file
    if devel:
        update_config(configfile="dev.cfg",
                      modulename="ipagui.config")
        update( { "i18n.locale_dir": "locales"} )
    else:
        update_config(configfile="/usr/share/ipa/ipa_webgui.cfg",
                      modulename="ipagui.config.app")
        update( { "i18n.locale_dir": "/usr/share/ipa/locales"} )

    from ipagui.controllers import Root

    start_server(Root())

try:
    main()
    sys.exit(0)
except SystemExit, e:
    sys.exit(e)
except Exception, e:
    message = "failed to start web gui: %s" % str(e)
    print message
    for str in traceback.format_tb(sys.exc_info()[2]):
        message = message + "\n" + str
    logging.error(message)

    sys.exit(1)