Skip to content

Commit 33c28de

Browse files
committed
support to skip device type updates
1 parent e184cf0 commit 33c28de

File tree

3 files changed

+48
-28
lines changed

3 files changed

+48
-28
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ The plugin behavior can be controlled with the following list of settings
6666
- `default_device_role_color` string (default FF0000), color assigned to the device role if it needs to be created.
6767
- `default_management_interface` string (default "PLACEHOLDER"), name of the management interface that will be created, if one can't be identified on the device.
6868
- `default_management_prefix_length` integer ( default 0), length of the prefix that will be used for the management IP address, if the IP can't be found.
69+
- `skip_device_type_on_update` boolean (default False), If True, an existing NetBox device will not get its device type updated. If False, device type will be updated with one discovered on a device.
70+
- `skip_manufacturer_on_update` boolean (default False), If True, an existing NetBox device will not get its manufacturer updated. If False, manufacturer will be updated with one discovered on a device.
6971
- `platform_map` (dictionary), mapping of an **auto-detected** Netmiko platform to the **NetBox slug** name of your Platform. The dictionary should be in the format:
7072
```python
7173
{

netbox_onboarding/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class OnboardingConfig(PluginConfig):
3939
"default_management_prefix_length": 0,
4040
"default_device_status": "active",
4141
"create_management_interface_if_missing": True,
42+
"skip_device_type_on_update": False,
43+
"skip_manufacturer_on_update": False,
4244
"platform_map": {},
4345
"onboarding_extensions_map": {"ios": "netbox_onboarding.onboarding_extensions.ios",},
4446
}

netbox_onboarding/netbox_keeper.py

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,30 @@ def __init__( # pylint: disable=R0913,R0914
9797
self.nb_platform = None
9898

9999
self.device = None
100+
self.onboarded_device = None
100101
self.nb_mgmt_ifname = None
101102
self.nb_primary_ip = None
102103

104+
def ensure_onboarded_device(self):
105+
"""Lookup if the device already exists in the NetBox.
106+
107+
Lookup is performed by querying for the IP address of the onboarded device.
108+
If the device with a given IP is already in NetBox, its attributes including name could be updated
109+
"""
110+
try:
111+
if self.netdev_mgmt_ip_address:
112+
self.onboarded_device = Device.objects.get(primary_ip4__address__net_host=self.netdev_mgmt_ip_address)
113+
except Device.DoesNotExist:
114+
logger.info(
115+
"Could not find existing NetBox device for requested primary IP address (%s)",
116+
self.netdev_mgmt_ip_address,
117+
)
118+
except Device.MultipleObjectsReturned:
119+
raise OnboardException(
120+
reason="fail-general",
121+
message=f"ERROR multiple devices using same IP in NetBox: {self.netdev_mgmt_ip_address}",
122+
)
123+
103124
def ensure_device_site(self):
104125
"""Ensure device's site."""
105126
try:
@@ -108,9 +129,17 @@ def ensure_device_site(self):
108129
raise OnboardException(reason="fail-config", message=f"Site not found: {self.netdev_nb_site_slug}")
109130

110131
def ensure_device_manufacturer(
111-
self, create_manufacturer=PLUGIN_SETTINGS["create_manufacturer_if_missing"],
132+
self,
133+
create_manufacturer=PLUGIN_SETTINGS["create_manufacturer_if_missing"],
134+
skip_manufacturer_on_update=PLUGIN_SETTINGS["skip_manufacturer_on_update"],
112135
):
113136
"""Ensure device's manufacturer."""
137+
# Support to skip manufacturer updates for existing devices
138+
if self.onboarded_device and skip_manufacturer_on_update:
139+
self.nb_manufacturer = self.onboarded_device.device_type.manufacturer
140+
141+
return
142+
114143
# First ensure that the vendor, as extracted from the network device exists
115144
# in NetBox. We need the ID for this vendor when ensuring the DeviceType
116145
# instance.
@@ -128,13 +157,15 @@ def ensure_device_manufacturer(
128157
)
129158

130159
def ensure_device_type(
131-
self, create_device_type=PLUGIN_SETTINGS["create_device_type_if_missing"],
160+
self,
161+
create_device_type=PLUGIN_SETTINGS["create_device_type_if_missing"],
162+
skip_device_type_on_update=PLUGIN_SETTINGS["skip_device_type_on_update"],
132163
):
133164
"""Ensure the Device Type (slug) exists in NetBox associated to the netdev "model" and "vendor" (manufacturer).
134165
135166
Args:
136-
#create_manufacturer (bool) :Flag to indicate if we need to create the manufacturer, if not already present
137167
create_device_type (bool): Flag to indicate if we need to create the device_type, if not already present
168+
skip_device_type_on_update (bool): Flag to indicate if we skip device type updates for existing devices
138169
Raises:
139170
OnboardException('fail-config'):
140171
When the device vendor value does not exist as a Manufacturer in
@@ -145,6 +176,12 @@ def ensure_device_type(
145176
manufacturer. This should *not* happen, but guard-rail checking
146177
regardless in case two vendors have the same model name.
147178
"""
179+
# Support to skip device type updates for existing devices
180+
if self.onboarded_device and skip_device_type_on_update:
181+
self.nb_device_type = self.onboarded_device.device_type
182+
183+
return
184+
148185
# Now see if the device type (slug) already exists,
149186
# if so check to make sure that it is not assigned as a different manufacturer
150187
# if it doesn't exist, create it if the flag 'create_device_type_if_missing' is defined
@@ -268,38 +305,16 @@ def ensure_device_instance(self, default_status=PLUGIN_SETTINGS["default_device_
268305
Args:
269306
default_status (str) : status assigned to a new device by default.
270307
"""
271-
# Lookup if the device already exists in the NetBox
272-
# First update and creation lookup is by checking the IP address
273-
# of the onboarded device.
274-
#
275-
# If the device with a given IP is already in NetBox,
276-
# any attributes including name could be updated
277-
onboarded_device = None
278-
279-
try:
280-
if self.netdev_mgmt_ip_address:
281-
onboarded_device = Device.objects.get(primary_ip4__address__net_host=self.netdev_mgmt_ip_address)
282-
except Device.DoesNotExist:
283-
logger.info(
284-
"Could not find existing NetBox device for requested primary IP address (%s)",
285-
self.netdev_mgmt_ip_address,
286-
)
287-
except Device.MultipleObjectsReturned:
288-
raise OnboardException(
289-
reason="fail-general",
290-
message=f"ERROR multiple devices using same IP in NetBox: {self.netdev_mgmt_ip_address}",
291-
)
292-
293-
if onboarded_device:
308+
if self.onboarded_device:
294309
# Construct lookup arguments if onboarded device already exists in NetBox
295310

296311
logger.info(
297312
"Found existing NetBox device (%s) for requested primary IP address (%s)",
298-
onboarded_device.name,
313+
self.onboarded_device.name,
299314
self.netdev_mgmt_ip_address,
300315
)
301316
lookup_args = {
302-
"pk": onboarded_device.pk,
317+
"pk": self.onboarded_device.pk,
303318
"defaults": dict(
304319
name=self.netdev_hostname,
305320
device_type=self.nb_device_type,
@@ -362,6 +377,7 @@ def ensure_primary_ip(self):
362377

363378
def ensure_device(self):
364379
"""Ensure that the device represented by the DevNetKeeper exists in the NetBox system."""
380+
self.ensure_onboarded_device()
365381
self.ensure_device_site()
366382
self.ensure_device_manufacturer()
367383
self.ensure_device_type()

0 commit comments

Comments
 (0)