Skip to content

Commit

Permalink
Add SNMP configuration to devices
Browse files Browse the repository at this point in the history
- Configure SNMP contacts and locations
- Assign SNMP communities to each device with read or read-write types
  • Loading branch information
cpaillet committed Jun 6, 2024
1 parent 61d560a commit 9d22704
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 10 deletions.
30 changes: 30 additions & 0 deletions netbox_cmdb/netbox_cmdb/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from netbox_cmdb.models.bgp_community_list import BGPCommunityList, BGPCommunityListTerm
from netbox_cmdb.models.prefix_list import PrefixList, PrefixListTerm
from netbox_cmdb.models.route_policy import RoutePolicy, RoutePolicyTerm
from netbox_cmdb.models.snmp import SNMP, SNMPCommunity


class BaseAdmin(admin.ModelAdmin):
Expand Down Expand Up @@ -173,6 +174,35 @@ class BGPCommunityListAdmin(BaseAdmin):
)


@admin.register(SNMP)
class SNMPAdmin(BaseAdmin):
"""Admin class to manage SNMPCommunity objects."""

list_display = (
"device",
"community_list_display",
"location",
"contact",
)

def community_list_display(self, obj):
return ", ".join([str(community) for community in obj.community_list.all()])

community_list_display.short_description = "Community List"


@admin.register(SNMPCommunity)
class SNMPCommunitytAdmin(BaseAdmin):
"""Admin class to manage SNMP objects."""

list_display = (
"name",
"type",
"community",
)
search_fields = ("name", "name")


# We need to register Netbox core models to the Admin page or we won't be able to lookup
# dynamically over the objects.
@admin.register(IPAddress)
Expand Down
12 changes: 12 additions & 0 deletions netbox_cmdb/netbox_cmdb/choices.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
from utilities.choices import ChoiceSet


class SNMPCommunityType(ChoiceSet):
"""A ChoiceSet to define the communityType."""

RO = "Read-Only"
RW = "Read&Write"

CHOICES = [
(RO, "Read-Only", "green"),
(RW, "Read&Write", "red"),
]


class AssetStateChoices(ChoiceSet):
"""A ChoiceSet to define the state of an asset."""

Expand Down
17 changes: 16 additions & 1 deletion netbox_cmdb/netbox_cmdb/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
from django import forms
from django.utils.translation import gettext as _
from extras.models import Tag
from netbox_cmdb.models.snmp import SNMP, SNMPCommunity
from utilities.forms import DynamicModelMultipleChoiceField
from utilities.forms.fields import DynamicModelChoiceField, MultipleChoiceField

from netbox.forms import NetBoxModelFilterSetForm, NetBoxModelForm
from netbox_cmdb.choices import AssetMonitoringStateChoices, AssetStateChoices
from netbox_cmdb.choices import AssetMonitoringStateChoices, AssetStateChoices, SNMPCommunityType
from netbox_cmdb.models.bgp import ASN, BGPPeerGroup, BGPSession


Expand Down Expand Up @@ -83,3 +84,17 @@ def clean(self):
pass # such validation is already handled in previous validation steps
if count < 1:
raise forms.ValidationError("You must have at least one term.")


class SNMPGroupForm(NetBoxModelForm):
device = DynamicModelChoiceField(queryset=Device.objects.all())

class Meta:
model = SNMP
fields = ["device", "community_list", "location", "contact"]


class SNMPCommunityGroupForm(NetBoxModelForm):
class Meta:
model = SNMPCommunity
fields = ["name", "community", "type"]
42 changes: 42 additions & 0 deletions netbox_cmdb/netbox_cmdb/migrations/0040_snmpcommunity_snmp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('dcim', '0161_cabling_cleanup'),
('netbox_cmdb', '0039_logicalinterface'),
]

