Merge lp:~rvb/maas/big-networks into lp:maas/trunk

Proposed by Raphaël Badin on 2012-10-05
Status: Merged
Approved by: Raphaël Badin on 2012-10-08
Approved revision: 1191
Merged at revision: 1205
Proposed branch: lp:~rvb/maas/big-networks
Merge into: lp:maas/trunk
Diff against target: 152 lines (+60/-6)
4 files modified
src/maasserver/models/nodegroupinterface.py (+26/-4)
src/maasserver/tests/test_fields.py (+3/-0)
src/maasserver/tests/test_forms.py (+2/-2)
src/maasserver/tests/test_nodegroupinterface.py (+29/-0)
To merge this branch: bzr merge lp:~rvb/maas/big-networks
Reviewer Review Type Date Requested Status
Gavin Panella (community) 2012-10-05 Approve on 2012-10-05
Review via email: mp+128269@code.launchpad.net

Commit Message

Reject networks >= /8 networks.

Description of the Change

Reject networks >= /8 networks. This ends up pre-populating a huge zone file that neither celeryd nor bind handle properly.

To post a comment you must log in.
Gavin Panella (allenap) wrote :

Looks good.

[1]

+# For instance, if MINIMUM_PREFIX_LEN is 9, a /8 will be rejected.
+MINIMUM_PREFIX_LEN = 9

This still allows for a network of ~8.3 million addresses. While we're generating the full zone maps, it seems ridiculous to support anything remotely close to that. If we want to support a flat network for 100k nodes then a /15 is all we need, but even that is slightly unhinged right now. A /16 is far more than enough for the size of cluster we're expecting (*dreaming*) of supporting, and if we want more than that we need to get rid of the pre-generation stuff, or rethink it (e.g. serve it up dynamically).

review: Approve
Gavin Panella (allenap) wrote :

Fwiw, I'm not against letting people specify a /8 if they want to. It's just that MAAS will grind to a halt right now, and appear desperately broken, and I think it's better to politely say "non" earlier in the process than to let it break like that.

lp:~rvb/maas/big-networks updated on 2012-10-07
1187. By Raphaël Badin on 2012-10-07

Only look for big networks in managed interfaces.

1188. By Raphaël Badin on 2012-10-07

Fix tests.

1189. By Raphaël Badin on 2012-10-07

Merge trunk.

1190. By Raphaël Badin on 2012-10-07

Fix test.

Raphaël Badin (rvb) wrote :

> This still allows for a network of ~8.3 million addresses. While we're
> generating the full zone maps, it seems ridiculous to support anything
> remotely close to that. If we want to support a flat network for 100k nodes
> then a /15 is all we need, but even that is slightly unhinged right now. A /16
> is far more than enough for the size of cluster we're expecting (*dreaming*)
> of supporting, and if we want more than that we need to get rid of the pre-
> generation stuff, or rethink it (e.g. serve it up dynamically).

You're definitely right… but I think it would be good to allow for a 100k network so I changed the limit to "/15". We can adjust that after doing so testing if we need to.

Julian Edwards (julian-edwards) wrote :

On Sunday 07 October 2012 17:34:21 you wrote:
> > This still allows for a network of ~8.3 million addresses. While we're
> > generating the full zone maps, it seems ridiculous to support anything
> > remotely close to that. If we want to support a flat network for 100k
> > nodes
> > then a /15 is all we need, but even that is slightly unhinged right now. A
> > /16 is far more than enough for the size of cluster we're expecting
> > (*dreaming*) of supporting, and if we want more than that we need to get
> > rid of the pre- generation stuff, or rethink it (e.g. serve it up
> > dynamically).
>
> You're definitely right… but I think it would be good to allow for a 100k
> network so I changed the limit to "/15". We can adjust that after doing so
> testing if we need to.

Yeah we had agreed /16 in the pre-imp I had with you :) /15 is ok too.

Julian Edwards (julian-edwards) wrote :

I think MINIMUM_PREFIX_LEN isn't an informative constant name as it could be.
Perhaps MINIMUM_NETMASK_BITS ?

lp:~rvb/maas/big-networks updated on 2012-10-08
1191. By Raphaël Badin on 2012-10-08

Rename MINIMUM_PREFIX_LEN into MINIMUM_NETMASK_BITS. Set minimum to /16.

Raphaël Badin (rvb) wrote :

>
> Yeah we had agreed /16 in the pre-imp I had with you :) /15 is ok too.

Really? I confess I don't really remember :). /16 it is then.

Raphaël Badin (rvb) wrote :

> I think MINIMUM_PREFIX_LEN isn't an informative constant name as it could be.
> Perhaps MINIMUM_NETMASK_BITS ?

Ok, done.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/models/nodegroupinterface.py'
2--- src/maasserver/models/nodegroupinterface.py 2012-10-04 11:43:37 +0000
3+++ src/maasserver/models/nodegroupinterface.py 2012-10-08 07:37:24 +0000
4@@ -38,6 +38,13 @@
5 )
6 from netaddr.core import AddrFormatError
7
8+# The minimum number of leading bits of the routing prefix for a
9+# network. A smaller number will be rejected as it creates a huge
10+# address space that is currently not well supported by the DNS
11+# machinery.
12+# For instance, if MINIMUM_NETMASK_BITS is 9, a /8 will be rejected.
13+MINIMUM_NETMASK_BITS = 16
14+
15
16 class NodeGroupInterface(CleanSave, TimestampedModel):
17
18@@ -93,8 +100,8 @@
19 return "<NodeGroupInterface %s,%s>" % (
20 self.nodegroup.uuid, self.interface)
21
22- def clean_network(self):
23- """Validate that the network is valid.
24+ def clean_network_valid(self):
25+ """Validate the network.
26
27 This validates that the network defined by broadcast_ip and
28 subnet_mask is valid.
29@@ -111,7 +118,21 @@
30 'subnet_mask': [e.message],
31 })
32
33- raise ValidationError(e.message)
34+ def clean_network_not_too_big(self):
35+ # If management is not 'UNMANAGED', refuse huge networks.
36+ if self.management != NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED:
37+ network = self.network
38+ if network is not None:
39+ if network.prefixlen < MINIMUM_NETMASK_BITS:
40+ message = (
41+ "Cannot create an address space bigger than "
42+ "a /%d network. This network is a /%d network." %
43+ (MINIMUM_NETMASK_BITS, network.prefixlen))
44+ raise ValidationError(
45+ {
46+ 'broadcast_ip': [message],
47+ 'subnet_mask': [message],
48+ })
49
50 def clean_management(self):
51 # XXX: rvb 2012-09-18 bug=1052339: Only one "managed" interface
52@@ -181,7 +202,8 @@
53
54 def clean_fields(self, *args, **kwargs):
55 super(NodeGroupInterface, self).clean_fields(*args, **kwargs)
56- self.clean_network()
57+ self.clean_network_valid()
58+ self.clean_network_not_too_big()
59 self.clean_ips_in_network()
60 self.clean_management()
61 self.clean_network_config_if_managed()
62
63=== modified file 'src/maasserver/tests/test_fields.py'
64--- src/maasserver/tests/test_fields.py 2012-10-03 11:19:13 +0000
65+++ src/maasserver/tests/test_fields.py 2012-10-08 07:37:24 +0000
66@@ -21,6 +21,7 @@
67 from maasserver.models import (
68 MACAddress,
69 NodeGroup,
70+ nodegroupinterface,
71 NodeGroupInterface,
72 )
73 from maasserver.testing.factory import factory
74@@ -96,6 +97,7 @@
75 factory.getRandomIPAddress())
76
77 def test_find_nodegroup_reports_if_multiple_matches(self):
78+ self.patch(nodegroupinterface, "MINIMUM_NETMASK_BITS", 1)
79 factory.make_node_group(network=IPNetwork("10/8"))
80 factory.make_node_group(network=IPNetwork("10.1.1/24"))
81 self.assertRaises(
82@@ -103,6 +105,7 @@
83 NodeGroupFormField().clean, '10.1.1.2')
84
85 def test_find_nodegroup_handles_multiple_matches_on_same_nodegroup(self):
86+ self.patch(nodegroupinterface, "MINIMUM_NETMASK_BITS", 1)
87 nodegroup = factory.make_node_group(network=IPNetwork("10/8"))
88 NodeGroupInterface.objects.create(
89 nodegroup=nodegroup, ip='10.0.0.2', subnet_mask='255.0.0.0',
90
91=== modified file 'src/maasserver/tests/test_forms.py'
92--- src/maasserver/tests/test_forms.py 2012-10-03 11:19:13 +0000
93+++ src/maasserver/tests/test_forms.py 2012-10-08 07:37:24 +0000
94@@ -211,9 +211,9 @@
95 # nodes. You can't change it later.
96 original_nodegroup = factory.make_node_group()
97 node = factory.make_node(nodegroup=original_nodegroup)
98- factory.make_node_group(network=IPNetwork("10.0.0.0/8"))
99+ factory.make_node_group(network=IPNetwork("192.168.1.0/24"))
100 form = NodeWithMACAddressesForm(
101- self.make_params(nodegroup='10.0.0.1'), instance=node)
102+ self.make_params(nodegroup='192.168.1.0'), instance=node)
103 form.save()
104 self.assertEqual(original_nodegroup, reload_object(node).nodegroup)
105
106
107=== modified file 'src/maasserver/tests/test_nodegroupinterface.py'
108--- src/maasserver/tests/test_nodegroupinterface.py 2012-10-04 11:43:37 +0000
109+++ src/maasserver/tests/test_nodegroupinterface.py 2012-10-08 07:37:24 +0000
110@@ -18,6 +18,8 @@
111 NODEGROUPINTERFACE_MANAGEMENT,
112 NODEGROUPINTERFACE_MANAGEMENT_CHOICES_DICT,
113 )
114+from maasserver.models import NodeGroup
115+from maasserver.models.nodegroupinterface import MINIMUM_NETMASK_BITS
116 from maasserver.testing.factory import factory
117 from maasserver.testing.testcase import TestCase
118 from netaddr import IPNetwork
119@@ -97,6 +99,33 @@
120 },
121 exception.message_dict)
122
123+ def test_clean_network_rejects_huge_network(self):
124+ big_network = IPNetwork('1.2.3.4/%d' % (MINIMUM_NETMASK_BITS - 1))
125+ exception = self.assertRaises(
126+ ValidationError, factory.make_node_group, network=big_network)
127+ message = (
128+ "Cannot create an address space bigger than a /%d network. "
129+ "This network is a /%d network." %
130+ (MINIMUM_NETMASK_BITS, MINIMUM_NETMASK_BITS - 1))
131+ self.assertEqual(
132+ {
133+ 'subnet_mask': [message],
134+ 'broadcast_ip': [message],
135+ },
136+ exception.message_dict)
137+
138+ def test_clean_network_accepts_network_if_not_too_big(self):
139+ network = IPNetwork('1.2.3.4/%d' % MINIMUM_NETMASK_BITS)
140+ self.assertIsInstance(
141+ factory.make_node_group(network=network), NodeGroup)
142+
143+ def test_clean_network_accepts_big_network_if_unmanaged(self):
144+ network = IPNetwork('1.2.3.4/%d' % (MINIMUM_NETMASK_BITS - 1))
145+ nodegroup = factory.make_node_group(
146+ network=network,
147+ management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
148+ self.assertIsInstance(nodegroup, NodeGroup)
149+
150 def test_clean_network_config_if_managed(self):
151 network = IPNetwork('192.168.0.3/24')
152 checked_fields = [