Skip to content

Commit 19185f4

Browse files
committed
Refactor of DNS resolving
1 parent 986fe8b commit 19185f4

File tree

4 files changed

+64
-58
lines changed

4 files changed

+64
-58
lines changed

netbox_onboarding/helpers.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""OnboardingTask Django model.
2+
3+
(c) 2020 Network To Code
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
"""
14+
15+
import socket
16+
17+
import netaddr
18+
from netaddr.core import AddrFormatError
19+
20+
from .exceptions import OnboardException
21+
22+
23+
def onboarding_task_fqdn_to_ip(ot):
24+
"""Method to assure OT has FQDN resolved to IP address and rewritten into OT.
25+
26+
If it is a DNS name, attempt to resolve the DNS address and assign the IP address to the
27+
name.
28+
29+
Returns:
30+
None
31+
32+
Raises:
33+
OnboardException("fail-general"):
34+
When a prefix was entered for an IP address
35+
OnboardException("fail-dns"):
36+
When a Name lookup via DNS fails to resolve an IP address
37+
"""
38+
try:
39+
# If successful, this is an IP address and can pass
40+
netaddr.IPAddress(ot.ip_address)
41+
# Raise an Exception for Prefix values
42+
except ValueError:
43+
raise OnboardException(reason="fail-general", message=f"ERROR appears a prefix was entered: {ot.ip_address}")
44+
# An AddrFormatError exception means that there is not an IP address in the field, and should continue on
45+
except AddrFormatError:
46+
try:
47+
# Perform DNS Lookup
48+
ot.ip_address = socket.gethostbyname(ot.ip_address)
49+
ot.save()
50+
except socket.gaierror:
51+
# DNS Lookup has failed, Raise an exception for unable to complete DNS lookup
52+
raise OnboardException(reason="fail-dns", message=f"ERROR failed to complete DNS lookup: {ot.ip_address}")

netbox_onboarding/netdev_keeper.py

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@
1616
import logging
1717
import socket
1818

19-
import netaddr
2019
from django.conf import settings
2120
from napalm import get_network_driver
2221
from napalm.base.exceptions import ConnectionException, CommandErrorException
23-
from netaddr.core import AddrFormatError
2422
from netmiko.ssh_autodetect import SSHDetect
2523
from netmiko.ssh_exception import NetMikoAuthenticationException
2624
from netmiko.ssh_exception import NetMikoTimeoutException
@@ -96,46 +94,6 @@ def __init__( # pylint: disable=R0913
9694
self.onboarding_class = StandaloneOnboarding
9795
self.driver_addon_result = None
9896

99-
def check_ip(self):
100-
"""Method to check if the IP address form field was an IP address.
101-
102-
If it is a DNS name, attempt to resolve the DNS address and assign the IP address to the
103-
name.
104-
105-
Returns:
106-
(bool): True if the IP address is an IP address, or a DNS entry was found and
107-
reassignment of the ot.ip_address was done.
108-
False if unable to find a device IP (error)
109-
110-
Raises:
111-
OnboardException("fail-general"):
112-
When a prefix was entered for an IP address
113-
OnboardException("fail-dns"):
114-
When a Name lookup via DNS fails to resolve an IP address
115-
"""
116-
try:
117-
# Assign checked_ip to None for error handling
118-
# If successful, this is an IP address and can pass
119-
checked_ip = netaddr.IPAddress(self.hostname)
120-
return True
121-
# Catch when someone has put in a prefix address, raise an exception
122-
except ValueError:
123-
raise OnboardException(
124-
reason="fail-general", message=f"ERROR appears a prefix was entered: {self.hostname}"
125-
)
126-
# An AddrFormatError exception means that there is not an IP address in the field, and should continue on
127-
except AddrFormatError:
128-
try:
129-
# Do a lookup of name to get the IP address to connect to
130-
checked_ip = socket.gethostbyname(self.hostname)
131-
self.hostname = checked_ip
132-
return True
133-
except socket.gaierror:
134-
# DNS Lookup has failed, Raise an exception for unable to complete DNS lookup
135-
raise OnboardException(
136-
reason="fail-dns", message=f"ERROR failed to complete DNS lookup: {self.hostname}"
137-
)
138-
13997
def check_reachability(self):
14098
"""Ensure that the device at the mgmt-ipaddr provided is reachable.
14199
@@ -231,9 +189,6 @@ def get_onboarding_facts(self):
231189
OnboardException('fail-general'):
232190
Any other unexpected device comms failure.
233191
"""
234-
# Check to see if the IP address entered was an IP address or a DNS entry, get the IP address
235-
self.check_ip()
236-
237192
self.check_reachability()
238193

239194
logger.info("COLLECT: device information %s", self.hostname)

netbox_onboarding/tests/test_netdev_keeper.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
from dcim.models import Site, DeviceRole, Platform
2020

2121
from netbox_onboarding.exceptions import OnboardException
22+
from netbox_onboarding.helpers import onboarding_task_fqdn_to_ip
2223
from netbox_onboarding.models import OnboardingTask
23-
from netbox_onboarding.netdev_keeper import NetdevKeeper
2424

2525

2626
class NetdevKeeperTestCase(TestCase):
@@ -46,37 +46,32 @@ def setUp(self):
4646
ip_address="192.0.2.1/32", site=self.site1, role=self.device_role1, platform=self.platform1
4747
)
4848

49-
@mock.patch("netbox_onboarding.netdev_keeper.socket.gethostbyname")
49+
@mock.patch("netbox_onboarding.helpers.socket.gethostbyname")
5050
def test_check_ip(self, mock_get_hostbyname):
5151
"""Check DNS to IP address."""
5252
# Look up response value
5353
mock_get_hostbyname.return_value = "192.0.2.1"
5454

55-
# Create a Device Keeper object of the device
56-
ndk4 = NetdevKeeper(hostname=self.onboarding_task4.ip_address)
57-
58-
# Check that the IP address is returned
59-
self.assertTrue(ndk4.check_ip())
55+
# FQDN -> IP
56+
onboarding_task_fqdn_to_ip(ot=self.onboarding_task4)
6057

6158
# Run the check to change the IP address
62-
self.assertEqual(ndk4.hostname, "192.0.2.1")
59+
self.assertEqual(self.onboarding_task4.ip_address, "192.0.2.1")
6360

64-
@mock.patch("netbox_onboarding.netdev_keeper.socket.gethostbyname")
61+
@mock.patch("netbox_onboarding.helpers.socket.gethostbyname")
6562
def test_failed_check_ip(self, mock_get_hostbyname):
6663
"""Check DNS to IP address failing."""
6764
# Look up a failed response
6865
mock_get_hostbyname.side_effect = gaierror(8)
69-
ndk5 = NetdevKeeper(hostname=self.onboarding_task5.ip_address)
70-
ndk7 = NetdevKeeper(hostname=self.onboarding_task7.ip_address)
7166

7267
# Check for bad.local raising an exception
7368
with self.assertRaises(OnboardException) as exc_info:
74-
ndk5.check_ip()
69+
onboarding_task_fqdn_to_ip(ot=self.onboarding_task5)
7570
self.assertEqual(exc_info.exception.message, "ERROR failed to complete DNS lookup: bad.local")
7671
self.assertEqual(exc_info.exception.reason, "fail-dns")
7772

7873
# Check for exception with prefix address entered
7974
with self.assertRaises(OnboardException) as exc_info:
80-
ndk7.check_ip()
75+
onboarding_task_fqdn_to_ip(ot=self.onboarding_task7)
8176
self.assertEqual(exc_info.exception.reason, "fail-prefix")
8277
self.assertEqual(exc_info.exception.message, "ERROR appears a prefix was entered: 192.0.2.1/32")

netbox_onboarding/worker.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from .choices import OnboardingFailChoices
2323
from .choices import OnboardingStatusChoices
2424
from .exceptions import OnboardException
25+
from .helpers import onboarding_task_fqdn_to_ip
2526
from .metrics import onboardingtask_results_counter
2627
from .models import OnboardingDevice
2728
from .models import OnboardingTask
@@ -43,6 +44,9 @@ def onboard_device(task_id, credentials): # pylint: disable=too-many-statements
4344

4445
ot = OnboardingTask.objects.get(id=task_id)
4546

47+
# Rewrite FQDN to IP for Onboarding Task
48+
onboarding_task_fqdn_to_ip(ot)
49+
4650
logger.info("START: onboard device")
4751
onboarded_device = None
4852

0 commit comments

Comments
 (0)