operations = [
migrations.CreateModel(
name='SNMPCommunity',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True, null=True)),
('last_updated', models.DateTimeField(auto_now=True, null=True)),
('name', models.CharField(max_length=100, unique=True)),
('community', models.CharField(max_length=31)),
('type', models.CharField(default='Read-Only', max_length=10)),
],
options={
'verbose_name_plural': 'SNMP Communities',
},
),
migrations.CreateModel(
name='SNMP',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True, null=True)),
('last_updated', models.DateTimeField(auto_now=True, null=True)),
('location', models.CharField(max_length=31)),
('contact', models.CharField(max_length=31)),
('community_list', models.ManyToManyField(blank=True, default=None, related_name='%(class)s_community', to='netbox_cmdb.snmpcommunity')),
('device', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='dcim.device')),
],
options={
'verbose_name_plural': 'SNMP',
},
),
]
46 changes: 46 additions & 0 deletions netbox_cmdb/netbox_cmdb/models/snmp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from django.db import models
from netbox_cmdb.choices import SNMPCommunityType
from netbox.models import ChangeLoggedModel
from django.core.exceptions import ValidationError
from django.contrib.postgres.fields import ArrayField


class SNMPCommunity(ChangeLoggedModel):
"""A Snmp Community"""

name = models.CharField(max_length=100, unique=True)
community = models.CharField(max_length=31)
type = models.CharField(
max_length=10,
choices=SNMPCommunityType,
default=SNMPCommunityType.RO,
help_text="Defines the community string permissions of either read-only RO or read-write RW",
)

def __str__(self):
return f"{self.name}"

class Meta:
verbose_name_plural = "SNMP Communities"


class SNMP(ChangeLoggedModel):
"""A Snmp configuration"""

community_list = models.ManyToManyField(
to=SNMPCommunity, related_name="%(class)s_community", blank=True, default=None
)

location = models.CharField(max_length=31)
contact = models.CharField(max_length=31)

device = models.OneToOneField(
to="dcim.Device",
on_delete=models.CASCADE,
)

class Meta:
verbose_name_plural = "SNMP"

def __str__(self):
return f"SNMP configuration of {self.device.name}"
24 changes: 24 additions & 0 deletions netbox_cmdb/netbox_cmdb/navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,28 @@
),
),
),
PluginMenuItem(
link="plugins:netbox_cmdb:snmp_list",
link_text="SNMP",
buttons=(
PluginMenuButton(
link="plugins:netbox_cmdb:snmp_add",
title="SNMP",
icon_class="mdi mdi-plus-thick",
color=ButtonColorChoices.GREEN,
),
),
),
PluginMenuItem(
link="plugins:netbox_cmdb:snmpcommunity_list",
link_text="SNMP Community",
buttons=(
PluginMenuButton(
link="plugins:netbox_cmdb:snmpcommunity_add",
title="SNMP Community",
icon_class="mdi mdi-plus-thick",
color=ButtonColorChoices.GREEN,
),
),
),
)
15 changes: 15 additions & 0 deletions netbox_cmdb/netbox_cmdb/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from netbox.tables import NetBoxTable, columns
from netbox_cmdb.models.bgp import ASN, BGPPeerGroup, BGPSession
from netbox_cmdb.models.snmp import SNMP, SNMPCommunity


class ASNTable(NetBoxTable):
Expand Down Expand Up @@ -60,3 +61,17 @@ class Meta(NetBoxTable.Meta):
"route_policy_out",
"maximum_prefixes",
)


class SNMPTable(NetBoxTable):
device = tables.LinkColumn()

class Meta(NetBoxTable.Meta):
model = SNMP
fields = ("device", "community_list", "location", "contact")


class SNMPCommunityTable(NetBoxTable):
class Meta(NetBoxTable.Meta):
model = SNMPCommunity
fields = ("name", "community", "type")
43 changes: 43 additions & 0 deletions netbox_cmdb/netbox_cmdb/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from netbox.views.generic import ObjectChangeLogView, ObjectJournalView

