Merge lp:~julian-edwards/maas/static-range-in-ui-api into lp:~maas-committers/maas/trunk

Proposed by Julian Edwards
Status: Merged
Approved by: Julian Edwards
Approved revision: no longer in the source branch.
Merged at revision: 2413
Proposed branch: lp:~julian-edwards/maas/static-range-in-ui-api
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 237 lines (+65/-17)
7 files modified
src/maasserver/api.py (+19/-5)
src/maasserver/forms.py (+2/-0)
src/maasserver/models/nodegroup.py (+5/-2)
src/maasserver/models/nodegroupinterface.py (+10/-4)
src/maasserver/models/tests/test_nodegroup.py (+2/-0)
src/maasserver/testing/factory.py (+22/-5)
src/maasserver/tests/test_forms.py (+5/-1)
To merge this branch: bzr merge lp:~julian-edwards/maas/static-range-in-ui-api
Reviewer Review Type Date Requested Status
Raphaël Badin (community) Approve
Review via email: mp+222590@code.launchpad.net

Commit message

Ensure static_ip_range_[low|high] can be edited in the UI and API.

Description of the change

Mostly mechanical change to allow UI/API editing of the new static IP ranges in cluster interfaces. I added help text to some of the fields since it now seems prudent to differentiate the range types.

To post a comment you must log in.
Revision history for this message
Raphaël Badin (rvb) wrote :

