forked from bartvdbraak/blender
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:
parent
d987003608
commit
efa757fd8d
@ -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)
|
||||||
|
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
119
release/io/netrender/master_html.py
Normal file
119
release/io/netrender/master_html.py
Normal file
@ -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 " ", link("view log", "/html/log%s_%i" % (job_id, frame.number)) if frame.log_path else " ")
|
||||||
|
|
||||||
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user