netrender: first draft for process jobs, to be able to run arbitrary commands on...
[blender.git] / release / scripts / io / netrender / master_html.py
1 import re
2
3 from netrender.utils import *
4
5
6 def get(handler):
7         def output(text):
8                 handler.wfile.write(bytes(text, encoding='utf8'))
9         
10         def link(text, url):
11                 return "<a href='%s'>%s</a>" % (url, text)
12         
13         def startTable(border=1):
14                 output("<table border='%i'>" % border)
15         
16         def headerTable(*headers):
17                 output("<thead><tr>")
18                 
19                 for c in headers:
20                         output("<td>" + c + "</td>")
21                 
22                 output("</tr></thead>")
23         
24         def rowTable(*data):
25                 output("<tr>")
26                 
27                 for c in data:
28                         output("<td>" + str(c) + "</td>")
29                 
30                 output("</tr>")
31         
32         def endTable():
33                 output("</table>")
34         
35         if handler.path == "/html" or handler.path == "/":
36                 handler.send_head(content = "text/html")
37                 output("<html><head><title>NetRender</title></head><body>")
38         
39                 output("<h2>Master</h2>")
40         
41                 output("<h2>Slaves</h2>")
42                 
43                 startTable()
44                 headerTable("name", "address", "last seen", "stats", "job")
45                 
46                 for slave in handler.server.slaves:
47                         rowTable(slave.name, slave.address[0], time.ctime(slave.last_seen), slave.stats, link(slave.job.name, "/html/job" + slave.job.id) if slave.job else "None")
48                 
49                 endTable()
50                 
51                 output("<h2>Jobs</h2>")
52                 
53                 startTable()
54                 headerTable(    
55                                                                         "name",
56                                                                         "priority",
57                                                                         "usage",
58                                                                         "wait",
59                                                                         "length",
60                                                                         "done",
61                                                                         "dispatched",
62                                                                         "error",
63                                                                         "first",
64                                                                         "exception"
65                                                                 )
66
67                 handler.server.balance()
68                 
69                 for job in handler.server.jobs:
70                         results = job.framesStatus()
71                         rowTable(       
72                                                                 link(job.name, "/html/job" + job.id),
73                                                                 job.priority,
74                                                                 "%0.1f%%" % (job.usage * 100),
75                                                                 "%is" % int(time.time() - job.last_dispatched),
76                                                                 len(job),
77                                                                 results[DONE],
78                                                                 results[DISPATCHED],
79                                                                 results[ERROR],
80                                                                 handler.server.balancer.applyPriorities(job), handler.server.balancer.applyExceptions(job)
81                                                         )
82                 
83                 endTable()
84                 
85                 output("</body></html>")
86         
87         elif handler.path.startswith("/html/job"):
88                 handler.send_head(content = "text/html")
89                 job_id = handler.path[9:]
90                 
91                 output("<html><head><title>NetRender</title></head><body>")
92         
93                 job = handler.server.getJobID(job_id)
94                 
95                 if job:
96                         output("<h2>Frames</h2>")
97                 
98                         startTable()
99                         headerTable("no", "status", "render time", "slave", "log")
100                         
101                         for frame in job.frames:
102                                 rowTable(frame.number, frame.statusText(), "%.1fs" % frame.time, frame.slave.name if frame.slave else "&nbsp;", link("view log", "/html/log%s_%i" % (job_id, frame.number)) if frame.log_path else "&nbsp;")
103                         
104                         endTable()
105                 else:
106                         output("no such job")
107                 
108                 output("</body></html>")
109         
110         elif handler.path.startswith("/html/log"):
111                 handler.send_head(content = "text/plain")
112                 pattern = re.compile("([a-zA-Z0-9]+)_([0-9]+)")
113                 
114                 match = pattern.match(handler.path[9:])
115                 if match:
116                         job_id = match.groups()[0]
117                         frame_number = int(match.groups()[1])
118                         
119                         job = handler.server.getJobID(job_id)
120                         
121                         if job:
122                                 frame = job[frame_number]
123                                 
124                                 if frame:
125                                                 f = open(frame.log_path, 'rb')
126                                                 
127                                                 shutil.copyfileobj(f, handler.wfile)
128                                                 
129                                                 f.close()
130                                 else:
131                                         output("no such frame")
132                         else:
133                                 output("no such job")
134                 else:
135                         output("malformed url")