Merge lp:~dimitern/maas/1.2-node-view-shows-kernel-params into lp:maas

Proposed by Dimiter Naydenov
Status: Merged
Approved by: John A Meinel
Approved revision: 1292
Merged at revision: 1338
Proposed branch: lp:~dimitern/maas/1.2-node-view-shows-kernel-params
Merge into: lp:maas
Prerequisite: lp:~jameinel/maas/land-kernel-opts-in-trunk
Diff against target: 267 lines (+124/-1)
11 files modified
src/maasserver/forms.py (+7/-0)
src/maasserver/static/css/components/blocks.css (+3/-0)
src/maasserver/templates/maasserver/form_field.html (+1/-1)
src/maasserver/templates/maasserver/node_view.html (+14/-0)
src/maasserver/templates/maasserver/settings.html (+15/-0)
src/maasserver/templates/maasserver/tag_view.html (+6/-0)
src/maasserver/tests/test_views_nodes.py (+35/-0)
src/maasserver/tests/test_views_settings.py (+15/-0)
src/maasserver/tests/test_views_tags.py (+11/-0)
src/maasserver/views/nodes.py (+8/-0)
src/maasserver/views/settings.py (+9/-0)
To merge this branch: bzr merge lp:~dimitern/maas/1.2-node-view-shows-kernel-params
Reviewer Review Type Date Requested Status
Martin Packman (community) Approve
Review via email: mp+133449@code.launchpad.net

This proposal supersedes a proposal from 2012-11-07.

Commit message

Related to bug #1044503: UI changes in node, tag and settings pages to show effective kernel parameters.

Description of the change

Adding UI for kernel parameters in node and tag views, as well as the settings page.

Resubmitted after merging lp:~jameinel/maas/land-kernel-opts-in-trunk and now is targeting trunk, instead of 1.2.

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote : Posted in a previous version of this proposal

Will want a little followup as the other branches land, but the view and template stuff looks good to me.

Revision history for this message
Dimiter Naydenov (dimitern) wrote : Posted in a previous version of this proposal

I'm ready with the changes and tests - everything works with one exception - test_view_node_shows_tag_kernel_params still fails, because it assumes Node.get_effective_kernel_options() returns (Tag, kernel_opts) tuple when a tag has kernel_opts and is applied to a node. So, once https://code.launchpad.net/~jameinel/maas/1.2-kernel-option-tags lands, the failing test should pass.

Revision history for this message
Martin Packman (gz) wrote :

Looks good, go for it!

review: Approve
Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Thanks for the review!

Revision history for this message
MAAS Lander (maas-lander) wrote :

