[pyoutline] Add OpenJD backend for job template serialization#2180
[pyoutline] Add OpenJD backend for job template serialization#2180mwiebe wants to merge 1 commit intoAcademySoftwareFoundation:masterfrom
Conversation
|
|
| - Layer outputs: the cue backend (spec >= 1.15) serializes get_outputs(). | ||
| Not yet mapped. OpenJD PATH parameters support dataFlow but only at | ||
| the job level, not per-step or per-task. | ||
| TODO: open a discussion on openjd-specifications for step- and task-level | ||
| file dataflow declarations (output path registration, existence checks). |
There was a problem hiding this comment.
This is crucial for some pipelines. Being able to trace what output was produced by each layer gives other systems the ability to trace assets for example for backups and recovers.
There was a problem hiding this comment.
Agreed, another reason is to be more efficient about data transfers or taking snapshots of just what's needed to run a particular task.
pyoutline/outline/backend/openjd.py
Outdated
| file dataflow declarations (output path registration, existence checks). | ||
| - Launcher flags: pause, priority, maxretries, autoeat, facility, show, | ||
| shot, user, email, uid are OpenCue scheduling metadata with no direct | ||
| OpenJD equivalent. The os flag could map to attr.worker.os.family. |
There was a problem hiding this comment.
Is there an equivalent way to launch a job as paused?
There was a problem hiding this comment.
OpenJD doesn't have that concept, we modeled that in Deadline Cloud as part of a job that is running, while the job template at this level is concerned with defining the job's parallel structure and the commands it will run.
I think a number of these flags could map to job parameter name conventions, e.g. job parameters named Facility, Show, Shot, User, Email, Uid.
There was a problem hiding this comment.
In my latest update, I've migrated a number of those to job parameters.
|
Hi @mwiebe It is missing the CLA Authorization. Thanks! |
|
Please note that there are some Python linting issues that need to be addressed. Additionally, when possible, remember to update the @docs/ for the new feature regarding the new feature in this pull request. |
ramonfigueiredo
left a comment
There was a problem hiding this comment.
Thanks for your contribution, @mwiebe
I've added some comments and suggestions for code improvements.
| attributes.append({"name": "opencue:attr.tag", "allOf": tag_list}) | ||
|
|
||
| # Service → custom attribute opencue:attr.service | ||
| service = layer.get_service() |
There was a problem hiding this comment.
Service name not split on comma
The cue backend does layer.get_service().split(",")[0] to extract just the first service when multiple are comma-separated. The OpenJD backend passes the full string as-is:
service = layer.get_service()
if service:
attributes.append({"name": "opencue:attr.service", "anyOf": [service]})If a layer has service="prman,shell", this would create anyOf: ["prman,shell"] instead of anyOf: ["prman"] (matching cue) or anyOf: ["prman", "shell"] (fully expanded). Should be intentional one way or the other.
There was a problem hiding this comment.
I switched it to match the cue backend's behavior, with a comment about considering the expanded anyOf case. Would be useful to work through some examples of how to map this in practice and see what makes the best sense.
pyoutline/outline/backend/openjd.py
Outdated
| cmd = ["openjd", "run", tmp.name] | ||
|
|
||
| logger.info("Running: %s", " ".join(cmd)) | ||
| result = subprocess.run(cmd, check=False) |
There was a problem hiding this comment.
launch() doesn't capture subprocess output
result = subprocess.run(cmd, check=False)If openjd run fails, the error is just "openjd run exited with code N" with no diagnostic output. Consider capturing stderr:
result = subprocess.run(cmd, check=False, capture_output=True, text=True)
if result.returncode != 0:
raise outline.exception.OutlineException(
"openjd run exited with code %d: %s" % (result.returncode, result.stderr)
)There was a problem hiding this comment.
I've got the code following this pattern, but I still need to exercise it end to end to see the diagnostics working as expected.
| # runs before setup. | ||
| # TODO: add a public get_code() method to PyEval so backends don't | ||
| # need to access the name-mangled attribute. | ||
| code = layer._PyEval__code |
There was a problem hiding this comment.
Private attribute access for PyEval
code = layer._PyEval__codeAcknowledged with a TODO. This is fragile, if the PyEval class renames or restructures its internals, this will break silently. Since this is a prototype, fine, but this should be addressed before any production use.
There was a problem hiding this comment.
I can update the PyEval class as part of this PR.
| @@ -1 +1 @@ | |||
| [build-system] | |||
There was a problem hiding this comment.
yaml (PyYAML) is not an explicit dependency:
The module imports yaml at the top level, but PyYAML isn't listed in pyproject.toml dependencies. It's likely pulled in transitively through opencue_pycue, but for correctness the dependency should be explicit, or at minimum noted.
There was a problem hiding this comment.
I've added the yaml dependency. I'm also thinking to put openjd-model directly as a dependency instead of having a separate feature for now, to keep things simpler. When we've exercised the change more, let's discuss how we feel about the best way to incorporate it.
efd7d4b to
f252b29
Compare
This is signed now, thanks! |
158cf35 to
cd64582
Compare
Add a new PyOutline backend that serializes Outline jobs into OpenJD 2023-09 job templates. This enables running OpenCue jobs via the openjd CLI or submitting them to OpenJD-compatible schedulers like AWS Deadline Cloud. - Serialize layers to OpenJD steps with CHUNK[INT] frame parameters - Map OpenCue command tokens (#IFRAME#, #FRAMESPEC#, etc.) to OpenJD expressions using the EXPR extension - Map host requirements: cores, memory, GPUs, tags, service, limits - Map dependencies including Post layer implicit depends - Wrap commands in bash scripts that export CUE_* environment variables - Support Shell, ShellScript, and PyEval layer types - Validate generated templates using openjd-model - Launch jobs locally via openjd CLI - Install with: pip install opencue-pyoutline[openjd]
Link the Issue(s) this Pull Request is related to.
OpenJobDescription/openjd-model-for-python#137
Summarize your change.
Add a new PyOutline backend that serializes Outline jobs into OpenJD 2023-09 job templates. This enables running OpenCue jobs via the openjd CLI or submitting them to OpenJD-compatible schedulers like AWS Deadline Cloud. It doesn't look at the opposite of running an OpenJD job template in OpenCue. That's a separate follow-up to perform.
This PR doesn't fix the linked issue, but implementing OpenCue's pyoutline API for defining a job is a nice way to get a feel for how such an API might look in the openjd-model library, and evaluate any missing functionality in Open Job Description for supporting OpenCue jobs.
This PR depends on an in-progress RFC for the EXPR extension in Open Job Description, so it probably should stay in draft until that is merged there.
This PR was created with LLM assistance via Kiro CLI and the Claude Opus 4.6 model.
The changes include:
Here's an example generated template based on the tutorials:
parallel_pipeline.template.yaml