debuggers.hg

view tools/python/xen/xend/server/SrvDaemon.py @ 6698:652bd7876153

Remove python virq code.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Wed Sep 07 14:19:05 2005 +0000 (2005-09-07)
parents dd668f7527cb
children 0e2b1e04d4cb 7d0fb56b4a91
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 socket
13 import pwd
14 import re
15 import StringIO
16 import traceback
17 import time
18 import glob
20 from xen.lowlevel import xu
22 from xen.xend import sxp
23 from xen.xend import PrettyPrint
24 from xen.xend import EventServer; eserver = EventServer.instance()
25 from xen.xend.XendError import XendError
26 from xen.xend.server import SrvServer
27 from xen.xend.XendLogging import log
28 from xen.xend import XendRoot; xroot = XendRoot.instance()
30 import channel
31 import controller
32 import event
33 import relocate
34 from params import *
36 class Daemon:
37 """The xend daemon.
38 """
39 def __init__(self):
40 self.channelF = None
41 self.shutdown = 0
42 self.traceon = 0
43 self.tracefile = None
44 self.traceindent = 0
45 self.child = 0
47 def daemon_pids(self):
48 pids = []
49 pidex = '(?P<pid>\d+)'
50 pythonex = '(?P<python>\S*python\S*)'
51 cmdex = '(?P<cmd>.*)'
52 procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
53 xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
54 procs = os.popen('ps -e -o pid,args 2>/dev/null')
55 for proc in procs:
56 pm = procre.match(proc)
57 if not pm: continue
58 xm = xendre.match(pm.group('cmd'))
59 if not xm: continue
60 pids.append(int(pm.group('pid')))
61 return pids
63 def new_cleanup(self, kill=0):
64 err = 0
65 pids = self.daemon_pids()
66 if kill:
67 for pid in pids:
68 print "Killing daemon pid=%d" % pid
69 os.kill(pid, signal.SIGHUP)
70 elif pids:
71 err = 1
72 print "Daemon already running: ", pids
73 return err
75 def read_pid(self, pidfile):
76 """Read process id from a file.
78 @param pidfile: file to read
79 @return pid or 0
80 """
81 pid = 0
82 if os.path.isfile(pidfile) and os.path.getsize(pidfile):
83 try:
84 pid = open(pidfile, 'r').read()
85 pid = int(pid)
86 except:
87 pid = 0
88 return pid
90 def find_process(self, pid, name):
91 """Search for a process.
93 @param pid: process id
94 @param name: process name
95 @return: pid if found, 0 otherwise
96 """
97 running = 0
98 if pid:
99 lines = os.popen('ps %d 2>/dev/null' % pid).readlines()
100 exp = '^ *%d.+%s' % (pid, name)
101 for line in lines:
102 if re.search(exp, line):
103 running = pid
104 break
105 return running
107 def cleanup_process(self, pidfile, name, kill):
108 """Clean up the pidfile for a process.
109 If a running process is found, kills it if 'kill' is true.
111 @param pidfile: pid file
112 @param name: process name
113 @param kill: whether to kill the process
114 @return running process id or 0
115 """
116 running = 0
117 pid = self.read_pid(pidfile)
118 if self.find_process(pid, name):
119 if kill:
120 os.kill(pid, 1)
121 else:
122 running = pid
123 if running == 0 and os.path.isfile(pidfile):
124 os.remove(pidfile)
125 return running
127 def cleanup_xend(self, kill=False):
128 return self.cleanup_process(XEND_PID_FILE, "xend", kill)
130 def cleanup(self, kill=False):
131 self.cleanup_xend(kill=kill)
133 def status(self):
134 """Returns the status of the xend daemon.
135 The return value is defined by the LSB:
136 0 Running
137 3 Not running
138 """
139 if self.cleanup_process(XEND_PID_FILE, "xend", False) == 0:
140 return 3
141 else:
142 return 0
144 def onSIGCHLD(self, signum, frame):
145 if self.child > 0:
146 try:
147 pid, sts = os.waitpid(self.child, os.WNOHANG)
148 except os.error, ex:
149 pass
151 def fork_pid(self, pidfile):
152 """Fork and write the pid of the child to 'pidfile'.
154 @param pidfile: pid file
155 @return: pid of child in parent, 0 in child
156 """
158 self.child = os.fork()
160 if self.child:
161 # Parent
162 pidfile = open(pidfile, 'w')
163 pidfile.write(str(self.child))
164 pidfile.close()
166 return self.child
168 def daemonize(self):
169 if not XEND_DAEMONIZE: return
170 # Detach from TTY.
171 os.setsid()
173 # Detach from standard file descriptors.
174 # I do this at the file-descriptor level: the overlying Python file
175 # objects also use fd's 0, 1 and 2.
176 os.close(0)
177 os.close(1)
178 os.close(2)
179 if XEND_DEBUG:
180 os.open('/dev/null', os.O_RDONLY)
181 # XXX KAF: Why doesn't this capture output from C extensions that
182 # fprintf(stdout) or fprintf(stderr) ??
183 os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT)
184 os.dup(1)
185 else:
186 os.open('/dev/null', os.O_RDWR)
187 os.dup(0)
188 os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT)
191 def start(self, trace=0):
192 """Attempts to start the daemons.
193 The return value is defined by the LSB:
194 0 Success
195 4 Insufficient privileges
196 """
197 xend_pid = self.cleanup_xend()
199 if self.set_user():
200 return 4
201 os.chdir("/")
203 if xend_pid > 0:
204 # Trying to run an already-running service is a success.
205 return 0
207 signal.signal(signal.SIGCHLD, self.onSIGCHLD)
208 if self.fork_pid(XEND_PID_FILE):
209 #Parent. Sleep to give child time to start.
210 time.sleep(1)
211 else:
212 # Child
213 self.tracing(trace)
214 self.run()
215 return 0
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, str):
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(str)
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, error:
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):
298 _enforce_dom0_cpus()
299 try:
300 log.info("Xend Daemon started")
301 self.createFactories()
302 event.listenEvent(self)
303 relocate.listenRelocation()
304 self.listenChannels()
305 servers = SrvServer.create()
306 self.daemonize()
307 servers.start()
308 except Exception, ex:
309 print >>sys.stderr, 'Exception starting xend:', ex
310 if XEND_DEBUG:
311 traceback.print_exc()
312 log.exception("Exception starting xend (%s)" % ex)
313 self.exit(1)
315 def createFactories(self):
316 self.channelF = channel.channelFactory()
318 def listenChannels(self):
319 self.channelF.start()
321 def exit(self, rc=0):
322 if self.channelF:
323 self.channelF.stop()
324 # Calling sys.exit() raises a SystemExit exception, which only
325 # kills the current thread. Calling os._exit() makes the whole
326 # Python process exit immediately. There doesn't seem to be another
327 # way to exit a Python with running threads.
328 #sys.exit(rc)
329 os._exit(rc)
331 def _enforce_dom0_cpus():
332 dn = xroot.get_dom0_cpus()
334 for d in glob.glob("/sys/devices/system/cpu/cpu*"):
335 cpu = int(os.path.basename(d)[3:])
336 if (dn == 0) or (cpu < dn):
337 v = "1"
338 else:
339 v = "0"
340 try:
341 f = open("%s/online" %d, "r+")
342 c = f.read(1)
343 if (c != v):
344 if v == "0":
345 log.info("dom0 is trying to give back cpu %d", cpu)
346 else:
347 log.info("dom0 is trying to take cpu %d", cpu)
348 f.seek(0)
349 f.write(v)
350 f.close()
351 log.info("dom0 successfully enforced cpu %d", cpu)
352 else:
353 f.close()
354 except:
355 pass
357 def instance():
358 global inst
359 try:
360 inst
361 except:
362 inst = Daemon()
363 return inst