Merge lp:~jtv/maas/curtin-copy 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: 3368
Proposed branch: lp:~jtv/maas/curtin-copy
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 199 lines (+63/-34)
4 files modified
src/provisioningserver/drivers/osystem/tests/test_ubuntu.py (+19/-13)
src/provisioningserver/drivers/osystem/ubuntu.py (+5/-10)
src/provisioningserver/utils/curtin.py (+11/-7)
src/provisioningserver/utils/tests/test_curtin.py (+28/-4)
To merge this branch: bzr merge lp:~jtv/maas/curtin-copy
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Review via email: mp+241609@code.launchpad.net

Commit message

Change the way network preseeds are installed in Curtin: instead of writing /etc files to individual temporary locations and then moving them into place individually, write them all to one /tmp/maas/etc/ and copy the whole directory tree in one go.

Description of the change

This is preparation for a change that writes each network interface's configuration to a separate fragment file in /etc/network/interfaces.d. Splitting up the job makes for easier reviewing, more confident progress, and more targeted Q/A. The new approach works on my test rig.

Jeroen

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) wrote :

This will need release-noting, as the last time we changed the curtin preseed we had a couple of complaints about clashing changes.

Otherwise, good stuff, this makes far more sense than the old way! Nits inline to prove I read it all.

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

