mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 01:48:38 -06:00
A modest attempt at improving interface ordering; see #9
This commit is contained in:
parent
43e030f1db
commit
b02c54ce52
@ -85,6 +85,48 @@ RPC_CLIENT_CHOICES = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def order_interfaces(queryset, sql_col, primary_ordering=tuple()):
|
||||||
|
"""
|
||||||
|
Attempt to match interface names by their slot/position identifiers and order according. Matching is done using the
|
||||||
|
following pattern:
|
||||||
|
|
||||||
|
{a}/{b}/{c}:{d}
|
||||||
|
|
||||||
|
Interfaces are ordered first by field a, then b, then c, and finally d. Leading text (which typically indicates the
|
||||||
|
interface's type) is ignored. If any fields are not contained by an interface name, those fields are treated as
|
||||||
|
None. 'None' is ordered after all other values. For example:
|
||||||
|
|
||||||
|
et-0/0/0
|
||||||
|
et-0/0/1
|
||||||
|
et-0/1/0
|
||||||
|
xe-0/1/1:0
|
||||||
|
xe-0/1/1:1
|
||||||
|
xe-0/1/1:2
|
||||||
|
xe-0/1/1:3
|
||||||
|
et-0/1/2
|
||||||
|
...
|
||||||
|
et-0/1/9
|
||||||
|
et-0/1/10
|
||||||
|
et-0/1/11
|
||||||
|
et-1/0/0
|
||||||
|
et-1/0/1
|
||||||
|
...
|
||||||
|
vlan1
|
||||||
|
vlan10
|
||||||
|
|
||||||
|
:param queryset: The base queryset to be ordered
|
||||||
|
:param sql_col: Table and name of the SQL column which contains the interface name (ex: ''dcim_interface.name')
|
||||||
|
:param primary_ordering: A tuple of fields which take ordering precedence before the interface name (optional)
|
||||||
|
"""
|
||||||
|
ordering = primary_ordering + ('_id1', '_id2', '_id3', '_id4')
|
||||||
|
return queryset.extra(select={
|
||||||
|
'_id1': "CAST(SUBSTRING({} FROM '([0-9]+)\/[0-9]+\/[0-9]+(:[0-9]+)?$') AS integer)".format(sql_col),
|
||||||
|
'_id2': "CAST(SUBSTRING({} FROM '([0-9]+)\/[0-9]+(:[0-9]+)?$') AS integer)".format(sql_col),
|
||||||
|
'_id3': "CAST(SUBSTRING({} FROM '([0-9]+)(:[0-9]+)?$') AS integer)".format(sql_col),
|
||||||
|
'_id4': "CAST(SUBSTRING({} FROM ':([0-9]+)$') AS integer)".format(sql_col),
|
||||||
|
}).order_by(*ordering)
|
||||||
|
|
||||||
|
|
||||||
class Site(CreatedUpdatedModel):
|
class Site(CreatedUpdatedModel):
|
||||||
"""
|
"""
|
||||||
A Site represents a geographic location within a network; typically a building or campus. The optional facility
|
A Site represents a geographic location within a network; typically a building or campus. The optional facility
|
||||||
@ -413,6 +455,13 @@ class PowerOutletTemplate(models.Model):
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceTemplateManager(models.Manager):
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = super(InterfaceTemplateManager, self).get_queryset()
|
||||||
|
return order_interfaces(qs, 'dcim_interfacetemplate.name', ('device_type',))
|
||||||
|
|
||||||
|
|
||||||
class InterfaceTemplate(models.Model):
|
class InterfaceTemplate(models.Model):
|
||||||
"""
|
"""
|
||||||
A template for a physical data interface on a new Device.
|
A template for a physical data interface on a new Device.
|
||||||
@ -422,6 +471,8 @@ class InterfaceTemplate(models.Model):
|
|||||||
form_factor = models.PositiveSmallIntegerField(choices=IFACE_FF_CHOICES, default=IFACE_FF_SFP_PLUS)
|
form_factor = models.PositiveSmallIntegerField(choices=IFACE_FF_CHOICES, default=IFACE_FF_SFP_PLUS)
|
||||||
mgmt_only = models.BooleanField(default=False, verbose_name='Management only')
|
mgmt_only = models.BooleanField(default=False, verbose_name='Management only')
|
||||||
|
|
||||||
|
objects = InterfaceTemplateManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['device_type', 'name']
|
ordering = ['device_type', 'name']
|
||||||
unique_together = ['device_type', 'name']
|
unique_together = ['device_type', 'name']
|
||||||
@ -713,18 +764,8 @@ class PowerOutlet(models.Model):
|
|||||||
class InterfaceManager(models.Manager):
|
class InterfaceManager(models.Manager):
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""
|
qs = super(InterfaceManager, self).get_queryset()
|
||||||
Cast up to three interface slot/position IDs as independent integers and order appropriately. This ensures that
|
return order_interfaces(qs, 'dcim_interface.name', ('device',))
|
||||||
interfaces are ordered numerically without regard to type. For example:
|
|
||||||
xe-0/0/0, xe-0/0/1, xe-0/0/2 ... et-0/0/47, et-0/0/48, et-0/0/49 ...
|
|
||||||
instead of:
|
|
||||||
et-0/0/48, et-0/0/49, et-0/0/50 ... et-0/0/53, xe-0/0/0, xe-0/0/1 ...
|
|
||||||
"""
|
|
||||||
return super(InterfaceManager, self).get_queryset().extra(select={
|
|
||||||
'_id1': "CAST(SUBSTRING(dcim_interface.name FROM '([0-9]+)\/([0-9]+)\/([0-9]+)$') AS integer)",
|
|
||||||
'_id2': "CAST(SUBSTRING(dcim_interface.name FROM '([0-9]+)\/([0-9]+)$') AS integer)",
|
|
||||||
'_id3': "CAST(SUBSTRING(dcim_interface.name FROM '([0-9]+)$') AS integer)",
|
|
||||||
}).order_by('device', '_id1', '_id2', '_id3')
|
|
||||||
|
|
||||||
def virtual(self):
|
def virtual(self):
|
||||||
return self.get_queryset().filter(form_factor=IFACE_FF_VIRTUAL)
|
return self.get_queryset().filter(form_factor=IFACE_FF_VIRTUAL)
|
||||||
|
Loading…
Reference in New Issue
Block a user