Merge lp:~jtv/maas/hide-disable_ipv4-if-no-ipv6 into lp:~maas-committers/maas/trunk

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Jeroen T. Vermeulen
Approved revision: no longer in the source branch.
Merged at revision: 3191
Proposed branch: lp:~jtv/maas/hide-disable_ipv4-if-no-ipv6
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 138 lines (+85/-3)
2 files modified
src/maasserver/forms.py (+29/-3)
src/maasserver/tests/test_forms_node.py (+56/-0)
To merge this branch: bzr merge lp:~jtv/maas/hide-disable_ipv4-if-no-ipv6
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+236993@code.launchpad.net

Commit message

Hide a node's “Disable IPv4 on deployment” checkbox if its cluster is not configured to manage an IPv6 network.

Description of the change

When the option is hidden, it's present on the form (so that the API will continue to support it) but with a HiddenInput widget instead of the default CheckboxInput widget for boolean settings. That's what the test checks for. The label also matters (it shows up even if the widget is "hidden") but it's nowhere near as important as getting the widget right.

The check doesn't go into too much detail: it doesn't care whether the node is actually connected to any of the managed IPv6 networks, only that they're there. The Node edit form is meant to configure what we know about the node, so in principle, we might have to hide or reveal that checkbox actively as the user edits the form. That's probably more trouble than it's worth.

Also, in reality, the option isn't shown on the Add Node form. I left the option to change that open, and provided sensible (I hope) behaviour.

Jeroen

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

Looks good.

What happens when there's a managed IPv6 network, the user disabled IPv4 on a node, then the IPv6 network is removed? Will MAAS still try to disable IPv4 on the node? If so, does this change remove the means to fix that?

review: Needs Information
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

In that case, the disable_ipv4 setting will remain on the node, but the node will ignore it.

Revision history for this message
Gavin Panella (allenap) wrote :

That's grand.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (19.6 KiB)

