Rename FHRPGroupAssignment object to interface

This commit is contained in:
jeremystretch 2021-11-02 15:10:02 -04:00
parent 264652f2c3
commit 131e433880
14 changed files with 54 additions and 45 deletions

View File

@ -601,9 +601,9 @@ class Interface(ComponentModel, BaseInterface, LinkTermination, PathEndpoint):
) )
fhrp_group_assignments = GenericRelation( fhrp_group_assignments = GenericRelation(
to='ipam.FHRPGroupAssignment', to='ipam.FHRPGroupAssignment',
content_type_field='content_type', content_type_field='interface_type',
object_id_field='object_id', object_id_field='interface_id',
related_query_name='interface' related_query_name='+'
) )
clone_fields = ['device', 'parent', 'bridge', 'lag', 'type', 'mgmt_only'] clone_fields = ['device', 'parent', 'bridge', 'lag', 'type', 'mgmt_only']

View File

@ -110,24 +110,25 @@ class FHRPGroupSerializer(PrimaryModelSerializer):
class FHRPGroupAssignmentSerializer(PrimaryModelSerializer): class FHRPGroupAssignmentSerializer(PrimaryModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:contactassignment-detail') url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:contactassignment-detail')
content_type = ContentTypeField( interface_type = ContentTypeField(
queryset=ContentType.objects.all() queryset=ContentType.objects.all()
) )
object = serializers.SerializerMethodField(read_only=True) interface = serializers.SerializerMethodField(read_only=True)
class Meta: class Meta:
model = FHRPGroupAssignment model = FHRPGroupAssignment
fields = [ fields = [
'id', 'url', 'display', 'content_type', 'object_id', 'object', 'priority', 'created', 'last_updated', 'id', 'url', 'display', 'interface_type', 'interface_id', 'interface', 'priority', 'created',
'last_updated',
] ]
@swagger_serializer_method(serializer_or_field=serializers.DictField) @swagger_serializer_method(serializer_or_field=serializers.DictField)
def get_object(self, obj): def get_interface(self, obj):
if obj.object is None: if obj.interface is None:
return None return None
serializer = get_serializer_for_model(obj.object, prefix='Nested') serializer = get_serializer_for_model(obj.interface, prefix='Nested')
context = {'request': self.context['request']} context = {'request': self.context['request']}
return serializer(obj.object, context=context).data return serializer(obj.interface, context=context).data
# #

View File

@ -130,7 +130,7 @@ class FHRPGroupViewSet(CustomFieldModelViewSet):
class FHRPGroupAssignmentViewSet(CustomFieldModelViewSet): class FHRPGroupAssignmentViewSet(CustomFieldModelViewSet):
queryset = FHRPGroupAssignment.objects.prefetch_related('group', 'object') queryset = FHRPGroupAssignment.objects.prefetch_related('group', 'interface')
serializer_class = serializers.FHRPGroupAssignmentSerializer serializer_class = serializers.FHRPGroupAssignmentSerializer
filterset_class = filtersets.FHRPGroupAssignmentFilterSet filterset_class = filtersets.FHRPGroupAssignmentFilterSet

View File

@ -663,11 +663,15 @@ class FHRPGroupFilterSet(PrimaryModelFilterSet):
class FHRPGroupAssignmentFilterSet(ChangeLoggedModelFilterSet): class FHRPGroupAssignmentFilterSet(ChangeLoggedModelFilterSet):
content_type = ContentTypeFilter() interface_type = ContentTypeFilter()
group_id = django_filters.ModelMultipleChoiceFilter(
queryset=FHRPGroup.objects.all(),
label='Group (ID)',
)
class Meta: class Meta:
model = FHRPGroupAssignment model = FHRPGroupAssignment
fields = ['id', 'content_type_id', 'priority'] fields = ['id', 'group_id', 'interface_type', 'interface_id', 'priority']
class VLANGroupFilterSet(OrganizationalModelFilterSet): class VLANGroupFilterSet(OrganizationalModelFilterSet):

