Skip to content

Commit ae5d685

Browse files
authored
Merge pull request #353 from nautobot/release-4.2.4
Release 4.2.4
2 parents fb575b6 + ff1c487 commit ae5d685

19 files changed

+421
-211
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ jobs:
146146
- python-version: "3.11"
147147
db-backend: "postgresql"
148148
nautobot-version: "2.2.3"
149+
- python-version: "3.12"
150+
db-backend: "mysql"
151+
nautobot-version: "stable"
149152
runs-on: "ubuntu-22.04"
150153
env:
151154
INVOKE_NAUTOBOT_DEVICE_ONBOARDING_PYTHON_VER: "${{ matrix.python-version }}"

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ Regardless, the Onboarding App greatly simplifies the onboarding process by allo
1919

2020
### Support Matrix (Sync Devices From Network)
2121

22-
| Data Attribute | Cisco IOS | Cisco XE | Cisco NXOS | Cisco WLC | Juniper Junos | Arista EOS | F5 | HP Comware | Palo Alto Panos |
23-
| ----------------------- | :----------------: | :--------------: | :--------------: | :--------------: | :--------------: | :--------------: | :-: | :-: | :-: |
24-
| Hostname |||||||| 🧪 | 🧪 |
25-
| Platform |||||||| 🧪 | 🧪 |
26-
| Manufacturer |||||||| 🧪 | 🧪 |
27-
| Serial Number |||||||| 🧪 | 🧪 |
28-
| Device Type |||||||| 🧪 | 🧪 |
29-
| Mgmt Interface |||||||| 🧪 | 🧪 |
30-
| Mgmt IP Address |||||||| 🧪 | 🧪 |
22+
| Data Attribute | Cisco IOS | Cisco XE | Cisco NXOS | Cisco WLC | Juniper Junos | Arista EOS | F5 | HP Comware | Palo Alto Panos | Aruba AOSCX |
23+
| ----------------------- | :----------------: | :--------------: | :--------------: | :--------------: | :--------------: | :--------------: | :-: | :-: | :-: | :-: |
24+
| Hostname |||||||| 🧪 | 🧪 | 🧪 |
25+
| Platform |||||||| 🧪 | 🧪 | 🧪 |
26+
| Manufacturer |||||||| 🧪 | 🧪 | 🧪 |
27+
| Serial Number |||||||| 🧪 | 🧪 | 🧪 |
28+
| Device Type |||||||| 🧪 | 🧪 | 🧪 |
29+
| Mgmt Interface |||||||| 🧪 | 🧪 | 🧪 |
30+
| Mgmt IP Address |||||||| 🧪 | 🧪 | 🧪 |
3131

3232
### Support Matrix (Sync Data From Network)
3333

