Let console connections use the same flexible framework

This commit is contained in:
Sander Steffann 2019-10-20 21:30:01 +02:00
parent 4e37175c3c
commit 45aa9de22a
7 changed files with 88 additions and 13 deletions

View File

@ -513,7 +513,7 @@ class ConsoleConnectionViewSet(ListModelMixin, GenericViewSet):
queryset = ConsolePort.objects.prefetch_related( queryset = ConsolePort.objects.prefetch_related(
'device', 'connected_endpoint__device' 'device', 'connected_endpoint__device'
).filter( ).filter(
connected_endpoint__isnull=False connected_endpoint_type=ContentType.objects.get_for_model(ConsoleServerPort)
) )
serializer_class = serializers.ConsolePortSerializer serializer_class = serializers.ConsolePortSerializer
filterset_class = filters.ConsoleConnectionFilter filterset_class = filters.ConsoleConnectionFilter

View File

@ -30,4 +30,45 @@ class Migration(migrations.Migration):
name='_trace', name='_trace',
field=django.contrib.postgres.fields.jsonb.JSONField(default=list), field=django.contrib.postgres.fields.jsonb.JSONField(default=list),
), ),
migrations.RenameField(
model_name='consoleport',
old_name='connected_endpoint',
new_name='old_connected_endpoint',
),
migrations.AddField(
model_name='consoleport',
name='connected_endpoint_id',
field=models.PositiveIntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='consoleport',
name='connected_endpoint_type',
field=models.ForeignKey(blank=True, limit_choices_to={
'model__in': ['consoleport', 'consoleserverport', 'interface', 'poweroutlet', 'powerport', 'frontport',
'rearport', 'circuittermination']
}, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.ContentType'),
),
migrations.AddField(
model_name='consoleport',
name='_trace',
field=django.contrib.postgres.fields.jsonb.JSONField(default=list),
),
migrations.AddField(
model_name='consoleserverport',
name='connected_endpoint_id',
field=models.PositiveIntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='consoleserverport',
name='connected_endpoint_type',
field=models.ForeignKey(blank=True, limit_choices_to={
'model__in': ['consoleport', 'consoleserverport', 'interface', 'poweroutlet', 'powerport', 'frontport',
'rearport', 'circuittermination']
}, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.ContentType'),
),
migrations.AddField(
model_name='consoleserverport',
name='_trace',
field=django.contrib.postgres.fields.jsonb.JSONField(default=list),
),
] ]

View File

@ -91,13 +91,17 @@ def to_generic_connected_endpoint(apps, schema_editor):
print("\nReconstructing all endpoints...", end='') print("\nReconstructing all endpoints...", end='')
interface_model = apps.get_model('dcim', 'Interface') interface_model = apps.get_model('dcim', 'Interface')
consoleport_model = apps.get_model('dcim', 'ConsolePort')
consoleserverport_model = apps.get_model('dcim', 'ConsoleServerPort')
circuittermination_model = apps.get_model('circuits', 'CircuitTermination') circuittermination_model = apps.get_model('circuits', 'CircuitTermination')
contenttype_model = apps.get_model('contenttypes', 'ContentType') contenttype_model = apps.get_model('contenttypes', 'ContentType')
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias
interface_endpoints = interface_model.objects.using(db_alias).all() interface_endpoints = interface_model.objects.using(db_alias).all()
circuittermination_endpoints = circuittermination_model.objects.using(db_alias).all() circuittermination_endpoints = circuittermination_model.objects.using(db_alias).all()
for endpoint in chain(interface_endpoints, circuittermination_endpoints): consoleport_endpoints = consoleport_model.objects.using(db_alias).all()
consoleserverport_endpoints = consoleserverport_model.objects.using(db_alias).all()
for endpoint in chain(interface_endpoints, circuittermination_endpoints, consoleport_endpoints, consoleserverport_endpoints):
path = migration_trace(apps, endpoint) path = migration_trace(apps, endpoint)
# The trace returns left and right, we just want a single list # The trace returns left and right, we just want a single list

View File

@ -18,4 +18,8 @@ class Migration(migrations.Migration):
model_name='interface', model_name='interface',
name='_connected_interface', name='_connected_interface',
), ),
migrations.RemoveField(
model_name='consoleport',
name='old_connected_endpoint',
),
] ]

View File

