Skip to content

Commit 2dbb33d

Browse files
author
Josh VanDeraa
committed
Updates to support name resolution; Updates form; Updates readme
1 parent 478ec0b commit 2dbb33d

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,15 @@ The plugin behavior can be controlled with the following list of settings
4848
- `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.
4949

5050
## Usage
51+
5152
### Preparation
5253

53-
To work properly the plugin needs to know the Site, Platform, Device Type, Device Role of each device as well as its primary IP address.
54-
It's recommended to create these objects in NetBox ahead of time and to provide them when you want to start the onboarding process.
54+
To work properly the plugin needs to know the Site, Platform, Device Type, Device Role of each
55+
device as well as its primary IP address or DNS Name. It's recommended to create these objects in
56+
NetBox ahead of time and to provide them when you want to start the onboarding process.
57+
58+
> For DNS Name Resolution to work, the instance of NetBox must be able to resolve the name of the
59+
> device to IP address.
5560
5661
If `Platform`, `Device Type` and/or `Device Role` are not provided, the plugin will try to identify these information automatically and, based on the settings, it can create them in NetBox as needed.
5762
> If the Platform is provided, it must contains a valid Napalm driver available to the worker in Python

netbox_onboarding/forms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
class OnboardingTaskForm(BootstrapMixin, forms.ModelForm):
3030
"""Form for creating a new OnboardingTask instance."""
3131

32-
ip_address = forms.CharField(required=True, label="IP address", help_text="IP address of the device to onboard")
32+
ip_address = forms.CharField(required=True, label="IP address", help_text="IP Address/DNS Name of the device to onboard")
3333

3434
site = forms.ModelChoiceField(required=True, queryset=Site.objects.all(), to_field_name="slug")
3535

netbox_onboarding/onboard.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -213,24 +213,23 @@ def check_ip(self):
213213
214214
"""
215215
# Assign checked_ip to None for error handling
216-
checked_ip = None
217216
try:
218217
# If successful, this is an IP address and can pass
219218
checked_ip = netaddr.IPNetwork(self.ot.ip_address)
220219
return True
220+
# An AddrFormatError exception means that there is not an IP address in the field, and should continue on
221221
except AddrFormatError:
222222
pass
223223

224224
# An IP address was not detected in the IP address field, attempt to find DNS
225-
if checked_ip is None:
226-
try:
227-
# Do a lookup of name
228-
checked_ip = socket.gethostbyname(self.ot.ip_address)
229-
self.ot.ip_address = checked_ip
230-
return True
231-
except socket.gaierror:
232-
# DNS Lookup has failed, not a DNS, do not do anything
233-
return False
225+
try:
226+
# Do a lookup of name
227+
checked_ip = socket.gethostbyname(self.ot.ip_address)
228+
self.ot.ip_address = checked_ip
229+
return True
230+
except socket.gaierror:
231+
# DNS Lookup has failed, not a DNS, do not do anything
232+
return False
234233

235234
def get_required_info(
236235
self,

netbox_onboarding/tests/test_onboard.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
See the License for the specific language governing permissions and
1212
limitations under the License.
1313
"""
14+
from socket import gaierror
15+
from unittest import mock
1416
from django.test import TestCase
1517
from django.utils.text import slugify
1618

@@ -40,6 +42,13 @@ def setUp(self):
4042
self.onboarding_task3 = OnboardingTask.objects.create(
4143
ip_address="192.168.1.2", site=self.site1, role=self.device_role1, platform=self.platform1
4244
)
45+
self.onboarding_task4 = OnboardingTask.objects.create(
46+
ip_address="ntc123.local", site=self.site1, role=self.device_role1, platform=self.platform1
47+
)
48+
49+
self.onboarding_task5 = OnboardingTask.objects.create(
50+
ip_address="bad.local", site=self.site1, role=self.device_role1, platform=self.platform1
51+
)
4352

4453
self.ndk1 = NetdevKeeper(self.onboarding_task1)
4554
self.ndk1.hostname = "device1"
@@ -182,3 +191,29 @@ def test_ensure_primary_ip_not_exist(self):
182191
nbk.ensure_primary_ip()
183192
self.assertIsInstance(nbk.primary_ip, IPAddress)
184193
self.assertEqual(nbk.primary_ip.interface, nbk.interface)
194+
195+
@mock.patch("netbox_onboarding.onboard.socket.gethostbyname")
196+
def test_check_ip(self, mock_get_hostbyname):
197+
"""Check DNS to IP address."""
198+
# Look up response value
199+
mock_get_hostbyname.return_value = "192.0.2.1"
200+
201+
# Create a Device Keeper object of the device
202+
ndk4 = NetdevKeeper(self.onboarding_task4)
203+
204+
# Check that the IP address is returned
205+
self.assertTrue(ndk4.check_ip())
206+
207+
# Run the check to change the IP address
208+
ndk4.check_ip()
209+
self.assertEqual(ndk4.ot.ip_address, "192.0.2.1")
210+
211+
@mock.patch("netbox_onboarding.onboard.socket.gethostbyname")
212+
def test_failed_check_ip(self, mock_get_hostbyname):
213+
"""Check DNS to IP address failing."""
214+
# Look up a failed response
215+
mock_get_hostbyname.side_effect = gaierror(8)
216+
ndk5 = NetdevKeeper(self.onboarding_task5)
217+
218+
self.assertFalse(ndk5.check_ip())
219+

0 commit comments

Comments
 (0)