Skip to content

Commit

Permalink
Merge pull request #88 from k01ek/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
k01ek authored Apr 8, 2022
2 parents 8627a43 + e3ea314 commit 307f3bd
Show file tree
Hide file tree
Showing 20 changed files with 228 additions and 296 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions netbox_bgp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class BGPConfig(PluginConfig):
author_email = '[email protected]'
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
Expand Down
49 changes: 8 additions & 41 deletions netbox_bgp/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -127,15 +94,15 @@ 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
fields = ['id', 'url', 'name', 'description']
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)
Expand Down Expand Up @@ -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)

Expand Down
43 changes: 27 additions & 16 deletions netbox_bgp/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -91,7 +89,7 @@ class ASNFilterForm(CustomFieldModelFilterForm):
tag = TagFilterField(model)


class ASNForm(CustomFieldModelForm):
class ASNForm(NetBoxModelForm):
number = ASNField(
widget=ASdotInput
)
Expand All @@ -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
Expand All @@ -126,7 +129,7 @@ class Meta:
]


class ASNBulkEditForm(CustomFieldBulkEditForm):
class ASNBulkEditForm(NetBoxModelBulkEditForm):
pk = forms.ModelMultipleChoiceField(
queryset=ASN.objects.all(),
widget=forms.MultipleHiddenInput
Expand All @@ -145,17 +148,25 @@ 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):
tags = DynamicModelMultipleChoiceField(
queryset=Tag.objects.all(),
required=False
)
status = forms.ChoiceField(
required=False,
choices=ASNStatusChoices,
widget=StaticSelect()
)
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False
Expand Down Expand Up @@ -219,7 +230,7 @@ class Meta:
]


class BGPSessionForm(CustomFieldModelForm):
class BGPSessionForm(NetBoxModelForm):
name = forms.CharField(
max_length=64,
required=True
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -394,7 +405,7 @@ class BGPSessionFilterForm(CustomFieldModelFilterForm):
tag = TagFilterField(model)


class RoutingPolicyFilterForm(CustomFieldModelFilterForm):
class RoutingPolicyFilterForm(NetBoxModelFilterSetForm):
model = RoutingPolicy
q = forms.CharField(
required=False,
Expand All @@ -404,7 +415,7 @@ class RoutingPolicyFilterForm(CustomFieldModelFilterForm):
tag = TagFilterField(model)


class RoutingPolicyForm(CustomFieldModelForm):
class RoutingPolicyForm(NetBoxModelForm):
tags = DynamicModelMultipleChoiceField(
queryset=Tag.objects.all(),
required=False
Expand All @@ -415,7 +426,7 @@ class Meta:
fields = ['name', 'description']


class BGPPeerGroupFilterForm(CustomFieldModelFilterForm):
class BGPPeerGroupFilterForm(NetBoxModelFilterSetForm):
model = BGPPeerGroup
q = forms.CharField(
required=False,
Expand All @@ -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,
Expand Down
95 changes: 95 additions & 0 deletions netbox_bgp/migrations/0021_netbox32_support.py
Original file line number Diff line number Diff line change
@@ -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),
),
]
Loading

0 comments on commit 307f3bd

Please sign in to comment.