diff --git a/vendor/deadline/custom/events/OpenPype/OpenPype.param b/vendor/deadline/custom/events/OpenPype/OpenPype.param deleted file mode 100644 index 871ce474676..00000000000 --- a/vendor/deadline/custom/events/OpenPype/OpenPype.param +++ /dev/null @@ -1,37 +0,0 @@ -[State] -Type=Enum -Items=Global Enabled;Opt-In;Disabled -Category=Options -CategoryOrder=0 -CategoryIndex=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. - -[PythonSearchPaths] -Type=MultiLineMultiFolder -Label=Additional Python Search Paths -Category=Options -CategoryOrder=0 -CategoryIndex=1 -Default= -Description=The list of paths to append to the PYTHONPATH environment variable. This allows the Python job to find custom modules in non-standard locations. - -[LoggingLevel] -Type=Enum -Label=Logging Level -Category=Options -CategoryOrder=0 -CategoryIndex=2 -Items=DEBUG;INFO;WARNING;ERROR -Default=DEBUG -Description=Logging level where printing will start. - -[OpenPypeExecutable] -Type=multilinemultifilename -Label=Path to OpenPype executable -Category=Job Plugins -CategoryOrder=1 -CategoryIndex=1 -Default= -Description= \ No newline at end of file diff --git a/vendor/deadline/custom/events/OpenPype/OpenPype.py b/vendor/deadline/custom/events/OpenPype/OpenPype.py deleted file mode 100644 index e5e2cf52a82..00000000000 --- a/vendor/deadline/custom/events/OpenPype/OpenPype.py +++ /dev/null @@ -1,191 +0,0 @@ -import Deadline.Events -import Deadline.Scripting - - -def GetDeadlineEventListener(): - return OpenPypeEventListener() - - -def CleanupDeadlineEventListener(eventListener): - eventListener.Cleanup() - - -class OpenPypeEventListener(Deadline.Events.DeadlineEventListener): - """ - Called on every Deadline plugin event, used for injecting OpenPype - environment variables into rendering process. - - Expects that job already contains env vars: - AVALON_PROJECT - AVALON_ASSET - AVALON_TASK - AVALON_APP_NAME - Without these only global environment would be pulled from OpenPype - - Configure 'Path to OpenPype executable dir' in Deadlines - 'Tools > Configure Events > openpype ' - Only directory path is needed. - - """ - def __init__(self): - self.OnJobSubmittedCallback += self.OnJobSubmitted - self.OnJobStartedCallback += self.OnJobStarted - self.OnJobFinishedCallback += self.OnJobFinished - self.OnJobRequeuedCallback += self.OnJobRequeued - self.OnJobFailedCallback += self.OnJobFailed - self.OnJobSuspendedCallback += self.OnJobSuspended - self.OnJobResumedCallback += self.OnJobResumed - self.OnJobPendedCallback += self.OnJobPended - self.OnJobReleasedCallback += self.OnJobReleased - self.OnJobDeletedCallback += self.OnJobDeleted - self.OnJobErrorCallback += self.OnJobError - self.OnJobPurgedCallback += self.OnJobPurged - - self.OnHouseCleaningCallback += self.OnHouseCleaning - self.OnRepositoryRepairCallback += self.OnRepositoryRepair - - self.OnSlaveStartedCallback += self.OnSlaveStarted - self.OnSlaveStoppedCallback += self.OnSlaveStopped - self.OnSlaveIdleCallback += self.OnSlaveIdle - self.OnSlaveRenderingCallback += self.OnSlaveRendering - self.OnSlaveStartingJobCallback += self.OnSlaveStartingJob - self.OnSlaveStalledCallback += self.OnSlaveStalled - - self.OnIdleShutdownCallback += self.OnIdleShutdown - self.OnMachineStartupCallback += self.OnMachineStartup - self.OnThermalShutdownCallback += self.OnThermalShutdown - self.OnMachineRestartCallback += self.OnMachineRestart - - def Cleanup(self): - del self.OnJobSubmittedCallback - del self.OnJobStartedCallback - del self.OnJobFinishedCallback - del self.OnJobRequeuedCallback - del self.OnJobFailedCallback - del self.OnJobSuspendedCallback - del self.OnJobResumedCallback - del self.OnJobPendedCallback - del self.OnJobReleasedCallback - del self.OnJobDeletedCallback - del self.OnJobErrorCallback - del self.OnJobPurgedCallback - - del self.OnHouseCleaningCallback - del self.OnRepositoryRepairCallback - - del self.OnSlaveStartedCallback - del self.OnSlaveStoppedCallback - del self.OnSlaveIdleCallback - del self.OnSlaveRenderingCallback - del self.OnSlaveStartingJobCallback - del self.OnSlaveStalledCallback - - del self.OnIdleShutdownCallback - del self.OnMachineStartupCallback - del self.OnThermalShutdownCallback - del self.OnMachineRestartCallback - - def set_openpype_executable_path(self, job): - """ - Sets configurable OpenPypeExecutable value to job extra infos. - - GlobalJobPreLoad takes this value, pulls env vars for each task - from specific worker itself. GlobalJobPreLoad is not easily - configured, so we are configuring Event itself. - """ - openpype_execs = self.GetConfigEntryWithDefault("OpenPypeExecutable", - "") - job.SetJobExtraInfoKeyValue("openpype_executables", openpype_execs) - - Deadline.Scripting.RepositoryUtils.SaveJob(job) - - def updateFtrackStatus(self, job, statusName, createIfMissing=False): - """Updates version status on ftrack""" - pass - - def OnJobSubmitted(self, job): - # self.LogInfo("OnJobSubmitted LOGGING") - # for 1st time submit - self.set_openpype_executable_path(job) - self.updateFtrackStatus(job, "Render Queued") - - def OnJobStarted(self, job): - # self.LogInfo("OnJobStarted") - self.set_openpype_executable_path(job) - self.updateFtrackStatus(job, "Rendering") - - def OnJobFinished(self, job): - # self.LogInfo("OnJobFinished") - self.updateFtrackStatus(job, "Artist Review") - - def OnJobRequeued(self, job): - # self.LogInfo("OnJobRequeued LOGGING") - self.set_openpype_executable_path(job) - - def OnJobFailed(self, job): - pass - - def OnJobSuspended(self, job): - # self.LogInfo("OnJobSuspended LOGGING") - self.updateFtrackStatus(job, "Render Queued") - - def OnJobResumed(self, job): - # self.LogInfo("OnJobResumed LOGGING") - self.set_openpype_executable_path(job) - self.updateFtrackStatus(job, "Rendering") - - def OnJobPended(self, job): - # self.LogInfo("OnJobPended LOGGING") - pass - - def OnJobReleased(self, job): - pass - - def OnJobDeleted(self, job): - pass - - def OnJobError(self, job, task, report): - # self.LogInfo("OnJobError LOGGING") - pass - - def OnJobPurged(self, job): - pass - - def OnHouseCleaning(self): - pass - - def OnRepositoryRepair(self, job, *args): - pass - - def OnSlaveStarted(self, job): - # self.LogInfo("OnSlaveStarted LOGGING") - pass - - def OnSlaveStopped(self, job): - pass - - def OnSlaveIdle(self, job): - pass - - def OnSlaveRendering(self, host_name, job): - # self.LogInfo("OnSlaveRendering LOGGING") - pass - - def OnSlaveStartingJob(self, host_name, job): - # self.LogInfo("OnSlaveStartingJob LOGGING") - self.set_openpype_executable_path(job) - - def OnSlaveStalled(self, job): - pass - - def OnIdleShutdown(self, job): - pass - - def OnMachineStartup(self, job): - pass - - def OnThermalShutdown(self, job): - pass - - def OnMachineRestart(self, job): - pass diff --git a/vendor/deadline/custom/plugins/GlobalJobPreLoad.py b/vendor/deadline/custom/plugins/GlobalJobPreLoad.py index ba1e5f6c6a5..ee137a2ee32 100644 --- a/vendor/deadline/custom/plugins/GlobalJobPreLoad.py +++ b/vendor/deadline/custom/plugins/GlobalJobPreLoad.py @@ -8,18 +8,23 @@ from Deadline.Scripting import RepositoryUtils, FileUtils +def get_openpype_executable(): + """Return OpenPype Executable from Event Plug-in Settings""" + config = RepositoryUtils.GetPluginConfig("OpenPype") + return config.GetConfigEntryWithDefault("OpenPypeExecutable", "") + + def inject_openpype_environment(deadlinePlugin): """ Pull env vars from OpenPype and push them to rendering process. Used for correct paths, configuration from OpenPype etc. """ job = deadlinePlugin.GetJob() - job = RepositoryUtils.GetJob(job.JobId, True) # invalidates cache print(">>> Injecting OpenPype environments ...") try: print(">>> Getting OpenPype executable ...") - exe_list = job.GetJobExtraInfoKeyValue("openpype_executables") + exe_list = get_openpype_executable() openpype_app = FileUtils.SearchFileList(exe_list) if openpype_app == "": raise RuntimeError( @@ -96,7 +101,6 @@ def inject_render_job_id(deadlinePlugin): """Inject dependency ids to publish process as env var for validation.""" print(">>> Injecting render job id ...") job = deadlinePlugin.GetJob() - job = RepositoryUtils.GetJob(job.JobId, True) # invalidates cache dependency_ids = job.JobDependencyIDs print(">>> Dependency IDs: {}".format(dependency_ids)) @@ -183,7 +187,6 @@ def __main__(deadlinePlugin): print("*** GlobalJobPreload start ...") print(">>> Getting job ...") job = deadlinePlugin.GetJob() - job = RepositoryUtils.GetJob(job.JobId, True) # invalidates cache openpype_render_job = \ job.GetJobEnvironmentKeyValue('OPENPYPE_RENDER_JOB') or '0' diff --git a/vendor/deadline/readme.md b/vendor/deadline/readme.md index 803a290050e..31ffffd0b78 100644 --- a/vendor/deadline/readme.md +++ b/vendor/deadline/readme.md @@ -1,32 +1,29 @@ ## OpenPype Deadline repository overlay - This directory is overlay for Deadline repository. - It means that you can copy whole hierarchy to Deadline repository and it should work. + This directory is an overlay for Deadline repository. + It means that you can copy the whole hierarchy to Deadline repository and it + should work. Logic: ----- - Event - ----- - For each rendering job OpenPype event is triggered, it stores path to OpenPype - executable (needs to be configured on `Deadline's Configure Events > OpenPype`) - job's extra key 'openpype_executables'. - - This value is used by `GlobalJobPreLoad` to call that executable to pull - environment's variables which are needed to add to ALL plugins process environments. - These env. vars are injected into rendering process. - - Event is necessary here as a middle man to allow configuring location of executable - which is ONLY then used by `GlobalJobPreLoad` (which doesnt have any user facing - configuration at all). + GlobalJobPreLoad + ----- - `GlobalJobPreLoad` is triggered before each job, it contains backward compatible - logic to not modify old Pype2 or not OpenPype triggered jobs. +The `GlobalJobPreLoad` will retrieve the OpenPype executable path from the +`OpenPype` Deadline Plug-in's settings. Then it will call the executable to +retrieve the environment variables needed for the Deadline Job. +These environment variables are injected into rendering process. + +Deadline triggers the `GlobalJobPreLoad.py` for each Worker as it starts the +Job. + +*Note*: It also contains backward compatible logic to preserve functionality +for old Pype2 and non-OpenPype triggered jobs. Plugin ------ - For each publishing job `OpenPypeDeadlinePlugin` is called, which calls - configured location of OpenPype executable (needs to be configured in - `Deadline's Configure Plugins > OpenPype`) - and triggers command. + For each render and publishing job the `OpenPype` Deadline Plug-in is checked + for the configured location of the OpenPype executable (needs to be configured + in `Deadline's Configure Plugins > OpenPype`) through `GlobalJobPreLoad`. diff --git a/website/docs/assets/deadline_configure_event.png b/website/docs/assets/deadline_configure_event.png deleted file mode 100644 index 537a18506c9..00000000000 Binary files a/website/docs/assets/deadline_configure_event.png and /dev/null differ diff --git a/website/docs/module_deadline.md b/website/docs/module_deadline.md index bb6b8cff89b..32dbcfa6df3 100644 --- a/website/docs/module_deadline.md +++ b/website/docs/module_deadline.md @@ -12,45 +12,39 @@ import TabItem from '@theme/TabItem'; For [AWS Thinkbox Deadline](https://www.awsthinkbox.com/deadline) support you need to set a few things up in both OpenPype and Deadline itself -1. Deploy OpenPype executable to all nodes of Deadline farm. See [Install & Run](admin_use) +1. Deploy OpenPype executable to all nodes of Deadline farm. See [Install & Run](admin_use). -2. Enable Deadline module it in the [settings](admin_settings_system.md#deadline) +2. Enable Deadline Module in the [OpenPype Admin Settings](admin_settings_system.md#deadline). 3. Set up *Deadline Web API service*. For more details on how to do it, see [here](https://docs.thinkboxsoftware.com/products/deadline/10.0/1_User%20Manual/manual/web-service.html). -4. Point OpenPype to your deadline webservice URL in the [settings](admin_settings_system.md#deadline) +4. Point OpenPype to your deadline webservice URL in the [OpenPype Admin Settings](admin_settings_system.md#deadline). -5. Install our custom plugin, event plugin and scripts to your deadline repository. It should be as simple as copying content of `openPype/vendor/deadline/custom` to `path/to/your/deadline/repository/custom` +5. Install our custom plugin and scripts to your deadline repository. It should be as simple as copying content of `openPype/vendor/deadline/custom` to `path/to/your/deadline/repository/custom`. ## Configuration -OpenPype integration with Deadline consists of two parts, event listener which gets triggered for each job and - handles populating rendering jobs with proper environment variables and -OpenPype plugin which handles publishing itself. +OpenPype integration for Deadline consists of two parts: -Both need to be configured by pointing DL to OpenPype executables. These executables need to be installed to +- The `OpenPype` Deadline Plug-in +- A `GlobalJobPreLoad` Deadline Script (this gets triggered for each deadline job) + +The `GlobalJobPreLoad` handles populating render and publish jobs with proper environment variables using settings from the `OpenPype` Deadline Plug-in. + +The `OpenPype` Deadline Plug-in must be configured to point to a valid OpenPype executable location. The executable need to be installed to destinations accessible by DL process. Check permissions (must be executable and accessible by Deadline process) - Enable `Tools > Super User Mode` in Deadline Monitor -- Go to `Tools > Configure plugins`, find `OpenPype` in the list on the left side, find location of OpenPype +- Go to `Tools > Configure Plugins...`, find `OpenPype` in the list on the left side, find location of OpenPype executable. It is recommended to use the `openpype_console` executable as it provides a bit more logging. -- In case of multi OS farms, provide multiple locations, each node goes through a list and tries to find accessible - locations for itself. +- In case of multi OS farms, provide multiple locations, each Deadline Worker goes through the list and tries to find the first accessible + location for itself. ![Configure plugin](assets/deadline_configure_plugin.png) -- Go to `Tools > Configure events`, find `OpenPype` in the list on the left side, find location of OpenPype -executable. It is recommended to use the `openpype_console` executable as it provides a bit more logging. - -- State is expected to be set to `Global Enabled` - -![Configure event](assets/deadline_configure_event.png) - -Path to executables needs to be configured on both, plugin and event level! - ## Troubleshooting #### Publishing jobs fail directly in DCCs @@ -67,7 +61,7 @@ Each publishing from OpenPype consists of 2 jobs, first one is rendering, second - Jobs are failing with `OpenPype executable was not found` error - Check if OpenPype is installed on a node handling this job, plugin and events are properly [configured](#configuration) + Check if OpenPype is installed on the Worker handling this job and ensure `OpenPype` Deadline Plug-in is properly [configured](#configuration) - Publishing job is failing with `ffmpeg not installed` error