ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/WEBTOOLS/cmsWeb.py
(Generate patch)

Comparing COMP/WEBTOOLS/cmsWeb.py (file contents):
Revision 1.1 by eulisse, Mon Mar 12 10:39:07 2007 UTC vs.
Revision 1.11 by eulisse, Mon Jun 9 10:16:45 2008 UTC

# Line 1 | Line 1
1   #!/usr/bin/env python
2   from Framework import BonsaiServer
3 + from Framework import Context
4 + from Framework.Logger import Logger
5 + from Framework.Logger import g_Logger
6 + from optparse import OptionParser
7 + from Framework import CmdLineArgs
8 + import sys
9 + import os
10 + import getpass
11 + from os.path import abspath
12 + import errno
13 +
14 + class Cfg:
15 +    def __init__ (self):
16 +        # TODO: make it a property.
17 +        self.installRoot = __file__.rsplit ("/", 1)[0]
18 +
19 + class CommandFactory (object):
20 +    def __init__ (self, context, opts, args):
21 +        self.context = context
22 +        self.registry = {"start": StartCommand,
23 +                         "status": StatusCommand,
24 +                         "stop": StopCommand}
25 +        self.opts, self.args = opts, args
26 +    
27 +    def createByName (self, name):
28 +        try:
29 +            obj = self.registry[name] ()
30 +        except KeyError:
31 +            return None
32 +        obj.context = self.context
33 +        obj.opts = self.opts
34 +        obj.args = self.args
35 +        return obj
36 +
37 + class Command (object):
38 +    def __init__ (self):
39 +        self.context = None
40 +        self.opts = None
41 +        self.args = None
42 +
43 +    def finish (self):
44 +        pass
45 +
46 + def checkIfPidRunning (pid):
47 +    try:
48 +        os.kill(pid, 0)
49 +        return True
50 +    except OSError, err:
51 +        return err.errno == errno.EPERM
52 +
53 + def getPidFromFile (filename):
54 +    try:
55 +        return int (open (filename).read ().strip ())
56 +    except ValueError:
57 +        print "Invalid lockfile format for %s." % filename
58 +        print "Cannot detect status."
59 +        sys.exit (2)
60 +
61 + class StatusCommand (Command):
62 +    def run (self):
63 +        filename = abspath (self.opts.pidFile)
64 +        try:
65 +            pid = getPidFromFile (filename)
66 +            if checkIfPidRunning (pid):
67 +                print "cmsWeb is running as pid %s" % pid
68 +                sys.exit (0)
69 +            print "cmsWeb not running."
70 +        except IOError:
71 +            print "File %s does not exists." % self.opts.pidFile
72 +            print "Cannot detect status."
73 +            sys.exit (2)
74 +
75 + class StopCommand (Command):
76 +    def run (self):
77 +        filename = abspath (self.opts.pidFile)
78 +        username = getpass.getuser ()
79 +        
80 +        try:
81 +            pid = getPidFromFile (filename)
82 +            if self.opts.forceKill == True:
83 +                print "Sending SIGKILL to pid %s" % pid
84 +                os.kill (pid, 9)
85 +                sys.exit (0)
86 +            print "Sending SIGTERM to pid %s" % pid
87 +            os.kill (pid, 15)
88 +        except OSError, err:
89 +            if err.errno == errno.EPERM:
90 +                print "Pid %s is not owned by user %s. Cannot stop it." % (pid, username)
91 +                sys.exit (2)
92 +            else:
93 +                print "Pid %s does not exists. Please remove the lock file %s." % (pid, filename)
94 +        except IOError:
95 +            print "File %s does not exists." % self.opts.pidFile
96 +            print "Cannot detect status."
97 +            sys.exit (2)
98 +        
99 +
100 + class StartCommand (Command):
101 +    def run (self):
102 +        app = BonsaiServer (self.context)
103 +        opts, args = self.context.OptionParser ().parse_args ()
104 +        filename = abspath (self.opts.pidFile)
105 +        try:
106 +            pid = getPidFromFile (filename)
107 +            if checkIfPidRunning (pid):
108 +                print "A process %s is alredy running using lock file %s. Nothing is done." % (pid, filename)
109 +                sys.exit (0)
110 +            else:
111 +                print "Process %s died unexpectedly. Removing lockfile %s." % (pid, filename)
112 +                os.unlink (filename)
113 +        except IOError:
114 +            # TODO: this should be a warning.
115 +            g_Logger.trace ("File %s does not exists. Will be created." % filename)
116 +        
117 +        open (filename, 'w').write (str (os.getpid ()))
118 +        self.context.addService (CmdLineArgs (self.context.OptionParser ()))
119 +        self.context.addService (Cfg ())
120 +        if opts.profile:
121 +            import pstats
122 +            try:
123 +                import cProfile as profile
124 +            except ImportError:
125 +                import profile
126 +            profile.run ('app.start ()', 'bonsaiProfiler')
127 +
128 +            p = pstats.Stats ('bonsaiProfiler')
129 +            p.strip_dirs().sort_stats (-1).print_stats()        
130 +        else:
131 +            app.start ()
132 +    
133 +    def finish (self):
134 +        filename = abspath (self.opts.pidFile)
135 +        try:
136 +            os.unlink (filename)
137 +        except IOError:
138 +            print "Unable to remove lock file %s" % filename
139 +
140 + def getValidOptions (args):
141 +    validArguments = ["start",
142 +                      "stop",
143 +                      "restart",
144 +                      "status"]
145 +    validOptions = ["--cfg", "--force-kill", "--pid-file",
146 +                    "--log-file", "--log-level"]
147 +
148 +    result = []
149 +    for i in range (0, len (args)):
150 +        arg = sys.argv[i]
151 +        if arg in validArguments:
152 +            result.append (args[i])
153 +    
154 +    for i in range (0, len (args)):
155 +        option = args[i]
156 +        if option in validOptions:
157 +            result.append (option)
158 +            result.append (args[i+1])
159 +    return result
160 +
161 + class CmsWebApplication (object):
162 +    def __init__ (self):
163 +        self.context = Context ()
164 +        self.context.addService (OptionParser ())
165 +        self.parser = self.context.OptionParser ()
166 +        self.__addOptions ()
167 +        
168 +    def __addOptions (self):
169 +        self.parser.add_option ("--profile",
170 +                           help="start server in profiler mode",
171 +                           default=False,
172 +                           action="store_true",
173 +                           dest="profile")
174 +
175 +        self.parser.add_option ("--pid-file",
176 +                           help="File in which it is specified the pid of wanted instance",
177 +                           default="pid.txt",
178 +                           dest="pidFile",
179 +                           metavar="FILE")
180 +
181 +        self.parser.add_option ("--force-kill",
182 +                           help="Uses SIGKILL rather than SIGTERM",
183 +                           default=False,
184 +                           action="store_true",
185 +                           dest="forceKill",
186 +                           metavar="FILE")
187 +                          
188 +        def openFilename (option, opt_str, value, parser, *args, **kwargs):
189 +            try:
190 +                f=open (value, 'a')
191 +            except IOError:
192 +                print "WARNING: Unable to open log file %s. Using stderr." % value
193 +                f=sys.stderr
194 +            setattr (parser.values, option.dest, f)
195 +        
196 +        self.parser.add_option ("--log-file",
197 +                           help="FILE to which redirect log messages",
198 +                           dest="logFile",
199 +                           default=sys.stderr,
200 +                           action="callback",
201 +                           callback=openFilename,
202 +                           metavar="FILENAME",
203 +                           type="str",
204 +                           nargs=1)
205 +                          
206 +        self.parser.add_option ("--log-level",
207 +                            help="detail LEVEL for the main log",
208 +                            dest="logLevel",
209 +                            default=10,
210 +                            metavar="LEVEL",
211 +                            type="int")
212 +    
213 +    def run (self):
214 +        if "--help" in sys.argv:
215 +            g_Logger.detailLevel = -100
216 +        validOptions = getValidOptions (sys.argv)
217 +
218 +        opts, args = self.parser.parse_args (args=validOptions)
219 +
220 +        g_Logger.stream = opts.logFile
221 +        if "--help" not in sys.argv:
222 +            g_Logger.detailLevel = opts.logLevel
223 +        
224 +        if not len (args):
225 +            args = ["start"]
226 +        
227 +        factory = CommandFactory (self.context, opts, args)
228 +        startCommand = factory.createByName (args[0])
229 +        if not startCommand:
230 +            "Command %s not known." % args[0]
231 +            sys.exit (1)
232 +        startCommand.run ()
233 +        startCommand.finish ()
234  
235   if __name__ == '__main__':
236 <    app = BonsaiServer (socket_port=8030)
237 <    app.start ()
236 >    app = CmsWebApplication ()
237 >    app.run ()

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines