Merge lp:~james-page/charm-helpers/network-spaces-api-endpoints into lp:charm-helpers

Proposed by James Page
Status: Merged
Merged at revision: 556
Proposed branch: lp:~james-page/charm-helpers/network-spaces-api-endpoints
Merge into: lp:charm-helpers
Diff against target: 200 lines (+73/-11)
3 files modified
charmhelpers/contrib/network/ip.py (+9/-0)
charmhelpers/contrib/openstack/ip.py (+35/-7)
tests/contrib/openstack/test_ip.py (+29/-4)
To merge this branch: bzr merge lp:~james-page/charm-helpers/network-spaces-api-endpoints
Reviewer Review Type Date Requested Status
David Ames (community) Approve
Review via email: mp+290529@code.launchpad.net
To post a comment you must log in.
559. By James Page

Drop network_get until juju actually implements it

Revision history for this message
David Ames (thedac) wrote :

Looks good. Merging.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charmhelpers/contrib/network/ip.py'
2--- charmhelpers/contrib/network/ip.py 2016-01-27 12:47:55 +0000
3+++ charmhelpers/contrib/network/ip.py 2016-03-30 21:04:29 +0000
4@@ -191,6 +191,15 @@
5 get_netmask_for_address = partial(_get_for_address, key='netmask')
6
7
8+def resolve_network_cidr(ip_address):
9+ '''
10+ Resolves the full address cidr of an ip_address based on
11+ configured network interfaces
12+ '''
13+ netmask = get_netmask_for_address(ip_address)
14+ return str(netaddr.IPNetwork("%s/%s" % (ip_address, netmask)).cidr)
15+
16+
17 def format_ipv6_addr(address):
18 """If address is IPv6, wrap it in '[]' otherwise return None.
19
20
21=== modified file 'charmhelpers/contrib/openstack/ip.py'
22--- charmhelpers/contrib/openstack/ip.py 2015-06-04 22:16:21 +0000
23+++ charmhelpers/contrib/openstack/ip.py 2016-03-30 21:04:29 +0000
24@@ -14,16 +14,19 @@
25 # You should have received a copy of the GNU Lesser General Public License
26 # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
27
28+
29 from charmhelpers.core.hookenv import (
30 config,
31 unit_get,
32 service_name,
33+ network_get_primary_address,
34 )
35 from charmhelpers.contrib.network.ip import (
36 get_address_in_network,
37 is_address_in_network,
38 is_ipv6,
39 get_ipv6_addr,
40+ resolve_network_cidr,
41 )
42 from charmhelpers.contrib.hahelpers.cluster import is_clustered
43
44@@ -33,16 +36,19 @@
45
46 ADDRESS_MAP = {
47 PUBLIC: {
48+ 'binding': 'public',
49 'config': 'os-public-network',
50 'fallback': 'public-address',
51 'override': 'os-public-hostname',
52 },
53 INTERNAL: {
54+ 'binding': 'internal',
55 'config': 'os-internal-network',
56 'fallback': 'private-address',
57 'override': 'os-internal-hostname',
58 },
59 ADMIN: {
60+ 'binding': 'admin',
61 'config': 'os-admin-network',
62 'fallback': 'private-address',
63 'override': 'os-admin-hostname',
64@@ -110,7 +116,7 @@
65 correct network. If clustered with no nets defined, return primary vip.
66
67 If not clustered, return unit address ensuring address is on configured net
68- split if one is configured.
69+ split if one is configured, or a Juju 2.0 extra-binding has been used.
70
71 :param endpoint_type: Network endpoing type
72 """
73@@ -125,23 +131,45 @@
74 net_type = ADDRESS_MAP[endpoint_type]['config']
75 net_addr = config(net_type)
76 net_fallback = ADDRESS_MAP[endpoint_type]['fallback']
77+ binding = ADDRESS_MAP[endpoint_type]['binding']
78 clustered = is_clustered()
79- if clustered:
80- if not net_addr:
81- # If no net-splits defined, we expect a single vip
82- resolved_address = vips[0]
83- else:
84+
85+ if clustered and vips:
86+ if net_addr:
87 for vip in vips:
88 if is_address_in_network(net_addr, vip):
89 resolved_address = vip
90 break
91+ else:
92+ # NOTE: endeavour to check vips against network space
93+ # bindings
94+ try:
95+ bound_cidr = resolve_network_cidr(
96+ network_get_primary_address(binding)
97+ )
98+ for vip in vips:
99+ if is_address_in_network(bound_cidr, vip):
100+ resolved_address = vip
101+ break
102+ except NotImplementedError:
103+ # If no net-splits configured and no support for extra
104+ # bindings/network spaces so we expect a single vip
105+ resolved_address = vips[0]
106 else:
107 if config('prefer-ipv6'):
108 fallback_addr = get_ipv6_addr(exc_list=vips)[0]
109 else:
110 fallback_addr = unit_get(net_fallback)
111
112- resolved_address = get_address_in_network(net_addr, fallback_addr)
113+ if net_addr:
114+ resolved_address = get_address_in_network(net_addr, fallback_addr)
115+ else:
116+ # NOTE: only try to use extra bindings if legacy network
117+ # configuration is not in use
118+ try:
119+ resolved_address = network_get_primary_address(binding)
120+ except NotImplementedError:
121+ resolved_address = fallback_addr
122
123 if resolved_address is None:
124 raise ValueError("Unable to resolve a suitable IP address based on "
125
126=== modified file 'tests/contrib/openstack/test_ip.py'
127--- tests/contrib/openstack/test_ip.py 2015-06-04 22:16:21 +0000
128+++ tests/contrib/openstack/test_ip.py 2016-03-30 21:04:29 +0000
129@@ -9,6 +9,8 @@
130 'get_address_in_network',
131 'is_clustered',
132 'service_name',
133+ 'network_get_primary_address',
134+ 'resolve_network_cidr',
135 ]
136
137
138@@ -32,6 +34,7 @@
139 setattr(self, m, self._patch(m))
140 self.test_config = TestConfig()
141 self.config.side_effect = self.test_config.get
142+ self.network_get_primary_address.side_effect = NotImplementedError
143
144 def _patch(self, method):
145 _m = patch('charmhelpers.contrib.openstack.ip.' + method)
146@@ -48,7 +51,6 @@
147 calls = [call('os-public-network'),
148 call('prefer-ipv6')]
149 self.config.assert_has_calls(calls)
150- self.get_address_in_network.assert_called_with(None, 'unit1')
151
152 def test_resolve_address_default_internal(self):
153 self.is_clustered.return_value = False
154@@ -59,7 +61,6 @@
155 calls = [call('os-internal-network'),
156 call('prefer-ipv6')]
157 self.config.assert_has_calls(calls)
158- self.get_address_in_network.assert_called_with(None, 'unit1')
159
160 def test_resolve_address_public_not_clustered(self):
161 self.is_clustered.return_value = False
162@@ -111,8 +112,7 @@
163 def test_resolve_address_ipv6_fallback(self):
164 self.test_config.set('prefer-ipv6', True)
165 self.is_clustered.return_value = False
166- ip.resolve_address()
167- self.get_address_in_network.assert_called_with(None, '::1')
168+ self.assertEqual(ip.resolve_address(), '::1')
169
170 @patch.object(ip, 'resolve_address')
171 def test_canonical_url_http(self, resolve_address):
172@@ -135,3 +135,28 @@
173 def test_canonical_url_ipv6(self, resolve_address):
174 resolve_address.return_value = 'unit1'
175 self.assertTrue(ip.canonical_url(None), 'http://[unit1]')
176+
177+ def test_resolve_address_network_get(self):
178+ self.is_clustered.return_value = False
179+ self.unit_get.return_value = 'unit1'
180+ self.network_get_primary_address.side_effect = None
181+ self.network_get_primary_address.return_value = '10.5.60.1'
182+ self.assertEqual(ip.resolve_address(), '10.5.60.1')
183+ self.unit_get.assert_called_with('public-address')
184+ calls = [call('os-public-network'),
185+ call('prefer-ipv6')]
186+ self.config.assert_has_calls(calls)
187+ self.network_get_primary_address.assert_called_with('public')
188+
189+ def test_resolve_address_network_get_clustered(self):
190+ self.is_clustered.return_value = True
191+ self.test_config.set('vip', '10.5.60.20 192.168.1.20')
192+ self.network_get_primary_address.side_effect = None
193+ self.network_get_primary_address.return_value = '10.5.60.1'
194+ self.resolve_network_cidr.return_value = '10.5.60.1/24'
195+ self.assertEqual(ip.resolve_address(), '10.5.60.20')
196+ calls = [call('os-public-hostname'),
197+ call('vip'),
198+ call('os-public-network')]
199+ self.config.assert_has_calls(calls)
200+ self.network_get_primary_address.assert_called_with('public')

Subscribers

People subscribed via source and target branches