1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright 2010 United States Government as represented by the
4
# Administrator of the National Aeronautics and Space Administration.
7
# Licensed under the Apache License, Version 2.0 (the "License"); you may
8
# not use this file except in compliance with the License. You may obtain
9
# a copy of the License at
11
# http://www.apache.org/licenses/LICENSE-2.0
13
# Unless required by applicable law or agreed to in writing, software
14
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
# License for the specific language governing permissions and limitations
20
Twisted daemon helpers, specifically to parse out gFlags from twisted flags,
21
manage pid files and support syslogging.
29
from twisted.scripts import twistd
30
from twisted.python import log
31
from twisted.python import reflect
32
from twisted.python import runtime
33
from twisted.python import usage
35
from nova import flags
36
from nova import log as logging
39
if runtime.platformType == "win32":
40
from twisted.scripts._twistw import ServerOptions
42
from twisted.scripts._twistd_unix import ServerOptions
48
class TwistdServerOptions(ServerOptions):
49
def parseArgs(self, *args):
53
class FlagParser(object):
54
# this is a required attribute for gflags
57
def __init__(self, parser):
64
def WrapTwistedOptions(wrapped):
65
class TwistedOptionsToFlags(wrapped):
69
# NOTE(termie): _data exists because Twisted stuff expects
70
# to be able to set arbitrary things that are
73
self._flagHandlers = {}
74
self._paramHandlers = {}
76
# Absorb the twistd flags into our FLAGS
78
self._absorbParameters()
79
self._absorbHandlers()
81
wrapped.__init__(self)
83
def _absorbFlags(self):
85
reflect.accumulateClassList(self.__class__, 'optFlags',
87
for flag in twistd_flags:
88
key = flag[0].replace('-', '_')
89
if hasattr(FLAGS, key):
91
flags.DEFINE_boolean(key, None, str(flag[-1]))
93
def _absorbParameters(self):
95
reflect.accumulateClassList(self.__class__, 'optParameters',
97
for param in twistd_params:
98
key = param[0].replace('-', '_')
99
if hasattr(FLAGS, key):
102
flags.DEFINE(FlagParser(param[4]),
103
key, param[2], str(param[3]),
104
serializer=gflags.ArgumentSerializer())
106
flags.DEFINE_string(key, param[2], str(param[3]))
108
def _absorbHandlers(self):
110
reflect.addMethodNamesToDict(self.__class__, twistd_handlers,
113
# NOTE(termie): Much of the following is derived/copied from
114
# twisted.python.usage with the express purpose of
115
# providing compatibility
116
for name in twistd_handlers.keys():
117
method = getattr(self, 'opt_' + name)
119
takesArg = not usage.flagFunction(method, name)
120
doc = getattr(method, '__doc__', None)
125
if name not in FLAGS:
126
flags.DEFINE_boolean(name, None, doc)
127
self._flagHandlers[name] = method
129
if name not in FLAGS:
130
flags.DEFINE_string(name, None, doc)
131
self._paramHandlers[name] = method
133
def _doHandlers(self):
134
for flag, handler in self._flagHandlers.iteritems():
137
for param, handler in self._paramHandlers.iteritems():
138
if self[param] is not None:
144
def parseOptions(self, options=None):
148
options.insert(0, '')
150
args = FLAGS(options)
156
self.parseArgs(*argv)
158
raise usage.UsageError(_("Wrong number of arguments."))
163
def parseArgs(self, *args):
164
# TODO(termie): figure out a decent way of dealing with args
166
wrapped.parseArgs(self, *args)
168
def postOptions(self):
171
wrapped.postOptions(self)
173
def __getitem__(self, key):
174
key = key.replace('-', '_')
176
return getattr(FLAGS, key)
177
except (AttributeError, KeyError):
178
return self._data[key]
180
def __setitem__(self, key, value):
181
key = key.replace('-', '_')
183
return setattr(FLAGS, key, value)
184
except (AttributeError, KeyError):
185
self._data[key] = value
187
def get(self, key, default):
188
key = key.replace('-', '_')
190
return getattr(FLAGS, key)
191
except (AttributeError, KeyError):
192
self._data.get(key, default)
194
return TwistedOptionsToFlags
201
# Get the pid from the pidfile
203
pf = file(pidfile, 'r')
204
pid = int(pf.read().strip())
210
message = _("pidfile %s does not exist. Daemon not running?\n")
211
sys.stderr.write(message % pidfile)
212
# Not an error in a restart
215
# Try killing the daemon process
218
os.kill(pid, signal.SIGKILL)
222
if err.find(_("No such process")) > 0:
223
if os.path.exists(pidfile):
231
logging.debug(_("Serving %s") % filename)
232
name = os.path.basename(filename)
233
OptionsClass = WrapTwistedOptions(TwistdServerOptions)
234
options = OptionsClass()
235
argv = options.parseOptions()
236
FLAGS.python = filename
238
if not FLAGS.pidfile:
239
FLAGS.pidfile = '%s.pid' % name
240
elif FLAGS.pidfile.endswith('twistd.pid'):
241
FLAGS.pidfile = FLAGS.pidfile.replace('twistd.pid', '%s.pid' % name)
244
elif FLAGS.prefix.endswith('twisted'):
245
FLAGS.prefix = FLAGS.prefix.replace('twisted', name)
254
elif action == 'restart':
256
elif action == 'start':
259
print 'usage: %s [options] [start|stop|restart]' % argv[0]
262
logging.debug(_("Full set of FLAGS:"))
264
logging.debug("%s : %s" % (flag, FLAGS.get(flag, None)))
266
logging.audit(_("Starting %s"), name)
267
twistd.runApp(options)