PageRenderTime 57ms CodeModel.GetById 29ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/circuits/app/startup.py

https://bitbucket.org/prologic/circuits/
Python | 127 lines | 114 code | 1 blank | 12 comment | 0 complexity | e1bfb764aa1c36ef08c0c2169fdd5b85 MD5 | raw file
  1# Module:   startup
  2# Date:     21st March 2011
  3# Author:   James Mills, jamesmills at comops dot com dot au
  4
  5"""Startup Component
  6
  7This module implements a ``Startup`` Component that create a unified
  8way of creating, managing and running an application in conjunction with
  9an environment (``circuits.app.env``). The ``Startup`` Component provides
 10five verbs that can be passed as command-line arguments:
 11- start   -- Start the application
 12- stop    -- Stop the application
 13- init    -- Create the application environment
 14- rehash  -- Reload the application's environment
 15- upgrade -- Upgrade the application's environment
 16"""
 17
 18import os
 19import errno
 20from time import sleep
 21try:
 22    from signal import SIGINT, SIGHUP, SIGTERM
 23except ImportError:
 24    # Windows doesn't share Unix's signal mechanism
 25    SIGINT = None
 26    SIGHUP = None
 27    SIGTERM = None
 28
 29from circuits import handler, Event, BaseComponent
 30
 31from .daemon import Daemon
 32from .env import Environment
 33from .env import Create, Load, Upgrade
 34
 35
 36class Error(Exception):
 37    """Error Exception"""
 38
 39
 40class Command(Event):
 41    """Command Event"""
 42
 43
 44class Terminate(Event):
 45    """Terminate Event"""
 46
 47
 48class Startup(BaseComponent):
 49
 50    channel = "startup"
 51
 52    def __init__(self, path, opts, command, env=Environment,
 53            channel=channel):
 54        super(Startup, self).__init__(channel=channel)
 55
 56        self.path = path
 57        self.opts = opts
 58        self.command = command
 59
 60        self.env = env(path).register(self)
 61
 62    def _getpid(self):
 63        with open(self.config.get("general", "pidfile"), "r") as f:
 64            return int(f.read().strip())
 65
 66    def __tick__(self):
 67        if not self.command == "start" and not self:
 68            self.stop()
 69
 70    @handler("signal", target="*")
 71    def _on_signal(self, signal, track):
 72        if signal in (SIGINT, SIGTERM):
 73            self.fire(Terminate())
 74
 75    @handler("environment_loaded", target="env")
 76    def _on_environment_loaded(self, *args):
 77        self.fire(Command(), self.command, self)
 78
 79    @handler("started")
 80    def _on_started(self, component, mode):
 81        if not self.command == "init":
 82            if not os.path.exists(self.env.path):
 83                raise Error("Environment does not exist!")
 84            else:
 85                self.fire(LoadEnvironment(), target=self.env)
 86        else:
 87            if os.path.exists(self.env.path):
 88                raise Error("Environment already exists!")
 89            else:
 90                self.fire(Command(), self.command, self)
 91
 92    @handler("start")
 93    def _on_start(self):
 94        if self.opts.daemon:
 95            pidfile = self.env.config.get("general", "pidfile", "app.pid")
 96            Daemon(pidfile, self.env.path).register(self)
 97
 98    @handler("stop")
 99    def _on_stop(self):
100        pid = self._getpid()
101
102        try:
103            os.kill(pid, SIGTERM)
104            os.waitpid(pid, os.WTERMSIG(0))
105        except OSError as e:
106            if not e.args[0] == errno.ECHILD:
107                raise
108
109    @handler("restart")
110    def _on_restart(self):
111        self.fire(Command(), "stop", self.channel)
112        sleep(1)
113        self.fire(Command(), "start", self.channel)
114
115    @handler("rehash")
116    def _on_rehash(self):
117        pid = self._getpid()
118
119        os.kill(pid, SIGHUP)
120
121    @handler("init")
122    def _on_init(self):
123        self.fire(CreateEnvironment(), target=self.env)
124
125    @handler("upgrade")
126    def _on_upgrade(self):
127        self.fire(UpgradeEnvironment(), target=self.env)