docs/admin/release_notes/version_4.2.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,31 @@ Versioning](https://semver.org/spec/v2.0.0.html).
1010
- [#200](https://github.com/nautobot/nautobot-app-device-onboarding/issues/200) - Added basic connectivity checker using Netutils tcp_ping method.
1111
- [#274](https://github.com/nautobot/nautobot-app-device-onboarding/issues/274) - Added TTP Parser support.
1212
- [#274](https://github.com/nautobot/nautobot-app-device-onboarding/issues/274) - Added Sync Device from Network support for Palo Alto Panos.
13+
- [#340](https://github.com/nautobot/nautobot-app-device-onboarding/issues/340) - Add Aruba AOSCX support for Sync Devices from Network Job.
14+
- [#278](https://github.com/nautobot/nautobot-app-device-onboarding/issues/278) - Optimized VLAN loading into diffsync from Nautbot
15+
- [#278](https://github.com/nautobot/nautobot-app-device-onboarding/issues/278) - Improved error handling when creating VLANs
16+
17+
## [v4.2.4 (2025-04-08)](https://github.com/nautobot/nautobot-app-device-onboarding/releases/tag/v4.2.4)
18+
19+
### Added
20+
21+
- [#326](https://github.com/nautobot/nautobot-app-device-onboarding/issues/326) - Added testing for cable termination type when adding cables to diffsync store.
22+
- [#340](https://github.com/nautobot/nautobot-app-device-onboarding/issues/340) - Add Aruba AOSCX support for Sync Devices from Network Job.
23+
24+
### Changed
25+
26+
- [#278](https://github.com/nautobot/nautobot-app-device-onboarding/issues/278) - Optimized VLAN loading into diffsync from Nautbot
27+
- [#278](https://github.com/nautobot/nautobot-app-device-onboarding/issues/278) - Improved error handling when creating VLANs
28+
29+
### Fixed
30+
31+
- [#326](https://github.com/nautobot/nautobot-app-device-onboarding/issues/326) - Fixed incorrect call to cable termination type.
32+
- [#337](https://github.com/nautobot/nautobot-app-device-onboarding/issues/337) - Fixed logging call from an invalid path to the correct one.
33+
- [#346](https://github.com/nautobot/nautobot-app-device-onboarding/issues/346) - Fixed Juniper IP addresses not syncing secondary IP addresses.
34+
35+
### Housekeeping
36+
37+
- [#341](https://github.com/nautobot/nautobot-app-device-onboarding/issues/341) - Add MySQL testing back to the CI configuration.
1338

1439
## [v4.2.3 (2025-03-11)](https://github.com/nautobot/nautobot-app-device-onboarding/releases/tag/v4.2.3)
1540

docs/dev/dev_environment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,4 +466,4 @@ To run an individual test, you can run any or all of the following:
466466
➜ invoke unittest
467467
➜ invoke ruff
468468
➜ invoke pylint
469-
```
469+
```
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
sync_devices:
3+
hostname:
4+
commands:
5+
- command: "show system"
6+
parser: "textfsm"
7+
jpath: "[*].hostname"
8+
serial:
9+
commands:
10+
- command: "show system"
11+
parser: "textfsm"
12+
jpath: "[*].serial[]"
13+
post_processor: "{{ obj | unique | first }}"
14+
iterable_type: "str"
15+
device_type:
16+
commands:
17+
- command: "show system"
18+
parser: "textfsm"
19+
jpath: "[*].product[]"
20+
post_processor: "{{ obj | unique | first }}"
21+
iterable_type: "str"
22+
mgmt_interface:
23+
commands:
24+
- command: "show interface"
25+
parser: "textfsm"
26+
jpath: "[?contains(ip_address, `{{ obj }}/`)].{name: interface, enabled: link_status}"
27+
post_processor: "{{ (obj | selectattr('enabled', 'eq', 'up') | list | first ).name }}"
28+
mask_length:
29+
commands:
30+
- command: "show interface"
31+
parser: "textfsm"
32+
jpath: "[?contains(ip_address, `{{ obj }}/`)].ip_address"
33+
post_processor: "{{ obj[0].split('/')[1] }}"
34+
iterable_type: "int"

nautobot_device_onboarding/diffsync/adapters/sync_devices_adapters.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ def execute_command_getter(self):
214214
raise Exception( # pylint: disable=broad-exception-raised
215215
"Platform.network_driver missing"
216216
)
217-
218217
result = sync_devices_command_getter(
219218
self.job.job_result,
220219
self.job.logger.getEffectiveLevel(),

nautobot_device_onboarding/diffsync/adapters/sync_network_data_adapters.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import diffsync
66
from diffsync.enum import DiffSyncModelFlags
77
from django.conf import settings
8+
from django.contrib.contenttypes.models import ContentType
89
from django.core.exceptions import ValidationError
910
from nautobot.dcim.models import Interface
1011
from nautobot.ipam.models import VLAN, VRF, IPAddress
@@ -129,9 +130,11 @@ def load_vlans(self):
129130
"""
130131
Load Vlans into the Diffsync store.
131132
132-
Only Vlans that were returned by the CommandGetter job should be synced.
133+
Only Vlans that share locations with devices included in the sync should be loaded.
133134
"""
134-
for vlan in VLAN.objects.all():
135+
# TODO: update this to support multiple locations per VLAN after the setting for this feature has been added.
136+
location_ids = list(self.job.devices_to_load.values_list("location__id", flat=True))
137+
for vlan in VLAN.objects.filter(location__in=location_ids):
135138
network_vlan = self.vlan(
136139
adapter=self,
137140
name=vlan.name,
@@ -249,9 +252,13 @@ def load_cables(self):
249252
250253
Only cables returned by the CommandGetter job should be synced.
251254
"""
255+
dcim_interface_content_type = ContentType.objects.get_for_model(Interface)
252256
for device in self.job.devices_to_load:
253257
for cable in device.get_cables():
254-
if cable.termination_a.type != "dcim.interface" or cable.termination_b.type != "dcim.interface":
258+
if (
259+
cable.termination_a_type != dcim_interface_content_type
260+
or cable.termination_b_type != dcim_interface_content_type
261+
):
255262
self.job.logger.warning(
256263
f"Skipping Cable: {cable}. Only cables with interface terminations are supported."
257264
)
@@ -590,7 +597,6 @@ def load_vlans(self):
590597
) in self.job.command_getter_result.items(): # pylint: disable=too-many-nested-blocks
591598
if self.job.debug:
592599
self.job.logger.debug(f"Loading Vlans from {hostname}")
593-
# for interface in device_data["interfaces"]:
594600
for _, interface_data in device_data["interfaces"].items():
595601
# add tagged vlans
596602
for tagged_vlan in interface_data["tagged_vlans"]:

nautobot_device_onboarding/diffsync/models/sync_network_data_models.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,18 @@ def create(cls, adapter, ids, attrs):
210210
location = None
211211
try:
212212
location = Location.objects.get(name=ids["location__name"])
213-
except ObjectDoesNotExist:
214-
adapter.job.logger.warning(
213+
except ObjectDoesNotExist as err:
214+
adapter.job.logger.error(
215215
f"While creating VLAN {ids['vid']} - {ids['name']}, "
216-
f"unable to find a Location with name: {ids['location__name']}. "
217-
"This VLAN will be created without a Location"
216+
f"unable to find a Location with name: {ids['location__name']}."
218217
)
219-
except MultipleObjectsReturned:
220-
adapter.job.logger.warning(
218+
raise diffsync_exceptions.ObjectNotCreated(err)
219+
except MultipleObjectsReturned as err:
220+
adapter.job.logger.error(
221221
f"While creating VLAN {ids['vid']} - {ids['name']}, "
222-
f"Multiple Locations were found with name: {ids['location__name']}. "
223-
"This VLAN will be created without a Location"
222+
f"Multiple Locations were found with name: {ids['location__name']}."
224223
)
224+
raise diffsync_exceptions.ObjectNotCreated(err)
225225
try:
226226
vlan = VLAN(
227227
name=ids["name"],
@@ -232,6 +232,7 @@ def create(cls, adapter, ids, attrs):
232232
vlan.validated_save()
233233
except ValidationError as err:
234234
adapter.job.logger.error(f"VLAN {vlan} failed to create, {err}")
235+
raise diffsync_exceptions.ObjectNotCreated(err)
235236

236237
return super().create(adapter, ids, attrs)
237238

@@ -576,7 +577,7 @@ def _get_and_assign_vrf(cls, adapter, attrs, interface, diff_method_type):
576577
vrf.validated_save()
577578
interface.vrf = vrf
578579
except Exception as err:
579-
adapter.logger.error(f"Failed to assign device: [{interface.device}] to vrf: [{vrf}], {err}")
580+
adapter.job.logger.error(f"Failed to assign device: [{interface.device}] to vrf: [{vrf}], {err}")
580581
if diff_method_type == "create":
581582
raise diffsync_exceptions.ObjectNotCreated(err)
582583
if diff_method_type == "update":

nautobot_device_onboarding/jinja_filters.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from itertools import chain
55

66
from django_jinja import library
7+
from netutils.ip import is_ip
78
from netutils.vlan import vlanconfig_to_list
89

910
from nautobot_device_onboarding.constants import INTERFACE_TYPE_MAP_STATIC
@@ -174,11 +175,27 @@ def parse_junos_ip_address(item):
174175
"""
175176
if isinstance(item, list) and len(item) > 0:
176177
if item[0]["prefix_length"] and item[0]["ip_address"]:
177-
return [
178-
{"prefix_length": item[0]["prefix_length"][0].split("/")[-1], "ip_address": item[0]["ip_address"][0]}
179-
]
178+
result = []
179+
for i in range(len(item[0]["ip_address"])):
180+
prefix = item[0]["prefix_length"][i].split("/")[-1]
181+
result.append(
182+
{
183+
"prefix_length": prefix,
184+
"ip_address": item[0]["ip_address"][i],
185+
}
186+
)
187+
return result
180188
if not item[0]["prefix_length"] and item[0]["ip_address"]:
181-
return [{"prefix_length": 32, "ip_address": item[0]["ip_address"][0]}]
189+
result = []
190+
for i in range(len(item[0]["ip_address"])):
191+
if is_ip(item[0]["ip_address"][i]):
192+
result.append(
193+
{
194+
"prefix_length": 32,
195+
"ip_address": item[0]["ip_address"][i],
196+
}
197+
)
198+
return result
182199
return []
183200

184201

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
{
2+
"show system": [
3+
{
4+
"hostname": "SW-CORE",
5+
"contact": "network",
6+
"location": "Main",
7+
"vendor": "Aruba",
8+
"product": "JL664A 6300M 24G 4SFP56 Swch ",
9+
"serial": "SG9BKN123V",
10+
"base_mac": "883a30-a73b80",
11+
"version": "FL.10.10.1080",
12+
"time_zone": "America/Edmonton",
13+
"uptime_weeks": "43",
14+
"uptime_days": "4",
15+
"uptime_hours": "23",
16+
"uptime_minutes": "3"
17+
}
18+
],
19+
"show interface": [
20+
{
21+
"interface": "1/1/1",
22+
"link_status": "up",
23+
"link_admin": "up",
24+
"link_state_info": "",
25+
"link_transitions": "5",
26+
"interface_desc": "Server",
27+
"hw_type": "Ethernet",
28+
"mac_address": "00:3a:30:a7:3b:a7",
29+
"mtu": "1500",
30+
"if_type": "1GbT",
31+
"ip_address": "",
32+
"duplex": "Full",
33+
"qos_trust": "dscp",
34+
"speed": "100 Mb/s",
35+
"auto_neg": "on",
36+
"flow_control": "off",
37+
"error_control": "off",
38+
"vlan_mode": "access",
39+
"vlan_access": "32",
40+
"vlan_native": "",
41+
"vlan_trunk": [],
42+
"aggregated_interfaces": [],
43+
"rx_total_packets": "237186061",
44+
"rx_total_bytes": "59967394350",
45+
"rx_unicast_packets": "237185944",
46+
"rx_mcast_packets": "0",
47+
"rx_broadcast_packets": "117",
48+
"rx_errors": "0",
49+
"rx_dropped": "0",
50+
"rx_crc_fcs": "0",
51+
"tx_total_packets": "233679330",
52+
"tx_total_bytes": "63892999335",
53+
"tx_unicast_packets": "218950785",
54+
"tx_mcast_packets": "14101983",
55+
"tx_broadcast_packets": "626562",
56+
"tx_errors": "0",
57+
"tx_dropped": "0",
58+
"tx_crc_fcs": "n/a",
59+
"tx_collision": "0"
60+
},
61+
{
62+
"auto_neg": "",
63+
"duplex": "",
64+
"error_control": "",
65+
"flow_control": "",
66+
"hw_type": "Ethernet",
67+
"if_type": "",
68+
"interface": "vlan100",
69+
"interface_desc": "mgmt",
70+
"link_admin": "up",
71+
"link_state_info": "",
72+
"link_status": "up",
73+
"link_transitions": "",
74+
"mac_address": "bc:d7:a5:be:a5:00",
75+
"mtu": "",
76+
"qos_trust": "",
77+
"rx_broadcast_packets": "",
78+
"rx_crc_fcs": "",
79+
"rx_dropped": "",
80+
"rx_errors": "",
81+
"rx_mcast_packets": "",
82+
"rx_total_bytes": "",
83+
"rx_total_packets": "",
84+
"rx_unicast_packets": "",
85+
"speed": "",
86+
"tx_broadcast_packets": "",
87+
"tx_collision": "",
88+
"tx_crc_fcs": "",
89+
"tx_dropped": "",
90+
"tx_errors": "",
91+
"tx_mcast_packets": "",
92+
"tx_total_bytes": "",
93+
"tx_total_packets": "",
94+
"tx_unicast_packets": "",
95+
"vlan_access": "",
96+
"vlan_mode": "",
97+
"ip_address": "198.51.100.1/24",
98+
"vlan_trunk": [],
99+
"vlan_native": "",
100+
"aggregated_interfaces": []
101+
}
102+
]
103+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"device_type": "JL664A 6300M 24G 4SFP56 Swch ",
3+
"hostname": "SW-CORE",
4+
"mask_length": 24,
5+
"mgmt_interface": "vlan100",
6+
"serial": "SG9BKN123V"
7+
}

0 commit comments

Comments
 (0)