This does not change the Curtin preseed yet, but the next branch will. What you see here is just a different way of getting (parts of) it onto the installed system.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/provisioningserver/drivers/osystem/tests/test_ubuntu.py'
2--- src/provisioningserver/drivers/osystem/tests/test_ubuntu.py 2014-10-01 03:58:43 +0000
3+++ src/provisioningserver/drivers/osystem/tests/test_ubuntu.py 2014-11-13 08:19:50 +0000
4@@ -28,6 +28,7 @@
5 from provisioningserver.drivers.osystem.ubuntu import UbuntuOS
6 import provisioningserver.drivers.osystem.ubuntu as ubuntu_module
7 from provisioningserver.udev import compose_network_interfaces_udev_rules
8+from provisioningserver.utils.curtin import compose_recursive_copy
9 from testtools.matchers import (
10 AllMatch,
11 HasLength,
12@@ -92,6 +93,13 @@
13
14 class TestComposeCurtinNetworkPreseed(MAASTestCase):
15
16+ def find_preseed(self, preseeds, key):
17+ """Extract from list of `preseeds` the first one containing `key`."""
18+ for preseed in preseeds:
19+ if key in preseed:
20+ return preseed
21+ return None
22+
23 def test__returns_list_of_dicts(self):
24 preseed = UbuntuOS().compose_curtin_network_preseed([], [], {}, {})
25 self.assertIsInstance(preseed, list)
26@@ -112,35 +120,33 @@
27 late_commands['late_commands'].values(),
28 AllMatch(IsInstance(list)))
29
30- def test__installs_and_moves_network_interfaces_file(self):
31+ def test__writes_network_interfaces_file(self):
32 interfaces_file = compose_network_interfaces([], [], {}, {})
33 write_text_file = self.patch_autospec(
34 ubuntu_module, 'compose_write_text_file')
35- mv_command = self.patch_autospec(ubuntu_module, 'compose_mv_command')
36
37 UbuntuOS().compose_curtin_network_preseed([], [], {}, {})
38
39- temp_path = '/tmp/maas-etc-network-interfaces'
40+ temp_path = '/tmp/maas/etc/network/interfaces'
41 self.expectThat(
42 write_text_file,
43 MockAnyCall(temp_path, interfaces_file, permissions=0644))
44- self.expectThat(
45- mv_command,
46- MockAnyCall(temp_path, '/etc/network/interfaces'))
47
48- def test__installs_and_moves_udev_rules_file(self):
49+ def test__writes_udev_rules_file(self):
50 udev_file = compose_network_interfaces_udev_rules([])
51 write_text_file = self.patch_autospec(
52 ubuntu_module, 'compose_write_text_file')
53- mv_command = self.patch_autospec(ubuntu_module, 'compose_mv_command')
54
55 UbuntuOS().compose_curtin_network_preseed([], [], {}, {})
56
57- temp_path = '/tmp/maas-udev-70-persistent-net.rules'
58+ temp_path = '/tmp/maas/etc/udev/rules.d/70-persistent-net.rules'
59 self.expectThat(
60 write_text_file,
61 MockAnyCall(temp_path, udev_file, permissions=0644))
62- self.expectThat(
63- mv_command,
64- MockAnyCall(
65- temp_path, '/etc/udev/rules.d/70-persistent-net.rules'))
66+
67+ def test__copies_temp_etc_to_real_etc(self):
68+ preseed = UbuntuOS().compose_curtin_network_preseed([], [], {}, {})
69+ late_commands = self.find_preseed(preseed, 'late_commands')
70+ self.assertEqual(
71+ {'copy_etc': compose_recursive_copy('/tmp/maas/etc', '/')},
72+ late_commands['late_commands'])
73
74=== modified file 'src/provisioningserver/drivers/osystem/ubuntu.py'
75--- src/provisioningserver/drivers/osystem/ubuntu.py 2014-10-10 06:24:35 +0000
76+++ src/provisioningserver/drivers/osystem/ubuntu.py 2014-11-13 08:19:50 +0000
77@@ -26,7 +26,7 @@
78 )
79 from provisioningserver.udev import compose_network_interfaces_udev_rules
80 from provisioningserver.utils.curtin import (
81- compose_mv_command,
82+ compose_recursive_copy,
83 compose_write_text_file,
84 )
85
86@@ -110,21 +110,16 @@
87 write_files = {
88 'write_files': {
89 'etc_network_interfaces': compose_write_text_file(
90- '/tmp/maas-etc-network-interfaces', interfaces_file,
91+ '/tmp/maas/etc/network/interfaces', interfaces_file,
92 permissions=0644),
93 'udev_persistent_net': compose_write_text_file(
94- '/tmp/maas-udev-70-persistent-net.rules', udev_rules,
95- permissions=0644),
96+ '/tmp/maas/etc/udev/rules.d/70-persistent-net.rules',
97+ udev_rules, permissions=0644),
98 },
99 }
100 late_commands = {
101 'late_commands': {
102- 'etc_network_interfaces': compose_mv_command(
103- '/tmp/maas-etc-network-interfaces',
104- '/etc/network/interfaces'),
105- 'udev_persistent_net': compose_mv_command(
106- '/tmp/maas-udev-70-persistent-net.rules',
107- '/etc/udev/rules.d/70-persistent-net.rules')
108+ 'copy_etc': compose_recursive_copy('/tmp/maas/etc', '/'),
109 },
110 }
111 return [write_files, late_commands]
112
113=== modified file 'src/provisioningserver/utils/curtin.py'
114--- src/provisioningserver/utils/curtin.py 2014-09-29 02:50:52 +0000
115+++ src/provisioningserver/utils/curtin.py 2014-11-13 08:19:50 +0000
116@@ -14,6 +14,7 @@
117 __metaclass__ = type
118 __all__ = [
119 'compose_mv_command',
120+ 'compose_recursive_copy',
121 'compose_write_text_file',
122 ]
123
124@@ -41,11 +42,14 @@
125 as an entry in `late_commands` dict.
126 """
127 return [
128- 'curtin',
129- 'in-target',
130- '--',
131- 'mv',
132- '--',
133- source,
134- dest,
135+ 'curtin', 'in-target', '--',
136+ 'mv', '--', source, dest,
137+ ]
138+
139+
140+def compose_recursive_copy(source, dest):
141+ """Return preseed for running a recursive `cp` in the install target."""
142+ return [
143+ 'curtin', 'in-target', '--',
144+ 'cp', '-r', '-p', '--', source, dest,
145 ]
146
147=== modified file 'src/provisioningserver/utils/tests/test_curtin.py'
148--- src/provisioningserver/utils/tests/test_curtin.py 2014-09-29 02:40:27 +0000
149+++ src/provisioningserver/utils/tests/test_curtin.py 2014-11-13 08:19:50 +0000
150@@ -18,6 +18,7 @@
151 from maastesting.testcase import MAASTestCase
152 from provisioningserver.utils.curtin import (
153 compose_mv_command,
154+ compose_recursive_copy,
155 compose_write_text_file,
156 )
157 from testtools.matchers import (
158@@ -38,14 +39,37 @@
159 def test__runs_command_in_target(self):
160 command = compose_mv_command(
161 factory.make_name('source'), factory.make_name('dest'))
162- self.assertEqual(['curtin', 'in-target', '--'], command[:3])
163+ curtin_prefix = ['curtin', 'in-target', '--']
164+ self.assertEqual(curtin_prefix, command[:len(curtin_prefix)])
165
166 def test__moves_file(self):
167 source = factory.make_name('source')
168 dest = factory.make_name('dest')
169- self.assertEqual(
170- ['mv', '--', source, dest],
171- compose_mv_command(source, dest)[-4:])
172+ command = compose_mv_command(source, dest)
173+ mv_suffix = ['mv', '--', source, dest]
174+ self.assertEqual(mv_suffix, command[-len(mv_suffix):])
175+
176+
177+class TestComposeRecursiveCopy(MAASTestCase):
178+
179+ def test__returns_command_list(self):
180+ command = compose_recursive_copy(
181+ factory.make_name('source'), factory.make_name('dest'))
182+ self.expectThat(command, IsInstance(list))
183+ self.expectThat(command, AllMatch(IsInstance(unicode)))
184+
185+ def test__runs_command_in_target(self):
186+ command = compose_recursive_copy(
187+ factory.make_name('source'), factory.make_name('dest'))
188+ curtin_prefix = ['curtin', 'in-target', '--']
189+ self.assertEqual(curtin_prefix, command[:len(curtin_prefix)])
190+
191+ def test__copies(self):
192+ source = factory.make_name('source')
193+ dest = factory.make_name('dest')
194+ command = compose_recursive_copy(source, dest)
195+ cp_suffix = ['cp', '-r', '-p', '--', source, dest]
196+ self.assertEqual(cp_suffix, command[-len(cp_suffix):])
197
198
199 class TestComposeWriteTextFile(MAASTestCase):