netrender
Display job status in web interface Better use of Reports api for errors and success notifications Don't show some Client options if server address is default (hasn't been scanned or entered manually yet)
This commit is contained in:
@@ -67,11 +67,13 @@ class MRenderJob(netrender.model.RenderJob):
|
||||
if self.type == netrender.model.JOB_PROCESS:
|
||||
self.chunks = 1
|
||||
|
||||
# Force WAITING status on creation
|
||||
self.status = JOB_WAITING
|
||||
|
||||
# special server properties
|
||||
self.last_update = 0
|
||||
self.save_path = ""
|
||||
self.files = [MRenderFile(rfile.filepath, rfile.index, rfile.start, rfile.end) for rfile in job_info.files]
|
||||
self.status = JOB_WAITING
|
||||
|
||||
def save(self):
|
||||
if self.save_path:
|
||||
|
||||
@@ -94,6 +94,7 @@ def get(handler):
|
||||
"priority",
|
||||
"usage",
|
||||
"wait",
|
||||
"status",
|
||||
"length",
|
||||
"done",
|
||||
"dispatched",
|
||||
@@ -114,6 +115,7 @@ def get(handler):
|
||||
job.priority,
|
||||
"%0.1f%%" % (job.usage * 100),
|
||||
"%is" % int(time.time() - job.last_dispatched),
|
||||
job.statusText(),
|
||||
len(job),
|
||||
results[DONE],
|
||||
results[DISPATCHED],
|
||||
|
||||
@@ -132,6 +132,7 @@ class RenderJob:
|
||||
self.type = JOB_BLENDER
|
||||
self.name = ""
|
||||
self.category = "None"
|
||||
self.status = JOB_WAITING
|
||||
self.files = []
|
||||
self.chunks = 0
|
||||
self.priority = 0
|
||||
@@ -145,6 +146,7 @@ class RenderJob:
|
||||
self.type = job_info.type
|
||||
self.name = job_info.name
|
||||
self.category = job_info.category
|
||||
self.status = job_info.status
|
||||
self.files = job_info.files
|
||||
self.chunks = job_info.chunks
|
||||
self.priority = job_info.priority
|
||||
@@ -172,6 +174,9 @@ class RenderJob:
|
||||
def countSlaves(self):
|
||||
return len(set((frame.slave for frame in self.frames if frame.status == DISPATCHED)))
|
||||
|
||||
def statusText(self):
|
||||
return JOB_STATUS_TEXT[self.status]
|
||||
|
||||
def framesStatus(self):
|
||||
results = {
|
||||
QUEUED: 0,
|
||||
@@ -207,6 +212,7 @@ class RenderJob:
|
||||
"type": self.type,
|
||||
"name": self.name,
|
||||
"category": self.category,
|
||||
"status": self.status,
|
||||
"files": [f.serialize() for f in self.files if f.start == -1 or not frames or (f.start <= max_frame and f.end >= min_frame)],
|
||||
"frames": [f.serialize() for f in self.frames if not frames or f in frames],
|
||||
"chunks": self.chunks,
|
||||
@@ -226,6 +232,7 @@ class RenderJob:
|
||||
job.type = data["type"]
|
||||
job.name = data["name"]
|
||||
job.category = data["category"]
|
||||
job.status = data["status"]
|
||||
job.files = [RenderFile.materialize(f) for f in data["files"]]
|
||||
job.frames = [RenderFrame.materialize(f) for f in data["frames"]]
|
||||
job.chunks = data["chunks"]
|
||||
@@ -245,7 +252,7 @@ class RenderFrame:
|
||||
self.command = command
|
||||
|
||||
def statusText(self):
|
||||
return STATUS_TEXT[self.status]
|
||||
return FRAME_STATUS_TEXT[self.status]
|
||||
|
||||
def serialize(self):
|
||||
return {
|
||||
|
||||
@@ -97,15 +97,12 @@ class RENDER_OT_netclientanim(bpy.types.Operator):
|
||||
scene = context.scene
|
||||
netsettings = scene.network_render
|
||||
|
||||
try:
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
|
||||
if conn:
|
||||
# Sending file
|
||||
scene.network_render.job_id = client.clientSendJob(conn, scene, True)
|
||||
conn.close()
|
||||
except Exception as err:
|
||||
self.report('ERROR', str(err))
|
||||
conn = None
|
||||
|
||||
bpy.ops.screen.render('INVOKE_AREA', animation=True)
|
||||
|
||||
@@ -128,12 +125,13 @@ class RENDER_OT_netclientsend(bpy.types.Operator):
|
||||
netsettings = scene.network_render
|
||||
|
||||
try:
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
|
||||
# Sending file
|
||||
scene.network_render.job_id = client.clientSendJob(conn, scene, True)
|
||||
conn.close()
|
||||
self.report('INFO', "Job sent to master")
|
||||
if conn:
|
||||
# Sending file
|
||||
scene.network_render.job_id = client.clientSendJob(conn, scene, True)
|
||||
conn.close()
|
||||
self.report('INFO', "Job sent to master")
|
||||
except Exception as err:
|
||||
self.report('ERROR', str(err))
|
||||
|
||||
@@ -154,7 +152,7 @@ class RENDER_OT_netclientstatus(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
netsettings = context.scene.network_render
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
|
||||
if conn:
|
||||
conn.request("GET", "/status")
|
||||
@@ -255,7 +253,7 @@ class RENDER_OT_netclientslaves(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
netsettings = context.scene.network_render
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
|
||||
if conn:
|
||||
conn.request("GET", "/slaves")
|
||||
@@ -301,7 +299,7 @@ class RENDER_OT_netclientcancel(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
netsettings = context.scene.network_render
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
|
||||
if conn:
|
||||
job = netrender.jobs[netsettings.active_job_index]
|
||||
@@ -329,7 +327,7 @@ class RENDER_OT_netclientcancelall(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
netsettings = context.scene.network_render
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
|
||||
if conn:
|
||||
conn.request("POST", "/clear")
|
||||
@@ -359,7 +357,7 @@ class netclientdownload(bpy.types.Operator):
|
||||
netsettings = context.scene.network_render
|
||||
rd = context.scene.render_data
|
||||
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
|
||||
if conn:
|
||||
job = netrender.jobs[netsettings.active_job_index]
|
||||
@@ -400,7 +398,7 @@ class netclientscan(bpy.types.Operator):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
address, port = clientScan()
|
||||
address, port = clientScan(self.report)
|
||||
|
||||
if address:
|
||||
scene = context.scene
|
||||
@@ -427,7 +425,7 @@ class netclientweb(bpy.types.Operator):
|
||||
|
||||
|
||||
# open connection to make sure server exists
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
|
||||
if conn:
|
||||
conn.close()
|
||||
|
||||
@@ -85,7 +85,8 @@ class RENDER_PT_network_job(RenderButtonsPanel):
|
||||
|
||||
def poll(self, context):
|
||||
scene = context.scene
|
||||
return super().poll(context) and scene.network_render.mode == "RENDER_CLIENT"
|
||||
return (super().poll(context)
|
||||
and scene.network_render.mode == "RENDER_CLIENT")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -98,9 +99,10 @@ class RENDER_PT_network_job(RenderButtonsPanel):
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.operator("render.netclientanim", icon='RENDER_ANIMATION')
|
||||
col.operator("render.netclientsend", icon='FILE_BLEND')
|
||||
col.operator("render.netclientweb", icon='QUESTION')
|
||||
if scene.network_render.server_address != "[default]":
|
||||
col.operator("render.netclientanim", icon='RENDER_ANIMATION')
|
||||
col.operator("render.netclientsend", icon='FILE_BLEND')
|
||||
col.operator("render.netclientweb", icon='QUESTION')
|
||||
col.prop(scene.network_render, "job_name")
|
||||
col.prop(scene.network_render, "job_category")
|
||||
row = col.row()
|
||||
@@ -114,7 +116,9 @@ class RENDER_PT_network_slaves(RenderButtonsPanel):
|
||||
|
||||
def poll(self, context):
|
||||
scene = context.scene
|
||||
return super().poll(context) and scene.network_render.mode == "RENDER_CLIENT"
|
||||
return (super().poll(context)
|
||||
and scene.network_render.mode == "RENDER_CLIENT"
|
||||
and scene.network_render.server_address != "[default]")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -150,7 +154,9 @@ class RENDER_PT_network_slaves_blacklist(RenderButtonsPanel):
|
||||
|
||||
def poll(self, context):
|
||||
scene = context.scene
|
||||
return super().poll(context) and scene.network_render.mode == "RENDER_CLIENT"
|
||||
return (super().poll(context)
|
||||
and scene.network_render.mode == "RENDER_CLIENT"
|
||||
and scene.network_render.server_address != "[default]")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -185,7 +191,9 @@ class RENDER_PT_network_jobs(RenderButtonsPanel):
|
||||
|
||||
def poll(self, context):
|
||||
scene = context.scene
|
||||
return super().poll(context) and scene.network_render.mode == "RENDER_CLIENT"
|
||||
return (super().poll(context)
|
||||
and scene.network_render.mode == "RENDER_CLIENT"
|
||||
and scene.network_render.server_address != "[default]")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@@ -28,7 +28,7 @@ try:
|
||||
except:
|
||||
bpy = None
|
||||
|
||||
VERSION = b"0.7"
|
||||
VERSION = bytes("0.7", encoding='utf8')
|
||||
|
||||
# Jobs status
|
||||
JOB_WAITING = 0 # before all data has been entered
|
||||
@@ -36,13 +36,21 @@ JOB_PAUSED = 1 # paused by user
|
||||
JOB_FINISHED = 2 # finished rendering
|
||||
JOB_QUEUED = 3 # ready to be dispatched
|
||||
|
||||
JOB_STATUS_TEXT = {
|
||||
JOB_WAITING: "Waiting",
|
||||
JOB_PAUSED: "Paused",
|
||||
JOB_FINISHED: "Finished",
|
||||
JOB_QUEUED: "Queued"
|
||||
}
|
||||
|
||||
|
||||
# Frames status
|
||||
QUEUED = 0
|
||||
DISPATCHED = 1
|
||||
DONE = 2
|
||||
ERROR = 3
|
||||
|
||||
STATUS_TEXT = {
|
||||
FRAME_STATUS_TEXT = {
|
||||
QUEUED: "Queued",
|
||||
DISPATCHED: "Dispatched",
|
||||
DONE: "Done",
|
||||
@@ -57,40 +65,66 @@ def rnaOperator(rna_op):
|
||||
if bpy: bpy.ops.add(rna_op)
|
||||
return rna_op
|
||||
|
||||
def clientScan():
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
s.settimeout(30)
|
||||
def reporting(report, message, errorType = None):
|
||||
if errorType:
|
||||
t = 'ERROR'
|
||||
else:
|
||||
t = 'INFO'
|
||||
|
||||
if report:
|
||||
report(t, message)
|
||||
return None
|
||||
elif errorType:
|
||||
raise errorType(message)
|
||||
else:
|
||||
return None
|
||||
|
||||
s.bind(('', 8000))
|
||||
|
||||
buf, address = s.recvfrom(64)
|
||||
|
||||
print("received:", buf)
|
||||
|
||||
address = address[0]
|
||||
port = int(str(buf, encoding='utf8'))
|
||||
return (address, port)
|
||||
except socket.timeout:
|
||||
print("no server info")
|
||||
return ("", 8000) # return default values
|
||||
def clientScan(report = None):
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
s.settimeout(30)
|
||||
|
||||
def clientConnection(address, port):
|
||||
if address == "[default]":
|
||||
s.bind(('', 8000))
|
||||
|
||||
buf, address = s.recvfrom(64)
|
||||
|
||||
address = address[0]
|
||||
port = int(str(buf, encoding='utf8'))
|
||||
|
||||
reporting(report, "Master server found")
|
||||
|
||||
return (address, port)
|
||||
except socket.timeout:
|
||||
reporting(report, "No master server on network", IOError)
|
||||
|
||||
return ("", 8000) # return default values
|
||||
|
||||
def clientConnection(address, port, report = None):
|
||||
if address == "[default]":
|
||||
# calling operator from python is fucked, scene isn't in context
|
||||
# if bpy:
|
||||
# bpy.ops.render.netclientscan()
|
||||
# else:
|
||||
address, port = clientScan()
|
||||
|
||||
conn = http.client.HTTPConnection(address, port)
|
||||
|
||||
if clientVerifyVersion(conn):
|
||||
return conn
|
||||
else:
|
||||
conn.close()
|
||||
raise IOError("Wrong version on master")
|
||||
address, port = clientScan()
|
||||
if address == "":
|
||||
return None
|
||||
|
||||
try:
|
||||
conn = http.client.HTTPConnection(address, port)
|
||||
|
||||
if conn:
|
||||
if clientVerifyVersion(conn):
|
||||
return conn
|
||||
else:
|
||||
conn.close()
|
||||
reporting(report, "Incorrect master version", ValueError)
|
||||
except Exception as err:
|
||||
if report:
|
||||
report('ERROR', str(err))
|
||||
return None
|
||||
else:
|
||||
raise
|
||||
|
||||
def clientVerifyVersion(conn):
|
||||
conn.request("GET", "/version")
|
||||
@@ -104,7 +138,7 @@ def clientVerifyVersion(conn):
|
||||
|
||||
if server_version != VERSION:
|
||||
print("Incorrect server version!")
|
||||
print("expected", VERSION, "received", server_version)
|
||||
print("expected", str(VERSION, encoding='utf8'), "received", str(server_version, encoding='utf8'))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user