ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/WEBTOOLS/cmsWeb.py
Revision: 1.8
Committed: Mon Mar 3 16:42:59 2008 UTC (17 years, 1 month ago) by eulisse
Content type: text/x-python
Branch: MAIN
CVS Tags: V01-03-03, V01-03-02
Changes since 1.7: +34 -6 lines
Log Message:
Misc Logger related issues.
* Refactored the Logger class to allow hierarchies of loggers. Children loggers
  can change their configuration but not parents one (for example they can
  have a different log level than the parent one).
* cmsWeb.py adapted to work with the new Logger, now there are two options:
  --log-level and --log-file to configure the general logging parameters.
  Controllers/Services can still define their own command line options to
  have more control on their logging.
* Better unittesting of the Logger class.

File Contents

# User Rev Content
1 eulisse 1.1 #!/usr/bin/env python
2     from Framework import BonsaiServer
3 eulisse 1.2 from Framework import Context
4 eulisse 1.8 from Framework.Logger import Logger
5     from Framework.Logger import g_Logger
6 eulisse 1.2 from optparse import OptionParser
7     from Framework import CmdLineArgs
8 eulisse 1.5 import sys
9 eulisse 1.6 import os
10     import getpass
11     from os.path import abspath
12     import errno
13 eulisse 1.1
14 eulisse 1.3 class Cfg:
15     def __init__ (self):
16     # TODO: make it a property.
17     self.installRoot = __file__.rsplit ("/", 1)[0]
18    
19 eulisse 1.5 class CommandFactory (object):
20 eulisse 1.7 def __init__ (self, context, opts, args):
21 eulisse 1.5 self.context = context
22 eulisse 1.6 self.registry = {"start": StartCommand,
23     "status": StatusCommand,
24     "stop": StopCommand}
25 eulisse 1.7 self.opts, self.args = opts, args
26 eulisse 1.5
27     def createByName (self, name):
28     try:
29     obj = self.registry[name] ()
30     except KeyError:
31     return None
32     obj.context = self.context
33 eulisse 1.6 obj.opts = self.opts
34     obj.args = self.args
35 eulisse 1.5 return obj
36    
37     class Command (object):
38     def __init__ (self):
39     self.context = None
40 eulisse 1.6 self.opts = None
41     self.args = None
42 eulisse 1.5
43 eulisse 1.6 def finish (self):
44 eulisse 1.5 pass
45    
46 eulisse 1.6 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." % 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 eulisse 1.7 username = getpass.getuser ()
79 eulisse 1.6
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 eulisse 1.8 print "File %s does not exists." % self.opts.pidFile
96 eulisse 1.6 print "Cannot detect status."
97     sys.exit (2)
98    
99    
100     class StartCommand (Command):
101 eulisse 1.5 def run (self):
102     app = BonsaiServer (self.context)
103 eulisse 1.7 opts, args = self.context.OptionParser ().parse_args ()
104 eulisse 1.6 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     print "File %s does not exists. Will be created." % filename
116    
117     open (filename, 'w').write (str (os.getpid ()))
118 eulisse 1.7 self.context.addService (CmdLineArgs (self.context.OptionParser ()))
119 eulisse 1.6 self.context.addService (Cfg ())
120 eulisse 1.5 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 eulisse 1.6 p = pstats.Stats ('bonsaiProfiler')
129     p.strip_dirs().sort_stats (-1).print_stats()
130 eulisse 1.5 else:
131     app.start ()
132 eulisse 1.6
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 eulisse 1.5
140     def getValidOptions (args):
141     validArguments = ["start",
142     "stop",
143     "restart"]
144 eulisse 1.8 validOptions = ["--cfg", "--force-kill", "--pid-file",
145     "--log-file", "--log-level"]
146 eulisse 1.5
147     result = []
148     for i in range (0, len (args)):
149     arg = sys.argv[i]
150     if arg in validArguments:
151     result.append (args[i])
152    
153     for i in range (0, len (args)):
154     option = args[i]
155     if option in validOptions:
156     result.append (option)
157     result.append (args[i+1])
158 eulisse 1.7 return result
159 eulisse 1.5
160 eulisse 1.7 class CmsWebApplication (object):
161     def __init__ (self):
162     self.context = Context ()
163     self.context.addService (OptionParser ())
164     self.parser = self.context.OptionParser ()
165     self.__addOptions ()
166 eulisse 1.4
167 eulisse 1.7 def __addOptions (self):
168     self.parser.add_option ("--profile",
169     help="start server in profiler mode",
170     default=False,
171     action="store_true",
172     dest="profile")
173    
174     self.parser.add_option ("--pid-file",
175     help="File in which it is specified the pid of wanted instance",
176     default="pid.txt",
177     dest="pidFile",
178     metavar="FILE")
179    
180     self.parser.add_option ("--force-kill",
181     help="Uses SIGKILL rather than SIGTERM",
182     default=False,
183     action="store_true",
184     dest="forceKill",
185     metavar="FILE")
186 eulisse 1.8
187     def openFilename (option, opt_str, value, parser, *args, **kwargs):
188     try:
189     f=open (value, 'a')
190     except IOError:
191     print "WARNING: Unable to open log file %s. Using stderr." % value
192     f=sys.stderr
193     setattr (parser.values, option.dest, f)
194    
195     self.parser.add_option ("--log-file",
196     help="FILE to which redirect log messages",
197     dest="logFile",
198     default=sys.stderr,
199     action="callback",
200     callback=openFilename,
201     metavar="FILENAME",
202     type="str",
203     nargs=1)
204    
205     self.parser.add_option ("--log-level",
206     help="detail LEVEL for the main log",
207     dest="logLevel",
208     default=10,
209     metavar="LEVEL",
210     type="int")
211 eulisse 1.6
212 eulisse 1.7 def run (self):
213     validOptions = getValidOptions (sys.argv)
214 eulisse 1.6
215 eulisse 1.7 opts, args = self.parser.parse_args (args=validOptions)
216 eulisse 1.8
217     g_Logger.stream = opts.logFile
218     g_Logger.detailLevel = opts.logLevel
219    
220 eulisse 1.7 if not len (args):
221     args = ["start"]
222    
223     factory = CommandFactory (self.context, opts, args)
224     startCommand = factory.createByName (args[0])
225     if not startCommand:
226     print "Command %s not known." % args[0]
227     sys.exit (1)
228     startCommand.run ()
229     startCommand.finish ()
230    
231     if __name__ == '__main__':
232     app = CmsWebApplication ()
233     app.run ()