View File

@ -543,7 +543,7 @@ class FHRPGroupAssignmentForm(BootstrapMixin, forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
ipaddresses = self.instance.object.ip_addresses.all() ipaddresses = self.instance.interface.ip_addresses.all()
for ipaddress in ipaddresses: for ipaddress in ipaddresses:
self.fields['group'].widget.add_query_param('related_ip', ipaddress.pk) self.fields['group'].widget.add_query_param('related_ip', ipaddress.pk)

View File

@ -8,8 +8,8 @@ import taggit.managers
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('extras', '0064_configrevision'),
('contenttypes', '0002_remove_content_type_name'), ('contenttypes', '0002_remove_content_type_name'),
('extras', '0064_configrevision'),
('ipam', '0051_extend_tag_support'), ('ipam', '0051_extend_tag_support'),
] ]
@ -44,15 +44,15 @@ class Migration(migrations.Migration):
('created', models.DateField(auto_now_add=True, null=True)), ('created', models.DateField(auto_now_add=True, null=True)),
('last_updated', models.DateTimeField(auto_now=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)),
('id', models.BigAutoField(primary_key=True, serialize=False)), ('id', models.BigAutoField(primary_key=True, serialize=False)),
('object_id', models.PositiveIntegerField()), ('interface_id', models.PositiveIntegerField()),
('priority', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(255)])), ('priority', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(255)])),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ipam.fhrpgroup')), ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ipam.fhrpgroup')),
('interface_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')),
], ],
options={ options={
'verbose_name': 'FHRP group assignment', 'verbose_name': 'FHRP group assignment',
'ordering': ('priority', 'pk'), 'ordering': ('priority', 'pk'),
'unique_together': {('content_type', 'object_id', 'group')}, 'unique_together': {('interface_type', 'interface_id', 'group')},
}, },
), ),
] ]

View File

@ -69,14 +69,14 @@ class FHRPGroup(PrimaryModel):
@extras_features('webhooks') @extras_features('webhooks')
class FHRPGroupAssignment(ChangeLoggedModel): class FHRPGroupAssignment(ChangeLoggedModel):
content_type = models.ForeignKey( interface_type = models.ForeignKey(
to=ContentType, to=ContentType,
on_delete=models.CASCADE on_delete=models.CASCADE
) )
object_id = models.PositiveIntegerField() interface_id = models.PositiveIntegerField()
object = GenericForeignKey( interface = GenericForeignKey(
ct_field='content_type', ct_field='interface_type',
fk_field='object_id' fk_field='interface_id'
) )
group = models.ForeignKey( group = models.ForeignKey(
to='ipam.FHRPGroup', to='ipam.FHRPGroup',
@ -93,8 +93,8 @@ class FHRPGroupAssignment(ChangeLoggedModel):
class Meta: class Meta:
ordering = ('priority', 'pk') ordering = ('priority', 'pk')
unique_together = ('content_type', 'object_id', 'group') unique_together = ('interface_type', 'interface_id', 'group')
verbose_name = 'FHRP group assignment' verbose_name = 'FHRP group assignment'
def __str__(self): def __str__(self):
return f'{self.object}: {self.group} ({self.priority})' return f'{self.interface}: {self.group} ({self.priority})'

View File

@ -27,8 +27,8 @@ class FHRPGroupTable(BaseTable):
orderable=False, orderable=False,
verbose_name='IP Addresses' verbose_name='IP Addresses'
) )
member_count = tables.Column( interface_count = tables.Column(
verbose_name='Members' verbose_name='Interfaces'
) )
tags = TagColumn( tags = TagColumn(
url_name='ipam:fhrpgroup_list' url_name='ipam:fhrpgroup_list'
@ -37,10 +37,10 @@ class FHRPGroupTable(BaseTable):
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):
model = FHRPGroup model = FHRPGroup
fields = ( fields = (
'pk', 'group_id', 'protocol', 'auth_type', 'auth_key', 'description', 'ip_addresses', 'member_count', 'pk', 'group_id', 'protocol', 'auth_type', 'auth_key', 'description', 'ip_addresses', 'interface_count',
'tags', 'tags',
) )
default_columns = ('pk', 'group_id', 'protocol', 'auth_type', 'description', 'ip_addresses', 'member_count') default_columns = ('pk', 'group_id', 'protocol', 'auth_type', 'description', 'ip_addresses', 'interface_count')
class FHRPGroupAssignmentTable(BaseTable): class FHRPGroupAssignmentTable(BaseTable):
@ -51,7 +51,7 @@ class FHRPGroupAssignmentTable(BaseTable):
orderable=False, orderable=False,
verbose_name='Parent' verbose_name='Parent'
) )
object = tables.Column( interface = tables.Column(
linkify=True, linkify=True,
orderable=False orderable=False
) )
@ -65,4 +65,4 @@ class FHRPGroupAssignmentTable(BaseTable):
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):
model = FHRPGroupAssignment model = FHRPGroupAssignment
fields = ('pk', 'group', 'object_parent', 'object', 'priority') fields = ('pk', 'group', 'object_parent', 'interface', 'priority')

