Browse Source

Reworked relationship between devices and clusters

Jeremy Stretch 7 years ago
parent
commit
a02055e9b5

+ 12 - 1
netbox/dcim/api/serializers.py

@@ -16,6 +16,7 @@ from dcim.models import (
 from extras.api.customfields import CustomFieldModelSerializer
 from tenancy.api.serializers import NestedTenantSerializer
 from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer
+from virtualization.models import Cluster
 
 
 #
@@ -446,6 +447,15 @@ class DeviceIPAddressSerializer(serializers.ModelSerializer):
         fields = ['id', 'url', 'family', 'address']
 
 
+# Cannot import virtualization.api.NestedClusterSerializer due to circular dependency
+class NestedClusterSerializer(serializers.ModelSerializer):
+    url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:cluster-detail')
+
+    class Meta:
+        model = Cluster
+        fields = ['id', 'url', 'name']
+
+
 class DeviceSerializer(CustomFieldModelSerializer):
     device_type = NestedDeviceTypeSerializer()
     device_role = NestedDeviceRoleSerializer()
@@ -459,13 +469,14 @@ class DeviceSerializer(CustomFieldModelSerializer):
     primary_ip4 = DeviceIPAddressSerializer()
     primary_ip6 = DeviceIPAddressSerializer()
     parent_device = serializers.SerializerMethodField()
+    cluster = NestedClusterSerializer()
 
     class Meta:
         model = Device
         fields = [
             'id', 'name', 'display_name', 'device_type', 'device_role', 'tenant', 'platform', 'serial', 'asset_tag',
             'site', 'rack', 'position', 'face', 'parent_device', 'status', 'primary_ip', 'primary_ip4', 'primary_ip6',
-            'comments', 'custom_fields',
+            'cluster', 'comments', 'custom_fields',
         ]
 
     def get_parent_device(self, obj):

+ 22 - 0
netbox/dcim/migrations/0042_device_cluster.py

@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-08-16 21:06
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('virtualization', '0001_initial'),
+        ('dcim', '0041_napalm_integration'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='device',
+            name='cluster',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='devices', to='virtualization.Cluster'),
+        ),
+    ]

+ 7 - 0
netbox/dcim/models.py

@@ -808,6 +808,13 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
         'ipam.IPAddress', related_name='primary_ip6_for', on_delete=models.SET_NULL, blank=True, null=True,
         verbose_name='Primary IPv6'
     )
+    cluster = models.ForeignKey(
+        to='virtualization.Cluster',
+        on_delete=models.SET_NULL,
+        related_name='devices',
+        blank=True,
+        null=True
+    )
     comments = models.TextField(blank=True)
     custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
     images = GenericRelation(ImageAttachment)

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

@@ -4,6 +4,13 @@
 {% block content %}
 <div class="row">
     <div class="col-sm-8 col-md-9">
+        <ol class="breadcrumb">
+            <li><a href="{{ cluster.type.get_absolute_url }}">{{ cluster.type }}</a></li>
+            {% if cluster.group %}
+                <li><a href="{{ cluster.group.get_absolute_url }}">{{ cluster.group }}</a></li>
+            {% endif %}
+            <li>{{ cluster }}</li>
+        </ol>
     </div>
     <div class="col-sm-4 col-md-3">
         <form action="{% url 'virtualization:cluster_list' %}" method="get">

+ 2 - 3
netbox/virtualization/migrations/0001_initial.py

@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Generated by Django 1.11.4 on 2017-08-16 19:27
+# Generated by Django 1.11.4 on 2017-08-16 21:06
 from __future__ import unicode_literals
 
 import dcim.fields
@@ -13,9 +13,9 @@ class Migration(migrations.Migration):
     initial = True
 
     dependencies = [
-        ('ipam', '0018_remove_service_uniqueness_constraint'),
         ('tenancy', '0003_unicode_literals'),
         ('dcim', '0041_napalm_integration'),
+        ('ipam', '0018_remove_service_uniqueness_constraint'),
     ]
 
     operations = [
@@ -27,7 +27,6 @@ class Migration(migrations.Migration):
                 ('last_updated', models.DateTimeField(auto_now=True)),
                 ('name', models.CharField(max_length=100, unique=True)),
                 ('comments', models.TextField(blank=True)),
-                ('devices', models.ManyToManyField(to='dcim.Device')),
             ],
             options={
                 'ordering': ['name'],

+ 0 - 3
netbox/virtualization/models.py

@@ -89,9 +89,6 @@ class Cluster(CreatedUpdatedModel, CustomFieldModel):
         blank=True,
         null=True
     )
-    devices = models.ManyToManyField(
-        to='dcim.Device'
-    )
     comments = models.TextField(
         blank=True
     )

+ 3 - 0
netbox/virtualization/views.py

@@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404, render
 from django.urls import reverse
 from django.views.generic import View
 
+from dcim.models import Device
 from utilities.views import (
     BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ComponentDeleteView, ComponentEditView,
     ObjectDeleteView, ObjectEditView, ObjectListView,
@@ -95,9 +96,11 @@ class ClusterView(View):
     def get(self, request, pk):
 
         cluster = get_object_or_404(Cluster, pk=pk)
+        devices = Device.objects.filter(cluster=cluster)
 
         return render(request, 'virtualization/cluster.html', {
             'cluster': cluster,
+            'devices': devices,
         })