← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~rvb/maas/preseed-templates into lp:maas

 

Raphaël Badin has proposed merging lp:~rvb/maas/preseed-templates into lp:maas with lp:~rvb/maas/preseed-customisation as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~rvb/maas/preseed-templates/+merge/111049

This branch adds the Tempita-based preseed templates.

= Pre-imp =

This is part of the plan which was devised last week with Gavin (see http://bit.ly/KXW5ZU for details) and I've had a pre-imp call with Jeroen about this.

= Notes =

The new templates are in contrib/preseeds_v2 for now.  When we will be ready to ditch the old templates (in contrib/preseeds and contrib/snippets), we will just "rm -rf contrib/preseeds contrib/snippets && mv contrib/preseeds_v2 contrib/preseeds and update src/maas/development.py:PRESEED_TEMPLATE_LOCATIONS.

The preseed templates files (contrib/preseeds_v2/preseed_master, contrib/preseeds_v2/enlist, contrib/preseeds_v2/commissioning and contrib/preseeds_v2/generic) are simply the existing cobbler preseed templates/snippets converted to a Tempita format.  Note that I've used Tempita's inheritance mechanism to create a master template with all the boilerplate stuff.  The 'generic' template inherits from it.

In get_preseed_context, the value of context['node_disable_pxe_url'] is the empty string for now.  It will need to point to an anonymous version of the metadata API method that we already have to turn netboot off for the node in question.  That will be done in another branch.

I've also changed get_preseed_filenames to allow an empty prefix to be passed.  This is nothing more than a small improvement: if you want to create a preseed template for all the nodes with architecture 'myarch', you'll need to create a template file named 'myarch' (rather than _myarch).
-- 
https://code.launchpad.net/~rvb/maas/preseed-templates/+merge/111049
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/preseed-templates into lp:maas.
=== added directory 'contrib/preseeds_v2'
=== added file 'contrib/preseeds_v2/commissioning'
--- contrib/preseeds_v2/commissioning	1970-01-01 00:00:00 +0000
+++ contrib/preseeds_v2/commissioning	2012-06-19 16:19:20 +0000
@@ -0,0 +1,2 @@
+{{preseed_data}}
+cloud-init   cloud-init/local-cloud-config string manage_etc_hosts: localhost

=== added file 'contrib/preseeds_v2/enlist'
--- contrib/preseeds_v2/enlist	1970-01-01 00:00:00 +0000
+++ contrib/preseeds_v2/enlist	2012-06-19 16:19:20 +0000
@@ -0,0 +1,9 @@
+d-i preseed/early_command string anna-install maas-enlist-udeb
+d-i maas-enlist/skip-maas-discover boolean true
+d-i maas-enlist/maas-server-address string {{server_host}}
+d-i maas-enlist/host-name string
+
+d-i     mirror/country string manual
+d-i     mirror/http/hostname string archive.ubuntu.com
+d-i     mirror/http/directory string /ubuntu
+d-i     mirror/http/proxy string http://{{server_host}}:8000/

=== added file 'contrib/preseeds_v2/generic'
--- contrib/preseeds_v2/generic	1970-01-01 00:00:00 +0000
+++ contrib/preseeds_v2/generic	2012-06-19 16:19:20 +0000
@@ -0,0 +1,24 @@
+{{inherit "preseed_master"}}
+{{def proxy}}
+d-i     mirror/country string manual
+d-i     mirror/http/hostname string archive.ubuntu.com
+d-i     mirror/http/directory string /ubuntu
+d-i     mirror/http/proxy string http://{{server_host}}:8000/
+{{enddef}}
+
+{{def client_packages}}
+d-i     pkgsel/include string cloud-init openssh-server python-software-properties vim avahi-daemon server^
+{{enddef}}
+
+{{def preseed}}
+{{preseed_data}}
+cloud-init   cloud-init/local-cloud-config string manage_etc_hosts: localhost
+{{enddef}}
+
+{{def post_scripts}}
+# Executes late command and disables PXE.
+d-i	preseed/late_command string true && \
+    in-target sh -c 'f=$1; shift; echo $0 > $f && chmod 0440 $f $*' 'ubuntu ALL=(ALL) NOPASSWD: ALL' /etc/sudoers.d/maas && \
+    wget "{{node_disable_pxe_url}}" -O /dev/null && \
+    true
+{{enddef}}

=== added file 'contrib/preseeds_v2/preseed_master'
--- contrib/preseeds_v2/preseed_master	1970-01-01 00:00:00 +0000
+++ contrib/preseeds_v2/preseed_master	2012-06-19 16:19:20 +0000
@@ -0,0 +1,90 @@
+# MAAS - Ubuntu Server Installation
+# * Minimal install
+# * Cloud-init for bare-metal
+# * maas_preseed snippet is expanded to provide cloud-init preseed data
+
+# Locale
+d-i     debian-installer/locale string en_US.UTF-8
+
+# No splash
+d-i     debian-installer/splash boolean false
+
+# Keyboard layout
+d-i     console-setup/ask_detect        boolean false
+d-i     console-setup/layoutcode        string us
+d-i     console-setup/variantcode       string
+
+# Network configuration
+d-i     netcfg/get_nameservers  string
+d-i     netcfg/get_ipaddress    string
+d-i     netcfg/get_netmask      string 255.255.255.0
+d-i     netcfg/get_gateway      string
+d-i     netcfg/confirm_static   boolean true
+
+# Local clock (set to UTC and use ntp)
+d-i     clock-setup/utc boolean true
+d-i     clock-setup/ntp boolean true
+d-i     clock-setup/ntp-server  string ntp.ubuntu.com
+
+# Partitioning
+d-i     partman/early_command string debconf-set partman-auto/disk `list-devices disk | head -n1`
+d-i     partman-iscsi/mainmenu string finish
+d-i     partman-auto/method string regular
+d-i     partman-lvm/device_remove_lvm boolean true
+d-i     partman-lvm/confirm boolean true
+d-i     partman/confirm_write_new_label boolean true
+d-i     partman/choose_partition        select Finish partitioning and write changes to disk
+d-i     partman/confirm boolean true
+d-i     partman/confirm_nooverwrite boolean true
+d-i     partman/default_filesystem string ext4
+
+# Use server kernel
+d-i     base-installer/kernel/image     string linux-server
+
+# User Setup
+d-i	passwd/root-login	boolean false
+d-i	passwd/make-user	boolean true
+d-i	passwd/user-fullname	string ubuntu
+d-i	passwd/username	string ubuntu
+d-i	passwd/user-password-crypted password !
+d-i	passwd/user-uid	string
+d-i	user-setup/allow-password-weak	boolean false
+d-i	user-setup/encrypt-home	boolean false
+d-i	passwd/user-default-groups	string adm cdrom dialout lpadmin plugdev sambashare
+
+# APT
+{{self.proxy}}
+
+# By default the installer requires that repositories be authenticated
+# using a known gpg key. This setting can be used to disable that
+# authentication. Warning: Insecure, not recommended.
+d-i debian-installer/allow_unauthenticated string false
+
+# Lang
+d-i     pkgsel/language-packs   multiselect en
+d-i     pkgsel/update-policy    select none
+d-i     pkgsel/updatedb boolean true
+
+# Boot-loader
+d-i     grub-installer/skip     boolean false
+d-i     lilo-installer/skip     boolean false
+d-i     grub-installer/only_debian      boolean true
+d-i     grub-installer/with_other_os    boolean true
+d-i     finish-install/keep-consoles    boolean false
+d-i     finish-install/reboot_in_progress       note
+
+# Eject cdrom
+d-i     cdrom-detect/eject      boolean true
+
+# Do not halt/poweroff after install
+d-i     debian-installer/exit/halt      boolean false
+d-i     debian-installer/exit/poweroff  boolean false
+
+# maas client packages
+{{self.client_packages}}
+
+# maas preseed
+{{self.preseed}}
+
+# Post scripts.
+{{self.post_scripts}}

=== modified file 'src/maas/development.py'
--- src/maas/development.py	2012-06-19 16:19:20 +0000
+++ src/maas/development.py	2012-06-19 16:19:20 +0000
@@ -86,7 +86,7 @@
 # Use in-branch preseed templates.
 PRESEED_TEMPLATE_LOCATIONS = (
     abspath("etc/preseeds"),
-    abspath("contrib/preseeds"),
+    abspath("contrib/preseeds_v2"),
     )
 
 # Allow the user to override settings in maas_local_settings.

=== modified file 'src/maasserver/preseed.py'
--- src/maasserver/preseed.py	2012-06-19 16:19:20 +0000
+++ src/maasserver/preseed.py	2012-06-19 16:19:20 +0000
@@ -13,8 +13,11 @@
 __all__ = []
 
 from os.path import join
+from urlparse import urlparse
 
 from django.conf import settings
+from maasserver.models import Config
+from maasserver.provisioning import compose_preseed
 import tempita
 
 
@@ -22,7 +25,7 @@
 
 
 # XXX: rvb 2012-06-14 bug=1013146:  'precise' is hardcoded here.
-def get_preseed_filenames(node, prefix, release='precise', default=False):
+def get_preseed_filenames(node, prefix='', release='precise', default=False):
     """List possible preseed template filenames for the given node.
 
     :param node: The node to return template preseed filenames for.
@@ -46,7 +49,10 @@
     'generic'
     """
     arch = split_subarch(node.architecture)
-    elements = [prefix] + arch + [release, node.hostname]
+    elements = []
+    if prefix != '':
+        elements.append(prefix)
+    elements.extend(arch + [release, node.hostname])
     while elements:
         yield compose_filename(elements)
         elements.pop()
@@ -120,3 +126,45 @@
             content, name=filepath, get_template=get_template)
 
     return get_template(prefix, None, default=True)
