forked from bartvdbraak/blender
more use of data structures for communication. begining support for more than one file per fob (external dependencies, point cache, ...)
This commit is contained in:
parent
47beb68a0f
commit
285d665d99
@ -22,7 +22,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
||||
|
||||
def render_master(self, scene):
|
||||
server_address = (scene.network_render.server_address, scene.network_render.server_port)
|
||||
httpd = master.RenderMasterServer(server_address, master.RenderHandler)
|
||||
httpd = master.RenderMasterServer(server_address, master.RenderHandler, scene.network_render.path)
|
||||
httpd.timeout = 1
|
||||
httpd.stats = self.update_stats
|
||||
while not self.test_break():
|
||||
@ -32,6 +32,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
||||
slave.render_slave(self, scene)
|
||||
|
||||
def render_client(self, scene):
|
||||
netsettings = scene.network_render
|
||||
self.update_stats("", "Network render client initiation")
|
||||
|
||||
conn = clientConnection(scene)
|
||||
@ -41,7 +42,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
||||
|
||||
self.update_stats("", "Network render exporting")
|
||||
|
||||
job_id = scene.network_render.job_id
|
||||
job_id = netsettings.job_id
|
||||
|
||||
# reading back result
|
||||
|
||||
@ -51,10 +52,10 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
||||
response = conn.getresponse()
|
||||
|
||||
if response.status == http.client.NO_CONTENT:
|
||||
scene.network_render.job_id = clientSendJob(conn, scene)
|
||||
netsettings.job_id = clientSendJob(conn, scene)
|
||||
clientRequestResult(conn, scene, job_id)
|
||||
|
||||
while response.status == http.client.PROCESSING and not self.test_break():
|
||||
while response.status == http.client.ACCEPTED and not self.test_break():
|
||||
print("waiting")
|
||||
time.sleep(1)
|
||||
clientRequestResult(conn, scene, job_id)
|
||||
@ -68,7 +69,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
||||
x= int(r.resolution_x*r.resolution_percentage*0.01)
|
||||
y= int(r.resolution_y*r.resolution_percentage*0.01)
|
||||
|
||||
f = open(PATH_PREFIX + "output.exr", "wb")
|
||||
f = open(netsetting.path + "output.exr", "wb")
|
||||
buf = response.read(1024)
|
||||
|
||||
while buf:
|
||||
@ -78,7 +79,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
||||
f.close()
|
||||
|
||||
result = self.begin_result(0, 0, x, y)
|
||||
result.load_from_file(PATH_PREFIX + "output.exr", 0, 0)
|
||||
result.load_from_file(netsettings.path + "output.exr", 0, 0)
|
||||
self.end_result(result)
|
||||
|
||||
conn.close()
|
||||
|
@ -9,12 +9,22 @@ JOB_WAITING = 0 # before all data has been entered
|
||||
JOB_PAUSED = 1 # paused by user
|
||||
JOB_QUEUED = 2 # ready to be dispatched
|
||||
|
||||
class MRenderFile:
|
||||
def __init__(self, filepath):
|
||||
self.filepath = filepath
|
||||
self.found = False
|
||||
|
||||
def test(self):
|
||||
self.found = os.path.exists(self.filepath)
|
||||
return self.found
|
||||
|
||||
|
||||
class MRenderSlave(netrender.model.RenderSlave):
|
||||
def __init__(self, name, adress, stats):
|
||||
def __init__(self, name, address, stats):
|
||||
super().__init__()
|
||||
self.id = hashlib.md5(bytes(repr(name) + repr(adress), encoding='utf8')).hexdigest()
|
||||
self.id = hashlib.md5(bytes(repr(name) + repr(address), encoding='utf8')).hexdigest()
|
||||
self.name = name
|
||||
self.adress = adress
|
||||
self.address = address
|
||||
self.stats = stats
|
||||
self.last_seen = time.time()
|
||||
|
||||
@ -31,11 +41,12 @@ def groupKey(job):
|
||||
return (job.status, job.framesLeft() > 0, job.priority, job.credits)
|
||||
|
||||
class MRenderJob(netrender.model.RenderJob):
|
||||
def __init__(self, job_id, name, path, chunks = 1, priority = 1, credits = 100.0, blacklist = []):
|
||||
def __init__(self, job_id, name, files, chunks = 1, priority = 1, credits = 100.0, blacklist = []):
|
||||
super().__init__()
|
||||
self.id = job_id
|
||||
self.name = name
|
||||
self.path = path
|
||||
self.files = files
|
||||
self.render_files = [MRenderFile(path) for path in files]
|
||||
self.status = JOB_WAITING
|
||||
self.frames = []
|
||||
self.chunks = chunks
|
||||
@ -44,6 +55,14 @@ class MRenderJob(netrender.model.RenderJob):
|
||||
self.blacklist = blacklist
|
||||
self.last_dispatched = time.time()
|
||||
|
||||
def testStart(self):
|
||||
for f in self.render_files:
|
||||
if not f.test():
|
||||
return False
|
||||
|
||||
self.start()
|
||||
return True
|
||||
|
||||
def start(self):
|
||||
self.status = JOB_QUEUED
|
||||
|
||||
@ -75,7 +94,7 @@ class MRenderJob(netrender.model.RenderJob):
|
||||
if f.status == QUEUED:
|
||||
self.update()
|
||||
frames.append(f)
|
||||
if len(frames) == self.chunks:
|
||||
if len(frames) >= self.chunks:
|
||||
break
|
||||
|
||||
return frames
|
||||
@ -162,10 +181,10 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
|
||||
if frame:
|
||||
if frame.status in (QUEUED, DISPATCHED):
|
||||
self.send_head(http.client.PROCESSING)
|
||||
self.send_head(http.client.ACCEPTED)
|
||||
elif frame.status == DONE:
|
||||
self.server.stats("", "Sending result back to client")
|
||||
f = open(PATH_PREFIX + job_id + "%04d" % job_frame + ".exr", 'rb')
|
||||
f = open(self.server.path + job_id + "%04d" % job_frame + ".exr", 'rb')
|
||||
|
||||
self.send_head()
|
||||
|
||||
@ -173,13 +192,13 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
|
||||
f.close()
|
||||
elif frame.status == ERROR:
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
self.send_head(http.client.PARTIAL_CONTENT)
|
||||
else:
|
||||
# no such frame
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
else:
|
||||
# no such job id
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
elif self.path == "log":
|
||||
job_id = self.headers['job-id']
|
||||
@ -194,23 +213,21 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
if frame:
|
||||
if frame.status in (QUEUED, DISPATCHED):
|
||||
self.send_head(http.client.PROCESSING)
|
||||
elif frame.status == DONE:
|
||||
else:
|
||||
self.server.stats("", "Sending log back to client")
|
||||
f = open(PATH_PREFIX + job_id + "%04d" % job_frame + ".log", 'rb')
|
||||
f = open(self.server.path + job_id + "%04d" % job_frame + ".log", 'rb')
|
||||
|
||||
self.send_head()
|
||||
|
||||
shutil.copyfileobj(f, self.wfile)
|
||||
|
||||
f.close()
|
||||
elif frame.status == ERROR:
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
else:
|
||||
# no such frame
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
else:
|
||||
# no such job id
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
elif self.path == "status":
|
||||
job_id = self.headers.get('job-id', "")
|
||||
@ -228,13 +245,13 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
message = frame.serialize()
|
||||
else:
|
||||
# no such frame
|
||||
self.send_heat(http.client.NOT_FOUND)
|
||||
self.send_heat(http.client.NO_CONTENT)
|
||||
return
|
||||
else:
|
||||
message = job.serialize()
|
||||
else:
|
||||
# no such job id
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
return
|
||||
else: # status of all jobs
|
||||
message = []
|
||||
@ -262,6 +279,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
|
||||
if job and frames:
|
||||
for f in frames:
|
||||
print("dispatch", f.number)
|
||||
f.status = DISPATCHED
|
||||
f.slave = slave
|
||||
|
||||
@ -274,9 +292,9 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
self.server.stats("", "Sending job frame to render node")
|
||||
else:
|
||||
# no job available, return error code
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
self.send_head(http.client.ACCEPTED)
|
||||
else: # invalid slave id
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
elif self.path == "file":
|
||||
job_id = self.headers['job-id']
|
||||
@ -288,14 +306,14 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
self.send_head(headers={"job-id": job.id})
|
||||
|
||||
self.server.stats("", "Sending file to render node")
|
||||
f = open(PATH_PREFIX + job.id + ".blend", 'rb')
|
||||
f = open(self.server.path + job.id + ".blend", 'rb')
|
||||
|
||||
shutil.copyfileobj(f, self.wfile)
|
||||
|
||||
f.close()
|
||||
else:
|
||||
# no such job id
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
elif self.path == "slave":
|
||||
message = []
|
||||
@ -322,33 +340,25 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
self.server.stats("", "Receiving job")
|
||||
|
||||
length = int(self.headers['content-length'])
|
||||
job_frame_string = self.headers['job-frame']
|
||||
job_name = self.headers.get('job-name', "")
|
||||
job_chunks = int(self.headers.get('job-chunks', "1"))
|
||||
blacklist = self.headers.get('slave-blacklist', '').split()
|
||||
|
||||
job_path = str(self.rfile.read(length), encoding='utf8')
|
||||
job_info = netrender.model.RenderJob.materialize(eval(str(self.rfile.read(length), encoding='utf8')))
|
||||
|
||||
if os.path.exists(job_path):
|
||||
job_id = self.server.nextJobID()
|
||||
job_id = self.server.nextJobID()
|
||||
|
||||
print("chunks", job_info.chunks)
|
||||
|
||||
job = MRenderJob(job_id, job_info.name, job_info.files, chunks = job_info.chunks, priority = job_info.priority, blacklist = job_info.blacklist)
|
||||
self.server.addJob(job)
|
||||
|
||||
for frame in job_info.frames:
|
||||
frame = job.addFrame(frame.number)
|
||||
|
||||
job = MRenderJob(job_id, job_name, job_path, chunks = job_chunks, blacklist = blacklist)
|
||||
self.server.addJob(job)
|
||||
|
||||
if ":" in job_frame_string:
|
||||
frame_start, frame_end = [int(x) for x in job_frame_string.split(":")]
|
||||
|
||||
for job_frame in range(frame_start, frame_end + 1):
|
||||
frame = job.addFrame(job_frame)
|
||||
else:
|
||||
job_frame = int(job_frame_string)
|
||||
frame = job.addFrame(job_frame)
|
||||
|
||||
job.start()
|
||||
|
||||
self.send_head(headers={"job-id": job_id})
|
||||
headers={"job-id": job_id}
|
||||
|
||||
if job.testStart():
|
||||
self.send_head(headers=headers)
|
||||
else:
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.ACCEPTED, headers=headers)
|
||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
elif self.path == "cancel":
|
||||
job_id = self.headers.get('job-id', "")
|
||||
@ -375,7 +385,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
|
||||
self.send_head()
|
||||
else: # job not found
|
||||
self.send_head(http.client.NOT_FOUND)
|
||||
self.send_head(http.client.NO_CONTENT)
|
||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
elif self.path == "slave":
|
||||
length = int(self.headers['content-length'])
|
||||
@ -412,7 +422,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
|
||||
job_path = job_id + ".blend"
|
||||
|
||||
f = open(PATH_PREFIX + job_path, "wb")
|
||||
f = open(self.server.path + job_path, "wb")
|
||||
f.write(buf)
|
||||
f.close()
|
||||
del buf
|
||||
@ -445,7 +455,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
if job_result == DONE:
|
||||
length = int(self.headers['content-length'])
|
||||
buf = self.rfile.read(length)
|
||||
f = open(PATH_PREFIX + job_id + "%04d" % job_frame + ".exr", 'wb')
|
||||
f = open(self.server.path + job_id + "%04d" % job_frame + ".exr", 'wb')
|
||||
f.write(buf)
|
||||
f.close()
|
||||
|
||||
@ -471,7 +481,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
print("log length:", length)
|
||||
|
||||
buf = self.rfile.read(length)
|
||||
f = open(PATH_PREFIX + job_id + "%04d" % job_frame + ".log", 'wb')
|
||||
f = open(self.server.path + job_id + "%04d" % job_frame + ".log", 'wb')
|
||||
f.write(buf)
|
||||
f.close()
|
||||
|
||||
@ -483,20 +493,21 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
||||
|
||||
|
||||
class RenderMasterServer(http.server.HTTPServer):
|
||||
def __init__(self, address, handler_class):
|
||||
def __init__(self, address, handler_class, path):
|
||||
super().__init__(address, handler_class)
|
||||
self.jobs = []
|
||||
self.jobs_map = {}
|
||||
self.slaves = []
|
||||
self.slaves_map = {}
|
||||
self.job_id = 0
|
||||
self.path = path
|
||||
|
||||
def nextJobID(self):
|
||||
self.job_id += 1
|
||||
return str(self.job_id)
|
||||
|
||||
def addSlave(self, name, adress, stats):
|
||||
slave = MRenderSlave(name, adress, stats)
|
||||
def addSlave(self, name, address, stats):
|
||||
slave = MRenderSlave(name, address, stats)
|
||||
self.slaves.append(slave)
|
||||
self.slaves_map[slave.id] = slave
|
||||
|
||||
|
@ -10,7 +10,7 @@ class RenderSlave:
|
||||
def __init__(self):
|
||||
self.id = ""
|
||||
self.name = ""
|
||||
self.adress = (0,0)
|
||||
self.address = (0,0)
|
||||
self.stats = ""
|
||||
self.total_done = 0
|
||||
self.total_error = 0
|
||||
@ -20,7 +20,7 @@ class RenderSlave:
|
||||
return {
|
||||
"id": self.id,
|
||||
"name": self.name,
|
||||
"adress": self.adress,
|
||||
"address": self.address,
|
||||
"stats": self.stats,
|
||||
"total_done": self.total_done,
|
||||
"total_error": self.total_error,
|
||||
@ -40,7 +40,7 @@ class RenderSlave:
|
||||
slave = RenderSlave()
|
||||
slave.id = slave_id
|
||||
slave.name = data["name"]
|
||||
slave.adress = data["adress"]
|
||||
slave.address = data["address"]
|
||||
slave.stats = data["stats"]
|
||||
slave.total_done = data["total_done"]
|
||||
slave.total_error = data["total_error"]
|
||||
@ -54,7 +54,7 @@ class RenderJob:
|
||||
def __init__(self):
|
||||
self.id = ""
|
||||
self.name = ""
|
||||
self.path = ""
|
||||
self.files = []
|
||||
self.frames = []
|
||||
self.chunks = 0
|
||||
self.priority = 0
|
||||
@ -62,6 +62,11 @@ class RenderJob:
|
||||
self.blacklist = []
|
||||
self.last_dispatched = 0.0
|
||||
|
||||
def addFrame(self, frame_number):
|
||||
frame = RenderFrame(frame_number)
|
||||
self.frames.append(frame)
|
||||
return frame
|
||||
|
||||
def __len__(self):
|
||||
return len(self.frames)
|
||||
|
||||
@ -96,8 +101,9 @@ class RenderJob:
|
||||
return {
|
||||
"id": self.id,
|
||||
"name": self.name,
|
||||
"path": self.path,
|
||||
"files": self.files,
|
||||
"frames": [f.serialize() for f in self.frames if not frames or f in frames],
|
||||
"chunks": self.chunks,
|
||||
"priority": self.priority,
|
||||
"credits": self.credits,
|
||||
"blacklist": self.blacklist,
|
||||
@ -112,8 +118,9 @@ class RenderJob:
|
||||
job = RenderJob()
|
||||
job.id = data["id"]
|
||||
job.name = data["name"]
|
||||
job.path = data["path"]
|
||||
job.files = data["files"]
|
||||
job.frames = [RenderFrame.materialize(f) for f in data["frames"]]
|
||||
job.chunks = data["chunks"]
|
||||
job.priority = data["priority"]
|
||||
job.credits = data["credits"]
|
||||
job.blacklist = data["blacklist"]
|
||||
@ -122,8 +129,8 @@ class RenderJob:
|
||||
return job
|
||||
|
||||
class RenderFrame:
|
||||
def __init__(self):
|
||||
self.number = 0
|
||||
def __init__(self, number = 0):
|
||||
self.number = number
|
||||
self.time = 0
|
||||
self.status = QUEUED
|
||||
self.slave = None
|
||||
|
@ -48,7 +48,7 @@ class RENDER_OT_netclientstatus(bpy.types.Operator):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
netprops = context.scene.network_render
|
||||
netsettings = context.scene.network_render
|
||||
conn = clientConnection(context.scene)
|
||||
|
||||
if conn:
|
||||
@ -59,12 +59,12 @@ class RENDER_OT_netclientstatus(bpy.types.Operator):
|
||||
|
||||
jobs = (netrender.model.RenderJob.materialize(j) for j in eval(str(response.read(), encoding='utf8')))
|
||||
|
||||
while(len(netprops.jobs) > 0):
|
||||
netprops.jobs.remove(0)
|
||||
while(len(netsettings.jobs) > 0):
|
||||
netsettings.jobs.remove(0)
|
||||
|
||||
for j in jobs:
|
||||
netprops.jobs.add()
|
||||
job = netprops.jobs[-1]
|
||||
netsettings.jobs.add()
|
||||
job = netsettings.jobs[-1]
|
||||
|
||||
job_results = j.framesStatus()
|
||||
|
||||
@ -93,22 +93,22 @@ class RENDER_OT_netclientblacklistslave(bpy.types.Operator):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
netprops = context.scene.network_render
|
||||
netsettings = context.scene.network_render
|
||||
|
||||
if netprops.active_slave_index >= 0:
|
||||
if netsettings.active_slave_index >= 0:
|
||||
|
||||
slave = netrender.slaves[netprops.active_slave_index]
|
||||
slave = netrender.slaves[netsettings.active_slave_index]
|
||||
|
||||
netprops.slaves_blacklist.add()
|
||||
netsettings.slaves_blacklist.add()
|
||||
|
||||
netprops.slaves_blacklist[-1].id = slave.id
|
||||
netprops.slaves_blacklist[-1].name = slave.name
|
||||
netprops.slaves_blacklist[-1].adress = slave.adress
|
||||
netprops.slaves_blacklist[-1].last_seen = slave.last_seen
|
||||
netprops.slaves_blacklist[-1].stats = slave.stats
|
||||
netsettings.slaves_blacklist[-1].id = slave.id
|
||||
netsettings.slaves_blacklist[-1].name = slave.name
|
||||
netsettings.slaves_blacklist[-1].address = slave.address
|
||||
netsettings.slaves_blacklist[-1].last_seen = slave.last_seen
|
||||
netsettings.slaves_blacklist[-1].stats = slave.stats
|
||||
|
||||
netprops.slaves.remove(netprops.active_slave_index)
|
||||
netprops.active_slave_index = -1
|
||||
netsettings.slaves.remove(netsettings.active_slave_index)
|
||||
netsettings.active_slave_index = -1
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
@ -129,22 +129,22 @@ class RENDER_OT_netclientwhitelistslave(bpy.types.Operator):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
netprops = context.scene.network_render
|
||||
netsettings = context.scene.network_render
|
||||
|
||||
if netprops.active_blacklisted_slave_index >= 0:
|
||||
if netsettings.active_blacklisted_slave_index >= 0:
|
||||
|
||||
slave = netprops.slaves_blacklist[netprops.active_blacklisted_slave_index]
|
||||
slave = netsettings.slaves_blacklist[netsettings.active_blacklisted_slave_index]
|
||||
|
||||
netprops.slaves.add()
|
||||
netsettings.slaves.add()
|
||||
|
||||
netprops.slaves[-1].id = slave.id
|
||||
netprops.slaves[-1].name = slave.name
|
||||
netprops.slaves[-1].adress = slave.adress
|
||||
netprops.slaves[-1].last_seen = slave.last_seen
|
||||
netprops.slaves[-1].stats = slave.stats
|
||||
netsettings.slaves[-1].id = slave.id
|
||||
netsettings.slaves[-1].name = slave.name
|
||||
netsettings.slaves[-1].address = slave.address
|
||||
netsettings.slaves[-1].last_seen = slave.last_seen
|
||||
netsettings.slaves[-1].stats = slave.stats
|
||||
|
||||
netprops.slaves_blacklist.remove(netprops.active_blacklisted_slave_index)
|
||||
netprops.active_blacklisted_slave_index = -1
|
||||
netsettings.slaves_blacklist.remove(netsettings.active_blacklisted_slave_index)
|
||||
netsettings.active_blacklisted_slave_index = -1
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
@ -166,7 +166,7 @@ class RENDER_OT_netclientslaves(bpy.types.Operator):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
netprops = context.scene.network_render
|
||||
netsettings = context.scene.network_render
|
||||
conn = clientConnection(context.scene)
|
||||
|
||||
if conn:
|
||||
@ -177,21 +177,21 @@ class RENDER_OT_netclientslaves(bpy.types.Operator):
|
||||
|
||||
slaves = (netrender.model.RenderSlave.materialize(s) for s in eval(str(response.read(), encoding='utf8')))
|
||||
|
||||
while(len(netprops.slaves) > 0):
|
||||
netprops.slaves.remove(0)
|
||||
while(len(netsettings.slaves) > 0):
|
||||
netsettings.slaves.remove(0)
|
||||
|
||||
for s in slaves:
|
||||
for slave in netprops.slaves_blacklist:
|
||||
for slave in netsettings.slaves_blacklist:
|
||||
if slave.id == s.id:
|
||||
break
|
||||
|
||||
netprops.slaves.add()
|
||||
slave = netprops.slaves[-1]
|
||||
netsettings.slaves.add()
|
||||
slave = netsettings.slaves[-1]
|
||||
|
||||
slave.id = s.id
|
||||
slave.name = s.name
|
||||
slave.stats = s.stats
|
||||
slave.adress = s.adress[0]
|
||||
slave.address = s.address[0]
|
||||
slave.last_seen = time.ctime(s.last_seen)
|
||||
|
||||
return ('FINISHED',)
|
||||
@ -210,15 +210,15 @@ class RENDER_OT_netclientcancel(bpy.types.Operator):
|
||||
__props__ = []
|
||||
|
||||
def poll(self, context):
|
||||
netprops = context.scene.network_render
|
||||
return netprops.active_job_index >= 0 and len(netprops.jobs) > 0
|
||||
netsettings = context.scene.network_render
|
||||
return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
|
||||
|
||||
def execute(self, context):
|
||||
netprops = context.scene.network_render
|
||||
netsettings = context.scene.network_render
|
||||
conn = clientConnection(context.scene)
|
||||
|
||||
if conn:
|
||||
job = netprops.jobs[netprops.active_job_index]
|
||||
job = netsettings.jobs[netsettings.active_job_index]
|
||||
|
||||
conn.request("POST", "cancel", headers={"job-id":job.id})
|
||||
|
||||
|
@ -21,17 +21,50 @@ def testCancel(conn, job_id):
|
||||
response = conn.getresponse()
|
||||
|
||||
# cancelled if job isn't found anymore
|
||||
if response.status == http.client.NOT_FOUND:
|
||||
if response.status == http.client.NO_CONTENT:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def render_slave(engine, scene):
|
||||
NODE_PREFIX = PATH_PREFIX + "node" + os.sep
|
||||
timeout = 1
|
||||
def testFile(conn, JOB_PREFIX, file_path, main_path = None):
|
||||
if os.path.isabs(file_path):
|
||||
# if an absolute path, make sure path exists, if it doesn't, use relative local path
|
||||
job_full_path = file_path
|
||||
if not os.path.exists(job_full_path):
|
||||
p, n = os.path.split(job_full_path)
|
||||
|
||||
if main_path and p.startswith(main_path):
|
||||
directory = JOB_PREFIX + p[len(main_path):]
|
||||
job_full_path = directory + n
|
||||
if not os.path.exists(directory):
|
||||
os.mkdir(directory)
|
||||
else:
|
||||
job_full_path = JOB_PREFIX + n
|
||||
else:
|
||||
job_full_path = JOB_PREFIX + file_path
|
||||
|
||||
if not os.path.exists(NODE_PREFIX):
|
||||
os.mkdir(NODE_PREFIX)
|
||||
if not os.path.exists(job_full_path):
|
||||
conn.request("GET", "file", headers={"job-id": job.id, "slave-id":slave_id})
|
||||
response = conn.getresponse()
|
||||
|
||||
if response.status != http.client.OK:
|
||||
return None # file for job not returned by server, need to return an error code to server
|
||||
|
||||
f = open(job_full_path, "wb")
|
||||
buf = response.read(1024)
|
||||
|
||||
while buf:
|
||||
f.write(buf)
|
||||
buf = response.read(1024)
|
||||
|
||||
f.close()
|
||||
|
||||
return job_full_path
|
||||
|
||||
|
||||
def render_slave(engine, scene):
|
||||
netsettings = scene.network_render
|
||||
timeout = 1
|
||||
|
||||
engine.update_stats("", "Network render node initiation")
|
||||
|
||||
@ -43,6 +76,10 @@ def render_slave(engine, scene):
|
||||
|
||||
slave_id = response.getheader("slave-id")
|
||||
|
||||
NODE_PREFIX = netsettings.path + "node_" + slave_id + os.sep
|
||||
if not os.path.exists(NODE_PREFIX):
|
||||
os.mkdir(NODE_PREFIX)
|
||||
|
||||
while not engine.test_break():
|
||||
|
||||
conn.request("GET", "job", headers={"slave-id":slave_id})
|
||||
@ -53,41 +90,30 @@ def render_slave(engine, scene):
|
||||
|
||||
job = netrender.model.RenderJob.materialize(eval(str(response.read(), encoding='utf8')))
|
||||
|
||||
print("File:", job.path)
|
||||
engine.update_stats("", "Render File", job.path, "for job", job.id)
|
||||
JOB_PREFIX = NODE_PREFIX + "job_" + job.id + os.sep
|
||||
if not os.path.exists(JOB_PREFIX):
|
||||
os.mkdir(JOB_PREFIX)
|
||||
|
||||
if os.path.isabs(job.path):
|
||||
# if an absolute path, make sure path exists, if it doesn't, use relative local path
|
||||
job_full_path = job.path
|
||||
if not os.path.exists(job_full_path):
|
||||
job_full_path = NODE_PREFIX + job.id + ".blend"
|
||||
else:
|
||||
job_full_path = NODE_PREFIX + job.path
|
||||
job_path = job.files[0]
|
||||
main_path, main_file = os.path.split(job_path)
|
||||
|
||||
if not os.path.exists(job_full_path):
|
||||
conn.request("GET", "file", headers={"job-id": job.id, "slave-id":slave_id})
|
||||
response = conn.getresponse()
|
||||
|
||||
if response.status != http.client.OK:
|
||||
break # file for job not returned by server, need to return an error code to server
|
||||
|
||||
f = open(job_full_path, "wb")
|
||||
buf = response.read(1024)
|
||||
|
||||
while buf:
|
||||
f.write(buf)
|
||||
buf = response.read(1024)
|
||||
|
||||
f.close()
|
||||
job_full_path = testFile(conn, JOB_PREFIX, job_path)
|
||||
print("Fullpath", job_full_path)
|
||||
print("File:", main_file, "and %i other files" % (len(job.files) - 1,))
|
||||
engine.update_stats("", "Render File", main_file, "for job", job.id)
|
||||
|
||||
for file_path in job.files[1:]:
|
||||
testFile(conn, JOB_PREFIX, file_path, main_path)
|
||||
|
||||
frame_args = []
|
||||
|
||||
for frame in job.frames:
|
||||
print("frame", frame.number)
|
||||
frame_args += ["-f", str(frame.number)]
|
||||
|
||||
start_t = time.time()
|
||||
|
||||
process = subprocess.Popen([sys.argv[0], "-b", job_full_path, "-o", NODE_PREFIX + job.id, "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
process = subprocess.Popen([sys.argv[0], "-b", job_full_path, "-o", JOB_PREFIX + "######", "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
|
||||
cancelled = False
|
||||
stdout = bytes()
|
||||
@ -120,7 +146,7 @@ def render_slave(engine, scene):
|
||||
for frame in job.frames:
|
||||
headers["job-frame"] = str(frame.number)
|
||||
# send result back to server
|
||||
f = open(NODE_PREFIX + job.id + "%04d" % frame.number + ".exr", 'rb')
|
||||
f = open(JOB_PREFIX + "%06d" % frame.number + ".exr", 'rb')
|
||||
conn.request("PUT", "render", f, headers=headers)
|
||||
f.close()
|
||||
response = conn.getresponse()
|
||||
|
@ -48,9 +48,11 @@ class SCENE_PT_network_settings(RenderButtonsPanel):
|
||||
col.itemR(scene.network_render, "mode")
|
||||
col.itemR(scene.network_render, "server_address")
|
||||
col.itemR(scene.network_render, "server_port")
|
||||
col.itemR(scene.network_render, "path")
|
||||
|
||||
if scene.network_render.mode == "RENDER_CLIENT":
|
||||
col.itemR(scene.network_render, "chunks")
|
||||
col.itemR(scene.network_render, "priority")
|
||||
col.itemR(scene.network_render, "job_name")
|
||||
col.itemO("render.netclientsend", text="send job to server")
|
||||
bpy.types.register(SCENE_PT_network_settings)
|
||||
@ -84,7 +86,7 @@ class SCENE_PT_network_slaves(RenderButtonsPanel):
|
||||
slave = netrender.slaves[netrender.active_slave_index]
|
||||
|
||||
layout.itemL(text="Name: " + slave.name)
|
||||
layout.itemL(text="Adress: " + slave.adress)
|
||||
layout.itemL(text="Address: " + slave.address)
|
||||
layout.itemL(text="Seen: " + slave.last_seen)
|
||||
layout.itemL(text="Stats: " + slave.stats)
|
||||
|
||||
@ -119,7 +121,7 @@ class SCENE_PT_network_slaves_blacklist(RenderButtonsPanel):
|
||||
slave = netrender.slaves_blacklist[netrender.active_blacklisted_slave_index]
|
||||
|
||||
layout.itemL(text="Name: " + slave.name)
|
||||
layout.itemL(text="Adress: " + slave.adress)
|
||||
layout.itemL(text="Address: " + slave.address)
|
||||
layout.itemL(text="Seen: " + slave.last_seen)
|
||||
layout.itemL(text="Stats: " + slave.stats)
|
||||
|
||||
@ -189,6 +191,12 @@ NetRenderSettings.IntProperty( attr="server_port",
|
||||
min=1,
|
||||
max=65535)
|
||||
|
||||
NetRenderSettings.StringProperty( attr="path",
|
||||
name="Path",
|
||||
description="Path for temporary files",
|
||||
maxlen = 128,
|
||||
default = "/tmp/")
|
||||
|
||||
NetRenderSettings.StringProperty( attr="job_name",
|
||||
name="Job name",
|
||||
description="Name of the job",
|
||||
@ -202,6 +210,13 @@ NetRenderSettings.IntProperty( attr="chunks",
|
||||
min=1,
|
||||
max=65535)
|
||||
|
||||
NetRenderSettings.IntProperty( attr="priority",
|
||||
name="Priority",
|
||||
description="Priority of the job",
|
||||
default = 1,
|
||||
min=1,
|
||||
max=10)
|
||||
|
||||
NetRenderSettings.StringProperty( attr="job_id",
|
||||
name="Network job id",
|
||||
description="id of the last sent render job",
|
||||
@ -249,8 +264,8 @@ NetRenderSlave.StringProperty( attr="name",
|
||||
maxlen = 64,
|
||||
default = "")
|
||||
|
||||
NetRenderSlave.StringProperty( attr="adress",
|
||||
name="Adress of the slave",
|
||||
NetRenderSlave.StringProperty( attr="address",
|
||||
name="Address of the slave",
|
||||
description="",
|
||||
maxlen = 64,
|
||||
default = "")
|
||||
|
@ -3,9 +3,9 @@ import sys, os
|
||||
import http, http.client, http.server, urllib
|
||||
import subprocess, shutil, time, hashlib
|
||||
|
||||
VERSION = b"0.3"
|
||||
import netrender.model
|
||||
|
||||
PATH_PREFIX = "/tmp/"
|
||||
VERSION = b"0.3"
|
||||
|
||||
QUEUED = 0
|
||||
DISPATCHED = 1
|
||||
@ -41,40 +41,46 @@ def clientVerifyVersion(conn):
|
||||
return True
|
||||
|
||||
def clientSendJob(conn, scene, anim = False, chunks = 5):
|
||||
netsettings = scene.network_render
|
||||
job = netrender.model.RenderJob()
|
||||
|
||||
if anim:
|
||||
job_frame = "%i:%i" % (scene.start_frame, scene.end_frame)
|
||||
for f in range(scene.start_frame, scene.end_frame + 1):
|
||||
job.addFrame(f)
|
||||
else:
|
||||
job_frame = "%i" % (scene.current_frame, )
|
||||
|
||||
blacklist = []
|
||||
job.addFrame(scene.current_frame)
|
||||
|
||||
filename = bpy.data.filename
|
||||
job.files.append(filename)
|
||||
|
||||
name = scene.network_render.job_name
|
||||
|
||||
name = netsettings.job_name
|
||||
if name == "[default]":
|
||||
path, name = os.path.split(filename)
|
||||
|
||||
for slave in scene.network_render.slaves_blacklist:
|
||||
blacklist.append(slave.id)
|
||||
|
||||
blacklist = " ".join(blacklist)
|
||||
job.name = name
|
||||
|
||||
headers = {"job-frame":job_frame, "job-name":name, "job-chunks": str(chunks), "slave-blacklist": blacklist}
|
||||
for slave in scene.network_render.slaves_blacklist:
|
||||
job.blacklist.append(slave.id)
|
||||
|
||||
job.chunks = netsettings.chunks
|
||||
job.priority = netsettings.priority
|
||||
|
||||
# try to send path first
|
||||
conn.request("POST", "job", filename, headers=headers)
|
||||
conn.request("POST", "job", repr(job.serialize()))
|
||||
response = conn.getresponse()
|
||||
|
||||
job_id = response.getheader("job-id")
|
||||
|
||||
# if not found, send whole file
|
||||
if response.status == http.client.NOT_FOUND:
|
||||
f = open(bpy.data.filename, "rb")
|
||||
conn.request("PUT", "file", f, headers=headers)
|
||||
conn.request("PUT", "file", f, headers={"job-id": job_id})
|
||||
f.close()
|
||||
response = conn.getresponse()
|
||||
|
||||
return response.getheader("job-id")
|
||||
# server will reply with NOT_FOUD until all files are found
|
||||
|
||||
return job_id
|
||||
|
||||
def clientRequestResult(conn, scene, job_id):
|
||||
conn.request("GET", "render", headers={"job-id": job_id, "job-frame":str(scene.current_frame)})
|
||||
|
Loading…
Reference in New Issue
Block a user