From 782a1a4699e2ec5d8bd5e277b1a817039404200b Mon Sep 17 00:00:00 2001 From: Brett Date: Mon, 23 Oct 2023 08:26:11 -0500 Subject: [PATCH] Added engine update check on launch (#43) --- config/config.yaml | 1 + src/api/api_server.py | 6 +++++- src/engines/blender/blender_downloader.py | 10 ++++----- src/engines/engine_manager.py | 26 +++++++++++++++-------- src/engines/ffmpeg/ffmpeg_downloader.py | 18 ++++++++++------ 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/config/config.yaml b/config/config.yaml index 31222f7..8a93c6d 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -1,4 +1,5 @@ upload_folder: "~/zordon-uploads/" +update_engines_on_launch: true max_content_path: 100000000 server_log_level: info flask_log_level: error diff --git a/src/api/api_server.py b/src/api/api_server.py index 8786b77..df38731 100755 --- a/src/api/api_server.py +++ b/src/api/api_server.py @@ -664,6 +664,10 @@ def start_server(background_thread=False): flask_log = logging.getLogger('werkzeug') flask_log.setLevel(config.get('flask_log_level', 'ERROR').upper()) + # check for updates for render engines if config'd or on first launch + if config.get('update_engines_on_launch', False) or not EngineManager.all_engines(): + EngineManager.update_all_engines() + # Set up the RenderQueue object RenderQueue.start_queue() DistributedJobManager.start() @@ -671,7 +675,7 @@ def start_server(background_thread=False): thread = threading.Thread(target=eval_loop, kwargs={'delay_sec': config.get('queue_eval_seconds', 1)}, daemon=True) thread.start() - logging.info(f"Starting Zordon Render Server - Hostname: '{server.config['HOSTNAME']}:'") + logger.info(f"Starting Zordon Render Server - Hostname: '{server.config['HOSTNAME']}:'") ZeroconfServer.configure("_zordon._tcp.local.", server.config['HOSTNAME'], server.config['PORT']) ZeroconfServer.start() diff --git a/src/engines/blender/blender_downloader.py b/src/engines/blender/blender_downloader.py index b777b6f..8045b57 100644 --- a/src/engines/blender/blender_downloader.py +++ b/src/engines/blender/blender_downloader.py @@ -19,7 +19,7 @@ class BlenderDownloader: @staticmethod def get_major_versions(): try: - response = requests.get(url) + response = requests.get(url, timeout=5) response.raise_for_status() # Use regex to find all the tags and extract the href attribute @@ -38,7 +38,7 @@ class BlenderDownloader: try: base_url = url + 'Blender' + major_version - response = requests.get(base_url) + response = requests.get(base_url, timeout=5) response.raise_for_status() versions_pattern = r'blender-(?P[\d\.]+)-(?P\w+)-(?P\w+).*' @@ -86,11 +86,11 @@ class BlenderDownloader: return lts_versions @classmethod - def find_most_recent_version(cls, system_os, cpu, lts_only=False): + def find_most_recent_version(cls, system_os=None, cpu=None, lts_only=False): try: major_version = cls.find_LTS_versions()[0] if lts_only else cls.get_major_versions()[0] - most_recent = cls.get_minor_versions(major_version, system_os, cpu)[0] - return most_recent + most_recent = cls.get_minor_versions(major_version=major_version, system_os=system_os, cpu=cpu) + return most_recent[0] except IndexError: logger.error("Cannot find a most recent version") diff --git a/src/engines/engine_manager.py b/src/engines/engine_manager.py index 327b181..c2ebc0e 100644 --- a/src/engines/engine_manager.py +++ b/src/engines/engine_manager.py @@ -88,7 +88,7 @@ class EngineManager: return None @classmethod - def has_engine_version(cls, engine, version, system_os=None, cpu=None): + def is_version_downloaded(cls, engine, version, system_os=None, cpu=None): system_os = system_os or cls.system_os() cpu = cpu or cls.system_cpu() @@ -107,26 +107,25 @@ class EngineManager: @classmethod def version_is_available_to_download(cls, engine, version, system_os=None, cpu=None): try: - return cls.downloader_classes[engine].version_is_available_to_download(version, system_os, cpu) + return cls.downloader_classes[engine].version_is_available_to_download(version=version, system_os=system_os, + cpu=cpu) except Exception as e: return None @classmethod - def find_most_recent_version(cls, engine, system_os, cpu, lts_only=False): + def find_most_recent_version(cls, engine=None, system_os=None, cpu=None, lts_only=False): try: - return cls.downloader_classes[engine].find_most_recent_version(system_os, cpu) + return cls.downloader_classes[engine].find_most_recent_version(system_os=system_os, cpu=cpu) except Exception as e: return None @classmethod def download_engine(cls, engine, version, system_os=None, cpu=None): - existing_download = cls.has_engine_version(engine, version, system_os, cpu) + existing_download = cls.is_version_downloaded(engine, version, system_os, cpu) if existing_download: logger.info(f"Requested download of {engine} {version}, but local copy already exists") return existing_download - logger.info(f"Requesting download of {engine} {version}") - # Check if the provided engine type is valid if engine not in cls.downloader_classes: logger.error("No valid engine found") @@ -137,7 +136,7 @@ class EngineManager: system_os=system_os, cpu=cpu, timeout=300) # Check that engine was properly downloaded - found_engine = cls.has_engine_version(engine, version, system_os, cpu) + found_engine = cls.is_version_downloaded(engine, version, system_os, cpu) if not found_engine: logger.error(f"Error downloading {engine}") return found_engine @@ -146,7 +145,7 @@ class EngineManager: @classmethod def delete_engine_download(cls, engine, version, system_os=None, cpu=None): logger.info(f"Requested deletion of engine: {engine}-{version}") - found = cls.has_engine_version(engine, version, system_os, cpu) + found = cls.is_version_downloaded(engine, version, system_os, cpu) if found: dir_path = os.path.dirname(found['path']) shutil.rmtree(dir_path, ignore_errors=True) @@ -155,6 +154,15 @@ class EngineManager: else: logger.error(f"Cannot find engine: {engine}-{version}") + @classmethod + def update_all_engines(cls): + logger.info(f"Checking for updates for render engines...") + for engine, engine_downloader in cls.downloader_classes.items(): + latest_version = engine_downloader.find_most_recent_version().get('version') + if latest_version and not cls.is_version_downloaded(engine, latest_version): + logger.info(f"Downloading newest version of {engine} ({latest_version})") + cls.download_engine(engine, latest_version) + if __name__ == '__main__': logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') diff --git a/src/engines/ffmpeg/ffmpeg_downloader.py b/src/engines/ffmpeg/ffmpeg_downloader.py index b988d9c..dff031a 100644 --- a/src/engines/ffmpeg/ffmpeg_downloader.py +++ b/src/engines/ffmpeg/ffmpeg_downloader.py @@ -25,7 +25,7 @@ class FFMPEGDownloader: @classmethod def __get_macos_versions(cls): - response = requests.get(cls.macos_url) + response = requests.get(cls.macos_url, timeout=5) response.raise_for_status() link_pattern = r'>(.*\.zip)[^\.]' @@ -37,12 +37,12 @@ class FFMPEGDownloader: def __get_linux_versions(cls): # Link 1 / 2 - Current Version - response = requests.get(cls.linux_url) + response = requests.get(cls.linux_url, timeout=5) response.raise_for_status() current_release = re.findall(r'release: ([\w\.]+)', response.text)[0] # Link 2 / 2 - Previous Versions - response = requests.get(os.path.join(cls.linux_url, 'old-releases')) + response = requests.get(os.path.join(cls.linux_url, 'old-releases'), timeout=5) response.raise_for_status() releases = list(set(re.findall(r'href="ffmpeg-([\w\.]+)-.*">ffmpeg', response.text))) releases.sort(reverse=True) @@ -51,7 +51,7 @@ class FFMPEGDownloader: @classmethod def __get_windows_versions(cls): - response = requests.get(cls.windows_api_url) + response = requests.get(cls.windows_api_url, timeout=5) response.raise_for_status() versions = [] @@ -62,8 +62,14 @@ class FFMPEGDownloader: return versions @classmethod - def find_most_recent_version(cls, system_os, cpu, lts_only=False): - return cls.all_versions(system_os, cpu)[0] + def find_most_recent_version(cls, system_os=None, cpu=None, lts_only=False): + try: + system_os = system_os or current_system_os() + cpu = cpu or current_system_cpu() + return cls.all_versions(system_os, cpu)[0] + except TypeError: + pass + return None @classmethod def all_versions(cls, system_os=None, cpu=None):