The attempt to merge lp:~jtv/maas/hide-disable_ipv4-if-no-ipv6 into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Get:1 http://security.ubuntu.com trusty-security Release.gpg [933 B]
Get:2 http://security.ubuntu.com trusty-security Release [59.7 kB]
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Get:3 http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg [933 B]
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:4 http://nova.clouds.archive.ubuntu.com trusty-updates Release [59.7 kB]
Get:5 http://security.ubuntu.com trusty-security/main Sources [46.3 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
Get:6 http://security.ubuntu.com trusty-security/universe Sources [10.8 kB]
Get:7 http://security.ubuntu.com trusty-security/main amd64 Packages [146 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en
Get:8 http://security.ubuntu.com trusty-security/universe amd64 Packages [49.1 kB]
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
Get:9 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [125 kB]
Get:10 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources [86.2 kB]
Get:11 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [337 kB]
Get:12 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [209 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en
Fetched 1,130 kB in 0s (1,802 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
     --no-install-recommends install apache2 authbind bind9 bind9utils build-essential bzr-builddeb curl daemontools debhelper dh-apport distro-info dnsutils firefox freeipmi-tools ipython isc-dhcp-common libjs-raphael libjs-yui3-full libjs-yui3-min libpq-dev make pep8 postgresql pyflakes python-amqplib python-bzrlib python-celery python-convoy python-crochet python-cssselect python-curtin python-dev python-distro-info python-django python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-extras python-fixtures python-flake8 python-formencode python-hivex python-httplib2 python-jinja2 python-jsonschema python-lockfile python-lxml python-mimeparse python-mock python-netaddr python-netifaces python-nose python-oauth python-oops python-oops-amqp python-oops-datedir-repo python-oops-twisted python-oops-wsgi python-...

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Argh. Stuck behind that JS lint that snuck in while I was fixing the other JS lint...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/maasserver/forms.py'
--- src/maasserver/forms.py 2014-10-03 01:50:39 +0000
+++ src/maasserver/forms.py 2014-10-03 04:54:19 +0000
@@ -150,7 +150,10 @@
150 )150 )
151from metadataserver.fields import Bin151from metadataserver.fields import Bin
152from metadataserver.models import CommissioningScript152from metadataserver.models import CommissioningScript
153from netaddr import IPAddress153from netaddr import (
154 IPAddress,
155 valid_ipv6,
156 )
154from provisioningserver.logger import get_maas_logger157from provisioningserver.logger import get_maas_logger
155from provisioningserver.network import REVEAL_IPv6158from provisioningserver.network import REVEAL_IPv6
156from provisioningserver.rpc.exceptions import (159from provisioningserver.rpc.exceptions import (
@@ -308,6 +311,14 @@
308 return None, None311 return None, None
309312
310313
314def contains_managed_ipv6_interface(interfaces):
315 """Does any of a list of cluster interfaces manage a IPv6 subnet?"""
316 return any(
317 interface.manages_static_range() and valid_ipv6(interface.ip)
318 for interface in interfaces
319 )
320
321
311class NodeForm(MAASModelForm):322class NodeForm(MAASModelForm):
312323
313 def __init__(self, request=None, *args, **kwargs):324 def __init__(self, request=None, *args, **kwargs):
@@ -322,10 +333,25 @@
322 # Offer choice of nodegroup.333 # Offer choice of nodegroup.
323 self.fields['nodegroup'] = NodeGroupFormField(334 self.fields['nodegroup'] = NodeGroupFormField(
324 required=False, empty_label="Default (master)")335 required=False, empty_label="Default (master)")
325 self.set_up_architecture_field()
326 self.set_up_osystem_and_distro_series_fields(kwargs.get('instance'))
327336
328 if not REVEAL_IPv6:337 if not REVEAL_IPv6:
338 # We're not showing the IPv6 feature to the user. Hide the ability
339 # to disable IPv4 on a node.
340 allow_disable_ipv4 = False
341 elif self.new_node:
342 # Permit disabling of IPv4 if at least one cluster supports IPv6.
343 allow_disable_ipv4 = contains_managed_ipv6_interface(
344 NodeGroupInterface.objects.all())
345 else:
346 # Permit disabling of IPv4 if at least one interface on the cluster
347 # supports IPv6.
348 allow_disable_ipv4 = contains_managed_ipv6_interface(
349 self.instance.nodegroup.nodegroupinterface_set.all())
350
351 self.set_up_architecture_field()
352 self.set_up_osystem_and_distro_series_fields(kwargs.get('instance'))
353
354 if not allow_disable_ipv4:
329 # Hide the disable_ipv4 field until support works properly. The355 # Hide the disable_ipv4 field until support works properly. The
330 # API will still support the field, but it won't be visible.356 # API will still support the field, but it won't be visible.
331 # This hidden field absolutely needs an empty label, because its357 # This hidden field absolutely needs an empty label, because its
332358
=== modified file 'src/maasserver/tests/test_forms_node.py'
--- src/maasserver/tests/test_forms_node.py 2014-09-29 13:21:42 +0000
+++ src/maasserver/tests/test_forms_node.py 2014-10-03 04:54:19 +0000
@@ -15,6 +15,10 @@
15__all__ = []15__all__ = []
1616
17from crochet import TimeoutError17from crochet import TimeoutError
18from django.forms import (
19 CheckboxInput,
20 HiddenInput,
21 )
18from maasserver import forms22from maasserver import forms
19from maasserver.clusterrpc.power_parameters import get_power_type_choices23from maasserver.clusterrpc.power_parameters import get_power_type_choices
20from maasserver.clusterrpc.testing.osystems import (24from maasserver.clusterrpc.testing.osystems import (
@@ -32,6 +36,7 @@
32 NodeForm,36 NodeForm,
33 pick_default_architecture,37 pick_default_architecture,
34 )38 )
39import maasserver.forms as forms_module
35from maasserver.testing.architecture import (40from maasserver.testing.architecture import (
36 make_usable_architecture,41 make_usable_architecture,
37 patch_usable_architectures,42 patch_usable_architectures,
@@ -412,6 +417,57 @@
412 node = form.save()417 node = form.save()
413 self.assertEqual(setting, node.disable_ipv4)418 self.assertEqual(setting, node.disable_ipv4)
414419
420 def test_shows_disable_ipv4_if_IPv6_revealed_and_configured(self):
421 self.patch(forms_module, 'REVEAL_IPv6', True)
422 node = factory.make_node_with_mac_attached_to_nodegroupinterface()
423 factory.make_NodeGroupInterface(
424 node.nodegroup, network=factory.make_ipv6_network(),
425 management=NODEGROUPINTERFACE_MANAGEMENT.DHCP)
426 form = NodeForm(
427 instance=node,
428 data={'architecture': make_usable_architecture(self)})
429 self.assertIsInstance(
430 form.fields['disable_ipv4'].widget, CheckboxInput)
431
432 def test_hides_disable_ipv4_if_IPv6_not_revealed(self):
433 self.patch(forms_module, 'REVEAL_IPv6', False)
434 node = factory.make_node_with_mac_attached_to_nodegroupinterface()
435 factory.make_NodeGroupInterface(
436 node.nodegroup, network=factory.make_ipv6_network(),
437 management=NODEGROUPINTERFACE_MANAGEMENT.DHCP)
438 form = NodeForm(
439 instance=node,
440 data={'architecture': make_usable_architecture(self)})
441 self.assertIsInstance(form.fields['disable_ipv4'].widget, HiddenInput)
442
443 def test_hides_disable_ipv4_if_IPv6_not_configured(self):
444 self.patch(forms_module, 'REVEAL_IPv6', True)
445 node = factory.make_node_with_mac_attached_to_nodegroupinterface()
446 factory.make_NodeGroupInterface(
447 node.nodegroup, network=factory.make_ipv6_network(),
448 management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
449 form = NodeForm(
450 instance=node,
451 data={'architecture': make_usable_architecture(self)})
452 self.assertIsInstance(form.fields['disable_ipv4'].widget, HiddenInput)
453
454 def test_shows_disable_ipv4_on_new_node_if_any_cluster_supports_it(self):
455 self.patch(forms_module, 'REVEAL_IPv6', True)
456 factory.make_NodeGroupInterface(
457 factory.make_NodeGroup(), network=factory.make_ipv6_network(),
458 management=NODEGROUPINTERFACE_MANAGEMENT.DHCP)
459 form = NodeForm(data={'architecture': make_usable_architecture(self)})
460 self.assertIsInstance(
461 form.fields['disable_ipv4'].widget, CheckboxInput)
462
463 def test_hides_disable_ipv4_on_new_node_if_no_cluster_supports_it(self):
464 self.patch(forms_module, 'REVEAL_IPv6', True)
465 factory.make_NodeGroupInterface(
466 factory.make_NodeGroup(), network=factory.make_ipv6_network(),
467 management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
468 form = NodeForm(data={'architecture': make_usable_architecture(self)})
469 self.assertIsInstance(form.fields['disable_ipv4'].widget, HiddenInput)
470
415471
416class TestAdminNodeForm(MAASServerTestCase):472class TestAdminNodeForm(MAASServerTestCase):
417473