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
1=== modified file 'src/maasserver/forms.py'
2--- src/maasserver/forms.py 2014-10-03 01:50:39 +0000
3+++ src/maasserver/forms.py 2014-10-03 04:54:19 +0000
4@@ -150,7 +150,10 @@
5 )
6 from metadataserver.fields import Bin
7 from metadataserver.models import CommissioningScript
8-from netaddr import IPAddress
9+from netaddr import (
10+ IPAddress,
11+ valid_ipv6,
12+ )
13 from provisioningserver.logger import get_maas_logger
14 from provisioningserver.network import REVEAL_IPv6
15 from provisioningserver.rpc.exceptions import (
16@@ -308,6 +311,14 @@
17 return None, None
18
19
20+def contains_managed_ipv6_interface(interfaces):
21+ """Does any of a list of cluster interfaces manage a IPv6 subnet?"""
22+ return any(
23+ interface.manages_static_range() and valid_ipv6(interface.ip)
24+ for interface in interfaces
25+ )
26+
27+
28 class NodeForm(MAASModelForm):
29
30 def __init__(self, request=None, *args, **kwargs):
31@@ -322,10 +333,25 @@
32 # Offer choice of nodegroup.
33 self.fields['nodegroup'] = NodeGroupFormField(
34 required=False, empty_label="Default (master)")
35- self.set_up_architecture_field()
36- self.set_up_osystem_and_distro_series_fields(kwargs.get('instance'))
37
38 if not REVEAL_IPv6:
39+ # We're not showing the IPv6 feature to the user. Hide the ability
40+ # to disable IPv4 on a node.
41+ allow_disable_ipv4 = False
42+ elif self.new_node:
43+ # Permit disabling of IPv4 if at least one cluster supports IPv6.
44+ allow_disable_ipv4 = contains_managed_ipv6_interface(
45+ NodeGroupInterface.objects.all())
46+ else:
47+ # Permit disabling of IPv4 if at least one interface on the cluster
48+ # supports IPv6.
49+ allow_disable_ipv4 = contains_managed_ipv6_interface(
50+ self.instance.nodegroup.nodegroupinterface_set.all())
51+
52+ self.set_up_architecture_field()
53+ self.set_up_osystem_and_distro_series_fields(kwargs.get('instance'))
54+
55+ if not allow_disable_ipv4:
56 # Hide the disable_ipv4 field until support works properly. The
57 # API will still support the field, but it won't be visible.
58 # This hidden field absolutely needs an empty label, because its
59
60=== modified file 'src/maasserver/tests/test_forms_node.py'
61--- src/maasserver/tests/test_forms_node.py 2014-09-29 13:21:42 +0000
62+++ src/maasserver/tests/test_forms_node.py 2014-10-03 04:54:19 +0000
63@@ -15,6 +15,10 @@
64 __all__ = []
65
66 from crochet import TimeoutError
67+from django.forms import (
68+ CheckboxInput,
69+ HiddenInput,
70+ )
71 from maasserver import forms
72 from maasserver.clusterrpc.power_parameters import get_power_type_choices
73 from maasserver.clusterrpc.testing.osystems import (
74@@ -32,6 +36,7 @@
75 NodeForm,
76 pick_default_architecture,
77 )
78+import maasserver.forms as forms_module
79 from maasserver.testing.architecture import (
80 make_usable_architecture,
81 patch_usable_architectures,
82@@ -412,6 +417,57 @@
83 node = form.save()
84 self.assertEqual(setting, node.disable_ipv4)
85
86+ def test_shows_disable_ipv4_if_IPv6_revealed_and_configured(self):
87+ self.patch(forms_module, 'REVEAL_IPv6', True)
88+ node = factory.make_node_with_mac_attached_to_nodegroupinterface()
89+ factory.make_NodeGroupInterface(
90+ node.nodegroup, network=factory.make_ipv6_network(),
91+ management=NODEGROUPINTERFACE_MANAGEMENT.DHCP)
92+ form = NodeForm(
93+ instance=node,
94+ data={'architecture': make_usable_architecture(self)})
95+ self.assertIsInstance(
96+ form.fields['disable_ipv4'].widget, CheckboxInput)
97+
98+ def test_hides_disable_ipv4_if_IPv6_not_revealed(self):
99+ self.patch(forms_module, 'REVEAL_IPv6', False)
100+ node = factory.make_node_with_mac_attached_to_nodegroupinterface()
101+ factory.make_NodeGroupInterface(
102+ node.nodegroup, network=factory.make_ipv6_network(),
103+ management=NODEGROUPINTERFACE_MANAGEMENT.DHCP)
104+ form = NodeForm(
105+ instance=node,
106+ data={'architecture': make_usable_architecture(self)})
107+ self.assertIsInstance(form.fields['disable_ipv4'].widget, HiddenInput)
108+
109+ def test_hides_disable_ipv4_if_IPv6_not_configured(self):
110+ self.patch(forms_module, 'REVEAL_IPv6', True)
111+ node = factory.make_node_with_mac_attached_to_nodegroupinterface()
112+ factory.make_NodeGroupInterface(
113+ node.nodegroup, network=factory.make_ipv6_network(),
114+ management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
115+ form = NodeForm(
116+ instance=node,
117+ data={'architecture': make_usable_architecture(self)})
118+ self.assertIsInstance(form.fields['disable_ipv4'].widget, HiddenInput)
119+
120+ def test_shows_disable_ipv4_on_new_node_if_any_cluster_supports_it(self):
121+ self.patch(forms_module, 'REVEAL_IPv6', True)
122+ factory.make_NodeGroupInterface(
123+ factory.make_NodeGroup(), network=factory.make_ipv6_network(),
124+ management=NODEGROUPINTERFACE_MANAGEMENT.DHCP)
125+ form = NodeForm(data={'architecture': make_usable_architecture(self)})
126+ self.assertIsInstance(
127+ form.fields['disable_ipv4'].widget, CheckboxInput)
128+
129+ def test_hides_disable_ipv4_on_new_node_if_no_cluster_supports_it(self):
130+ self.patch(forms_module, 'REVEAL_IPv6', True)
131+ factory.make_NodeGroupInterface(
132+ factory.make_NodeGroup(), network=factory.make_ipv6_network(),
133+ management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
134+ form = NodeForm(data={'architecture': make_usable_architecture(self)})
135+ self.assertIsInstance(form.fields['disable_ipv4'].widget, HiddenInput)
136+
137
138 class TestAdminNodeForm(MAASServerTestCase):
139