slurpit-netbox 0.8.36__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. slurpit_netbox-0.8.36/PKG-INFO +64 -0
  2. slurpit_netbox-0.8.36/README.md +48 -0
  3. slurpit_netbox-0.8.36/pyproject.toml +23 -0
  4. slurpit_netbox-0.8.36/src/slurpit_netbox/__init__.py +39 -0
  5. slurpit_netbox-0.8.36/src/slurpit_netbox/api/__init__.py +1 -0
  6. slurpit_netbox-0.8.36/src/slurpit_netbox/api/serializers.py +55 -0
  7. slurpit_netbox-0.8.36/src/slurpit_netbox/api/urls.py +11 -0
  8. slurpit_netbox-0.8.36/src/slurpit_netbox/api/views.py +172 -0
  9. slurpit_netbox-0.8.36/src/slurpit_netbox/decorators.py +57 -0
  10. slurpit_netbox-0.8.36/src/slurpit_netbox/filtersets.py +79 -0
  11. slurpit_netbox-0.8.36/src/slurpit_netbox/forms.py +182 -0
  12. slurpit_netbox-0.8.36/src/slurpit_netbox/importer.py +285 -0
  13. slurpit_netbox-0.8.36/src/slurpit_netbox/management/__init__.py +0 -0
  14. slurpit_netbox-0.8.36/src/slurpit_netbox/management/choices.py +49 -0
  15. slurpit_netbox-0.8.36/src/slurpit_netbox/migrations/0001_initial.py +135 -0
  16. slurpit_netbox-0.8.36/src/slurpit_netbox/migrations/0002_alter_slurpitplanning_name_and_more.py +23 -0
  17. slurpit_netbox-0.8.36/src/slurpit_netbox/migrations/0003_alter_slurpitimporteddevice_ipv4_and_more.py +23 -0
  18. slurpit_netbox-0.8.36/src/slurpit_netbox/migrations/0004_slurpitmapping.py +31 -0
  19. slurpit_netbox-0.8.36/src/slurpit_netbox/migrations/__init__.py +0 -0
  20. slurpit_netbox-0.8.36/src/slurpit_netbox/models/__init__.py +122 -0
  21. slurpit_netbox-0.8.36/src/slurpit_netbox/models/device.py +69 -0
  22. slurpit_netbox-0.8.36/src/slurpit_netbox/models/logs.py +41 -0
  23. slurpit_netbox-0.8.36/src/slurpit_netbox/models/mapping.py +9 -0
  24. slurpit_netbox-0.8.36/src/slurpit_netbox/models/planning.py +22 -0
  25. slurpit_netbox-0.8.36/src/slurpit_netbox/models/setting.py +38 -0
  26. slurpit_netbox-0.8.36/src/slurpit_netbox/navigation.py +49 -0
  27. slurpit_netbox-0.8.36/src/slurpit_netbox/search.py +11 -0
  28. slurpit_netbox-0.8.36/src/slurpit_netbox/slurpitch.py +15 -0
  29. slurpit_netbox-0.8.36/src/slurpit_netbox/tables.py +136 -0
  30. slurpit_netbox-0.8.36/src/slurpit_netbox/template_content.py +10 -0
  31. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/bulk_edit.html +129 -0
  32. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/comingsoon.html +49 -0
  33. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/data_mapping.html +86 -0
  34. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/logo.html +33 -0
  35. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/mapping/netbox_to_slurpit.html +217 -0
  36. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/onboard/conflict_device_list.html +75 -0
  37. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/onboard/migrate_device_list.html +75 -0
  38. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/onboard/new_device_list.html +74 -0
  39. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/onboard/onboarded_device_list.html +38 -0
  40. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/onboard_device.html +97 -0
  41. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/planning_table.html +120 -0
  42. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/settings/data_tabs.html +81 -0
  43. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/settings/general.html +216 -0
  44. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/settings.html +70 -0
  45. slurpit_netbox-0.8.36/src/slurpit_netbox/templates/slurpit_netbox/slurpitlog_list.html +54 -0
  46. slurpit_netbox-0.8.36/src/slurpit_netbox/urls.py +26 -0
  47. slurpit_netbox-0.8.36/src/slurpit_netbox/utilities.py +17 -0
  48. slurpit_netbox-0.8.36/src/slurpit_netbox/validator.py +30 -0
  49. slurpit_netbox-0.8.36/src/slurpit_netbox/views/__init__.py +5 -0
  50. slurpit_netbox-0.8.36/src/slurpit_netbox/views/datamapping.py +216 -0
  51. slurpit_netbox-0.8.36/src/slurpit_netbox/views/logging.py +14 -0
  52. slurpit_netbox-0.8.36/src/slurpit_netbox/views/onboarding.py +294 -0
  53. slurpit_netbox-0.8.36/src/slurpit_netbox/views/reconcile.py +13 -0
  54. slurpit_netbox-0.8.36/src/slurpit_netbox/views/setting.py +434 -0
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.1
2
+ Name: slurpit_netbox
3
+ Version: 0.8.36
4
+ Summary:
5
+ Author: Pieter
6
+ Author-email: pieter@slurpit.io
7
+ Requires-Python: >=3.10,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Requires-Dist: djangorestframework-bulk (>=0.2.1,<0.3.0)
13
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
14
+ Description-Content-Type: text/markdown
15
+
16
+ ## Compatibility
17
+
18
+ | NetBox Version | Plugin Version |
19
+ |----------------|----------------|
20
+ | NetBox 3.7 | >= 0.8.0 |
21
+
22
+ ## How to install the plugin on your local NetBox server
23
+
24
+ ### Activate the Virtual Environment
25
+
26
+ Firstly, to make the plugin available within NetBox, we must activate the Python virtual environment that was set up during the NetBox installation; you can do this by finding the path of the virtual environment, which typically is /opt/netbox/venv/ if you followed the default installation guide.
27
+
28
+ ```
29
+ $ source /opt/netbox/venv/bin/activate
30
+ ```
31
+
32
+ ### Run setup.py
33
+
34
+ ```
35
+ $ python setup.py develop
36
+ ```
37
+
38
+ ### Configure NetBox
39
+
40
+ To enable our new plugin, we have to configure NetBox by opening the configuration.py file located in the netbox/netbox directory and modifying the PLUGINS parameter.
41
+
42
+ ```
43
+ # configuration.py
44
+ PLUGINS = [
45
+ 'slurpit_netbox',
46
+ ]
47
+ ```
48
+
49
+
50
+
51
+ ### Apply Migrations
52
+
53
+ Use the 'migrate' management command to apply the migration file.
54
+
55
+ ```
56
+ python manage.py migrate slurpit_netbox
57
+ ```
58
+
59
+ After saving the file, start the NetBox development server if it isn't already running.
60
+
61
+ ```
62
+ $ python manage.py runserver 0.0.0.0:8000 --insecure
63
+ ```
64
+
@@ -0,0 +1,48 @@
1
+ ## Compatibility
2
+
3
+ | NetBox Version | Plugin Version |
4
+ |----------------|----------------|
5
+ | NetBox 3.7 | >= 0.8.0 |
6
+
7
+ ## How to install the plugin on your local NetBox server
8
+
9
+ ### Activate the Virtual Environment
10
+
11
+ Firstly, to make the plugin available within NetBox, we must activate the Python virtual environment that was set up during the NetBox installation; you can do this by finding the path of the virtual environment, which typically is /opt/netbox/venv/ if you followed the default installation guide.
12
+
13
+ ```
14
+ $ source /opt/netbox/venv/bin/activate
15
+ ```
16
+
17
+ ### Run setup.py
18
+
19
+ ```
20
+ $ python setup.py develop
21
+ ```
22
+
23
+ ### Configure NetBox
24
+
25
+ To enable our new plugin, we have to configure NetBox by opening the configuration.py file located in the netbox/netbox directory and modifying the PLUGINS parameter.
26
+
27
+ ```
28
+ # configuration.py
29
+ PLUGINS = [
30
+ 'slurpit_netbox',
31
+ ]
32
+ ```
33
+
34
+
35
+
36
+ ### Apply Migrations
37
+
38
+ Use the 'migrate' management command to apply the migration file.
39
+
40
+ ```
41
+ python manage.py migrate slurpit_netbox
42
+ ```
43
+
44
+ After saving the file, start the NetBox development server if it isn't already running.
45
+
46
+ ```
47
+ $ python manage.py runserver 0.0.0.0:8000 --insecure
48
+ ```
@@ -0,0 +1,23 @@
1
+ [tool.poetry]
2
+ name = "slurpit_netbox"
3
+ version = "0.8.36"
4
+ description = ""
5
+ authors = ["Pieter <pieter@slurpit.io>"]
6
+ readme = "README.md"
7
+ packages = [{include = "slurpit_netbox", from = "src"}]
8
+
9
+
10
+ [tool.poetry.dependencies]
11
+ python = "^3.10"
12
+ requests = "^2.31.0"
13
+ djangorestframework-bulk = "^0.2.1"
14
+
15
+
16
+ [tool.poetry.group.develop.dependencies]
17
+ django = "^4.2.6"
18
+ djangorestframework = "^3.14.0"
19
+ django-tables2 = "^2.6.0"
20
+
21
+ [build-system]
22
+ requires = ["poetry-core"]
23
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,39 @@
1
+ import os
2
+
3
+ from django.apps import apps
4
+ from django.db.models.signals import post_migrate
5
+ from extras.plugins import PluginConfig, get_plugin_config
6
+
7
+ class SlurpitConfig(PluginConfig):
8
+ name = "slurpit_netbox"
9
+ verbose_name = "Slurp'it Plugin"
10
+ description = "Sync Slurp'it into NetBox"
11
+ version = '0.8.36'
12
+ base_url = "slurpit"
13
+ default_settings = {
14
+ 'DeviceType': {'model': "Slurp'it", 'slug': 'slurpit'},
15
+ 'DeviceRole': {'name': "Slurp'it", 'slug': 'slurpit'},
16
+ 'Site': {'name': "Slurp'it", 'slug': 'slurpit'},
17
+ 'Location': {'name': 'Slurp\'it', 'slug': 'slurpit'},
18
+ 'Region': {'name': 'Slurp\'it', 'slug': 'slurpit'},
19
+ 'SiteGroup': {'name': 'Slurp\'it', 'slug': 'slurpit'},
20
+ 'Rack': {'name': 'Slurp\'it'},
21
+ 'ConfigTemplate': {'name': 'Slurp\'it'},
22
+ 'Manufacturer': {'name': 'OEM', 'slug': 'oem'},
23
+ 'unattended_import': False,
24
+ 'version': version
25
+ }
26
+
27
+ def ready(self):
28
+ from .models import post_migration
29
+ deps_app = apps.get_app_config("virtualization")
30
+ post_migrate.connect(post_migration, sender=deps_app, weak=False)
31
+ super().ready()
32
+
33
+
34
+ config = SlurpitConfig
35
+
36
+
37
+ def get_config(cfg):
38
+ return get_plugin_config(get_config.__module__, cfg)
39
+
@@ -0,0 +1 @@
1
+ from .serializers import * # noqa: F401, F403
@@ -0,0 +1,55 @@
1
+ from core.choices import DataSourceStatusChoices
2
+ from netbox.api.fields import ChoiceField
3
+ from netbox.api.serializers import NetBoxModelSerializer
4
+ from rest_framework import serializers
5
+
6
+ from slurpit_netbox.models import SlurpitPlanning, SlurpitImportedDevice, SlurpitStagedDevice, SlurpitLog, SlurpitSetting, SlurpitSnapshot, SlurpitMapping
7
+
8
+ __all__ = (
9
+ 'SlurpitPlanningSerializer',
10
+ 'SlurpitStagedDeviceSerializer',
11
+ 'SlurpitImportedDeviceSerializer',
12
+ 'SlurpitLogSerializer',
13
+ 'SlurpitSettingSerializer',
14
+ 'SlurpitSnapshotSerializer'
15
+ )
16
+
17
+ class SlurpitPlanningSerializer(NetBoxModelSerializer):
18
+ id = serializers.IntegerField(source='planning_id')
19
+ comment = serializers.CharField(source='comments')
20
+
21
+ class Meta:
22
+ model = SlurpitPlanning
23
+ fields = ['id', "name", "comment", "display"]
24
+
25
+ class SlurpitStagedDeviceSerializer(serializers.ModelSerializer):
26
+ class Meta:
27
+ model = SlurpitStagedDevice
28
+ fields = '__all__'
29
+
30
+ class SlurpitSnapshotSerializer(serializers.ModelSerializer):
31
+ class Meta:
32
+ model = SlurpitSnapshot
33
+ fields = '__all__'
34
+
35
+
36
+ class SlurpitImportedDeviceSerializer(serializers.ModelSerializer):
37
+ id = serializers.IntegerField(source='slurpit_id')
38
+ class Meta:
39
+ model = SlurpitImportedDevice
40
+ fields = ['id', 'disabled', 'hostname', 'fqdn', 'ipv4', 'device_os', 'device_type', 'brand', 'createddate', 'changeddate']
41
+
42
+ class SlurpitLogSerializer(NetBoxModelSerializer):
43
+ class Meta:
44
+ model = SlurpitLog
45
+ fields = '__all__'
46
+
47
+ class SlurpitSettingSerializer(NetBoxModelSerializer):
48
+ class Meta:
49
+ model = SlurpitSetting
50
+ fields = '__all__'
51
+
52
+ class SlurpitMappingSerializer(NetBoxModelSerializer):
53
+ class Meta:
54
+ model = SlurpitMapping
55
+ fields = '__all__'
@@ -0,0 +1,11 @@
1
+ from netbox.api.routers import NetBoxRouter
2
+ from . import views
3
+
4
+ router = NetBoxRouter()
5
+ router.APIRootView = views.SlurpitRootView
6
+ router.register("planning", views.SlurpitPlanningViewSet)
7
+ router.register("planning-data", views.SlurpitSnapshotViewSet)
8
+ router.register("device", views.DeviceViewSet)
9
+ router.register('test', views.SlurpitTestAPIView)
10
+ app_name = 'slurpit-api'
11
+ urlpatterns = router.urls
@@ -0,0 +1,172 @@
1
+
2
+ from netbox.api.viewsets import NetBoxModelViewSet
3
+ from dcim.models import Device
4
+ from dcim.choices import DeviceStatusChoices
5
+ from slurpit_netbox.models import SlurpitPlanning, SlurpitSnapshot, SlurpitImportedDevice, SlurpitStagedDevice, SlurpitLog
6
+ from slurpit_netbox.filtersets import SlurpitPlanningFilterSet, SlurpitSnapshotFilterSet, SlurpitImportedDeviceFilterSet
7
+ from .serializers import SlurpitPlanningSerializer, SlurpitSnapshotSerializer, SlurpitImportedDeviceSerializer
8
+ from rest_framework.routers import APIRootView
9
+ from rest_framework_bulk import BulkCreateModelMixin, BulkDestroyModelMixin
10
+ from rest_framework.decorators import action
11
+ from rest_framework.response import Response
12
+ from rest_framework.permissions import IsAuthenticated
13
+ from rest_framework.views import APIView
14
+ from rest_framework import status
15
+ from django.db import transaction
16
+ from django.http import JsonResponse
17
+ import json
18
+ from ..validator import device_validator
19
+ from ..importer import process_import, import_devices, import_plannings
20
+ from ..management.choices import *
21
+
22
+ __all__ = (
23
+ 'SlurpitPlanningViewSet',
24
+ 'SlurpitRootView',
25
+ )
26
+
27
+ class SlurpitRootView(APIRootView):
28
+ """
29
+ Slurpit API root view
30
+ """
31
+ def get_view_name(self):
32
+ return 'Slurpit'
33
+
34
+
35
+ class SlurpitPlanningViewSet(
36
+ NetBoxModelViewSet
37
+ ):
38
+ queryset = SlurpitPlanning.objects.all()
39
+ serializer_class = SlurpitPlanningSerializer
40
+ filterset_class = SlurpitPlanningFilterSet
41
+
42
+ @action(detail=False, methods=['delete'], url_path='delete-all')
43
+ def delete_all(self, request, *args, **kwargs):
44
+ """
45
+ A custom action to delete all SlurpitPlanning objects.
46
+ Be careful with this operation: it cannot be undone!
47
+ """
48
+ self.queryset.delete()
49
+ SlurpitSnapshot.objects.all().delete()
50
+ SlurpitLog.info(category=LogCategoryChoices.PLANNING, message=f"Api deleted all snapshots and plannings")
51
+ return Response(status=status.HTTP_204_NO_CONTENT)
52
+
53
+ def get_queryset(self):
54
+ if self.request.method == 'GET':
55
+ # Customize this queryset to suit your requirements for GET requests
56
+ return SlurpitPlanning.objects.filter(selected=True)
57
+ # For other methods, use the default queryset
58
+ return self.queryset
59
+
60
+ @action(detail=False, methods=['delete'], url_path='delete/(?P<planning_id>[^/.]+)')
61
+ def delete(self, request, *args, **kwargs):
62
+ planning_id = kwargs.get('planning_id')
63
+ planning = SlurpitPlanning.objects.filter(planning_id=planning_id).first()
64
+ if not planning:
65
+ return Response(f"Unknown planning id {planning_id}", status=status.HTTP_400_BAD_REQUEST)
66
+
67
+ planning.delete()
68
+ count = SlurpitSnapshot.objects.filter(planning_id=planning_id).delete()[0]
69
+ SlurpitLog.info(category=LogCategoryChoices.PLANNING, message=f"Api deleted all {count} snapshots and planning {planning.name}")
70
+ return Response(status=status.HTTP_204_NO_CONTENT)
71
+
72
+ @action(detail=False, methods=['post'], url_path='sync')
73
+ def sync(self, request):
74
+ if not isinstance(request.data, list):
75
+ return Response("Should be a list", status=status.HTTP_400_BAD_REQUEST)
76
+ import_plannings(request.data)
77
+ return JsonResponse({'status': 'success'})
78
+
79
+ def create(self, request):
80
+ if not isinstance(request.data, list):
81
+ return Response("Should be a list", status=status.HTTP_400_BAD_REQUEST)
82
+
83
+ import_plannings(request.data, False)
84
+ return JsonResponse({'status': 'success'})
85
+
86
+ class SlurpitSnapshotViewSet(
87
+ BulkCreateModelMixin,
88
+ BulkDestroyModelMixin,
89
+ NetBoxModelViewSet
90
+ ):
91
+ queryset = SlurpitSnapshot.objects.all()
92
+ serializer_class = SlurpitSnapshotSerializer
93
+ filterset_class = SlurpitSnapshotFilterSet
94
+
95
+ @action(detail=False, methods=['delete'], url_path='delete-all/(?P<hostname>[^/.]+)/(?P<planning_id>[^/.]+)')
96
+ def delete_all(self, request, *args, **kwargs):
97
+ planning_id = kwargs.get('planning_id')
98
+ planning = SlurpitPlanning.objects.filter(planning_id=planning_id).first()
99
+ if not planning:
100
+ return Response(f"Unknown planning id {planning_id}", status=status.HTTP_400_BAD_REQUEST)
101
+
102
+ hostname = kwargs.get('hostname')
103
+ if not hostname:
104
+ return Response(f"No hostname was given", status=status.HTTP_400_BAD_REQUEST)
105
+
106
+ count = SlurpitSnapshot.objects.filter(hostname=hostname, planning_id=planning_id).delete()[0]
107
+
108
+ SlurpitLog.info(category=LogCategoryChoices.PLANNING, message=f"Api deleted all {count} snapshots for planning {planning.name} and hostname {hostname}")
109
+
110
+ return Response(status=status.HTTP_204_NO_CONTENT)
111
+
112
+ @action(detail=False, methods=['delete'], url_path='clear/(?P<planning_id>[^/.]+)')
113
+ def clear(self, request, *args, **kwargs):
114
+ planning_id = kwargs.get('planning_id')
115
+ planning = SlurpitPlanning.objects.filter(planning_id=planning_id).first()
116
+ if not planning:
117
+ return Response(f"Unknown planning id {planning_id}", status=status.HTTP_400_BAD_REQUEST)
118
+ count = SlurpitSnapshot.objects.filter(planning_id=planning_id).delete()[0]
119
+ SlurpitLog.info(category=LogCategoryChoices.PLANNING, message=f"Api deleted all {count} snapshots for planning {planning.name}")
120
+
121
+ return Response(status=status.HTTP_204_NO_CONTENT)
122
+
123
+ class DeviceViewSet(
124
+ BulkCreateModelMixin,
125
+ BulkDestroyModelMixin,
126
+ NetBoxModelViewSet
127
+ ):
128
+ queryset = SlurpitImportedDevice.objects.all()
129
+ serializer_class = SlurpitImportedDeviceSerializer
130
+ filterset_class = SlurpitImportedDeviceFilterSet
131
+
132
+ @action(detail=False, methods=['delete'], url_path='delete-all')
133
+ def delete_all(self, request, *args, **kwargs):
134
+ with transaction.atomic():
135
+ Device.objects.select_related('slurpitimporteddevice').update(status=DeviceStatusChoices.STATUS_OFFLINE)
136
+ SlurpitStagedDevice.objects.all().delete()
137
+ SlurpitImportedDevice.objects.filter(mapped_device__isnull=True).delete()
138
+
139
+ return Response(status=status.HTTP_204_NO_CONTENT)
140
+
141
+ @action(detail=False, methods=['delete'], url_path='delete/(?P<hostname>[^/.]+)')
142
+ def delete(self, request, *args, **kwargs):
143
+ hostname_to_delete = kwargs.get('hostname')
144
+ with transaction.atomic():
145
+ to_delete = SlurpitImportedDevice.objects.filter(hostname=hostname_to_delete)
146
+ Device.objects.filter(slurpitimporteddevice__in=to_delete).update(status=DeviceStatusChoices.STATUS_OFFLINE)
147
+ to_delete.filter(mapped_device__isnull=True).delete()
148
+ SlurpitStagedDevice.objects.filter(hostname=hostname_to_delete).delete()
149
+
150
+ return Response(status=status.HTTP_204_NO_CONTENT)
151
+
152
+ def create(self, request):
153
+ errors = device_validator(request.data)
154
+
155
+ if errors:
156
+ return JsonResponse({'status': 'error', 'errors': errors}, status=400)
157
+
158
+ import_devices(request.data)
159
+ process_import(delete=False)
160
+
161
+ return JsonResponse({'status': 'success'})
162
+
163
+ class SlurpitTestAPIView(NetBoxModelViewSet):
164
+ queryset = SlurpitImportedDevice.objects.all()
165
+ serializer_class = SlurpitImportedDeviceSerializer
166
+ filterset_class = SlurpitImportedDeviceFilterSet
167
+
168
+ permission_classes = [IsAuthenticated]
169
+
170
+ @action(detail=False, methods=['get'], url_path='api')
171
+ def api(self, request, *args, **kwargs):
172
+ return JsonResponse({'status': 'success'})
@@ -0,0 +1,57 @@
1
+ from functools import wraps
2
+ from .models import SlurpitSetting
3
+ from django.core.exceptions import ObjectDoesNotExist
4
+ from django.contrib import messages
5
+ from account.models import UserToken
6
+
7
+ def slurpit_plugin_registered(view_func):
8
+ @wraps(view_func)
9
+ def _wrapped_view(request, *args, **kwargs):
10
+
11
+ paths = [
12
+ 'plugins/slurpit/settings/',
13
+ 'plugins/slurpit/devices/',
14
+ 'plugins/slurpit/data_mapping/',
15
+ 'plugins/slurpit/reconcile/',
16
+ 'plugins/slurpit/slurpitlog/'
17
+ ]
18
+
19
+ for path in paths:
20
+ if path in request.path and request.method == 'GET':
21
+ # Ignore test case
22
+ test_param = request.GET.get('test',None)
23
+ if test_param == 'test':
24
+ continue
25
+
26
+ appliance_type_param = request.GET.get('appliance_type', None)
27
+ if appliance_type_param:
28
+ continue
29
+
30
+ reset_param = request.GET.get('reset', None)
31
+ if reset_param:
32
+ continue
33
+
34
+ tokens = UserToken.objects.filter(user=request.user).count()
35
+
36
+ if tokens == 0:
37
+ messages.warning(request, "To use the Slurp'it plugin, it is necessary to first generate a Plugin API Key on the Setting Page.")
38
+ return view_func(request, *args, **kwargs)
39
+
40
+ try:
41
+ setting = SlurpitSetting.objects.get()
42
+ server_url = setting.server_url
43
+ api_key = setting.api_key
44
+ appliance_type = setting.appliance_type
45
+
46
+ if appliance_type == '':
47
+ messages.warning(request, "To use the Slurp'it plugin, it is necessary to first select the Appliance Type on the Setting Page.")
48
+ elif appliance_type != 'cloud' and (api_key == '' or server_url == ''):
49
+ messages.warning(request, "To use the Slurp'it plugin, you should first configure the server settings. Go to settings and configure the Slurp'it server in the parameter section.")
50
+ except Exception as e:
51
+ setting = None
52
+ messages.warning(request, "To use the Slurp'it plugin, it is necessary to first select the Appliance Type on the Setting Page.")
53
+
54
+ return view_func(request, *args, **kwargs)
55
+
56
+ return view_func(request, *args, **kwargs)
57
+ return _wrapped_view
@@ -0,0 +1,79 @@
1
+ import django_filters
2
+ from core.choices import DataSourceStatusChoices
3
+ from django.db.models import Q
4
+ from netbox.filtersets import NetBoxModelFilterSet, BaseFilterSet
5
+ from .models import SlurpitLog, SlurpitPlanning, SlurpitSnapshot, SlurpitImportedDevice
6
+ from django.utils.translation import gettext as _
7
+
8
+
9
+ class LoggingFilterSet(BaseFilterSet):
10
+ q = django_filters.CharFilter(
11
+ method='search',
12
+ label=_('Search'),
13
+ )
14
+
15
+ class Meta:
16
+ model = SlurpitLog
17
+ fields = [
18
+ 'log_time', 'level', 'category', 'message'
19
+ ]
20
+
21
+ def search(self, queryset, name, value):
22
+ if not value.strip():
23
+ return queryset
24
+ return queryset.filter(
25
+ Q(level__icontains=value) |
26
+ Q(category__icontains=value) |
27
+ Q(message__icontains=value)
28
+ )
29
+
30
+ class SlurpitPlanningFilterSet(BaseFilterSet):
31
+ q = django_filters.CharFilter(
32
+ method='search',
33
+ label=_('Search'),
34
+ )
35
+
36
+ class Meta:
37
+ model = SlurpitPlanning
38
+ fields = ["id", "name", "planning_id"]
39
+
40
+ def search(self, queryset, name, value):
41
+ if not value.strip():
42
+ return queryset
43
+ return queryset.filter(
44
+ Q(name__icontains=value)
45
+ )
46
+
47
+ class SlurpitSnapshotFilterSet(BaseFilterSet):
48
+ q = django_filters.CharFilter(
49
+ method='search',
50
+ label=_('Search'),
51
+ )
52
+
53
+ class Meta:
54
+ model = SlurpitSnapshot
55
+ fields = ["id", "hostname", "planning_id"]
56
+
57
+ def search(self, queryset, name, value):
58
+ if not value.strip():
59
+ return queryset
60
+ return queryset.filter(
61
+ Q(name__icontains=value)
62
+ )
63
+
64
+ class SlurpitImportedDeviceFilterSet(BaseFilterSet):
65
+ q = django_filters.CharFilter(
66
+ method='search',
67
+ label=_('Search'),
68
+ )
69
+
70
+ class Meta:
71
+ model = SlurpitImportedDevice
72
+ fields = ["id", "hostname"]
73
+
74
+ def search(self, queryset, name, value):
75
+ if not value.strip():
76
+ return queryset
77
+ return queryset.filter(
78
+ Q(name__icontains=value)
79
+ )