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.12 by valya, Fri Oct 8 18:14:38 2010 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 (iargs):
141 +    validArguments = ["start",
142 +                      "stop",
143 +                      "restart",
144 +                      "status"]
145 +    validOptions = ["--cfg", "--force-kill", "--pid-file",
146 +                    "--log-file", "--log-level"]
147 +
148 +    args = []
149 +    for arg in iargs:
150 +        for item in arg.split('='):
151 +            args.append(item)
152 +    result = []
153 +    for i in range (0, len (iargs)):
154 +        arg = sys.argv[i]
155 +        if arg in validArguments:
156 +            result.append (args[i])
157 +    
158 +    for i in range (0, len (args)):
159 +        option = args[i]
160 +        if option in validOptions:
161 +            result.append (option)
162 +            result.append (args[i+1])
163 +    return result
164 +
165 + class CmsWebApplication (object):
166 +    def __init__ (self):
167 +        self.context = Context ()
168 +        self.context.addService (OptionParser ())
169 +        self.parser = self.context.OptionParser ()
170 +        self.__addOptions ()
171 +        
172 +    def __addOptions (self):
173 +        self.parser.add_option ("--profile",
174 +                           help="start server in profiler mode",
175 +                           default=False,
176 +                           action="store_true",
177 +                           dest="profile")
178 +
179 +        self.parser.add_option ("--pid-file",
180 +                           help="File in which it is specified the pid of wanted instance",
181 +                           default="pid.txt",
182 +                           dest="pidFile",
183 +                           metavar="FILE")
184 +
185 +        self.parser.add_option ("--force-kill",
186 +                           help="Uses SIGKILL rather than SIGTERM",
187 +                           default=False,
188 +                           action="store_true",
189 +                           dest="forceKill",
190 +                           metavar="FILE")
191 +                          
192 +        def openFilename (option, opt_str, value, parser, *args, **kwargs):
193 +            try:
194 +                f=open (value, 'a')
195 +            except IOError:
196 +                print "WARNING: Unable to open log file %s. Using stderr." % value
197 +                f=sys.stderr
198 +            setattr (parser.values, option.dest, f)
199 +        
200 +        self.parser.add_option ("--log-file",
201 +                           help="FILE to which redirect log messages",
202 +                           dest="logFile",
203 +                           default=sys.stderr,
204 +                           action="callback",
205 +                           callback=openFilename,
206 +                           metavar="FILENAME",
207 +                           type="str",
208 +                           nargs=1)
209 +                          
210 +        self.parser.add_option ("--log-level",
211 +                            help="detail LEVEL for the main log",
212 +                            dest="logLevel",
213 +                            default=10,
214 +                            metavar="LEVEL",
215 +                            type="int")
216 +    
217 +    def run (self):
218 +        if "--help" in sys.argv:
219 +            g_Logger.detailLevel = -100
220 +        validOptions = getValidOptions (sys.argv)
221 +
222 +        opts, args = self.parser.parse_args (args=validOptions)
223 +
224 +        g_Logger.stream = opts.logFile
225 +        if "--help" not in sys.argv:
226 +            g_Logger.detailLevel = opts.logLevel
227 +        
228 +        if not len (args):
229 +            args = ["start"]
230 +        
231 +        factory = CommandFactory (self.context, opts, args)
232 +        startCommand = factory.createByName (args[0])
233 +        if not startCommand:
234 +            "Command %s not known." % args[0]
235 +            sys.exit (1)
236 +        startCommand.run ()
237 +        startCommand.finish ()
238  
239   if __name__ == '__main__':
240 <    app = BonsaiServer (socket_port=8030)
241 <    app.start ()
240 >    app = CmsWebApplication ()
241 >    app.run ()

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines