Skip to content

Commit 033a237

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Fix API URL reachability test to use full URL with port"
2 parents a1739af + 7d7735a commit 033a237

File tree

3 files changed

+42
-43
lines changed

3 files changed

+42
-43
lines changed

ironic_python_agent/agent.py

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -308,45 +308,36 @@ def _get_route_source(self, dest):
308308

309309
return source
310310

311-
def _test_ip_reachability(self, ip_address):
312-
"""Test if an IP address is reachable via HTTP GET request.
311+
def _test_ip_reachability(self, api_url):
312+
"""Test if an API URL is reachable via HTTP GET request.
313313
314-
:param ip_address: The IP address to test
315-
:returns: True if the IP is reachable, False otherwise
314+
:param api_url: The full API URL to test (including protocol and port)
315+
:returns: True if the URL is reachable, False otherwise
316316
"""
317-
test_urls = [
318-
'http://{}'.format(ip_address),
319-
'https://{}'.format(ip_address),
320-
]
321-
322-
for url in test_urls:
323-
try:
324-
# Disable SSL verification for reachability testing only
325-
response = requests.get(
326-
url, timeout=CONF.http_request_timeout, verify=False
327-
) # nosec
328-
# Any HTTP response (even 404, 500, etc.) indicates
329-
# reachability
330-
LOG.debug('IP %s is reachable via %s (status: %s)',
331-
ip_address, url, response.status_code)
332-
return True
333-
except requests.exceptions.RequestException as e:
334-
LOG.debug('IP %s not reachable via %s: %s',
335-
ip_address, url, e)
336-
continue
337-
338-
return False
317+
try:
318+
# Disable SSL verification for reachability testing only
319+
response = requests.get(
320+
api_url, timeout=CONF.http_request_timeout, verify=False
321+
) # nosec
322+
# Any HTTP response (even 404, 500, etc.) indicates reachability
323+
LOG.debug('API URL %s is reachable (status: %s)',
324+
api_url, response.status_code)
325+
return True
326+
except requests.exceptions.RequestException as e:
327+
LOG.debug('API URL %s not reachable: %s', api_url, e)
328+
return False
339329

340330
def _find_routable_addr(self):
341331
# Process API URLs: check reachability and collect IPs in one pass
342332
reachable_api_urls = []
343333
ips = set()
344334

345335
for api_url in self.api_urls:
346-
ironic_host = urlparse.urlparse(api_url).hostname
336+
parsed = urlparse.urlparse(api_url)
337+
ironic_host = parsed.hostname
347338

348-
# Test reachability once per hostname
349-
if self._test_ip_reachability(ironic_host):
339+
# Test reachability using the full URL (including port)
340+
if self._test_ip_reachability(api_url):
350341
reachable_api_urls.append(api_url)
351342
LOG.debug('API URL %s is reachable', api_url)
352343

ironic_python_agent/tests/unit/test_agent.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -956,34 +956,34 @@ def test_test_ip_reachability_success(self, mock_get):
956956
mock_response.status_code = 200
957957
mock_get.return_value = mock_response
958958

959-
result = self.agent._test_ip_reachability('192.168.1.1')
959+
result = self.agent._test_ip_reachability('http://192.168.1.1:6385/v1')
960960
self.assertTrue(result)
961-
mock_get.assert_called_once_with('http://192.168.1.1', timeout=30,
962-
verify=False)
961+
mock_get.assert_called_once_with('http://192.168.1.1:6385/v1',
962+
timeout=30, verify=False)
963963

964964
@mock.patch('requests.get', autospec=True)
965965
def test_test_ip_reachability_https_success(self, mock_get):
966-
"""Test _test_ip_reachability with HTTPS fallback."""
967-
# First call (HTTP) fails, second call (HTTPS) succeeds
968-
mock_get.side_effect = [
969-
requests.exceptions.ConnectionError('Connection failed'),
970-
mock.Mock(status_code=404) # Any status code indicates
971-
# reachability
972-
]
966+
"""Test _test_ip_reachability with HTTPS URL."""
967+
mock_response = mock.Mock()
968+
mock_response.status_code = 404 # Any status code is acceptable
969+
mock_get.return_value = mock_response
973970

974-
result = self.agent._test_ip_reachability('192.168.1.1')
971+
result = self.agent._test_ip_reachability(
972+
'https://192.168.1.1:6385/v1')
975973
self.assertTrue(result)
976-
self.assertEqual(mock_get.call_count, 2)
974+
mock_get.assert_called_once_with('https://192.168.1.1:6385/v1',
975+
timeout=30, verify=False)
977976

978977
@mock.patch('requests.get', autospec=True)
979978
def test_test_ip_reachability_failure(self, mock_get):
980979
"""Test _test_ip_reachability with connection failure."""
981980
mock_get.side_effect = requests.exceptions.ConnectionError(
982981
'Connection failed')
983982

984-
result = self.agent._test_ip_reachability('192.168.1.1')
983+
result = self.agent._test_ip_reachability('http://192.168.1.1:6385/v1')
985984
self.assertFalse(result)
986-
self.assertEqual(mock_get.call_count, 2) # Tries both HTTP and HTTPS
985+
mock_get.assert_called_once_with('http://192.168.1.1:6385/v1',
986+
timeout=30, verify=False)
987987

988988
@mock.patch('requests.get', autospec=True)
989989
@mock.patch.object(socket, 'getaddrinfo', autospec=True)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
fixes:
3+
- |
4+
Fixes an issue where the agent could not find a valid IP address when
5+
the Ironic API was running on a non-standard port. The reachability test
6+
now uses the full API URL including the port number, instead of only
7+
using the hostname. This prevents ``LookupAgentIPError`` when connecting
8+
to Ironic APIs on custom ports.

0 commit comments

Comments
 (0)