ia64/xen-unstable

view tools/python/xen/xend/server/SrvDaemon.py @ 7086:8fe341229827

Remove unused imports, variables.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Tue Sep 27 22:09:12 2005 +0100 (2005-09-27)
parents 06d84bf87159
children 61b3b357d827 2c9e66555ff4
line source
1 ###########################################################
2 ## Xen controller daemon
3 ## Copyright (c) 2004, K A Fraser (University of Cambridge)
4 ## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
5 ###########################################################
7 import os
8 import signal
9 import sys
10 import threading
11 import linecache
12 import pwd
13 import re
14 import traceback
16 from xen.xend import EventServer
17 from xen.xend.server import SrvServer
18 from xen.xend.XendLogging import log
19 from xen.xend import XendRoot
21 import event
22 import relocate
23 from params import *
26 eserver = EventServer.instance()
27 xroot = XendRoot.instance()
30 class Daemon:
31 """The xend daemon.
32 """
33 def __init__(self):
34 self.shutdown = 0
35 self.traceon = 0
36 self.tracefile = None
37 self.traceindent = 0
38 self.child = 0
40 def daemon_pids(self):
41 pids = []
42 pidex = '(?P<pid>\d+)'
43 pythonex = '(?P<python>\S*python\S*)'
44 cmdex = '(?P<cmd>.*)'
45 procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
46 xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
47 procs = os.popen('ps -e -o pid,args 2>/dev/null')
48 for proc in procs:
49 pm = procre.match(proc)
50 if not pm: continue
51 xm = xendre.match(pm.group('cmd'))
52 if not xm: continue
53 pids.append(int(pm.group('pid')))
54 return pids
56 def new_cleanup(self, kill=0):
57 err = 0
58 pids = self.daemon_pids()
59 if kill:
60 for pid in pids:
61 print "Killing daemon pid=%d" % pid
62 os.kill(pid, signal.SIGHUP)
63 elif pids:
64 err = 1
65 print "Daemon already running: ", pids
66 return err
68 def read_pid(self, pidfile):
69 """Read process id from a file.
71 @param pidfile: file to read
72 @return pid or 0
73 """
74 pid = 0
75 if os.path.isfile(pidfile) and os.path.getsize(pidfile):
76 try:
77 pid = open(pidfile, 'r').read()
78 pid = int(pid)
79 except:
80 pid = 0
81 return pid
83 def find_process(self, pid, name):
84 """Search for a process.
86 @param pid: process id
87 @param name: process name
88 @return: pid if found, 0 otherwise
89 """
90 running = 0
91 if pid:
92 lines = os.popen('ps %d 2>/dev/null' % pid).readlines()
93 exp = '^ *%d.+%s' % (pid, name)
94 for line in lines:
95 if re.search(exp, line):
96 running = pid
97 break
98 return running
100 def cleanup_process(self, pidfile, name, kill):
101 """Clean up the pidfile for a process.
102 If a running process is found, kills it if 'kill' is true.
104 @param pidfile: pid file
105 @param name: process name
106 @param kill: whether to kill the process
107 @return running process id or 0
108 """
109 running = 0
110 pid = self.read_pid(pidfile)
111 if self.find_process(pid, name):
112 if kill:
113 os.kill(pid, 1)
114 else:
115 running = pid
116 if running == 0 and os.path.isfile(pidfile):
117 os.remove(pidfile)
118 return running
120 def cleanup_xend(self, kill=False):
121 return self.cleanup_process(XEND_PID_FILE, "xend", kill)
123 def cleanup(self, kill=False):
124 self.cleanup_xend(kill=kill)
126 def status(self):
127 """Returns the status of the xend daemon.
128 The return value is defined by the LSB:
129 0 Running
130 3 Not running
131 """
132 if self.cleanup_process(XEND_PID_FILE, "xend", False) == 0:
133 return 3
134 else:
135 return 0
137 def fork_pid(self, pidfile):
138 """Fork and write the pid of the child to 'pidfile'.
140 @param pidfile: pid file
141 @return: pid of child in parent, 0 in child
142 """
144 self.child = os.fork()
146 if self.child:
147 # Parent
148 pidfile = open(pidfile, 'w')
149 pidfile.write(str(self.child))
150 pidfile.close()
152 return self.child
154 def daemonize(self):
155 if not XEND_DAEMONIZE: return
156 # Detach from TTY.
157 os.setsid()
159 # Detach from standard file descriptors.
160 # I do this at the file-descriptor level: the overlying Python file
161 # objects also use fd's 0, 1 and 2.
162 os.close(0)
163 os.close(1)
164 os.close(2)
165 if XEND_DEBUG:
166 os.open('/dev/null', os.O_RDONLY)
167 # XXX KAF: Why doesn't this capture output from C extensions that
168 # fprintf(stdout) or fprintf(stderr) ??
169 os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT)
170 os.dup(1)
171 else:
172 os.open('/dev/null', os.O_RDWR)
173 os.dup(0)
174 os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT)
177 def start(self, trace=0):
178 """Attempts to start the daemons.
179 The return value is defined by the LSB:
180 0 Success
181 4 Insufficient privileges
182 """
183 xend_pid = self.cleanup_xend()
185 if self.set_user():
186 return 4
187 os.chdir("/")
189 if xend_pid > 0:
190 # Trying to run an already-running service is a success.
191 return 0
193 ret = 0
195 # we use a pipe to communicate between the parent and the child process
196 # this way we know when the child has actually initialized itself so
197 # we can avoid a race condition during startup
199 r,w = os.pipe()
200 if self.fork_pid(XEND_PID_FILE):
201 os.close(w)
202 r = os.fdopen(r, 'r')
203 s = r.read()
204 r.close()
205 if not len(s):
206 ret = 1
207 else:
208 ret = int(s)
209 else:
210 os.close(r)
211 # Child
212 self.tracing(trace)
213 self.run(os.fdopen(w, 'w'))
215 return ret
217 def tracing(self, traceon):
218 """Turn tracing on or off.
220 @param traceon: tracing flag
221 """
222 if traceon == self.traceon:
223 return
224 self.traceon = traceon
225 if traceon:
226 self.tracefile = open(XEND_TRACE_FILE, 'w+', 1)
227 self.traceindent = 0
228 sys.settrace(self.trace)
229 try:
230 threading.settrace(self.trace) # Only in Python >= 2.3
231 except:
232 pass
234 def print_trace(self, string):
235 for i in range(self.traceindent):
236 ch = " "
237 if (i % 5):
238 ch = ' '
239 else:
240 ch = '|'
241 self.tracefile.write(ch)
242 self.tracefile.write(string)
244 def trace(self, frame, event, arg):
245 if not self.traceon:
246 print >>self.tracefile
247 print >>self.tracefile, '-' * 20, 'TRACE OFF', '-' * 20
248 self.tracefile.close()
249 self.tracefile = None
250 return None
251 if event == 'call':
252 code = frame.f_code
253 filename = code.co_filename
254 m = re.search('.*xend/(.*)', filename)
255 if not m:
256 return None
257 modulename = m.group(1)
258 if re.search('sxp.py', modulename):
259 return None
260 self.traceindent += 1
261 self.print_trace("> %s:%s\n"
262 % (modulename, code.co_name))
263 elif event == 'line':
264 filename = frame.f_code.co_filename
265 lineno = frame.f_lineno
266 self.print_trace("%4d %s" %
267 (lineno, linecache.getline(filename, lineno)))
268 elif event == 'return':
269 code = frame.f_code
270 filename = code.co_filename
271 m = re.search('.*xend/(.*)', filename)
272 if not m:
273 return None
274 modulename = m.group(1)
275 self.print_trace("< %s:%s\n"
276 % (modulename, code.co_name))
277 self.traceindent -= 1
278 elif event == 'exception':
279 self.print_trace("! Exception:\n")
280 (ex, val, tb) = arg
281 traceback.print_exception(ex, val, tb, 10, self.tracefile)
282 #del tb
283 return self.trace
285 def set_user(self):
286 # Set the UID.
287 try:
288 os.setuid(pwd.getpwnam(XEND_USER)[2])
289 return 0
290 except KeyError:
291 print >>sys.stderr, "Error: no such user '%s'" % XEND_USER
292 return 1
294 def stop(self):
295 return self.cleanup(kill=True)
297 def run(self, status):
298 try:
299 log.info("Xend Daemon started")
300 event.listenEvent(self)
301 relocate.listenRelocation()
302 servers = SrvServer.create()
303 self.daemonize()
304 servers.start(status)
305 except Exception, ex:
306 print >>sys.stderr, 'Exception starting xend:', ex
307 if XEND_DEBUG:
308 traceback.print_exc()
309 log.exception("Exception starting xend (%s)" % ex)
310 status.write('1')
311 status.close()
312 self.exit(1)
314 def exit(self, rc=0):
315 # Calling sys.exit() raises a SystemExit exception, which only
316 # kills the current thread. Calling os._exit() makes the whole
317 # Python process exit immediately. There doesn't seem to be another
318 # way to exit a Python with running threads.
319 #sys.exit(rc)
320 os._exit(rc)
322 def instance():
323 global inst
324 try:
325 inst
326 except:
327 inst = Daemon()
328 return inst