Initial push to public repo

This commit is contained in:
Jeremy Stretch
2016-03-01 11:23:03 -05:00
commit 27b289ee3b
281 changed files with 26061 additions and 0 deletions

View File

View File

@@ -0,0 +1,6 @@
from rest_framework.exceptions import APIException
class MissingFilterException(APIException):
status_code = 400
default_detail = "One or more required filters is missing from the request."

View File

@@ -0,0 +1,300 @@
from rest_framework import serializers
from ipam.models import IPAddress
from dcim.models import Site, Rack, RackGroup, Manufacturer, DeviceType, DeviceRole, Platform, Device, ConsolePort,\
ConsoleServerPort, PowerPort, PowerOutlet, Interface, InterfaceConnection, RACK_FACE_FRONT, RACK_FACE_REAR
#
# Sites
#
class SiteSerializer(serializers.ModelSerializer):
class Meta:
model = Site
fields = ['id', 'name', 'slug', 'facility', 'asn', 'physical_address', 'shipping_address', 'comments',
'count_prefixes', 'count_vlans', 'count_racks', 'count_devices', 'count_circuits']
class SiteNestedSerializer(SiteSerializer):
class Meta(SiteSerializer.Meta):
fields = ['id', 'name', 'slug']
#
# Rack groups
#
class RackGroupSerializer(serializers.ModelSerializer):
site = SiteNestedSerializer()
class Meta:
model = RackGroup
fields = ['id', 'name', 'slug', 'site']
class RackGroupNestedSerializer(SiteSerializer):
class Meta(SiteSerializer.Meta):
fields = ['id', 'name', 'slug']
#
# Racks
#
class RackSerializer(serializers.ModelSerializer):
display_name = serializers.SerializerMethodField()
site = SiteNestedSerializer()
group = RackGroupNestedSerializer()
class Meta:
model = Rack
fields = ['id', 'name', 'facility_id', 'display_name', 'site', 'group', 'u_height', 'comments']
def get_display_name(self, obj):
return str(obj)
class RackNestedSerializer(RackSerializer):
class Meta(RackSerializer.Meta):
fields = ['id', 'name', 'facility_id', 'display_name']
class RackDetailSerializer(RackSerializer):
front_units = serializers.SerializerMethodField()
rear_units = serializers.SerializerMethodField()
class Meta(RackSerializer.Meta):
fields = ['id', 'name', 'facility_id', 'display_name', 'site', 'group', 'u_height', 'comments', 'front_units',
'rear_units']
def get_front_units(self, obj):
units = obj.get_rack_units(face=RACK_FACE_FRONT)
for u in units:
u['device'] = DeviceNestedSerializer(u['device']).data if u['device'] else None
return units
def get_rear_units(self, obj):
units = obj.get_rack_units(face=RACK_FACE_REAR)
for u in units:
u['device'] = DeviceNestedSerializer(u['device']).data if u['device'] else None
return units
#
# Manufacturers
#
class ManufacturerSerializer(serializers.ModelSerializer):
class Meta:
model = Manufacturer
fields = ['id', 'name', 'slug']
class ManufacturerNestedSerializer(ManufacturerSerializer):
class Meta(ManufacturerSerializer.Meta):
pass
#
# Device types
#
class DeviceTypeSerializer(serializers.ModelSerializer):
manufacturer = ManufacturerNestedSerializer()
class Meta:
model = DeviceType
fields = ['id', 'manufacturer', 'model', 'slug', 'u_height', 'is_console_server', 'is_pdu', 'is_network_device']
class DeviceTypeNestedSerializer(DeviceTypeSerializer):
class Meta(DeviceTypeSerializer.Meta):
fields = ['id', 'manufacturer', 'model', 'slug']
#
# Device roles
#
class DeviceRoleSerializer(serializers.ModelSerializer):
class Meta:
model = DeviceRole
fields = ['id', 'name', 'slug', 'color']
class DeviceRoleNestedSerializer(DeviceRoleSerializer):
class Meta(DeviceRoleSerializer.Meta):
fields = ['id', 'name', 'slug']
#
# Platforms
#
class PlatformSerializer(serializers.ModelSerializer):
class Meta:
model = Platform
fields = ['id', 'name', 'slug', 'rpc_client']
class PlatformNestedSerializer(PlatformSerializer):
class Meta(PlatformSerializer.Meta):
fields = ['id', 'name', 'slug']
#
# Devices
#
# Cannot import ipam.api.IPAddressNestedSerializer due to circular dependency
class DeviceIPAddressNestedSerializer(serializers.ModelSerializer):
class Meta:
model = IPAddress
fields = ['id', 'family', 'address']
class DeviceSerializer(serializers.ModelSerializer):
device_type = DeviceTypeNestedSerializer()
device_role = DeviceRoleNestedSerializer()
platform = PlatformNestedSerializer()
rack = RackNestedSerializer()
primary_ip = DeviceIPAddressNestedSerializer()
class Meta:
model = Device
fields = ['id', 'name', 'display_name', 'device_type', 'device_role', 'platform', 'serial', 'rack', 'position',
'face', 'status', 'primary_ip', 'ro_snmp', 'comments']
class DeviceNestedSerializer(DeviceSerializer):
class Meta(DeviceSerializer.Meta):
model = Device
fields = ['id', 'name']
#
# Console server ports
#
class ConsoleServerPortSerializer(serializers.ModelSerializer):
device = DeviceNestedSerializer()
class Meta:
model = ConsoleServerPort
fields = ['id', 'device', 'name', 'connected_console']
class ConsoleServerPortNestedSerializer(ConsoleServerPortSerializer):
class Meta(ConsoleServerPortSerializer.Meta):
fields = ['id', 'device', 'name']
#
# Console ports
#
class ConsolePortSerializer(serializers.ModelSerializer):
device = DeviceNestedSerializer()
cs_port = ConsoleServerPortNestedSerializer()
class Meta:
model = ConsolePort
fields = ['id', 'device', 'name', 'cs_port', 'connection_status']
class ConsolePortNestedSerializer(ConsolePortSerializer):
class Meta(ConsolePortSerializer.Meta):
fields = ['id', 'device', 'name']
#
# Power outlets
#
class PowerOutletSerializer(serializers.ModelSerializer):
device = DeviceNestedSerializer()
class Meta:
model = PowerOutlet
fields = ['id', 'device', 'name', 'connected_port']
class PowerOutletNestedSerializer(PowerOutletSerializer):
class Meta(PowerOutletSerializer.Meta):
fields = ['id', 'device', 'name']
#
# Power ports
#
class PowerPortSerializer(serializers.ModelSerializer):
device = DeviceNestedSerializer()
power_outlet = PowerOutletNestedSerializer()
class Meta:
model = PowerPort
fields = ['id', 'device', 'name', 'power_outlet', 'connection_status']
class PowerPortNestedSerializer(PowerPortSerializer):
class Meta(PowerPortSerializer.Meta):
fields = ['id', 'device', 'name']
#
# Interfaces
#
class InterfaceSerializer(serializers.ModelSerializer):
device = DeviceNestedSerializer()
form_factor = serializers.ReadOnlyField(source='get_form_factor_display')
class Meta:
model = Interface
fields = ['id', 'device', 'name', 'form_factor', 'mgmt_only', 'description', 'is_connected']
class InterfaceNestedSerializer(InterfaceSerializer):
form_factor = serializers.ReadOnlyField(source='get_form_factor_display')
class Meta(InterfaceSerializer.Meta):
fields = ['id', 'device', 'name']
class InterfaceDetailSerializer(InterfaceSerializer):
connected_interface = InterfaceSerializer(source='get_connected_interface')
class Meta(InterfaceSerializer.Meta):
fields = ['id', 'device', 'name', 'form_factor', 'mgmt_only', 'description', 'is_connected',
'connected_interface']
#
# Interface connections
#
class InterfaceConnectionSerializer(serializers.ModelSerializer):
class Meta:
model = InterfaceConnection
fields = ['id', 'interface_a', 'interface_b', 'connection_status']

