Merge lp:~blake-rouse/maas/fix-1519527-1.9 into lp:maas/1.9

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 4521
Proposed branch: lp:~blake-rouse/maas/fix-1519527-1.9
Merge into: lp:maas/1.9
Diff against target: 112 lines (+84/-0)
2 files modified
src/maasserver/models/interface.py (+5/-0)
src/maasserver/models/tests/test_interface.py (+79/-0)
To merge this branch: bzr merge lp:~blake-rouse/maas/fix-1519527-1.9
Reviewer Review Type Date Requested Status
Mike Pontillo (community) Approve
Review via email: mp+279632@code.launchpad.net

This proposal supersedes a proposal from 2015-12-04.

Commit message

Prevent claim_static_ips from allocated more than one IP address per discovered subnet.

To post a comment you must log in.
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Nice find. Looks good!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/models/interface.py'
2--- src/maasserver/models/interface.py 2015-12-03 18:59:49 +0000
3+++ src/maasserver/models/interface.py 2015-12-04 16:56:51 +0000
4@@ -1317,6 +1317,11 @@
5 if ngi is not None and ngi.subnet is not None:
6 discovered_subnets.append(ngi.subnet)
7
8+ # This must be a set because it is highly possible that the parent
9+ # has multiple subnets on the same interface or same subnet on multiple
10+ # interfaces. We only want to allocate one ip address per subnet.
11+ discovered_subnets = set(discovered_subnets)
12+
13 if len(discovered_subnets) == 0:
14 node = self.node
15 if parent is not None:
16
17=== modified file 'src/maasserver/models/tests/test_interface.py'
18--- src/maasserver/models/tests/test_interface.py 2015-12-03 19:51:52 +0000
19+++ src/maasserver/models/tests/test_interface.py 2015-12-04 16:56:51 +0000
20@@ -2575,6 +2575,42 @@
21 call(INTERFACE_LINK_TYPE.STATIC, subnet_v4),
22 call(INTERFACE_LINK_TYPE.STATIC, subnet_v6)))
23
24+ def test__without_address_calls_link_subnet_once_per_subnet(self):
25+ nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ENABLED)
26+ interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
27+ network_v4 = factory.make_ipv4_network()
28+ subnet_v4 = factory.make_Subnet(cidr=unicode(network_v4.cidr))
29+ factory.make_NodeGroupInterface(
30+ nodegroup, management=NODEGROUPINTERFACE_MANAGEMENT.DHCP,
31+ subnet=subnet_v4)
32+ factory.make_StaticIPAddress(
33+ alloc_type=IPADDRESS_TYPE.DISCOVERED, ip="",
34+ subnet=subnet_v4, interface=interface)
35+ # Make it have the same subnet twice.
36+ factory.make_StaticIPAddress(
37+ alloc_type=IPADDRESS_TYPE.DISCOVERED, ip="",
38+ subnet=subnet_v4, interface=interface)
39+ network_v6 = factory.make_ipv6_network()
40+ subnet_v6 = factory.make_Subnet(cidr=unicode(network_v6.cidr))
41+ factory.make_NodeGroupInterface(
42+ nodegroup, management=NODEGROUPINTERFACE_MANAGEMENT.DHCP,
43+ subnet=subnet_v6)
44+ factory.make_StaticIPAddress(
45+ alloc_type=IPADDRESS_TYPE.DISCOVERED, ip="",
46+ subnet=subnet_v6, interface=interface)
47+ # Make it have the same subnet twice.
48+ factory.make_StaticIPAddress(
49+ alloc_type=IPADDRESS_TYPE.DISCOVERED, ip="",
50+ subnet=subnet_v6, interface=interface)
51+
52+ mock_link_subnet = self.patch_autospec(interface, "link_subnet")
53+ interface.claim_static_ips()
54+ self.assertThat(
55+ mock_link_subnet,
56+ MockCallsMatch(
57+ call(INTERFACE_LINK_TYPE.STATIC, subnet_v4),
58+ call(INTERFACE_LINK_TYPE.STATIC, subnet_v6)))
59+
60 def test__without_address_does_nothing_if_none_managed(self):
61 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
62 network_v4 = factory.make_ipv4_network()
63@@ -2659,6 +2695,49 @@
64 call(INTERFACE_LINK_TYPE.STATIC, subnet_v4),
65 call(INTERFACE_LINK_TYPE.STATIC, subnet_v6)))
66
67+ def test__device_no_address_calls_link_subnet_once_per_subnet(self):
68+ nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ENABLED)
69+ parent = factory.make_Node()
70+ parent_nic0 = factory.make_Interface(
71+ INTERFACE_TYPE.PHYSICAL, node=parent)
72+ parent_nic1 = factory.make_Interface(
73+ INTERFACE_TYPE.PHYSICAL, node=parent)
74+ network_v4 = factory.make_ipv4_network()
75+ subnet_v4 = factory.make_Subnet(cidr=unicode(network_v4.cidr))
76+ factory.make_NodeGroupInterface(
77+ nodegroup, management=NODEGROUPINTERFACE_MANAGEMENT.DHCP,
78+ subnet=subnet_v4)
79+ factory.make_StaticIPAddress(
80+ alloc_type=IPADDRESS_TYPE.DISCOVERED, ip="",
81+ subnet=subnet_v4, interface=parent_nic0)
82+ # Make second interface on the parent have the same subnet.
83+ factory.make_StaticIPAddress(
84+ alloc_type=IPADDRESS_TYPE.DISCOVERED, ip="",
85+ subnet=subnet_v4, interface=parent_nic1)
86+ network_v6 = factory.make_ipv6_network()
87+ subnet_v6 = factory.make_Subnet(cidr=unicode(network_v6.cidr))
88+ factory.make_NodeGroupInterface(
89+ nodegroup, management=NODEGROUPINTERFACE_MANAGEMENT.DHCP,
90+ subnet=subnet_v6)
91+ factory.make_StaticIPAddress(
92+ alloc_type=IPADDRESS_TYPE.DISCOVERED, ip="",
93+ subnet=subnet_v6, interface=parent_nic0)
94+ # Make second interface on the parent have the same subnet.
95+ factory.make_StaticIPAddress(
96+ alloc_type=IPADDRESS_TYPE.DISCOVERED, ip="",
97+ subnet=subnet_v6, interface=parent_nic1)
98+ device = factory.make_Device(parent=parent)
99+ device_interface = factory.make_Interface(
100+ INTERFACE_TYPE.PHYSICAL, node=device)
101+
102+ mock_link_subnet = self.patch_autospec(device_interface, "link_subnet")
103+ device_interface.claim_static_ips()
104+ self.assertThat(
105+ mock_link_subnet,
106+ MockCallsMatch(
107+ call(INTERFACE_LINK_TYPE.STATIC, subnet_v4),
108+ call(INTERFACE_LINK_TYPE.STATIC, subnet_v6)))
109+
110 def test__device_with_address_calls_link_subnet_with_ip_address(self):
111 parent = factory.make_Node()
112 interface = factory.make_Interface(

Subscribers

People subscribed via source and target branches