View File

@ -914,24 +914,24 @@ class FHRPGroupAssignmentEditView(generic.ObjectEditView):
def alter_obj(self, instance, request, args, kwargs): def alter_obj(self, instance, request, args, kwargs):
if not instance.pk: if not instance.pk:
# Assign the object based on URL kwargs # Assign the interface based on URL kwargs
try: try:
app_label, model = request.GET.get('content_type').split('.') app_label, model = request.GET.get('interface_type').split('.')
except (AttributeError, ValueError): except (AttributeError, ValueError):
raise Http404("Content type not specified") raise Http404("Content type not specified")
content_type = get_object_or_404(ContentType, app_label=app_label, model=model) content_type = get_object_or_404(ContentType, app_label=app_label, model=model)
instance.object = get_object_or_404(content_type.model_class(), pk=request.GET.get('object_id')) instance.interface = get_object_or_404(content_type.model_class(), pk=request.GET.get('interface_id'))
return instance return instance
def get_return_url(self, request, obj=None): def get_return_url(self, request, obj=None):
return obj.object.get_absolute_url() if obj else super().get_return_url(request) return obj.interface.get_absolute_url() if obj else super().get_return_url(request)
class FHRPGroupAssignmentDeleteView(generic.ObjectDeleteView): class FHRPGroupAssignmentDeleteView(generic.ObjectDeleteView):
queryset = FHRPGroupAssignment.objects.all() queryset = FHRPGroupAssignment.objects.all()
def get_return_url(self, request, obj=None): def get_return_url(self, request, obj=None):
return obj.object.get_absolute_url() if obj else super().get_return_url(request) return obj.interface.get_absolute_url() if obj else super().get_return_url(request)
# #

View File

@ -459,7 +459,7 @@
</div> </div>
{% if perms.ipam.add_ipaddress %} {% if perms.ipam.add_ipaddress %}
<div class="card-footer text-end noprint"> <div class="card-footer text-end noprint">
<a href="{% url 'ipam:ipaddress_add' %}?device={{ object.device.pk }}&interface={{ object.pk }}" class="btn btn-sm btn-primary"> <a href="{% url 'ipam:ipaddress_add' %}?device={{ object.device.pk }}&interface={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add IP Address <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add IP Address
</a> </a>
</div> </div>

View File

@ -9,7 +9,7 @@
<div class="row mb-3"> <div class="row mb-3">
<label class="col-sm-3 col-form-label text-lg-end">Interface</label> <label class="col-sm-3 col-form-label text-lg-end">Interface</label>
<div class="col"> <div class="col">
<input class="form-control" value="{{ form.instance.object }}" disabled /> <input class="form-control" value="{{ form.instance.interface }}" disabled />
</div> </div>
</div> </div>
{% render_field form.group %} {% render_field form.group %}