@ -1888,7 +1888,7 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
# Console ports # Console ports
# #
class ConsolePort(CableTermination, ComponentModel): class ConsolePort(CableTermination, ComponentModel, CachedTraceModel):
""" """
A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts. A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts.
""" """
@ -1900,13 +1900,22 @@ class ConsolePort(CableTermination, ComponentModel):
name = models.CharField( name = models.CharField(
max_length=50 max_length=50
) )
connected_endpoint = models.OneToOneField( connected_endpoint_type = models.ForeignKey(
to='dcim.ConsoleServerPort', to=ContentType,
on_delete=models.SET_NULL, limit_choices_to={'model__in': CABLE_TERMINATION_TYPES},
related_name='connected_endpoint', on_delete=models.PROTECT,
related_name='+',
blank=True, blank=True,
null=True null=True
) )
connected_endpoint_id = models.PositiveIntegerField(
blank=True,
null=True
)
connected_endpoint = GenericForeignKey(
ct_field='connected_endpoint_type',
fk_field='connected_endpoint_id'
)
connection_status = models.NullBooleanField( connection_status = models.NullBooleanField(
choices=CONNECTION_STATUS_CHOICES, choices=CONNECTION_STATUS_CHOICES,
blank=True blank=True
@ -1939,7 +1948,7 @@ class ConsolePort(CableTermination, ComponentModel):
# Console server ports # Console server ports
# #
class ConsoleServerPort(CableTermination, ComponentModel): class ConsoleServerPort(CableTermination, ComponentModel, CachedTraceModel):
""" """
A physical port within a Device (typically a designated console server) which provides access to ConsolePorts. A physical port within a Device (typically a designated console server) which provides access to ConsolePorts.
""" """
@ -1951,6 +1960,22 @@ class ConsoleServerPort(CableTermination, ComponentModel):
name = models.CharField( name = models.CharField(
max_length=50 max_length=50
) )
connected_endpoint_type = models.ForeignKey(
to=ContentType,
limit_choices_to={'model__in': CABLE_TERMINATION_TYPES},
on_delete=models.PROTECT,
related_name='+',
blank=True,
null=True
)
connected_endpoint_id = models.PositiveIntegerField(
blank=True,
null=True
)
connected_endpoint = GenericForeignKey(
ct_field='connected_endpoint_type',
fk_field='connected_endpoint_id'
)
connection_status = models.NullBooleanField( connection_status = models.NullBooleanField(
choices=CONNECTION_STATUS_CHOICES, choices=CONNECTION_STATUS_CHOICES,
blank=True blank=True

View File

@ -1879,9 +1879,9 @@ class ConsoleConnectionsListView(PermissionRequiredMixin, ObjectListView):
queryset = ConsolePort.objects.prefetch_related( queryset = ConsolePort.objects.prefetch_related(
'device', 'connected_endpoint__device' 'device', 'connected_endpoint__device'
).filter( ).filter(
connected_endpoint__isnull=False connected_endpoint_type=ContentType.objects.get_for_model(ConsoleServerPort)
).order_by( ).order_by(
'cable', 'connected_endpoint__device__name', 'connected_endpoint__name' 'cable', # 'connected_endpoint__device__name', 'connected_endpoint__name'
) )
filter = filters.ConsoleConnectionFilter filter = filters.ConsoleConnectionFilter
filter_form = forms.ConsoleConnectionFilterForm filter_form = forms.ConsoleConnectionFilterForm

View File

@ -16,8 +16,9 @@ from dcim.filters import (
VirtualChassisFilter, VirtualChassisFilter,
) )
from dcim.models import ( from dcim.models import (
Cable, ConsolePort, Device, DeviceType, Interface, PowerPanel, PowerFeed, PowerPort, Rack, RackGroup, Site, VirtualChassis Cable, ConsolePort, Device, DeviceType, Interface, PowerPanel, PowerFeed, PowerPort, Rack, RackGroup, Site,
) VirtualChassis,
ConsoleServerPort)
from dcim.tables import ( from dcim.tables import (
CableTable, DeviceDetailTable, DeviceTypeTable, PowerFeedTable, RackTable, RackGroupTable, SiteTable, CableTable, DeviceDetailTable, DeviceTypeTable, PowerFeedTable, RackTable, RackGroupTable, SiteTable,
VirtualChassisTable, VirtualChassisTable,
@ -195,7 +196,7 @@ class HomeView(View):
def get(self, request): def get(self, request):
connected_consoleports = ConsolePort.objects.filter( connected_consoleports = ConsolePort.objects.filter(
connected_endpoint__isnull=False connected_endpoint_type=ContentType.objects.get_for_model(ConsoleServerPort),
) )
connected_powerports = PowerPort.objects.filter( connected_powerports = PowerPort.objects.filter(
_connected_poweroutlet__isnull=False _connected_poweroutlet__isnull=False