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