Merge ~cgrabowski/maas:backport_safe_getaddrinfo_fix_3.4 into maas:3.4

Proposed by Christian Grabowski
Status: Merged
Approved by: Christian Grabowski
Approved revision: 24be18a6df5521a8a29b52e1d0ce256be1c5858c
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~cgrabowski/maas:backport_safe_getaddrinfo_fix_3.4
Merge into: maas:3.4
Diff against target: 106 lines (+41/-9)
2 files modified
src/provisioningserver/utils/network.py (+15/-5)
src/provisioningserver/utils/tests/test_network.py (+26/-4)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Christian Grabowski Approve
Review via email: mp+461743@code.launchpad.net

Commit message

add test that hits _v6_lookup in safe_getaddrinfo and ensures
non-deferred answer
(cherry picked from commit 5c0dbab94c842269a6f06ded9f2378ff934d6bbf)

To post a comment you must log in.
Revision history for this message
Christian Grabowski (cgrabowski) wrote :

self-approving backport

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b backport_safe_getaddrinfo_fix_3.4 lp:~cgrabowski/maas/+git/maas into -b 3.4 lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 24be18a6df5521a8a29b52e1d0ce256be1c5858c

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/provisioningserver/utils/network.py b/src/provisioningserver/utils/network.py
2index d6fb989..1ea4ec0 100644
3--- a/src/provisioningserver/utils/network.py
4+++ b/src/provisioningserver/utils/network.py
5@@ -26,7 +26,7 @@ from zlib import crc32
6 from netaddr import EUI, IPAddress, IPNetwork, IPRange
7 from netaddr.core import AddrFormatError, NotRegisteredError
8 import netifaces
9-from twisted.internet.defer import inlineCallbacks
10+from twisted.internet.defer import Deferred, inlineCallbacks
11 from twisted.internet.interfaces import IResolver
12 from twisted.names.client import getResolver
13 from twisted.names.error import (
14@@ -41,7 +41,7 @@ from provisioningserver.utils.ipaddr import get_ip_addr
15 from provisioningserver.utils.iproute import get_ip_route
16 from provisioningserver.utils.ps import running_in_container
17 from provisioningserver.utils.shell import call_and_check, get_env_with_locale
18-from provisioningserver.utils.twisted import synchronous
19+from provisioningserver.utils.twisted import asynchronous, synchronous
20
21 # Address families in /etc/network/interfaces that MAAS chooses to parse. All
22 # other families are ignored.
23@@ -751,7 +751,9 @@ def get_all_interface_addresses() -> Iterable[str]:
24 yield from get_all_addresses_for_interface(interface)
25
26
27-def safe_getaddrinfo(hostname, port, family=AF_INET, proto=IPPROTO_TCP):
28+def safe_getaddrinfo(
29+ hostname, port, family=AF_INET, proto=IPPROTO_TCP, timeout=10
30+):
31 if family in (
32 AF_INET,
33 0,
34@@ -764,19 +766,27 @@ def safe_getaddrinfo(hostname, port, family=AF_INET, proto=IPPROTO_TCP):
35 socket.SOCK_STREAM if proto == IPPROTO_TCP else socket.SOCK_DGRAM
36 )
37
38+ @asynchronous(timeout=timeout)
39 @inlineCallbacks
40 def _v6_lookup():
41 resolver = getResolver()
42 answers = yield resolver.lookupIPV6Address(hostname)
43 return [
44- (AF_INET6, sock_type, proto, "", (ans.address, port, 0, 0))
45+ (AF_INET6, sock_type, proto, "", (ans._address, port, 0, 0))
46 for ans in answers[0]
47 ]
48
49 try:
50 addr = IPAddress(hostname)
51 except AddrFormatError:
52- return _v6_lookup()
53+ result = _v6_lookup()
54+ # this should only happen in tests where twisted is in the thread,
55+ # but this is called from a synchronous context
56+ if isinstance(result, Deferred) and result.result:
57+ return result.result
58+ # synchronous contexts should use sync_safe_getaddrinfo to ensure
59+ # this is not a Deferred
60+ return result
61 else:
62 return [(AF_INET6, sock_type, proto, "", (str(addr), port, 0, 0))]
63
64diff --git a/src/provisioningserver/utils/tests/test_network.py b/src/provisioningserver/utils/tests/test_network.py
65index 5101208..1ed3e6e 100644
66--- a/src/provisioningserver/utils/tests/test_network.py
67+++ b/src/provisioningserver/utils/tests/test_network.py
68@@ -2566,12 +2566,34 @@ class TestSafeGetaddrinfo(MAASTestCase):
69 (AF_INET6, socket.SOCK_STREAM, IPPROTO_TCP, "", ("::", 53, 0, 0))
70 ]
71 mock_resolver = Mock()
72- mock_resolver.lookupIPV6Address = lambda _: (
73- [Record_AAAA(address="::")],
74- [],
75- [],
76+ mock_resolver.lookupIPV6Address = lambda _: succeed(
77+ (
78+ [Record_AAAA(address="::")],
79+ [],
80+ [],
81+ )
82 )
83 get_resolver = self.patch(network_module, "getResolver")
84 get_resolver.return_value = mock_resolver
85 result = safe_getaddrinfo("::", 53, family=AF_INET6, proto=IPPROTO_TCP)
86 self.assertCountEqual(expected, result)
87+
88+ def test_safe_get_addrinfo_uses_resolver_for_v6_with_hostname(self):
89+ expected = [
90+ (AF_INET6, socket.SOCK_STREAM, IPPROTO_TCP, "", ("::1", 53, 0, 0))
91+ ]
92+ mock_resolver = Mock()
93+ mock_resolver.lookupIPV6Address = lambda _: succeed(
94+ (
95+ [Record_AAAA(address="::1")],
96+ [],
97+ [],
98+ )
99+ )
100+ get_resolver = self.patch(network_module, "getResolver")
101+ get_resolver.return_value = mock_resolver
102+ # tests that _v6_lookup works in a synchronous context
103+ result = safe_getaddrinfo(
104+ "example.com", 53, family=AF_INET6, proto=IPPROTO_TCP
105+ )
106+ self.assertCountEqual(expected, result)

Subscribers

People subscribed via source and target branches