netrender. first draft of html master details. Just point a browser at the master's address and port, et voila. Gives a list of jobs and slaves and well as per frame status for each job and access to slave output logs per frame

This commit is contained in:
Martin Poirier 2009-09-23 01:59:57 +00:00
parent d987003608
commit efa757fd8d
6 changed files with 139 additions and 5 deletions

@ -5,6 +5,7 @@ import operators
import client import client
import slave import slave
import master import master
import master_html
import utils import utils
import balancing import balancing
import ui import ui

@ -1,5 +1,5 @@
import bpy import bpy
import sys, os import sys, os, re
import http, http.client, http.server, urllib import http, http.client, http.server, urllib
import subprocess, shutil, time, hashlib import subprocess, shutil, time, hashlib

@ -5,6 +5,7 @@ import subprocess, shutil, time, hashlib
from netrender.utils import * from netrender.utils import *
import netrender.model import netrender.model
import netrender.balancing import netrender.balancing
import netrender.master_html
class MRenderFile: class MRenderFile:
def __init__(self, filepath, start, end): def __init__(self, filepath, start, end):
@ -126,9 +127,9 @@ class MRenderFrame(netrender.model.RenderFrame):
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
class RenderHandler(http.server.BaseHTTPRequestHandler): class RenderHandler(http.server.BaseHTTPRequestHandler):
def send_head(self, code = http.client.OK, headers = {}): def send_head(self, code = http.client.OK, headers = {}, content = "application/octet-stream"):
self.send_response(code) self.send_response(code)
self.send_header("Content-type", "application/octet-stream") self.send_header("Content-type", content)
for key, value in headers.items(): for key, value in headers.items():
self.send_header(key, value) self.send_header(key, value)
@ -342,7 +343,10 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
self.send_head() self.send_head()
self.wfile.write(bytes(repr(message), encoding='utf8')) self.wfile.write(bytes(repr(message), encoding='utf8'))
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
else:
# hand over the rest to the html section
netrender.master_html.get(self)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

@ -0,0 +1,119 @@
import re
from netrender.utils import *
def get(handler):
def output(text):
handler.wfile.write(bytes(text, encoding='utf8'))
def link(text, url):
return "<a href='%s'>%s</a>" % (url, text)
def startTable(border=1):
output("<table border='%i'>" % border)
def headerTable(*headers):
output("<thead><tr>")
for c in headers:
output("<td>" + c + "</td>")
output("</tr></thead>")
def rowTable(*data):
output("<tr>")
for c in data:
output("<td>" + str(c) + "</td>")
output("</tr>")
def endTable():
output("</table>")
handler.send_head(content = "text/html")
if handler.path == "/html" or handler.path == "/":
output("<html><head><title>NetRender</title></head><body>")
output("<h2>Master</h2>")
output("<h2>Slaves</h2>")
startTable()
headerTable("id", "name", "address", "stats")
for slave in handler.server.slaves:
rowTable(slave.id, slave.name, slave.address[0], slave.stats)
endTable()
output("<h2>Jobs</h2>")
startTable()
headerTable("id", "name", "length", "done", "dispatched", "error")
for job in handler.server.jobs:
results = job.framesStatus()
rowTable(link(job.id, "/html/job" + job.id), job.name, len(job), results[DONE], results[DISPATCHED], results[ERROR])
endTable()
output("</body></html>")
elif handler.path.startswith("/html/job"):
job_id = handler.path[9:]
output("<html><head><title>NetRender</title></head><body>")
job = handler.server.getJobByID(job_id)
if job:
output("<h2>Frames</h2>")
startTable()
headerTable("no", "status", "render time", "slave", "log")
for frame in job.frames:
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;")
endTable()
else:
output("no such job")
output("</body></html>")
elif handler.path.startswith("/html/log"):
pattern = re.compile("([a-zA-Z0-9]+)_([0-9]+)")
output("<html><head><title>NetRender</title></head><body>")
match = pattern.match(handler.path[9:])
if match:
job_id = match.groups()[0]
frame_number = int(match.groups()[1])
job = handler.server.getJobByID(job_id)
if job:
frame = job[frame_number]
if frame:
f = open(frame.log_path, 'rb')
output("<pre>")
shutil.copyfileobj(f, handler.wfile)
output("</pre>")
f.close()
else:
output("no such frame")
else:
output("no such job")
else:
output("malformed url")
output("</body></html>")

@ -32,7 +32,7 @@ class RenderSlave:
def __init__(self): def __init__(self):
self.id = "" self.id = ""
self.name = "" self.name = ""
self.address = (0,0) self.address = ("",0)
self.stats = "" self.stats = ""
self.total_done = 0 self.total_done = 0
self.total_error = 0 self.total_error = 0
@ -173,6 +173,9 @@ class RenderFrame:
self.status = QUEUED self.status = QUEUED
self.slave = None self.slave = None
def statusText(self):
return STATUS_TEXT[self.status]
def serialize(self): def serialize(self):
return { return {
"number": self.number, "number": self.number,

@ -19,6 +19,13 @@ DISPATCHED = 1
DONE = 2 DONE = 2
ERROR = 3 ERROR = 3
STATUS_TEXT = {
QUEUED: "Queued",
DISPATCHED: "Dispatched",
DONE: "Done",
ERROR: "Error"
}
def rnaType(rna_type): def rnaType(rna_type):
bpy.types.register(rna_type) bpy.types.register(rna_type)
return rna_type return rna_type