netrender (features coded by Philippe van Hecke)
Support for secure connections between Master/client/slave using SSL/HTTPS Fixed a bug with total job time on web interface (wrong value)
This commit is contained in:
parent
88085b624c
commit
8b56ce969d
|
@ -112,10 +112,10 @@ def fillCommonJobSettings(job, job_name, netsettings):
|
|||
elif netsettings.job_type == "JOB_VCS":
|
||||
job.type = netrender.model.JOB_VCS
|
||||
|
||||
def sendJob(conn, scene, anim = False):
|
||||
def sendJob(conn, scene, anim = False, can_save = True):
|
||||
netsettings = scene.network_render
|
||||
if netsettings.job_type == "JOB_BLENDER":
|
||||
return sendJobBlender(conn, scene, anim)
|
||||
return sendJobBlender(conn, scene, anim, can_save)
|
||||
elif netsettings.job_type == "JOB_VCS":
|
||||
return sendJobVCS(conn, scene, anim)
|
||||
|
||||
|
@ -171,7 +171,7 @@ def sendJobVCS(conn, scene, anim = False):
|
|||
|
||||
return job_id
|
||||
|
||||
def sendJobBaking(conn, scene):
|
||||
def sendJobBaking(conn, scene, can_save = True):
|
||||
netsettings = scene.network_render
|
||||
job = netrender.model.RenderJob()
|
||||
|
||||
|
@ -179,6 +179,9 @@ def sendJobBaking(conn, scene):
|
|||
|
||||
if not os.path.exists(filename):
|
||||
raise RuntimeError("Current file path not defined\nSave your file before sending a job")
|
||||
|
||||
if can_save and netsettings.save_before_job:
|
||||
bpy.ops.wm.save_mainfile(filepath=filename, check_existing=False)
|
||||
|
||||
job.addFile(filename)
|
||||
|
||||
|
@ -248,7 +251,7 @@ def sendJobBaking(conn, scene):
|
|||
|
||||
return job_id
|
||||
|
||||
def sendJobBlender(conn, scene, anim = False):
|
||||
def sendJobBlender(conn, scene, anim = False, can_save = True):
|
||||
netsettings = scene.network_render
|
||||
job = netrender.model.RenderJob()
|
||||
|
||||
|
@ -263,7 +266,7 @@ def sendJobBlender(conn, scene, anim = False):
|
|||
if not os.path.exists(filename):
|
||||
raise RuntimeError("Current file path not defined\nSave your file before sending a job")
|
||||
|
||||
if netsettings.save_before_job:
|
||||
if can_save and netsettings.save_before_job:
|
||||
bpy.ops.wm.save_mainfile(filepath=filename, check_existing=False)
|
||||
|
||||
job.addFile(filename)
|
||||
|
@ -371,7 +374,10 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
|||
force = netsettings.use_master_force_upload,
|
||||
path = bpy.path.abspath(netsettings.path),
|
||||
update_stats = self.update_stats,
|
||||
test_break = self.test_break)
|
||||
test_break = self.test_break,
|
||||
use_ssl=netsettings.use_ssl,
|
||||
cert_path=netsettings.cert_path,
|
||||
key_path=netsettings.key_path)
|
||||
|
||||
|
||||
def render_slave(self, scene):
|
||||
|
@ -382,7 +388,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
|||
self.update_stats("", "Network render client initiation")
|
||||
|
||||
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings)
|
||||
|
||||
if conn:
|
||||
# Sending file
|
||||
|
@ -404,7 +410,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
|
|||
|
||||
if response.status == http.client.NO_CONTENT:
|
||||
new_job = True
|
||||
netsettings.job_id = sendJob(conn, scene)
|
||||
netsettings.job_id = sendJob(conn, scene, can_save = False)
|
||||
job_id = netsettings.job_id
|
||||
|
||||
requestResult(conn, job_id, scene.frame_current)
|
||||
|
|
|
@ -23,7 +23,7 @@ var jobTableHeader = ["action", "id", "name", "category", "tags", "type", "chunk
|
|||
var framesTableHeader = ["no", "status", "render time", "slave", "log", "result"];
|
||||
var JOB_TYPES = ["None", "Blender", "Process", "Versioned"];
|
||||
var JOB_STATUS_TEXT = ["Waiting", "Paused", "Finished", "Queued"];
|
||||
var JOB_SUBTYPE = ["BLENDER", "CYCLE"];
|
||||
var JOB_SUBTYPE = ["None", "BLENDER", "CYCLE"];
|
||||
var FRAME_STATUS_TEXT = ["Queued", "Dispatched", "Done", "error"];
|
||||
var JOB_TYPE_NONE = 0;
|
||||
var JOB_TYPE_BLENDER = 1;
|
||||
|
@ -86,7 +86,7 @@ function changeJobsTable(jobs) {
|
|||
}
|
||||
|
||||
if(name == "type") {
|
||||
return JOB_TYPES[row.type] + "[" + JOB_SUBTYPE[row.subtype] + "]";
|
||||
return JOB_TYPES[row.type] + "[" + row.render + "]";
|
||||
}
|
||||
|
||||
if(name == "status") {
|
||||
|
@ -283,14 +283,13 @@ function changeConfigureTable(rules) {
|
|||
function showJob(id, name) {
|
||||
|
||||
var job = {};
|
||||
|
||||
|
||||
function general(tab_name) {
|
||||
|
||||
var rendertime = 0;
|
||||
var cumulate_rendertime = 0;
|
||||
$.each(job.frames, function(index, frame) {
|
||||
rendertime += frame.time;
|
||||
cumulate_rendertime += frame.time;
|
||||
});
|
||||
var info = [new namevalue("resolution", job.resolution[0] + 'x' + job.resolution[1] + ' at ' + job.resolution[2] + '%'), new namevalue("tags", job.tags), new namevalue("result", getresult(id)), new namevalue("frames", job.frames.length), new namevalue("status", job.status), new namevalue("job name", job.name), new namevalue("type", job.type), new namevalue("render", job.subtype), new namevalue("render time:", secondsToHms(rendertime))];
|
||||
var info = [new namevalue("resolution", job.resolution[0] + 'x' + job.resolution[1] + ' at ' + job.resolution[2] + '%'), new namevalue("tags", job.tags), new namevalue("result", getresult(id)), new namevalue("frames", job.frames.length), new namevalue("status", job.status), new namevalue("job name", job.name), new namevalue("type", job.type), new namevalue("render", job.subtype), new namevalue("render time", secondsToHms(job.wktime)), new namevalue("cumulate render time", secondsToHms(cumulate_rendertime))];
|
||||
|
||||
function cellview(name, row) {
|
||||
|
||||
|
@ -313,7 +312,7 @@ function showJob(id, name) {
|
|||
case "type":
|
||||
return JOB_TYPES[job.type];
|
||||
case "render":
|
||||
return JOB_SUBTYPE[job.subtype];
|
||||
return job.render;
|
||||
|
||||
default:
|
||||
return row.value;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
#s
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
|
@ -24,6 +24,7 @@ import zipfile
|
|||
import select # for select.error
|
||||
import json
|
||||
|
||||
|
||||
from netrender.utils import *
|
||||
import netrender.model
|
||||
import netrender.balancing
|
||||
|
@ -59,6 +60,7 @@ class MRenderSlave(netrender.model.RenderSlave):
|
|||
super().__init__(slave_info)
|
||||
self.id = hashlib.md5(bytes(repr(slave_info.name) + repr(slave_info.address), encoding='utf8')).hexdigest()
|
||||
self.last_seen = time.time()
|
||||
|
||||
|
||||
self.job = None
|
||||
self.job_frames = []
|
||||
|
@ -82,7 +84,8 @@ class MRenderJob(netrender.model.RenderJob):
|
|||
super().__init__(job_info)
|
||||
self.id = job_id
|
||||
self.last_dispatched = time.time()
|
||||
|
||||
self.start_time = time.time()
|
||||
self.finish_time = self.start_time
|
||||
# force one chunk for process jobs
|
||||
if self.type == netrender.model.JOB_PROCESS:
|
||||
self.chunks = 1
|
||||
|
@ -136,6 +139,7 @@ class MRenderJob(netrender.model.RenderJob):
|
|||
break
|
||||
else:
|
||||
self.status = JOB_FINISHED
|
||||
self.finish_time=time.time()
|
||||
|
||||
def pause(self, status = None):
|
||||
if self.status not in {JOB_PAUSED, JOB_QUEUED}:
|
||||
|
@ -150,6 +154,7 @@ class MRenderJob(netrender.model.RenderJob):
|
|||
|
||||
def start(self):
|
||||
self.status = JOB_QUEUED
|
||||
|
||||
|
||||
def addLog(self, frames):
|
||||
frames = sorted(frames)
|
||||
|
@ -1149,11 +1154,13 @@ def saveMaster(path, httpd):
|
|||
with open(filepath, 'wb') as f:
|
||||
pickle.dump((httpd.path, httpd.jobs, httpd.slaves), f, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
def runMaster(address, broadcast, clear, force, path, update_stats, test_break):
|
||||
def runMaster(address, broadcast, clear, force, path, update_stats, test_break,use_ssl=False,cert_path="",key_path=""):
|
||||
httpd = createMaster(address, clear, force, path)
|
||||
httpd.timeout = 1
|
||||
httpd.stats = update_stats
|
||||
|
||||
if use_ssl:
|
||||
import ssl
|
||||
httpd.socket=ssl.wrap_socket(httpd.socket,certfile=cert_path,server_side=True,keyfile=key_path,ciphers="ALL",ssl_version=ssl.PROTOCOL_SSLv3)
|
||||
if broadcast:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
|
|
|
@ -142,7 +142,8 @@ def get(handler):
|
|||
tot_cache, tot_fluid, tot_other = countFiles(job)
|
||||
serializedJob["totcache"] = tot_cache
|
||||
serializedJob["totfluid"] = tot_fluid
|
||||
serializedJob["totother"] = tot_other
|
||||
serializedJob["totother"] = tot_other
|
||||
serializedJob["wktime"] = (time.time()-job.start_time ) if job.status != JOB_FINISHED else (job.finish_time-job.start_time)
|
||||
else:
|
||||
serializedJob={"name":"invalid job"}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class RENDER_OT_netclientsendbake(bpy.types.Operator):
|
|||
netsettings = scene.network_render
|
||||
|
||||
try:
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
# Sending file
|
||||
|
@ -70,7 +70,7 @@ class RENDER_OT_netclientanim(bpy.types.Operator):
|
|||
scene = context.scene
|
||||
netsettings = scene.network_render
|
||||
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
# Sending file
|
||||
|
@ -115,7 +115,7 @@ class RENDER_OT_netclientsend(bpy.types.Operator):
|
|||
netsettings = scene.network_render
|
||||
|
||||
try:
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
# Sending file
|
||||
|
@ -145,7 +145,7 @@ class RENDER_OT_netclientsendframe(bpy.types.Operator):
|
|||
netsettings = scene.network_render
|
||||
|
||||
try:
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
# Sending file
|
||||
|
@ -172,7 +172,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, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
with ConnectionContext():
|
||||
|
@ -274,7 +274,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, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
with ConnectionContext():
|
||||
|
@ -326,7 +326,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, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
job = netrender.jobs[netsettings.active_job_index]
|
||||
|
@ -355,7 +355,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, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
with ConnectionContext():
|
||||
|
@ -385,7 +385,7 @@ class netclientdownload(bpy.types.Operator):
|
|||
def execute(self, context):
|
||||
netsettings = context.scene.network_render
|
||||
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
job_id = netrender.jobs[netsettings.active_job_index].id
|
||||
|
@ -530,13 +530,14 @@ class netclientweb(bpy.types.Operator):
|
|||
|
||||
|
||||
# open connection to make sure server exists
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
|
||||
conn = clientConnection(netsettings, report = self.report)
|
||||
|
||||
if conn:
|
||||
conn.close()
|
||||
|
||||
webbrowser.open("http://%s:%i" % (netsettings.server_address, netsettings.server_port))
|
||||
|
||||
if netsettings.use_ssl:
|
||||
webbrowser.open("https://%s:%i" % (netsettings.server_address, netsettings.server_port))
|
||||
else:
|
||||
webbrowser.open("http://%s:%i" % (netsettings.server_address, netsettings.server_port))
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
|
|
|
@ -118,8 +118,8 @@ def render_slave(engine, netsettings, threads):
|
|||
if not os.access(slave_path, os.W_OK):
|
||||
print("Slave working path ( %s ) is not writable" % netsettings.path)
|
||||
return
|
||||
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
|
||||
conn = clientConnection(netsettings)
|
||||
|
||||
if not conn:
|
||||
print("Connection failed, will try connecting again at most %i times" % MAX_CONNECT_TRY)
|
||||
|
@ -128,7 +128,7 @@ def render_slave(engine, netsettings, threads):
|
|||
for i in range(MAX_CONNECT_TRY):
|
||||
bisleep.sleep()
|
||||
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port)
|
||||
conn = clientConnection(netsettings)
|
||||
|
||||
if conn or engine.test_break():
|
||||
break
|
||||
|
|
|
@ -70,7 +70,7 @@ def verify_address(netsettings, force=False):
|
|||
LAST_ADDRESS_TEST = time.time()
|
||||
|
||||
try:
|
||||
conn = clientConnection(netsettings.server_address, netsettings.server_port, scan = False, timeout = 1)
|
||||
conn = clientConnection(netsettings, scan = False, timeout = 1)
|
||||
except:
|
||||
conn = None
|
||||
|
||||
|
@ -120,25 +120,34 @@ class RENDER_PT_network_settings(NetRenderButtonsPanel, bpy.types.Panel):
|
|||
layout.operator("render.netclientstart", icon='PLAY')
|
||||
|
||||
layout.prop(netsettings, "path")
|
||||
|
||||
row = layout.row()
|
||||
|
||||
split = layout.split(percentage=0.7)
|
||||
split = layout.split(percentage=0.5)
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Server Address:")
|
||||
col.prop(netsettings, "server_address", text="")
|
||||
col.prop(netsettings, "server_address", text="Address")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Port:")
|
||||
col.prop(netsettings, "server_port", text="")
|
||||
row = col.row()
|
||||
row.prop(netsettings, "server_port", text="Port")
|
||||
row.prop(netsettings, "use_ssl", text="SSL")
|
||||
|
||||
if netsettings.mode != "RENDER_MASTER":
|
||||
layout.operator("render.netclientscan", icon='FILE_REFRESH', text="")
|
||||
|
||||
if not netrender.valid_address:
|
||||
layout.label(text="No master at specified address")
|
||||
|
||||
|
||||
if netsettings.use_ssl and netsettings.mode == "RENDER_MASTER":
|
||||
layout.prop(netsettings, "cert_path", text="Certificate")
|
||||
layout.prop(netsettings, "key_path", text="Key")
|
||||
|
||||
layout.operator("render.netclientweb", icon='QUESTION')
|
||||
|
||||
|
||||
|
||||
class RENDER_PT_network_slave_settings(NetRenderButtonsPanel, bpy.types.Panel):
|
||||
bl_label = "Slave Settings"
|
||||
COMPAT_ENGINES = {'NET_RENDER'}
|
||||
|
@ -403,6 +412,22 @@ class NetRenderSettings(bpy.types.PropertyGroup):
|
|||
name="Broadcast",
|
||||
description="broadcast master server address on local network",
|
||||
default = True)
|
||||
NetRenderSettings.use_ssl = BoolProperty(
|
||||
name="use ssl",
|
||||
description="use ssl encryption for communication",
|
||||
default = False)
|
||||
NetRenderSettings.cert_path = StringProperty(
|
||||
name="CertPath",
|
||||
description="Path to ssl certifcate",
|
||||
maxlen = 128,
|
||||
default = "",
|
||||
subtype='FILE_PATH')
|
||||
NetRenderSettings.key_path = StringProperty(
|
||||
name="key",
|
||||
description="Path to ssl key file",
|
||||
maxlen = 128,
|
||||
default = "",
|
||||
subtype='FILE_PATH')
|
||||
|
||||
NetRenderSettings.use_slave_clear = BoolProperty(
|
||||
name="Clear on exit",
|
||||
|
|
|
@ -186,8 +186,12 @@ def clientScan(report = None):
|
|||
|
||||
return ("", 8000) # return default values
|
||||
|
||||
def clientConnection(address, port, report = None, scan = True, timeout = 5):
|
||||
if address == "[default]":
|
||||
def clientConnection(netsettings, report = None, scan = True, timeout = 5):
|
||||
address = netsettings.server_address
|
||||
port = netsettings.server_port
|
||||
use_ssl = netsettings.use_ssl
|
||||
|
||||
if address== "[default]":
|
||||
# calling operator from python is fucked, scene isn't in context
|
||||
# if bpy:
|
||||
# bpy.ops.render.netclientscan()
|
||||
|
@ -198,13 +202,14 @@ def clientConnection(address, port, report = None, scan = True, timeout = 5):
|
|||
address, port = clientScan()
|
||||
if address == "":
|
||||
return None
|
||||
|
||||
conn = None
|
||||
try:
|
||||
HTTPConnection = http.client.HTTPSConnection if use_ssl else http.client.HTTPConnection
|
||||
if platform.system() == "Darwin":
|
||||
with ConnectionContext(timeout):
|
||||
conn = http.client.HTTPConnection(address, port)
|
||||
conn = HTTPConnection(address, port)
|
||||
else:
|
||||
conn = http.client.HTTPConnection(address, port, timeout = timeout)
|
||||
conn = HTTPConnection(address, port, timeout = timeout)
|
||||
|
||||
if conn:
|
||||
if clientVerifyVersion(conn):
|
||||
|
|
Loading…
Reference in New Issue