581
netbox/dcim/api/tests.py Normal file
View File

@@ -0,0 +1,581 @@
import json
from rest_framework import status
from rest_framework.test import APITestCase
class SiteTest(APITestCase):
fixtures = [
'dcim',
'ipam',
'extras',
]
standard_fields = [
'id',
'name',
'slug',
'facility',
'asn',
'physical_address',
'shipping_address',
'comments',
'count_prefixes',
'count_vlans',
'count_racks',
'count_devices',
'count_circuits'
]
nested_fields = [
'id',
'name',
'slug'
]
rack_fields = [
'id',
'name',
'facility_id',
'display_name',
'site',
'group',
'u_height',
'comments'
]
graph_fields = [
'name',
'embed_url',
'link',
]
def test_get_list(self, endpoint='/api/dcim/sites/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
def test_get_detail(self, endpoint='/api/dcim/sites/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.standard_fields),
)
def test_get_site_list_rack(self, endpoint='/api/dcim/sites/1/racks/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in json.loads(response.content):
self.assertEqual(
sorted(i.keys()),
sorted(self.rack_fields),
)
# Check Nested Serializer.
self.assertEqual(
sorted(i.get('site').keys()),
sorted(self.nested_fields),
)
def test_get_site_list_graphs(self, endpoint='/api/dcim/sites/1/graphs/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in json.loads(response.content):
self.assertEqual(
sorted(i.keys()),
sorted(self.graph_fields),
)
class RackTest(APITestCase):
fixtures = [
'dcim',
'ipam'
]
nested_fields = [
'id',
'name',
'facility_id',
'display_name'
]
standard_fields = [
'id',
'name',
'facility_id',
'display_name',
'site',
'group',
'u_height',
'comments'
]
detail_fields = [
'id',
'name',
'facility_id',
'display_name',
'site',
'group',
'u_height',
'comments',
'front_units',
'rear_units'
]
def test_get_list(self, endpoint='/api/dcim/racks/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(i.get('site').keys()),
sorted(SiteTest.nested_fields),
)
def test_get_detail(self, endpoint='/api/dcim/racks/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.detail_fields),
)
self.assertEqual(
sorted(content.get('site').keys()),
sorted(SiteTest.nested_fields),
)
class ManufacturersTest(APITestCase):
fixtures = [
'dcim',
'ipam'
]
standard_fields = [
'id',
'name',
'slug',
]
nested_fields = standard_fields
def test_get_list(self, endpoint='/api/dcim/manufacturers/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
def test_get_detail(self, endpoint='/api/dcim/manufacturers/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.standard_fields),
)
class DeviceTypeTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = [
'id',
'manufacturer',
'model',
'slug',
'u_height',
'is_console_server',
'is_pdu',
'is_network_device'
]
nested_fields = [
'id',
'manufacturer',
'model',
'slug'
]
def test_get_list(self, endpoint='/api/dcim/device-types/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
def test_detail_list(self, endpoint='/api/dcim/device-types/1/'):
# TODO: details returns list view.
# response = self.client.get(endpoint)
# content = json.loads(response.content)
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(
# sorted(content.keys()),
# sorted(self.standard_fields),
# )
# self.assertEqual(
# sorted(content.get('manufacturer').keys()),
# sorted(ManufacturersTest.nested_fields),
# )
pass
class DeviceRolesTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = ['id', 'name', 'slug', 'color']
nested_fields = ['id', 'name', 'slug']
def test_get_list(self, endpoint='/api/dcim/device-roles/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
def test_get_detail(self, endpoint='/api/dcim/device-roles/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.standard_fields),
)
class PlatformsTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = ['id', 'name', 'slug', 'rpc_client']
nested_fields = ['id', 'name', 'slug']
def test_get_list(self, endpoint='/api/dcim/platforms/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
def test_get_detail(self, endpoint='/api/dcim/platforms/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.standard_fields),
)
class DeviceTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = [
'id',
'name',
'display_name',
'device_type',
'device_role',
'platform',
'serial',
'rack',
'position',
'face',
'status',
'primary_ip',
'ro_snmp',
'comments',
]
nested_fields = ['id', 'name']
def test_get_list(self, endpoint='/api/dcim/devices/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for device in content:
self.assertEqual(
sorted(device.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(device.get('device_type')),
sorted(DeviceTypeTest.nested_fields),
)
self.assertEqual(
sorted(device.get('device_role')),
sorted(DeviceRolesTest.nested_fields),
)
if device.get('platform'):
self.assertEqual(
sorted(device.get('platform')),
sorted(PlatformsTest.nested_fields),
)
self.assertEqual(
sorted(device.get('rack')),
sorted(RackTest.nested_fields),
)
def test_get_detail(self, endpoint='/api/dcim/devices/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.standard_fields),
)
class ConsoleServerPortsTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = ['id', 'device', 'name', 'connected_console']
nested_fields = ['id', 'device', 'name']
def test_get_list(self, endpoint='/api/dcim/devices/9/console-server-ports/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for console_port in content:
self.assertEqual(
sorted(console_port.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(console_port.get('device')),
sorted(DeviceTest.nested_fields),
)
class ConsolePortsTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = ['id', 'device', 'name', 'cs_port', 'connection_status']
nested_fields = ['id', 'device', 'name']
def test_get_list(self, endpoint='/api/dcim/devices/1/console-ports/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for console_port in content:
self.assertEqual(
sorted(console_port.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(console_port.get('device')),
sorted(DeviceTest.nested_fields),
)
self.assertEqual(
sorted(console_port.get('cs_port')),
sorted(ConsoleServerPortsTest.nested_fields),
)
def test_get_detail(self, endpoint='/api/dcim/console-ports/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(content.get('device')),
sorted(DeviceTest.nested_fields),
)
class PowerPortsTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = ['id', 'device', 'name', 'power_outlet', 'connection_status']
nested_fields = ['id', 'device', 'name']
def test_get_list(self, endpoint='/api/dcim/devices/1/power-ports/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(i.get('device')),
sorted(DeviceTest.nested_fields),
)
def test_get_detail(self, endpoint='/api/dcim/power-ports/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(content.get('device')),
sorted(DeviceTest.nested_fields),
)
class PowerOutletsTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = ['id', 'device', 'name', 'connected_port']
nested_fields = ['id', 'device', 'name']
def test_get_list(self, endpoint='/api/dcim/devices/11/power-outlets/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(i.get('device')),
sorted(DeviceTest.nested_fields),
)
class InterfaceTest(APITestCase):
fixtures = ['dcim', 'ipam', 'extras']
standard_fields = [
'id',
'device',
'name',
'form_factor',
'mgmt_only',
'description',
'is_connected'
]
nested_fields = ['id', 'device', 'name']
detail_fields = [
'id',
'device',
'name',
'form_factor',
'mgmt_only',
'description',
'is_connected',
'connected_interface'
]
connection_fields = [
'id',
'interface_a',
'interface_b',
'connection_status',
]
def test_get_list(self, endpoint='/api/dcim/devices/1/interfaces/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(self.standard_fields),
)
self.assertEqual(
sorted(i.get('device')),
sorted(DeviceTest.nested_fields),
)
def test_get_detail(self, endpoint='/api/dcim/interfaces/1/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.detail_fields),
)
self.assertEqual(
sorted(content.get('device')),
sorted(DeviceTest.nested_fields),
)
def test_get_graph_list(self, endpoint='/api/dcim/interfaces/1/graphs/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
for i in content:
self.assertEqual(
sorted(i.keys()),
sorted(SiteTest.graph_fields),
)
def test_get_interface_connections(self, endpoint='/api/dcim/interface-connections/4/'):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.connection_fields),
)
class RelatedConnectionsTest(APITestCase):
fixtures = ['dcim', 'ipam']
standard_fields = [
'device',
'console-ports',
'power-ports',
'interfaces',
]
def test_get_list(self, endpoint=(
'/api/dcim/related-connections/'
'?peer-device=test1-edge1&peer-interface=xe-0/0/3')):
response = self.client.get(endpoint)
content = json.loads(response.content)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
sorted(content.keys()),
sorted(self.standard_fields),
)

66
netbox/dcim/api/urls.py Normal file
View File

@@ -0,0 +1,66 @@
from django.conf.urls import url
from extras.models import GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
from extras.api.views import GraphListView
from .views import *
urlpatterns = [
# Sites
url(r'^sites/$', SiteListView.as_view(), name='site_list'),
url(r'^sites/(?P<pk>\d+)/$', SiteDetailView.as_view(), name='site_detail'),
url(r'^sites/(?P<pk>\d+)/graphs/$', GraphListView.as_view(), {'type': GRAPH_TYPE_SITE}, name='site_graphs'),
url(r'^sites/(?P<site>\d+)/racks/$', RackListView.as_view(), name='site_racks'),
# Rack groups
url(r'^rack-groups/$', RackGroupListView.as_view(), name='rackgroup_list'),
url(r'^rack-groups/(?P<pk>\d+)/$', RackGroupDetailView.as_view(), name='rackgroup_detail'),
# Racks
url(r'^racks/$', RackListView.as_view(), name='rack_list'),
url(r'^racks/(?P<pk>\d+)/$', RackDetailView.as_view(), name='rack_detail'),
url(r'^racks/(?P<pk>\d+)/rack-units/$', RackUnitListView.as_view(), name='rack_units'),
# Manufacturers
url(r'^manufacturers/$', ManufacturerListView.as_view(), name='manufacturer_list'),
url(r'^manufacturers/(?P<pk>\d+)/$', ManufacturerDetailView.as_view(), name='manufacturer_detail'),
# Device types
url(r'^device-types/$', DeviceTypeListView.as_view(), name='devicetype_list'),
url(r'^device-types/(?P<pk>\d+)/$', DeviceTypeDetailView.as_view(), name='devicetype_detail'),
# Device roles
url(r'^device-roles/$', DeviceRoleListView.as_view(), name='devicerole_list'),
url(r'^device-roles/(?P<pk>\d+)/$', DeviceRoleDetailView.as_view(), name='devicerole_detail'),
# Platforms
url(r'^platforms/$', PlatformListView.as_view(), name='platform_list'),
url(r'^platforms/(?P<pk>\d+)/$', PlatformDetailView.as_view(), name='platform_detail'),
# Devices
url(r'^devices/$', DeviceListView.as_view(), name='device_list'),
url(r'^devices/(?P<pk>\d+)/$', DeviceDetailView.as_view(), name='device_detail'),
url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', LLDPNeighborsView.as_view(), name='device_lldp-neighbors'),
url(r'^devices/(?P<pk>\d+)/console-ports/$', ConsolePortListView.as_view(), name='device_consoleports'),
url(r'^devices/(?P<pk>\d+)/console-server-ports/$', ConsoleServerPortListView.as_view(), name='device_consoleserverports'),
url(r'^devices/(?P<pk>\d+)/power-ports/$', PowerPortListView.as_view(), name='device_powerports'),
url(r'^devices/(?P<pk>\d+)/power-outlets/$', PowerOutletListView.as_view(), name='device_poweroutlets'),
url(r'^devices/(?P<pk>\d+)/interfaces/$', InterfaceListView.as_view(), name='device_interfaces'),
# Console ports
url(r'^console-ports/(?P<pk>\d+)/$', ConsolePortView.as_view(), name='consoleport'),
# Power ports
url(r'^power-ports/(?P<pk>\d+)/$', PowerPortView.as_view(), name='powerport'),
# Interfaces
url(r'^interfaces/(?P<pk>\d+)/$', InterfaceDetailView.as_view(), name='interface_detail'),
url(r'^interfaces/(?P<pk>\d+)/graphs/$', GraphListView.as_view(), {'type': GRAPH_TYPE_INTERFACE}, name='interface_graphs'),
url(r'^interface-connections/(?P<pk>\d+)/$', InterfaceConnectionView.as_view(), name='interfaceconnection'),
# Miscellaneous
url(r'^related-connections/$', RelatedConnectionsView.as_view(), name='related_connections'),
]

438
netbox/dcim/api/views.py Normal file
View File

@@ -0,0 +1,438 @@
from rest_framework import generics
from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.views import APIView
from django.conf import settings
from django.http import Http404
from django.shortcuts import get_object_or_404
from dcim.models import Site, Rack, RackGroup, Manufacturer, DeviceType, DeviceRole, Platform, Device, ConsolePort, \
ConsoleServerPort, PowerPort, PowerOutlet, Interface, InterfaceConnection, IFACE_FF_VIRTUAL
from dcim.filters import RackGroupFilter, RackFilter, DeviceTypeFilter, DeviceFilter, InterfaceFilter
from .exceptions import MissingFilterException
from .serializers import SiteSerializer, RackGroupSerializer, RackSerializer, RackDetailSerializer, \
ManufacturerSerializer, DeviceTypeSerializer, DeviceRoleSerializer, PlatformSerializer, DeviceSerializer, \
DeviceNestedSerializer, ConsolePortSerializer, ConsoleServerPortSerializer, PowerPortSerializer, \
PowerOutletSerializer, InterfaceSerializer, InterfaceDetailSerializer, InterfaceConnectionSerializer
from extras.api.renderers import BINDZoneRenderer
from utilities.api import ServiceUnavailable
#
# Sites
#
class SiteListView(generics.ListAPIView):
"""
List all sites
"""
queryset = Site.objects.all()
serializer_class = SiteSerializer
class SiteDetailView(generics.RetrieveAPIView):
"""
Retrieve a single site
"""
queryset = Site.objects.all()
serializer_class = SiteSerializer
#
# Rack groups
#
class RackGroupListView(generics.ListAPIView):
"""
List all rack groups
"""
queryset = RackGroup.objects.all()
serializer_class = RackGroupSerializer
filter_class = RackGroupFilter
class RackGroupDetailView(generics.RetrieveAPIView):
"""
Retrieve a single rack group
"""
queryset = RackGroup.objects.all()
serializer_class = RackGroupSerializer
#
# Racks
#
class RackListView(generics.ListAPIView):
"""
List racks (filterable)
"""
queryset = Rack.objects.select_related('site')
serializer_class = RackSerializer
filter_class = RackFilter
class RackDetailView(generics.RetrieveAPIView):
"""
Retrieve a single rack
"""
queryset = Rack.objects.select_related('site')
serializer_class = RackDetailSerializer
#
# Rack units
#
class RackUnitListView(APIView):
"""
List rack units (by rack)
"""
def get(self, request, pk):
rack = get_object_or_404(Rack, pk=pk)
face = request.GET.get('face', 0)
elevation = rack.get_rack_units(face)
# Serialize Devices within the rack elevation
for u in elevation:
if u['device']:
u['device'] = DeviceNestedSerializer(instance=u['device']).data
return Response(elevation)
#
# Manufacturers
#
class ManufacturerListView(generics.ListAPIView):
"""
List all hardware manufacturers
"""
queryset = Manufacturer.objects.all()
serializer_class = ManufacturerSerializer
class ManufacturerDetailView(generics.RetrieveAPIView):
"""
Retrieve a single hardware manufacturers
"""
queryset = Manufacturer.objects.all()
serializer_class = ManufacturerSerializer
#
# Device Types
#
class DeviceTypeListView(generics.ListAPIView):
"""
List device types (filterable)
"""
queryset = DeviceType.objects.select_related('manufacturer')
serializer_class = DeviceTypeSerializer
filter_class = DeviceTypeFilter
class DeviceTypeDetailView(generics.ListAPIView):
"""
Retrieve a single device type
"""
queryset = DeviceType.objects.select_related('manufacturer')
serializer_class = DeviceTypeSerializer
#
# Device roles
#
class DeviceRoleListView(generics.ListAPIView):
"""
List all device roles
"""
queryset = DeviceRole.objects.all()
serializer_class = DeviceRoleSerializer
class DeviceRoleDetailView(generics.RetrieveAPIView):
"""
Retrieve a single device role
"""
queryset = DeviceRole.objects.all()
serializer_class = DeviceRoleSerializer
#
# Platforms
#
class PlatformListView(generics.ListAPIView):
"""
List all platforms
"""
queryset = Platform.objects.all()
serializer_class = PlatformSerializer
class PlatformDetailView(generics.RetrieveAPIView):
"""
Retrieve a single platform
"""
queryset = Platform.objects.all()
serializer_class = PlatformSerializer
#
# Devices
#
class DeviceListView(generics.ListAPIView):
"""
List devices (filterable)
"""
queryset = Device.objects.select_related('device_type__manufacturer', 'device_role', 'platform', 'rack__site')\
.prefetch_related('primary_ip__nat_outside')
serializer_class = DeviceSerializer
filter_class = DeviceFilter
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [BINDZoneRenderer]
class DeviceDetailView(generics.RetrieveAPIView):
"""
Retrieve a single device
"""
queryset = Device.objects.all()
serializer_class = DeviceSerializer
#
# Console ports
#
class ConsolePortListView(generics.ListAPIView):
"""
List console ports (by device)
"""
serializer_class = ConsolePortSerializer
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return ConsolePort.objects.filter(device=device).select_related('cs_port')
class ConsolePortView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
serializer_class = ConsolePortSerializer
queryset = ConsolePort.objects.all()
#
# Console server ports
#
class ConsoleServerPortListView(generics.ListAPIView):
"""
List console server ports (by device)
"""
serializer_class = ConsoleServerPortSerializer
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return ConsoleServerPort.objects.filter(device=device).select_related('connected_console')
#
# Power ports
#
class PowerPortListView(generics.ListAPIView):
"""
List power ports (by device)
"""
serializer_class = PowerPortSerializer
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return PowerPort.objects.filter(device=device).select_related('power_outlet')
class PowerPortView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
serializer_class = PowerPortSerializer
queryset = PowerPort.objects.all()
#
# Power outlets
#
class PowerOutletListView(generics.ListAPIView):
"""
List power outlets (by device)
"""
serializer_class = PowerOutletSerializer
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return PowerOutlet.objects.filter(device=device).select_related('connected_port')
#
# Interfaces
#
class InterfaceListView(generics.ListAPIView):
"""
List interfaces (by device)
"""
serializer_class = InterfaceSerializer
filter_class = InterfaceFilter
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
queryset = Interface.objects.filter(device=device).select_related('connected_as_a', 'connected_as_b')
# Filter by type (physical or virtual)
iface_type = self.request.query_params.get('type')
if iface_type == 'physical':
queryset = queryset.exclude(form_factor=IFACE_FF_VIRTUAL)
elif iface_type == 'virtual':
queryset = queryset.filter(form_factor=IFACE_FF_VIRTUAL)
elif iface_type is not None:
queryset = queryset.empty()
return queryset
class InterfaceDetailView(generics.RetrieveAPIView):
"""
Retrieve a single interface
"""
queryset = Interface.objects.select_related('device')
serializer_class = InterfaceDetailSerializer
class InterfaceConnectionView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
serializer_class = InterfaceConnectionSerializer
queryset = InterfaceConnection.objects.all()
#
# Live queries
#
class LLDPNeighborsView(APIView):
"""
Retrieve live LLDP neighbors of a device
"""
def get(self, request, pk):
device = get_object_or_404(Device, pk=pk)
if not device.primary_ip:
raise ServiceUnavailable(detail="No IP configured for this device.")
hostname = str(device.primary_ip.address.ip)
RPC = device.get_rpc_client()
if not RPC:
raise ServiceUnavailable(detail="No RPC client available for this platform ({}).".format(device.platform))
# Connect to device and retrieve inventory info
try:
with RPC(device, username=settings.NETBOX_USERNAME, password=settings.NETBOX_PASSWORD) as rpc_client:
lldp_neighbors = rpc_client.get_lldp_neighbors()
except:
raise ServiceUnavailable(detail="Error connecting to the remote device.")
return Response(lldp_neighbors)
#
# Miscellaneous
#
class RelatedConnectionsView(APIView):
"""
Retrieve all connections related to a given console/power/interface connection
"""
def get(self, request):
peer_device = request.GET.get('peer-device')
peer_interface = request.GET.get('peer-interface')
# Search by interface
if peer_device and peer_interface:
# Determine local interface from peer interface's connection
try:
peer_iface = Interface.objects.get(device__name=peer_device, name=peer_interface)
except Interface.DoesNotExist:
raise Http404()
local_iface = peer_iface.get_connected_interface()
if local_iface:
device = local_iface.device
else:
return Response()
else:
raise MissingFilterException(detail='Must specify search parameters (peer-device and peer-interface).')
# Initialize response skeleton
response = dict()
response['device'] = DeviceSerializer(device).data
response['console-ports'] = []
response['power-ports'] = []
response['interfaces'] = []
# Build console connections
console_ports = ConsolePort.objects.filter(device=device).select_related('cs_port__device')
for cp in console_ports:
cp_info = dict()
cp_info['name'] = cp.name
if cp.cs_port:
cp_info['console-server'] = cp.cs_port.device.name
cp_info['port'] = cp.cs_port.name
else:
cp_info['console-server'] = None
cp_info['port'] = None
response['console-ports'].append(cp_info)
# Build power connections
power_ports = PowerPort.objects.filter(device=device).select_related('power_outlet__device')
for pp in power_ports:
pp_info = dict()
pp_info['name'] = pp.name
if pp.power_outlet:
pp_info['pdu'] = pp.power_outlet.device.name
pp_info['outlet'] = pp.power_outlet.name
else:
pp_info['pdu'] = None
pp_info['outlet'] = None
response['power-ports'].append(pp_info)
# Built interface connections
interfaces = Interface.objects.filter(device=device)
for iface in interfaces:
iface_info = dict()
iface_info['name'] = iface.name
peer_interface = iface.get_connected_interface()
if peer_interface:
iface_info['device'] = peer_interface.device.name
iface_info['interface'] = peer_interface.name
else:
iface_info['device'] = None
iface_info['interface'] = None
response['interfaces'].append(iface_info)
return Response(response)