Beispiel #1
0
 def test_postOptionsNoSubCommandSavesAsUsual(self):
     """
     If no sub command is used, postOptions should not touch no_save.
     """
     config = twistd.ServerOptions()
     config.postOptions()
     self.assertEquals(config['no_save'], False)
Beispiel #2
0
    def test_setupEnvironment(self):
        """
        L{UnixApplicationRunner.startApplication} calls
        L{UnixApplicationRunner.setupEnvironment} with the chroot, rundir,
        nodaemon, umask, and pidfile parameters from the configuration it is
        constructed with.
        """
        options = twistd.ServerOptions()
        options.parseOptions([
                '--nodaemon',
                '--umask', '0070',
                '--chroot', '/foo/chroot',
                '--rundir', '/foo/rundir',
                '--pidfile', '/foo/pidfile'])
        application = service.Application("test_setupEnvironment")
        self.runner = UnixApplicationRunner(options)

        args = []
        def fakeSetupEnvironment(self, chroot, rundir, nodaemon, umask, pidfile):
            args.extend((chroot, rundir, nodaemon, umask, pidfile))

        # Sanity check
        self.assertEqual(
            inspect.getargspec(self.runner.setupEnvironment),
            inspect.getargspec(fakeSetupEnvironment))

        self.patch(UnixApplicationRunner, 'setupEnvironment', fakeSetupEnvironment)
        self.patch(UnixApplicationRunner, 'shedPrivileges', lambda *a, **kw: None)
        self.patch(app, 'startApplication', lambda *a, **kw: None)
        self.runner.startApplication(application)

        self.assertEqual(
            args,
            ['/foo/chroot', '/foo/rundir', True, 56, '/foo/pidfile'])
Beispiel #3
0
 def test_invalidUmask(self):
     """
     If a value is given for the C{umask} option which cannot be parsed as
     an integer, L{UsageError} is raised by L{ServerOptions.parseOptions}.
     """
     config = twistd.ServerOptions()
     self.assertRaises(UsageError, config.parseOptions, ['--umask', 'abcdef'])
Beispiel #4
0
 def setUp(self):
     config = twistd.ServerOptions()
     self.serviceMaker = MockServiceMaker()
     # Set up a config object like it's been parsed with a subcommand
     config.loadedPlugins = {'test_command': self.serviceMaker}
     config.subOptions = object()
     config.subCommand = 'test_command'
     self.config = config
Beispiel #5
0
 def test_postOptionsSubCommandCausesNoSave(self):
     """
     postOptions should set no_save to True when a subcommand is used.
     """
     config = twistd.ServerOptions()
     config.subCommand = 'ueoa'
     config.postOptions()
     self.assertEquals(config['no_save'], True)
Beispiel #6
0
 def test_listAllProfilers(self):
     """
     All the profilers that can be used in L{app.AppProfiler} are listed in
     the help output.
     """
     config = twistd.ServerOptions()
     helpOutput = str(config)
     for profiler in app.AppProfiler.profilers:
         self.assertIn(profiler, helpOutput)
Beispiel #7
0
 def test_createOrGetApplicationWithTapFile(self):
     """
     Ensure that the createOrGetApplication call that 'twistd -f foo.tap'
     makes will load the Application out of foo.tap.
     """
     config = twistd.ServerOptions()
     config.parseOptions(['-f', self.tapfile])
     application = CrippledApplicationRunner(config).createOrGetApplication()
     self.assertEquals(service.IService(application).name, 'Hi!')
Beispiel #8
0
 def test_reportProfileDeprecation(self):
     """
     Check that the --report-profile option prints a C{DeprecationWarning}.
     """
     config = twistd.ServerOptions()
     self.assertWarns(
         DeprecationWarning, "--report-profile option is deprecated and "
         "a no-op since Twisted 8.0.", app.__file__,
         config.parseOptions, ["--report-profile", "foo"])
Beispiel #9
0
 def test_umask(self):
     """
     The value given for the C{umask} option is parsed as an octal integer
     literal.
     """
     config = twistd.ServerOptions()
     config.parseOptions(['--umask', '123'])
     self.assertEqual(config['umask'], 83)
     config.parseOptions(['--umask', '0123'])
     self.assertEqual(config['umask'], 83)
