Merge lp:~jtv/maas/ubuntu-generate-networking-curtin-preseed 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: 3138
Proposed branch: lp:~jtv/maas/ubuntu-generate-networking-curtin-preseed
Merge into: lp:~maas-committers/maas/trunk
Prerequisite: lp:~jtv/maas/move-etc-network-interfaces-code
Diff against target: 179 lines (+136/-0)
3 files modified
src/provisioningserver/drivers/osystem/__init__.py (+25/-0)
src/provisioningserver/drivers/osystem/tests/test_ubuntu.py (+67/-0)
src/provisioningserver/drivers/osystem/ubuntu.py (+44/-0)
To merge this branch: bzr merge lp:~jtv/maas/ubuntu-generate-networking-curtin-preseed
Reviewer Review Type Date Requested Status
Graham Binns (community) Approve
Review via email: mp+236478@code.launchpad.net

Commit message

Implement method for generating network preseed on Ubuntu. The other operating systems will return an empty list, meaning that they rely entirely on DHCP for configuring network interfaces.

This call is to be made available to the region controller through RPC.

Description of the change

The region controller will add the resulting preseeds to the ones it sends to Curtin when installing the node.

Jeroen

To post a comment you must log in.
Revision history for this message
Graham Binns (gmb) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/provisioningserver/drivers/osystem/__init__.py'
2--- src/provisioningserver/drivers/osystem/__init__.py 2014-09-29 13:22:44 +0000
3+++ src/provisioningserver/drivers/osystem/__init__.py 2014-09-30 09:56:10 +0000
4@@ -194,6 +194,31 @@
5 """
6 raise NotImplementedError()
7
8+ def compose_curtin_network_preseed(interfaces, ips_mapping,
9+ gateways_mapping, disable_ipv4=False):
10+ """Compose a Curtin preseed to configure a node's networking.
11+
12+ :param interfaces: A list of tuples, each a pair of an interface name
13+ and a MAC address. If supported, the resulting preseed will assign
14+ these interface names to these MAC addresses.
15+ :param ips_mapping: A dict mapping MAC addresses to iterables of the
16+ corresponding network interfaces' IP addresses (up to one each for
17+ IPv4 and IPv6). If supported, the resulting preseed will configure
18+ the network interface corresponding to each MAC to have the given
19+ IP addresses. By default, DHCP is available for IPv4 and will
20+ provide the same addresses, so the caller may choose not to
21+ configure those in this way.
22+ :param gateways_mapping: A dict mapping MAC addresses to iterables of
23+ default gateways (up to one each for IPv4 and IPv6). If supported,
24+ the resulting preseed will configure the network interface
25+ corresponding to each MAC to use the given default gateways.
26+ :param disable_ipv4: Should this node be installed without IPv4
27+ networking?
28+ :return: A list of dicts that can be JSON-encoded and submitted to
29+ Curtin as preseeds, perhaps in combination with other preseeds.
30+ """
31+ return []
32+
33 def get_xinstall_parameters(self, arch, subarch, release, label):
34 """Return the xinstall image name and type for this operating system.
35
36
37=== modified file 'src/provisioningserver/drivers/osystem/tests/test_ubuntu.py'
38--- src/provisioningserver/drivers/osystem/tests/test_ubuntu.py 2014-09-20 15:48:39 +0000
39+++ src/provisioningserver/drivers/osystem/tests/test_ubuntu.py 2014-09-30 09:56:10 +0000
40@@ -19,9 +19,20 @@
41
42 from distro_info import UbuntuDistroInfo
43 from maastesting.factory import factory
44+from maastesting.matchers import MockAnyCall
45 from maastesting.testcase import MAASTestCase
46 from provisioningserver.drivers.osystem import BOOT_IMAGE_PURPOSE
47+from provisioningserver.drivers.osystem.debian_networking import (
48+ compose_network_interfaces,
49+ )
50 from provisioningserver.drivers.osystem.ubuntu import UbuntuOS
51+import provisioningserver.drivers.osystem.ubuntu as ubuntu_module
52+from provisioningserver.udev import compose_network_interfaces_udev_rules
53+from testtools.matchers import (
54+ AllMatch,
55+ HasLength,
56+ IsInstance,
57+ )
58
59
60 class TestUbuntuOS(MAASTestCase):
61@@ -77,3 +88,59 @@
62 self.assertEqual(
63 osystem.get_release_title(release),
64 self.get_release_title(release))
65+
66+
67+class TestComposeCurtinNetworkPreseed(MAASTestCase):
68+
69+ def test__returns_list_of_dicts(self):
70+ preseed = UbuntuOS().compose_curtin_network_preseed([], {}, {})
71+ self.assertIsInstance(preseed, list)
72+ self.assertThat(preseed, HasLength(2))
73+ [write_files, late_commands] = preseed
74+
75+ self.assertIsInstance(write_files, dict)
76+ self.assertIn('write_files', write_files)
77+ self.assertIsInstance(write_files['write_files'], dict)
78+ self.assertThat(
79+ write_files['write_files'].values(),
80+ AllMatch(IsInstance(dict)))
81+
82+ self.assertIsInstance(late_commands, dict)
83+ self.assertIn('late_commands', late_commands)
84+ self.assertIsInstance(late_commands['late_commands'], dict)
85+ self.assertThat(
86+ late_commands['late_commands'].values(),
87+ AllMatch(IsInstance(list)))
88+
89+ def test__installs_and_moves_network_interfaces_file(self):
90+ interfaces_file = compose_network_interfaces([], {}, {})
91+ write_text_file = self.patch_autospec(
92+ ubuntu_module, 'compose_write_text_file')
93+ mv_command = self.patch_autospec(ubuntu_module, 'compose_mv_command')
94+
95+ UbuntuOS().compose_curtin_network_preseed([], {}, {})
96+
97+ temp_path = '/tmp/maas-etc-network-interfaces'
98+ self.expectThat(
99+ write_text_file,
100+ MockAnyCall(temp_path, interfaces_file, permissions=0644))
101+ self.expectThat(
102+ mv_command,
103+ MockAnyCall(temp_path, '/etc/network/interfaces'))
104+
105+ def test__installs_and_moves_udev_rules_file(self):
106+ udev_file = compose_network_interfaces_udev_rules([])
107+ write_text_file = self.patch_autospec(
108+ ubuntu_module, 'compose_write_text_file')
109+ mv_command = self.patch_autospec(ubuntu_module, 'compose_mv_command')
110+
111+ UbuntuOS().compose_curtin_network_preseed([], {}, {})
112+
113+ temp_path = '/tmp/maas-udev-70-persistent-net.rules'
114+ self.expectThat(
115+ write_text_file,
116+ MockAnyCall(temp_path, udev_file, permissions=0644))
117+ self.expectThat(
118+ mv_command,
119+ MockAnyCall(
120+ temp_path, '/etc/udev/rules.d/70-persistent-net.rules'))
121
122=== modified file 'src/provisioningserver/drivers/osystem/ubuntu.py'
123--- src/provisioningserver/drivers/osystem/ubuntu.py 2014-09-22 15:16:20 +0000
124+++ src/provisioningserver/drivers/osystem/ubuntu.py 2014-09-30 09:56:10 +0000
125@@ -21,6 +21,14 @@
126 BOOT_IMAGE_PURPOSE,
127 OperatingSystem,
128 )
129+from provisioningserver.drivers.osystem.debian_networking import (
130+ compose_network_interfaces,
131+ )
132+from provisioningserver.udev import compose_network_interfaces_udev_rules
133+from provisioningserver.utils.curtin import (
134+ compose_mv_command,
135+ compose_write_text_file,
136+ )
137
138
139 class UbuntuOS(OperatingSystem):
140@@ -81,3 +89,39 @@
141 if row is None:
142 return None
143 return UbuntuDistroInfo()._format("fullname", row)
144+
145+ def compose_curtin_network_preseed(self, interfaces, ips_mapping,
146+ gateways_mapping, disable_ipv4=False):
147+ """As defined in `OperatingSystem`: generate networking Curtin preseed.
148+
149+ Supports:
150+ * Static IPv6 address and gateway configuration.
151+ * DHCP-based IPv4 configuration.
152+ * Assigning network interface names through udev rules.
153+ * Disabling IPv4.
154+ """
155+ interfaces_file = compose_network_interfaces(
156+ interfaces, ips_mapping=ips_mapping,
157+ gateways_mapping=gateways_mapping, disable_ipv4=disable_ipv4)
158+ udev_rules = compose_network_interfaces_udev_rules(interfaces)
159+ write_files = {
160+ 'write_files': {
161+ 'etc_network_interfaces': compose_write_text_file(
162+ '/tmp/maas-etc-network-interfaces', interfaces_file,
163+ permissions=0644),
164+ 'udev_persistent_net': compose_write_text_file(
165+ '/tmp/maas-udev-70-persistent-net.rules', udev_rules,
166+ permissions=0644),
167+ },
168+ }
169+ late_commands = {
170+ 'late_commands': {
171+ 'etc_network_interfaces': compose_mv_command(
172+ '/tmp/maas-etc-network-interfaces',
173+ '/etc/network/interfaces'),
174+ 'udev_persistent_net': compose_mv_command(
175+ '/tmp/maas-udev-70-persistent-net.rules',
176+ '/etc/udev/rules.d/70-persistent-net.rules')
177+ },
178+ }
179+ return [write_files, late_commands]