Merge pull request #200 from ynput/feature/AY-745_Deadline-webservice-password

Deadline: webservice password
This commit is contained in:
Petr Kalis 2024-05-06 17:12:44 +02:00 committed by GitHub
commit 3e6e66492c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 345 additions and 133 deletions

View file

@ -24,7 +24,7 @@ class AERenderInstance(RenderInstance):
class CollectAERender(publish.AbstractCollectRender):
order = pyblish.api.CollectorOrder + 0.405
order = pyblish.api.CollectorOrder + 0.100
label = "Collect After Effects Render Layers"
hosts = ["aftereffects"]
@ -145,6 +145,7 @@ class CollectAERender(publish.AbstractCollectRender):
if "review" in instance.families:
# to skip ExtractReview locally
instance.families.remove("review")
instance.deadline = inst.data.get("deadline")
instances.append(instance)

View file

@ -115,6 +115,7 @@ class CollectFusionRender(
if "review" in instance.families:
# to skip ExtractReview locally
instance.families.remove("review")
instance.deadline = inst.data.get("deadline")
instances.append(instance)

View file

@ -177,7 +177,10 @@ class CollectFarmRender(publish.AbstractCollectRender):
outputFormat=info[1],
outputStartFrame=info[3],
leadingZeros=info[2],
ignoreFrameHandleCheck=True
ignoreFrameHandleCheck=True,
#todo: inst is not available, must be determined, fix when
#reworking to Publisher
# deadline=inst.data.get("deadline")
)
render_instance.context = context

View file

@ -1,6 +1,8 @@
from .deadline_module import DeadlineModule
from .version import __version__
__all__ = (
"DeadlineModule",
"__version__"
)

View file

@ -49,6 +49,10 @@ def requests_post(*args, **kwargs):
if 'verify' not in kwargs:
kwargs['verify'] = False if os.getenv("OPENPYPE_DONT_VERIFY_SSL",
True) else True # noqa
auth = kwargs.get("auth")
if auth:
kwargs["auth"] = tuple(auth) # explicit cast to tuple
# add 10sec timeout before bailing out
kwargs['timeout'] = 10
return requests.post(*args, **kwargs)
@ -70,6 +74,9 @@ def requests_get(*args, **kwargs):
if 'verify' not in kwargs:
kwargs['verify'] = False if os.getenv("OPENPYPE_DONT_VERIFY_SSL",
True) else True # noqa
auth = kwargs.get("auth")
if auth:
kwargs["auth"] = tuple(auth)
# add 10sec timeout before bailing out
kwargs['timeout'] = 10
return requests.get(*args, **kwargs)
@ -434,9 +441,7 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin,
"""Plugin entry point."""
self._instance = instance
context = instance.context
self._deadline_url = context.data.get("defaultDeadline")
self._deadline_url = instance.data.get(
"deadlineUrl", self._deadline_url)
self._deadline_url = instance.data["deadline"]["url"]
assert self._deadline_url, "Requires Deadline Webservice URL"
@ -460,7 +465,8 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin,
self.plugin_info = self.get_plugin_info()
self.aux_files = self.get_aux_files()
job_id = self.process_submission()
auth = instance.data["deadline"]["auth"]
job_id = self.process_submission(auth)
self.log.info("Submitted job to Deadline: {}.".format(job_id))
# TODO: Find a way that's more generic and not render type specific
@ -473,10 +479,10 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin,
job_info=render_job_info,
plugin_info=render_plugin_info
)
render_job_id = self.submit(payload)
render_job_id = self.submit(payload, auth)
self.log.info("Render job id: %s", render_job_id)
def process_submission(self):
def process_submission(self, auth=None):
"""Process data for submission.
This takes Deadline JobInfo, PluginInfo, AuxFile, creates payload
@ -487,7 +493,7 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin,
"""
payload = self.assemble_payload()
return self.submit(payload)
return self.submit(payload, auth)
@abstractmethod
def get_job_info(self):
@ -577,7 +583,7 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin,
"AuxFiles": aux_files or self.aux_files
}
def submit(self, payload):
def submit(self, payload, auth):
"""Submit payload to Deadline API end-point.
This takes payload in the form of JSON file and POST it to
@ -585,6 +591,7 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin,
Args:
payload (dict): dict to become json in deadline submission.
auth (tuple): (username, password)
Returns:
str: resulting Deadline job id.
@ -594,7 +601,8 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin,
"""
url = "{}/api/jobs".format(self._deadline_url)
response = requests_post(url, json=payload)
response = requests_post(url, json=payload,
auth=auth)
if not response.ok:
self.log.error("Submission failed!")
self.log.error(response.status_code)

