mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-18 05:28:16 -06:00
update logic to accomodate more cases
This commit is contained in:
parent
c433b1c95c
commit
b62bc3a193
@ -145,6 +145,9 @@ class NaturalOrderingTestCase(TestCase):
|
|||||||
def test_interface_ordering_ios(self):
|
def test_interface_ordering_ios(self):
|
||||||
|
|
||||||
INTERFACES = [
|
INTERFACES = [
|
||||||
|
'FastEthernet1',
|
||||||
|
'FastEthernet2',
|
||||||
|
'FastEthernet10',
|
||||||
'GigabitEthernet0/1',
|
'GigabitEthernet0/1',
|
||||||
'GigabitEthernet0/2',
|
'GigabitEthernet0/2',
|
||||||
'GigabitEthernet0/10',
|
'GigabitEthernet0/10',
|
||||||
@ -155,9 +158,6 @@ class NaturalOrderingTestCase(TestCase):
|
|||||||
'GigabitEthernet1/10',
|
'GigabitEthernet1/10',
|
||||||
'TenGigabitEthernet1/20',
|
'TenGigabitEthernet1/20',
|
||||||
'TenGigabitEthernet1/21',
|
'TenGigabitEthernet1/21',
|
||||||
'FastEthernet1',
|
|
||||||
'FastEthernet2',
|
|
||||||
'FastEthernet10',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for name in INTERFACES:
|
for name in INTERFACES:
|
||||||
|
@ -45,31 +45,21 @@ def naturalize_interface(value, max_length, integer_places=5, model_instance=Non
|
|||||||
:param model_instance: The netbox model instance. This is required to modify the sort order based on the model characteristics
|
:param model_instance: The netbox model instance. This is required to modify the sort order based on the model characteristics
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# See #2872, #3799, #6882, #9368
|
||||||
|
|
||||||
digit_separators = [':', '/', '-']
|
digit_separators = [':', '/', '-']
|
||||||
subinterface_separators = ['.']
|
subinterface_separators = ['.']
|
||||||
interface_remainder_len = 10
|
interface_remainder_len = 10
|
||||||
interface_type_sort_length = 4
|
interface_type_sort_length = 4
|
||||||
|
|
||||||
interface_type_weight_list = {
|
interface_type_weight_list = { # First matched expression is used. The order and the assigned weith can be out of order to accomodate correct sortimg
|
||||||
r'^([fgstx]e|et|lt)-': '5', # Group Juniper interfaces (https://www.juniper.net/documentation/us/en/software/junos/interfaces-fundamentals/topics/topic-map/router-interfaces-overview.html). Other Juniper interfaces will come after these and sorted alphabetically
|
r'^([fgstx]e|et|lt|st)-': 5, # Group Juniper interfaces (https://www.juniper.net/documentation/us/en/software/junos/interfaces-fundamentals/topics/topic-map/router-interfaces-overview.html). Other Juniper interfaces will come after these and sorted alphabetically
|
||||||
r'^ethernet\d+(\/[1-4])?$': '10', # Group Arista Interfaces Ethernet1, Ethernet2, Ethernet49/1, Ethernet50/1
|
r'^(embed|eth|fa|gi|ten|hun)[^\d]*\d*': 10, # Group Cisco/Arista Interfaces (order is a combination of weight+nbr_of_separators, so next weight must be 20)
|
||||||
r'^(fa|gi|ten|hun)[a-z]*\d+$': '16', # Group Cisco Interfaces with only numbers after with digit_separators
|
r'^[^a-z]*$': 30, # Group Only digits
|
||||||
r'^(fa|gi|ten|hun)[a-z]*\d+?[' + '\\'.join(subinterface_separators) + r']\d*': '16', # Group Cisco Interfaces with only numbers after with digit_separators
|
r'^[e]?\d+[a-z]*$': 25, # Group Netapp Interfaces https://library.netapp.com/ecmdocs/ECMP1155586/html/GUID-60DA02FA-B824-4B4E-862F-6862D1407453.html
|
||||||
r'^(fa|gi|ten|hun)[a-z]*\d+[' + '\\'.join(digit_separators) + ']+': '15', # Group Cisco Interfaces (Ethernet, FastEthernet, GigeEthernet, TenEthernet, HundredEthernet) with digit_separators
|
r'[' + '\\'.join(digit_separators) + ']+': 30, # Group Anything with a digit_separator
|
||||||
r'^[e]?\d+[a-z]*$': '20', # Group Netapp Interfaces
|
|
||||||
r'^[^a-z]*$': '25', # Group Only digits together
|
|
||||||
r'[' + '\\'.join(digit_separators) + ']+': '30', # Group Anything with a digit_separator
|
|
||||||
r'eth': '35', # Group Anything with eth in the name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# interface_type_weight_list = {
|
|
||||||
# r'^([fgstx]e|et|lt)-': '05', # Group juniper interfaces (https://www.juniper.net/documentation/us/en/software/junos/interfaces-fundamentals/topics/topic-map/router-interfaces-overview.html). Other Juniper interfaces will come after these and sorted alphabetically
|
|
||||||
# r'^ethernet\d+(\/[1-4])?$': '10', # Group Arista Interfaces Ethernet1, Ethernet2, Ethernet49/1, Ethernet50/1
|
|
||||||
# r'[' + '\\'.join(digit_separators) + ']+[' + '\\'.join(subinterface_separators) + ']*': '15', # Group Anything with a digit_separator and an optional subinterface_separator
|
|
||||||
# r'^\d+' + '\\'.join(subinterface_separators) + '?\d*$': '15', # Group Only digits together with digit_separator, including optional subinterface
|
|
||||||
# r'eth': '20', # Group Anything with eth in the name
|
|
||||||
# }
|
|
||||||
|
|
||||||
if integer_places < 5:
|
if integer_places < 5:
|
||||||
integer_places = 5
|
integer_places = 5
|
||||||
|
|
||||||
@ -83,16 +73,21 @@ def naturalize_interface(value, max_length, integer_places=5, model_instance=Non
|
|||||||
if re.match(r'[^\d]+', parts[-1]):
|
if re.match(r'[^\d]+', parts[-1]):
|
||||||
interface_remainder = naturalize(parts[-1], interface_remainder_len).ljust(interface_remainder_len, '.')
|
interface_remainder = naturalize(parts[-1], interface_remainder_len).ljust(interface_remainder_len, '.')
|
||||||
parts.pop()
|
parts.pop()
|
||||||
if re.match(r'[^\d]+', parts[0]):
|
|
||||||
|
interface_type_weight = ''
|
||||||
|
if re.match(r'[^\d]+', parts[0]): # if the first part is not only numbers, then use that for sorting
|
||||||
interface_type_weight = parts[0][:interface_type_sort_length].upper()
|
interface_type_weight = parts[0][:interface_type_sort_length].upper()
|
||||||
parts.pop(0)
|
parts.pop(0)
|
||||||
|
|
||||||
if getattr(model_instance, 'mgmt_only', False):
|
if getattr(model_instance, 'mgmt_only', False): # if mgmt_only, then place it as last item
|
||||||
interface_type_weight = ''.ljust(interface_type_sort_length, 'Z') # mgmt interfaces are put at the end of the table
|
interface_type_weight = ''.ljust(interface_type_sort_length, 'Z')
|
||||||
else:
|
else:
|
||||||
|
nbr_of_separators = len(re.findall(r'[' + '\\'.join(digit_separators) + r']\d+?', value, re.IGNORECASE))
|
||||||
for regmatch, weigth in interface_type_weight_list.items(): # unless it matches a specific pattern, then the interfaces will be grouped
|
for regmatch, weigth in interface_type_weight_list.items(): # unless it matches a specific pattern, then the interfaces will be grouped
|
||||||
if re.search(regmatch, value, re.IGNORECASE): # first match is applied
|
if re.search(regmatch, value, re.IGNORECASE): # first match is applied
|
||||||
interface_type_weight = weigth
|
if weigth == 10:
|
||||||
|
weigth += nbr_of_separators # for Cisco type, take the nbr of separators into account
|
||||||
|
interface_type_weight = str(weigth).zfill(interface_type_sort_length)
|
||||||
break
|
break
|
||||||
|
|
||||||
output = interface_type_weight.ljust(interface_type_sort_length, '0')
|
output = interface_type_weight.ljust(interface_type_sort_length, '0')
|
||||||
@ -100,7 +95,7 @@ def naturalize_interface(value, max_length, integer_places=5, model_instance=Non
|
|||||||
for part in parts:
|
for part in parts:
|
||||||
if part.isdigit():
|
if part.isdigit():
|
||||||
output += str(int(part) + 1).rjust(integer_places, '0') # zero-pre-pad the port number. 'integer_places' digits must be at least 5, because subinterfaces can go to 65535. Interface numbers are incremented with one to better sort the '0' interfaces (0:0.0; 0; 0.0)
|
output += str(int(part) + 1).rjust(integer_places, '0') # zero-pre-pad the port number. 'integer_places' digits must be at least 5, because subinterfaces can go to 65535. Interface numbers are incremented with one to better sort the '0' interfaces (0:0.0; 0; 0.0)
|
||||||
elif part in subinterface_separators: # replace the subinterface separators with a 0
|
elif part in subinterface_separators: # standardize the subinterface separators to a 0
|
||||||
output += '0' # this will group subinterfaces with the master interface, when there are interfaces with more /'s (ex: Eth1.1 and Eth1/1.5)
|
output += '0' # this will group subinterfaces with the master interface, when there are interfaces with more /'s (ex: Eth1.1 and Eth1/1.5)
|
||||||
elif part in digit_separators: # standardize the digit separators to a 9.
|
elif part in digit_separators: # standardize the digit separators to a 9.
|
||||||
output += '9'
|
output += '9'
|
||||||
|
@ -32,33 +32,33 @@ class NaturalizationTestCase(TestCase):
|
|||||||
data = (
|
data = (
|
||||||
|
|
||||||
# IOS/JunOS-style
|
# IOS/JunOS-style
|
||||||
('Gi', 'GI........................................................................................Gi........'),
|
('Gi', '0015................................................................................................'),
|
||||||
('Gi1', '1500002.............................................................................................'),
|
('Gi1', '001500002...........................................................................................'),
|
||||||
('Gi1.0', '1500002000001.......................................................................................'),
|
('Gi1.0', '001500002000001.....................................................................................'),
|
||||||
('Gi1.1', '1500002000002.......................................................................................'),
|
('Gi1.1', '001500002000002.....................................................................................'),
|
||||||
('Gi1:0', '1500002900001.......................................................................................'),
|
('Gi1:0', '001600002900001.....................................................................................'),
|
||||||
('Gi1:0.0', '1500002900001000001.................................................................................'),
|
('Gi1:0.0', '001600002900001000001...............................................................................'),
|
||||||
('Gi1:0.1', '1500002900001000002.................................................................................'),
|
('Gi1:0.1', '001600002900001000002...............................................................................'),
|
||||||
('Gi1:1', '1500002900002.......................................................................................'),
|
('Gi1:1', '001600002900002.....................................................................................'),
|
||||||
('Gi1:1.0', '1500002900002000001.................................................................................'),
|
('Gi1:1.0', '001600002900002000001...............................................................................'),
|
||||||
('Gi1:1.1', '1500002900002000002.................................................................................'),
|
('Gi1:1.1', '001600002900002000002...............................................................................'),
|
||||||
('Gi1/2', '1500002900003.......................................................................................'),
|
('Gi1/2', '001600002900003.....................................................................................'),
|
||||||
('Gi1/2/3', '1500002900003900004.................................................................................'),
|
('Gi1/2/3', '001700002900003900004...............................................................................'),
|
||||||
('Gi1/2/3/4', '1500002900003900004900005...........................................................................'),
|
('Gi1/2/3/4', '001800002900003900004900005.........................................................................'),
|
||||||
('Gi1/2/3/4/5', '1500002900003900004900005900006.....................................................................'),
|
('Gi1/2/3/4/5', '001900002900003900004900005900006...................................................................'),
|
||||||
('Gi1/2/3/4/5:6', '1500002900003900004900005900006900007...............................................................'),
|
('Gi1/2/3/4/5:6', '002000002900003900004900005900006900007.............................................................'),
|
||||||
('Gi1/2/3/4/5:6.7', '1500002900003900004900005900006900007000008.........................................................'),
|
('Gi1/2/3/4/5:6.7', '002000002900003900004900005900006900007000008.......................................................'),
|
||||||
|
|
||||||
# Generic
|
# Generic
|
||||||
('PCIe1-p1', '200000200002........................................................................................'),
|
('PCIe1-p1', '00300000200002......................................................................................'),
|
||||||
('PCIe1-p99', '200000200100........................................................................................'),
|
('PCIe1-p99', '00300000200100......................................................................................'),
|
||||||
('Interface 1', 'IN00002.............................................................................................'),
|
('Interface 1', 'INTE00002...........................................................................................'),
|
||||||
('Interface 1 (other)', 'IN00002................................................................................... (other)..'),
|
('Interface 1 (other)', 'INTE00002................................................................................. (other)..'),
|
||||||
('Interface 99', 'IN00100.............................................................................................'),
|
('Interface 99', 'INTE00100...........................................................................................'),
|
||||||
)
|
)
|
||||||
|
|
||||||
for origin, naturalized in data:
|
for origin, naturalized in data:
|
||||||
self.assertEqual(naturalize_interface(origin, max_length=100), naturalized)
|
self.assertEqual(naturalize_interface(origin, max_length=100), naturalized)
|
||||||
|
|
||||||
def test_naturalize_interface_max_length(self):
|
def test_naturalize_interface_max_length(self):
|
||||||
self.assertEqual(naturalize_interface('Gi1/2/3', max_length=20), '1500002900003900004.')
|
self.assertEqual(naturalize_interface('Gi1/2/3', max_length=25), '150000002900003900004....')
|
||||||
|
Loading…
Reference in New Issue
Block a user