Просмотр исходного кода

Add tenancy to cluster

fix pep8
Fredrik Lönnegren 6 лет назад
Родитель
Сommit
3262805938

+ 4 - 0
netbox/templates/tenancy/tenant.html

@@ -142,6 +142,10 @@
                     <h2><a href="{% url 'virtualization:virtualmachine_list' %}?tenant={{ tenant.slug }}" class="btn {% if stats.virtualmachine_count %}btn-primary{% else %}btn-default{% endif %} btn-lg">{{ stats.virtualmachine_count }}</a></h2>
                     <p>Virtual machines</p>
                 </div>
+                <div class="col-md-4 text-center">
+                    <h2><a href="{% url 'virtualization:cluster_list' %}?tenant={{ tenant.slug }}" class="btn {% if stats.cluser_count %}btn-primary{% else %}btn-default{% endif %} btn-lg">{{ stats.cluster_count }}</a></h2>
+                    <p>Clusters</p>
+                </div>
             </div>
         </div>
     </div>

+ 10 - 0
netbox/templates/virtualization/cluster.html

@@ -83,6 +83,16 @@
                         {% endif %}
                     </td>
                 </tr>
+                <tr>
+                    <td>Tenant</td>
+                    <td>
+                        {% if cluster.tenant %}
+                            <a href="{{ cluster.tenant.get_absolute_url }}">{{ cluster.tenant }}</a>
+                        {% else %}
+                            <span class="text-muted">None</span>
+                        {% endif %}
+                    </td>
+                </tr>
                 <tr>
                     <td>Site</td>
                     <td>

+ 1 - 0
netbox/templates/virtualization/cluster_edit.html

@@ -8,6 +8,7 @@
             {% render_field form.name %}
             {% render_field form.type %}
             {% render_field form.group %}
+            {% render_field form.tenant %}
             {% render_field form.site %}
         </div>
     </div>

+ 2 - 1
netbox/tenancy/api/serializers.py

@@ -31,11 +31,12 @@ class TenantSerializer(TaggitSerializer, CustomFieldModelSerializer):
     virtualmachine_count = serializers.IntegerField(read_only=True)
     vlan_count = serializers.IntegerField(read_only=True)
     vrf_count = serializers.IntegerField(read_only=True)
+    cluster_count = serializers.IntegerField(read_only=True)
 
     class Meta:
         model = Tenant
         fields = [
             'id', 'name', 'slug', 'group', 'description', 'comments', 'tags', 'custom_fields', 'created',
             'last_updated', 'circuit_count', 'device_count', 'ipaddress_count', 'prefix_count', 'rack_count',
-            'site_count', 'virtualmachine_count', 'vlan_count', 'vrf_count',
+            'site_count', 'virtualmachine_count', 'vlan_count', 'vrf_count', 'cluster_count',
         ]

+ 2 - 1
netbox/tenancy/views.py

@@ -9,7 +9,7 @@ from ipam.models import IPAddress, Prefix, VLAN, VRF
 from utilities.views import (
     BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
 )
-from virtualization.models import VirtualMachine
+from virtualization.models import VirtualMachine, Cluster
 from . import filters, forms, tables
 from .models import Tenant, TenantGroup
 
@@ -80,6 +80,7 @@ class TenantView(PermissionRequiredMixin, View):
             'vlan_count': VLAN.objects.filter(tenant=tenant).count(),
             'circuit_count': Circuit.objects.filter(tenant=tenant).count(),
             'virtualmachine_count': VirtualMachine.objects.filter(tenant=tenant).count(),