Beispiel #10
0
    def test_unknownProfiler(self):
        """
        Check that L{app.AppProfiler} raises L{SystemExit} when given an
        unknown profiler name.
        """
        config = twistd.ServerOptions()
        config["profile"] = self.mktemp()
        config["profiler"] = "foobar"

        error = self.assertRaises(SystemExit, app.AppProfiler, config)
        self.assertEquals(str(error), "Unsupported profiler name: foobar")
Beispiel #11
0
 def test_badAttributeWithConfiguredLogObserver(self):
     """
     C{--logger} with a non-existent object raises a L{UsageError}.
     """
     config = twistd.ServerOptions()
     e = self.assertRaises(UsageError, config.parseOptions,
                           ["--logger", "twisted.test.test_twistd.FOOBAR"])
     self.assertTrue(e.args[0].startswith(
             "Logger 'twisted.test.test_twistd.FOOBAR' could not be "
             "imported: 'module' object has no attribute 'FOOBAR'"))
     self.assertNotIn('\n', e.args[0])
Beispiel #12
0
 def test_unimportableConfiguredLogObserver(self):
     """
     C{--logger} with an unimportable module raises a L{UsageError}.
     """
     config = twistd.ServerOptions()
     e = self.assertRaises(UsageError, config.parseOptions,
                       ['--logger', 'no.such.module.I.hope'])
     self.assertTrue(e.args[0].startswith(
             "Logger 'no.such.module.I.hope' could not be imported: "
             "'no.such.module.I.hope' does not name an object"))
     self.assertNotIn('\n', e.args[0])
Beispiel #13
0
 def test_nothotshotDeprecation(self):
     """
     Check that switching on the C{nothotshot} option produces a warning and
     sets the profiler to B{profile}.
     """
     config = twistd.ServerOptions()
     config['nothotshot'] = True
     profiler = self.assertWarns(DeprecationWarning,
         "The --nothotshot option is deprecated. Please specify the "
         "profiler name using the --profiler option",
         app.__file__, app.AppProfiler, config)
     self.assertEquals(profiler.profiler, "profile")
Beispiel #14
0
    def test_hotshotSaveStats(self):
        """
        With the C{savestats} option specified, L{app.HotshotRunner.run} should
        save the raw stats object instead of a summary output.
        """
        config = twistd.ServerOptions()
        config["profile"] = self.mktemp()
        config["profiler"] = "hotshot"
        config["savestats"] = True
        profiler = app.AppProfiler(config)
        reactor = DummyReactor()

        profiler.run(reactor)

        self.assertTrue(reactor.called)
        self._testStats(hotshot.stats.load, config['profile'])
Beispiel #15
0
    def test_withoutHotshot(self):
        """
        When the C{hotshot} module is not present, L{app.HotshotRunner.run}
        should raise a C{SystemExit} exception and log the C{ImportError}.
        """
        savedModules = sys.modules.copy()
        sys.modules["hotshot"] = None

        config = twistd.ServerOptions()
        config["profiler"] = "hotshot"
        profiler = app.AppProfiler(config)
        try:
            self.assertRaises(SystemExit, profiler.run, None)
        finally:
            sys.modules.clear()
            sys.modules.update(savedModules)
Beispiel #16
0
    def test_cProfile(self):
        """
        L{app.CProfileRunner.run} should call the C{run} method of the
        reactor and save profile data in the specified file.
        """
        config = twistd.ServerOptions()
        config["profile"] = self.mktemp()
        config["profiler"] = "cProfile"
        profiler = app.AppProfiler(config)
        reactor = DummyReactor()

        profiler.run(reactor)

        self.assertTrue(reactor.called)
        data = file(config["profile"]).read()
        self.assertIn("run", data)
        self.assertIn("function calls", data)
Beispiel #17
0
    def test_withoutProfile(self):
        """
        When the C{profile} module is not present, L{app.ProfilerRunner.run}
        should raise a C{SystemExit} exception.
        """
        savedModules = sys.modules.copy()

        config = twistd.ServerOptions()
        config["profiler"] = "profile"
        profiler = app.AppProfiler(config)

        sys.modules["profile"] = None
        try:
            self.assertRaises(SystemExit, profiler.run, None)
        finally:
            sys.modules.clear()
            sys.modules.update(savedModules)
