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
=== modified file 'src/provisioningserver/drivers/osystem/__init__.py'
--- src/provisioningserver/drivers/osystem/__init__.py 2014-09-29 13:22:44 +0000
+++ src/provisioningserver/drivers/osystem/__init__.py 2014-09-30 09:56:10 +0000
@@ -194,6 +194,31 @@
194 """194 """
195 raise NotImplementedError()195 raise NotImplementedError()
196196
197 def compose_curtin_network_preseed(interfaces, ips_mapping,
198 gateways_mapping, disable_ipv4=False):
199 """Compose a Curtin preseed to configure a node's networking.
200
201 :param interfaces: A list of tuples, each a pair of an interface name
202 and a MAC address. If supported, the resulting preseed will assign
203 these interface names to these MAC addresses.
204 :param ips_mapping: A dict mapping MAC addresses to iterables of the
205 corresponding network interfaces' IP addresses (up to one each for
206 IPv4 and IPv6). If supported, the resulting preseed will configure
207 the network interface corresponding to each MAC to have the given
208 IP addresses. By default, DHCP is available for IPv4 and will
209 provide the same addresses, so the caller may choose not to
210 configure those in this way.
211 :param gateways_mapping: A dict mapping MAC addresses to iterables of
212 default gateways (up to one each for IPv4 and IPv6). If supported,
213 the resulting preseed will configure the network interface
214 corresponding to each MAC to use the given default gateways.
215 :param disable_ipv4: Should this node be installed without IPv4
216 networking?
217 :return: A list of dicts that can be JSON-encoded and submitted to
218 Curtin as preseeds, perhaps in combination with other preseeds.
219 """
220 return []
221
197 def get_xinstall_parameters(self, arch, subarch, release, label):222 def get_xinstall_parameters(self, arch, subarch, release, label):
198 """Return the xinstall image name and type for this operating system.223 """Return the xinstall image name and type for this operating system.
199224
200225
=== modified file 'src/provisioningserver/drivers/osystem/tests/test_ubuntu.py'
--- src/provisioningserver/drivers/osystem/tests/test_ubuntu.py 2014-09-20 15:48:39 +0000
+++ src/provisioningserver/drivers/osystem/tests/test_ubuntu.py 2014-09-30 09:56:10 +0000
@@ -19,9 +19,20 @@
1919
20from distro_info import UbuntuDistroInfo20from distro_info import UbuntuDistroInfo
21from maastesting.factory import factory21from maastesting.factory import factory
22from maastesting.matchers import MockAnyCall
22from maastesting.testcase import MAASTestCase23from maastesting.testcase import MAASTestCase
23from provisioningserver.drivers.osystem import BOOT_IMAGE_PURPOSE24from provisioningserver.drivers.osystem import BOOT_IMAGE_PURPOSE
25from provisioningserver.drivers.osystem.debian_networking import (
26 compose_network_interfaces,
27 )
24from provisioningserver.drivers.osystem.ubuntu import UbuntuOS28from provisioningserver.drivers.osystem.ubuntu import UbuntuOS
29import provisioningserver.drivers.osystem.ubuntu as ubuntu_module
30from provisioningserver.udev import compose_network_interfaces_udev_rules
31from testtools.matchers import (
32 AllMatch,
33 HasLength,
34 IsInstance,
35 )
2536
2637
27class TestUbuntuOS(MAASTestCase):38class TestUbuntuOS(MAASTestCase):
@@ -77,3 +88,59 @@
77 self.assertEqual(88 self.assertEqual(
78 osystem.get_release_title(release),89 osystem.get_release_title(release),
79 self.get_release_title(release))90 self.get_release_title(release))
91
92
93class TestComposeCurtinNetworkPreseed(MAASTestCase):
94
95 def test__returns_list_of_dicts(self):
96 preseed = UbuntuOS().compose_curtin_network_preseed([], {}, {})
97 self.assertIsInstance(preseed, list)
98 self.assertThat(preseed, HasLength(2))
99 [write_files, late_commands] = preseed
100
101 self.assertIsInstance(write_files, dict)
102 self.assertIn('write_files', write_files)
103 self.assertIsInstance(write_files['write_files'], dict)
104 self.assertThat(
105 write_files['write_files'].values(),
106 AllMatch(IsInstance(dict)))
107
108 self.assertIsInstance(late_commands, dict)
109 self.assertIn('late_commands', late_commands)
110 self.assertIsInstance(late_commands['late_commands'], dict)
111 self.assertThat(
112 late_commands['late_commands'].values(),
113 AllMatch(IsInstance(list)))
114
115 def test__installs_and_moves_network_interfaces_file(self):
116 interfaces_file = compose_network_interfaces([], {}, {})
117 write_text_file = self.patch_autospec(
118 ubuntu_module, 'compose_write_text_file')
119 mv_command = self.patch_autospec(ubuntu_module, 'compose_mv_command')
120
121 UbuntuOS().compose_curtin_network_preseed([], {}, {})
122
123 temp_path = '/tmp/maas-etc-network-interfaces'
124 self.expectThat(
125 write_text_file,
126 MockAnyCall(temp_path, interfaces_file, permissions=0644))
127 self.expectThat(
128 mv_command,
129 MockAnyCall(temp_path, '/etc/network/interfaces'))
130
131 def test__installs_and_moves_udev_rules_file(self):
132 udev_file = compose_network_interfaces_udev_rules([])
133 write_text_file = self.patch_autospec(
134 ubuntu_module, 'compose_write_text_file')
135 mv_command = self.patch_autospec(ubuntu_module, 'compose_mv_command')
136
137 UbuntuOS().compose_curtin_network_preseed([], {}, {})
138
139 temp_path = '/tmp/maas-udev-70-persistent-net.rules'
140 self.expectThat(
141 write_text_file,
142 MockAnyCall(temp_path, udev_file, permissions=0644))
143 self.expectThat(
144 mv_command,
145 MockAnyCall(
146 temp_path, '/etc/udev/rules.d/70-persistent-net.rules'))
80147
=== modified file 'src/provisioningserver/drivers/osystem/ubuntu.py'
--- src/provisioningserver/drivers/osystem/ubuntu.py 2014-09-22 15:16:20 +0000
+++ src/provisioningserver/drivers/osystem/ubuntu.py 2014-09-30 09:56:10 +0000
@@ -21,6 +21,14 @@
21 BOOT_IMAGE_PURPOSE,21 BOOT_IMAGE_PURPOSE,
22 OperatingSystem,22 OperatingSystem,
23 )23 )
24from provisioningserver.drivers.osystem.debian_networking import (
25 compose_network_interfaces,
26 )
27from provisioningserver.udev import compose_network_interfaces_udev_rules
28from provisioningserver.utils.curtin import (
29 compose_mv_command,
30 compose_write_text_file,
31 )
2432
2533
26class UbuntuOS(OperatingSystem):34class UbuntuOS(OperatingSystem):
@@ -81,3 +89,39 @@
81 if row is None:89 if row is None:
82 return None90 return None
83 return UbuntuDistroInfo()._format("fullname", row)91 return UbuntuDistroInfo()._format("fullname", row)
92
93 def compose_curtin_network_preseed(self, interfaces, ips_mapping,
94 gateways_mapping, disable_ipv4=False):
95 """As defined in `OperatingSystem`: generate networking Curtin preseed.
96
97 Supports:
98 * Static IPv6 address and gateway configuration.
99 * DHCP-based IPv4 configuration.
100 * Assigning network interface names through udev rules.
101 * Disabling IPv4.
102 """
103 interfaces_file = compose_network_interfaces(
104 interfaces, ips_mapping=ips_mapping,
105 gateways_mapping=gateways_mapping, disable_ipv4=disable_ipv4)
106 udev_rules = compose_network_interfaces_udev_rules(interfaces)
107 write_files = {
108 'write_files': {
109 'etc_network_interfaces': compose_write_text_file(
110 '/tmp/maas-etc-network-interfaces', interfaces_file,
111 permissions=0644),
112 'udev_persistent_net': compose_write_text_file(
113 '/tmp/maas-udev-70-persistent-net.rules', udev_rules,
114 permissions=0644),
115 },
116 }
117 late_commands = {
118 'late_commands': {
119 'etc_network_interfaces': compose_mv_command(
120 '/tmp/maas-etc-network-interfaces',
121 '/etc/network/interfaces'),
122 'udev_persistent_net': compose_mv_command(
123 '/tmp/maas-udev-70-persistent-net.rules',
124 '/etc/udev/rules.d/70-persistent-net.rules')
125 },
126 }
127 return [write_files, late_commands]