import asyncore
import asynchat
+import grp
import os
+import pwd
import signal
import logging
import sched
from ganeti import errors
+_DEFAULT_RUN_USER = "root"
+_DEFAULT_RUN_GROUP = "root"
+
+
class SchedulerBreakout(Exception):
"""Exception used to get out of the scheduler loop
def GenericMain(daemon_name, optionparser, dirs, check_fn, exec_fn,
multithreaded=False, console_logging=False,
- default_ssl_cert=None, default_ssl_key=None):
+ default_ssl_cert=None, default_ssl_key=None,
+ user=_DEFAULT_RUN_USER, group=_DEFAULT_RUN_GROUP):
"""Shared main function for daemons.
@type daemon_name: string
@param default_ssl_cert: Default SSL certificate path
@type default_ssl_key: string
@param default_ssl_key: Default SSL key path
+ @param user: Default user to run as
+ @type user: string
+ @param group: Default group to run as
+ @type group: string
"""
optionparser.add_option("-f", "--foreground", dest="fork",
utils.EnsureDirs(dirs)
if options.fork:
+ try:
+ uid = pwd.getpwnam(user).pw_uid
+ gid = grp.getgrnam(group).gr_gid
+ except KeyError:
+ raise errors.ConfigurationError("User or group not existing on system:"
+ " %s:%s" % (user, group))
utils.CloseFDs()
- utils.Daemonize(logfile=constants.DAEMONS_LOGFILES[daemon_name])
+ utils.Daemonize(constants.DAEMONS_LOGFILES[daemon_name], uid, gid)
utils.WritePidFile(daemon_name)
try:
logging.debug("Memory lock set")
-def Daemonize(logfile):
+def Daemonize(logfile, run_uid, run_gid):
"""Daemonize the current process.
This detaches the current process from the controlling terminal and
@type logfile: str
@param logfile: the logfile to which we should redirect stdout/stderr
+ @type run_uid: int
+ @param run_uid: Run the child under this uid
+ @type run_gid: int
+ @param run_gid: Run the child under this gid
@rtype: int
@return: the value zero
pid = os.fork()
if (pid == 0): # The first child.
os.setsid()
+ # FIXME: When removing again and moving to start-stop-daemon privilege drop
+ # make sure to check for config permission and bail out when invoked
+ # with wrong user.
+ os.setgid(run_gid)
+ os.setuid(run_uid)
# this might fail
pid = os.fork() # Fork a second child.
if (pid == 0): # The second child.