Merge "Advertise the correct address when using IPv6"
This commit is contained in:
commit
51ab461af8
@ -210,7 +210,7 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
|
||||
return
|
||||
|
||||
try:
|
||||
return out.strip().split('\n')[0].split('src')[1].strip()
|
||||
return out.strip().split('\n')[0].split('src')[1].split()[0]
|
||||
except IndexError:
|
||||
LOG.warning('No route to host %(dest)s, route record: %(rec)s',
|
||||
{'dest': dest, 'rec': out})
|
||||
|
@ -20,6 +20,7 @@ import requests
|
||||
|
||||
from ironic_python_agent import encoding
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent import netutils
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
@ -141,5 +142,5 @@ class APIClient(object):
|
||||
raise loopingcall.LoopingCallDone(retvalue=content)
|
||||
|
||||
def _get_agent_url(self, advertise_address):
|
||||
return 'http://{}:{}'.format(advertise_address[0],
|
||||
return 'http://{}:{}'.format(netutils.wrap_ipv6(advertise_address[0]),
|
||||
advertise_address[1])
|
||||
|
@ -22,6 +22,7 @@ import sys
|
||||
import netifaces
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import netutils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
@ -213,3 +214,9 @@ def interface_has_carrier(interface_name):
|
||||
LOG.debug('No carrier information for interface %s',
|
||||
interface_name)
|
||||
return False
|
||||
|
||||
|
||||
def wrap_ipv6(ip):
|
||||
if netutils.is_valid_ipv6(ip):
|
||||
return "[%s]" % ip
|
||||
return ip
|
||||
|
@ -466,6 +466,22 @@ class TestBaseAgent(test_base.BaseTestCase):
|
||||
self.assertRaises(errors.UnknownNodeError,
|
||||
self.agent.get_node_uuid)
|
||||
|
||||
@mock.patch.object(utils, 'execute', autospec=True)
|
||||
def test_get_route_source(self, mock_execute):
|
||||
mock_execute.return_value = ('XXX src 1.2.3.4 XXX\n cache', None)
|
||||
|
||||
source = self.agent._get_route_source('XXX')
|
||||
self.assertEqual('1.2.3.4', source)
|
||||
|
||||
@mock.patch.object(agent, 'LOG', autospec=True)
|
||||
@mock.patch.object(utils, 'execute', autospec=True)
|
||||
def test_get_route_source_indexerror(self, mock_execute, mock_log):
|
||||
mock_execute.return_value = ('XXX src \n cache', None)
|
||||
|
||||
source = self.agent._get_route_source('XXX')
|
||||
self.assertIsNone(source)
|
||||
mock_log.warning.assert_called_once()
|
||||
|
||||
|
||||
@mock.patch.object(hardware.GenericHardwareManager, '_wait_for_disks',
|
||||
lambda self: None)
|
||||
@ -597,6 +613,22 @@ class TestAdvertiseAddress(test_base.BaseTestCase):
|
||||
mock_exec.assert_called_once_with('ip', 'route', 'get', '1.2.1.2')
|
||||
mock_gethostbyname.assert_called_once_with('1.2.1.2')
|
||||
|
||||
def test_route_with_ipv6(self, mock_exec, mock_gethostbyname):
|
||||
self.agent.api_url = 'http://[fc00:1111::1]:8081/v1'
|
||||
mock_gethostbyname.side_effect = socket.gaierror()
|
||||
mock_exec.return_value = (
|
||||
"""fc00:101::1 dev br-ctlplane src fc00:101::4 metric 0
|
||||
cache """,
|
||||
""
|
||||
)
|
||||
|
||||
self.agent.set_agent_advertise_addr()
|
||||
|
||||
self.assertEqual(('fc00:101::4', 9990),
|
||||
self.agent.advertise_address)
|
||||
mock_exec.assert_called_once_with('ip', 'route', 'get', 'fc00:1111::1')
|
||||
mock_gethostbyname.assert_called_once_with('fc00:1111::1')
|
||||
|
||||
def test_route_with_host(self, mock_exec, mock_gethostbyname):
|
||||
mock_gethostbyname.return_value = '1.2.1.2'
|
||||
mock_exec.return_value = (
|
||||
|
@ -70,8 +70,29 @@ class TestBaseIronicPythonAgent(test_base.BaseTestCase):
|
||||
|
||||
heartbeat_path = 'v1/heartbeat/deadbeef-dabb-ad00-b105-f00d00bab10c'
|
||||
request_args = self.api_client.session.request.call_args[0]
|
||||
data = self.api_client.session.request.call_args[1]['data']
|
||||
self.assertEqual('POST', request_args[0])
|
||||
self.assertEqual(API_URL + heartbeat_path, request_args[1])
|
||||
self.assertEqual('{"callback_url": "http://192.0.2.1:9999"}', data)
|
||||
|
||||
def test_successful_heartbeat_ip6(self):
|
||||
response = FakeResponse(status_code=202)
|
||||
|
||||
self.api_client.session.request = mock.Mock()
|
||||
self.api_client.session.request.return_value = response
|
||||
|
||||
self.api_client.heartbeat(
|
||||
uuid='deadbeef-dabb-ad00-b105-f00d00bab10c',
|
||||
advertise_address=('fc00:1111::4', '9999')
|
||||
)
|
||||
|
||||
heartbeat_path = 'v1/heartbeat/deadbeef-dabb-ad00-b105-f00d00bab10c'
|
||||
request_args = self.api_client.session.request.call_args[0]
|
||||
data = self.api_client.session.request.call_args[1]['data']
|
||||
self.assertEqual('POST', request_args[0])
|
||||
self.assertEqual(API_URL + heartbeat_path, request_args[1])
|
||||
self.assertEqual('{"callback_url": "http://[fc00:1111::4]:9999"}',
|
||||
data)
|
||||
|
||||
def test_heartbeat_requests_exception(self):
|
||||
self.api_client.session.request = mock.Mock()
|
||||
@ -240,3 +261,11 @@ class TestBaseIronicPythonAgent(test_base.BaseTestCase):
|
||||
node_uuid=None)
|
||||
|
||||
self.assertFalse(error)
|
||||
|
||||
def test_get_agent_url_ipv4(self):
|
||||
url = self.api_client._get_agent_url(('1.2.3.4', '9999'))
|
||||
self.assertEqual('http://1.2.3.4:9999', url)
|
||||
|
||||
def test_get_agent_url_ipv6(self):
|
||||
url = self.api_client._get_agent_url(('1:2::3:4', '9999'))
|
||||
self.assertEqual('http://[1:2::3:4]:9999', url)
|
||||
|
@ -336,3 +336,11 @@ class TestNetutils(test_base.BaseTestCase):
|
||||
|
||||
sock1.close.assert_called_once_with()
|
||||
sock2.close.assert_called_once_with()
|
||||
|
||||
def test_wrap_ipv6(self):
|
||||
res = netutils.wrap_ipv6('1:2::3:4')
|
||||
self.assertEqual('[1:2::3:4]', res)
|
||||
|
||||
def test_wrap_ipv6_with_ipv4(self):
|
||||
res = netutils.wrap_ipv6('1.2.3.4')
|
||||
self.assertEqual('1.2.3.4', res)
|
||||
|
6
releasenotes/notes/ip6-addresses-1c2b9bcd9a124de7.yaml
Normal file
6
releasenotes/notes/ip6-addresses-1c2b9bcd9a124de7.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- Ironic Python Agent now correctly detects its IPv6 address
|
||||
if communicating with ironic over IPv6. This address is also
|
||||
wrapped in square brackets if the address being advertised
|
||||
is IPv6.
|
Loading…
Reference in New Issue
Block a user