Beispiel #18
0
    def test_cProfileSaveStats(self):
        """
        With the C{savestats} option specified,
        L{app.CProfileRunner.run} should save the raw stats object
        instead of a summary output.
        """
        config = twistd.ServerOptions()
        config["profile"] = self.mktemp()
        config["profiler"] = "cProfile"
        config["savestats"] = True
        profiler = app.AppProfiler(config)
        reactor = DummyReactor()

        profiler.run(reactor)

        self.assertTrue(reactor.called)
        data = file(config["profile"]).read()
        self.assertIn("run", data)
Beispiel #19
0
    def test_profilePrintStatsError(self):
        """
        When an error happens during the print of the stats, C{sys.stdout}
        should be restored to its initial value.
        """
        class ErroneousProfile(profile.Profile):
            def print_stats(self):
                raise RuntimeError("Boom")
        self.patch(profile, "Profile", ErroneousProfile)

        config = twistd.ServerOptions()
        config["profile"] = self.mktemp()
        config["profiler"] = "profile"
        profiler = app.AppProfiler(config)
        reactor = DummyReactor()

        oldStdout = sys.stdout
        self.assertRaises(RuntimeError, profiler.run, reactor)
        self.assertIdentical(sys.stdout, oldStdout)
Beispiel #20
0
    def test_hotshotPrintStatsError(self):
        """
        When an error happens while printing the stats, C{sys.stdout}
        should be restored to its initial value.
        """
        import pstats
        class ErroneousStats(pstats.Stats):
            def print_stats(self):
                raise RuntimeError("Boom")
        self.patch(pstats, "Stats", ErroneousStats)

        config = twistd.ServerOptions()
        config["profile"] = self.mktemp()
        config["profiler"] = "hotshot"
        profiler = app.AppProfiler(config)
        reactor = DummyReactor()

        oldStdout = sys.stdout
        self.assertRaises(RuntimeError, profiler.run, reactor)
        self.assertIdentical(sys.stdout, oldStdout)
Beispiel #21
0
    def test_subCommands(self):
        """
        subCommands is built from IServiceMaker plugins, and is sorted
        alphabetically.
        """
        class FakePlugin(object):
            def __init__(self, name):
                self.tapname = name
                self._options = 'options for ' + name
                self.description = 'description of ' + name

            def options(self):
                return self._options

        apple = FakePlugin('apple')
        banana = FakePlugin('banana')
        coconut = FakePlugin('coconut')
        donut = FakePlugin('donut')

        def getPlugins(interface):
            self.assertEqual(interface, IServiceMaker)
            yield coconut
            yield banana
            yield donut
            yield apple

        config = twistd.ServerOptions()
        self.assertEqual(config._getPlugins, plugin.getPlugins)
        config._getPlugins = getPlugins

        # "subCommands is a list of 4-tuples of (command name, command
        # shortcut, parser class, documentation)."
        subCommands = config.subCommands
        expectedOrder = [apple, banana, coconut, donut]

        for subCommand, expectedCommand in zip(subCommands, expectedOrder):
            name, shortcut, parserClass, documentation = subCommand
            self.assertEqual(name, expectedCommand.tapname)
            self.assertEqual(shortcut, None)
            self.assertEqual(parserClass(), expectedCommand._options),
            self.assertEqual(documentation, expectedCommand.description)
Beispiel #22
0
    def test_sortedReactorHelp(self):
        """
        Reactor names are listed alphabetically by I{--help-reactors}.
        """
        class FakeReactorInstaller(object):
            def __init__(self, name):
                self.shortName = 'name of ' + name
                self.description = 'description of ' + name

        apple = FakeReactorInstaller('apple')
        banana = FakeReactorInstaller('banana')
        coconut = FakeReactorInstaller('coconut')
        donut = FakeReactorInstaller('donut')

        def getReactorTypes():
            yield coconut
            yield banana
            yield donut
            yield apple

        config = twistd.ServerOptions()
        self.assertEqual(config._getReactorTypes, reactors.getReactorTypes)
        config._getReactorTypes = getReactorTypes
        config.messageOutput = StringIO.StringIO()

        self.assertRaises(SystemExit, config.parseOptions, ['--help-reactors'])
        helpOutput = config.messageOutput.getvalue()
        indexes = []
        for reactor in apple, banana, coconut, donut:
            def getIndex(s):
                self.assertIn(s, helpOutput)
                indexes.append(helpOutput.index(s))

            getIndex(reactor.shortName)
            getIndex(reactor.description)

        self.assertEqual(
            indexes, sorted(indexes),
            'reactor descriptions were not in alphabetical order: %r' % (
                helpOutput,))