from netbox_cmdb.models.bgp import *
from netbox_cmdb.models.snmp import SNMP, SNMPCommunity
from netbox_cmdb.views import (
ASNDeleteView,
ASNEditView,
Expand All @@ -18,6 +19,10 @@
BGPSessionEditView,
BGPSessionListView,
BGPSessionView,
SNMPCommunityEditView,
SNMPCommunityListView,
SNMPEditView,
SNMPListView,
)

urlpatterns = [
Expand Down Expand Up @@ -92,4 +97,42 @@
name="bgppeergroup_journal",
kwargs={"model": BGPPeerGroup},
),
# SNMP
path("snmp/", SNMPListView.as_view(), name="snmp_list"),
path("snmp/add/", SNMPEditView.as_view(), name="snmp_add"),
path(
"snmp/<int:pk>/edit/",
SNMPEditView.as_view(),
name="snmp_edit",
),
path(
"snmp/<int:pk>/delete/",
SNMPListView.as_view(),
name="snmp_delete",
),
path(
"snmp/<int:pk>/changelog/",
ObjectChangeLogView.as_view(),
name="snmp_changelog",
kwargs={"model": SNMP},
),
# SNMP Community
path("snmp-community/", SNMPCommunityListView.as_view(), name="snmpcommunity_list"),
path("snmp-community/add/", SNMPCommunityEditView.as_view(), name="snmpcommunity_add"),
path(
"snmp-community/<int:pk>/edit/",
SNMPCommunityEditView.as_view(),
name="snmpcommunity_edit",
),
path(
"snmp-community/<int:pk>/delete/",
SNMPCommunityListView.as_view(),
name="snmpcommunity_delete",
),
path(
"snmp-community/<int:pk>/changelog/",
ObjectChangeLogView.as_view(),
name="snmpcommunity_changelog",
kwargs={"model": SNMPCommunity},
),
]
41 changes: 32 additions & 9 deletions netbox_cmdb/netbox_cmdb/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@
BGPPeerGroupForm,
BGPSessionFilterSetForm,
BGPSessionForm,
SNMPCommunityGroupForm,
SNMPGroupForm,
)
from netbox_cmdb.models.bgp import ASN, BGPPeerGroup, BGPSession, DeviceBGPSession
from netbox_cmdb.tables import ASNTable, BGPPeerGroupTable, BGPSessionTable
from netbox_cmdb.models.snmp import SNMP, SNMPCommunity
from netbox_cmdb.tables import (
ASNTable,
BGPPeerGroupTable,
BGPSessionTable,
SNMPCommunityTable,
SNMPTable,
)


## ASN views
Expand Down Expand Up @@ -90,14 +99,6 @@ def get_extra_context(self, request, instance):
}


## DeviceBGPSession views


class DeviceBGPSessionListView(ObjectListView):
queryset = DeviceBGPSession.objects.all()
filterset = None


## Peer groups views
class BGPPeerGroupListView(ObjectListView):
queryset = BGPPeerGroup.objects.all()
Expand All @@ -118,3 +119,25 @@ class BGPPeerGroupDeleteView(ObjectDeleteView):
class BGPPeerGroupView(ObjectView):
queryset = BGPPeerGroup.objects.all()
template_name = "netbox_cmdb/bgppeergroup.html"


## Snmp groups views
class SNMPListView(ObjectListView):
queryset = SNMP.objects.all()
table = SNMPTable


class SNMPEditView(ObjectEditView):
queryset = SNMP.objects.all()
form = SNMPGroupForm


## Snmp Community groups views
class SNMPCommunityListView(ObjectListView):
queryset = SNMPCommunity.objects.all()
table = SNMPCommunityTable


class SNMPCommunityEditView(ObjectEditView):
queryset = SNMPCommunity.objects.all()
form = SNMPCommunityGroupForm

0 comments on commit 9d22704

Please sign in to comment.