View File

@ -7,6 +7,7 @@
<thead> <thead>
<tr> <tr>
<th>Group</th> <th>Group</th>
<th>Protocol</th>
<th>Virtual IPs</th> <th>Virtual IPs</th>
<th>Priority</th> <th>Priority</th>
</tr> </tr>
@ -15,7 +16,10 @@
{% for assignment in object.fhrp_group_assignments.all %} {% for assignment in object.fhrp_group_assignments.all %}
<tr> <tr>
<td> <td>
<a href="{{ assignment.group.get_absolute_url }}">{{ assignment.group }}</a> <a href="{{ assignment.group.get_absolute_url }}">{{ assignment.group.group_id }}</a>
</td>
<td>
{{ assignment.group.get_protocol_display }}
</td> </td>
<td> <td>
{% for ipaddress in assignment.group.ip_addresses.all %} {% for ipaddress in assignment.group.ip_addresses.all %}
@ -37,12 +41,12 @@
</div> </div>
<div class="card-footer text-end noprint"> <div class="card-footer text-end noprint">
{% if perms.ipam.add_fhrpgroup %} {% if perms.ipam.add_fhrpgroup %}
<a href="{% url 'ipam:fhrpgroup_add' %}?return_url={% url 'ipam:fhrpgroupassignment_add' %}%3Fcontent_type={{ object|meta:"app_label" }}.{{ object|meta:"model_name" }}%26object_id={{ object.pk }}" class="btn btn-sm btn-primary"> <a href="{% url 'ipam:fhrpgroup_add' %}?return_url={% url 'ipam:fhrpgroupassignment_add' %}%3Finterface_type={{ object|meta:"app_label" }}.{{ object|meta:"model_name" }}%26interface_id={{ object.pk }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Create Group <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Create Group
</a> </a>
{% endif %} {% endif %}
{% if perms.ipam.add_fhrpgroupassignment %} {% if perms.ipam.add_fhrpgroupassignment %}
<a href="{% url 'ipam:fhrpgroupassignment_add' %}?content_type={{ object|meta:"app_label" }}.{{ object|meta:"model_name" }}&object_id={{ object.pk }}" class="btn btn-sm btn-primary"> <a href="{% url 'ipam:fhrpgroupassignment_add' %}?interface_type={{ object|meta:"app_label" }}.{{ object|meta:"model_name" }}&interface_id={{ object.pk }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Assign Group <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Assign Group
</a> </a>
{% endif %} {% endif %}

View File

@ -100,7 +100,7 @@
</div> </div>
{% if perms.ipam.add_ipaddress %} {% if perms.ipam.add_ipaddress %}
<div class="card-footer text-end noprint"> <div class="card-footer text-end noprint">
<a href="{% url 'ipam:ipaddress_add' %}?virtual_machine={{ object.virtual_machine.pk }}&vminterface={{ object.pk }}" class="btn btn-sm btn-primary"> <a href="{% url 'ipam:ipaddress_add' %}?virtual_machine={{ object.virtual_machine.pk }}&vminterface={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add IP Address <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add IP Address
</a> </a>
</div> </div>

View File

@ -400,9 +400,9 @@ class VMInterface(PrimaryModel, BaseInterface):
) )
fhrp_group_assignments = GenericRelation( fhrp_group_assignments = GenericRelation(
to='ipam.FHRPGroupAssignment', to='ipam.FHRPGroupAssignment',
content_type_field='content_type', content_type_field='interface_type',
object_id_field='object_id', object_id_field='interface_id',
related_query_name='vminterface' related_query_name='+'
) )
objects = RestrictedQuerySet.as_manager() objects = RestrictedQuerySet.as_manager()