Merge lp:~jtv/maas/curtin-preseed-helpers 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: 3118
Proposed branch: lp:~jtv/maas/curtin-preseed-helpers
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 156 lines (+147/-0)
2 files modified
src/provisioningserver/utils/curtin.py (+51/-0)
src/provisioningserver/utils/tests/test_curtin.py (+96/-0)
To merge this branch: bzr merge lp:~jtv/maas/curtin-preseed-helpers
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+236275@code.launchpad.net

Commit message

Two helpers that I need for generating Curtin preseeds: compose_write_text_file and compose_mv_command.

Description of the change

Part of the work for writing a node's network configuration on the server side.

Jeroen

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

I don't really know how compose_write_text_file() is going to be used, but it looks sane, as do the tests :)

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

I should have covered the basics better. This data is for passing into Curtin as a Curtin preseed — not to be confused with a cloud-init preseed, which is incredibly similar but subtly different. Most of the documentation I have is examples, so for the file permissions I just stuck to a format I knew worked.

Thanks for the review.

Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (19.1 KiB)

The attempt to merge lp:~jtv/maas/curtin-preseed-helpers into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Hit http://security.ubuntu.com trusty-security Release.gpg
Hit http://security.ubuntu.com trusty-security Release
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
Hit http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Hit http://nova.clouds.archive.ubuntu.com trusty-updates Release
Hit http://security.ubuntu.com trusty-security/main Sources
Hit http://security.ubuntu.com trusty-security/universe Sources
Hit http://security.ubuntu.com trusty-security/main amd64 Packages
Hit http://security.ubuntu.com trusty-security/universe amd64 Packages
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
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
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/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
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-openssl python-paramiko python-pexpect python-pip python-pocket-lint python-psycopg2 python-pyinotify python-seamicroclient python-simplejson python-simplestreams python-sphinx pyth...

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

Apparently unrelated failure: timeout waiting for BIND to start.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'src/provisioningserver/utils/curtin.py'
--- src/provisioningserver/utils/curtin.py 1970-01-01 00:00:00 +0000
+++ src/provisioningserver/utils/curtin.py 2014-09-29 02:51:51 +0000
@@ -0,0 +1,51 @@
1# Copyright 2014 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Utilities related to Curtin."""
5
6from __future__ import (
7 absolute_import,
8 print_function,
9 unicode_literals,
10 )
11
12str = None
13
14__metaclass__ = type
15__all__ = [
16 'compose_mv_command',
17 'compose_write_text_file',
18 ]
19
20
21def compose_write_text_file(path, content, owner='root:root',
22 permissions=0600):
23 """Return preseed for uploading a text file to the install target.
24
25 Use this to write files into the filesystem that Curtin is installing. The
26 result goes into a `write_files` preseed entry.
27 """
28 return {
29 'path': path,
30 'content': content,
31 'owner': owner,
32 'permissions': '0%o' % permissions,
33 }
34
35
36def compose_mv_command(source, dest):
37 """Return preseed for running the `mv` command in the install target.
38
39 Use this for moving files around in the filesystem that Curtin is
40 installing. The result goes in a preseed entry for running commands, such
41 as an entry in `late_commands` dict.
42 """
43 return [
44 'curtin',
45 'in-target',
46 '--',
47 'mv',
48 '--',
49 source,
50 dest,
51 ]
052
=== added file 'src/provisioningserver/utils/tests/test_curtin.py'
--- src/provisioningserver/utils/tests/test_curtin.py 1970-01-01 00:00:00 +0000
+++ src/provisioningserver/utils/tests/test_curtin.py 2014-09-29 02:51:51 +0000
@@ -0,0 +1,96 @@
1# Copyright 2014 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Tests for Curtin-related utilities."""
5
6from __future__ import (
7 absolute_import,
8 print_function,
9 unicode_literals,
10 )
11
12str = None
13
14__metaclass__ = type
15__all__ = []
16
17from maastesting.factory import factory
18from maastesting.testcase import MAASTestCase
19from provisioningserver.utils.curtin import (
20 compose_mv_command,
21 compose_write_text_file,
22 )
23from testtools.matchers import (
24 AllMatch,
25 ContainsAll,
26 IsInstance,
27 )
28
29
30class TestComposeMvCommand(MAASTestCase):
31
32 def test__returns_command_list(self):
33 command = compose_mv_command(
34 factory.make_name('source'), factory.make_name('dest'))
35 self.expectThat(command, IsInstance(list))
36 self.expectThat(command, AllMatch(IsInstance(unicode)))
37
38 def test__runs_command_in_target(self):
39 command = compose_mv_command(
40 factory.make_name('source'), factory.make_name('dest'))
41 self.assertEqual(['curtin', 'in-target', '--'], command[:3])
42
43 def test__moves_file(self):
44 source = factory.make_name('source')
45 dest = factory.make_name('dest')
46 self.assertEqual(
47 ['mv', '--', source, dest],
48 compose_mv_command(source, dest)[-4:])
49
50
51class TestComposeWriteTextFile(MAASTestCase):
52
53 def test__returns_complete_write_file_dict(self):
54 preseed = compose_write_text_file(
55 factory.make_name('file'), factory.make_name('content'))
56 self.expectThat(preseed, IsInstance(dict))
57 self.expectThat(
58 preseed.keys(),
59 ContainsAll(['path', 'content', 'owner', 'permissions']))
60
61 def test__obeys_path_param(self):
62 path = factory.make_name('path')
63 preseed = compose_write_text_file(path, factory.make_name('content'))
64 self.assertEqual(path, preseed['path'])
65
66 def test__obeys_content_param(self):
67 content = factory.make_name('content')
68 preseed = compose_write_text_file(factory.make_name('path'), content)
69 self.assertEqual(content, preseed['content'])
70
71 def test__defaults_owner_to_root(self):
72 preseed = compose_write_text_file(
73 factory.make_name('file'), factory.make_name('content'))
74 self.assertEqual('root:root', preseed['owner'])
75
76 def test__obeys_owner_param(self):
77 owner = '%s:%s' % (
78 factory.make_name('user'),
79 factory.make_name('group'),
80 )
81 preseed = compose_write_text_file(
82 factory.make_name('file'), factory.make_name('content'),
83 owner=owner)
84 self.assertEqual(owner, preseed['owner'])
85
86 def test__defaults_permissions_to_0600(self):
87 preseed = compose_write_text_file(
88 factory.make_name('file'), factory.make_name('content'))
89 self.assertEqual('0600', preseed['permissions'])
90
91 def test__obeys_permissions_param(self):
92 permissions = 0123
93 preseed = compose_write_text_file(
94 factory.make_name('file'), factory.make_name('content'),
95 permissions=permissions)
96 self.assertEqual('0123', preseed['permissions'])