The prerequisite lp:~jameinel/maas/land-kernel-opts-in-trunk has not yet been merged into lp:maas.

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 2012-11-08 11:00:29 +0000
3+++ src/maasserver/forms.py 2012-11-08 11:00:30 +0000
4@@ -655,6 +655,13 @@
5 self._load_initials()
6
7
8+class GlobalKernelOptsForm(ConfigForm):
9+ """Settings page, Global Kernel Parameters section."""
10+ kernel_opts = forms.CharField(
11+ label="Boot parameters to pass to the kernel by default",
12+ required=False)
13+
14+
15 hostname_error_msg = "Enter a valid hostname (e.g. host.example.com)."
16
17
18
19=== modified file 'src/maasserver/static/css/components/blocks.css'
20--- src/maasserver/static/css/components/blocks.css 2012-10-03 03:59:53 +0000
21+++ src/maasserver/static/css/components/blocks.css 2012-11-08 11:00:30 +0000
22@@ -82,3 +82,6 @@
23 .size12 {
24 width: 720px;
25 }
26+.size12 input {
27+ width: 100%;
28+ }
29
30=== modified file 'src/maasserver/templates/maasserver/form_field.html'
31--- src/maasserver/templates/maasserver/form_field.html 2012-08-03 16:36:26 +0000
32+++ src/maasserver/templates/maasserver/form_field.html 2012-11-08 11:00:30 +0000
33@@ -1,5 +1,5 @@
34 {% load field_type %}
35-<li class="{{ field.html_name }}{% if field.errors %} error{% endif %}">
36+<li class="{{ field.html_name }}{% if css_class %} {{ css_class }}{% endif %}{% if field.errors %} error{% endif %}">
37 <label for="id_{{ field.html_name }}">
38 {% ifequal field|field_type "CheckboxInput" %}
39 {{ field }}
40
41=== modified file 'src/maasserver/templates/maasserver/node_view.html'
42--- src/maasserver/templates/maasserver/node_view.html 2012-11-07 14:43:58 +0000
43+++ src/maasserver/templates/maasserver/node_view.html 2012-11-08 11:00:30 +0000
44@@ -85,6 +85,20 @@
45 {% endif %}
46 </span>
47 </li>
48+ {% if kernel_opts.value %}
49+ <li class="block size10 first">
50+ <h4>Kernel Parameters
51+ {% if kernel_opts.is_global %}
52+ - from: <a class="kernelopts-global-link" href="{% url 'settings' %}">Global Kernel Parameters</a>
53+ {% elif kernel_opts.is_tag %}
54+ - from tag: <span><a class="kernelopts-tag-link" href="{% url 'tag-view' kernel_opts.tag.name %}">{{ kernel_opts.tag.name }}</a></span>
55+ {% endif %}
56+ </h4>
57+ <span id="node_kernel_opts">
58+ {{ kernel_opts.value }}
59+ </span>
60+ </li>
61+ {% endif %}
62 {% if error_text %}
63 <li class="block first">
64 <h4>Error output</h4>
65
66=== modified file 'src/maasserver/templates/maasserver/settings.html'
67--- src/maasserver/templates/maasserver/settings.html 2012-11-06 16:47:23 +0000
68+++ src/maasserver/templates/maasserver/settings.html 2012-11-08 11:00:30 +0000
69@@ -125,6 +125,21 @@
70 <div class="clear"></div>
71 </div>
72 <div class="divider"></div>
73+ <div id="global_kernel_opts" class="block size7 first">
74+ <h2>Global Kernel Parameters</h2>
75+ <form action="{% url "settings" %}" method="post">
76+ {% csrf_token %}
77+ <ul>
78+ {% with field=kernelopts_form.kernel_opts %}
79+ {% include "maasserver/form_field.html" with css_class="size12" %}
80+ {% endwith %}
81+ </ul>
82+ <input type="hidden" name="kernelopts_submit" value="1" />
83+ <input type="submit" class="button right" value="Save" />
84+ </form>
85+ <div class="clear"></div>
86+ </div>
87+ <div class="divider"></div>
88 <div id="maas_and_network" class="block size7 first">
89 <h2>Network Configuration</h2>
90 <form action="{% url "settings" %}" method="post">
91
92=== modified file 'src/maasserver/templates/maasserver/tag_view.html'
93--- src/maasserver/templates/maasserver/tag_view.html 2012-10-24 12:51:10 +0000
94+++ src/maasserver/templates/maasserver/tag_view.html 2012-11-08 11:00:30 +0000
95@@ -19,6 +19,12 @@
96 <h4>Definition</h4>
97 <span>{{ tag.definition }}</span>
98 </li>
99+ {% if tag.kernel_opts %}
100+ <li class="kernel-opts-tag block size10">
101+ <h4>Kernel Parameters</h4>
102+ <span>{{ tag.kernel_opts }}</span>
103+ </li>
104+ {% endif %}
105 {% if error_text %}
106 <li class="block first">
107 <h4>Error output</h4>
108
109=== modified file 'src/maasserver/tests/test_views_nodes.py'
110--- src/maasserver/tests/test_views_nodes.py 2012-11-08 10:11:03 +0000
111+++ src/maasserver/tests/test_views_nodes.py 2012-11-08 11:00:30 +0000
112@@ -39,6 +39,7 @@
113 )
114 from maasserver.forms import NodeActionForm
115 from maasserver.models import (
116+ Config,
117 MACAddress,
118 Node,
119 )
120@@ -440,6 +441,40 @@
121 self.assertIn(
122 reverse('mac-add', args=[node.system_id]), response.content)
123
124+ def test_view_node_shows_global_kernel_params(self):
125+ Config.objects.create(name='kernel_opts', value='--test param')
126+ node = factory.make_node()
127+ self.assertEqual(
128+ node.get_effective_kernel_options(),
129+ (None, "--test param", )
130+ )
131+
132+ node_link = reverse('node-view', args=[node.system_id])
133+ response = self.client.get(node_link)
134+ doc = fromstring(response.content)
135+ kernel_params = doc.cssselect('#node_kernel_opts')[0]
136+ self.assertEqual('--test param', kernel_params.text.strip())
137+
138+ details_link = doc.cssselect('a.kernelopts-global-link')[0].get('href')
139+ self.assertEqual(reverse('settings'), details_link)
140+
141+ def test_view_node_shows_tag_kernel_params(self):
142+ tag = factory.make_tag(name='shiny', kernel_opts="--test params")
143+ node = factory.make_node()
144+ node.tags = [tag]
145+ self.assertEqual(
146+ (tag, '--test params',),
147+ node.get_effective_kernel_options())
148+
149+ node_link = reverse('node-view', args=[node.system_id])
150+ response = self.client.get(node_link)
151+ doc = fromstring(response.content)
152+ kernel_params = doc.cssselect('#node_kernel_opts')[0]
153+ self.assertEqual('--test params', kernel_params.text.strip())
154+
155+ details_link = doc.cssselect('a.kernelopts-tag-link')[0].get('href')
156+ self.assertEqual(reverse('tag-view', args=[tag.name]), details_link)
157+
158 def test_view_node_has_button_to_accept_enlistment_for_user(self):
159 # A simple user can't see the button to enlist a declared node.
160 node = factory.make_node(status=NODE_STATUS.DECLARED)
161
162=== modified file 'src/maasserver/tests/test_views_settings.py'
163--- src/maasserver/tests/test_views_settings.py 2012-11-08 06:34:48 +0000
164+++ src/maasserver/tests/test_views_settings.py 2012-11-08 11:00:30 +0000
165@@ -185,6 +185,21 @@
166 choices + [['my.hostname.com', 'my.hostname.com']],
167 new_choices)
168
169+ def test_settings_kernelopts_POST(self):
170+ new_kernel_opts = "--new='arg' --flag=1 other"
171+ response = self.client.post(
172+ reverse('settings'),
173+ get_prefixed_form_data(
174+ prefix='kernelopts',
175+ data={
176+ 'kernel_opts': new_kernel_opts,
177+ }))
178+
179+ self.assertEqual(httplib.FOUND, response.status_code)
180+ self.assertEqual(
181+ new_kernel_opts,
182+ Config.objects.get_config('kernel_opts'))
183+
184 def test_settings_contains_form_to_accept_all_nodegroups(self):
185 factory.make_node_group(status=NODEGROUP_STATUS.PENDING),
186 response = self.client.get(reverse('settings'))
187
188=== modified file 'src/maasserver/tests/test_views_tags.py'
189--- src/maasserver/tests/test_views_tags.py 2012-11-08 07:38:39 +0000
190+++ src/maasserver/tests/test_views_tags.py 2012-11-08 11:00:30 +0000
191@@ -89,6 +89,17 @@
192 self.assertIn(node.hostname, content_text)
193 self.assertNotIn(node2.hostname, content_text)
194
195+ def test_view_tag_shows_kernel_params(self):
196+ tag = factory.make_tag(kernel_opts='--test tag params')
197+ node = factory.make_node()
198+ node.tags = [tag]
199+ tag_link = reverse('tag-view', args=[tag.name])
200+ response = self.client.get(tag_link)
201+ doc = fromstring(response.content)
202+ kernel_opts = doc.cssselect('.kernel-opts-tag')[0].text_content()
203+ self.assertIn('Kernel Parameters', kernel_opts)
204+ self.assertIn(tag.kernel_opts, kernel_opts)
205+
206 def test_view_tag_paginates_nodes(self):
207 """Listing of nodes with tag is split across multiple pages
208
209
210=== modified file 'src/maasserver/views/nodes.py'
211--- src/maasserver/views/nodes.py 2012-11-08 10:11:03 +0000
212+++ src/maasserver/views/nodes.py 2012-11-08 11:00:30 +0000
213@@ -56,6 +56,7 @@
214 from maasserver.models import (
215 MACAddress,
216 Node,
217+ Tag,
218 )
219 from maasserver.models.node import CONSTRAINTS_JUJU_MAP
220 from maasserver.models.node_constraint_filter import constrain_nodes
221@@ -247,6 +248,13 @@
222 node.error if node.status == NODE_STATUS.FAILED_TESTS else None)
223 context['status_text'] = (
224 node.error if node.status != NODE_STATUS.FAILED_TESTS else None)
225+ kernel_opts = node.get_effective_kernel_options()
226+ context['kernel_opts'] = {
227+ 'is_global': kernel_opts[0] is None,
228+ 'is_tag': isinstance(kernel_opts[0], Tag),
229+ 'tag': kernel_opts[0],
230+ 'value': kernel_opts[1]
231+ }
232 return context
233
234 def dispatch(self, *args, **kwargs):
235
236=== modified file 'src/maasserver/views/settings.py'
237--- src/maasserver/views/settings.py 2012-11-07 10:39:19 +0000
238+++ src/maasserver/views/settings.py 2012-11-08 11:00:30 +0000
239@@ -46,6 +46,7 @@
240 MAASAndNetworkForm,
241 NewUserCreationForm,
242 UbuntuForm,
243+ GlobalKernelOptsForm,
244 )
245 from maasserver.models import (
246 NodeGroup,
247@@ -177,6 +178,13 @@
248 if response is not None:
249 return response
250
251+ # Process the Global Kernel Opts form.
252+ kernelopts_form, response = process_form(
253+ request, GlobalKernelOptsForm, reverse('settings'), 'kernelopts',
254+ "Configuration updated.")
255+ if response is not None:
256+ return response
257+
258 # Process accept clusters en masse.
259 if 'mass_accept_submit' in request.POST:
260 number = NodeGroup.objects.accept_all_pending()
261@@ -217,6 +225,7 @@
262 'maas_and_network_form': maas_and_network_form,
263 'commissioning_form': commissioning_form,
264 'ubuntu_form': ubuntu_form,
265+ 'kernelopts_form': kernelopts_form,
266 },
267 context_instance=RequestContext(request))
268