+
+
+def get_maas_server_host():
+    """Return MAAS' server name."""
+    maas_url = Config.objects.get_config('maas_url')
+    return urlparse(maas_url).netloc.split(':')[0]
+
+
+# XXX: rvb 2012-06-19 bug=1013146:  'precise' is hardcoded here.
+def get_preseed_context(node, release="precise"):
+    """Return the context dictionary to be used to render preseed templates
+    for this node.
+
+    :param node: See `get_preseed_filenames`.
+    :param prefix: See `get_preseed_filenames`.
+    :param release: See `get_preseed_filenames`.
+    :return: The context dictionary.
+    :rtype: dict.
+    """
+    server_host = ''
+    return {
+        'node': node,
+        'release': release,
+        'server_host': server_host,
+        'preseed_data': compose_preseed(node),
+        'node_disable_pxe_url': '',  # TODO.
+    }
+
+
+# XXX: rvb 2012-06-19 bug=1013146:  'precise' is hardcoded here.
+def render_preseed(node, prefix, release="precise"):
+    """Find and load a `PreseedTemplate` for the given node.
+
+    :param node: See `get_preseed_filenames`.
+    :param prefix: See `get_preseed_filenames`.
+    :param release: See `get_preseed_filenames`.
+    :return: The rendered preseed string.
+    :rtype: basestring.
+    """
+    template = load_preseed_template(node, prefix, release)
+    context = get_preseed_context(node, release)
+    return template.substitute(**context)

