Skip to content

api

Wrapper around Royal Render API.

Api

Source code in client/ayon_royalrender/api.py
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
class Api:

    _settings = None
    RR_SUBMIT_CONSOLE = 1
    RR_SUBMIT_API = 2

    def __init__(self, rr_path=None):
        self.log = Logger.get_logger("RoyalRender")
        self._rr_path = rr_path
        os.environ["RR_ROOT"] = rr_path

    @staticmethod
    def get_rr_bin_path(rr_root, tool_name=None):
        # type: (str, str) -> str
        """Get path to RR bin folder.

        Args:
            tool_name (str): Name of RR executable you want.
            rr_root (str): Custom RR root if needed.

        Returns:
            str: Path to the tool based on current platform.

        """
        is_64bit_python = sys.maxsize > 2 ** 32

        rr_bin_parts = [rr_root, "bin"]
        if sys.platform.lower() == "win32":
            rr_bin_parts.append("win")

        if sys.platform.lower() == "darwin":
            rr_bin_parts.append("mac")

        if sys.platform.lower().startswith("linux"):
            rr_bin_parts.append("lx")

        rr_bin_path = os.sep.join(rr_bin_parts)

        paths_to_check = []
        # if we use 64bit python, append 64bit specific path first
        if is_64bit_python:
            if not tool_name:
                return rr_bin_path + "64"
            paths_to_check.append(rr_bin_path + "64")

        # otherwise use 32bit
        if not tool_name:
            return rr_bin_path
        paths_to_check.append(rr_bin_path)

        return find_tool_in_custom_paths(paths_to_check, tool_name)

    def _initialize_module_path(self):
        # type: () -> None
        """Set RR modules for Python."""
        # default for linux
        rr_bin = self.get_rr_bin_path(self._rr_path)
        rr_module_path = os.path.join(rr_bin, "lx64/lib")

        if sys.platform.lower() == "win32":
            rr_module_path = rr_bin
            rr_module_path = rr_module_path.replace(
                "/", os.path.sep
            )

        if sys.platform.lower() == "darwin":
            rr_module_path = os.path.join(rr_bin, "lib/python/27")

        sys.path.append(os.path.join(self._rr_path, rr_module_path))

    @staticmethod
    def create_submission(jobs, submitter_attributes):
        # type: (list[RRJob], list[SubmitterParameter]) -> SubmitFile
        """Create jobs submission file.

        Args:
            jobs (list): List of :class:`RRJob`
            submitter_attributes (list): List of submitter attributes
                :class:`SubmitterParameter` for whole submission batch.

        Returns:
            str: XML data of job submission files.

        """
        return SubmitFile(SubmitterParameters=submitter_attributes, Jobs=jobs)

    def submit_file(self, file, mode=RR_SUBMIT_CONSOLE):
        # type: (SubmitFile, int) -> None
        if mode == self.RR_SUBMIT_CONSOLE:
            self._submit_using_console(file)
            return

        # RR v7 supports only Python 2.7, so we bail out in fear
        # until there is support for Python 3 😰
        raise NotImplementedError(
            "Submission via RoyalRender API is not supported yet")
        # self._submit_using_api(file)

    def _submit_using_console(self, job_file):
        # type: (SubmitFile) -> None
        rr_start_local = self.get_rr_bin_path(
            self._rr_path, "rrStartLocal")

        self.log.info("rr_console: {}".format(rr_start_local))

        args = [rr_start_local, "rrSubmitterconsole", job_file]
        self.log.info("Executing: {}".format(" ".join(args)))
        env = os.environ
        env["RR_ROOT"] = self._rr_path
        run_subprocess(args, logger=self.log, env=env)

    def _submit_using_api(self, file):
        # type: (SubmitFile) -> None
        """Use RR API to submit jobs.

        Args:
            file (SubmitFile): Submit jobs definition.

        Throws:
            RoyalRenderException: When something fails.

        """
        self._initialize_module_path()
        import libpyRR2 as rrLib  # noqa
        from rrJob import getClass_JobBasics  # noqa
        import libpyRR2 as _RenderAppBasic  # noqa

        tcp = rrLib._rrTCP("")  # noqa
        rr_server = tcp.getRRServer()

        if len(rr_server) == 0:
            self.log.info("Got RR IP address {}".format(rr_server))

        # TODO: Port is hardcoded in RR? If not, move it to Settings
        if not tcp.setServer(rr_server, 7773):
            self.log.error(
                "Can not set RR server: {}".format(tcp.errorMessage()))
            raise RoyalRenderException(tcp.errorMessage())

        # TODO: This need UI and better handling of username/password.
        # We can't store password in keychain as it is pulled multiple
        # times and users on linux must enter keychain password every time.
        # Probably best way until we setup our own user management would be
        # to encrypt password and save it to json locally. Not bulletproof
        # but at least it is not stored in plaintext.
        reg = AYONSettingsRegistry("rr_settings")
        try:
            rr_user = reg.get_item("rr_username")
            rr_password = reg.get_item("rr_password")
        except ValueError:
            # user has no rr credentials set
            pass
        else:
            # login to RR
            tcp.setLogin(rr_user, rr_password)

        job = getClass_JobBasics()
        renderer = _RenderAppBasic()

        # iterate over SubmitFile, set _JobBasic (job) and renderer
        # and feed it to jobSubmitNew()
        # not implemented yet
        job.renderer = renderer
        tcp.jobSubmitNew(job)

create_submission(jobs, submitter_attributes) staticmethod

Create jobs submission file.

Parameters:

Name Type Description Default
jobs list

List of :class:RRJob

required
submitter_attributes list

List of submitter attributes :class:SubmitterParameter for whole submission batch.

required

Returns:

Name Type Description
str

XML data of job submission files.

Source code in client/ayon_royalrender/api.py
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
@staticmethod
def create_submission(jobs, submitter_attributes):
    # type: (list[RRJob], list[SubmitterParameter]) -> SubmitFile
    """Create jobs submission file.

    Args:
        jobs (list): List of :class:`RRJob`
        submitter_attributes (list): List of submitter attributes
            :class:`SubmitterParameter` for whole submission batch.

    Returns:
        str: XML data of job submission files.

    """
    return SubmitFile(SubmitterParameters=submitter_attributes, Jobs=jobs)

get_rr_bin_path(rr_root, tool_name=None) staticmethod

Get path to RR bin folder.

Parameters:

Name Type Description Default
tool_name str

Name of RR executable you want.

None
rr_root str

Custom RR root if needed.

required

Returns:

Name Type Description
str

Path to the tool based on current platform.

Source code in client/ayon_royalrender/api.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@staticmethod
def get_rr_bin_path(rr_root, tool_name=None):
    # type: (str, str) -> str
    """Get path to RR bin folder.

    Args:
        tool_name (str): Name of RR executable you want.
        rr_root (str): Custom RR root if needed.

    Returns:
        str: Path to the tool based on current platform.

    """
    is_64bit_python = sys.maxsize > 2 ** 32

    rr_bin_parts = [rr_root, "bin"]
    if sys.platform.lower() == "win32":
        rr_bin_parts.append("win")

    if sys.platform.lower() == "darwin":
        rr_bin_parts.append("mac")

    if sys.platform.lower().startswith("linux"):
        rr_bin_parts.append("lx")

    rr_bin_path = os.sep.join(rr_bin_parts)

    paths_to_check = []
    # if we use 64bit python, append 64bit specific path first
    if is_64bit_python:
        if not tool_name:
            return rr_bin_path + "64"
        paths_to_check.append(rr_bin_path + "64")

    # otherwise use 32bit
    if not tool_name:
        return rr_bin_path
    paths_to_check.append(rr_bin_path)

    return find_tool_in_custom_paths(paths_to_check, tool_name)

RoyalRenderException

Bases: Exception

Exception used in various error states coming from RR.

Source code in client/ayon_royalrender/api.py
179
180
181
class RoyalRenderException(Exception):
    """Exception used in various error states coming from RR."""
    pass