launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #14096
[Merge] lp:~dimitern/maas/1.2-node-view-shows-kernel-params into lp:maas
Dimiter Naydenov has proposed merging lp:~dimitern/maas/1.2-node-view-shows-kernel-params into lp:maas with lp:~jameinel/maas/land-kernel-opts-in-trunk as a prerequisite.
Requested reviews:
MAAS Maintainers (maas-maintainers)
Related bugs:
Bug #1044503 in MAAS: "kernel command line is not easily customizable"
https://bugs.launchpad.net/maas/+bug/1044503
For more details, see:
https://code.launchpad.net/~dimitern/maas/1.2-node-view-shows-kernel-params/+merge/133449
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.
--
https://code.launchpad.net/~dimitern/maas/1.2-node-view-shows-kernel-params/+merge/133449
Your team MAAS Maintainers is requested to review the proposed merge of lp:~dimitern/maas/1.2-node-view-shows-kernel-params into lp:maas.
=== modified file 'src/maasserver/forms.py'
--- src/maasserver/forms.py 2012-11-08 11:00:29 +0000
+++ src/maasserver/forms.py 2012-11-08 11:00:30 +0000
@@ -655,6 +655,13 @@
self._load_initials()
+class GlobalKernelOptsForm(ConfigForm):
+ """Settings page, Global Kernel Parameters section."""
+ kernel_opts = forms.CharField(
+ label="Boot parameters to pass to the kernel by default",
+ required=False)
+
+
hostname_error_msg = "Enter a valid hostname (e.g. host.example.com)."
=== modified file 'src/maasserver/static/css/components/blocks.css'
--- src/maasserver/static/css/components/blocks.css 2012-10-03 03:59:53 +0000
+++ src/maasserver/static/css/components/blocks.css 2012-11-08 11:00:30 +0000
@@ -82,3 +82,6 @@
.size12 {
width: 720px;
}
+.size12 input {
+ width: 100%;
+ }
=== modified file 'src/maasserver/templates/maasserver/form_field.html'
--- src/maasserver/templates/maasserver/form_field.html 2012-08-03 16:36:26 +0000
+++ src/maasserver/templates/maasserver/form_field.html 2012-11-08 11:00:30 +0000
@@ -1,5 +1,5 @@
{% load field_type %}
-<li class="{{ field.html_name }}{% if field.errors %} error{% endif %}">
+<li class="{{ field.html_name }}{% if css_class %} {{ css_class }}{% endif %}{% if field.errors %} error{% endif %}">
<label for="id_{{ field.html_name }}">
{% ifequal field|field_type "CheckboxInput" %}
{{ field }}
=== modified file 'src/maasserver/templates/maasserver/node_view.html'
--- src/maasserver/templates/maasserver/node_view.html 2012-11-07 14:43:58 +0000
+++ src/maasserver/templates/maasserver/node_view.html 2012-11-08 11:00:30 +0000
@@ -85,6 +85,20 @@
{% endif %}
</span>
</li>
+ {% if kernel_opts.value %}
+ <li class="block size10 first">
+ <h4>Kernel Parameters
+ {% if kernel_opts.is_global %}
+ - from: <a class="kernelopts-global-link" href="{% url 'settings' %}">Global Kernel Parameters</a>
+ {% elif kernel_opts.is_tag %}
+ - from tag: <span><a class="kernelopts-tag-link" href="{% url 'tag-view' kernel_opts.tag.name %}">{{ kernel_opts.tag.name }}</a></span>
+ {% endif %}
+ </h4>
+ <span id="node_kernel_opts">
+ {{ kernel_opts.value }}
+ </span>
+ </li>
+ {% endif %}
{% if error_text %}
<li class="block first">
<h4>Error output</h4>
=== modified file 'src/maasserver/templates/maasserver/settings.html'
--- src/maasserver/templates/maasserver/settings.html 2012-11-06 16:47:23 +0000
+++ src/maasserver/templates/maasserver/settings.html 2012-11-08 11:00:30 +0000
@@ -125,6 +125,21 @@
<div class="clear"></div>
</div>
<div class="divider"></div>
+ <div id="global_kernel_opts" class="block size7 first">
+ <h2>Global Kernel Parameters</h2>
+ <form action="{% url "settings" %}" method="post">
+ {% csrf_token %}
+ <ul>
+ {% with field=kernelopts_form.kernel_opts %}
+ {% include "maasserver/form_field.html" with css_class="size12" %}
+ {% endwith %}
+ </ul>
+ <input type="hidden" name="kernelopts_submit" value="1" />
+ <input type="submit" class="button right" value="Save" />
+ </form>
+ <div class="clear"></div>
+ </div>
+ <div class="divider"></div>
<div id="maas_and_network" class="block size7 first">
<h2>Network Configuration</h2>
<form action="{% url "settings" %}" method="post">
=== modified file 'src/maasserver/templates/maasserver/tag_view.html'
--- src/maasserver/templates/maasserver/tag_view.html 2012-10-24 12:51:10 +0000
+++ src/maasserver/templates/maasserver/tag_view.html 2012-11-08 11:00:30 +0000
@@ -19,6 +19,12 @@
<h4>Definition</h4>
<span>{{ tag.definition }}</span>
</li>
+ {% if tag.kernel_opts %}
+ <li class="kernel-opts-tag block size10">
+ <h4>Kernel Parameters</h4>
+ <span>{{ tag.kernel_opts }}</span>
+ </li>
+ {% endif %}
{% if error_text %}
<li class="block first">
<h4>Error output</h4>
=== modified file 'src/maasserver/tests/test_views_nodes.py'
--- src/maasserver/tests/test_views_nodes.py 2012-11-08 10:11:03 +0000
+++ src/maasserver/tests/test_views_nodes.py 2012-11-08 11:00:30 +0000
@@ -39,6 +39,7 @@
)
from maasserver.forms import NodeActionForm
from maasserver.models import (
+ Config,
MACAddress,
Node,
)
@@ -440,6 +441,40 @@
self.assertIn(
reverse('mac-add', args=[node.system_id]), response.content)
+ def test_view_node_shows_global_kernel_params(self):
+ Config.objects.create(name='kernel_opts', value='--test param')
+ node = factory.make_node()
+ self.assertEqual(
+ node.get_effective_kernel_options(),
+ (None, "--test param", )
+ )
+
+ node_link = reverse('node-view', args=[node.system_id])
+ response = self.client.get(node_link)
+ doc = fromstring(response.content)
+ kernel_params = doc.cssselect('#node_kernel_opts')[0]
+ self.assertEqual('--test param', kernel_params.text.strip())
+
+ details_link = doc.cssselect('a.kernelopts-global-link')[0].get('href')
+ self.assertEqual(reverse('settings'), details_link)
+
+ def test_view_node_shows_tag_kernel_params(self):
+ tag = factory.make_tag(name='shiny', kernel_opts="--test params")
+ node = factory.make_node()
+ node.tags = [tag]
+ self.assertEqual(
+ (tag, '--test params',),
+ node.get_effective_kernel_options())
+
+ node_link = reverse('node-view', args=[node.system_id])
+ response = self.client.get(node_link)
+ doc = fromstring(response.content)
+ kernel_params = doc.cssselect('#node_kernel_opts')[0]
+ self.assertEqual('--test params', kernel_params.text.strip())
+
+ details_link = doc.cssselect('a.kernelopts-tag-link')[0].get('href')
+ self.assertEqual(reverse('tag-view', args=[tag.name]), details_link)
+
def test_view_node_has_button_to_accept_enlistment_for_user(self):
# A simple user can't see the button to enlist a declared node.
node = factory.make_node(status=NODE_STATUS.DECLARED)
=== modified file 'src/maasserver/tests/test_views_settings.py'
--- src/maasserver/tests/test_views_settings.py 2012-11-08 06:34:48 +0000
+++ src/maasserver/tests/test_views_settings.py 2012-11-08 11:00:30 +0000
@@ -185,6 +185,21 @@
choices + [['my.hostname.com', 'my.hostname.com']],
new_choices)
+ def test_settings_kernelopts_POST(self):
+ new_kernel_opts = "--new='arg' --flag=1 other"
+ response = self.client.post(
+ reverse('settings'),
+ get_prefixed_form_data(
+ prefix='kernelopts',
+ data={
+ 'kernel_opts': new_kernel_opts,
+ }))
+
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertEqual(
+ new_kernel_opts,
+ Config.objects.get_config('kernel_opts'))
+
def test_settings_contains_form_to_accept_all_nodegroups(self):
factory.make_node_group(status=NODEGROUP_STATUS.PENDING),
response = self.client.get(reverse('settings'))
=== modified file 'src/maasserver/tests/test_views_tags.py'
--- src/maasserver/tests/test_views_tags.py 2012-11-08 07:38:39 +0000
+++ src/maasserver/tests/test_views_tags.py 2012-11-08 11:00:30 +0000
@@ -89,6 +89,17 @@
self.assertIn(node.hostname, content_text)
self.assertNotIn(node2.hostname, content_text)
+ def test_view_tag_shows_kernel_params(self):
+ tag = factory.make_tag(kernel_opts='--test tag params')
+ node = factory.make_node()
+ node.tags = [tag]
+ tag_link = reverse('tag-view', args=[tag.name])
+ response = self.client.get(tag_link)
+ doc = fromstring(response.content)
+ kernel_opts = doc.cssselect('.kernel-opts-tag')[0].text_content()
+ self.assertIn('Kernel Parameters', kernel_opts)
+ self.assertIn(tag.kernel_opts, kernel_opts)
+
def test_view_tag_paginates_nodes(self):
"""Listing of nodes with tag is split across multiple pages
=== modified file 'src/maasserver/views/nodes.py'
--- src/maasserver/views/nodes.py 2012-11-08 10:11:03 +0000
+++ src/maasserver/views/nodes.py 2012-11-08 11:00:30 +0000
@@ -56,6 +56,7 @@
from maasserver.models import (
MACAddress,
Node,
+ Tag,
)
from maasserver.models.node import CONSTRAINTS_JUJU_MAP
from maasserver.models.node_constraint_filter import constrain_nodes
@@ -247,6 +248,13 @@
node.error if node.status == NODE_STATUS.FAILED_TESTS else None)
context['status_text'] = (
node.error if node.status != NODE_STATUS.FAILED_TESTS else None)
+ kernel_opts = node.get_effective_kernel_options()
+ context['kernel_opts'] = {
+ 'is_global': kernel_opts[0] is None,
+ 'is_tag': isinstance(kernel_opts[0], Tag),
+ 'tag': kernel_opts[0],
+ 'value': kernel_opts[1]
+ }
return context
def dispatch(self, *args, **kwargs):
=== modified file 'src/maasserver/views/settings.py'
--- src/maasserver/views/settings.py 2012-11-07 10:39:19 +0000
+++ src/maasserver/views/settings.py 2012-11-08 11:00:30 +0000
@@ -46,6 +46,7 @@
MAASAndNetworkForm,
NewUserCreationForm,
UbuntuForm,
+ GlobalKernelOptsForm,
)
from maasserver.models import (
NodeGroup,
@@ -177,6 +178,13 @@
if response is not None:
return response
+ # Process the Global Kernel Opts form.
+ kernelopts_form, response = process_form(
+ request, GlobalKernelOptsForm, reverse('settings'), 'kernelopts',
+ "Configuration updated.")
+ if response is not None:
+ return response
+
# Process accept clusters en masse.
if 'mass_accept_submit' in request.POST:
number = NodeGroup.objects.accept_all_pending()
@@ -217,6 +225,7 @@
'maas_and_network_form': maas_and_network_form,
'commissioning_form': commissioning_form,
'ubuntu_form': ubuntu_form,
+ 'kernelopts_form': kernelopts_form,
},
context_instance=RequestContext(request))
Follow ups