Skip to content

Commit

Permalink
Initial work on #5892
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremystretch committed Mar 8, 2021
1 parent 1c66733 commit 07e412e
Show file tree
Hide file tree
Showing 29 changed files with 1,117 additions and 184 deletions.
50 changes: 38 additions & 12 deletions netbox/circuits/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.db.models import Q

from dcim.filters import CableTerminationFilterSet, PathEndpointFilterSet
from dcim.models import Region, Site
from dcim.models import Region, Site, SiteGroup
from extras.filters import CustomFieldModelFilterSet, CreatedUpdatedFilterSet
from tenancy.filters import TenancyFilterSet
from utilities.filters import (
Expand Down Expand Up @@ -37,6 +37,19 @@ class ProviderFilterSet(BaseFilterSet, CustomFieldModelFilterSet, CreatedUpdated
to_field_name='slug',
label='Region (slug)',
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='circuits__terminations__site__group',
lookup_expr='in',
label='Site group (ID)',
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='circuits__terminations__site__group',
lookup_expr='in',
to_field_name='slug',
label='Site group (slug)',
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='circuits__terminations__site',
queryset=Site.objects.all(),
Expand Down Expand Up @@ -102,17 +115,6 @@ class CircuitFilterSet(BaseFilterSet, CustomFieldModelFilterSet, TenancyFilterSe
choices=CircuitStatusChoices,
null_value=None
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='terminations__site',
queryset=Site.objects.all(),
label='Site (ID)',
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='terminations__site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
label='Site (slug)',
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='terminations__site__region',
Expand All @@ -126,6 +128,30 @@ class CircuitFilterSet(BaseFilterSet, CustomFieldModelFilterSet, TenancyFilterSe
to_field_name='slug',
label='Region (slug)',
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='terminations__site__group',
lookup_expr='in',
label='Site group (ID)',
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='terminations__site__group',
lookup_expr='in',
to_field_name='slug',
label='Site group (slug)',
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='terminations__site',
queryset=Site.objects.all(),
label='Site (ID)',
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='terminations__site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
label='Site (slug)',
)
tag = TagFilter()

class Meta:
Expand Down
58 changes: 43 additions & 15 deletions netbox/circuits/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from circuits.choices import *
from circuits.filters import *
from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
from dcim.models import Cable, Region, Site
from dcim.models import Cable, Region, Site, SiteGroup
from tenancy.models import Tenant, TenantGroup


Expand All @@ -27,13 +27,20 @@ def setUpTestData(cls):
Region(name='Test Region 1', slug='test-region-1'),
Region(name='Test Region 2', slug='test-region-2'),
)
# Can't use bulk_create for models with MPTT fields
for r in regions:
r.save()

site_groups = (
SiteGroup(name='Site Group 1', slug='site-group-1'),
SiteGroup(name='Site Group 2', slug='site-group-2'),
SiteGroup(name='Site Group 3', slug='site-group-3'),
)
for site_group in site_groups:
site_group.save()

sites = (
Site(name='Test Site 1', slug='test-site-1', region=regions[0]),
Site(name='Test Site 2', slug='test-site-2', region=regions[1]),
Site(name='Test Site 1', slug='test-site-1', region=regions[0], group=site_groups[0]),
Site(name='Test Site 2', slug='test-site-2', region=regions[1], group=site_groups[1]),
)
Site.objects.bulk_create(sites)

Expand Down Expand Up @@ -74,20 +81,27 @@ def test_account(self):
params = {'account': ['1234', '2345']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_site(self):
sites = Site.objects.all()[:2]
params = {'site_id': [sites[0].pk, sites[1].pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
params = {'site': [sites[0].slug, sites[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_region(self):
regions = Region.objects.all()[:2]
params = {'region_id': [regions[0].pk, regions[1].pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
params = {'region': [regions[0].slug, regions[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_site_group(self):
site_groups = SiteGroup.objects.all()[:2]
params = {'site_group_id': [site_groups[0].pk, site_groups[1].pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
params = {'site_group': [site_groups[0].slug, site_groups[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_site(self):
sites = Site.objects.all()[:2]
params = {'site_id': [sites[0].pk, sites[1].pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
params = {'site': [sites[0].slug, sites[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)


class CircuitTypeTestCase(TestCase):
queryset = CircuitType.objects.all()
Expand Down Expand Up @@ -127,14 +141,21 @@ def setUpTestData(cls):
Region(name='Test Region 2', slug='test-region-2'),
Region(name='Test Region 3', slug='test-region-3'),
)
# Can't use bulk_create for models with MPTT fields
for r in regions:
r.save()

site_groups = (
SiteGroup(name='Site Group 1', slug='site-group-1'),
SiteGroup(name='Site Group 2', slug='site-group-2'),
SiteGroup(name='Site Group 3', slug='site-group-3'),
)
for site_group in site_groups:
site_group.save()

sites = (
Site(name='Test Site 1', slug='test-site-1', region=regions[0]),
Site(name='Test Site 2', slug='test-site-2', region=regions[1]),
Site(name='Test Site 3', slug='test-site-3', region=regions[2]),
Site(name='Test Site 1', slug='test-site-1', region=regions[0], group=site_groups[0]),
Site(name='Test Site 2', slug='test-site-2', region=regions[1], group=site_groups[1]),
Site(name='Test Site 3', slug='test-site-3', region=regions[2], group=site_groups[2]),
)
Site.objects.bulk_create(sites)

Expand Down Expand Up @@ -223,6 +244,13 @@ def test_region(self):
params = {'region': [regions[0].slug, regions[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_site_group(self):
site_groups = SiteGroup.objects.all()[:2]
params = {'site_group_id': [site_groups[0].pk, site_groups[1].pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
params = {'site_group': [site_groups[0].slug, site_groups[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_site(self):
sites = Site.objects.all()[:2]
params = {'site_id': [sites[0].pk, sites[1].pk]}
Expand Down
11 changes: 11 additions & 0 deletions netbox/dcim/api/nested_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
'NestedRearPortTemplateSerializer',
'NestedRegionSerializer',
'NestedSiteSerializer',
'NestedSiteGroupSerializer',
'NestedVirtualChassisSerializer',
]

Expand All @@ -53,6 +54,16 @@ class Meta:
fields = ['id', 'url', 'name', 'slug', 'site_count', '_depth']


class NestedSiteGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:sitegroup-detail')
site_count = serializers.IntegerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)

class Meta:
model = models.SiteGroup
fields = ['id', 'url', 'name', 'slug', 'site_count', '_depth']


class NestedSiteSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:site-detail')

Expand Down
30 changes: 19 additions & 11 deletions netbox/dcim/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@

from dcim.choices import *
from dcim.constants import *
from dcim.models import (
Cable, CablePath, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
DeviceBayTemplate, DeviceType, DeviceRole, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate,
Manufacturer, InventoryItem, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort,
PowerPortTemplate, Rack, Location, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
VirtualChassis,
)
from dcim.models import *
from netbox.api.serializers import CustomFieldModelSerializer
from extras.api.serializers import TaggedObjectSerializer
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
Expand Down Expand Up @@ -94,10 +88,24 @@ class Meta:
]


class SiteGroupSerializer(NestedGroupModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:sitegroup-detail')
parent = NestedRegionSerializer(required=False, allow_null=True)
site_count = serializers.IntegerField(read_only=True)

class Meta:
model = SiteGroup
fields = [
'id', 'url', 'name', 'slug', 'parent', 'description', 'custom_fields', 'created', 'last_updated',
'site_count', '_depth',
]


class SiteSerializer(TaggedObjectSerializer, CustomFieldModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:site-detail')
status = ChoiceField(choices=SiteStatusChoices, required=False)
region = NestedRegionSerializer(required=False, allow_null=True)
group = NestedSiteGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
time_zone = TimeZoneField(required=False)
circuit_count = serializers.IntegerField(read_only=True)
Expand All @@ -110,10 +118,10 @@ class SiteSerializer(TaggedObjectSerializer, CustomFieldModelSerializer):
class Meta:
model = Site
fields = [
'id', 'url', 'name', 'slug', 'status', 'region', 'tenant', 'facility', 'asn', 'time_zone', 'description',
'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone',
'contact_email', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count',
'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count', 'vlan_count',
'id', 'url', 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'asn', 'time_zone',
'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name',
'contact_phone', 'contact_email', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
'circuit_count', 'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count', 'vlan_count',
]


Expand Down
1 change: 1 addition & 0 deletions netbox/dcim/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

# Sites
router.register('regions', views.RegionViewSet)
router.register('site-groups', views.SiteGroupViewSet)
router.register('sites', views.SiteViewSet)

# Racks
Expand Down
24 changes: 17 additions & 7 deletions netbox/dcim/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@

from circuits.models import Circuit
from dcim import filters
from dcim.models import (
Cable, CablePath, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate,
Manufacturer, InventoryItem, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort,
PowerPortTemplate, Rack, Location, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
VirtualChassis,
)
from dcim.models import *
from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet
from ipam.models import Prefix, VLAN
from netbox.api.views import ModelViewSet
Expand Down Expand Up @@ -111,6 +105,22 @@ class RegionViewSet(CustomFieldModelViewSet):
filterset_class = filters.RegionFilterSet


#
# Site groups
#

class SiteGroupViewSet(CustomFieldModelViewSet):
queryset = SiteGroup.objects.add_related_count(
SiteGroup.objects.all(),
Site,
'group',
'site_count',
cumulative=True
)
serializer_class = serializers.SiteGroupSerializer
filterset_class = filters.SiteGroupFilterSet


#
# Sites
#
Expand Down
Loading

0 comments on commit 07e412e

Please sign in to comment.