mirror of
https://github.com/blw1138/Zordon.git
synced 2025-12-17 16:58:12 +00:00
* Add is_engine_available_to_download API call * Fix issue with worker never throwing error if engine is not found * Add API call to get most recent engine version * Fix some minor import issues * Fix web urls * Fix default server log level * Add progress bar for project download worker_factory downloads missing engine versions * Better error handling when invalid version is given * Add timeouts to engine downloaders
This commit is contained in:
@@ -12,24 +12,25 @@ import threading
|
||||
import time
|
||||
import zipfile
|
||||
from datetime import datetime
|
||||
from urllib.request import urlretrieve
|
||||
from zipfile import ZipFile
|
||||
|
||||
import json2html
|
||||
import psutil
|
||||
import requests
|
||||
import yaml
|
||||
from flask import Flask, request, render_template, send_file, after_this_request, Response, redirect, url_for, abort
|
||||
from tqdm import tqdm
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
from src.api.server_proxy import RenderServerProxy
|
||||
from src.distributed_job_manager import DistributedJobManager
|
||||
from src.engines.core.base_worker import string_to_status, RenderStatus
|
||||
from src.engines.core.worker_factory import RenderWorkerFactory
|
||||
from src.engines.engine_manager import EngineManager
|
||||
from src.render_queue import RenderQueue, JobNotFoundError
|
||||
from src.api.server_proxy import RenderServerProxy
|
||||
from src.utilities.misc_helper import system_safe_path
|
||||
from src.utilities.server_helper import generate_thumbnail_for_job
|
||||
from src.utilities.zeroconf_server import ZeroconfServer
|
||||
from src.utilities.misc_helper import system_safe_path
|
||||
from src.engines.core.worker_factory import RenderWorkerFactory
|
||||
from src.engines.core.base_worker import string_to_status, RenderStatus
|
||||
|
||||
logger = logging.getLogger()
|
||||
server = Flask(__name__, template_folder='web/templates', static_folder='web/static')
|
||||
@@ -133,15 +134,15 @@ def job_thumbnail(job_id):
|
||||
|
||||
# Misc status icons
|
||||
if found_job.status == RenderStatus.RUNNING:
|
||||
return send_file('web/static/images/gears.png', mimetype="image/png")
|
||||
return send_file('../web/static/images/gears.png', mimetype="image/png")
|
||||
elif found_job.status == RenderStatus.CANCELLED:
|
||||
return send_file('web/static/images/cancelled.png', mimetype="image/png")
|
||||
return send_file('../web/static/images/cancelled.png', mimetype="image/png")
|
||||
elif found_job.status == RenderStatus.SCHEDULED:
|
||||
return send_file('web/static/images/scheduled.png', mimetype="image/png")
|
||||
return send_file('../web/static/images/scheduled.png', mimetype="image/png")
|
||||
elif found_job.status == RenderStatus.NOT_STARTED:
|
||||
return send_file('web/static/images/not_started.png', mimetype="image/png")
|
||||
return send_file('../web/static/images/not_started.png', mimetype="image/png")
|
||||
# errors
|
||||
return send_file('web/static/images/error.png', mimetype="image/png")
|
||||
return send_file('../web/static/images/error.png', mimetype="image/png")
|
||||
|
||||
|
||||
# Get job file routing
|
||||
@@ -190,7 +191,7 @@ def get_job_status(job_id):
|
||||
@server.get('/api/job/<job_id>/logs')
|
||||
def get_job_logs(job_id):
|
||||
found_job = RenderQueue.job_with_id(job_id)
|
||||
log_path = system_safe_path(found_job.log_path()),
|
||||
log_path = system_safe_path(found_job.log_path())
|
||||
log_data = None
|
||||
if log_path and os.path.exists(log_path):
|
||||
with open(log_path) as file:
|
||||
@@ -322,10 +323,30 @@ def add_job_handler():
|
||||
referred_name = os.path.basename(uploaded_project.filename)
|
||||
elif project_url:
|
||||
# download and save url - have to download first to know filename due to redirects
|
||||
logger.info(f"Attempting to download URL: {project_url}")
|
||||
logger.info(f"Downloading project from url: {project_url}")
|
||||
try:
|
||||
downloaded_file_url, info = urlretrieve(project_url)
|
||||
referred_name = info.get_filename() or os.path.basename(project_url)
|
||||
referred_name = os.path.basename(project_url)
|
||||
response = requests.get(project_url, stream=True)
|
||||
if response.status_code == 200:
|
||||
# Get the total file size from the "Content-Length" header
|
||||
file_size = int(response.headers.get("Content-Length", 0))
|
||||
|
||||
# Create a progress bar using tqdm
|
||||
progress_bar = tqdm(total=file_size, unit="B", unit_scale=True)
|
||||
|
||||
# Open a file for writing in binary mode
|
||||
downloaded_file_url = os.path.join(tempfile.gettempdir(), referred_name)
|
||||
with open(downloaded_file_url, "wb") as file:
|
||||
for chunk in response.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
# Write the chunk to the file
|
||||
file.write(chunk)
|
||||
# Update the progress bar
|
||||
progress_bar.update(len(chunk))
|
||||
|
||||
# Close the progress bar
|
||||
progress_bar.close()
|
||||
|
||||
except Exception as e:
|
||||
err_msg = f"Error downloading file: {e}"
|
||||
logger.error(err_msg)
|
||||
@@ -419,6 +440,10 @@ def add_job_handler():
|
||||
if not worker.parent:
|
||||
make_job_ready(worker.id)
|
||||
results.append(worker.json())
|
||||
except FileNotFoundError as e:
|
||||
err_msg = f"Cannot create job: {e}"
|
||||
logger.error(err_msg)
|
||||
results.append({'error': err_msg})
|
||||
except Exception as e:
|
||||
err_msg = f"Exception creating render job: {e}"
|
||||
logger.exception(err_msg)
|
||||
@@ -549,6 +574,24 @@ def renderer_info():
|
||||
'supported_export_formats': engine(install_path).get_output_formats()}
|
||||
return renderer_data
|
||||
|
||||
@server.get('/api/is_engine_available_to_download')
|
||||
def is_engine_available_to_download():
|
||||
available_result = EngineManager.version_is_available_to_download(request.args.get('engine'),
|
||||
request.args.get('version'),
|
||||
request.args.get('system_os'),
|
||||
request.args.get('cpu'))
|
||||
return available_result if available_result else \
|
||||
(f"Cannot find available download for {request.args.get('engine')} {request.args.get('version')}", 500)
|
||||
|
||||
|
||||
@server.get('/api/find_most_recent_version')
|
||||
def find_most_recent_version():
|
||||
most_recent = EngineManager.find_most_recent_version(request.args.get('engine'),
|
||||
request.args.get('system_os'),
|
||||
request.args.get('cpu'))
|
||||
return most_recent if most_recent else \
|
||||
(f"Error finding most recent version of {request.args.get('engine')}", 500)
|
||||
|
||||
|
||||
@server.post('/api/download_engine')
|
||||
def download_engine():
|
||||
@@ -556,7 +599,8 @@ def download_engine():
|
||||
request.args.get('version'),
|
||||
request.args.get('system_os'),
|
||||
request.args.get('cpu'))
|
||||
return download_result if download_result else ("Error downloading requested engine", 500)
|
||||
return download_result if download_result else \
|
||||
(f"Error downloading {request.args.get('engine')} {request.args.get('version')}", 500)
|
||||
|
||||
|
||||
@server.post('/api/delete_engine')
|
||||
@@ -565,7 +609,8 @@ def delete_engine_download():
|
||||
request.args.get('version'),
|
||||
request.args.get('system_os'),
|
||||
request.args.get('cpu'))
|
||||
return "Success" if delete_result else ("Error deleting requested engine", 500)
|
||||
return "Success" if delete_result else \
|
||||
(f"Error deleting {request.args.get('engine')} {request.args.get('version')}", 500)
|
||||
|
||||
|
||||
@server.get('/api/renderer/<renderer>/args')
|
||||
|
||||
Reference in New Issue
Block a user