mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
* Reference database object by GFK when running scripts & reports via UI * Reference database object by GFK when running scripts & reports via API * Remove old enqueue_job() method * Enable filtering jobs by object * Introduce ObjectJobsView * Add tabbed views for report & script jobs * Add object_id to JobSerializer * Move generic relation to JobsMixin * Clean up old naming
This commit is contained in:
@ -25,7 +25,7 @@ from utilities.forms import add_blank_choice, DynamicModelChoiceField, DynamicMo
|
||||
from .context_managers import change_logging
|
||||
from .forms import ScriptForm
|
||||
|
||||
__all__ = [
|
||||
__all__ = (
|
||||
'BaseScript',
|
||||
'BooleanVar',
|
||||
'ChoiceVar',
|
||||
@ -40,7 +40,9 @@ __all__ = [
|
||||
'Script',
|
||||
'StringVar',
|
||||
'TextVar',
|
||||
]
|
||||
'get_module_and_script',
|
||||
'run_script',
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
@ -436,18 +438,23 @@ def is_variable(obj):
|
||||
return isinstance(obj, ScriptVariable)
|
||||
|
||||
|
||||
def run_script(data, request, commit=True, *args, **kwargs):
|
||||
def get_module_and_script(module_name, script_name):
|
||||
module = ScriptModule.objects.get(file_path=f'{module_name}.py')
|
||||
script = module.scripts.get(script_name)
|
||||
return module, script
|
||||
|
||||
|
||||
def run_script(data, request, job, commit=True, **kwargs):
|
||||
"""
|
||||
A wrapper for calling Script.run(). This performs error handling and provides a hook for committing changes. It
|
||||
exists outside the Script class to ensure it cannot be overridden by a script author.
|
||||
"""
|
||||
job_result = kwargs.pop('job_result')
|
||||
job_result.start()
|
||||
job.start()
|
||||
|
||||
module_name, script_name = job_result.name.split('.', 1)
|
||||
script = get_script(module_name, script_name)()
|
||||
module = ScriptModule.objects.get(pk=job.object_id)
|
||||
script = module.scripts.get(job.name)()
|
||||
|
||||
logger = logging.getLogger(f"netbox.scripts.{module_name}.{script_name}")
|
||||
logger = logging.getLogger(f"netbox.scripts.{script.full_name}")
|
||||
logger.info(f"Running script (commit={commit})")
|
||||
|
||||
# Add files to form data
|
||||
@ -472,8 +479,8 @@ def run_script(data, request, commit=True, *args, **kwargs):
|
||||
except AbortTransaction:
|
||||
script.log_info("Database changes have been reverted automatically.")
|
||||
clear_webhooks.send(request)
|
||||
job_result.data = ScriptOutputSerializer(script).data
|
||||
job_result.terminate()
|
||||
job.data = ScriptOutputSerializer(script).data
|
||||
job.terminate()
|
||||
except Exception as e:
|
||||
if type(e) is AbortScript:
|
||||
script.log_failure(f"Script aborted with error: {e}")
|
||||
@ -483,11 +490,11 @@ def run_script(data, request, commit=True, *args, **kwargs):
|
||||
script.log_failure(f"An exception occurred: `{type(e).__name__}: {e}`\n```\n{stacktrace}\n```")
|
||||
logger.error(f"Exception raised during script execution: {e}")
|
||||
script.log_info("Database changes have been reverted due to error.")
|
||||
job_result.data = ScriptOutputSerializer(script).data
|
||||
job_result.terminate(status=JobStatusChoices.STATUS_ERRORED)
|
||||
job.data = ScriptOutputSerializer(script).data
|
||||
job.terminate(status=JobStatusChoices.STATUS_ERRORED)
|
||||
clear_webhooks.send(request)
|
||||
|
||||
logger.info(f"Script completed in {job_result.duration}")
|
||||
logger.info(f"Script completed in {job.duration}")
|
||||
|
||||
# Execute the script. If commit is True, wrap it with the change_logging context manager to ensure we process
|
||||
# change logging, webhooks, etc.
|
||||
@ -498,25 +505,17 @@ def run_script(data, request, commit=True, *args, **kwargs):
|
||||
_run_script()
|
||||
|
||||
# Schedule the next job if an interval has been set
|
||||
if job_result.interval:
|
||||
new_scheduled_time = job_result.scheduled + timedelta(minutes=job_result.interval)
|
||||
Job.enqueue_job(
|
||||
if job.interval:
|
||||
new_scheduled_time = job.scheduled + timedelta(minutes=job.interval)
|
||||
Job.enqueue(
|
||||
run_script,
|
||||
name=job_result.name,
|
||||
obj_type=job_result.obj_type,
|
||||
user=job_result.user,
|
||||
instance=job.object,
|
||||
name=job.name,
|
||||
user=job.user,
|
||||
schedule_at=new_scheduled_time,
|
||||
interval=job_result.interval,
|
||||
interval=job.interval,
|
||||
job_timeout=script.job_timeout,
|
||||
data=data,
|
||||
request=request,
|
||||
commit=commit
|
||||
)
|
||||
|
||||
|
||||
def get_script(module_name, script_name):
|
||||
"""
|
||||
Retrieve a script class by module and name. Returns None if the script does not exist.
|
||||
"""
|
||||
module = ScriptModule.objects.get(file_path=f'{module_name}.py')
|
||||
return module.scripts.get(script_name)
|
||||
|
Reference in New Issue
Block a user