Looks good. See my comments inline; I guess we will add validation for the new fields in a follow-up branch (check that the static range doesn't overlap with other ip ranges [static or dynamic])…?

review: Approve
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Thanks for the review!

On 10/06/14 17:50, Raphaël Badin wrote:
> Review: Approve
>
> Looks good. See my comments inline; I guess we will add validation for the new fields in a follow-up branch (check that the static range doesn't overlap with other ip ranges [static or dynamic])…?

Correct, jtv said he'd look at that.

>> class NodeGroupInterfacesHandler(OperationsHandler):
>> @@ -1837,10 +1839,16 @@
>> :type broadcast_ip: unicode (IP Address)
>> :param router_ip: Address of default gateway.
>> :type router_ip: unicode (IP Address)
>> - :param ip_range_low: Lowest IP address to assign to clients.
>> + :param ip_range_low: Lowest dynamic IP address to assign to clients.
>> :type ip_range_low: unicode (IP Address)
>> - :param ip_range_high: Highest IP address to assign to clients.
>> + :param ip_range_high: Highest dynamic IP address to assign to clients.
>> :type ip_range_high: unicode (IP Address)
>> + :param static_ip_range_low: Lowest static IP address to assign to
>> + clients.
>> + :type static_ip_range_low: unicode (IP Address)
>> + :param static_ip_range_high: Highest static IP address to assign to
>> + clients.
>> + :type static_ip_range_high: unicode (IP Address)
>
> This is probably worth testing (see src/maasserver/tests/test_api.py:TestNodeGroupInterfaceAPI and TestNodeGroupInterfacesAPI.test_new_creates_interface).

It's already tested with the existing tests, they iterate over the list
of fields supplied!

>> + if static_ip_range_low is None or static_ip_range_high is None:
>> + static_low, static_high = self.make_ip_range()
>
> AFAIK, we've always worked under the assumption that the static range (same as the dynamic range) was going to be *inside* the nodegroupinterface's network. Here you're creating a completely different network range possibility outside of the nodegroupinterface's network: although this is testing code I think we should change this to better reflect what happens in reality.

Yes. However I am thinking ahead here. If we assume it's not in the
same range and make the code work for that now, it'll also just DTRT
when we redefine the ranges later.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/api.py'
2--- src/maasserver/api.py 2014-06-04 18:21:48 +0000
3+++ src/maasserver/api.py 2014-06-10 06:23:18 +0000
4@@ -1799,7 +1799,9 @@
5
6 DISPLAYED_NODEGROUPINTERFACE_FIELDS = (
7 'ip', 'management', 'interface', 'subnet_mask',
8- 'broadcast_ip', 'ip_range_low', 'ip_range_high')
9+ 'broadcast_ip', 'ip_range_low', 'ip_range_high',
10+ 'static_ip_range_low', 'static_ip_range_high',
11+ )
12
13
14 class NodeGroupInterfacesHandler(OperationsHandler):
15@@ -1837,10 +1839,16 @@
16 :type broadcast_ip: unicode (IP Address)
17 :param router_ip: Address of default gateway.
18 :type router_ip: unicode (IP Address)
19- :param ip_range_low: Lowest IP address to assign to clients.
20+ :param ip_range_low: Lowest dynamic IP address to assign to clients.
21 :type ip_range_low: unicode (IP Address)
22- :param ip_range_high: Highest IP address to assign to clients.
23+ :param ip_range_high: Highest dynamic IP address to assign to clients.
24 :type ip_range_high: unicode (IP Address)
25+ :param static_ip_range_low: Lowest static IP address to assign to
26+ clients.
27+ :type static_ip_range_low: unicode (IP Address)
28+ :param static_ip_range_high: Highest static IP address to assign to
29+ clients.
30+ :type static_ip_range_high: unicode (IP Address)
31 """
32 nodegroup = get_object_or_404(NodeGroup, uuid=uuid)
33 if not request.user.is_superuser:
34@@ -1904,10 +1912,16 @@
35 :type broadcast_ip: unicode (IP Address)
36 :param router_ip: Address of default gateway.
37 :type router_ip: unicode (IP Address)
38- :param ip_range_low: Lowest IP address to assign to clients.
39+ :param ip_range_low: Lowest dynamic IP address to assign to clients.
40 :type ip_range_low: unicode (IP Address)
41- :param ip_range_high: Highest IP address to assign to clients.
42+ :param ip_range_high: Highest dynamic IP address to assign to clients.
43 :type ip_range_high: unicode (IP Address)
44+ :param static_ip_range_low: Lowest static IP address to assign to
45+ clients.
46+ :type static_ip_range_low: unicode (IP Address)
47+ :param static_ip_range_high: Highest static IP address to assign to
48+ clients.
49+ :type static_ip_range_high: unicode (IP Address)
50 """
51 nodegroupinterface = self.get_interface(request, uuid, interface)
52 form = NodeGroupInterfaceForm(
53
54=== modified file 'src/maasserver/forms.py'
55--- src/maasserver/forms.py 2014-06-04 16:46:28 +0000
56+++ src/maasserver/forms.py 2014-06-10 06:23:18 +0000
57@@ -1074,6 +1074,8 @@
58 'router_ip',
59 'ip_range_low',
60 'ip_range_high',
61+ 'static_ip_range_low',
62+ 'static_ip_range_high',
63 )
64
65
66
67=== modified file 'src/maasserver/models/nodegroup.py'
68--- src/maasserver/models/nodegroup.py 2014-05-22 14:15:52 +0000
69+++ src/maasserver/models/nodegroup.py 2014-06-10 06:23:18 +0000
70@@ -62,7 +62,8 @@
71 ip_range_high=None, dhcp_key='', interface='',
72 status=NODEGROUP_STATUS.DEFAULT,
73 management=NODEGROUPINTERFACE_MANAGEMENT.DEFAULT,
74- cluster_name=None, maas_url=''):
75+ cluster_name=None, maas_url='',
76+ static_ip_range_low=None, static_ip_range_high=None):
77 """Create a :class:`NodeGroup` with the given parameters.
78
79 This method will:
80@@ -91,7 +92,9 @@
81 nodegroup=nodegroup, ip=ip, subnet_mask=subnet_mask,
82 broadcast_ip=broadcast_ip, router_ip=router_ip,
83 interface=interface, ip_range_low=ip_range_low,
84- ip_range_high=ip_range_high, management=management)
85+ ip_range_high=ip_range_high, management=management,
86+ static_ip_range_low=static_ip_range_low,
87+ static_ip_range_high=static_ip_range_high)
88 nginterface.save()
89 return nodegroup
90
91
92=== modified file 'src/maasserver/models/nodegroupinterface.py'
93--- src/maasserver/models/nodegroupinterface.py 2014-05-28 04:53:27 +0000
94+++ src/maasserver/models/nodegroupinterface.py 2014-06-10 06:23:18 +0000
95@@ -75,13 +75,19 @@
96 router_ip = GenericIPAddressField(
97 editable=True, unique=False, blank=True, null=True, default=None)
98 ip_range_low = GenericIPAddressField(
99- editable=True, unique=False, blank=True, null=True, default=None)
100+ editable=True, unique=False, blank=True, null=True, default=None,
101+ help_text="Lowest IP number of the range for dynamic IPs.")
102 ip_range_high = GenericIPAddressField(
103- editable=True, unique=False, blank=True, null=True, default=None)
104+ editable=True, unique=False, blank=True, null=True, default=None,
105+ help_text="Highest IP number of the range for dynamic IPs.")
106 static_ip_range_low = GenericIPAddressField(
107- editable=True, unique=False, blank=True, null=True, default=None)
108+ editable=True, unique=False, blank=True, null=True, default=None,
109+ help_text="Lowest IP number of the range for static IPs, must be same"
110+ " network as dynamic range.")
111 static_ip_range_high = GenericIPAddressField(
112- editable=True, unique=False, blank=True, null=True, default=None)
113+ editable=True, unique=False, blank=True, null=True, default=None,
114+ help_text="Highest IP number of the range for static IPs, must be same"
115+ " network as dynamic range.")
116
117 # Foreign DHCP server address, if any, that was detected on this
118 # interface.
119
120=== modified file 'src/maasserver/models/tests/test_nodegroup.py'
121--- src/maasserver/models/tests/test_nodegroup.py 2014-05-22 14:15:52 +0000
122+++ src/maasserver/models/tests/test_nodegroup.py 2014-06-10 06:23:18 +0000
123@@ -63,6 +63,8 @@
124 'router_ip': factory.getRandomIPInNetwork(network),
125 'ip_range_low': factory.getRandomIPInNetwork(network),
126 'ip_range_high': factory.getRandomIPInNetwork(network),
127+ 'static_ip_range_low': factory.getRandomIPInNetwork(network),
128+ 'static_ip_range_high': factory.getRandomIPInNetwork(network),
129 }
130
131
132
133=== modified file 'src/maasserver/testing/factory.py'
134--- src/maasserver/testing/factory.py 2014-06-04 17:08:10 +0000
135+++ src/maasserver/testing/factory.py 2014-06-10 06:23:18 +0000
136@@ -222,13 +222,21 @@
137 def get_interface_fields(self, ip=None, router_ip=None, network=None,
138 subnet_mask=None, broadcast_ip=None,
139 ip_range_low=None, ip_range_high=None,
140- interface=None, management=None, **kwargs):
141+ interface=None, management=None,
142+ static_ip_range_low=None,
143+ static_ip_range_high=None, **kwargs):
144 if network is None:
145 network = factory.getRandomNetwork()
146 if subnet_mask is None:
147 subnet_mask = unicode(network.netmask)
148 if broadcast_ip is None:
149 broadcast_ip = unicode(network.broadcast)
150+ if static_ip_range_low is None or static_ip_range_high is None:
151+ static_low, static_high = self.make_ip_range()
152+ if static_ip_range_low is None:
153+ static_ip_range_low = unicode(static_low)
154+ if static_ip_range_high is None:
155+ static_ip_range_high = unicode(static_high)
156 if ip_range_low is None:
157 ip_range_low = unicode(IPAddress(network.first))
158 if ip_range_high is None:
159@@ -246,6 +254,8 @@
160 broadcast_ip=broadcast_ip,
161 ip_range_low=ip_range_low,
162 ip_range_high=ip_range_high,
163+ static_ip_range_low=static_ip_range_low,
164+ static_ip_range_high=static_ip_range_high,
165 router_ip=router_ip,
166 ip=ip,
167 management=management,
168@@ -255,7 +265,8 @@
169 ip=None, router_ip=None, network=None,
170 subnet_mask=None, broadcast_ip=None, ip_range_low=None,
171 ip_range_high=None, interface=None, management=None,
172- status=None, maas_url='', **kwargs):
173+ status=None, maas_url='', static_ip_range_low=None,
174+ static_ip_range_high=None, **kwargs):
175 """Create a :class:`NodeGroup`.
176
177 If network (an instance of IPNetwork) is provided, use it to populate
178@@ -277,7 +288,9 @@
179 ip=ip, router_ip=router_ip, network=network,
180 subnet_mask=subnet_mask, broadcast_ip=broadcast_ip,
181 ip_range_low=ip_range_low, ip_range_high=ip_range_high,
182- interface=interface, management=management)
183+ interface=interface, management=management,
184+ static_ip_range_low=static_ip_range_low,
185+ static_ip_range_high=static_ip_range_high)
186 interface_settings.update(kwargs)
187 return NodeGroup.objects.new(
188 name=name, uuid=uuid, cluster_name=cluster_name, status=status,
189@@ -306,12 +319,16 @@
190 router_ip=None, network=None,
191 subnet_mask=None, broadcast_ip=None,
192 ip_range_low=None, ip_range_high=None,
193- interface=None, management=None, **kwargs):
194+ interface=None, management=None,
195+ static_ip_range_low=None,
196+ static_ip_range_high=None, **kwargs):
197 interface_settings = self.get_interface_fields(
198 ip=ip, router_ip=router_ip, network=network,
199 subnet_mask=subnet_mask, broadcast_ip=broadcast_ip,
200 ip_range_low=ip_range_low, ip_range_high=ip_range_high,
201- interface=interface, management=management)
202+ interface=interface, management=management,
203+ static_ip_range_low=static_ip_range_low,
204+ static_ip_range_high=static_ip_range_high)
205 interface_settings.update(**kwargs)
206 interface = NodeGroupInterface(
207 nodegroup=nodegroup, **interface_settings)
208
209=== modified file 'src/maasserver/tests/test_forms.py'
210--- src/maasserver/tests/test_forms.py 2014-06-04 16:46:28 +0000
211+++ src/maasserver/tests/test_forms.py 2014-06-10 06:23:18 +0000
212@@ -1021,6 +1021,7 @@
213 management = factory.getRandomEnum(NODEGROUPINTERFACE_MANAGEMENT)
214 # Pick upper and lower boundaries of IP range, with upper > lower.
215 ip_range_low, ip_range_high = factory.make_ip_range(network)
216+ static_ip_range_low, static_ip_range_high = factory.make_ip_range(network)
217 return {
218 'ip': factory.getRandomIPInNetwork(network),
219 'interface': factory.make_name('interface'),
220@@ -1029,13 +1030,16 @@
221 'router_ip': factory.getRandomIPInNetwork(network),
222 'ip_range_low': unicode(ip_range_low),
223 'ip_range_high': unicode(ip_range_high),
224+ 'static_ip_range_low': unicode(static_ip_range_low),
225+ 'static_ip_range_high': unicode(static_ip_range_high),
226 'management': management,
227 }
228
229
230 nullable_fields = [
231 'subnet_mask', 'broadcast_ip', 'router_ip', 'ip_range_low',
232- 'ip_range_high']
233+ 'ip_range_high', 'static_ip_range_low', 'static_ip_range_high',
234+ ]
235
236
237 class TestNodeGroupInterfaceForm(MAASServerTestCase):