diff --git a/netbox/dcim/api/urls.py b/netbox/dcim/api/urls.py index 2e16e2786..36a0c99a5 100644 --- a/netbox/dcim/api/urls.py +++ b/netbox/dcim/api/urls.py @@ -37,7 +37,7 @@ router.register('inventory-item-templates', views.InventoryItemTemplateViewSet) router.register('device-roles', views.DeviceRoleViewSet) router.register('platforms', views.PlatformViewSet) router.register('devices', views.DeviceViewSet) -router.register('vdcs', views.VirtualDeviceContextViewSet) +router.register('virtual-device-contexts', views.VirtualDeviceContextViewSet) router.register('modules', views.ModuleViewSet) # Device components diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index ce637fb3d..9c4ab569b 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -1407,12 +1407,12 @@ class PowerFeedPhaseChoices(ChoiceSet): class VirtualDeviceContextStatusChoices(ChoiceSet): key = 'VirtualDeviceContext.status' - STATUS_PLANNED = 'planned' STATUS_ACTIVE = 'active' + STATUS_PLANNED = 'planned' STATUS_OFFLINE = 'offline' CHOICES = [ - (STATUS_PLANNED, 'Planned', 'cyan'), (STATUS_ACTIVE, 'Active', 'green'), + (STATUS_PLANNED, 'Planned', 'cyan'), (STATUS_OFFLINE, 'Offline', 'red'), ] diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index 53576d017..b190ae65a 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -1032,7 +1032,7 @@ class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet): class Meta: model = VirtualDeviceContext - fields = ['id', 'device', 'name', ] + fields = ['id', 'device', 'name'] def search(self, queryset, name, value): if not value.strip(): diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 1b850b403..53adb4d56 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -736,9 +736,8 @@ class VirtualDeviceContextFilterForm( model = VirtualDeviceContext fieldsets = ( (None, ('q', 'filter_id', 'tag')), - ('Hardware', ('device', 'status', )), + ('Attributes', ('device', 'status', 'has_primary_ip')), ('Tenant', ('tenant_group_id', 'tenant_id')), - ('Miscellaneous', ('has_primary_ip',)) ) device = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index 76d2d9204..23498af06 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -1698,21 +1698,19 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm): ) fieldsets = ( - ('Device', ('region', 'site_group', 'site', 'location', 'rack', 'device')), - ('Virtual Device Context', ('name', 'status', 'identifier', 'primary_ip4', 'primary_ip6', 'tenant_group', - 'tenant')), - (None, ('tags', )) + ('Assigned Device', ('region', 'site_group', 'site', 'location', 'rack', 'device')), + ('Virtual Device Context', ('name', 'status', 'identifier', 'primary_ip4', 'primary_ip6', 'tags')), + ('Tenancy', ('tenant_group', 'tenant')) ) class Meta: model = VirtualDeviceContext fields = [ - 'region', 'site_group', 'site', 'location', 'rack', - 'device', 'name', 'status', 'identifier', 'primary_ip4', 'primary_ip6', 'tenant_group', 'tenant', - 'comments', 'tags' + 'region', 'site_group', 'site', 'location', 'rack', 'device', 'name', 'status', 'identifier', + 'primary_ip4', 'primary_ip6', 'tenant_group', 'tenant', 'comments', 'tags' ] - help_texts = {} widgets = { + 'status': StaticSelect(), 'primary_ip4': StaticSelect(), 'primary_ip6': StaticSelect(), } diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index c89dd67ef..3a76c826f 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -1113,7 +1113,7 @@ class VirtualDeviceContext(PrimaryModel): choices=VirtualDeviceContextStatusChoices, ) identifier = models.PositiveSmallIntegerField( - help_text='Unique identifier provided by the platform being virtualized (Example: Nexus VDC Identifier)', + help_text='Numeric identifier unique to the parent device', blank=True, null=True, ) @@ -1163,6 +1163,9 @@ class VirtualDeviceContext(PrimaryModel): def get_absolute_url(self): return reverse('dcim:virtualdevicecontext', kwargs={'pk': self.pk}) + def get_status_color(self): + return VirtualDeviceContextStatusChoices.colors.get(self.status) + @property def primary_ip(self): if ConfigItem('PREFER_IPV4')() and self.primary_ip4: diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 33b61309e..6772f96ad 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -184,12 +184,12 @@ urlpatterns = [ path('devices//', include(get_model_urls('dcim', 'device'))), # Virtual Device Context - path('vdcs/', views.VirtualDeviceContextListView.as_view(), name='virtualdevicecontext_list'), - path('vdcs/add/', views.VirtualDeviceContextEditView.as_view(), name='virtualdevicecontext_add'), - path('vdcs/import/', views.VirtualDeviceContextBulkImportView.as_view(), name='virtualdevicecontext_import'), - path('vdcs/edit/', views.VirtualDeviceContextBulkEditView.as_view(), name='virtualdevicecontext_bulk_edit'), - path('vdcs/delete/', views.VirtualDeviceContextBulkDeleteView.as_view(), name='virtualdevicecontext_bulk_delete'), - path('vdcs//', include(get_model_urls('dcim', 'virtualdevicecontext'))), + path('virtual-device-contexts/', views.VirtualDeviceContextListView.as_view(), name='virtualdevicecontext_list'), + path('virtual-device-contexts/add/', views.VirtualDeviceContextEditView.as_view(), name='virtualdevicecontext_add'), + path('virtual-device-contexts/import/', views.VirtualDeviceContextBulkImportView.as_view(), name='virtualdevicecontext_import'), + path('virtual-device-contexts/edit/', views.VirtualDeviceContextBulkEditView.as_view(), name='virtualdevicecontext_bulk_edit'), + path('virtual-device-contexts/delete/', views.VirtualDeviceContextBulkDeleteView.as_view(), name='virtualdevicecontext_bulk_delete'), + path('virtual-device-contexts//', include(get_model_urls('dcim', 'virtualdevicecontext'))), # Modules path('modules/', views.ModuleListView.as_view(), name='module_list'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index ae621008a..b04222600 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1837,11 +1837,14 @@ class DeviceView(generic.ObjectView): else: vc_members = [] - # Services services = Service.objects.restrict(request.user, 'view').filter(device=instance) + vdcs = VirtualDeviceContext.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( + 'tenant' + ) return { 'services': services, + 'vdcs': vdcs, 'vc_members': vc_members, 'svg_extra': f'highlight=id:{instance.pk}' } diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 046600d08..f0e7bb33a 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -155,6 +155,38 @@ {% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/tags.html' %} {% include 'inc/panels/comments.html' %} +
+
Virtual Device Contexts
+
+ {% if vdcs %} + + + + + + + + {% for vdc in vdcs %} + + + + + + + {% endfor %} +
NameStatusIdentifierTenant
{{ vdc|linkify }}{% badge vdc.get_status_display bg_color=vdc.get_status_color %}{{ vdc.identifier|placeholder }}{{ vdc.tenant|linkify|placeholder }}
+ {% else %} +
None
+ {% endif %} +
+ {% if perms.dcim.add_virtualdevicecontext %} + + {% endif %} +
{% plugin_left_page object %}
@@ -264,34 +296,30 @@
{% endif %}
-
- Services -
-
+
Services
+
{% if services %} - - {% for service in services %} - {% include 'ipam/inc/service.html' %} - {% endfor %} -
+ + {% for service in services %} + {% include 'ipam/inc/service.html' %} + {% endfor %} +
{% else %} -
- None -
+
None
{% endif %} -
- {% if perms.ipam.add_service %} +
+ {% if perms.ipam.add_service %} - {% endif %} + {% endif %}
{% include 'inc/panels/contacts.html' %} {% include 'inc/panels/image_attachments.html' %} {% if object.rack and object.position %} -
+

Front

@@ -304,7 +332,7 @@ {% include 'dcim/inc/rack_elevation.html' with object=object.rack face='rear' extra_params=svg_extra %}
-
+
{% endif %} {% plugin_right_page object %} diff --git a/netbox/templates/dcim/virtualdevicecontext.html b/netbox/templates/dcim/virtualdevicecontext.html index f5eb820f0..c76fed803 100644 --- a/netbox/templates/dcim/virtualdevicecontext.html +++ b/netbox/templates/dcim/virtualdevicecontext.html @@ -28,7 +28,6 @@ Identifier {{ object.identifier|placeholder }} - Primary IPv4 @@ -41,6 +40,15 @@ {{ object.primary_ip6|placeholder }} + + Tenant + + {% if object.tenant.group %} + {{ object.tenant.group|linkify }} / + {% endif %} + {{ object.tenant|linkify|placeholder }} + +