AWS Thinkbox Discussion Forums

custom event to set custom plugin path for Nuke jobs

Hi all,

Running Deadline 10 and first time trying to make a custom event so that when a Nuke job is started, Deadline can specify a custom plugin path for the jobs. I mimic what is available in the existing NukeCleanup even to make SetNukePluginPath.py and SetNukePluginPath.param, and store them in \…\DeadlineRepo10\custom\events\SetNukePluginPath.

SetNukePluginPath.py

###############################################################
#  Give Deadline an instance of this class so it can use it.
###############################################################
def GetDeadlineEventListener():
    return SetNukePluginPathListener()

def CleanupDeadlineEventListener(eventListener):
    eventListener.Cleanup()


###############################################################
#  The SetNukePluginPath event listener class.
###############################################################
class SetNukePluginPathListener (DeadlineEventListener):
    def __init__(self):
        self.OnJobSubmittedCallback += self.OnJobSubmitted
        self.OnJobStartedCallback += self.OnJobStarted
        
    def OnJobStarted(self, job):
        eventType = self.GetConfigEntryWithDefault( "SetNukePluginPath", "On Job Started" )
        if 'Nuke' in job.PluginName and ( eventType == "On Job Started" ):
            self.CustomPluginDirectory='//network/library/scripts/nuke'           
        pass
        
    def OnJobSubmitted(self, job):
        eventType = self.GetConfigEntryWithDefault( "SetNukePluginPath", "On Job Started" )
        if 'Nuke' in job.PluginName and ( eventType == "On Job Started" ):
            self.CustomPluginDirectory='//network/library/scripts/nuke'
        pass

SetNukePluginPath.param

[State]
Type=Enum
Items=Global Enabled;Opt-In;Disabled
Category=Options
CategoryOrder=0
Index=0
Label=State
Default=Global Enabled
Description=How this event plug-in should respond to events. If Global, all jobs and slaves will trigger the events for this plugin. If Opt-In, jobs and slaves can choose to trigger the events for this plugin. If Disabled, no events are triggered for this plugin.

[SetNukePluginPath]
Type=Enum
Items=On Job Started;On Job Finished;On Job Started and On Job Finished
Category=Options
#CategoryOrder=0
Index=1
Label=set Nuke custom plugin path directory
Default=On Job Started
Description=Mostly just to show an example property

With that, I am able to see options populated in the Configure Event Plugins page in Deadline Monitor.
[attachment=0]deadline_custom_event.jpg[/attachment]
However, Nuke jobs failed to render due to missing plugins. What have I missed?

I appreciate any help or pointers. Thanks!

DeadlineEventListener won’t have a CustomPluginDirectory property. So you’ll want to change that “self” to “job”.

Also, you’re not saving the job when you’re done with editing it, so make sure to do a “RepositoryUtils.SaveJob(job)” in there.

If you have more problems, send along a job report. I’ll be pretty helpful. Just right-click the job that’s erroring, view the job reports, and right-click the picker to save.

Thanks for taking a look. I modified the code based on your suggestion and got a bit closer. But still got stuck at not correctly specifying the custom plugin path or something. My workstation is on Windows 10 and farm nodes are on Windows 7.

###############################################################
#  Imports
###############################################################
import os

from System.Diagnostics import *
from System.IO import *

from Deadline.Events import *
from Deadline.Scripting import *


###############################################################
#  Give Deadline an instance of this class so it can use it.
###############################################################
def GetDeadlineEventListener():
    return SetNukePluginPathListener()

def CleanupDeadlineEventListener(eventListener):
    eventListener.Cleanup()


###############################################################
#  The SetNukePluginPath event listener class.
###############################################################
class SetNukePluginPathListener (DeadlineEventListener):
    def __init__(self):
        self.OnJobSubmittedCallback += self.OnJobSubmitted
        self.OnJobStartedCallback += self.OnJobStarted
        
    def OnJobStarted(self, job):
        eventType = self.GetConfigEntryWithDefault( "SetNukePluginPath", "On Job Started" )
        if 'Nuke' in job.PluginName and ( eventType == "On Job Started" ):
            myDir = r"//network/library/scripts/nuke"
            job.JobCustomPluginDirectory(myDir)
        
        RepositoryUtils.SaveJob(job)      
        pass
        
    def OnJobSubmitted(self, job):
        eventType = self.GetConfigEntryWithDefault( "SetNukePluginPath", "On Job Started" )
        if 'Nuke' in job.PluginName and ( eventType == "On Job Started" ):
            myDir = r"//network/library/scripts/nuke"
            job.JobCustomPluginDirectory(myDir)
        
        RepositoryUtils.SaveJob(job)
        pass

I’ve attached the job report. It seems that I didn’t specify plugin path correctly while Python keeps throwing unicode is not callable errors. I’ve tried several ways to specify the path in different ways shown above or:
job.JobCustomPluginDirectory("//network/library/scripts/nuke")
job.JobCustomPluginDirectory =="//network/library/scripts/nuke"
None of those works.

Definitely getting much closer. Any time you see “unicode is not callable” that means you’re trying to run string (unicode) as a function (callable). It’s text, not program code, so Python gets a bit grumpy.

In this case, it’s this line:

            job.JobCustomPluginDirectory(myDir)

You’ll probably want to use an equals sign instead of brackets there:

            job.JobCustomPluginDirectory = myDir

If this adventure’s been more fun that frustrating so far, this site is pretty fantastic (personal endorsement here, not from the company):
codecademy.com/learn/learn-python

