blender/release/scripts/io/netrender/model.py
Martin Poirier c0bae16dad netrender
Downloading results for jobs from blender now uses the current output settings, it doesn't just download the multilayer exr as it used to.

Render output panel now visible under the jobs panel in client mode.
2011-01-08 19:42:26 +00:00

361 lines
11 KiB
Python

# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# 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.
#
# 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
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
import sys, os
import http, http.client, http.server, urllib
import subprocess, shutil, time, hashlib
import netrender.versioning as versioning
from netrender.utils import *
class LogFile:
def __init__(self, job_id = 0, slave_id = 0, frames = []):
self.job_id = job_id
self.slave_id = slave_id
self.frames = frames
def serialize(self):
return {
"job_id": self.job_id,
"slave_id": self.slave_id,
"frames": self.frames
}
@staticmethod
def materialize(data):
if not data:
return None
logfile = LogFile()
logfile.job_id = data["job_id"]
logfile.slave_id = data["slave_id"]
logfile.frames = data["frames"]
return logfile
class RenderSlave:
_slave_map = {}
def __init__(self):
self.id = ""
self.name = ""
self.address = ("",0)
self.stats = ""
self.total_done = 0
self.total_error = 0
self.last_seen = 0.0
def serialize(self):
return {
"id": self.id,
"name": self.name,
"address": self.address,
"stats": self.stats,
"total_done": self.total_done,
"total_error": self.total_error,
"last_seen": self.last_seen
}
@staticmethod
def materialize(data, cache = True):
if not data:
return None
slave_id = data["id"]
if cache and slave_id in RenderSlave._slave_map:
return RenderSlave._slave_map[slave_id]
slave = RenderSlave()
slave.id = slave_id
slave.name = data["name"]
slave.address = data["address"]
slave.stats = data["stats"]
slave.total_done = data["total_done"]
slave.total_error = data["total_error"]
slave.last_seen = data["last_seen"]
if cache:
RenderSlave._slave_map[slave_id] = slave
return slave
JOB_BLENDER = 1
JOB_PROCESS = 2
JOB_VCS = 3
JOB_TYPES = {
JOB_BLENDER: "Blender",
JOB_PROCESS: "Process",
JOB_VCS: "Versioned",
}
class VersioningInfo:
def __init__(self, info = None):
self._system = None
self.wpath = ""
self.rpath = ""
self.revision = ""
@property
def system(self):
return self._system
@system.setter
def system(self, value):
self._system = versioning.SYSTEMS[value]
def update(self):
self.system.update(self)
def serialize(self):
return {
"wpath": self.wpath,
"rpath": self.rpath,
"revision": self.revision,
"system": self.system.name
}
@staticmethod
def generate(system, path):
vs = VersioningInfo()
vs.wpath = path
vs.system = system
vs.rpath = vs.system.path(path)
vs.revision = vs.system.revision(path)
return vs
@staticmethod
def materialize(data):
if not data:
return None
vs = VersioningInfo()
vs.wpath = data["wpath"]
vs.rpath = data["rpath"]
vs.revision = data["revision"]
vs.system = data["system"]
return vs
class RenderFile:
def __init__(self, filepath = "", index = 0, start = -1, end = -1, signature=0):
self.filepath = filepath
self.original_path = filepath
self.signature = signature
self.index = index
self.start = start
self.end = end
def serialize(self):
return {
"filepath": self.filepath,
"original_path": self.original_path,
"index": self.index,
"start": self.start,
"end": self.end,
"signature": self.signature
}
@staticmethod
def materialize(data):
if not data:
return None
rfile = RenderFile(data["filepath"], data["index"], data["start"], data["end"], data["signature"])
rfile.original_path = data["original_path"]
return rfile
class RenderJob:
def __init__(self, job_info = None):
self.id = ""
self.type = JOB_BLENDER
self.name = ""
self.category = "None"
self.status = JOB_WAITING
self.files = []
self.chunks = 0
self.priority = 0
self.blacklist = []
self.version_info = None
self.resolution = None
self.usage = 0.0
self.last_dispatched = 0.0
self.frames = []
if job_info:
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
self.blacklist = job_info.blacklist
self.version_info = job_info.version_info
def hasRenderResult(self):
return self.type in (JOB_BLENDER, JOB_VCS)
def rendersWithBlender(self):
return self.type in (JOB_BLENDER, JOB_VCS)
def addFile(self, file_path, start=-1, end=-1, signed=True):
if signed:
signature = hashFile(file_path)
else:
signature = None
self.files.append(RenderFile(file_path, len(self.files), start, end, signature))
def addFrame(self, frame_number, command = ""):
frame = RenderFrame(frame_number, command)
self.frames.append(frame)
return frame
def __len__(self):
return len(self.frames)
def countFrames(self, status=QUEUED):
total = 0
for f in self.frames:
if f.status == status:
total += 1
return total
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,
DISPATCHED: 0,
DONE: 0,
ERROR: 0
}
for frame in self.frames:
results[frame.status] += 1
return results
def __contains__(self, frame_number):
for f in self.frames:
if f.number == frame_number:
return True
else:
return False
def __getitem__(self, frame_number):
for f in self.frames:
if f.number == frame_number:
return f
else:
return None
def serialize(self, frames = None):
min_frame = min((f.number for f in frames)) if frames else -1
max_frame = max((f.number for f in frames)) if frames else -1
return {
"id": self.id,
"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,
"priority": self.priority,
"usage": self.usage,
"blacklist": self.blacklist,
"last_dispatched": self.last_dispatched,
"version_info": self.version_info.serialize() if self.version_info else None,
"resolution": self.resolution
}
@staticmethod
def materialize(data):
if not data:
return None
job = RenderJob()
job.id = data["id"]
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"]
job.priority = data["priority"]
job.usage = data["usage"]
job.blacklist = data["blacklist"]
job.last_dispatched = data["last_dispatched"]
job.resolution = data["resolution"]
version_info = data.get("version_info", None)
if version_info:
job.version_info = VersioningInfo.materialize(version_info)
return job
class RenderFrame:
def __init__(self, number = 0, command = ""):
self.number = number
self.time = 0
self.status = QUEUED
self.slave = None
self.command = command
def statusText(self):
return FRAME_STATUS_TEXT[self.status]
def serialize(self):
return {
"number": self.number,
"time": self.time,
"status": self.status,
"slave": None if not self.slave else self.slave.serialize(),
"command": self.command
}
@staticmethod
def materialize(data):
if not data:
return None
frame = RenderFrame()
frame.number = data["number"]
frame.time = data["time"]
frame.status = data["status"]
frame.slave = RenderSlave.materialize(data["slave"])
frame.command = data["command"]
return frame