From b492af169f1d8c0ab6bff69d1c5d4fa9f389c9d8 Mon Sep 17 00:00:00 2001 From: Kevin Petremann Date: Thu, 22 Aug 2024 14:39:26 +0200 Subject: [PATCH] feat(decomm): endpoint to decomm a device + rationalize endpoints --- netbox_cmdb/netbox_cmdb/api/cmdb/views.py | 62 +++++++++++++++++++---- netbox_cmdb/netbox_cmdb/api/urls.py | 23 ++++++--- 2 files changed, 69 insertions(+), 16 deletions(-) diff --git a/netbox_cmdb/netbox_cmdb/api/cmdb/views.py b/netbox_cmdb/netbox_cmdb/api/cmdb/views.py index 6e5ab14..1315d80 100644 --- a/netbox_cmdb/netbox_cmdb/api/cmdb/views.py +++ b/netbox_cmdb/netbox_cmdb/api/cmdb/views.py @@ -10,16 +10,16 @@ from netbox_cmdb.helpers import cleaning -class DeleteAllCMDBObjectsRelatedToDeviceSerializer(serializers.Serializer): +class DeviceDecommissioningBaseSerializer(serializers.Serializer): device_name = serializers.CharField() -class DeleteAllCMDBObjectsRelatedToDevice(APIView): +class DeviceCMDBDecommissioningAPIView(APIView): permission_classes = [IsAuthenticatedOrLoginNotRequired] @swagger_auto_schema( - request_body=DeleteAllCMDBObjectsRelatedToDeviceSerializer, + request_body=DeviceDecommissioningBaseSerializer, responses={ status.HTTP_200_OK: "Objects related to device have been deleted successfully", status.HTTP_400_BAD_REQUEST: "Bad Request: Device name is required", @@ -31,7 +31,7 @@ def delete(self, request): device_name = request.data.get("device_name", None) if device_name is None: return Response( - {"error": "device name is required"}, status=status.HTTP_400_BAD_REQUEST + {"error": "device_name is required"}, status=status.HTTP_400_BAD_REQUEST ) devices = Device.objects.filter(name=device_name) @@ -49,23 +49,67 @@ def delete(self, request): return Response( { - "message": f"objects related to device {device_name} have been deleted successfully", + "message": f"CMDB cleaned for {device_name}", "deleted": deleted, }, status=status.HTTP_200_OK, ) -class DecommissionSiteSerializer(serializers.Serializer): +class DeviceDecommissioningAPIView(APIView): + + permission_classes = [IsAuthenticatedOrLoginNotRequired] + + @swagger_auto_schema( + request_body=DeviceDecommissioningBaseSerializer, + responses={ + status.HTTP_200_OK: "Objects related to device have been deleted successfully", + status.HTTP_400_BAD_REQUEST: "Bad Request: Device name is required", + status.HTTP_404_NOT_FOUND: "Bad Request: Device not found", + status.HTTP_500_INTERNAL_SERVER_ERROR: "Internal Server Error: Something went wrong on the server", + }, + ) + def delete(self, request): + device_name = request.data.get("device_name", None) + if device_name is None: + return Response( + {"error": "device_name is required"}, status=status.HTTP_400_BAD_REQUEST + ) + + devices = Device.objects.filter(name=device_name) + device_ids = [dev.id for dev in devices] + if not device_ids: + return Response( + {"error": "no matching devices found"}, status=status.HTTP_404_NOT_FOUND + ) + + try: + with transaction.atomic(): + deleted = cleaning.clean_cmdb_for_devices(device_ids) + for device in devices: + device.delete() + except Exception as e: + return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + return Response( + { + "message": f"{device_name} decommissionned", + "deleted": deleted, + }, + status=status.HTTP_200_OK, + ) + + +class SiteDecommissioningSerializer(serializers.Serializer): site_name = serializers.CharField() -class DecommissionSite(APIView): +class SiteDecommissioningAPIView(APIView): permission_classes = [IsAuthenticatedOrLoginNotRequired] @swagger_auto_schema( - request_body=DecommissionSiteSerializer, + request_body=SiteDecommissioningSerializer, responses={ status.HTTP_200_OK: "Site have been deleted successfully", status.HTTP_400_BAD_REQUEST: "Bad Request: Site name is required", @@ -76,7 +120,7 @@ class DecommissionSite(APIView): def delete(self, request): site_name = request.data.get("site_name", None) if site_name is None: - return Response({"error": "site name is required"}, status=status.HTTP_400_BAD_REQUEST) + return Response({"error": "site_name is required"}, status=status.HTTP_400_BAD_REQUEST) try: site = Site.objects.get(name=site_name) diff --git a/netbox_cmdb/netbox_cmdb/api/urls.py b/netbox_cmdb/netbox_cmdb/api/urls.py index e98f5d9..160339c 100644 --- a/netbox_cmdb/netbox_cmdb/api/urls.py +++ b/netbox_cmdb/netbox_cmdb/api/urls.py @@ -13,7 +13,11 @@ from netbox_cmdb.api.prefix_list.views import PrefixListViewSet from netbox_cmdb.api.route_policy.views import RoutePolicyViewSet from netbox_cmdb.api.snmp.views import SNMPCommunityViewSet, SNMPViewSet -from netbox_cmdb.api.cmdb.views import DeleteAllCMDBObjectsRelatedToDevice, DecommissionSite +from netbox_cmdb.api.cmdb.views import ( + DeviceCMDBDecommissioningAPIView, + DeviceDecommissioningAPIView, + SiteDecommissioningAPIView, +) router = NetBoxRouter() @@ -35,14 +39,19 @@ name="asns-available-asn", ), path( - "management/delete-all-objects/", - DeleteAllCMDBObjectsRelatedToDevice.as_view(), - name="delete-all-objects", + "management/device-cmdb-decommissioning/", + DeviceCMDBDecommissioningAPIView.as_view(), + name="device-cmdb-decommissioning", + ), + path( + "management/device-decommissioning/", + DeviceDecommissioningAPIView.as_view(), + name="device-decommissioning", ), path( - "management/decommission-site/", - DecommissionSite.as_view(), - name="decommission-site", + "management/site-decommissioning/", + SiteDecommissioningAPIView.as_view(), + name="site-decommissioning", ), ] urlpatterns += router.urls