Thanks Edwin. Cheers for the codeacademy link. I went through the non-pro stuff a while ago. My memory gets washed out when not doing it full-time. :slight_smile:

I made the change and not getting unicode error anymore. However, farm node is still unable to load the custom plugin and Nuke has exited/terminated.

part of the job report: (full report attached)

2018-07-20 10:59:40:  0: STDOUT: VRayDenoiser: Unknown command
2018-07-20 10:59:40:  0: STDOUT: PMask: Unknown command
2018-07-20 10:59:40:  0: STDOUT: Cryptomatte: Unknown command
2018-07-20 10:59:40:  0: WARNING: Monitored managed process Nuke is no longer running
2018-07-20 10:59:40:  0: Done executing plugin command of type 'Render Task'

I attached a screenshot of the Job Reports window where I see that the custom event is logged? (without a slave name?) In the log, the custom plugin path seems correctly specified for “OnJobStarted” and “OnJobSubmitted”.

Latest modified SetNukePluginPath.py below. Is there a way to print some info to the Job Reports window to help me debug?

###############################################################
#  Imports
###############################################################
import os

from System.Diagnostics import *
from System.IO import *

from Deadline.Events import *
from Deadline.Scripting import *


###############################################################
#  Give Deadline an instance of this class so it can use it.
###############################################################
def GetDeadlineEventListener():
    return SetNukePluginPathListener()

def CleanupDeadlineEventListener(eventListener):
    eventListener.Cleanup()


###############################################################
#  The SetNukePluginPath event listener class.
###############################################################
class SetNukePluginPathListener (DeadlineEventListener):
    def __init__(self):
        self.OnJobSubmittedCallback += self.OnJobSubmitted
        self.OnJobStartedCallback += self.OnJobStarted
        
    def OnJobStarted(self, job):
        eventType = self.GetConfigEntryWithDefault( "SetNukePluginPath", "On Job Started" )
        if 'Nuke' in job.PluginName and ( eventType == "On Job Started" ):
            myDir = r"//lax04rend/Nikola/library/scripts/nuke"
            print (myDir)
            job.JobCustomPluginDirectory=myDir
        
        RepositoryUtils.SaveJob(job)      
        pass
        
    def OnJobSubmitted(self, job):
        eventType = self.GetConfigEntryWithDefault( "SetNukePluginPath", "On Job Started" )
        if 'Nuke' in job.PluginName and ( eventType == "On Job Started" ):
            myDir = r"//lax04rend/Nikola/library/scripts/nuke"
            print (myDir)
            job.JobCustomPluginDirectory=myDir
        
        RepositoryUtils.SaveJob(job)
        pass
        

Yeah, it does look like things aren’t acting correctly here… I didn’t think hard enough on this before, but OnJobStarted is too late to be changing the Nuke render plugin’s path as far as I know, but it should be taking effect since it’s also being done at submission time. The big callout is that this path isn’t right in the log:

2018-07-20 10:59:36:  0: Synchronizing Plugin Nuke from \\lax04rend\Nikola\DeadlineRepo10\plugins\Nuke took: 0 seconds

As far as more debug info, any LogInfo, LogWarning, LogError or print lines should end up in the script when it’s run. In this case, it looks like Nuke is either crashing or some internal script is closing it down before Deadline wants it to which is the source of that error. If there are scripts inside Nuke closing things, any print calls should get bubbled up through standard output as far as I know.

So why is Deadline making it to sync Nuke plugin from \lax04rend\Nikola\DeadlineRepo10\plugins\Nuke instead of the path I specified?
I even tried copying all custom plugin/gizmos/scripts over to \lax04rend\Nikola\DeadlineRepo10\plugins\Nuke. It still errors out.

I can work around the issue by setting the NUKE_PATH environment variable and pointing it to the custom plugin directory for every single farm node, but I am hoping to solve it through Deadline custom event.

Is there a way, in the Job Reports, to confirm that I have correctly ask Deadline to set the custom plugin path for Nuke jobs submitted? The information I got from the Job Reports is there is a “Log report” of SutNukePluginPath: \lax04rend\Nikola\library\scripts\nuke for Event Type: OnJobSubmitted, whereas in all the “Error report”, Deadline is Synchronizing Plugin Nuke from \lax04rend\Nikola\DeadlineRepo10\plugins\Nuke and Nuke has been terminated.

The best way to see if you’ve set it is to check the UI in the “Modify Job Settings”:

[attachment=0]2018-07-24 14_06_33-Job Properties.png[/attachment]

I’ll spend a few minutes here trying to reproduce…

Update: So, you’ll need to make sure your custom Deadline plugin lives at “//network/library/scripts/nuke/Nuke”. I think there may be some misunderstanding here as well. The “CustomPluginDirectory” property allows you to have Deadline’s Nuke plugin live in a different folder than “[repo]/plugins/Nuke” or “[repo]/custom/plugins/Nuke” and does not in fact have anything to do with Nuke itself.

Thanks for all your help Edwin.

I added

job.SetJobEnvironmentKeyValue("NUKE_PATH", myDir) for OnJobSubmitted, and that took care of the business by adding the NUKE_PATH env variable for submitted jobs.

I should’ve have thought about that much ealier. :slight_smile:

Nice! Glad you got it working. We also now have some pretty good troubleshooting info for someone with a very custom Deadline plugin too, so win-win!

Privacy | Site terms | Cookie preferences