Deadline本身機制是通過各DCC軟件自身的后臺命令去執(zhí)行渲染或者解算。如果要從外部提交任務(wù)到Deadline需要通過Deadline提供的Web Sevice進行數(shù)據(jù)交互。但是官方只提供了Python2版本的API并沒有提供Python3版的。為了能在Houdini18.5 python3版里直接提交任務(wù)到Deadline,這里對其接口API稍微改了一下。(當然,如果熟悉Deadline的job數(shù)據(jù),直接使用 GET,POST,DELETE,PUT這四種方式與Web Service進行數(shù)據(jù)交互也是可以的,這樣不僅能無視python版本還能支持其他語言)
啟動WebService
任意一臺安裝Deadline Client的機器上,在安裝目錄里可以找到deadlinewebservice.exe。以管理員身份運行后可以在該機器上開啟一個Deadline Web Service。該Serivce的作用其實就是一個中間數(shù)據(jù)轉(zhuǎn)發(fā)小服務(wù),它能接收從其他機器傳來的命令數(shù)據(jù),之后對Deadline倉庫與數(shù)據(jù)進行交互,最后將操作結(jié)果返回。為了統(tǒng)一管理,一般我們會將Deadline Web Serivce放在倉庫統(tǒng)一的服務(wù)器里。
然后其他機器上要連接到Web Service就需要連接它所在的IP與端口。
<meta name="source" content="lake">
幾處腳本修改
Repository中腳本修改
找到Deadline倉庫安裝目錄下的Houdini插件,比如:xxx/DeadlineRepository10/plugins/Houdini
1.Houdini.param添加Houdini18.5的配置
如果要使用HQueue,需要同樣配置[Houdini18_5_SimTracker]
[Houdini18_5_Hython_Executable]
Label=Houdini 18.5 Hython Executable
Category=Render Executables
CategoryOrder=0
Type=multilinemultifilename
Index=3
Default=C:\Program Files\Side Effects Software\Houdini 18.5.448\bin\Hython.exe;/Applications/Houdini/Houdini18.5.448/Frameworks/Houdini.framework/Versions/18.5.448/Resources/bin/hython;/opt/hfs18.5/bin/hython
Description=The path to the hython executable. It can be found in the Houdini bin folder.
Description=The path to the hython executable. It can be found in the Houdini bin folder.
2.Houdini.py的RenderExecutable()函數(shù)里.添加version版本執(zhí)行文件返回值。
我這里使用self.GetConfigEntry返回報錯,所以直接返回houdiniExeList,其實就是Exe的配置路徑
def RenderExecutable( self ):
version = self.GetPluginInfoEntryWithDefault( "Version", "16.0" ).replace( ".", "_" )
build = self.GetPluginInfoEntryWithDefault( "Build", "none" ).lower()
if version.startswith('18_5'):
houdiniExeList=r'C:\Program Files\Side Effects Software\Houdini 18.5.449\bin\Hython.exe;/Applications/Houdini/Houdini18.5.449/Frameworks/Houdini.framework/Versions/18.5.449/Resources/bin/hython;/opt/hfs18.5/bin/hython'
else:
houdiniExeList = self.GetConfigEntry( "Houdini" + version + "_Hython_Executable" )
...
Deadline API腳本更改
也就是Deadline提供的Standalone Web Service接口python包。在倉庫安裝目錄的api/python文件夾下的Deadline,比如: xxx/DeadlineRepository10/api/python/Deadline.最好把這個文件夾復(fù)制到你Houdini中心管理的地方統(tǒng)一載入。
1.找到DeadlineUtility.py將 basestring 替換為 str
def ArrayToCommaSeparatedString( iterable ):
# if isinstance( iterable, basestring ):
if isinstance( iterable, str ):
return iterable
if iterable is None:
return ""
return ",".join( str(x) for x in iterable )
2.找到DeadlineSend.py 注銷掉所以python2的url請求方式,改為python3的requests方式。
從這里可以看出,與Web Serive交互其實就是Http請求機制。其中send函數(shù)主要處理GET,DELETE請求,psend函數(shù)主要處理PUT,POST請求。
import socket
# import httplib
import json
# import urllib2
import traceback
import requests
def send(address, message, requestType, useAuth=False, username="", password=""):
"""
Used for sending requests that do not require message body, like GET and DELETE.
Params: address of the webservice (string).
message to the webservice (string).
request type for the message (string, GET or DELETE).
"""
try:
if not address.startswith("http://"):
address = "http://" + address
url = address + message
response =requests.request(requestType,url)
data = response.text
data = data.replace('\n', ' ')
# except urllib2.HTTPError as err:
except Exception as err:
data = traceback.format_exc()
if response == 401:
data = "Error: HTTP Status Code 401\. Authentication with the Web Service failed. Please ensure that the authentication credentials are set, are correct, and that authentication mode is enabled."
# else:
# data = err.read()
try:
data = json.loads(data)
except:
pass
return data
def pSend(address, message, requestType, body, useAuth=False, username="", password=""):
"""
Used for sending requests that require a message body, like PUT and POST.
Params: address of the webservice (string).
message to the webservice (string).
request type for the message (string, PUT or POST).
message body for the request (string, JSON object).
"""
response = ""
try:
if not address.startswith("http://"):
address = "http://"+address
url = address + message
except Exception as err:
data = traceback.format_exc()
if response == 401:
data = "Error: HTTP Status Code 401\. Authentication with the Web Service failed. Please ensure that the authentication credentials are set, are correct, and that authentication mode is enabled."
# else:
# data = err.read()
try:
data = json.loads(data)
except:
pass
return data
Houdini18.5 py3版提交案例
import os
import hou
import getpass
import DeadlineConnect as Connect
connectionObject = Connect.DeadlineCon('192.168.1.xx',8082)
file_path = hou.hipFile.name()
version =hou.applicationVersionString()
hip_name=os.path.sliptext(hou.hipFile.basename())[0]
user_name = getpass.getuser()
pool ='none'
pri=100
chunk=10
node=hou.node('obj/geo1/filecache1')
node_name=node.name()
f1=node.parm('f1').eval()
f2=node.parm('f2').eval()
#設(shè)置job屬性
props={}
props['Name']=hip_name+'_'+node_name
props['UserName']= user_name
props['Frames']='{}-{}'.format(f1,f2)
props['Plugin']='Houdini'
props['Pool']=pool
props['Pri']=pri
props['ChunkSize']=chunk
#插件屬性
plug = {"OutputDriver": node.path()+'/render',
"SceneFile": file_path ,
"Version": version
}
job = connectionObject.Jobs.SubmitJob(props, plug)
JOB數(shù)據(jù)內(nèi)容
job信息本身是一個大json. Deadline對Job數(shù)據(jù)的具體值進行對應(yīng)的操作。
job的keys有:
['Props', 'ComFra', 'IsSub', 'Purged', 'Mach', 'Date', 'DateStart', 'DateComp', 'Plug', 'OutDir', 'OutFile', 'TileFile', 'Main',
'MainStart', 'MainEnd', 'Tile', 'TileFrame', 'TileCount', 'TileX', 'TileY', 'Stat', 'Aux', 'Bad', 'CompletedChunks', 'QueuedChunks', 'SuspendedChunks', 'RenderingChunks', 'FailedChunks', 'PendingChunks', 'SnglTskPrg', 'Errs', 'DataSize', '_id', 'ExtraElements']
常用屬性說明:
Props : 屬性
Stat : 狀態(tài)
值為int,在使用api的時候可以傳入字符串,其中對于的int值如下
Unknown:0
Active:1
Suspended:2
Completed:3
Failed :4
Pending :6
_id : job id
其中最重要的是Props屬性,它的內(nèi)容有:
['Name', 'Batch', 'User', 'Region', 'Cmmt', 'Dept', 'Frames', 'Chunk', 'Tasks', 'Grp', 'Pool', 'SecPool', 'Pri', 'ReqAss', 'ScrDep', 'Conc', 'ConcLimt', 'AuxSync', 'Int', 'IntPer', 'RemTmT', 'Seq', 'Reload', 'NoEvnt', 'OnComp', 'Protect', 'PathMap', 'AutoTime', 'TimeScrpt', 'MinTime', 'MaxTime', 'Timeout', 'FrameTimeout', 'StartTime', 'InitializePluginTime', 'Dep', 'DepFrame', 'DepFrameStart', 'DepFrameEnd', 'DepComp', 'DepDel', 'DepFail', 'DepPer', 'NoBad', 'OverAutoClean', 'OverClean', 'OverCleanDays', 'OverCleanType', 'JobFailOvr', 'JobFailErr', 'TskFailOvr', 'TskFailErr', 'SndWarn', 'NotOvr', 'SndEmail', 'SndPopup', 'NotEmail', 'NotUser', 'NotNote', 'Limits', 'ListedSlaves', 'White', 'MachLmt', 'MachLmtProg', 'PrJobScrp', 'PoJobScrp', 'PrTskScrp', 'PoTskScrp', 'Schd', 'SchdDays', 'SchdDate', 'SchdStop', 'MonStart','MonStop', 'TueStart', 'TueStop', 'WedStart', 'WedStop', 'ThuStart', 'ThuStop', 'FriStart', 'FriStop', 'SatStart', 'SatStop', 'SunStart', 'SunStop', 'PlugInfo', 'Env', 'EnvOnly', 'PlugDir', 'EventDir', 'OptIns', 'EventOI', 'AWSPortalAssets', 'AWSPortalAssetFileWhitelist', 'Ex0','Ex1', 'Ex2', 'Ex3', 'Ex4', 'Ex5', 'Ex6', 'Ex7', 'Ex8', 'Ex9', 'ExDic', 'OvrTaskEINames', 'TaskEx0', 'TaskEx1', 'TaskEx2', 'TaskEx3', 'TaskEx4', 'TaskEx5', 'TaskEx6', 'TaskEx7', 'TaskEx8', 'TaskEx9']
常見屬性說明:
Name: 任務(wù)名稱
User: 電腦賬戶名稱 比如 Administrator,laozhang
Frames: 幀數(shù)范圍 結(jié)構(gòu)'1-2'
Chunk: 1 ,每臺機器載入一次工程的執(zhí)行長度。如果設(shè)置為1,那么每次載入工程后,渲染一幀然后關(guān)閉工程,下次繼續(xù)載入。機器少建議開大。
Tasks: 執(zhí)行的任務(wù)數(shù)量,就是點擊一個job后,右邊顯示任務(wù)數(shù)。
Grp: 機器組
Pool: 機器池
Pri: 優(yōu)先級
Dep: 依賴關(guān)系
[{u'ResumeOnPercentageValue': 0.0, u'OverrideFrameOffsets': False, u'EndOffset': 0, u'OverrideResumeOn': False,
u'ResumeOnFailed': False, u'JobID': u'5ff7c49d14a13a26f4b9f893', u'IgnoreFrameOffsets': False,
u'ResumeOnDeleted': False, u'StartOffset': 0, u'ResumeOnComplete': True, u'ResumeOnPercentageCompleted': False, u'Notes': u''}]
一些真正被Deadline輸入識別的屬性
Deadline有個不嚴謹?shù)牡胤骄褪?,從Deadline API返回的job數(shù)據(jù)屬性名其與傳入的屬性名稱不一致。
建議在User-Manual-> Manual Job Submission下可查看job傳入屬性名稱
這里說2個常用的。
Frames Per Tasks: 每任務(wù)長度
在返回的job屬性里是Chunk字段
而需要傳入的是ChunkSize
調(diào)用的API是Jobs.SetJobFrameRange(self, id, frameList, chunkSize):
body = json.dumps({"Command":"setjobframerange","JobID":id, "FrameList":frameList, "ChunkSize":chunkSize})
return self.connectionProperties.__put__("/api/jobs", body)
JobDependencies: 依賴job
所謂依賴關(guān)系,就是當A依賴B時,只有B渲染或解算完后才會執(zhí)行A。
在返回的job中屬性是Dep:[] 一個列表
而需要傳入的名稱是JobDependencies,值為父依賴的job id
props['JobDependencies']= dependent_job_id