=== modified file 'src/maasserver/tests/test_preseed.py'
--- src/maasserver/tests/test_preseed.py	2012-06-19 16:19:20 +0000
+++ src/maasserver/tests/test_preseed.py	2012-06-19 16:19:20 +0000
@@ -15,12 +15,16 @@
 import os
 
 from django.conf import settings
+from maasserver.models import Config
 from maasserver.preseed import (
     GENERIC_FILENAME,
+    get_maas_server_host,
+    get_preseed_context,
     get_preseed_filenames,
     get_preseed_template,
     load_preseed_template,
     PreseedTemplate,
+    render_preseed,
     split_subarch,
     TemplateNotFoundError,
     )
@@ -82,6 +86,18 @@
             ],
             list(get_preseed_filenames(node, prefix, release, default=True)))
 
+    def test_get_preseed_filenames_supports_empty_prefix(self):
+        hostname = factory.getRandomString()
+        release = factory.getRandomString()
+        node = factory.make_node(hostname=hostname)
+        self.assertSequenceEqual(
+            [
+                '%s_%s_%s' % (node.architecture, release, hostname),
+                '%s_%s' % (node.architecture, release),
+                '%s' % node.architecture,
+            ],
+            list(get_preseed_filenames(node, '', release)))
+
     def test_get_preseed_filenames_returns_list_without_default(self):
         # If default=False is passed to get_preseed_filenames, the
         # returned list won't include the default template name as a
@@ -264,3 +280,52 @@
         template = load_preseed_template(node, prefix)
         self.assertRaises(
             TemplateNotFoundError, template.substitute)
+
+
+class TestGetMAASServerHost(TestCase):
+    """Tests for `get_maas_server_host`."""
+
+    def test_get_maas_server_host_returns_host(self):
+        Config.objects.set_config('maas_url', 'http://example.com/path')
+        self.assertEqual('example.com', get_maas_server_host())
+
+    def test_get_maas_server_host_strips_out_port(self):
+        Config.objects.set_config(
+            'maas_url', 'http://example.com:%d' % factory.getRandomPort())
+        self.assertEqual('example.com', get_maas_server_host())
+
+
+class TestPreseedContext(TestCase):
+    """Tests for `get_preseed_context`."""
+
+    def test_get_preseed_context_contains_keys(self):
+        node = factory.make_node()
+        release = factory.getRandomString()
+        context = get_preseed_context(node, release)
+        self.assertItemsEqual(
+            ['node', 'release', 'server_host', 'preseed_data',
+             'node_disable_pxe_url'],
+            context)
+
+
+class TestRenderPreseed(TestCase):
+    """Tests for `render_preseed`.
+
+    These tests check that the templates render (i.e. that no variable is
+    missing) and 'look right'.
+    """
+
+    def test_render_default_preseed(self):
+        node = factory.make_node()
+        preseed = render_preseed(node, factory.getRandomString(), "precise")
+        self.assertIn('preseed/late_command', preseed)
+
+    def test_render_enlist_preseed(self):
+        node = factory.make_node()
+        preseed = render_preseed(node, 'enlist', "precise")
+        self.assertIn('maas-enlist-udeb', preseed)
+
+    def test_render_commissioning_preseed(self):
+        node = factory.make_node()
+        preseed = render_preseed(node, 'commissioning', "precise")
+        self.assertIn('cloud-init', preseed)