diff mbox series

[ovs-dev] python/socket_util: Add system resolver fallback.

Message ID 20260407031532.36157-1-byunjin11@naver.com
State Rejected
Delegated to: Ilya Maximets
Headers show
Series [ovs-dev] python/socket_util: Add system resolver fallback. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/cirrus-robot success cirrus build: passed
ovsrobot/github-robot-_Build_and_Test success github build: passed

Commit Message

wlswo April 7, 2026, 3:15 a.m. UTC
When the python unbound library is not installed, dns_resolve.resolve()
  returns None for hostnames, causing all hostname-based TCP connections
  to silently fail. This affects services like neutron-ovn-metadata-agent
  that use hostname-based connection strings (e.g. tcp:hostname:6642).

  Add a fallback to socket.getaddrinfo() which uses the system resolver
  (/etc/hosts, nsswitch.conf, system DNS) when unbound is unavailable
  or fails to resolve.

  Signed-off-by: wlswo <byunjin11@naver.com>

Signed-off-by: wlswo <byunjin11@naver.com>
---
 python/ovs/socket_util.py | 11 +++++++++++
 1 file changed, 11 insertions(+)

Comments

Mike Pattrick April 8, 2026, 1:25 p.m. UTC | #1
On Tue, Apr 7, 2026 at 4:59 AM wlswo <byunjin11@naver.com> wrote:

>   When the python unbound library is not installed, dns_resolve.resolve()
>   returns None for hostnames, causing all hostname-based TCP connections
>   to silently fail. This affects services like neutron-ovn-metadata-agent
>   that use hostname-based connection strings (e.g. tcp:hostname:6642).
>
>   Add a fallback to socket.getaddrinfo() which uses the system resolver
>   (/etc/hosts, nsswitch.conf, system DNS) when unbound is unavailable
>   or fails to resolve.
>
>   Signed-off-by: wlswo <byunjin11@naver.com>
>
> Signed-off-by: wlswo <byunjin11@naver.com>
> ---
>  python/ovs/socket_util.py | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py
> index a26298b75..93764568b 100644
> --- a/python/ovs/socket_util.py
> +++ b/python/ovs/socket_util.py
> @@ -235,6 +235,17 @@ def _inet_parse_active(target, default_port):
>          host_name = str(ipaddress.ip_address(host_name))
>      except ValueError:
>          host_name = dns_resolve.resolve(host_name)

+        if not host_name:
>

resolve() returns None in the case that the dns resolution returned no
results. If we want support for system dns lookup, it should probably just
be added to dns_resolve.py.

-M


> +            # Fallback to the system resolver (e.g. /etc/hosts, system
> DNS)
> +            # when the unbound library is not available.
> +            try:
> +                result = socket.getaddrinfo(
> +                    ":".join(address[0:-1]).lstrip('[').rstrip(']'),
> +                    None, 0, socket.SOCK_STREAM)
> +                if result:
> +                    host_name = result[0][4][0]
> +            except socket.gaierror:
> +                pass
>      if not host_name:
>          raise ValueError("%s: bad peer name format" % target)
>      return (host_name, port)
> --
> 2.40.1
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Ilya Maximets May 7, 2026, 11:40 a.m. UTC | #2
On 4/7/26 5:15 AM, wlswo wrote:
>   When the python unbound library is not installed, dns_resolve.resolve()
>   returns None for hostnames, causing all hostname-based TCP connections
>   to silently fail. This affects services like neutron-ovn-metadata-agent
>   that use hostname-based connection strings (e.g. tcp:hostname:6642).
> 
>   Add a fallback to socket.getaddrinfo() which uses the system resolver
>   (/etc/hosts, nsswitch.conf, system DNS) when unbound is unavailable
>   or fails to resolve.
> 
>   Signed-off-by: wlswo <byunjin11@naver.com>
> 
> Signed-off-by: wlswo <byunjin11@naver.com>
> ---
>  python/ovs/socket_util.py | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 

Hi, wlswo.  Thanks for the patch!

> diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py
> index a26298b75..93764568b 100644
> --- a/python/ovs/socket_util.py
> +++ b/python/ovs/socket_util.py
> @@ -235,6 +235,17 @@ def _inet_parse_active(target, default_port):
>          host_name = str(ipaddress.ip_address(host_name))
>      except ValueError:
>          host_name = dns_resolve.resolve(host_name)
> +        if not host_name:
> +            # Fallback to the system resolver (e.g. /etc/hosts, system DNS)
> +            # when the unbound library is not available.
> +            try:
> +                result = socket.getaddrinfo(
> +                    ":".join(address[0:-1]).lstrip('[').rstrip(']'),
> +                    None, 0, socket.SOCK_STREAM)

getaddrinfo() can block indefinitely if the DNS server is not available.
And even if it is available the resolution can take a lot of time not
allowing the process to attend to other things.  That's the primary reason
to use unbound library, as it supports async resolution that we're utilizing.

While it may be fine for a command line tool, blocking resolution method is
not an acceptable solution for a daemon that needs to do other things as well.

Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py
index a26298b75..93764568b 100644
--- a/python/ovs/socket_util.py
+++ b/python/ovs/socket_util.py
@@ -235,6 +235,17 @@  def _inet_parse_active(target, default_port):
         host_name = str(ipaddress.ip_address(host_name))
     except ValueError:
         host_name = dns_resolve.resolve(host_name)
+        if not host_name:
+            # Fallback to the system resolver (e.g. /etc/hosts, system DNS)
+            # when the unbound library is not available.
+            try:
+                result = socket.getaddrinfo(
+                    ":".join(address[0:-1]).lstrip('[').rstrip(']'),
+                    None, 0, socket.SOCK_STREAM)
+                if result:
+                    host_name = result[0][4][0]
+            except socket.gaierror:
+                pass
     if not host_name:
         raise ValueError("%s: bad peer name format" % target)
     return (host_name, port)