mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Reworked relationship between devices and clusters
This commit is contained in:
@ -16,6 +16,7 @@ from dcim.models import (
|
|||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from extras.api.customfields import CustomFieldModelSerializer
|
||||||
from tenancy.api.serializers import NestedTenantSerializer
|
from tenancy.api.serializers import NestedTenantSerializer
|
||||||
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer
|
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer
|
||||||
|
from virtualization.models import Cluster
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -446,6 +447,15 @@ class DeviceIPAddressSerializer(serializers.ModelSerializer):
|
|||||||
fields = ['id', 'url', 'family', 'address']
|
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):
|
class DeviceSerializer(CustomFieldModelSerializer):
|
||||||
device_type = NestedDeviceTypeSerializer()
|
device_type = NestedDeviceTypeSerializer()
|
||||||
device_role = NestedDeviceRoleSerializer()
|
device_role = NestedDeviceRoleSerializer()
|
||||||
@ -459,13 +469,14 @@ class DeviceSerializer(CustomFieldModelSerializer):
|
|||||||
primary_ip4 = DeviceIPAddressSerializer()
|
primary_ip4 = DeviceIPAddressSerializer()
|
||||||
primary_ip6 = DeviceIPAddressSerializer()
|
primary_ip6 = DeviceIPAddressSerializer()
|
||||||
parent_device = serializers.SerializerMethodField()
|
parent_device = serializers.SerializerMethodField()
|
||||||
|
cluster = NestedClusterSerializer()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Device
|
model = Device
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'name', 'display_name', 'device_type', 'device_role', 'tenant', 'platform', 'serial', 'asset_tag',
|
'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',
|
'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):
|
def get_parent_device(self, obj):
|
||||||
|
22
netbox/dcim/migrations/0042_device_cluster.py
Normal file
22
netbox/dcim/migrations/0042_device_cluster.py
Normal file
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
@ -808,6 +808,13 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
|
|||||||
'ipam.IPAddress', related_name='primary_ip6_for', on_delete=models.SET_NULL, blank=True, null=True,
|
'ipam.IPAddress', related_name='primary_ip6_for', on_delete=models.SET_NULL, blank=True, null=True,
|
||||||
verbose_name='Primary IPv6'
|
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)
|
comments = models.TextField(blank=True)
|
||||||
custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
|
custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
|
||||||
images = GenericRelation(ImageAttachment)
|
images = GenericRelation(ImageAttachment)
|
||||||
|
@ -4,6 +4,13 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-8 col-md-9">
|
<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>
|
||||||
<div class="col-sm-4 col-md-3">
|
<div class="col-sm-4 col-md-3">
|
||||||
<form action="{% url 'virtualization:cluster_list' %}" method="get">
|
<form action="{% url 'virtualization:cluster_list' %}" method="get">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- 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
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import dcim.fields
|
import dcim.fields
|
||||||
@ -13,9 +13,9 @@ class Migration(migrations.Migration):
|
|||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('ipam', '0018_remove_service_uniqueness_constraint'),
|
|
||||||
('tenancy', '0003_unicode_literals'),
|
('tenancy', '0003_unicode_literals'),
|
||||||
('dcim', '0041_napalm_integration'),
|
('dcim', '0041_napalm_integration'),
|
||||||
|
('ipam', '0018_remove_service_uniqueness_constraint'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
@ -27,7 +27,6 @@ class Migration(migrations.Migration):
|
|||||||
('last_updated', models.DateTimeField(auto_now=True)),
|
('last_updated', models.DateTimeField(auto_now=True)),
|
||||||
('name', models.CharField(max_length=100, unique=True)),
|
('name', models.CharField(max_length=100, unique=True)),
|
||||||
('comments', models.TextField(blank=True)),
|
('comments', models.TextField(blank=True)),
|
||||||
('devices', models.ManyToManyField(to='dcim.Device')),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'ordering': ['name'],
|
'ordering': ['name'],
|
||||||
|
@ -89,9 +89,6 @@ class Cluster(CreatedUpdatedModel, CustomFieldModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
devices = models.ManyToManyField(
|
|
||||||
to='dcim.Device'
|
|
||||||
)
|
|
||||||
comments = models.TextField(
|
comments = models.TextField(
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
|
@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404, render
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
|
from dcim.models import Device
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ComponentDeleteView, ComponentEditView,
|
BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ComponentDeleteView, ComponentEditView,
|
||||||
ObjectDeleteView, ObjectEditView, ObjectListView,
|
ObjectDeleteView, ObjectEditView, ObjectListView,
|
||||||
@ -95,9 +96,11 @@ class ClusterView(View):
|
|||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
|
|
||||||
cluster = get_object_or_404(Cluster, pk=pk)
|
cluster = get_object_or_404(Cluster, pk=pk)
|
||||||
|
devices = Device.objects.filter(cluster=cluster)
|
||||||
|
|
||||||
return render(request, 'virtualization/cluster.html', {
|
return render(request, 'virtualization/cluster.html', {
|
||||||
'cluster': cluster,
|
'cluster': cluster,
|
||||||
|
'devices': devices,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user