diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 58de803a5..fcd60462c 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -917,6 +917,10 @@ class ReportModule(JobResultsMixin, WebhooksMixin, PythonModuleMixin, ManagedFil def get_absolute_url(self): return reverse('extras:report_list') + @property + def name(self): + return self.file_path + @cached_property def reports(self): module = self.get_module() diff --git a/netbox/extras/reports.py b/netbox/extras/reports.py index 969fb3369..cedc1491f 100644 --- a/netbox/extras/reports.py +++ b/netbox/extras/reports.py @@ -3,6 +3,7 @@ import traceback from datetime import timedelta from django.utils import timezone +from django.utils.functional import classproperty from django_rq import job from .choices import JobResultStatusChoices, LogLevelChoices @@ -26,7 +27,7 @@ def run_report(job_result, *args, **kwargs): method for queueing into the background processor. """ module_name, report_name = job_result.name.split('.', 1) - report = get_report(module_name, report_name) + report = get_report(module_name, report_name)() try: job_result.start() @@ -83,7 +84,7 @@ class Report(object): self.active_test = None self.failed = False - self.logger = logging.getLogger(f"netbox.reports.{self.full_name}") + self.logger = logging.getLogger(f"netbox.reports.{self.__module__}.{self.__class__.__name__}") # Compile test methods and initialize results skeleton test_methods = [] @@ -101,13 +102,17 @@ class Report(object): raise Exception("A report must contain at least one test method.") self.test_methods = test_methods - @property + @classproperty def module(self): return self.__module__ - @property + @classproperty def class_name(self): - return self.__class__.__name__ + return self.__name__ + + @classproperty + def full_name(self): + return f'{self.module}.{self.class_name}' @property def name(self): @@ -116,9 +121,9 @@ class Report(object): """ return self.class_name - @property - def full_name(self): - return f'{self.module}.{self.class_name}' + # + # Logging methods + # def _log(self, obj, message, level=LogLevelChoices.LOG_DEFAULT): """ @@ -175,6 +180,10 @@ class Report(object): self.logger.info(f"Failure | {obj}: {message}") self.failed = True + # + # Run methods + # + def run(self, job_result): """ Run the report and save its results. Each test method will be executed in order. diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index eb73f8b51..23a9f9f73 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -267,7 +267,7 @@ class BaseScript: def __init__(self): # Initiate the log - self.logger = logging.getLogger(f"netbox.scripts.{self.module()}.{self.__class__.__name__}") + self.logger = logging.getLogger(f"netbox.scripts.{self.__module__}.{self.__class__.__name__}") self.log = [] # Declare the placeholder for the current request @@ -280,22 +280,26 @@ class BaseScript: def __str__(self): return self.name + @classproperty + def module(self): + return self.__module__ + + @classproperty + def class_name(self): + return self.__name__ + + @classproperty + def full_name(self): + return f'{self.module}.{self.class_name}' + @classproperty def name(self): return getattr(self.Meta, 'name', self.__name__) - @classproperty - def full_name(self): - return '.'.join([self.__module__, self.__name__]) - @classproperty def description(self): return getattr(self.Meta, 'description', '') - @classmethod - def module(cls): - return cls.__module__ - @classmethod def root_module(cls): return cls.__module__.split(".")[0] diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 3d9419263..0a441b6fd 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -852,20 +852,17 @@ class ReportView(ContentTypePermissionRequiredMixin, View): ).first() return render(request, 'extras/report.html', { + 'module': module, 'report': report, 'form': ReportForm(), }) def post(self, request, module, name): - - # Permissions check if not request.user.has_perm('extras.run_report'): return HttpResponseForbidden() - report = get_report(module, name) - if report is None: - raise Http404 - + module = get_object_or_404(ReportModule.objects.restrict(request.user), file_path=f'{module}.py') + report = module.reports[name]() form = ReportForm(request.POST) if form.is_valid(): @@ -891,6 +888,7 @@ class ReportView(ContentTypePermissionRequiredMixin, View): return redirect('extras:report_result', job_result_pk=job_result.pk) return render(request, 'extras/report.html', { + 'module': module, 'report': report, 'form': form, }) diff --git a/netbox/templates/extras/report.html b/netbox/templates/extras/report.html index a3876d319..382c0669f 100644 --- a/netbox/templates/extras/report.html +++ b/netbox/templates/extras/report.html @@ -10,7 +10,7 @@ {% block breadcrumbs %}