Merge "Fix API URL reachability test to use full URL with port"

This commit is contained in:
Zuul
2025年11月19日 12:36:00 +00:00
committed by Gerrit Code Review

View File

@@ -308,34 +308,24 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
return source
def _test_ip_reachability(self, ip_address):
"""Test if an IP address is reachable via HTTP GET request.
def _test_ip_reachability(self, api_url):
"""Test if an API URL is reachable via HTTP GET request.
:param ip_address: The IP address to test
:returns: True if the IP is reachable, False otherwise
:param api_url: The full API URL to test (including protocol and port)
:returns: True if the URL is reachable, False otherwise
"""
test_urls = [
'http://{}'.format(ip_address),
'https://{}'.format(ip_address),
]
for url in test_urls:
try:
# Disable SSL verification for reachability testing only
response = requests.get(
url, timeout=CONF.http_request_timeout, verify=False
) # nosec
# Any HTTP response (even 404, 500, etc.) indicates
# reachability
LOG.debug('IP %s is reachable via %s (status: %s)',
ip_address, url, response.status_code)
return True
except requests.exceptions.RequestException as e:
LOG.debug('IP %s not reachable via %s: %s',
ip_address, url, e)
continue
return False
try:
# Disable SSL verification for reachability testing only
response = requests.get(
api_url, timeout=CONF.http_request_timeout, verify=False
) # nosec
# Any HTTP response (even 404, 500, etc.) indicates reachability
LOG.debug('API URL %s is reachable (status: %s)',
api_url, response.status_code)
return True
except requests.exceptions.RequestException as e:
LOG.debug('API URL %s not reachable: %s', api_url, e)
return False
def _find_routable_addr(self):
# Process API URLs: check reachability and collect IPs in one pass
@@ -343,10 +333,11 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
ips = set()
for api_url in self.api_urls:
ironic_host = urlparse.urlparse(api_url).hostname
parsed = urlparse.urlparse(api_url)
ironic_host = parsed.hostname
# Test reachability once per hostname
if self._test_ip_reachability(ironic_host):
# Test reachability using the full URL (including port)
if self._test_ip_reachability(api_url):
reachable_api_urls.append(api_url)
LOG.debug('API URL %s is reachable', api_url)

View File

@@ -956,24 +956,23 @@ class TestBaseAgent(ironic_agent_base.IronicAgentTest):
mock_response.status_code = 200
mock_get.return_value = mock_response
result = self.agent._test_ip_reachability('192.168.1.1')
result = self.agent._test_ip_reachability('http://192.168.1.1:6385/v1')
self.assertTrue(result)
mock_get.assert_called_once_with('http://192.168.1.1', timeout=30,
verify=False)
mock_get.assert_called_once_with('http://192.168.1.1:6385/v1',
timeout=30, verify=False)
@mock.patch('requests.get', autospec=True)
def test_test_ip_reachability_https_success(self, mock_get):
"""Test _test_ip_reachability with HTTPS fallback."""
# First call (HTTP) fails, second call (HTTPS) succeeds
mock_get.side_effect = [
requests.exceptions.ConnectionError('Connection failed'),
mock.Mock(status_code=404) # Any status code indicates
# reachability
]
"""Test _test_ip_reachability with HTTPS URL."""
mock_response = mock.Mock()
mock_response.status_code = 404 # Any status code is acceptable
mock_get.return_value = mock_response
result = self.agent._test_ip_reachability('192.168.1.1')
result = self.agent._test_ip_reachability(
'https://192.168.1.1:6385/v1')
self.assertTrue(result)
self.assertEqual(mock_get.call_count, 2)
mock_get.assert_called_once_with('https://192.168.1.1:6385/v1',
timeout=30, verify=False)
@mock.patch('requests.get', autospec=True)
def test_test_ip_reachability_failure(self, mock_get):
@@ -981,9 +980,10 @@ class TestBaseAgent(ironic_agent_base.IronicAgentTest):
mock_get.side_effect = requests.exceptions.ConnectionError(
'Connection failed')
result = self.agent._test_ip_reachability('192.168.1.1')
result = self.agent._test_ip_reachability('http://192.168.1.1:6385/v1')
self.assertFalse(result)
self.assertEqual(mock_get.call_count, 2) # Tries both HTTP and HTTPS
mock_get.assert_called_once_with('http://192.168.1.1:6385/v1',
timeout=30, verify=False)
@mock.patch('requests.get', autospec=True)
@mock.patch.object(socket, 'getaddrinfo', autospec=True)

View File

@@ -0,0 +1,8 @@
---
fixes:
- |
Fixes an issue where the agent could not find a valid IP address when
the Ironic API was running on a non-standard port. The reachability test
now uses the full API URL including the port number, instead of only
using the hostname. This prevents ``LookupAgentIPError`` when connecting
to Ironic APIs on custom ports.
Reference in New Issue
openstack/ironic-python-agent
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.

The note is not visible to the blocked user.