From 95bed3a0c0e872cee9b6f5fbabca33c19369c652 Mon Sep 17 00:00:00 2001 From: Justin Parsell Date: Thu, 15 Feb 2024 17:48:23 +0000 Subject: [PATCH] Upload files to "dnac_integration" --- dnac_integration/__init__.py | 12 +++++ dnac_integration/filtersets.py | 10 ++++ dnac_integration/forms.py | 27 +++++++++++ dnac_integration/graphql.py | 15 ++++++ dnac_integration/models.py | 83 ++++++++++++++++++++++++++++++++++ 5 files changed, 147 insertions(+) create mode 100644 dnac_integration/__init__.py create mode 100644 dnac_integration/filtersets.py create mode 100644 dnac_integration/forms.py create mode 100644 dnac_integration/graphql.py create mode 100644 dnac_integration/models.py diff --git a/dnac_integration/__init__.py b/dnac_integration/__init__.py new file mode 100644 index 0000000..d7ac6fe --- /dev/null +++ b/dnac_integration/__init__.py @@ -0,0 +1,12 @@ +from extras.plugins import PluginConfig + +class DNAC_Integration(PluginConfig): + name = 'dnac_integration' + verbose_name = ' DNAC Integration' + description = 'Allows DNAC to import devices into Netbox' + author = 'Justin Parsell' + author_email = 'jxp787@jefferson.edu' + version = '0.1' + base_url = 'dnac' + +config = DNAC_Integration \ No newline at end of file diff --git a/dnac_integration/filtersets.py b/dnac_integration/filtersets.py new file mode 100644 index 0000000..747860e --- /dev/null +++ b/dnac_integration/filtersets.py @@ -0,0 +1,10 @@ +from netbox.filtersets import NetBoxModelFilterSet +from .models import dnacServer + +class dnacServerFilterSet(NetBoxModelFilterSet): + def search(self, queryset, name, value): + return queryset.filter(description__icontains=value) + + class Meta: + model = dnacServer + fields = ('id', 'hostname', 'username', 'password', 'version', 'verify', 'default_filter_action', 'status') \ No newline at end of file diff --git a/dnac_integration/forms.py b/dnac_integration/forms.py new file mode 100644 index 0000000..353efe7 --- /dev/null +++ b/dnac_integration/forms.py @@ -0,0 +1,27 @@ +from django import forms +from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm +from utilities.forms.fields import CommentField +from .models import dnacServer + +class dnacServerForm(NetBoxModelForm): + + class Meta: + model = dnacServer + fields = ('hostname', 'username', 'password', 'version', 'verify', 'default_filter_action', 'tags') + +class dnacServerFilterForm(NetBoxModelFilterSetForm): + model = dnacServer + + username = forms.TextInput() + version = forms.IntegerField( + required=False + ) + verify = forms.BooleanField( + required=False + ) + status = forms.BooleanField( + required=False + ) + default_filter_action = forms.BooleanField( + required=False + ) diff --git a/dnac_integration/graphql.py b/dnac_integration/graphql.py new file mode 100644 index 0000000..526c28f --- /dev/null +++ b/dnac_integration/graphql.py @@ -0,0 +1,15 @@ +from graphene import ObjectType +from netbox.graphql.types import NetBoxObjectType +from netbox.graphql.fields import ObjectField, ObjectListField +from . import filtersets, models + +class dnacServerType(NetBoxObjectType): + class Meta: + model = models.dnacServer + fields = '__all__' + +class Query(ObjectType): + dnacServer = ObjectField(dnacServerType) + dnacServer_list = ObjectListField(dnacServerType) + +schema = Query \ No newline at end of file diff --git a/dnac_integration/models.py b/dnac_integration/models.py new file mode 100644 index 0000000..4c17cba --- /dev/null +++ b/dnac_integration/models.py @@ -0,0 +1,83 @@ +from django.db import models +from django.urls import reverse +from netbox.models.features import ChangeLoggingMixin, TagsMixin +from netbox.models import NetBoxModel + +class dnacServer(NetBoxModel): + # Change Logging Fields + created = models.DateTimeField( + auto_now_add=True, + blank=True, + null=True + ) + last_updated = models.DateTimeField( + auto_now=True, + blank=True, + null=True + ) + + # DNAC Server Fields + hostname = models.CharField(max_length=2000, unique=True, blank=True, null=True) + username = models.CharField(max_length=100) + password = models.CharField(max_length=100) + version = models.CharField(max_length=10) + verify = models.BooleanField(default=False) + status = models.BooleanField(default=True) + + # Filter options + ## This action should be utilized when no matching filter is found in dnacFilters, given it's associated site + default_filter_action = models.BooleanField(default=False) # True=ALLOW | False=DENY + + # Ordering of the data + class Meta: + ordering = ('hostname',) + + # Required variables + def __str__(self): + return self.hostname + + def get_absolute_url(self): + return reverse('plugins:dnac_integration:dnacServer', args=[self.pk]) + +class dnacSite(NetBoxModel): + _netbox_private = True + + site = models.CharField(max_length=2000, unique=True) + parent = models.ForeignKey( + 'self', + on_delete=models.CASCADE, + blank=True, + null=True + ) + ## TODO: allow generic models OR create ContentType of SITE,SITE_GROUP,REGION + #assocation = models.ForeignKey() + + class Meta: + ordering = ('parent', 'site',) + + def __str__(self): + return self.site + + def get_absolute_url(self): + return reverse('plugins:dnac_integration:dnacSite', args=[self.pk]) + +class dnacFilter(NetBoxModel): + + server = models.OneToOneField( + to=dnacServer, + on_delete=models.CASCADE, + unique=True + ) + priority = models.PositiveSmallIntegerField() + action = models.BooleanField(default=False) # True=ALLOW | False=DENY + ## TODO: Figure out how to define this, should be able to filter on DEVICE TYPE, DEVICE STATUS, ROLE + ## This should allow allow actions, ie REGEX_MATCH charfield, EXISTS netbox object? + + class Meta: + ordering = ('server', 'priority', ) + + def __str__(self): + return "FIXME! server:priority:rule:action" + + def get_absolute_url(self): + return reverse('plugins:dnac_integration:dnacFilter', args=[self.pk]) \ No newline at end of file