Merge lp:~jtv/maas/warn-unconfigured-ip 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: 3042
Proposed branch: lp:~jtv/maas/warn-unconfigured-ip
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 225 lines (+126/-4)
3 files modified
src/maasserver/templates/maasserver/node_view.html (+9/-2)
src/maasserver/views/nodes.py (+36/-0)
src/maasserver/views/tests/test_nodes.py (+81/-2)
To merge this branch: bzr merge lp:~jtv/maas/warn-unconfigured-ip
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+235259@code.launchpad.net

Commit message

Warn on the Node page if a node has static IPv6 addresses that can't be configured on the node. IPv6 address configuration is currently only supported with Ubuntu, using the fast installer.

Description of the change

The warning shows up in two places: a big colourful detailed message at the top of the page, and a warning triangle next to the “IP addresses” heading with a tooltip that says the node's IPv6 addresses are not configured. It's terse, but hopefully it combines well with the full notice at the top of the page.

I chose to show the warning only while the node has an owner. Otherwise, the node's operating-system property is meaningless: it will be reset before the node is ever deployed.

Eventually, we hope this notice can go away as we will support IPv6 on all operating systems.

Jeroen

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

Grand. It's cool to watch the IPv6 work progressing.

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

Implemented your suggestion using any(). Much better, thanks!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/templates/maasserver/node_view.html'
2--- src/maasserver/templates/maasserver/node_view.html 2014-09-15 14:28:28 +0000
3+++ src/maasserver/templates/maasserver/node_view.html 2014-09-20 02:25:09 +0000
4@@ -159,8 +159,15 @@
5 </li>
6 {% with ip_addresses=node.ip_addresses %}
7 {% if ip_addresses|length %}
8- <li class="block size3">
9- <h4>IP addresses</h4>
10+ <li class="block size3" id="ip-addresses">
11+ <h4>IP addresses
12+ {% if unconfigured_ips_warning %}
13+ <img
14+ src="{{ STATIC_URL }}img/warning.png"
15+ title="This node's IPv6 addresses are not automatically configured."
16+ id="unconfigured-ips-warning" />
17+ {% endif %}
18+ </h4>
19 <span>
20 {% for ip in ip_addresses %}
21 {{ ip }}{% if not forloop.last %}, {% endif %}
22
23=== modified file 'src/maasserver/views/nodes.py'
24--- src/maasserver/views/nodes.py 2014-09-11 17:45:02 +0000
25+++ src/maasserver/views/nodes.py 2014-09-20 02:25:09 +0000
26@@ -54,6 +54,7 @@
27 from maasserver import logger
28 from maasserver.clusterrpc.power_parameters import get_power_types
29 from maasserver.enum import (
30+ NODE_BOOT,
31 NODE_PERMISSION,
32 NODE_STATUS,
33 )
34@@ -72,6 +73,7 @@
35 from maasserver.models import (
36 MACAddress,
37 Node,
38+ StaticIPAddress,
39 Tag,
40 )
41 from maasserver.models.config import Config
42@@ -96,6 +98,7 @@
43 from metadataserver.models import NodeResult
44 from netaddr import (
45 EUI,
46+ IPAddress,
47 NotRegisteredError,
48 )
49 from provisioningserver.tags import merge_details_cleanly
50@@ -497,6 +500,12 @@
51 href="%s#third_party_drivers">settings</a> page.
52 """)
53
54+UNCONFIGURED_IPS_NOTICE = dedent("""
55+ Automatic configuration of IPv6 addresses is currently only supported on
56+ Ubuntu, using the fast installer. To activate the IPv6 address(es) shown
57+ here, configure them in the installed operating system.
58+ """)
59+
60
61 def construct_third_party_drivers_notice(user_is_admin):
62 """Build and return the notice about third party drivers.
63@@ -529,6 +538,29 @@
64 # The number of events shown on the node view page.
65 number_of_events_shown = 5
66
67+ def warn_unconfigured_ip_addresses(self, node):
68+ """Should the UI warn about unconfigured IPv6 addresses on the node?
69+
70+ Static IPv6 addresses are configured on the node using Curtin. But
71+ this is not yet supported for all operating systems and installers.
72+ If a node has IPv6 addresses assigned but is not being deployed in a
73+ way that supports configuring them, the node page should show a warning
74+ to say that the user will need to configure the node to use those
75+ addresses.
76+
77+ :return: Bool: should the UI show this warning?
78+ """
79+ if node.osystem == 'ubuntu' and node.boot_type == NODE_BOOT.FASTPATH:
80+ # MAAS knows how to configure IPv6 addresses on an Ubuntu node
81+ # installed with the fast installer. No warning needed.
82+ return False
83+ # For other installs, we need the warning if and only if the node has
84+ # static IPv6 addresses.
85+ static_ips = StaticIPAddress.objects.filter(macaddress__node=node)
86+ return any(
87+ IPAddress(static_ip.ip).version == 6
88+ for static_ip in static_ips)
89+
90 def get_context_data(self, **kwargs):
91 context = super(NodeView, self).get_context_data(**kwargs)
92 node = self.get_object()
93@@ -538,6 +570,10 @@
94 messages.info(self.request, NODE_BOOT_INFO)
95 if node.power_type == '':
96 messages.error(self.request, NO_POWER_SET)
97+ if self.warn_unconfigured_ip_addresses(node):
98+ messages.warning(self.request, UNCONFIGURED_IPS_NOTICE)
99+ context['unconfigured_ips_warning'] = UNCONFIGURED_IPS_NOTICE
100+
101 context['error_text'] = (
102 node.error if node.status == NODE_STATUS.FAILED_COMMISSIONING
103 else None)
104
105=== modified file 'src/maasserver/views/tests/test_nodes.py'
106--- src/maasserver/views/tests/test_nodes.py 2014-09-18 12:44:38 +0000
107+++ src/maasserver/views/tests/test_nodes.py 2014-09-20 02:25:09 +0000
108@@ -18,7 +18,10 @@
109 import httplib
110 from operator import attrgetter
111 import os
112-from random import randint
113+from random import (
114+ choice,
115+ randint,
116+ )
117 from textwrap import dedent
118 from urlparse import (
119 parse_qsl,
120@@ -34,6 +37,7 @@
121 import maasserver.api
122 from maasserver.clusterrpc.testing.boot_images import make_rpc_boot_image
123 from maasserver.enum import (
124+ NODE_BOOT,
125 NODE_STATUS,
126 NODEGROUP_STATUS,
127 NODEGROUPINTERFACE_MANAGEMENT,
128@@ -86,7 +90,11 @@
129 )
130 from provisioningserver.utils.enum import map_enum
131 from provisioningserver.utils.text import normalise_whitespace
132-from testtools.matchers import ContainsAll
133+from testtools.matchers import (
134+ ContainsAll,
135+ HasLength,
136+ Not,
137+ )
138
139
140 class TestGenerateJSPowerTypes(MAASServerTestCase):
141@@ -478,6 +486,34 @@
142 response = self.client.get(node_link)
143 self.assertNotIn("IP addresses", response.content)
144
145+ def test_view_node_warns_about_unconfigured_IPv6_addresses(self):
146+ self.client_log_in()
147+ ipv6_network = factory.make_ipv6_network()
148+ node = factory.make_node_with_mac_attached_to_nodegroupinterface(
149+ owner=self.logged_in_user, network=ipv6_network,
150+ osystem='windows')
151+ factory.make_StaticIPAddress(
152+ ip=factory.pick_ip_in_network(ipv6_network),
153+ mac=node.get_primary_mac())
154+ node_link = reverse('node-view', args=[node.system_id])
155+ page = fromstring(self.client.get(node_link).content)
156+ [addresses_section] = page.cssselect('#ip-addresses')
157+ self.expectThat(
158+ addresses_section.cssselect('#unconfigured-ips-warning'),
159+ Not(HasLength(0)))
160+
161+ def test_view_node_does_not_warn_if_no_unconfigured_IPv6_addresses(self):
162+ self.client_log_in()
163+ node = factory.make_node_with_mac_attached_to_nodegroupinterface(
164+ owner=self.logged_in_user)
165+ factory.make_StaticIPAddress(mac=node.get_primary_mac())
166+ node_link = reverse('node-view', args=[node.system_id])
167+ page = fromstring(self.client.get(node_link).content)
168+ [addresses_section] = page.cssselect('#ip-addresses')
169+ self.assertEqual(
170+ [],
171+ addresses_section.cssselect('#unconfigured-ip-warning'))
172+
173 def test_view_node_displays_node_info_no_owner(self):
174 # If the node has no owner, the Owner 'slot' does not exist.
175 self.client_log_in()
176@@ -1276,6 +1312,49 @@
177 self.assertIn(node_event_list, get_content_links(response))
178
179
180+class TestWarnUnconfiguredIPAddresses(MAASServerTestCase):
181+
182+ def test__warns_for_IPv6_address_on_non_ubuntu_OS(self):
183+ network = factory.make_ipv6_network()
184+ osystem = choice(['windows', 'centos', 'suse'])
185+ node = factory.make_node_with_mac_attached_to_nodegroupinterface(
186+ osystem=osystem, network=network)
187+ factory.make_StaticIPAddress(
188+ ip=factory.pick_ip_in_network(network), mac=node.get_primary_mac())
189+ self.assertTrue(NodeView().warn_unconfigured_ip_addresses(node))
190+
191+ def test__warns_for_IPv6_address_on_debian_installer(self):
192+ network = factory.make_ipv6_network()
193+ node = factory.make_node_with_mac_attached_to_nodegroupinterface(
194+ osystem='ubuntu', network=network, boot_type=NODE_BOOT.DEBIAN)
195+ factory.make_StaticIPAddress(
196+ ip=factory.pick_ip_in_network(network), mac=node.get_primary_mac())
197+ self.assertTrue(NodeView().warn_unconfigured_ip_addresses(node))
198+
199+ def test__does_not_warn_for_ubuntu_fast_installer(self):
200+ network = factory.make_ipv6_network()
201+ node = factory.make_node_with_mac_attached_to_nodegroupinterface(
202+ osystem='ubuntu', network=network, boot_type=NODE_BOOT.FASTPATH)
203+ factory.make_StaticIPAddress(
204+ ip=factory.pick_ip_in_network(network), mac=node.get_primary_mac())
205+ self.assertFalse(NodeView().warn_unconfigured_ip_addresses(node))
206+
207+ def test__does_not_warn_for_just_IPv4_address(self):
208+ network = factory.make_ipv4_network()
209+ osystem = choice(['windows', 'centos', 'suse'])
210+ node = factory.make_node_with_mac_attached_to_nodegroupinterface(
211+ osystem=osystem, network=network)
212+ factory.make_StaticIPAddress(
213+ ip=factory.pick_ip_in_network(network), mac=node.get_primary_mac())
214+ self.assertFalse(NodeView().warn_unconfigured_ip_addresses(node))
215+
216+ def test__does_not_warn_without_static_address(self):
217+ osystem = choice(['windows', 'centos', 'suse'])
218+ node = factory.make_node_with_mac_attached_to_nodegroupinterface(
219+ osystem=osystem)
220+ self.assertFalse(NodeView().warn_unconfigured_ip_addresses(node))
221+
222+
223 class NodeEventLogTest(MAASServerTestCase):
224
225 def test_event_log_shows_event_list(self):