fhrp.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
  2. from django.core.validators import MaxValueValidator, MinValueValidator
  3. from django.db import models
  4. from django.utils.translation import gettext_lazy as _
  5. from ipam.choices import *
  6. from ipam.constants import *
  7. from netbox.models import ChangeLoggedModel, PrimaryModel
  8. __all__ = (
  9. 'FHRPGroup',
  10. 'FHRPGroupAssignment',
  11. )
  12. class FHRPGroup(PrimaryModel):
  13. """
  14. A grouping of next hope resolution protocol (FHRP) peers. (For instance, VRRP or HSRP.)
  15. """
  16. group_id = models.PositiveSmallIntegerField(
  17. verbose_name=_('group ID')
  18. )
  19. name = models.CharField(
  20. verbose_name=_('name'),
  21. max_length=100,
  22. blank=True
  23. )
  24. protocol = models.CharField(
  25. verbose_name=_('protocol'),
  26. max_length=50,
  27. choices=FHRPGroupProtocolChoices
  28. )
  29. auth_type = models.CharField(
  30. max_length=50,
  31. choices=FHRPGroupAuthTypeChoices,
  32. blank=True,
  33. null=True,
  34. verbose_name=_('authentication type')
  35. )
  36. auth_key = models.CharField(
  37. max_length=255,
  38. blank=True,
  39. verbose_name=_('authentication key')
  40. )
  41. ip_addresses = GenericRelation(
  42. to='ipam.IPAddress',
  43. content_type_field='assigned_object_type',
  44. object_id_field='assigned_object_id',
  45. related_query_name='fhrpgroup'
  46. )
  47. services = GenericRelation(
  48. to='ipam.Service',
  49. content_type_field='parent_object_type',
  50. object_id_field='parent_object_id',
  51. related_query_name='fhrpgroup',
  52. )
  53. clone_fields = ('protocol', 'auth_type', 'auth_key', 'description')
  54. class Meta:
  55. ordering = ['protocol', 'group_id', 'pk']
  56. indexes = (
  57. models.Index(fields=('protocol', 'group_id', 'id')), # Default ordering
  58. )
  59. verbose_name = _('FHRP group')
  60. verbose_name_plural = _('FHRP groups')
  61. def __str__(self):
  62. name = ''
  63. if self.name:
  64. name = f'{self.name} '
  65. name += f'{self.get_protocol_display()}: {self.group_id}'
  66. # Append the first assigned IP addresses (if any) to serve as an additional identifier
  67. if self.pk:
  68. ip_address = self.ip_addresses.first()
  69. if ip_address:
  70. return f"{name} ({ip_address})"
  71. return name
  72. class FHRPGroupAssignment(ChangeLoggedModel):
  73. interface_type = models.ForeignKey(
  74. to='contenttypes.ContentType',
  75. on_delete=models.CASCADE
  76. )
  77. interface_id = models.PositiveBigIntegerField()
  78. interface = GenericForeignKey(
  79. ct_field='interface_type',
  80. fk_field='interface_id'
  81. )
  82. group = models.ForeignKey(
  83. to='ipam.FHRPGroup',
  84. on_delete=models.CASCADE
  85. )
  86. priority = models.PositiveSmallIntegerField(
  87. verbose_name=_('priority'),
  88. validators=(
  89. MinValueValidator(FHRPGROUPASSIGNMENT_PRIORITY_MIN),
  90. MaxValueValidator(FHRPGROUPASSIGNMENT_PRIORITY_MAX)
  91. )
  92. )
  93. clone_fields = ('interface_type', 'interface_id')
  94. class Meta:
  95. ordering = ('-priority', 'pk')
  96. indexes = (
  97. models.Index(fields=('-priority', 'id')), # Default ordering
  98. models.Index(fields=('interface_type', 'interface_id')),
  99. )
  100. constraints = (
  101. models.UniqueConstraint(
  102. fields=('interface_type', 'interface_id', 'group'),
  103. name='%(app_label)s_%(class)s_unique_interface_group'
  104. ),
  105. )
  106. verbose_name = _('FHRP group assignment')
  107. verbose_name_plural = _('FHRP group assignments')
  108. def __str__(self):
  109. return f'{self.interface}: {self.group} ({self.priority})'
  110. def get_absolute_url(self):
  111. # Used primarily for redirection after creating a new assignment
  112. if self.interface:
  113. return self.interface.get_absolute_url()
  114. return None