1 """A XMLRPC-Server that answeres about the current state of a Foam-Run"""
2
3 from ServerBase import ServerBase
4
5 from xmlrpclib import ServerProxy
6
7 from PyFoam import configuration as config
8 from PyFoam import versionString
9 from PyFoam.Basics.RingBuffer import RingBuffer
10 from PyFoam.Infrastructure.NetworkHelpers import freeServerPort
11 from PyFoam.Infrastructure.Logging import foamLogger
12 from PyFoam.FoamInformation import getPathFromEnviron,foamMPI
13 from PyFoam.RunDictionary.ParameterFile import ParameterFile
14
15 from Hardcoded import userName
16
17 from threading import Lock,Thread,Timer
18 from time import time
19 from os import environ,uname,path,getpid
20 import socket
21
22 import sys,string
23 from traceback import extract_tb
24
26 """Finds a free server port on this machine and returns it
27
28 Valid server ports are in the range 18000 upward (the function tries to
29 find the lowest possible port number
30
31 ATTENTION: this part may introduce race conditions"""
32
33 return freeServerPort(config().getint("Network","startServerPort"),
34 length=config().getint("Network","nrServerPorts"))
35
37 """The class that handles the actual requests (only needed to hide the
38 Thread-methods from the world
39 """
40 - def __init__(self,run=None,master=None,lines=100):
41 """
42 @param run: The thread that controls the run
43 @param master: The Runner-Object that controls everything
44 @param lines: the number of lines the server should remember
45 """
46 self._run=run
47 self._master=master
48 self._lines=RingBuffer(nr=lines)
49 self._lastTime=time()
50 self._linesLock=Lock()
51 self._maxOutputTime=config().getfloat("IsAlive","maxTimeStart")
52
54 """Inserts a new line, not to be called via XMLRPC"""
55 self._linesLock.acquire()
56 self._lines.insert(line)
57 tmp=time()
58 if (tmp-self._lastTime)>self._maxOutputTime:
59 self._maxOutputTime=tmp-self._lastTime
60 self._lastTime=tmp
61 self._linesLock.release()
62
64 """This is a Foam-Server (True by default)"""
65 return True
66
68 """The calculation still generates output and therefor seems to be living"""
69 return self.elapsedTime()<self._maxOutputTime
70
72 """Interrupts the FOAM-process"""
73 if self._run:
74 foamLogger().warning("Killed by request")
75 self._run.interrupt()
76 return True
77 else:
78 return False
79
81 """Stops the run gracefully (after writing the last time-step to disk)"""
82 self._master.stopGracefully()
83 return True
84
86 """Argument vector with which the runner was called"""
87 if self._master:
88 return self._master.origArgv
89 else:
90 return []
91
93 """Argument vector with which the runner started the run"""
94 if self._master:
95 return self._master.argv
96 else:
97 return []
98
100 """Is it a parallel run?"""
101 if self._master:
102 return self._master.lam!=None
103 else:
104 return False
105
107 """How many processors are used?"""
108 if self._master:
109 if self._master.lam!=None:
110 return self._master.lam.cpuNr()
111 else:
112 return 1
113 else:
114 return 0
115
117 """Number of warnings the executable emitted"""
118 if self._master:
119 return self._master.warnings
120 else:
121 return 0
122
124 """The command line"""
125 if self._master:
126 return string.join(self._master.origArgv)
127 else:
128 return ""
129
131 """The actual command line used"""
132 if self._master:
133 return self._master.cmd
134 else:
135 return ""
136
138 """Name of the Python-Script that runs the show"""
139 return sys.argv[0]
140
142 """@return: the last line that was output by the running FOAM-process"""
143 self._linesLock.acquire()
144 result=self._lines.last()
145 self._linesLock.release()
146 if not result:
147 return ""
148 return result
149
151 """@return: the current last lines as a string"""
152 self._linesLock.acquire()
153 tmp=self._lines.dump()
154 self._linesLock.release()
155 result=""
156 for l in tmp:
157 result+=l
158
159 return result
160
162 """@return: time in seconds since the last line was output"""
163 self._linesLock.acquire()
164 result=time()-self._lastTime
165 self._linesLock.release()
166
167 return result
168
170 """@param name: name of an environment variable
171 @return: value of the variable, empty string if non-existing"""
172 result=""
173 if environ.has_key(name):
174 result=environ[name]
175 return result
176
178 """@return: name of the MPI-implementation"""
179 return foamMPI()
180
182 """Version number of the Foam-Version"""
183 return self.getEnviron("WM_PROJECT_VERSION")
184
186 """@return: Version number of the PyFoam"""
187 return versionString()
188
190 """@return: the complete uname-information"""
191 return uname()
192
194 """@return: the ip of this machine"""
195 return socket.gethostbyname(socket.gethostname())
196
198 """@return: The name of the computer"""
199 return uname()[1]
200
202 """@return: all the configured parameters"""
203 return config().dump()
204
206 """@return: the current working directory"""
207 return path.abspath(path.curdir)
208
210 """@return: the PID of the script"""
211 return getpid()
212
214 """@return: the user that runs this script"""
215 return userName()
216
218 """@return: an ID for this run: IP and process-id"""
219 return "%s:%d" % (self.ip(),self.pid())
220
222 """@return: the current time in the simulation"""
223 if self._master.nowTime:
224 return self._master.nowTime
225 else:
226 return 0
227
229 """@return: the time in the simulation for which the mesh was created"""
230 if self._master.nowTime:
231 return self._master.createTime
232 else:
233 return 0
234
241
243 """@return: parameter startTime from the controlDict"""
244 return float(self._readParameter("startTime"))
245
247 """@return: parameter endTime from the controlDict"""
248 return float(self._readParameter("endTime"))
249
251 """@return: parameter startTime from the controlDict"""
252 return float(self._readParameter("deltaT"))
253
255 """This is the class that serves the requests about the FOAM-Run"""
256 - def __init__(self,run=None,master=None,lines=100):
257 """
258 @param run: The thread that controls the run
259 @param master: The Runner-Object that controls everything
260 @param lines: the number of lines the server should remember
261 """
262 Thread.__init__(self)
263 self._port=findFreePort()
264
265 self._running=False
266
267 if self._port<0:
268 foamLogger().warning("Could not get a free port. Server not started")
269 return
270
271 foamLogger().info("Serving on port %d" % self._port)
272 self._server=ServerBase(('',self._port),logRequests=False)
273 self._server.register_introspection_functions()
274 self._answerer=FoamAnswerer(run=run,master=master,lines=lines)
275 self._server.register_instance(self._answerer)
276 self._server.register_function(self.killServer)
277 self._server.register_function(self.kill)
278 if run:
279 self._server.register_function(run.cpuTime)
280 self._server.register_function(run.cpuUserTime)
281 self._server.register_function(run.cpuSystemTime)
282 self._server.register_function(run.wallTime)
283 self._server.register_function(run.usedMemory)
284
286 if self._port<0:
287 return
288
289 reg=Timer(5.,self.register)
290 reg.start()
291
292 self._running=True
293
294 while self._running:
295 self._server.handle_request()
296
297
298 self._server.server_close()
299
300 foamLogger().info("Stopped serving on port %d" % self._port)
301
303 """Interrupts the FOAM-process (and kills the server)"""
304 self._answerer._kill()
305 return self.killServer()
306
308 """Kills the server process"""
309 tmp=self._running
310 self._running=False
311 return tmp
312
314 """Tries to register with the Meta-Server"""
315 try:
316 meta=ServerProxy("http://%s:%d" % (config().get("Metaserver","ip"),config().getint("Metaserver","port")))
317 meta.registerServer(self._answerer.ip(),self._answerer.pid(),self._port)
318 except socket.error, reason:
319 foamLogger().warning("Can't connect to meta-server - SocketError: "+str(reason))
320 except:
321 foamLogger().error("Can't connect to meta-server - Unknown Error: "+str(sys.exc_info()[0]))
322 foamLogger().error(str(sys.exc_info()[1]))
323 foamLogger().error("Traceback: "+str(extract_tb(sys.exc_info()[2])))
324
326 """Tries to deregister with the Meta-Server"""
327 self._server.server_close()
328 try:
329 meta=ServerProxy("http://%s:%d" % (config().get("Metaserver","ip"),config().getint("Metaserver","port")))
330 meta.deregisterServer(self._answerer.ip(),self._answerer.pid(),self._port)
331 except socket.error, reason:
332 foamLogger().warning("Can't connect to meta-server - SocketError: "+str(reason))
333 except:
334 foamLogger().error("Can't connect to meta-server - Unknown Error: "+str(sys.exc_info()[0]))
335 foamLogger().error(str(sys.exc_info()[1]))
336 foamLogger().error("Traceback: "+str(extract_tb(sys.exc_info()[2])))
337
339 """Inserts a new line, not to be called via XMLRPC"""
340 self._answerer._insertLine(line)
341