diff --git a/Makefile b/Makefile index 4ba0fb6..71cd4d0 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -PYTHON_VER?=3.7 -NETBOX_VER?=v3.1.5 +PYTHON_VER?=3.8 +NETBOX_VER?=v3.2.0 NAME=netbox-bgp diff --git a/README.md b/README.md index ec14fa9..a3d0e60 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ | NetBox 2.11 | 0.3.9 | | NetBox 3.0 | 0.4.3 | | NetBox 3.1 | 0.5.0 | +| NetBox 3.2 | 0.6.0 | ## Installation diff --git a/netbox_bgp/__init__.py b/netbox_bgp/__init__.py index 47981bc..7cf922c 100644 --- a/netbox_bgp/__init__.py +++ b/netbox_bgp/__init__.py @@ -11,8 +11,8 @@ class BGPConfig(PluginConfig): author_email = 'mgk.kolek@gmail.com' base_url = 'bgp' required_settings = [] - min_version = '3.1.0' - max_version = '3.1.99' + min_version = '3.2.0' + max_version = '3.2.99' default_settings = { 'device_ext_page': 'right', 'asdot': False diff --git a/netbox_bgp/api/serializers.py b/netbox_bgp/api/serializers.py index c8415a4..808705b 100644 --- a/netbox_bgp/api/serializers.py +++ b/netbox_bgp/api/serializers.py @@ -2,52 +2,19 @@ from rest_framework.relations import PrimaryKeyRelatedField from netbox.api import ChoiceField, WritableNestedSerializer, ValidatedModelSerializer +from netbox.api.serializers import NetBoxModelSerializer from dcim.api.nested_serializers import NestedSiteSerializer, NestedDeviceSerializer from tenancy.api.nested_serializers import NestedTenantSerializer from extras.api.nested_serializers import NestedTagSerializer from ipam.api.nested_serializers import NestedIPAddressSerializer -try: - from extras.api.customfields import CustomFieldModelSerializer -except ImportError: - from netbox.api.serializers import CustomFieldModelSerializer - from netbox_bgp.models import ( ASN, ASNStatusChoices, BGPSession, SessionStatusChoices, RoutingPolicy, BGPPeerGroup, Community ) -class TaggedObjectSerializer(Serializer): - tags = NestedTagSerializer(many=True, required=False) - - def create(self, validated_data): - tags = validated_data.pop('tags', None) - instance = super().create(validated_data) - - if tags is not None: - return self._save_tags(instance, tags) - return instance - - def update(self, instance, validated_data): - tags = validated_data.pop('tags', None) - # Cache tags on instance for change logging - instance._tags = tags or [] - - instance = super().update(instance, validated_data) - if tags is not None: - return self._save_tags(instance, tags) - return instance - - def _save_tags(self, instance, tags): - if tags: - instance.tags.set(*[t.name for t in tags]) - else: - instance.tags.clear() - return instance - - class SerializedPKRelatedField(PrimaryKeyRelatedField): def __init__(self, serializer, **kwargs): self.serializer = serializer @@ -58,7 +25,7 @@ def to_representation(self, value): return self.serializer(value, context={'request': self.context['request']}).data -class ASNSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): +class ASNSerializer(NetBoxModelSerializer): status = ChoiceField(choices=ASNStatusChoices, required=False) site = NestedSiteSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True) @@ -91,21 +58,21 @@ class Meta: fields = ['id', 'url', 'number', 'description'] -class RoutingPolicySerializer(TaggedObjectSerializer, CustomFieldModelSerializer): +class RoutingPolicySerializer(NetBoxModelSerializer): class Meta: model = RoutingPolicy fields = '__all__' class NestedRoutingPolicySerializer(WritableNestedSerializer): - url = HyperlinkedIdentityField(view_name='plugins:netbox_bgp:routing_policy') + url = HyperlinkedIdentityField(view_name='plugins:netbox_bgp:routingpolicy') class Meta: model = RoutingPolicy fields = ['id', 'url', 'name', 'description'] -class BGPPeerGroupSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): +class BGPPeerGroupSerializer(NetBoxModelSerializer): import_policies = SerializedPKRelatedField( queryset=RoutingPolicy.objects.all(), serializer=NestedRoutingPolicySerializer, @@ -127,7 +94,7 @@ class Meta: class NestedBGPPeerGroupSerializer(WritableNestedSerializer): - url = HyperlinkedIdentityField(view_name='plugins:netbox_bgp:peergroup') + url = HyperlinkedIdentityField(view_name='plugins:netbox_bgp:bgppeergroup') class Meta: model = BGPPeerGroup @@ -135,7 +102,7 @@ class Meta: validators = [] -class BGPSessionSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): +class BGPSessionSerializer(NetBoxModelSerializer): status = ChoiceField(choices=SessionStatusChoices, required=False) site = NestedSiteSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True) @@ -195,7 +162,7 @@ def to_representation(self, instance): return ret -class CommunitySerializer(TaggedObjectSerializer, ValidatedModelSerializer): +class CommunitySerializer(NetBoxModelSerializer): status = ChoiceField(choices=ASNStatusChoices, required=False) tenant = NestedTenantSerializer(required=False, allow_null=True) diff --git a/netbox_bgp/forms.py b/netbox_bgp/forms.py index f6edf91..76ec0f1 100644 --- a/netbox_bgp/forms.py +++ b/netbox_bgp/forms.py @@ -15,9 +15,7 @@ DynamicModelMultipleChoiceField, StaticSelect, APISelect, APISelectMultiple, StaticSelectMultiple, TagFilterField ) -from extras.forms import ( - CustomFieldModelForm, CustomFieldBulkEditForm, CustomFieldModelFilterForm -) +from netbox.forms import NetBoxModelForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from .models import ( ASN, ASNStatusChoices, Community, BGPSession, @@ -68,7 +66,7 @@ def render(self, name, value, attrs=None, renderer=None): return super().render(name, value, attrs, renderer) -class ASNFilterForm(CustomFieldModelFilterForm): +class ASNFilterForm(NetBoxModelFilterSetForm): model = ASN q = forms.CharField( required=False, @@ -91,7 +89,7 @@ class ASNFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class ASNForm(CustomFieldModelForm): +class ASNForm(NetBoxModelForm): number = ASNField( widget=ASdotInput ) @@ -103,6 +101,11 @@ class ASNForm(CustomFieldModelForm): queryset=Site.objects.all(), required=False ) + status = forms.ChoiceField( + required=False, + choices=ASNStatusChoices, + widget=StaticSelect() + ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), required=False @@ -126,7 +129,7 @@ class Meta: ] -class ASNBulkEditForm(CustomFieldBulkEditForm): +class ASNBulkEditForm(NetBoxModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=ASN.objects.all(), widget=forms.MultipleHiddenInput @@ -145,10 +148,13 @@ class ASNBulkEditForm(CustomFieldBulkEditForm): widget=StaticSelect() ) - class Meta: - nullable_fields = [ - 'tenant', 'description', - ] + model = ASN + fieldsets = ( + (None, ('tenant', 'description', 'status')), + ) + nullable_fields = ( + 'tenant', 'description', + ) class CommunityForm(BootstrapMixin, forms.ModelForm): @@ -156,6 +162,11 @@ class CommunityForm(BootstrapMixin, forms.ModelForm): queryset=Tag.objects.all(), required=False ) + status = forms.ChoiceField( + required=False, + choices=ASNStatusChoices, + widget=StaticSelect() + ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), required=False @@ -219,7 +230,7 @@ class Meta: ] -class BGPSessionForm(CustomFieldModelForm): +class BGPSessionForm(NetBoxModelForm): name = forms.CharField( max_length=64, required=True @@ -325,7 +336,7 @@ def clean_remote_address(self): return self.cleaned_data['remote_address'] -class BGPSessionFilterForm(CustomFieldModelFilterForm): +class BGPSessionFilterForm(NetBoxModelFilterSetForm): model = BGPSession q = forms.CharField( required=False, @@ -394,7 +405,7 @@ class BGPSessionFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class RoutingPolicyFilterForm(CustomFieldModelFilterForm): +class RoutingPolicyFilterForm(NetBoxModelFilterSetForm): model = RoutingPolicy q = forms.CharField( required=False, @@ -404,7 +415,7 @@ class RoutingPolicyFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class RoutingPolicyForm(CustomFieldModelForm): +class RoutingPolicyForm(NetBoxModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -415,7 +426,7 @@ class Meta: fields = ['name', 'description'] -class BGPPeerGroupFilterForm(CustomFieldModelFilterForm): +class BGPPeerGroupFilterForm(NetBoxModelFilterSetForm): model = BGPPeerGroup q = forms.CharField( required=False, @@ -425,7 +436,7 @@ class BGPPeerGroupFilterForm(CustomFieldModelFilterForm): tag = TagFilterField(model) -class BGPPeerGroupForm(CustomFieldModelForm): +class BGPPeerGroupForm(NetBoxModelForm): import_policies = DynamicModelMultipleChoiceField( queryset=RoutingPolicy.objects.all(), required=False, diff --git a/netbox_bgp/migrations/0021_netbox32_support.py b/netbox_bgp/migrations/0021_netbox32_support.py new file mode 100644 index 0000000..b89454a --- /dev/null +++ b/netbox_bgp/migrations/0021_netbox32_support.py @@ -0,0 +1,95 @@ +# Generated by Django 4.0.2 on 2022-02-24 20:04 + +import django.core.serializers.json +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0153_created_datetimefield'), + ('netbox_bgp', '0020_netbox_bgp'), + ] + + operations = [ + migrations.AlterModelOptions( + name='asn', + options={'verbose_name': 'AS Number', 'verbose_name_plural': 'AS Numbers'}, + ), + migrations.AddField( + model_name='community', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AlterField( + model_name='asn', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='asn', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='asn', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='%(class)s_related', to='dcim.site'), + ), + migrations.AlterField( + model_name='asngroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='asngroup', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='bgppeergroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='bgppeergroup', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='bgpsession', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='bgpsession', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='community', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='community', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='community', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='%(class)s_related', to='dcim.site'), + ), + migrations.AlterField( + model_name='routingpolicy', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='routingpolicy', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False), + ), + ] diff --git a/netbox_bgp/models.py b/netbox_bgp/models.py index da7d528..af8429c 100644 --- a/netbox_bgp/models.py +++ b/netbox_bgp/models.py @@ -6,13 +6,8 @@ from taggit.managers import TaggableManager from utilities.choices import ChoiceSet -from utilities.querysets import RestrictedQuerySet -from netbox.models import ChangeLoggedModel - -from netbox.models import CustomFieldsMixin as CustomFieldModel - -from extras.models import TaggedItem -from extras.utils import extras_features +from netbox.models import NetBoxModel +from netbox.models.features import ChangeLoggingMixin class ASNStatusChoices(ChoiceSet): @@ -22,17 +17,11 @@ class ASNStatusChoices(ChoiceSet): STATUS_DEPRECATED = 'deprecated' CHOICES = ( - (STATUS_ACTIVE, 'Active'), - (STATUS_RESERVED, 'Reserved'), - (STATUS_DEPRECATED, 'Deprecated'), + (STATUS_ACTIVE, 'Active', 'blue'), + (STATUS_RESERVED, 'Reserved', 'cyan'), + (STATUS_DEPRECATED, 'Deprecated', 'red'), ) - CSS_CLASSES = { - STATUS_ACTIVE: 'primary', - STATUS_RESERVED: 'info', - STATUS_DEPRECATED: 'danger', - } - class SessionStatusChoices(ChoiceSet): @@ -42,21 +31,14 @@ class SessionStatusChoices(ChoiceSet): STATUS_FAILED = 'failed' CHOICES = ( - (STATUS_OFFLINE, 'Offline'), - (STATUS_ACTIVE, 'Active'), - (STATUS_PLANNED, 'Planned'), - (STATUS_FAILED, 'Failed'), + (STATUS_OFFLINE, 'Offline', 'orange'), + (STATUS_ACTIVE, 'Active', 'green'), + (STATUS_PLANNED, 'Planned', 'cyan'), + (STATUS_FAILED, 'Failed', 'red'), ) - CSS_CLASSES = { - STATUS_OFFLINE: 'warning', - STATUS_ACTIVE: 'success', - STATUS_PLANNED: 'info', - STATUS_FAILED: 'danger', - } - -class ASNGroup(ChangeLoggedModel): +class ASNGroup(ChangeLoggingMixin, models.Model): """ """ name = models.CharField( @@ -77,8 +59,7 @@ def __str__(self): return self.name -@extras_features('custom_fields', 'export_templates', 'webhooks') -class RoutingPolicy(ChangeLoggedModel, CustomFieldModel): +class RoutingPolicy(NetBoxModel): """ """ name = models.CharField( @@ -89,10 +70,6 @@ class RoutingPolicy(ChangeLoggedModel, CustomFieldModel): blank=True ) - tags = TaggableManager(through=TaggedItem) - - objects = RestrictedQuerySet.as_manager() - class Meta: verbose_name_plural = 'Routing Policies' unique_together = ['name', 'description'] @@ -101,11 +78,10 @@ def __str__(self): return self.name def get_absolute_url(self): - return reverse('plugins:netbox_bgp:routing_policy', args=[self.pk]) + return reverse('plugins:netbox_bgp:routingpolicy', args=[self.pk]) -@extras_features('custom_fields', 'export_templates', 'webhooks') -class BGPPeerGroup(ChangeLoggedModel, CustomFieldModel): +class BGPPeerGroup(NetBoxModel): """ """ name = models.CharField( @@ -126,10 +102,6 @@ class BGPPeerGroup(ChangeLoggedModel, CustomFieldModel): related_name='group_export_policies' ) - tags = TaggableManager(through=TaggedItem) - - objects = RestrictedQuerySet.as_manager() - class Meta: verbose_name_plural = 'Peer Groups' unique_together = ['name', 'description'] @@ -138,10 +110,10 @@ def __str__(self): return self.name def get_absolute_url(self): - return reverse('plugins:netbox_bgp:peergroup', args=[self.pk]) + return reverse('plugins:netbox_bgp:bgppeergroup', args=[self.pk]) -class BGPBase(ChangeLoggedModel): +class BGPBase(NetBoxModel): """ """ site = models.ForeignKey( @@ -172,16 +144,12 @@ class BGPBase(ChangeLoggedModel): max_length=200, blank=True ) - tags = TaggableManager(through=TaggedItem) - - objects = RestrictedQuerySet.as_manager() class Meta: abstract = True -@extras_features('custom_fields', 'export_templates', 'webhooks') -class ASN(BGPBase, CustomFieldModel): +class ASN(BGPBase): number = models.PositiveBigIntegerField( validators=[MinValueValidator(1), MaxValueValidator(4294967295)] @@ -194,11 +162,12 @@ class ASN(BGPBase, CustomFieldModel): null=True ) - tags = TaggableManager(through=TaggedItem, related_name='asn_tags') + tags = TaggableManager(through='extras.TaggedItem', related_name='asn_tags') clone_fields = ['description', 'status', 'tenant'] class Meta: + verbose_name = 'AS Number' verbose_name_plural = 'AS Numbers' constraints = [ models.UniqueConstraint( @@ -213,8 +182,8 @@ class Meta: ] # unique_together = ['number', 'site', 'tenant'] - def get_status_class(self): - return ASNStatusChoices.CSS_CLASSES.get(self.status) + def get_status_color(self): + return ASNStatusChoices.colors.get(self.status) def get_absolute_url(self): return reverse('plugins:netbox_bgp:asn', args=[self.pk]) @@ -233,7 +202,6 @@ def __str__(self): return str(self.number) -@extras_features('export_templates', 'webhooks') class Community(BGPBase): """ """ @@ -248,15 +216,14 @@ class Meta: def __str__(self): return self.value - def get_status_class(self): - return ASNStatusChoices.CSS_CLASSES.get(self.status) + def get_status_color(self): + return ASNStatusChoices.colors.get(self.status) def get_absolute_url(self): return reverse('plugins:netbox_bgp:community', args=[self.pk]) -@extras_features('custom_fields', 'export_templates', 'webhooks') -class BGPSession(ChangeLoggedModel, CustomFieldModel): +class BGPSession(NetBoxModel): name = models.CharField( max_length=64, blank=True, @@ -327,10 +294,6 @@ class BGPSession(ChangeLoggedModel, CustomFieldModel): afi_safi = None # for future use - tags = TaggableManager(through=TaggedItem) - - objects = RestrictedQuerySet.as_manager() - class Meta: verbose_name_plural = 'BGP Sessions' unique_together = ['device', 'local_address', 'local_as', 'remote_address', 'remote_as'] @@ -338,8 +301,8 @@ class Meta: def __str__(self): return f'{self.device}:{self.name}' - def get_status_class(self): - return SessionStatusChoices.CSS_CLASSES.get(self.status) + def get_status_color(self): + return SessionStatusChoices.colors.get(self.status) def get_absolute_url(self): - return reverse('plugins:netbox_bgp:session', args=[self.pk]) + return reverse('plugins:netbox_bgp:bgpsession', args=[self.pk]) diff --git a/netbox_bgp/navigation.py b/netbox_bgp/navigation.py index 4780f21..712e2bf 100644 --- a/netbox_bgp/navigation.py +++ b/netbox_bgp/navigation.py @@ -31,12 +31,12 @@ ), ), PluginMenuItem( - link='plugins:netbox_bgp:session_list', + link='plugins:netbox_bgp:bgpsession_list', link_text='Sessions', permissions=['netbox_bgp.view_bgpsession'], buttons=( PluginMenuButton( - link='plugins:netbox_bgp:session_add', + link='plugins:netbox_bgp:bgpsession_add', title='Sessions', icon_class='mdi mdi-plus-thick', color=ButtonColorChoices.GREEN, @@ -45,12 +45,12 @@ ), ), PluginMenuItem( - link='plugins:netbox_bgp:routing_policy_list', + link='plugins:netbox_bgp:routingpolicy_list', link_text='Routing Policies', permissions=['netbox_bgp.view_routingpolicy'], buttons=( PluginMenuButton( - link='plugins:netbox_bgp:routing_policy_add', + link='plugins:netbox_bgp:routingpolicy_add', title='Routing Policies', icon_class='mdi mdi-plus-thick', color=ButtonColorChoices.GREEN, @@ -59,12 +59,12 @@ ), ), PluginMenuItem( - link='plugins:netbox_bgp:peergroup_list', + link='plugins:netbox_bgp:bgppeergroup_list', link_text='Peer Groups', permissions=['netbox_bgp.view_bgppeergroup'], buttons=( PluginMenuButton( - link='plugins:netbox_bgp:peergroup_add', + link='plugins:netbox_bgp:bgppeergroup_add', title='Peer Groups', icon_class='mdi mdi-plus-thick', color=ButtonColorChoices.GREEN, diff --git a/netbox_bgp/tables.py b/netbox_bgp/tables.py index 4f031e7..3955b43 100644 --- a/netbox_bgp/tables.py +++ b/netbox_bgp/tables.py @@ -2,7 +2,8 @@ from django.utils.safestring import mark_safe from django_tables2.utils import A -from utilities.tables import BaseTable, ChoiceFieldColumn, ToggleColumn, TagColumn +from netbox.tables import NetBoxTable +from netbox.tables.columns import ChoiceFieldColumn, TagColumn from .models import ASN, Community, BGPSession, RoutingPolicy, BGPPeerGroup @@ -24,8 +25,7 @@ """ -class ASNTable(BaseTable): - pk = ToggleColumn() +class ASNTable(NetBoxTable): number = tables.LinkColumn(text=lambda record: record.__str__(), args=[A('pk')]) status = ChoiceFieldColumn( default=AVAILABLE_LABEL @@ -35,13 +35,12 @@ class ASNTable(BaseTable): template_code=COL_TENANT ) - class Meta(BaseTable.Meta): + class Meta(NetBoxTable.Meta): model = ASN - fields = ('pk', 'number', 'description', 'status') + fields = ('pk', 'number', 'description', 'status', 'tenant') -class CommunityTable(BaseTable): - pk = ToggleColumn() +class CommunityTable(NetBoxTable): value = tables.LinkColumn() status = ChoiceFieldColumn( default=AVAILABLE_LABEL @@ -53,16 +52,15 @@ class CommunityTable(BaseTable): url_name='plugins:netbox_bgp:community_list' ) - class Meta(BaseTable.Meta): + class Meta(NetBoxTable.Meta): model = Community - fields = ('pk', 'value', 'description', 'status', 'tags') + fields = ('pk', 'value', 'description', 'status', 'tenant', 'tags') default_columns = ( 'pk', 'value', 'description', 'status', 'tenant' ) -class BGPSessionTable(BaseTable): - pk = ToggleColumn() +class BGPSessionTable(NetBoxTable): name = tables.LinkColumn() device = tables.LinkColumn() local_address = tables.LinkColumn() @@ -78,12 +76,12 @@ class BGPSessionTable(BaseTable): template_code=COL_TENANT ) - class Meta(BaseTable.Meta): + class Meta(NetBoxTable.Meta): model = BGPSession fields = ( 'pk', 'name', 'device', 'local_address', 'local_as', 'remote_address', 'remote_as', 'description', 'peer_group', - 'site', 'status' + 'site', 'status', 'tenant' ) default_columns = ( 'pk', 'name', 'device', 'local_address', 'local_as', @@ -92,17 +90,15 @@ class Meta(BaseTable.Meta): ) -class RoutingPolicyTable(BaseTable): - pk = ToggleColumn() +class RoutingPolicyTable(NetBoxTable): name = tables.LinkColumn() - class Meta(BaseTable.Meta): + class Meta(NetBoxTable.Meta): model = RoutingPolicy fields = ('pk', 'name', 'description') -class BGPPeerGroupTable(BaseTable): - pk = ToggleColumn() +class BGPPeerGroupTable(NetBoxTable): name = tables.LinkColumn() import_policies = tables.TemplateColumn( template_code=POLICIES, @@ -116,7 +112,7 @@ class BGPPeerGroupTable(BaseTable): url_name='plugins:netbox_bgp:peer_group_list' ) - class Meta(BaseTable.Meta): + class Meta(NetBoxTable.Meta): model = BGPPeerGroup fields = ( 'pk', 'name', 'description', 'tags', diff --git a/netbox_bgp/templates/netbox_bgp/asn_list.html b/netbox_bgp/templates/netbox_bgp/asn_list.html deleted file mode 100644 index 4b1a158..0000000 --- a/netbox_bgp/templates/netbox_bgp/asn_list.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends 'generic/object_list.html' %} - -{% block extra_controls %} -{% if permissions.add %} - - Add - -{% endif %} -{% endblock %} -{% block bulk_buttons %} -{% if permissions.change %} - -{% endif %} -{% if permissions.delete %} - -{% endif %} -{% endblock %} \ No newline at end of file diff --git a/netbox_bgp/templates/netbox_bgp/bgppeergroup.html b/netbox_bgp/templates/netbox_bgp/bgppeergroup.html index e175045..5a94771 100644 --- a/netbox_bgp/templates/netbox_bgp/bgppeergroup.html +++ b/netbox_bgp/templates/netbox_bgp/bgppeergroup.html @@ -6,18 +6,18 @@ {% load render_table from django_tables2 %} {% block breadcrumbs %} - + {% endblock %} {% block controls %}
{% if perms.netbox_bgp.change_peergroup %} - + Edit {% endif %} {% if perms.netbox_bgp.delete_peergroup %} - + Delete {% endif %} @@ -32,7 +32,7 @@ {% endblock tab_items %} {% if perms.extras.view_objectchange %} {% endif %} diff --git a/netbox_bgp/templates/netbox_bgp/bgppeergroup_list.html b/netbox_bgp/templates/netbox_bgp/bgppeergroup_list.html deleted file mode 100644 index dee1dd3..0000000 --- a/netbox_bgp/templates/netbox_bgp/bgppeergroup_list.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'generic/object_list.html' %} - -{% block extra_controls %} -{% if permissions.add %} - - Add - -{% endif %} -{% endblock %} -{% block bulk_buttons %} -{% if permissions.delete %} - -{% endif %} -{% endblock %} \ No newline at end of file diff --git a/netbox_bgp/templates/netbox_bgp/bgpsession.html b/netbox_bgp/templates/netbox_bgp/bgpsession.html index 9579d73..4e302fe 100644 --- a/netbox_bgp/templates/netbox_bgp/bgpsession.html +++ b/netbox_bgp/templates/netbox_bgp/bgpsession.html @@ -6,17 +6,17 @@ {% load render_table from django_tables2 %} {% block breadcrumbs %} - + {% endblock %} {% block controls %}
{% if perms.netbox_bgp.change_session %} - + Edit {% endif %} {% if perms.netbox_bgp.delete_session %} - + Delete {% endif %} @@ -31,7 +31,7 @@ {% endblock tab_items %} {% if perms.extras.view_objectchange %} {% endif %} diff --git a/netbox_bgp/templates/netbox_bgp/bgpsession_list.html b/netbox_bgp/templates/netbox_bgp/bgpsession_list.html deleted file mode 100644 index 8dd51b7..0000000 --- a/netbox_bgp/templates/netbox_bgp/bgpsession_list.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'generic/object_list.html' %} - -{% block extra_controls %} -{% if permissions.add %} - - Add - -{% endif %} -{% endblock %} -{% block bulk_buttons %} -{% if permissions.delete %} - -{% endif %} -{% endblock %} \ No newline at end of file diff --git a/netbox_bgp/templates/netbox_bgp/community_list.html b/netbox_bgp/templates/netbox_bgp/community_list.html deleted file mode 100644 index e1510af..0000000 --- a/netbox_bgp/templates/netbox_bgp/community_list.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends 'generic/object_list.html' %} - -{% block extra_controls %} -{% if permissions.add %} - - Add - -{% endif %} -{% endblock %} -{% block bulk_buttons %} -{% if permissions.change %} - -{% endif %} -{% if permissions.delete %} - -{% endif %} -{% endblock %} \ No newline at end of file diff --git a/netbox_bgp/templates/netbox_bgp/routingpolicy.html b/netbox_bgp/templates/netbox_bgp/routingpolicy.html index 73ed92c..824a340 100644 --- a/netbox_bgp/templates/netbox_bgp/routingpolicy.html +++ b/netbox_bgp/templates/netbox_bgp/routingpolicy.html @@ -6,17 +6,17 @@ {% load render_table from django_tables2 %} {% block breadcrumbs %} - + {% endblock %} {% block controls %}
{% if perms.netbox_bgp.change_policy %} - + Edit {% endif %} {% if perms.netbox_bgp.delete_policy %} - + Delete {% endif %} @@ -31,7 +31,7 @@ {% endblock tab_items %} {% if perms.extras.view_objectchange %} {% endif %} diff --git a/netbox_bgp/templates/netbox_bgp/routingpolicy_list.html b/netbox_bgp/templates/netbox_bgp/routingpolicy_list.html deleted file mode 100644 index 9b5b1b7..0000000 --- a/netbox_bgp/templates/netbox_bgp/routingpolicy_list.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'generic/object_list.html' %} - -{% block extra_controls %} -{% if permissions.add %} - - Add - -{% endif %} -{% endblock %} -{% block bulk_buttons %} -{% if permissions.delete %} - -{% endif %} -{% endblock %} \ No newline at end of file diff --git a/netbox_bgp/urls.py b/netbox_bgp/urls.py index 07fb972..96d0119 100644 --- a/netbox_bgp/urls.py +++ b/netbox_bgp/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from extras.views import ObjectChangeLogView +from netbox.views.generic import ObjectChangeLogView from .models import ASN, BGPSession, Community, RoutingPolicy, BGPPeerGroup from .views import ( @@ -33,27 +33,27 @@ path('community//delete/', CommunityDeleteView.as_view(), name='community_delete'), path('community//changelog/', ObjectChangeLogView.as_view(), name='community_changelog', kwargs={'model': Community}), # Sessions - path('session/', BGPSessionListView.as_view(), name='session_list'), - path('session/add/', BGPSessionAddView.as_view(), name='session_add'), - path('session/delete/', BGPSessionBulkDeleteView.as_view(), name='session_bulk_delete'), - path('session//', BGPSessionView.as_view(), name='session'), - path('session//edit/', BGPSessionEditView.as_view(), name='session_edit'), - path('session//delete/', BGPSessionDeleteView.as_view(), name='session_delete'), - path('session//changelog/', ObjectChangeLogView.as_view(), name='session_changelog', kwargs={'model': BGPSession}), + path('session/', BGPSessionListView.as_view(), name='bgpsession_list'), + path('session/add/', BGPSessionAddView.as_view(), name='bgpsession_add'), + path('session/delete/', BGPSessionBulkDeleteView.as_view(), name='bgpsession_bulk_delete'), + path('session//', BGPSessionView.as_view(), name='bgpsession'), + path('session//edit/', BGPSessionEditView.as_view(), name='bgpsession_edit'), + path('session//delete/', BGPSessionDeleteView.as_view(), name='bgpsession_delete'), + path('session//changelog/', ObjectChangeLogView.as_view(), name='bgpsession_changelog', kwargs={'model': BGPSession}), # Routing Policies - path('routing-policy//', RoutingPolicyView.as_view(), name='routing_policy'), - path('routing-policy/', RoutingPolicyListView.as_view(), name='routing_policy_list'), - path('routing-policy/add/', RoutingPolicyEditView.as_view(), name='routing_policy_add'), - path('routing-policy//edit/', RoutingPolicyEditView.as_view(), name='routing_policy_edit'), - path('routing-policy/delete/', RoutingPolicyBulkDeleteView.as_view(), name='routing_policy_bulk_delete'), - path('routing-policy//delete/', RoutingPolicyDeleteView.as_view(), name='routing_policy_delete'), - path('routing-policy//changelog/', ObjectChangeLogView.as_view(), name='routing_policy_changelog', kwargs={'model': RoutingPolicy}), + path('routing-policy//', RoutingPolicyView.as_view(), name='routingpolicy'), + path('routing-policy/', RoutingPolicyListView.as_view(), name='routingpolicy_list'), + path('routing-policy/add/', RoutingPolicyEditView.as_view(), name='routingpolicy_add'), + path('routing-policy//edit/', RoutingPolicyEditView.as_view(), name='routingpolicy_edit'), + path('routing-policy/delete/', RoutingPolicyBulkDeleteView.as_view(), name='routingpolicy_bulk_delete'), + path('routing-policy//delete/', RoutingPolicyDeleteView.as_view(), name='routingpolicy_delete'), + path('routing-policy//changelog/', ObjectChangeLogView.as_view(), name='routingpolicy_changelog', kwargs={'model': RoutingPolicy}), # Peer Groups - path('peer-group/', BGPPeerGroupListView.as_view(), name='peergroup_list'), - path('peer-group/add/', BGPPeerGroupEditView.as_view(), name='peergroup_add'), - path('peer-group/delete/', BGPPeerGroupBulkDeleteView.as_view(), name='peergroup_bulk_delete'), - path('peer-group//', BGPPeerGroupView.as_view(), name='peergroup'), - path('peer-group//edit/', BGPPeerGroupEditView.as_view(), name='peergroup_edit'), - path('peer-group//delete/', BGPPeerGroupDeleteView.as_view(), name='peergroup_delete'), - path('peer-group//changelog/', ObjectChangeLogView.as_view(), name='peergroup_changelog', kwargs={'model': BGPPeerGroup}), + path('peer-group/', BGPPeerGroupListView.as_view(), name='bgppeergroup_list'), + path('peer-group/add/', BGPPeerGroupEditView.as_view(), name='bgppeergroup_add'), + path('peer-group/delete/', BGPPeerGroupBulkDeleteView.as_view(), name='bgppeergroup_bulk_delete'), + path('peer-group//', BGPPeerGroupView.as_view(), name='bgppeergroup'), + path('peer-group//edit/', BGPPeerGroupEditView.as_view(), name='bgppeergroup_edit'), + path('peer-group//delete/', BGPPeerGroupDeleteView.as_view(), name='bgppeergroup_delete'), + path('peer-group//changelog/', ObjectChangeLogView.as_view(), name='bgppeergroup_changelog', kwargs={'model': BGPPeerGroup}), ] diff --git a/netbox_bgp/version.py b/netbox_bgp/version.py index dd9b22c..906d362 100644 --- a/netbox_bgp/version.py +++ b/netbox_bgp/version.py @@ -1 +1 @@ -__version__ = "0.5.1" +__version__ = "0.6.0" diff --git a/netbox_bgp/views.py b/netbox_bgp/views.py index 27805f1..0017027 100644 --- a/netbox_bgp/views.py +++ b/netbox_bgp/views.py @@ -21,8 +21,7 @@ class ASNListView(generic.ObjectListView): filterset = ASNFilterSet filterset_form = ASNFilterForm table = ASNTable - action_buttons = () - template_name = 'netbox_bgp/asn_list.html' + action_buttons = ('add',) class ASNView(generic.ObjectView): @@ -39,8 +38,7 @@ def get_extra_context(self, request, instance): class ASNEditView(generic.ObjectEditView): queryset = ASN.objects.all() - model_form = ASNForm - default_return_url = 'plugins:netbox_bgp:asn_list' + form = ASNForm class ASNBulkDeleteView(generic.BulkDeleteView): @@ -64,8 +62,7 @@ class CommunityListView(generic.ObjectListView): filterset = CommunityFilterSet filterset_form = CommunityFilterForm table = CommunityTable - action_buttons = () - template_name = 'netbox_bgp/community_list.html' + action_buttons = ('add',) class CommunityView(generic.ObjectView): @@ -75,8 +72,7 @@ class CommunityView(generic.ObjectView): class CommunityEditView(generic.ObjectEditView): queryset = Community.objects.all() - model_form = CommunityForm - default_return_url = 'plugins:netbox_bgp:community_list' + form = CommunityForm class CommunityBulkDeleteView(generic.BulkDeleteView): @@ -100,20 +96,17 @@ class BGPSessionListView(generic.ObjectListView): filterset = BGPSessionFilterSet filterset_form = BGPSessionFilterForm table = BGPSessionTable - action_buttons = () - template_name = 'netbox_bgp/bgpsession_list.html' + action_buttons = ('add',) class BGPSessionEditView(generic.ObjectEditView): queryset = BGPSession.objects.all() - model_form = BGPSessionForm - default_return_url = 'plugins:netbox_bgp:session_list' + form = BGPSessionForm class BGPSessionAddView(generic.ObjectEditView): queryset = BGPSession.objects.all() - model_form = BGPSessionAddForm - default_return_url = 'plugins:netbox_bgp:session_list' + form = BGPSessionAddForm class BGPSessionBulkDeleteView(generic.BulkDeleteView): @@ -157,14 +150,12 @@ class RoutingPolicyListView(generic.ObjectListView): filterset = RoutingPolicyFilterSet filterset_form = RoutingPolicyFilterForm table = RoutingPolicyTable - action_buttons = () - template_name = 'netbox_bgp/routingpolicy_list.html' + action_buttons = ('add',) class RoutingPolicyEditView(generic.ObjectEditView): queryset = RoutingPolicy.objects.all() - model_form = RoutingPolicyForm - default_return_url = 'plugins:netbox_bgp:routing_policy_list' + form = RoutingPolicyForm class RoutingPolicyBulkDeleteView(generic.BulkDeleteView): @@ -199,14 +190,12 @@ class BGPPeerGroupListView(generic.ObjectListView): filterset = BGPPeerGroupFilterSet filterset_form = BGPPeerGroupFilterForm table = BGPPeerGroupTable - action_buttons = () - template_name = 'netbox_bgp/bgppeergroup_list.html' + action_buttons = ('add',) class BGPPeerGroupEditView(generic.ObjectEditView): queryset = BGPPeerGroup.objects.all() - model_form = BGPPeerGroupForm - default_return_url = 'plugins:netbox_bgp:peergroup_list' + form = BGPPeerGroupForm class BGPPeerGroupBulkDeleteView(generic.BulkDeleteView):