diff --git a/docs/customization/custom-scripts.md b/docs/customization/custom-scripts.md index 02af19726..982a4f8e3 100644 --- a/docs/customization/custom-scripts.md +++ b/docs/customization/custom-scripts.md @@ -89,6 +89,10 @@ The checkbox to commit database changes when executing a script is checked by de commit_default = False ``` +### `job_timeout` + +Set the allowed runtime of a script. If not set the `RQ_DEFAULT_TIMEOUT` will be used. + ## Accessing Request Data Details of the current HTTP request (the one being made to execute the script) are available as the instance attribute `self.request`. This can be used to infer, for example, the user executing the script and the client IP address: diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 4f42b4c93..579e39d86 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -236,7 +236,8 @@ class ReportViewSet(ViewSet): run_report, report.full_name, report_content_type, - request.user + request.user, + job_timeout=report.job_timeout ) report.result = job_result @@ -320,7 +321,8 @@ class ScriptViewSet(ViewSet): request.user, data=data, request=copy_safe_request(request), - commit=commit + commit=commit, + job_timeout=script.job_timeout, ) script.result = job_result serializer = serializers.ScriptDetailSerializer(script, context={'request': request}) diff --git a/netbox/extras/management/commands/runreport.py b/netbox/extras/management/commands/runreport.py index de7c5c91b..ee166ae6a 100644 --- a/netbox/extras/management/commands/runreport.py +++ b/netbox/extras/management/commands/runreport.py @@ -35,7 +35,8 @@ class Command(BaseCommand): run_report, report.full_name, report_content_type, - None + None, + job_timeout=report.job_timeout ) # Wait on the job to finish diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index ef0ab8b1f..48a076f75 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -13,6 +13,7 @@ from django.urls import reverse from django.utils import timezone from django.utils.formats import date_format from rest_framework.utils.encoders import JSONEncoder +import django_rq from extras.choices import * from extras.constants import * @@ -549,8 +550,9 @@ class JobResult(models.Model): user=user, job_id=uuid.uuid4() ) - - func.delay(*args, job_id=str(job_result.job_id), job_result=job_result, **kwargs) + + queue = django_rq.get_queue("default") + queue.enqueue(func, job_id=str(job_result.job_id), job_result=job_result, **kwargs) return job_result diff --git a/netbox/extras/reports.py b/netbox/extras/reports.py index 2eb6584c9..0bdc4847e 100644 --- a/netbox/extras/reports.py +++ b/netbox/extras/reports.py @@ -119,6 +119,7 @@ class Report(object): } """ description = None + job_timeout = None def __init__(self): diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index f80dfaefa..4b9d17d67 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -298,6 +298,10 @@ class BaseScript: def module(cls): return cls.__module__ + @classproperty + def job_timeout(self): + return getattr(self.Meta, 'job_timeout', None) + @classmethod def _get_vars(cls): vars = {} @@ -414,7 +418,7 @@ def is_variable(obj): return isinstance(obj, ScriptVariable) -@job('default') +#@job('default') def run_script(data, request, commit=True, *args, **kwargs): """ A wrapper for calling Script.run(). This performs error handling and provides a hook for committing changes. It diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 0a190dd49..785c5eb5a 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -588,7 +588,8 @@ class ReportView(ContentTypePermissionRequiredMixin, View): run_report, report.full_name, report_content_type, - request.user + request.user, + job_timeout=report.job_timeout ) return redirect('extras:report_result', job_result_pk=job_result.pk) @@ -708,6 +709,7 @@ class ScriptView(ContentTypePermissionRequiredMixin, GetScriptMixin, View): commit = form.cleaned_data.pop('_commit') script_content_type = ContentType.objects.get(app_label='extras', model='script') + job_result = JobResult.enqueue_job( run_script, script.full_name, @@ -715,7 +717,8 @@ class ScriptView(ContentTypePermissionRequiredMixin, GetScriptMixin, View): request.user, data=form.cleaned_data, request=copy_safe_request(request), - commit=commit + commit=commit, + job_timeout=script.job_timeout, ) return redirect('extras:script_result', job_result_pk=job_result.pk)