scripts.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import inspect
  2. import logging
  3. from functools import cached_property
  4. from django.db import models
  5. from django.urls import reverse
  6. from core.choices import ManagedFileRootPathChoices
  7. from core.models import ManagedFile
  8. from extras.utils import is_script
  9. from netbox.models.features import JobsMixin, WebhooksMixin
  10. from utilities.querysets import RestrictedQuerySet
  11. from .mixins import PythonModuleMixin
  12. __all__ = (
  13. 'Script',
  14. 'ScriptModule',
  15. )
  16. logger = logging.getLogger('netbox.data_backends')
  17. class Script(WebhooksMixin, models.Model):
  18. """
  19. Dummy model used to generate permissions for custom scripts. Does not exist in the database.
  20. """
  21. class Meta:
  22. managed = False
  23. class ScriptModuleManager(models.Manager.from_queryset(RestrictedQuerySet)):
  24. def get_queryset(self):
  25. return super().get_queryset().filter(file_root=ManagedFileRootPathChoices.SCRIPTS)
  26. class ScriptModule(PythonModuleMixin, JobsMixin, ManagedFile):
  27. """
  28. Proxy model for script module files.
  29. """
  30. objects = ScriptModuleManager()
  31. class Meta:
  32. proxy = True
  33. def get_absolute_url(self):
  34. return reverse('extras:script_list')
  35. def __str__(self):
  36. return self.python_name
  37. @cached_property
  38. def scripts(self):
  39. def _get_name(cls):
  40. # For child objects in submodules use the full import path w/o the root module as the name
  41. return cls.full_name.split(".", maxsplit=1)[1]
  42. try:
  43. module = self.get_module()
  44. except Exception as e:
  45. logger.debug(f"Failed to load script: {self.python_name} error: {e}")
  46. module = None
  47. scripts = {}
  48. ordered = getattr(module, 'script_order', [])
  49. for cls in ordered:
  50. scripts[_get_name(cls)] = cls
  51. for name, cls in inspect.getmembers(module, is_script):
  52. if cls not in ordered:
  53. scripts[_get_name(cls)] = cls
  54. return scripts
  55. def save(self, *args, **kwargs):
  56. self.file_root = ManagedFileRootPathChoices.SCRIPTS
  57. return super().save(*args, **kwargs)