+            'cluster_count': Cluster.objects.filter(tenant=tenant).count(),
         }
 
         return render(request, 'tenancy/tenant.html', {

+ 2 - 1
netbox/virtualization/api/serializers.py

@@ -38,6 +38,7 @@ class ClusterGroupSerializer(ValidatedModelSerializer):
 class ClusterSerializer(TaggitSerializer, CustomFieldModelSerializer):
     type = NestedClusterTypeSerializer()
     group = NestedClusterGroupSerializer(required=False, allow_null=True)
+    tenant = NestedTenantSerializer(required=False, allow_null=True)
     site = NestedSiteSerializer(required=False, allow_null=True)
     tags = TagListSerializerField(required=False)
     device_count = serializers.IntegerField(read_only=True)
@@ -46,7 +47,7 @@ class ClusterSerializer(TaggitSerializer, CustomFieldModelSerializer):
     class Meta:
         model = Cluster
         fields = [
-            'id', 'name', 'type', 'group', 'site', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
+            'id', 'name', 'type', 'group', 'tenant', 'site', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
             'device_count', 'virtualmachine_count',
         ]
 

+ 1 - 1
netbox/virtualization/api/views.py

@@ -41,7 +41,7 @@ class ClusterGroupViewSet(ModelViewSet):
 
 class ClusterViewSet(CustomFieldModelViewSet):
     queryset = Cluster.objects.prefetch_related(
-        'type', 'group', 'site', 'tags'
+        'type', 'group', 'tenant', 'site', 'tags'
     ).annotate(
         device_count=get_subquery(Device, 'cluster'),
         virtualmachine_count=get_subquery(VirtualMachine, 'cluster')

+ 5 - 0
netbox/virtualization/filters.py

@@ -4,6 +4,7 @@ from netaddr import EUI
 from netaddr.core import AddrFormatError
 
 from dcim.models import DeviceRole, Interface, Platform, Region, Site
+from tenancy.models import Tenant
 from extras.filters import CustomFieldFilterSet
 from tenancy.filtersets import TenancyFilterSet
 from utilities.filters import (
@@ -56,6 +57,10 @@ class ClusterFilter(CustomFieldFilterSet):
         to_field_name='slug',
         label='Cluster type (slug)',
     )
+    tenant = django_filters.ModelMultipleChoiceFilter(
+        queryset=Tenant.objects.all(),
+        label="Tenant (ID)"
+    )
     site_id = django_filters.ModelMultipleChoiceFilter(
         queryset=Site.objects.all(),
         label='Site (ID)',

+ 24 - 2
netbox/virtualization/forms.py

@@ -87,7 +87,7 @@ class ClusterForm(BootstrapMixin, CustomFieldForm):
     class Meta:
         model = Cluster
         fields = [
-            'name', 'type', 'group', 'site', 'comments', 'tags',
+            'name', 'type', 'group', 'tenant', 'site', 'comments', 'tags',
         ]
         widgets = {
             'type': APISelect(
@@ -129,6 +129,15 @@ class ClusterCSVForm(forms.ModelForm):
             'invalid_choice': 'Invalid site name.',
         }
     )
+    tenant = forms.ModelChoiceField(
+        queryset=Tenant.objects.all(),
+        to_field_name='name',
+        required=False,
+        help_text='Name of assigned tenant',
+        error_messages={
+            'invalid_choice': 'Invalid tenant name'
+        }
+    )
 
     class Meta:
         model = Cluster
@@ -154,6 +163,10 @@ class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
             api_url="/api/virtualization/cluster-groups/"
         )
     )
+    tenant = forms.ModelChoiceField(
+        queryset=Tenant.objects.all(),
+        required=False
+    )
     site = forms.ModelChoiceField(
         queryset=Site.objects.all(),
         required=False,
@@ -167,7 +180,7 @@ class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
 
     class Meta:
         nullable_fields = [
-            'group', 'site', 'comments',
+            'group', 'site', 'comments', 'tenant',
         ]
 
 
@@ -194,6 +207,15 @@ class ClusterFilterForm(BootstrapMixin, CustomFieldFilterForm):
             null_option=True,
         )
     )
+    tenant = FilterChoiceField(
+        queryset=Tenant.objects.all(),
+        null_label='-- None --',
+        required=False,
+        widget=APISelectMultiple(
+            api_url="/api/tenancy/tenants/",
+            null_option=True,
+        )
+    )
     site = FilterChoiceField(
         queryset=Site.objects.all(),
         to_field_name='slug',

+ 18 - 0
netbox/virtualization/migrations/0010_cluster_add_tenant.py

@@ -0,0 +1,18 @@
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('tenancy', '0001_initial'),
+        ('virtualization', '0009_custom_tag_models'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='cluster',
+            name='tenant',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='clusters', to='tenancy.Tenant'),
+        ),
+    ]

+ 8 - 0
netbox/virtualization/models.py

@@ -103,6 +103,13 @@ class Cluster(ChangeLoggedModel, CustomFieldModel):
         blank=True,
         null=True
     )
+    tenant = models.ForeignKey(
+        to='tenancy.Tenant',
+        on_delete=models.PROTECT,
+        related_name='tenants',
+        blank=True,
+        null=True
+    )
     site = models.ForeignKey(
         to='dcim.Site',
         on_delete=models.PROTECT,
@@ -150,6 +157,7 @@ class Cluster(ChangeLoggedModel, CustomFieldModel):
             self.type.name,
             self.group.name if self.group else None,
             self.site.name if self.site else None,
+            self.tenant.name if self.tenant else None,
             self.comments,
         )
 

+ 2 - 1
netbox/virtualization/tables.py

@@ -84,13 +84,14 @@ class ClusterGroupTable(BaseTable):
 class ClusterTable(BaseTable):
     pk = ToggleColumn()
     name = tables.LinkColumn()
+    tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')], verbose_name='Tenant')
     site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
     device_count = tables.Column(accessor=Accessor('devices.count'), orderable=False, verbose_name='Devices')
     vm_count = tables.Column(accessor=Accessor('virtual_machines.count'), orderable=False, verbose_name='VMs')
 
     class Meta(BaseTable.Meta):
         model = Cluster
-        fields = ('pk', 'name', 'type', 'group', 'site', 'device_count', 'vm_count')
+        fields = ('pk', 'name', 'type', 'group', 'tenant', 'site', 'device_count', 'vm_count')
 
 
 #

+ 1 - 1
netbox/virtualization/views.py

@@ -96,7 +96,7 @@ class ClusterGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 
 class ClusterListView(PermissionRequiredMixin, ObjectListView):
     permission_required = 'virtualization.view_cluster'
-    queryset = Cluster.objects.prefetch_related('type', 'group', 'site')
+    queryset = Cluster.objects.prefetch_related('type', 'group', 'site', 'tenant')
     table = tables.ClusterTable
     filter = filters.ClusterFilter
     filter_form = forms.ClusterFilterForm