diff --git a/netbox/circuits/forms.py b/netbox/circuits/forms.py index adbf78fdc..cffbf14ae 100644 --- a/netbox/circuits/forms.py +++ b/netbox/circuits/forms.py @@ -1,7 +1,7 @@ from django import forms from django.utils.translation import gettext as _ -from dcim.models import Region, Site +from dcim.models import Region, Site, SiteGroup from extras.forms import ( AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldModelForm, CustomFieldModelCSVForm, ) @@ -320,18 +320,26 @@ class CircuitTerminationForm(BootstrapMixin, forms.ModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) class Meta: model = CircuitTermination fields = [ - 'term_side', 'region', 'site', 'mark_connected', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', - 'description', + 'term_side', 'region', 'site_group', 'site', 'mark_connected', 'port_speed', 'upstream_speed', + 'xconnect_id', 'pp_info', 'description', ] help_texts = { 'port_speed': "Physical circuit speed", diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 567e68b42..102c3114b 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -429,10 +429,18 @@ class LocationForm(BootstrapMixin, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) parent = DynamicModelChoiceField( @@ -447,7 +455,7 @@ class LocationForm(BootstrapMixin, CustomFieldModelForm): class Meta: model = Location fields = ( - 'region', 'site', 'parent', 'name', 'slug', 'description', + 'region', 'site_group', 'site', 'parent', 'name', 'slug', 'description', ) @@ -534,10 +542,18 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) location = DynamicModelChoiceField( @@ -560,9 +576,9 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): class Meta: model = Rack fields = [ - 'region', 'site', 'location', 'name', 'facility_id', 'tenant_group', 'tenant', 'status', 'role', 'serial', - 'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', - 'comments', 'tags', + 'region', 'site_group', 'site', 'location', 'name', 'facility_id', 'tenant_group', 'tenant', 'status', + 'role', 'serial', 'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', + 'outer_unit', 'comments', 'tags', ] help_texts = { 'site': "The site at which the rack exists", @@ -646,11 +662,19 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) location = DynamicModelChoiceField( @@ -811,11 +835,19 @@ class RackReservationForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) location = DynamicModelChoiceField( @@ -851,7 +883,8 @@ class RackReservationForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): class Meta: model = RackReservation fields = [ - 'region', 'site', 'location', 'rack', 'units', 'user', 'tenant_group', 'tenant', 'description', 'tags', + 'region', 'site_group', 'site', 'location', 'rack', 'units', 'user', 'tenant_group', 'tenant', + 'description', 'tags', ] fieldsets = ( ('Reservation', ('region', 'site', 'location', 'rack', 'units', 'user', 'description', 'tags')), @@ -1838,10 +1871,19 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), + required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) location = DynamicModelChoiceField( @@ -1927,9 +1969,9 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): class Meta: model = Device fields = [ - 'name', 'device_role', 'device_type', 'serial', 'asset_tag', 'site', 'rack', 'position', 'face', - 'status', 'platform', 'primary_ip4', 'primary_ip6', 'cluster_group', 'cluster', 'tenant_group', 'tenant', - 'comments', 'tags', 'local_context_data' + 'name', 'device_role', 'device_type', 'serial', 'asset_tag', 'region', 'site_group', 'site', 'rack', + 'position', 'face', 'status', 'platform', 'primary_ip4', 'primary_ip6', 'cluster_group', 'cluster', + 'tenant_group', 'tenant', 'comments', 'tags', 'local_context_data' ] help_texts = { 'device_role': "The function this device serves", @@ -3738,12 +3780,18 @@ class ConnectCableToDeviceForm(BootstrapMixin, CustomFieldModelForm): label='Region', required=False ) + termination_b_site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + label='Site group', + required=False + ) termination_b_site = DynamicModelChoiceField( queryset=Site.objects.all(), label='Site', required=False, query_params={ - 'region_id': '$termination_b_region' + 'region_id': '$termination_b_region', + 'group_id': '$termination_b_site_group', } ) termination_b_rack = DynamicModelChoiceField( @@ -3877,12 +3925,18 @@ class ConnectCableToCircuitTerminationForm(BootstrapMixin, CustomFieldModelForm) label='Region', required=False ) + termination_b_site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + label='Site group', + required=False + ) termination_b_site = DynamicModelChoiceField( queryset=Site.objects.all(), label='Site', required=False, query_params={ - 'region_id': '$termination_b_region' + 'region_id': '$termination_b_region', + 'group_id': '$termination_b_site_group', } ) termination_b_circuit = DynamicModelChoiceField( @@ -3926,12 +3980,18 @@ class ConnectCableToPowerFeedForm(BootstrapMixin, CustomFieldModelForm): label='Region', required=False ) + termination_b_site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + label='Site group', + required=False + ) termination_b_site = DynamicModelChoiceField( queryset=Site.objects.all(), label='Site', required=False, query_params={ - 'region_id': '$termination_b_region' + 'region_id': '$termination_b_region', + 'group_id': '$termination_b_site_group', } ) termination_b_location = DynamicModelChoiceField( @@ -4305,11 +4365,19 @@ class VirtualChassisCreateForm(BootstrapMixin, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) rack = DynamicModelChoiceField( @@ -4343,7 +4411,7 @@ class VirtualChassisCreateForm(BootstrapMixin, CustomFieldModelForm): class Meta: model = VirtualChassis fields = [ - 'name', 'domain', 'region', 'site', 'rack', 'members', 'initial_position', 'tags', + 'name', 'domain', 'region', 'site_group', 'site', 'rack', 'members', 'initial_position', 'tags', ] def save(self, *args, **kwargs): @@ -4447,11 +4515,19 @@ class VCMemberSelectForm(BootstrapMixin, forms.Form): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) rack = DynamicModelChoiceField( @@ -4549,10 +4625,19 @@ class PowerPanelForm(BootstrapMixin, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), + required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) location = DynamicModelChoiceField( @@ -4570,7 +4655,7 @@ class PowerPanelForm(BootstrapMixin, CustomFieldModelForm): class Meta: model = PowerPanel fields = [ - 'region', 'site', 'location', 'name', 'tags', + 'region', 'site_group', 'site', 'location', 'name', 'tags', ] fieldsets = ( ('Power Panel', ('region', 'site', 'location', 'name', 'tags')), @@ -4615,11 +4700,19 @@ class PowerPanelBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkE 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) location = DynamicModelChoiceField( @@ -4682,6 +4775,13 @@ class PowerFeedForm(BootstrapMixin, CustomFieldModelForm): 'sites__powerpanel': '$power_panel' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, @@ -4689,7 +4789,8 @@ class PowerFeedForm(BootstrapMixin, CustomFieldModelForm): 'powerpanel': '$power_panel' }, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) power_panel = DynamicModelChoiceField( @@ -4715,8 +4816,8 @@ class PowerFeedForm(BootstrapMixin, CustomFieldModelForm): class Meta: model = PowerFeed fields = [ - 'region', 'site', 'power_panel', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', 'phase', - 'voltage', 'amperage', 'max_utilization', 'comments', 'tags', + 'region', 'site_group', 'site', 'power_panel', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', + 'phase', 'voltage', 'amperage', 'max_utilization', 'comments', 'tags', ] fieldsets = ( ('Power Panel', ('region', 'site', 'power_panel')), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 8d20ea5ef..1a68ba932 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -2225,6 +2225,8 @@ class CableCreateView(generic.ObjectEditView): termination_a_site = getattr(obj.termination_a.parent_object, 'site', None) if termination_a_site and 'termination_b_region' not in initial_data: initial_data['termination_b_region'] = termination_a_site.region + if termination_a_site and 'termination_b_site_group' not in initial_data: + initial_data['termination_b_site_group'] = termination_a_site.group if 'termination_b_site' not in initial_data: initial_data['termination_b_site'] = termination_a_site if 'termination_b_rack' not in initial_data: diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 85a06c352..ab25833ad 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -369,12 +369,20 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, null_option='None', query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) vlan_group = DynamicModelChoiceField( @@ -416,7 +424,7 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): ] fieldsets = ( ('Prefix', ('prefix', 'status', 'vrf', 'role', 'is_pool', 'description', 'tags')), - ('Site/VLAN Assignment', ('region', 'site', 'vlan_group', 'vlan')), + ('Site/VLAN Assignment', ('region', 'site_group', 'site', 'vlan_group', 'vlan')), ('Tenancy', ('tenant_group', 'tenant')), ) widgets = { @@ -497,11 +505,16 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF queryset=Region.objects.all(), required=False ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) vrf = DynamicModelChoiceField( @@ -678,12 +691,21 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModel 'sites': '$nat_site' } ) + nat_site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + label='Site group', + initial_params={ + 'sites': '$nat_site' + } + ) nat_site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, label='Site', query_params={ - 'region_id': '$nat_region' + 'region_id': '$nat_region', + 'group_id': '$nat_site_group', } ) nat_rack = DynamicModelChoiceField( @@ -1094,11 +1116,19 @@ class VLANGroupForm(BootstrapMixin, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) slug = SlugField() @@ -1158,12 +1188,20 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, null_option='None', query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) group = DynamicModelChoiceField( @@ -1189,7 +1227,7 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): ] fieldsets = ( ('VLAN', ('vid', 'name', 'status', 'role', 'description', 'tags')), - ('Assignment', ('region', 'site', 'group')), + ('Assignment', ('region', 'site_group', 'site', 'group')), ('Tenancy', ('tenant_group', 'tenant')), ) help_texts = { @@ -1262,11 +1300,16 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor queryset=Region.objects.all(), required=False ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) group = DynamicModelChoiceField( diff --git a/netbox/templates/circuits/circuittermination_edit.html b/netbox/templates/circuits/circuittermination_edit.html index 01aa96c14..4e737d16d 100644 --- a/netbox/templates/circuits/circuittermination_edit.html +++ b/netbox/templates/circuits/circuittermination_edit.html @@ -27,6 +27,7 @@ {% render_field form.region %} + {% render_field form.site_group %} {% render_field form.site %} {% render_field form.mark_connected %} diff --git a/netbox/templates/dcim/cable_connect.html b/netbox/templates/dcim/cable_connect.html index 78b2e5aa7..3215bc8e9 100644 --- a/netbox/templates/dcim/cable_connect.html +++ b/netbox/templates/dcim/cable_connect.html @@ -38,6 +38,12 @@

{{ termination_a.device.site.region }}

+
+ +
+

{{ termination_a.device.site.group }}

+
+
@@ -120,6 +126,9 @@ {% if 'termination_b_region' in form.fields %} {% render_field form.termination_b_region %} {% endif %} + {% if 'termination_b_site_group' in form.fields %} + {% render_field form.termination_b_site_group %} + {% endif %} {% if 'termination_b_site' in form.fields %} {% render_field form.termination_b_site %} {% endif %} diff --git a/netbox/templates/dcim/device_edit.html b/netbox/templates/dcim/device_edit.html index b84b7e5a2..0859a163b 100644 --- a/netbox/templates/dcim/device_edit.html +++ b/netbox/templates/dcim/device_edit.html @@ -23,6 +23,7 @@
Location
{% render_field form.region %} + {% render_field form.site_group %} {% render_field form.site %} {% render_field form.location %} {% render_field form.rack %} diff --git a/netbox/templates/dcim/rack_edit.html b/netbox/templates/dcim/rack_edit.html index 63a9fc183..af94a7197 100644 --- a/netbox/templates/dcim/rack_edit.html +++ b/netbox/templates/dcim/rack_edit.html @@ -6,6 +6,7 @@
Rack
{% render_field form.region %} + {% render_field form.site_group %} {% render_field form.site %} {% render_field form.location %} {% render_field form.name %} diff --git a/netbox/templates/dcim/virtualchassis_add.html b/netbox/templates/dcim/virtualchassis_add.html index 2a68cb5e4..6dc9fc59f 100644 --- a/netbox/templates/dcim/virtualchassis_add.html +++ b/netbox/templates/dcim/virtualchassis_add.html @@ -14,6 +14,7 @@
Member Devices
{% render_field form.region %} + {% render_field form.site_group %} {% render_field form.site %} {% render_field form.rack %} {% render_field form.members %} diff --git a/netbox/templates/ipam/ipaddress_edit.html b/netbox/templates/ipam/ipaddress_edit.html index 33e58ce09..01c7b25cd 100644 --- a/netbox/templates/ipam/ipaddress_edit.html +++ b/netbox/templates/ipam/ipaddress_edit.html @@ -64,6 +64,7 @@
{% render_field form.nat_region %} + {% render_field form.nat_site_group %} {% render_field form.nat_site %} {% render_field form.nat_rack %} {% render_field form.nat_device %} diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index 65c2e45d4..c2d0aee38 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -6,7 +6,7 @@ from django.utils.translation import gettext as _ from dcim.choices import InterfaceModeChoices from dcim.constants import INTERFACE_MTU_MAX, INTERFACE_MTU_MIN from dcim.forms import InterfaceCommonForm, INTERFACE_MODE_HELP_TEXT -from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site +from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site, SiteGroup from extras.forms import ( AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldModelCSVForm, CustomFieldModelForm, CustomFieldFilterForm, ) @@ -87,11 +87,19 @@ class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): 'sites': '$site' } ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + initial_params={ + 'sites': '$site' + } + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) comments = CommentField() @@ -103,10 +111,10 @@ class ClusterForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): class Meta: model = Cluster fields = ( - 'name', 'type', 'group', 'tenant', 'region', 'site', 'comments', 'tags', + 'name', 'type', 'group', 'tenant', 'region', 'site_group', 'site', 'comments', 'tags', ) fieldsets = ( - ('Cluster', ('name', 'type', 'group', 'region', 'site', 'tags')), + ('Cluster', ('name', 'type', 'group', 'region', 'site_group', 'site', 'tags')), ('Tenancy', ('tenant_group', 'tenant')), ) @@ -162,11 +170,16 @@ class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit queryset=Region.objects.all(), required=False, ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) comments = CommentField( @@ -223,11 +236,17 @@ class ClusterAddDevicesForm(BootstrapMixin, forms.Form): required=False, null_option='None' ) + site_group = DynamicModelChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + null_option='None' + ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region_id': '$region' + 'region_id': '$region', + 'group_id': '$site_group', } ) rack = DynamicModelChoiceField(