Beispiel #23
0
    def test_legacyApplicationRunnerGetLogObserver(self):
        """
        L{app.ApplicationRunner} subclasses can have a getLogObserver that used
        to return a log observer. This test is there to ensure that it's
        supported but it raises a warning when used.
        """
        observer = []
        self.addCleanup(log.removeObserver, observer.append)

        class GetLogObserverRunner(app.ApplicationRunner):
            def getLogObserver(self):
                return observer.append

            def startLogging(self, observer):
                """
                Override C{startLogging} to call L{log.addObserver} instead of
                L{log.startLoggingWithObserver}.
                """
                log.addObserver(observer)
                self.logger._initialLog()

            def preApplication(self):
                pass

            def postApplication(self):
                pass

            def createOrGetApplication(self):
                pass

        conf = twistd.ServerOptions()
        runner = GetLogObserverRunner(conf)
        self.assertWarns(
            DeprecationWarning,
            "Specifying a log observer with getLogObserver is "
            "deprecated. Please use a loggerFactory instead.", app.__file__,
            runner.run)
        self.assertEquals(len(observer), 3)
Beispiel #24
0
def daemon(**kwargs):
    """When this function returns, you are a daemon.
       If use_syslog is specified then this installs a logger.
       Iff capture_output is specified then stdout and stderr
       are also directed to syslog.

       valid kwargs:

         - pidfile,
         - logfile,
         - capture_output,    # log stdout and stderr?
         - capture_stdout_name   # getLogger(capture_name) for captured stdout stderr
         - capture_stdout_log_level
         - capture_stderr_name
         - capture_stderr_log_level
         - twisted_info_log_level  # log level for non-errors coming from twisted logging.
         - twisted_error_log_level # log level for errors coming from twisted logging.
         - log_level          # log only things ith level >= log_level.
         - use_syslog, and    # output to syslog.
         - anything defined by twistd.ServerOptions.
    """
    if os.name == 'mac':
        raise NotImplementedError("Daemonization doesn't work on macs.")

    if noisy:
        print "in daemon"
    uid = os.getuid()
    gid = os.getgid()
    if uid == 0 and not kwargs.has_key("username"):
        raise Exception(
            "If you start with root privileges you need to "
            "provide a username argument so that daemon() can shed those "
            "privileges before returning.")
    if kwargs.has_key("username") and kwargs["username"]:
        username = kwargs["username"]
        uid = getuid_from_username(username)
        if noisy:
            print "setting username to uid of '%s', which is %d." % (username,
                                                                     uid)
        if uid != os.getuid() and os.getuid() != 0:
            raise Exception(
                "When specifying a uid other than your own "
                "you must be running as root for setuid to work. "
                "Your uid is %d, while the specified user '%s' has uid %d." %
                (os.getuid(), username, uid))
        gid = getgid_from_username(username)  # uses this user's group
        del kwargs["username"]
    if kwargs.has_key("groupname") and kwargs["groupname"]:
        groupname = kwargs["groupname"]
        if noisy:
            print "setting groupname to gid of '%s', which is %d." % (
                groupname, gid)
        gid = getgid_from_groupname(groupname)
        del kwargs["groupname"]
    capture_output = kwargs.get("capture_output", False)
    if kwargs.has_key("capture_output"):
        del kwargs["capture_output"]
    capture_stdout_name = kwargs.get("capture_stdout_name", "stdout")
    if kwargs.has_key("capture_stdout_name"):
        del kwargs["capture_stdout_name"]
    capture_stderr_name = kwargs.get("capture_stderr_name", "stderr")
    if kwargs.has_key("capture_stderr_name"):
        del kwargs["capture_stderr_name"]
    capture_stdout_log_level = kwargs.get("capture_stdout_log_level",
                                          logging.INFO)
    if kwargs.has_key("capture_stdout_log_level"):
        del kwargs["capture_stdout_log_level"]
    capture_stderr_log_level = kwargs.get("capture_stderr_log_level",
                                          logging.INFO)
    if kwargs.has_key("capture_stderr_log_level"):
        del kwargs["capture_stderr_log_level"]
    log_level = kwargs.get("log_level", logging.INFO)
    if kwargs.has_key("log_level"):
        del kwargs["log_level"]
    twisted_info_log_level = kwargs.get("twisted_info_log_level", logging.INFO)
    if kwargs.has_key("twisted_info_log_level"):
        del kwargs["twisted_info_log_level"]
    twisted_error_log_level = kwargs.get("twisted_error_log_level",
                                         logging.ERROR)
    if kwargs.has_key("twisted_error_log_level"):
        del kwargs["twisted_error_log_level"]

    pid_dir = os.path.join("/var/run/", app_name)
    pidfile = os.path.join(pid_dir, app_name + ".pid")
    if not isinstance(kwargs, twistd.ServerOptions):
        config = twistd.ServerOptions()
        for k in kwargs:
            config[k] = kwargs[k]
    config['daemon'] = True
    if config.has_key("pidfile"):
        pidfile = config['pidfile']
    else:
        config['pidfile'] = pidfile
    pid_dir = os.path.split(pidfile)[0]
    if pid_dir and not os.path.exists(pid_dir):
        os.mkdir(pid_dir)
        os.chown(pid_dir, uid, gid)
    twistd.checkPID(pidfile)
    logfile = config.get('log_file', None)
    use_syslog = config.get('use_syslog', sys.platform != 'darwin'
                            and not logfile)
    if config.has_key('logfile') and config['logfile']:
        if 'use_syslog' in config and config['use_syslog']:
            raise Exception(
                "You have specified both a logfile and "
                "that the daemon should use_syslog.  Specify one or "
                "the other.")
        injectLogger(use_syslog=False,
                     log_file=config['logfile'],
                     log_level=log_level,
                     capture_output=capture_output,
                     capture_stdout_name=capture_stdout_name,
                     capture_stderr_name=capture_stderr_name,
                     twisted_info_log_level=twisted_info_log_level,
                     twisted_error_log_level=twisted_error_log_level,
                     capture_stdout_log_level=capture_stdout_log_level,
                     capture_stderr_log_level=capture_stderr_log_level)
    elif use_syslog:
        injectLogger(use_syslog=True,
                     log_level=log_level,
                     capture_output=capture_output,
                     capture_stdout_name=capture_stdout_name,
                     capture_stderr_name=capture_stderr_name,
                     twisted_info_log_level=twisted_info_log_level,
                     twisted_error_log_level=twisted_error_log_level,
                     capture_stdout_log_level=capture_stdout_log_level,
                     capture_stderr_log_level=capture_stderr_log_level)
    else:
        raise Exception("You are attempting to daemonize without a log file,"
                        "and with use_syslog set to false.  A daemon must "
                        "output to syslog, a logfile, or both.")
    twistd.setupEnvironment(config)  # forks, moves into its own process
    # group, forks again, middle process
    # exits with status 0.  Creates pid
    # file. Also redirects stdout, stderr
    # to /dev/null.
    # I should now be a daemon.

    # pid file can be removed because it is in a subdirectory
    # of /var/run that is owned by the user id running
    # the service and not by root.
    #
    # Dave says, "daemon no longer removes pid file.  If
    # monitors see a pidfile exists and the process is not
    # running then the monitor will restart the process.
    # If you want the process to REALLY die then the
    # pid file should be removed external to the program,
    # e.g., by an init.d script that is passed "stop".
    #
    #def rmpid():
    #    if os.path.exists(pidfile):
    #        try:
    #            os.unlink(pidfile)
    #        except Exception,e:
    #            log.error( str(e), exc_info = sys.exc_info())
    #atexit.register(rmpid)

    if not os.path.exists(pidfile):
        raise Exception("pidfile %s does not exist" % pidfile)

    os.chown(pidfile, uid, gid)
    os.chmod(pidfile,
             stat.S_IRUSR | stat.S_IWUSR | stat.S_IROTH | stat.S_IRGRP)

    if os.getuid() == 0:
        twistd.shedPrivileges(False, uid, gid)
    if os.getuid() != uid:
        raise Exception("twistd failed to setuid to uid %d" % uid)
    if os.getgid() != gid:
        raise Exception("twistd failed to setgid to gid %d" % gid)
Beispiel #25
0
 def test_defaultUmask(self):
     """
     The default value for the C{umask} option is C{None}.
     """
     config = twistd.ServerOptions()
     self.assertEqual(config['umask'], None)
def run_app():
    """Runs the application using opennode/oms.tac"""
    config = twistd.ServerOptions()
    config.parseOptions(['-ny', '%s/opennode/oms.tac' % (get_base_dir(), )])
    twistd._SomeApplicationRunner(config).run()