Fix the ipsec conn issue when peer addr is fqdn
ipsec site connection fails when fqdn is provided for peer addr. The failure is because the command 'ip route get' expects ip address. This patch fixes the issue by resolving the fqdn to the ip address and using this ip address to the 'ip route get'. Change-Id: I3e22e8170ffe977ece3d36355a59def9e9d01d94 Closes-bug: #1405413
This commit is contained in:
parent
f351173db5
commit
e546478c7f
|
@ -87,6 +87,10 @@ class RouterIsNotExternal(nexception.BadRequest):
|
|||
message = _("Router %(router_id)s has no external network gateway set")
|
||||
|
||||
|
||||
class VPNPeerAddressNotResolved(nexception.InvalidInput):
|
||||
message = _("Peer address %(peer_address)s cannot be resolved")
|
||||
|
||||
|
||||
vpn_supported_initiators = ['bi-directional', 'response-only']
|
||||
vpn_supported_encryption_algorithms = ['3des', 'aes-128',
|
||||
'aes-192', 'aes-256']
|
||||
|
|
|
@ -20,10 +20,12 @@ import os
|
|||
import re
|
||||
import shutil
|
||||
import six
|
||||
import socket
|
||||
|
||||
|
||||
from neutron.agent.linux import ip_lib
|
||||
from neutron.agent.linux import utils
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.common import rpc as n_rpc
|
||||
from neutron import context
|
||||
from neutron.i18n import _LE
|
||||
|
@ -35,6 +37,7 @@ from oslo_concurrency import lockutils
|
|||
from oslo_config import cfg
|
||||
import oslo_messaging
|
||||
|
||||
from neutron_vpnaas.extensions import vpnaas
|
||||
from neutron_vpnaas.services.vpn.common import topics
|
||||
from neutron_vpnaas.services.vpn import device_drivers
|
||||
|
||||
|
@ -338,9 +341,25 @@ class OpenSwanProcess(BaseSwanProcess):
|
|||
self.start()
|
||||
return
|
||||
|
||||
def _resolve_fqdn(self, fqdn):
|
||||
# The first addrinfo member from the list returned by
|
||||
# socket.getaddrinfo is used for the address resolution.
|
||||
# The code doesn't filter for ipv4 or ipv6 address.
|
||||
try:
|
||||
addrinfo = socket.getaddrinfo(fqdn, None)[0]
|
||||
return addrinfo[-1][0]
|
||||
except socket.gaierror:
|
||||
LOG.exception(_LE("Peer address %s cannot be resolved"), fqdn)
|
||||
raise vpnaas.VPNPeerAddressNotResolved(peer_address=fqdn)
|
||||
|
||||
def _get_nexthop(self, address):
|
||||
routes = self._execute(
|
||||
['ip', 'route', 'get', address])
|
||||
# check if address is an ip address or fqdn
|
||||
invalid_ip_address = attributes._validate_ip_address(address)
|
||||
if invalid_ip_address:
|
||||
ip_addr = self._resolve_fqdn(address)
|
||||
else:
|
||||
ip_addr = address
|
||||
routes = self._execute(['ip', 'route', 'get', ip_addr])
|
||||
if routes.find('via') >= 0:
|
||||
return routes.split(' ')[2]
|
||||
return address
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
import contextlib
|
||||
import copy
|
||||
import mock
|
||||
import socket
|
||||
|
||||
from neutron.openstack.common import uuidutils
|
||||
from neutron.plugins.common import constants
|
||||
|
||||
from neutron_vpnaas.extensions import vpnaas
|
||||
from neutron_vpnaas.services.vpn.device_drivers import ipsec as ipsec_driver
|
||||
from neutron_vpnaas.tests import base
|
||||
|
||||
|
@ -195,7 +197,7 @@ class TestIPsecDeviceDriver(base.BaseTestCase):
|
|||
self.assertEqual(ensure_p.call_count, 0)
|
||||
|
||||
def test__sync_vpn_processes_router_with_no_vpn_and_no_vpn_services(self):
|
||||
"""No vpn services running and router not hosting vpn svc"""
|
||||
"""No vpn services running and router not hosting vpn svc."""
|
||||
router_id_no_vpn = _uuid()
|
||||
self.driver.process_status_cache = {}
|
||||
self.driver.processes = {}
|
||||
|
@ -384,3 +386,71 @@ class TestIPsecDeviceDriver(base.BaseTestCase):
|
|||
missing_conn = new_status['ipsec_site_connections'].get('20')
|
||||
self.assertIsNotNone(missing_conn)
|
||||
self.assertEqual(constants.DOWN, missing_conn['status'])
|
||||
|
||||
|
||||
class TestOpenSwanProcess(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestOpenSwanProcess, self).setUp()
|
||||
self.driver = ipsec_driver.OpenSwanProcess(mock.ANY, 'foo-process-id',
|
||||
FAKE_VPN_SERVICE, mock.ANY)
|
||||
|
||||
def test__resolve_fqdn(self):
|
||||
with mock.patch.object(socket, 'getaddrinfo') as mock_getaddr_info:
|
||||
mock_getaddr_info.return_value = [(2, 1, 6, '',
|
||||
('172.168.1.2', 0))]
|
||||
resolved_ip_addr = self.driver._resolve_fqdn('fqdn.foo.addr')
|
||||
self.assertEqual('172.168.1.2', resolved_ip_addr)
|
||||
|
||||
def _test_get_nexthop_helper(self, address, _resolve_fqdn_side_effect,
|
||||
_execute_ret_val, expected_ip_cmd,
|
||||
expected_nexthop):
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.driver, '_execute'),
|
||||
mock.patch.object(self.driver, '_resolve_fqdn')
|
||||
) as (fake_execute, fake_resolve_fqdn):
|
||||
fake_resolve_fqdn.side_effect = _resolve_fqdn_side_effect
|
||||
fake_execute.return_value = _execute_ret_val
|
||||
|
||||
returned_next_hop = self.driver._get_nexthop(address)
|
||||
_resolve_fqdn_expected_call_count = (
|
||||
1 if _resolve_fqdn_side_effect else 0)
|
||||
|
||||
self.assertEqual(_resolve_fqdn_expected_call_count,
|
||||
fake_resolve_fqdn.call_count)
|
||||
fake_execute.assert_called_once_with(expected_ip_cmd)
|
||||
self.assertEqual(expected_nexthop, returned_next_hop)
|
||||
|
||||
def test__get_nexthop_peer_addr_is_ipaddr(self):
|
||||
gw_addr = '10.0.0.1'
|
||||
_fake_execute_ret_val = '172.168.1.2 via %s' % gw_addr
|
||||
peer_address = '172.168.1.2'
|
||||
expected_ip_cmd = ['ip', 'route', 'get', peer_address]
|
||||
self._test_get_nexthop_helper(peer_address, None,
|
||||
_fake_execute_ret_val, expected_ip_cmd,
|
||||
gw_addr)
|
||||
|
||||
def test__get_nexthop_peer_addr_is_valid_fqdn(self):
|
||||
peer_address = 'foo.peer.addr'
|
||||
expected_ip_cmd = ['ip', 'route', 'get', '172.168.1.2']
|
||||
gw_addr = '10.0.0.1'
|
||||
_fake_execute_ret_val = '172.168.1.2 via %s' % gw_addr
|
||||
|
||||
def _fake_resolve_fqdn(address):
|
||||
return '172.168.1.2'
|
||||
|
||||
self._test_get_nexthop_helper(peer_address, _fake_resolve_fqdn,
|
||||
_fake_execute_ret_val, expected_ip_cmd,
|
||||
gw_addr)
|
||||
|
||||
def test__get_nexthop_gw_not_present(self):
|
||||
peer_address = '172.168.1.2'
|
||||
expected_ip_cmd = ['ip', 'route', 'get', '172.168.1.2']
|
||||
_fake_execute_ret_val = ' '
|
||||
|
||||
self._test_get_nexthop_helper(peer_address, None,
|
||||
_fake_execute_ret_val, expected_ip_cmd,
|
||||
peer_address)
|
||||
|
||||
def test__get_nexthop_fqdn_peer_addr_is_not_resolved(self):
|
||||
self.assertRaises(vpnaas.VPNPeerAddressNotResolved,
|
||||
self.driver._get_nexthop, 'foo.peer.addr')
|
||||
|
|
Loading…
Reference in New Issue