View file

@ -19,23 +19,23 @@ class DeadlineModule(AYONAddon, IPluginPaths):
def initialize(self, studio_settings):
# This module is always enabled
deadline_urls = {}
deadline_servers_info = {}
enabled = self.name in studio_settings
if enabled:
deadline_settings = studio_settings[self.name]
deadline_urls = {
url_item["name"]: url_item["value"]
deadline_servers_info = {
url_item["name"]: url_item
for url_item in deadline_settings["deadline_urls"]
}
if enabled and not deadline_urls:
if enabled and not deadline_servers_info:
enabled = False
self.log.warning((
"Deadline Webservice URLs are not specified. Disabling addon."
))
self.enabled = enabled
self.deadline_urls = deadline_urls
self.deadline_servers_info = deadline_servers_info
def get_plugin_paths(self):
"""Deadline plugin paths."""
@ -45,13 +45,15 @@ class DeadlineModule(AYONAddon, IPluginPaths):
}
@staticmethod
def get_deadline_pools(webservice, log=None):
def get_deadline_pools(webservice, auth=None, log=None):
"""Get pools from Deadline.
Args:
webservice (str): Server url.
log (Logger)
auth (Optional[Tuple[str, str]]): Tuple containing username,
password
log (Optional[Logger]): Logger to log errors to, if provided.
Returns:
list: Pools.
List[str]: Pools.
Throws:
RuntimeError: If deadline webservice is unreachable.
@ -63,7 +65,10 @@ class DeadlineModule(AYONAddon, IPluginPaths):
argument = "{}/api/pools?NamesOnly=true".format(webservice)
try:
response = requests_get(argument)
kwargs = {}
if auth:
kwargs["auth"] = auth
response = requests_get(argument, **kwargs)
except requests.exceptions.ConnectionError as exc:
msg = 'Cannot connect to DL web service {}'.format(webservice)
log.error(msg)

View file

@ -13,17 +13,45 @@ class CollectDeadlineServerFromInstance(pyblish.api.InstancePlugin):
"""Collect Deadline Webservice URL from instance."""
# Run before collect_render.
order = pyblish.api.CollectorOrder + 0.005
order = pyblish.api.CollectorOrder + 0.225
label = "Deadline Webservice from the Instance"
families = ["rendering", "renderlayer"]
hosts = ["maya"]
targets = ["local"]
families = ["render",
"rendering",
"render.farm",
"renderFarm",
"renderlayer",
"maxrender",
"usdrender",
"redshift_rop",
"arnold_rop",
"mantra_rop",
"karma_rop",
"vray_rop",
"publish.hou",
"image"] # for Fusion
def process(self, instance):
instance.data["deadlineUrl"] = self._collect_deadline_url(instance)
instance.data["deadlineUrl"] = \
instance.data["deadlineUrl"].strip().rstrip("/")
if not instance.data.get("farm"):
self.log.debug("Should not be processed on farm, skipping.")
return
if not instance.data.get("deadline"):
instance.data["deadline"] = {}
# todo: separate logic should be removed, all hosts should have same
host_name = instance.context.data["hostName"]
if host_name == "maya":
deadline_url = self._collect_deadline_url(instance)
else:
deadline_url = (instance.data.get("deadlineUrl") or # backwards
instance.data.get("deadline", {}).get("url"))
if deadline_url:
instance.data["deadline"]["url"] = deadline_url.strip().rstrip("/")
else:
instance.data["deadline"]["url"] = instance.context.data["deadline"]["defaultUrl"] # noqa
self.log.debug(
"Using {} for submission.".format(instance.data["deadlineUrl"]))
"Using {} for submission".format(instance.data["deadline"]["url"]))
def _collect_deadline_url(self, render_instance):
# type: (pyblish.api.Instance) -> str
@ -49,13 +77,13 @@ class CollectDeadlineServerFromInstance(pyblish.api.InstancePlugin):
["project_settings"]
["deadline"]
)
default_server = render_instance.context.data["defaultDeadline"]
default_server_url = (render_instance.context.data["deadline"]
["defaultUrl"])
# QUESTION How and where is this is set? Should be removed?
instance_server = render_instance.data.get("deadlineServers")
if not instance_server:
self.log.debug("Using default server.")
return default_server
return default_server_url
# Get instance server as sting.
if isinstance(instance_server, int):
@ -66,7 +94,7 @@ class CollectDeadlineServerFromInstance(pyblish.api.InstancePlugin):
default_servers = {
url_item["name"]: url_item["value"]
for url_item in deadline_settings["deadline_urls"]
for url_item in deadline_settings["deadline_servers_info"]
}
project_servers = (
render_instance.context.data

View file

@ -18,10 +18,9 @@ class CollectDefaultDeadlineServer(pyblish.api.ContextPlugin):
"""
# Run before collect_deadline_server_instance.
order = pyblish.api.CollectorOrder + 0.0025
order = pyblish.api.CollectorOrder + 0.200
label = "Default Deadline Webservice"
pass_mongo_url = False
targets = ["local"]
def process(self, context):
try:
@ -33,15 +32,17 @@ class CollectDefaultDeadlineServer(pyblish.api.ContextPlugin):
deadline_settings = context.data["project_settings"]["deadline"]
deadline_server_name = deadline_settings["deadline_server"]
deadline_webservice = None
dl_server_info = None
if deadline_server_name:
deadline_webservice = deadline_module.deadline_urls.get(
dl_server_info = deadline_module.deadline_servers_info.get(
deadline_server_name)
default_deadline_webservice = deadline_module.deadline_urls["default"]
deadline_webservice = (
deadline_webservice
or default_deadline_webservice
)
if dl_server_info:
deadline_url = dl_server_info["value"]
else:
default_dl_server_info = deadline_module.deadline_servers_info[0]
deadline_url = default_dl_server_info["value"]
context.data["defaultDeadline"] = deadline_webservice.strip().rstrip("/") # noqa
context.data["deadline"] = {}
context.data["deadline"]["defaultUrl"] = (
deadline_url.strip().rstrip("/"))

View file

@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
"""Collect user credentials
Requires:
context -> project_settings
instance.data["deadline"]["url"]
Provides:
instance.data["deadline"] -> require_authentication (bool)
instance.data["deadline"] -> auth (tuple (str, str)) -
(username, password) or None
"""
import pyblish.api
from ayon_api import get_server_api_connection
from ayon_core.modules.deadline.deadline_module import DeadlineModule
from ayon_core.modules.deadline import __version__
class CollectDeadlineUserCredentials(pyblish.api.InstancePlugin):
"""Collects user name and password for artist if DL requires authentication
"""
order = pyblish.api.CollectorOrder + 0.250
label = "Collect Deadline User Credentials"
targets = ["local"]
hosts = ["aftereffects",
"blender",
"fusion",
"harmony",
"nuke",
"maya",
"max",
"houdini"]
families = ["render",
"rendering",
"render.farm",
"renderFarm",
"renderlayer",
"maxrender",
"usdrender",
"redshift_rop",
"arnold_rop",
"mantra_rop",
"karma_rop",
"vray_rop",
"publish.hou"]
def process(self, instance):
if not instance.data.get("farm"):
self.log.debug("Should not be processed on farm, skipping.")
return
collected_deadline_url = instance.data["deadline"]["url"]
if not collected_deadline_url:
raise ValueError("Instance doesn't have '[deadline][url]'.")
context_data = instance.context.data
deadline_settings = context_data["project_settings"]["deadline"]
deadline_server_name = None
# deadline url might be set directly from instance, need to find
# metadata for it
for deadline_info in deadline_settings["deadline_urls"]:
dl_settings_url = deadline_info["value"].strip().rstrip("/")
if dl_settings_url == collected_deadline_url:
deadline_server_name = deadline_info["name"]
break
if not deadline_server_name:
raise ValueError(f"Collected {collected_deadline_url} doesn't "
"match any site configured in Studio Settings")
instance.data["deadline"]["require_authentication"] = (
deadline_info["require_authentication"]
)
instance.data["deadline"]["auth"] = None
if not deadline_info["require_authentication"]:
return
# TODO import 'get_addon_site_settings' when available
# in public 'ayon_api'
local_settings = get_server_api_connection().get_addon_site_settings(
DeadlineModule.name, __version__)
local_settings = local_settings["local_settings"]
for server_info in local_settings:
if deadline_server_name == server_info["server_name"]:
instance.data["deadline"]["auth"] = (server_info["username"],
server_info["password"])

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<root>
<error id="main">
<title>Deadline Authentication</title>
<description>
## Deadline authentication is required
This project has set in Settings that Deadline requires authentication.
### How to repair?
Please go to Ayon Server > Site Settings and provide your Deadline username and password.
In some cases the password may be empty if Deadline is configured to allow that. Ask your administrator.
</description>
</error>
</root>

View file

@ -174,7 +174,8 @@ class BlenderSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
instance.data["toBeRenderedOn"] = "deadline"
payload = self.assemble_payload()
return self.submit(payload)
return self.submit(payload,
auth=instance.data["deadline"]["auth"])
def from_published_scene(self):
"""

View file

@ -2,9 +2,10 @@ import os
import re
import json
import getpass
import requests
import pyblish.api
from openpype_modules.deadline.abstract_submit_deadline import requests_post
class CelactionSubmitDeadline(pyblish.api.InstancePlugin):
"""Submit CelAction2D scene to Deadline
@ -30,11 +31,7 @@ class CelactionSubmitDeadline(pyblish.api.InstancePlugin):
context = instance.context
# get default deadline webservice url from deadline module
deadline_url = instance.context.data["defaultDeadline"]
# if custom one is set in instance, use that
if instance.data.get("deadlineUrl"):
deadline_url = instance.data.get("deadlineUrl")
deadline_url = instance.data["deadline"]["url"]
assert deadline_url, "Requires Deadline Webservice URL"
self.deadline_url = "{}/api/jobs".format(deadline_url)
@ -197,7 +194,8 @@ class CelactionSubmitDeadline(pyblish.api.InstancePlugin):
self.log.debug("__ expectedFiles: `{}`".format(
instance.data["expectedFiles"]))
response = requests.post(self.deadline_url, json=payload)
response = requests_post(self.deadline_url, json=payload,
auth=instance.data["deadline"]["require_authentication"])
if not response.ok:
self.log.error(

View file

@ -2,10 +2,9 @@ import os
import json
import getpass
import requests
import pyblish.api
from openpype_modules.deadline.abstract_submit_deadline import requests_post
from ayon_core.pipeline.publish import (
AYONPyblishPluginMixin
)
@ -82,11 +81,7 @@ class FusionSubmitDeadline(
from ayon_core.hosts.fusion.api.lib import get_frame_path
# get default deadline webservice url from deadline module
deadline_url = instance.context.data["defaultDeadline"]
# if custom one is set in instance, use that
if instance.data.get("deadlineUrl"):
deadline_url = instance.data.get("deadlineUrl")
deadline_url = instance.data["deadline"]["url"]
assert deadline_url, "Requires Deadline Webservice URL"
# Collect all saver instances in context that are to be rendered
@ -246,7 +241,8 @@ class FusionSubmitDeadline(
# E.g. http://192.168.0.1:8082/api/jobs
url = "{}/api/jobs".format(deadline_url)
response = requests.post(url, json=payload)
auth = instance.data["deadline"]["auth"]
response = requests_post(url, json=payload, auth=auth)
if not response.ok:
raise Exception(response.text)

View file

@ -187,11 +187,13 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
payload_data, project_settings)
job_infos, plugin_infos = payload
for job_info, plugin_info in zip(job_infos, plugin_infos):
self.submit(self.assemble_payload(job_info, plugin_info))
self.submit(self.assemble_payload(job_info, plugin_info),
instance.data["deadline"]["auth"])
else:
payload = self._use_published_name(payload_data, project_settings)
job_info, plugin_info = payload
self.submit(self.assemble_payload(job_info, plugin_info))
self.submit(self.assemble_payload(job_info, plugin_info),
instance.data["deadline"]["auth"])
def _use_published_name(self, data, project_settings):
# Not all hosts can import these modules.

View file

@ -292,7 +292,7 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
return plugin_payload
def process_submission(self):
def process_submission(self, auth=None):
from maya import cmds
instance = self._instance
@ -332,7 +332,8 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
if "vrayscene" in instance.data["families"]:
self.log.debug("Submitting V-Ray scene render..")
vray_export_payload = self._get_vray_export_payload(payload_data)
export_job = self.submit(vray_export_payload)
export_job = self.submit(vray_export_payload,
instance.data["deadline"]["auth"])
payload = self._get_vray_render_payload(payload_data)
@ -351,7 +352,8 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
else:
# Submit main render job
job_info, plugin_info = payload
self.submit(self.assemble_payload(job_info, plugin_info))
self.submit(self.assemble_payload(job_info, plugin_info),
instance.data["deadline"]["auth"])
def _tile_render(self, payload):
"""Submit as tile render per frame with dependent assembly jobs."""
@ -451,7 +453,8 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
# Submit frame tile jobs
frame_tile_job_id = {}
for frame, tile_job_payload in frame_payloads.items():
job_id = self.submit(tile_job_payload)
job_id = self.submit(tile_job_payload,
instance.data["deadline"]["auth"])
frame_tile_job_id[frame] = job_id
# Define assembly payloads
@ -559,7 +562,8 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
"submitting assembly job {} of {}".format(i + 1,
num_assemblies)
)
assembly_job_id = self.submit(payload)
assembly_job_id = self.submit(payload,
instance.data["deadline"]["auth"])
assembly_job_ids.append(assembly_job_id)
instance.data["assemblySubmissionJobs"] = assembly_job_ids

View file

@ -4,9 +4,9 @@ import json
import getpass
from datetime import datetime
import requests
import pyblish.api
from openpype_modules.deadline.abstract_submit_deadline import requests_post
from ayon_core.pipeline.publish import (
AYONPyblishPluginMixin
)
@ -100,11 +100,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin,
node = instance.data["transientData"]["node"]
context = instance.context
# get default deadline webservice url from deadline module
deadline_url = instance.context.data["defaultDeadline"]
# if custom one is set in instance, use that
if instance.data.get("deadlineUrl"):
deadline_url = instance.data.get("deadlineUrl")
deadline_url = instance.data["deadline"]["url"]
assert deadline_url, "Requires Deadline Webservice URL"
self.deadline_url = "{}/api/jobs".format(deadline_url)
@ -427,7 +423,9 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin,
self.log.debug("__ expectedFiles: `{}`".format(
instance.data["expectedFiles"]))
response = requests.post(self.deadline_url, json=payload, timeout=10)
auth = instance.data["deadline"]["auth"]
response = requests_post(self.deadline_url, json=payload, timeout=10,
auth=auth)
if not response.ok:
raise Exception(response.text)

View file

@ -5,10 +5,10 @@ import json
import re
from copy import deepcopy
import requests
import ayon_api
import pyblish.api
from openpype_modules.deadline.abstract_submit_deadline import requests_post
from ayon_core.pipeline import publish
from ayon_core.lib import EnumDef, is_in_tests
from ayon_core.pipeline.version_start import get_versioning_start
@ -209,7 +209,9 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin,
self.log.debug("Submitting Deadline publish job ...")
url = "{}/api/jobs".format(self.deadline_url)
response = requests.post(url, json=payload, timeout=10)
auth = instance.data["deadline"]["auth"]
response = requests_post(url, json=payload, timeout=10,
auth=auth)
if not response.ok:
raise Exception(response.text)
@ -341,11 +343,7 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin,
deadline_publish_job_id = None
if submission_type == "deadline":
# get default deadline webservice url from deadline module
self.deadline_url = instance.context.data["defaultDeadline"]
# if custom one is set in instance, use that
if instance.data.get("deadlineUrl"):
self.deadline_url = instance.data.get("deadlineUrl")
self.deadline_url = instance.data["deadline"]["url"]
assert self.deadline_url, "Requires Deadline Webservice URL"
deadline_publish_job_id = \
@ -353,7 +351,9 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin,
# Inject deadline url to instances.
for inst in instances:
inst["deadlineUrl"] = self.deadline_url
if "deadline" not in inst:
inst["deadline"] = {}
inst["deadline"] = instance.data["deadline"]
# publish job file
publish_job = {

View file

@ -5,11 +5,11 @@ import json
import re
from copy import deepcopy
import requests
import clique
import ayon_api
import pyblish.api
from openpype_modules.deadline.abstract_submit_deadline import requests_post
from ayon_core.pipeline import publish
from ayon_core.lib import EnumDef, is_in_tests
from ayon_core.pipeline.version_start import get_versioning_start
@ -303,7 +303,9 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin,
self.log.debug("Submitting Deadline publish job ...")
url = "{}/api/jobs".format(self.deadline_url)
response = requests.post(url, json=payload, timeout=10)
auth = instance.data["deadline"]["auth"]
response = requests_post(url, json=payload, timeout=10,
auth=auth)
if not response.ok:
raise Exception(response.text)
@ -457,18 +459,17 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin,
}
# get default deadline webservice url from deadline module
self.deadline_url = instance.context.data["defaultDeadline"]
# if custom one is set in instance, use that
if instance.data.get("deadlineUrl"):
self.deadline_url = instance.data.get("deadlineUrl")
self.deadline_url = instance.data["deadline"]["url"]
assert self.deadline_url, "Requires Deadline Webservice URL"
deadline_publish_job_id = \
self._submit_deadline_post_job(instance, render_job, instances)
# Inject deadline url to instances.
# Inject deadline url to instances to query DL for job id for overrides
for inst in instances:
inst["deadlineUrl"] = self.deadline_url
if not "deadline" in inst:
inst["deadline"] = {}
inst["deadline"] = instance.data["deadline"]
# publish job file
publish_job = {

View file

@ -1,5 +1,7 @@
import pyblish.api
from ayon_core.pipeline import PublishXmlValidationError
from openpype_modules.deadline.abstract_submit_deadline import requests_get
@ -8,27 +10,42 @@ class ValidateDeadlineConnection(pyblish.api.InstancePlugin):
label = "Validate Deadline Web Service"
order = pyblish.api.ValidatorOrder
hosts = ["maya", "nuke"]
families = ["renderlayer", "render"]
hosts = ["maya", "nuke", "aftereffects", "harmony", "fusion"]
families = ["renderlayer", "render", "render.farm"]
# cache
responses = {}
def process(self, instance):
# get default deadline webservice url from deadline module
deadline_url = instance.context.data["defaultDeadline"]
# if custom one is set in instance, use that
if instance.data.get("deadlineUrl"):
deadline_url = instance.data.get("deadlineUrl")
self.log.debug(
"We have deadline URL on instance {}".format(deadline_url)
)
if not instance.data.get("farm"):
self.log.debug("Should not be processed on farm, skipping.")
return
deadline_url = instance.data["deadline"]["url"]
assert deadline_url, "Requires Deadline Webservice URL"
kwargs = {}
if instance.data["deadline"]["require_authentication"]:
auth = instance.data["deadline"]["auth"]
kwargs["auth"] = auth
if not auth[0]:
raise PublishXmlValidationError(
self,
"Deadline requires authentication. "
"At least username is required to be set in "
"Site Settings.")
if deadline_url not in self.responses:
self.responses[deadline_url] = requests_get(deadline_url)
self.responses[deadline_url] = requests_get(deadline_url, **kwargs)
response = self.responses[deadline_url]
if response.status_code == 401:
raise PublishXmlValidationError(
self,
"Deadline requires authentication. "
"Provided credentials are not working. "
"Please change them in Site Settings")
assert response.ok, "Response must be ok"
assert response.text.startswith("Deadline Web Service "), (
"Web service did not respond with 'Deadline Web Service'"

View file

@ -37,8 +37,9 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin,
self.log.debug("Skipping local instance.")
return
deadline_url = self.get_deadline_url(instance)
pools = self.get_pools(deadline_url)
deadline_url = instance.data["deadline"]["url"]
pools = self.get_pools(deadline_url,
instance.data["deadline"].get("auth"))
invalid_pools = {}
primary_pool = instance.data.get("primaryPool")
@ -61,22 +62,18 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin,
formatting_data={"pools_str": ", ".join(pools)}
)
def get_deadline_url(self, instance):
# get default deadline webservice url from deadline module
deadline_url = instance.context.data["defaultDeadline"]
if instance.data.get("deadlineUrl"):
# if custom one is set in instance, use that
deadline_url = instance.data.get("deadlineUrl")
return deadline_url
def get_pools(self, deadline_url):
def get_pools(self, deadline_url, auth):
if deadline_url not in self.pools_per_url:
self.log.debug(
"Querying available pools for Deadline url: {}".format(
deadline_url)
)
pools = DeadlineModule.get_deadline_pools(deadline_url,
auth=auth,
log=self.log)
# some DL return "none" as a pool name
if not "none" in pools:
pools.append("none")
self.log.info("Available pools: {}".format(pools))
self.pools_per_url[deadline_url] = pools

View file

@ -199,16 +199,16 @@ class ValidateExpectedFiles(pyblish.api.InstancePlugin):
(dict): Job info from Deadline
"""
# get default deadline webservice url from deadline module
deadline_url = instance.context.data["defaultDeadline"]
# if custom one is set in instance, use that
if instance.data.get("deadlineUrl"):
deadline_url = instance.data.get("deadlineUrl")
deadline_url = instance.data["deadline"]["url"]
assert deadline_url, "Requires Deadline Webservice URL"
url = "{}/api/jobs?JobID={}".format(deadline_url, job_id)
try:
response = requests_get(url)
kwargs = {}
auth = instance.data["deadline"]["auth"]
if auth:
kwargs["auth"] = auth
response = requests_get(url, **kwargs)
except requests.exceptions.ConnectionError:
self.log.error("Deadline is not accessible at "
"{}".format(deadline_url))

View file

@ -0,0 +1 @@
__version__ = "0.1.10"

View file

@ -80,6 +80,7 @@ class RenderInstance(object):
anatomyData = attr.ib(default=None)
outputDir = attr.ib(default=None)
context = attr.ib(default=None)
deadline = attr.ib(default=None)
# The source instance the data of this render instance should merge into
source_instance = attr.ib(default=None, type=pyblish.api.Instance)
@ -215,13 +216,12 @@ class AbstractCollectRender(pyblish.api.ContextPlugin):
# add additional data
data = self.add_additional_data(data)
render_instance_dict = attr.asdict(render_instance)
# Merge into source instance if provided, otherwise create instance
instance = render_instance_dict.pop("source_instance", None)
instance = render_instance.source_instance
if instance is None:
instance = context.create_instance(render_instance.name)
render_instance_dict = attr.asdict(render_instance)
instance.data.update(render_instance_dict)
instance.data.update(data)

View file

@ -2,11 +2,13 @@ from typing import Type
from ayon_server.addons import BaseServerAddon
from .settings import DeadlineSettings, DEFAULT_VALUES
from .settings import DeadlineSettings, DEFAULT_VALUES, DeadlineSiteSettings
class Deadline(BaseServerAddon):
settings_model: Type[DeadlineSettings] = DeadlineSettings
site_settings_model: Type[DeadlineSiteSettings] = DeadlineSiteSettings
async def get_default_settings(self):
settings_model_cls = self.get_settings_model()

View file

@ -2,9 +2,11 @@ from .main import (
DeadlineSettings,
DEFAULT_VALUES,
)
from .site_settings import DeadlineSiteSettings
__all__ = (
"DeadlineSettings",
"DeadlineSiteSettings",
"DEFAULT_VALUES",
)

View file

@ -15,12 +15,6 @@ from .publish_plugins import (
)
class ServerListSubmodel(BaseSettingsModel):
_layout = "compact"
name: str = SettingsField(title="Name")
value: str = SettingsField(title="Value")
async def defined_deadline_ws_name_enum_resolver(
addon: "BaseServerAddon",
settings_variant: str = "production",
@ -32,25 +26,40 @@ async def defined_deadline_ws_name_enum_resolver(
settings = await addon.get_studio_settings(variant=settings_variant)
ws_urls = []
ws_server_name = []
for deadline_url_item in settings.deadline_urls:
ws_urls.append(deadline_url_item.name)
ws_server_name.append(deadline_url_item.name)
return ws_urls
return ws_server_name
class ServerItemSubmodel(BaseSettingsModel):
"""Connection info about configured DL servers."""
_layout = "compact"
name: str = SettingsField(title="Name")
value: str = SettingsField(title="Url")
require_authentication: bool = SettingsField(
False,
title="Require authentication")
ssl: bool = SettingsField(False,
title="SSL")
class DeadlineSettings(BaseSettingsModel):
deadline_urls: list[ServerListSubmodel] = SettingsField(
# configured DL servers
deadline_urls: list[ServerItemSubmodel] = SettingsField(
default_factory=list,
title="System Deadline Webservice URLs",
title="System Deadline Webservice Info",
scope=["studio"],
)
# name(key) of selected server for project
deadline_server: str = SettingsField(
title="Project deadline server",
title="Project Deadline server name",
section="---",
scope=["project"],
enum_resolver=defined_deadline_ws_name_enum_resolver
)
publish: PublishPluginsModel = SettingsField(
default_factory=PublishPluginsModel,
title="Publish Plugins",
@ -62,11 +71,14 @@ class DeadlineSettings(BaseSettingsModel):
return value
DEFAULT_VALUES = {
"deadline_urls": [
{
"name": "default",
"value": "http://127.0.0.1:8082"
"value": "http://127.0.0.1:8082",
"require_authentication": False,
"ssl": False
}
],
"deadline_server": "default",

View file

@ -0,0 +1,26 @@
from ayon_server.settings import (
BaseSettingsModel,
SettingsField,
)
from .main import defined_deadline_ws_name_enum_resolver
class CredentialPerServerModel(BaseSettingsModel):
"""Provide credentials for configured DL servers"""
_layout = "expanded"
server_name: str = SettingsField("",
title="DL server name",
enum_resolver=defined_deadline_ws_name_enum_resolver)
username: str = SettingsField("",
title="Username")
password: str = SettingsField("",
title="Password")
class DeadlineSiteSettings(BaseSettingsModel):
local_settings: list[CredentialPerServerModel] = SettingsField(
default_factory=list,
title="Local setting",
description="Please provide credentials for configured Deadline servers",
)