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
=== modified file 'src/maasserver/api.py'
--- src/maasserver/api.py 2014-06-04 18:21:48 +0000
+++ src/maasserver/api.py 2014-06-10 06:23:18 +0000
@@ -1799,7 +1799,9 @@
17991799
1800DISPLAYED_NODEGROUPINTERFACE_FIELDS = (1800DISPLAYED_NODEGROUPINTERFACE_FIELDS = (
1801 'ip', 'management', 'interface', 'subnet_mask',1801 'ip', 'management', 'interface', 'subnet_mask',
1802 'broadcast_ip', 'ip_range_low', 'ip_range_high')1802 'broadcast_ip', 'ip_range_low', 'ip_range_high',
1803 'static_ip_range_low', 'static_ip_range_high',
1804 )
18031805
18041806
1805class NodeGroupInterfacesHandler(OperationsHandler):1807class NodeGroupInterfacesHandler(OperationsHandler):
@@ -1837,10 +1839,16 @@
1837 :type broadcast_ip: unicode (IP Address)1839 :type broadcast_ip: unicode (IP Address)
1838 :param router_ip: Address of default gateway.1840 :param router_ip: Address of default gateway.
1839 :type router_ip: unicode (IP Address)1841 :type router_ip: unicode (IP Address)
1840 :param ip_range_low: Lowest IP address to assign to clients.1842 :param ip_range_low: Lowest dynamic IP address to assign to clients.
1841 :type ip_range_low: unicode (IP Address)1843 :type ip_range_low: unicode (IP Address)
1842 :param ip_range_high: Highest IP address to assign to clients.1844 :param ip_range_high: Highest dynamic IP address to assign to clients.
1843 :type ip_range_high: unicode (IP Address)1845 :type ip_range_high: unicode (IP Address)
1846 :param static_ip_range_low: Lowest static IP address to assign to
1847 clients.
1848 :type static_ip_range_low: unicode (IP Address)
1849 :param static_ip_range_high: Highest static IP address to assign to
1850 clients.
1851 :type static_ip_range_high: unicode (IP Address)
1844 """1852 """
1845 nodegroup = get_object_or_404(NodeGroup, uuid=uuid)1853 nodegroup = get_object_or_404(NodeGroup, uuid=uuid)
1846 if not request.user.is_superuser:1854 if not request.user.is_superuser:
@@ -1904,10 +1912,16 @@
1904 :type broadcast_ip: unicode (IP Address)1912 :type broadcast_ip: unicode (IP Address)
1905 :param router_ip: Address of default gateway.1913 :param router_ip: Address of default gateway.
1906 :type router_ip: unicode (IP Address)1914 :type router_ip: unicode (IP Address)
1907 :param ip_range_low: Lowest IP address to assign to clients.1915 :param ip_range_low: Lowest dynamic IP address to assign to clients.
1908 :type ip_range_low: unicode (IP Address)1916 :type ip_range_low: unicode (IP Address)
1909 :param ip_range_high: Highest IP address to assign to clients.1917 :param ip_range_high: Highest dynamic IP address to assign to clients.
1910 :type ip_range_high: unicode (IP Address)1918 :type ip_range_high: unicode (IP Address)
1919 :param static_ip_range_low: Lowest static IP address to assign to
1920 clients.
1921 :type static_ip_range_low: unicode (IP Address)
1922 :param static_ip_range_high: Highest static IP address to assign to
1923 clients.
1924 :type static_ip_range_high: unicode (IP Address)
1911 """1925 """
1912 nodegroupinterface = self.get_interface(request, uuid, interface)1926 nodegroupinterface = self.get_interface(request, uuid, interface)
1913 form = NodeGroupInterfaceForm(1927 form = NodeGroupInterfaceForm(
19141928
=== modified file 'src/maasserver/forms.py'
--- src/maasserver/forms.py 2014-06-04 16:46:28 +0000
+++ src/maasserver/forms.py 2014-06-10 06:23:18 +0000
@@ -1074,6 +1074,8 @@
1074 'router_ip',1074 'router_ip',
1075 'ip_range_low',1075 'ip_range_low',
1076 'ip_range_high',1076 'ip_range_high',
1077 'static_ip_range_low',
1078 'static_ip_range_high',
1077 )1079 )
10781080
10791081
10801082
=== modified file 'src/maasserver/models/nodegroup.py'
--- src/maasserver/models/nodegroup.py 2014-05-22 14:15:52 +0000
+++ src/maasserver/models/nodegroup.py 2014-06-10 06:23:18 +0000
@@ -62,7 +62,8 @@
62 ip_range_high=None, dhcp_key='', interface='',62 ip_range_high=None, dhcp_key='', interface='',
63 status=NODEGROUP_STATUS.DEFAULT,63 status=NODEGROUP_STATUS.DEFAULT,
64 management=NODEGROUPINTERFACE_MANAGEMENT.DEFAULT,64 management=NODEGROUPINTERFACE_MANAGEMENT.DEFAULT,
65 cluster_name=None, maas_url=''):65 cluster_name=None, maas_url='',
66 static_ip_range_low=None, static_ip_range_high=None):
66 """Create a :class:`NodeGroup` with the given parameters.67 """Create a :class:`NodeGroup` with the given parameters.
6768
68 This method will:69 This method will:
@@ -91,7 +92,9 @@
91 nodegroup=nodegroup, ip=ip, subnet_mask=subnet_mask,92 nodegroup=nodegroup, ip=ip, subnet_mask=subnet_mask,
92 broadcast_ip=broadcast_ip, router_ip=router_ip,93 broadcast_ip=broadcast_ip, router_ip=router_ip,
93 interface=interface, ip_range_low=ip_range_low,94 interface=interface, ip_range_low=ip_range_low,
94 ip_range_high=ip_range_high, management=management)95 ip_range_high=ip_range_high, management=management,
96 static_ip_range_low=static_ip_range_low,
97 static_ip_range_high=static_ip_range_high)
95 nginterface.save()98 nginterface.save()
96 return nodegroup99 return nodegroup
97100
98101
=== modified file 'src/maasserver/models/nodegroupinterface.py'
--- src/maasserver/models/nodegroupinterface.py 2014-05-28 04:53:27 +0000
+++ src/maasserver/models/nodegroupinterface.py 2014-06-10 06:23:18 +0000
@@ -75,13 +75,19 @@
75 router_ip = GenericIPAddressField(75 router_ip = GenericIPAddressField(
76 editable=True, unique=False, blank=True, null=True, default=None)76 editable=True, unique=False, blank=True, null=True, default=None)
77 ip_range_low = GenericIPAddressField(77 ip_range_low = GenericIPAddressField(
78 editable=True, unique=False, blank=True, null=True, default=None)78 editable=True, unique=False, blank=True, null=True, default=None,
79 help_text="Lowest IP number of the range for dynamic IPs.")
79 ip_range_high = GenericIPAddressField(80 ip_range_high = GenericIPAddressField(
80 editable=True, unique=False, blank=True, null=True, default=None)81 editable=True, unique=False, blank=True, null=True, default=None,
82 help_text="Highest IP number of the range for dynamic IPs.")
81 static_ip_range_low = GenericIPAddressField(83 static_ip_range_low = GenericIPAddressField(
82 editable=True, unique=False, blank=True, null=True, default=None)84 editable=True, unique=False, blank=True, null=True, default=None,
85 help_text="Lowest IP number of the range for static IPs, must be same"
86 " network as dynamic range.")
83 static_ip_range_high = GenericIPAddressField(87 static_ip_range_high = GenericIPAddressField(
84 editable=True, unique=False, blank=True, null=True, default=None)88 editable=True, unique=False, blank=True, null=True, default=None,
89 help_text="Highest IP number of the range for static IPs, must be same"
90 " network as dynamic range.")
8591
86 # Foreign DHCP server address, if any, that was detected on this92 # Foreign DHCP server address, if any, that was detected on this
87 # interface.93 # interface.
8894
=== modified file 'src/maasserver/models/tests/test_nodegroup.py'
--- src/maasserver/models/tests/test_nodegroup.py 2014-05-22 14:15:52 +0000
+++ src/maasserver/models/tests/test_nodegroup.py 2014-06-10 06:23:18 +0000
@@ -63,6 +63,8 @@
63 'router_ip': factory.getRandomIPInNetwork(network),63 'router_ip': factory.getRandomIPInNetwork(network),
64 'ip_range_low': factory.getRandomIPInNetwork(network),64 'ip_range_low': factory.getRandomIPInNetwork(network),
65 'ip_range_high': factory.getRandomIPInNetwork(network),65 'ip_range_high': factory.getRandomIPInNetwork(network),
66 'static_ip_range_low': factory.getRandomIPInNetwork(network),
67 'static_ip_range_high': factory.getRandomIPInNetwork(network),
66 }68 }
6769
6870
6971
=== modified file 'src/maasserver/testing/factory.py'
--- src/maasserver/testing/factory.py 2014-06-04 17:08:10 +0000
+++ src/maasserver/testing/factory.py 2014-06-10 06:23:18 +0000
@@ -222,13 +222,21 @@
222 def get_interface_fields(self, ip=None, router_ip=None, network=None,222 def get_interface_fields(self, ip=None, router_ip=None, network=None,
223 subnet_mask=None, broadcast_ip=None,223 subnet_mask=None, broadcast_ip=None,
224 ip_range_low=None, ip_range_high=None,224 ip_range_low=None, ip_range_high=None,
225 interface=None, management=None, **kwargs):225 interface=None, management=None,
226 static_ip_range_low=None,
227 static_ip_range_high=None, **kwargs):
226 if network is None:228 if network is None:
227 network = factory.getRandomNetwork()229 network = factory.getRandomNetwork()
228 if subnet_mask is None:230 if subnet_mask is None:
229 subnet_mask = unicode(network.netmask)231 subnet_mask = unicode(network.netmask)
230 if broadcast_ip is None:232 if broadcast_ip is None:
231 broadcast_ip = unicode(network.broadcast)233 broadcast_ip = unicode(network.broadcast)
234 if static_ip_range_low is None or static_ip_range_high is None:
235 static_low, static_high = self.make_ip_range()
236 if static_ip_range_low is None:
237 static_ip_range_low = unicode(static_low)
238 if static_ip_range_high is None:
239 static_ip_range_high = unicode(static_high)
232 if ip_range_low is None:240 if ip_range_low is None:
233 ip_range_low = unicode(IPAddress(network.first))241 ip_range_low = unicode(IPAddress(network.first))
234 if ip_range_high is None:242 if ip_range_high is None:
@@ -246,6 +254,8 @@
246 broadcast_ip=broadcast_ip,254 broadcast_ip=broadcast_ip,
247 ip_range_low=ip_range_low,255 ip_range_low=ip_range_low,
248 ip_range_high=ip_range_high,256 ip_range_high=ip_range_high,
257 static_ip_range_low=static_ip_range_low,
258 static_ip_range_high=static_ip_range_high,
249 router_ip=router_ip,259 router_ip=router_ip,
250 ip=ip,260 ip=ip,
251 management=management,261 management=management,
@@ -255,7 +265,8 @@
255 ip=None, router_ip=None, network=None,265 ip=None, router_ip=None, network=None,
256 subnet_mask=None, broadcast_ip=None, ip_range_low=None,266 subnet_mask=None, broadcast_ip=None, ip_range_low=None,
257 ip_range_high=None, interface=None, management=None,267 ip_range_high=None, interface=None, management=None,
258 status=None, maas_url='', **kwargs):268 status=None, maas_url='', static_ip_range_low=None,
269 static_ip_range_high=None, **kwargs):
259 """Create a :class:`NodeGroup`.270 """Create a :class:`NodeGroup`.
260271
261 If network (an instance of IPNetwork) is provided, use it to populate272 If network (an instance of IPNetwork) is provided, use it to populate
@@ -277,7 +288,9 @@
277 ip=ip, router_ip=router_ip, network=network,288 ip=ip, router_ip=router_ip, network=network,
278 subnet_mask=subnet_mask, broadcast_ip=broadcast_ip,289 subnet_mask=subnet_mask, broadcast_ip=broadcast_ip,
279 ip_range_low=ip_range_low, ip_range_high=ip_range_high,290 ip_range_low=ip_range_low, ip_range_high=ip_range_high,
280 interface=interface, management=management)291 interface=interface, management=management,
292 static_ip_range_low=static_ip_range_low,
293 static_ip_range_high=static_ip_range_high)
281 interface_settings.update(kwargs)294 interface_settings.update(kwargs)
282 return NodeGroup.objects.new(295 return NodeGroup.objects.new(
283 name=name, uuid=uuid, cluster_name=cluster_name, status=status,296 name=name, uuid=uuid, cluster_name=cluster_name, status=status,
@@ -306,12 +319,16 @@
306 router_ip=None, network=None,319 router_ip=None, network=None,
307 subnet_mask=None, broadcast_ip=None,320 subnet_mask=None, broadcast_ip=None,
308 ip_range_low=None, ip_range_high=None,321 ip_range_low=None, ip_range_high=None,
309 interface=None, management=None, **kwargs):322 interface=None, management=None,
323 static_ip_range_low=None,
324 static_ip_range_high=None, **kwargs):
310 interface_settings = self.get_interface_fields(325 interface_settings = self.get_interface_fields(
311 ip=ip, router_ip=router_ip, network=network,326 ip=ip, router_ip=router_ip, network=network,
312 subnet_mask=subnet_mask, broadcast_ip=broadcast_ip,327 subnet_mask=subnet_mask, broadcast_ip=broadcast_ip,
313 ip_range_low=ip_range_low, ip_range_high=ip_range_high,328 ip_range_low=ip_range_low, ip_range_high=ip_range_high,
314 interface=interface, management=management)329 interface=interface, management=management,
330 static_ip_range_low=static_ip_range_low,
331 static_ip_range_high=static_ip_range_high)
315 interface_settings.update(**kwargs)332 interface_settings.update(**kwargs)
316 interface = NodeGroupInterface(333 interface = NodeGroupInterface(
317 nodegroup=nodegroup, **interface_settings)334 nodegroup=nodegroup, **interface_settings)
318335
=== modified file 'src/maasserver/tests/test_forms.py'
--- src/maasserver/tests/test_forms.py 2014-06-04 16:46:28 +0000
+++ src/maasserver/tests/test_forms.py 2014-06-10 06:23:18 +0000
@@ -1021,6 +1021,7 @@
1021 management = factory.getRandomEnum(NODEGROUPINTERFACE_MANAGEMENT)1021 management = factory.getRandomEnum(NODEGROUPINTERFACE_MANAGEMENT)
1022 # Pick upper and lower boundaries of IP range, with upper > lower.1022 # Pick upper and lower boundaries of IP range, with upper > lower.
1023 ip_range_low, ip_range_high = factory.make_ip_range(network)1023 ip_range_low, ip_range_high = factory.make_ip_range(network)
1024 static_ip_range_low, static_ip_range_high = factory.make_ip_range(network)
1024 return {1025 return {
1025 'ip': factory.getRandomIPInNetwork(network),1026 'ip': factory.getRandomIPInNetwork(network),
1026 'interface': factory.make_name('interface'),1027 'interface': factory.make_name('interface'),
@@ -1029,13 +1030,16 @@
1029 'router_ip': factory.getRandomIPInNetwork(network),1030 'router_ip': factory.getRandomIPInNetwork(network),
1030 'ip_range_low': unicode(ip_range_low),1031 'ip_range_low': unicode(ip_range_low),
1031 'ip_range_high': unicode(ip_range_high),1032 'ip_range_high': unicode(ip_range_high),
1033 'static_ip_range_low': unicode(static_ip_range_low),
1034 'static_ip_range_high': unicode(static_ip_range_high),
1032 'management': management,1035 'management': management,
1033 }1036 }
10341037
10351038
1036nullable_fields = [1039nullable_fields = [
1037 'subnet_mask', 'broadcast_ip', 'router_ip', 'ip_range_low',1040 'subnet_mask', 'broadcast_ip', 'router_ip', 'ip_range_low',
1038 'ip_range_high']1041 'ip_range_high', 'static_ip_range_low', 'static_ip_range_high',
1042 ]
10391043
10401044
1041class TestNodeGroupInterfaceForm(MAASServerTestCase):1045class TestNodeGroupInterfaceForm(MAASServerTestCase):