Flamenco/addon/flamenco/job_submission.py
Sybren A. Stüvel 3b4da656c9 Add-on: cache manager info in a JSON file
Instead of storing the cached manager info in the Blender preferences,
store the info in a JSON file. The file is located in the user prefs
folder (`~/.config/blender/{version}/config` on Linux).

This also reduces the number of 'refresh' operators to a single one, which
then fetches all necessary info from the Manager.

This fixes an issue (reported via chat) where worker tags were sometimes
not retained across file saves.
2024-03-04 13:08:53 +01:00

151 lines
4.8 KiB
Python

# SPDX-License-Identifier: GPL-3.0-or-later
from pathlib import Path, PurePosixPath
from typing import TYPE_CHECKING, Optional, Union
import platform
import logging
import bpy
from .job_types_propgroup import JobTypePropertyGroup
from .bat.submodules import bpathlib
from . import manager_info
if TYPE_CHECKING:
from .manager import ApiClient as _ApiClient
from .manager.models import (
AvailableJobType as _AvailableJobType,
Job as _Job,
SubmittedJob as _SubmittedJob,
)
else:
_AvailableJobType = object
_ApiClient = object
_Job = object
_SubmittedJob = object
# If a job has a setting with this key, type 'str', and subtype 'file_path',
# it'll be set to the path of the BAT-packed blend file.
BLENDFILE_SETTING_KEY = "blendfile"
log = logging.getLogger(__name__)
def job_for_scene(scene: bpy.types.Scene) -> Optional[_SubmittedJob]:
from flamenco.manager.models import SubmittedJob, JobMetadata
propgroup = getattr(scene, "flamenco_job_settings", None)
assert isinstance(propgroup, JobTypePropertyGroup), "did not expect %s" % (
type(propgroup)
)
settings = propgroup.as_jobsettings()
metadata = JobMetadata()
priority = getattr(scene, "flamenco_job_priority", 50)
job: SubmittedJob = SubmittedJob(
name=scene.flamenco_job_name,
type=propgroup.job_type.name,
priority=priority,
settings=settings,
metadata=metadata,
submitter_platform=platform.system().lower(),
type_etag=propgroup.job_type.etag,
)
worker_tag: str = getattr(scene, "flamenco_worker_tag", "")
if worker_tag and worker_tag != "-":
job.worker_tag = worker_tag
return job
def set_blend_file(
job_type: _AvailableJobType,
job: _SubmittedJob,
blendfile: Union[str, Path, PurePosixPath],
) -> None:
"""Update the job's 'blendfile' setting, if available.
If a job has a 'blendfile' setting, type 'str', it'll be set to the path/URL
of the BAT-packed blend file.
"""
from .manager.models import AvailableJobSetting, AvailableJobSettingType
expected_type = AvailableJobSettingType("string")
for setting in job_type.settings:
if setting.key == BLENDFILE_SETTING_KEY and setting.type == expected_type:
break
else:
# Not having this setting is fine.
return
assert isinstance(setting, AvailableJobSetting)
job.settings[BLENDFILE_SETTING_KEY] = str(blendfile)
def set_shaman_checkout_id(job: _SubmittedJob, checkout_id: PurePosixPath) -> None:
from flamenco.manager.models import JobStorageInfo
# The job.storage attribute doesn't even exist if it's not set.
if getattr(job, "storage", None) is None:
job.storage = JobStorageInfo()
job.storage.shaman_checkout_id = checkout_id.as_posix()
def submit_job(job: _SubmittedJob, api_client: _ApiClient) -> _Job:
"""Send the given job to Flamenco Manager."""
from flamenco.manager import ApiClient
from flamenco.manager.api import jobs_api
from flamenco.manager.models import SubmittedJob, Job
assert isinstance(job, SubmittedJob), "got %s" % type(job)
assert isinstance(api_client, ApiClient), "got %s" % type(api_client)
job_api_instance = jobs_api.JobsApi(api_client)
response: Job = job_api_instance.submit_job(job)
print("Job submitted: %s (%s)" % (response.name, response.id))
return response
def submit_job_check(job: _SubmittedJob, api_client: _ApiClient) -> None:
"""Check the given job at Flamenco Manager to see if it is acceptable."""
from flamenco.manager import ApiClient
from flamenco.manager.api import jobs_api
from flamenco.manager.models import SubmittedJob, Job
assert isinstance(job, SubmittedJob), "got %s" % type(job)
assert isinstance(api_client, ApiClient), "got %s" % type(api_client)
job_api_instance = jobs_api.JobsApi(api_client)
job_api_instance.submit_job_check(job)
def is_file_inside_job_storage(context: bpy.types.Context, blendfile: Path) -> bool:
"""Check whether current blend file is inside the storage path.
:return: True when the current blend file is inside the Flamenco job storage
directory already. In this case it won't be BAT-packed, as it's assumed
the job storage dir is accessible by the workers already.
"""
blendfile = bpathlib.make_absolute(blendfile)
info = manager_info.load_cached()
if not info:
raise RuntimeError("Flamenco Manager info unknown, please refresh.")
job_storage = bpathlib.make_absolute(Path(info.shared_storage.location))
log.info("Checking whether the file is already inside the job storage")
log.info(" file : %s", blendfile)
log.info(" storage: %s", job_storage)
try:
blendfile.relative_to(job_storage)
except ValueError:
return False
return True