[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3458] trunk/py/scripts/tools/bi_farm: initial commit for the blender institutes renderfarm - written by Brecht, Segrey and myself.

Campbell Barton ideasman42 at gmail.com
Wed Jun 6 09:16:23 CEST 2012


Revision: 3458
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3458
Author:   campbellbarton
Date:     2012-06-06 07:16:10 +0000 (Wed, 06 Jun 2012)
Log Message:
-----------
initial commit for the blender institutes renderfarm - written by Brecht, Segrey and myself.

Added Paths:
-----------
    trunk/py/scripts/tools/bi_farm/exr_header_collate.py
    trunk/py/scripts/tools/bi_farm/master_ui.css
    trunk/py/scripts/tools/bi_farm/master_ui.js
    trunk/py/scripts/tools/bi_farm/master_ui.py
    trunk/py/scripts/tools/bi_farm/new_blend_2_frames.py
    trunk/py/scripts/tools/bi_farm/new_master.py
    trunk/py/scripts/tools/bi_farm/render_dirs.py

Added: trunk/py/scripts/tools/bi_farm/exr_header_collate.py
===================================================================
--- trunk/py/scripts/tools/bi_farm/exr_header_collate.py	                        (rev 0)
+++ trunk/py/scripts/tools/bi_farm/exr_header_collate.py	2012-06-06 07:16:10 UTC (rev 3458)
@@ -0,0 +1,213 @@
+#!/usr/bin/env 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 #####
+
+# <pep8-80 compliant>
+
+import os
+import subprocess
+import time
+
+DIR = "/render/mango/frames/"
+BIGNUM = 100000000.0
+
+# copied from bpy.utils
+def smpte_from_seconds(time):
+    import math
+
+    hours = minutes = seconds = frames = 0
+
+    if time < 0:
+        time = -time
+        neg = "-"
+    else:
+        neg = ""
+
+    if time >= 3600.0: # hours
+        hours = int(time / 3600.0)
+        time = time % 3600.0
+    if time >= 60.0: # mins
+        minutes = int(time / 60.0)
+        time = time % 60.0
+
+    seconds = time
+    string = "%s%02dh, %02dmin, %0.1fsec" % (neg, hours, minutes, seconds)
+    return string.replace("00h, ", "     ")
+
+
+def format_time(file, sec, ip):
+    return "%s | %s | %.2f | %s" % (file, smpte_from_seconds(sec), sec, ip)
+
+
+def decode_rendertime(time_str):
+    '''decodes blender rendertime from metadata'''
+    time_split = time_str.split(":")
+    sec = float(time_split.pop())
+    if time_split:
+        sec += float(time_split.pop()) * 60.0
+
+    if time_split:
+        sec += float(time_split.pop()) * 3600.0
+    return sec
+
+
+def file_date(path):
+    #currtime = (year, month, day, hour, min, sec)
+    # year, month, day, hour, minute, second, weekday, yearday, daylight = now
+    return time.localtime(os.stat(path)[8])[0:6]
+
+
+def update_render_times(dirname, all_rendertimes, size=(None, None)):
+    dirname_full = os.path.join(DIR, dirname)
+    if not os.path.isdir(dirname_full):
+        print("NOT A DIR:", dirname_full)
+        return
+    
+    exrs = []
+    time_sec_average = 0.0
+    time_sec_min = BIGNUM
+    time_sec_max = 0.0
+
+    time_file = os.path.join(dirname_full, "render_times.txt")
+    if os.path.exists(time_file):
+        generate_timefile = False
+        time_file_chtime = file_date(time_file) 
+    else:
+        generate_timefile = True
+        time_file_chtime = None
+    
+    for exr in sorted(os.listdir(dirname_full)):
+        if exr.endswith(".exr"):
+            # print(exr)
+            exr_full = os.path.join(dirname_full, exr)
+            exrs.append((exr, exr_full))
+            
+            if generate_timefile is False:
+                if time_file_chtime < file_date(exr_full):
+                    generate_timefile = True
+
+    '''
+    if generate_timefile:
+        print("Timefile writing:", time_file)
+    else:
+        print("Timefile up-to-date:", time_file)
+    '''
+
+    # XXX - always generate
+    if generate_timefile or True:
+        file_rendertimes = []
+        for exr, exr_full in exrs:
+            # yay. we have exr
+
+            out, err = subprocess.Popen(["exrheader", exr_full], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+            # print(out)
+            lines = str(out).split("\\n")
+            lines_rtime = [l for l in lines if "RenderTime " in l]
+
+            if lines_rtime:
+                lines_rtime = [l for l in lines if "RenderTime " in l]
+                lines_ip = [l for l in lines if "Note " in l]
+                lines_size = [l for l in lines if "displayWindow " in l]
+
+                # convert to time
+                sec = decode_rendertime(lines_rtime[0].split()[-1].replace('"', ''))
+
+                # ip of PC rendering
+                print(exr_full)
+                ip = lines_ip[0].split(": ", 1)[-1].replace('"', '')
+
+                # size
+                size_exr = lines_size[0].replace("(", "").replace(")", "").split()[-2:]
+                size_exr = int(size_exr[0]) + 1, int(size_exr[1]) + 1
+
+                if size != (None, None):
+                    if size_exr != size:
+                        print("Skipping mismatch size", size_exr, size)
+                        continue
+
+                file_rendertimes.append((exr, sec, ip))
+    
+        if file_rendertimes:
+            for exr, sec, ip in file_rendertimes:
+                time_sec_average += sec 
+                
+                time_sec_max = max(time_sec_max, sec)
+                time_sec_min = min(time_sec_min, sec)
+            
+            time_sec_average /= len(file_rendertimes)
+            
+            file_rendertimes.insert(0, (dirname_full, time_sec_average, ""))
+            
+            # write a txt to the farm
+            file_txt = open(time_file, 'w')
+            for item in file_rendertimes:
+                file_txt.write(format_time(*item) + "\n")
+            
+            print(time_file)
+            
+            all_rendertimes.append(file_rendertimes)
+    
+    if time_sec_min == BIGNUM:
+        time_sec_min = 0.0
+
+    return time_sec_average, time_sec_min, time_sec_max
+
+
+def render_times(blendfile):
+    dirname = blendfile.split("/")[-1].split("\\")[-1].replace(".blend", "")
+    return update_render_times(dirname, [])
+    
+
+def main():
+    all_rendertimes = []
+    
+    size = 2048, 872
+    
+    DIR = "/shared/render/"
+    for dirname in sorted(os.listdir(DIR)):
+        update_render_times(dirname, all_rendertimes, size=size)
+    
+    summery = os.path.join(DIR, "render_times.txt")
+    print(summery)
+    summery_file = open(summery, 'w')
+    
+    # first wrote totals
+    summery_average_time = 0.0
+    summery_total_time = 0.0
+    summery_total_frames = 0
+    
+    for file_rendertimes in all_rendertimes:
+        for exr, sec, ip in file_rendertimes:
+            summery_total_time += sec
+            summery_total_frames += 1
+
+    summery_average_time = summery_total_time / summery_total_frames
+
+    summery_file.write("Summery: average time %s | total time %s | total frames %d\n" % (smpte_from_seconds(summery_average_time), smpte_from_seconds(summery_total_time), summery_total_frames))
+    
+    for file_rendertimes in all_rendertimes:
+        summery_file.write(format_time(*file_rendertimes[0]) + (" | frames %d\n" % (len(file_rendertimes)-1)))
+        
+
+if __name__ == "__main__":
+    import time
+    while True:
+        print("generating times...")
+        main()
+        time.sleep(3600)

Added: trunk/py/scripts/tools/bi_farm/master_ui.css
===================================================================
--- trunk/py/scripts/tools/bi_farm/master_ui.css	                        (rev 0)
+++ trunk/py/scripts/tools/bi_farm/master_ui.css	2012-06-06 07:16:10 UTC (rev 3458)
@@ -0,0 +1,247 @@
+body {
+	background-color:#000;
+	color: #cdc;
+	font-size:10px;
+	font-family: "Lucida Sans","Lucida Sans Unicode","Lucida Grande",Lucida,sans-serif;
+	cursor: default;
+}
+a {
+	text-decoration:none;
+	color:#cc7733;
+}
+a:hover {
+	color:#fff;
+	text-decoration:underline;
+}
+h1 {
+       font-size:100%;
+       float:right;
+       display: none;
+}
+
+h2 {
+    font-size:120%;
+    margin: 1px; 
+    color: #aaa;
+
+}
+
+h2 img {
+    display:block;
+/*    border: thin solid #777; */
+    margin-bottom:4px;
+}
+
+
+h3 {
+       clear:both;
+        font-size:150%;
+	letter-spacing: -1px;
+        margin: 2px 0 5px 0;
+	color: #7a7;
+}
+
+hr {
+       clear: both;
+       background-color: #333;
+       height:1px;
+       border:0;
+       width: 100%;
+       margin: 20px auto;
+}
+
+#container {
+	margin: 5px auto;
+	width: 1145px;
+}
+
+button {
+	color: #111;
+	width: auto;
+	height: auto;
+}
+
+.centered {
+       text-align: center;
+}
+
+.toggle {
+	text-decoration: underline;
+}
+
+.cache {
+	display: none;
+}
+
+.fluid {
+	display: none;
+}
+
+.rules {
+	width: 60em;
+	text-align: left;
+}
+
+img.thumb {
+	display: none;
+
+}
+
+span.thumb {
+	text-decoration: underline;
+
+}
+
+input {
+	background-color: #111;
+	color: #ccc;
+	border-radius: 6px;
+	-moz-border-radius: 6px;
+	border: thin solid #555;
+	padding: 5px;
+}
+
+input:hover, input:focus {
+       background-color: #000;
+}
+
+input:disabled {
+	color: #222;
+}
+
+#clearall {
+       clear:both;
+}
+
+table {
+    border-color: #000;
+    border-spacing: 0px;
+    border-collapse:collapse;
+    border-radius: 6px;
+    -moz-border-radius: 6px;
+    font-size: 120%;
+}
+
+#table-jobs {
+    background-color: #111;
+    width: 100%;
+    color: #aaa;
+}
+
+#table-jobs td {
+	border-bottom: thin solid #222;
+    word-wrap: break-word;
+    padding: 0px 0px 0px 5px;
+}
+
+#td-toggle {
+       width: 12px !important;
+       background-color: #000 ;
+       text-align: center;
+       padding: 1px 10px 1px 0px;
+}
+
+#td-toggle:hover {
+       background-color: #800;
+}
+
+thead{
+       font-size:80%;
+	color: #aca;
+	padding: 0px;
+    background-color: #111 !important;
+}
+
+tr {
+	letter-spacing: -1px;
+	background-color: #101313; 
+}
+
+tr:hover {
+       background-color: #222 !important;
+       color: #fff;
+}
+
+.job-dir {color: #666}
+.job-file {font-weight: solid}
+
+.job-add{
+    width:140px;
+    font-weight: bold;
+    border: 2px solid #500;
+    background: #800;
+    cursor: pointer;
+    padding:2px;
+}
+
+.job-add:hover{
+    border: 2px solid #800;
+    background: #b11;
+       color: #fff;
+}
+
+#status-disabled {
+	text-align:center;
+	background-color: #770000 !important;
+	color: #fff !important;
+    padding:0px;
+}
+#status-disabled:hover {
+	background-color: #990000 !important;
+}
+
+#status-inprogress {
+	text-align:center;
+	background-color: #bb6622 !important;
+	color: #fff;
+	border: thin solid #000;
+}
+
+#status-inprogress:hover {
+	background-color: #cc7733 !important;
+}
+
+#status-done {
+	text-align:center;
+	background-color: #88bb00 !important;
+	color: #fff;
+	font-weight: bold;
+}
+

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list