Sybren A. Stüvel
3b4da656c9
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.
151 lines
4.8 KiB
Python
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
|