Merge lp:~lamont/maas/bug-1564925 into lp:~maas-committers/maas/trunk
- bug-1564925
- Merge into trunk
Proposed by
LaMont Jones
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | LaMont Jones | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 4866 | ||||
Proposed branch: | lp:~lamont/maas/bug-1564925 | ||||
Merge into: | lp:~maas-committers/maas/trunk | ||||
Diff against target: |
275 lines (+63/-38) 3 files modified
src/provisioningserver/dhcp/testing/config.py (+13/-6) src/provisioningserver/dhcp/tests/test_config.py (+49/-31) src/provisioningserver/templates/dhcp/dhcpd6.conf.template (+1/-1) |
||||
To merge this branch: | bzr merge lp:~lamont/maas/bug-1564925 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Review via email: mp+290765@code.launchpad.net |
Commit message
Generate correct dhcpd6.conf configuration.
Description of the change
Generate correct dhcpd6.conf configuration.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/provisioningserver/dhcp/testing/config.py' | |||
2 | --- src/provisioningserver/dhcp/testing/config.py 2016-03-26 00:36:43 +0000 | |||
3 | +++ src/provisioningserver/dhcp/testing/config.py 2016-04-01 17:46:03 +0000 | |||
4 | @@ -40,7 +40,7 @@ | |||
5 | 40 | 40 | ||
6 | 41 | def make_host( | 41 | def make_host( |
7 | 42 | hostname=None, interface_name=None, | 42 | hostname=None, interface_name=None, |
9 | 43 | mac_address=None, ip=None, dhcp_snippets=None): | 43 | mac_address=None, ip=None, ipv6=False, dhcp_snippets=None): |
10 | 44 | """Return a host entry for a subnet from network.""" | 44 | """Return a host entry for a subnet from network.""" |
11 | 45 | if hostname is None: | 45 | if hostname is None: |
12 | 46 | hostname = factory.make_name("host") | 46 | hostname = factory.make_name("host") |
13 | @@ -49,7 +49,10 @@ | |||
14 | 49 | if mac_address is None: | 49 | if mac_address is None: |
15 | 50 | mac_address = factory.make_mac_address() | 50 | mac_address = factory.make_mac_address() |
16 | 51 | if ip is None: | 51 | if ip is None: |
18 | 52 | ip = str(factory.make_ipv4_address()) | 52 | if ipv6 is True: |
19 | 53 | ip = str(factory.make_ipv6_address()) | ||
20 | 54 | else: | ||
21 | 55 | ip = str(factory.make_ipv4_address()) | ||
22 | 53 | if dhcp_snippets is None: | 56 | if dhcp_snippets is None: |
23 | 54 | dhcp_snippets = make_dhcp_snippets() | 57 | dhcp_snippets = make_dhcp_snippets() |
24 | 55 | return { | 58 | return { |
25 | @@ -60,10 +63,14 @@ | |||
26 | 60 | } | 63 | } |
27 | 61 | 64 | ||
28 | 62 | 65 | ||
30 | 63 | def make_subnet_config(network=None, pools=None, dhcp_snippets=None): | 66 | def make_subnet_config(network=None, pools=None, ipv6=False, |
31 | 67 | dhcp_snippets=None): | ||
32 | 64 | """Return complete DHCP configuration dict for a subnet.""" | 68 | """Return complete DHCP configuration dict for a subnet.""" |
33 | 65 | if network is None: | 69 | if network is None: |
35 | 66 | network = factory.make_ipv4_network() | 70 | if ipv6 is True: |
36 | 71 | network = factory.make_ipv6_network() | ||
37 | 72 | else: | ||
38 | 73 | network = factory.make_ipv4_network() | ||
39 | 67 | if pools is None: | 74 | if pools is None: |
40 | 68 | pools = [make_subnet_pool(network)] | 75 | pools = [make_subnet_pool(network)] |
41 | 69 | if dhcp_snippets is None: | 76 | if dhcp_snippets is None: |
42 | @@ -82,13 +89,13 @@ | |||
43 | 82 | } | 89 | } |
44 | 83 | 90 | ||
45 | 84 | 91 | ||
47 | 85 | def make_shared_network(name=None, subnets=None): | 92 | def make_shared_network(name=None, subnets=None, ipv6=False): |
48 | 86 | """Return complete DHCP configuration dict for a shared network.""" | 93 | """Return complete DHCP configuration dict for a shared network.""" |
49 | 87 | if name is None: | 94 | if name is None: |
50 | 88 | name = factory.make_name("vlan") | 95 | name = factory.make_name("vlan") |
51 | 89 | if subnets is None: | 96 | if subnets is None: |
52 | 90 | subnets = [ | 97 | subnets = [ |
54 | 91 | make_subnet_config() | 98 | make_subnet_config(ipv6=ipv6) |
55 | 92 | for _ in range(3) | 99 | for _ in range(3) |
56 | 93 | ] | 100 | ] |
57 | 94 | return { | 101 | return { |
58 | 95 | 102 | ||
59 | === modified file 'src/provisioningserver/dhcp/tests/test_config.py' | |||
60 | --- src/provisioningserver/dhcp/tests/test_config.py 2016-03-26 00:36:43 +0000 | |||
61 | +++ src/provisioningserver/dhcp/tests/test_config.py 2016-04-01 17:46:03 +0000 | |||
62 | @@ -62,19 +62,19 @@ | |||
63 | 62 | """) | 62 | """) |
64 | 63 | 63 | ||
65 | 64 | 64 | ||
67 | 65 | def make_sample_params(hosts=None): | 65 | def make_sample_params(hosts=None, ipv6=False): |
68 | 66 | """Return a dict of arbitrary DHCP configuration parameters.""" | 66 | """Return a dict of arbitrary DHCP configuration parameters.""" |
69 | 67 | failover_peers = [ | 67 | failover_peers = [ |
70 | 68 | make_failover_peer_config() | 68 | make_failover_peer_config() |
71 | 69 | for _ in range(3) | 69 | for _ in range(3) |
72 | 70 | ] | 70 | ] |
73 | 71 | shared_networks = [ | 71 | shared_networks = [ |
75 | 72 | make_shared_network() | 72 | make_shared_network(ipv6=ipv6) |
76 | 73 | for _ in range(3) | 73 | for _ in range(3) |
77 | 74 | ] | 74 | ] |
78 | 75 | if hosts is None: | 75 | if hosts is None: |
79 | 76 | hosts = [ | 76 | hosts = [ |
81 | 77 | make_host() | 77 | make_host(ipv6=ipv6) |
82 | 78 | for _ in range(3) | 78 | for _ in range(3) |
83 | 79 | ] | 79 | ] |
84 | 80 | return { | 80 | return { |
85 | @@ -89,6 +89,11 @@ | |||
86 | 89 | class TestGetConfig(PservTestCase): | 89 | class TestGetConfig(PservTestCase): |
87 | 90 | """Tests for `get_config`.""" | 90 | """Tests for `get_config`.""" |
88 | 91 | 91 | ||
89 | 92 | scenarios = [ | ||
90 | 93 | ("v4", dict(template='dhcpd.conf.template', ipv6=False)), | ||
91 | 94 | ("v6", dict(template='dhcpd6.conf.template', ipv6=True)), | ||
92 | 95 | ] | ||
93 | 96 | |||
94 | 92 | def patch_template(self, name=None, template_content=sample_template): | 97 | def patch_template(self, name=None, template_content=sample_template): |
95 | 93 | """Patch the DHCP config template with the given contents. | 98 | """Patch the DHCP config template with the given contents. |
96 | 94 | 99 | ||
97 | @@ -97,7 +102,7 @@ | |||
98 | 97 | code being tested. | 102 | code being tested. |
99 | 98 | """ | 103 | """ |
100 | 99 | if name is None: | 104 | if name is None: |
102 | 100 | name = 'dhcpd.conf.template' | 105 | name = self.template |
103 | 101 | fake_root = self.make_dir() | 106 | fake_root = self.make_dir() |
104 | 102 | template_dir = path.join(fake_root, 'templates', 'dhcp') | 107 | template_dir = path.join(fake_root, 'templates', 'dhcp') |
105 | 103 | makedirs(template_dir) | 108 | makedirs(template_dir) |
106 | @@ -106,30 +111,29 @@ | |||
107 | 106 | self.patch(config, 'locate_template').return_value = template | 111 | self.patch(config, 'locate_template').return_value = template |
108 | 107 | return tempita.Template(template_content, name=template) | 112 | return tempita.Template(template_content, name=template) |
109 | 108 | 113 | ||
110 | 109 | def test__uses_branch_template_by_default(self): | ||
111 | 110 | # Since the branch comes with dhcp templates in etc/maas, we can | ||
112 | 111 | # instantiate those templates without any hackery. | ||
113 | 112 | self.assertIsNotNone( | ||
114 | 113 | config.get_config('dhcpd.conf.template', **make_sample_params())) | ||
115 | 114 | self.assertIsNotNone( | ||
116 | 115 | config.get_config('dhcpd6.conf.template', **make_sample_params())) | ||
117 | 116 | |||
118 | 117 | def test__substitutes_parameters(self): | 114 | def test__substitutes_parameters(self): |
119 | 118 | template_name = factory.make_name('template') | 115 | template_name = factory.make_name('template') |
120 | 119 | template = self.patch_template(name=template_name) | 116 | template = self.patch_template(name=template_name) |
122 | 120 | params = make_sample_params() | 117 | params = make_sample_params(ipv6=self.ipv6) |
123 | 121 | self.assertEqual( | 118 | self.assertEqual( |
124 | 122 | template.substitute(params), | 119 | template.substitute(params), |
125 | 123 | config.get_config(template_name, **params)) | 120 | config.get_config(template_name, **params)) |
126 | 124 | 121 | ||
127 | 122 | def test__uses_branch_template_by_default(self): | ||
128 | 123 | # Since the branch comes with dhcp templates in etc/maas, we can | ||
129 | 124 | # instantiate those templates without any hackery. | ||
130 | 125 | self.assertIsNotNone( | ||
131 | 126 | config.get_config( | ||
132 | 127 | self.template, **make_sample_params(ipv6=self.ipv6))) | ||
133 | 128 | |||
134 | 125 | def test__complains_if_too_few_parameters(self): | 129 | def test__complains_if_too_few_parameters(self): |
135 | 126 | template = self.patch_template() | 130 | template = self.patch_template() |
137 | 127 | params = make_sample_params() | 131 | params = make_sample_params(ipv6=self.ipv6) |
138 | 128 | del params['shared_networks'][0]['subnets'][0]['subnet'] | 132 | del params['shared_networks'][0]['subnets'][0]['subnet'] |
139 | 129 | 133 | ||
140 | 130 | e = self.assertRaises( | 134 | e = self.assertRaises( |
141 | 131 | config.DHCPConfigError, | 135 | config.DHCPConfigError, |
143 | 132 | config.get_config, 'dhcpd.conf.template', **params) | 136 | config.get_config, self.template, **params) |
144 | 133 | 137 | ||
145 | 134 | tbe = traceback.TracebackException.from_exception(e) | 138 | tbe = traceback.TracebackException.from_exception(e) |
146 | 135 | self.assertDocTestMatches( | 139 | self.assertDocTestMatches( |
147 | @@ -152,14 +156,14 @@ | |||
148 | 152 | ) | 156 | ) |
149 | 153 | 157 | ||
150 | 154 | def test__includes_compose_conditional_bootloader(self): | 158 | def test__includes_compose_conditional_bootloader(self): |
152 | 155 | params = make_sample_params() | 159 | params = make_sample_params(ipv6=self.ipv6) |
153 | 156 | bootloader = config.compose_conditional_bootloader() | 160 | bootloader = config.compose_conditional_bootloader() |
154 | 157 | self.assertThat( | 161 | self.assertThat( |
156 | 158 | config.get_config('dhcpd.conf.template', **params), | 162 | config.get_config(self.template, **params), |
157 | 159 | Contains(bootloader)) | 163 | Contains(bootloader)) |
158 | 160 | 164 | ||
159 | 161 | def test__renders_without_ntp_servers_set(self): | 165 | def test__renders_without_ntp_servers_set(self): |
161 | 162 | params = make_sample_params() | 166 | params = make_sample_params(ipv6=self.ipv6) |
162 | 163 | for network in params['shared_networks']: | 167 | for network in params['shared_networks']: |
163 | 164 | for subnet in network['subnets']: | 168 | for subnet in network['subnets']: |
164 | 165 | del subnet['ntp_server'] | 169 | del subnet['ntp_server'] |
165 | @@ -167,19 +171,19 @@ | |||
166 | 167 | rendered = template.substitute(params) | 171 | rendered = template.substitute(params) |
167 | 168 | self.assertEqual( | 172 | self.assertEqual( |
168 | 169 | rendered, | 173 | rendered, |
170 | 170 | config.get_config('dhcpd.conf.template', **params)) | 174 | config.get_config(self.template, **params)) |
171 | 171 | self.assertNotIn("ntp-servers", rendered) | 175 | self.assertNotIn("ntp-servers", rendered) |
172 | 172 | 176 | ||
173 | 173 | def test__renders_router_ip_if_present(self): | 177 | def test__renders_router_ip_if_present(self): |
175 | 174 | params = make_sample_params() | 178 | params = make_sample_params(ipv6=self.ipv6) |
176 | 175 | router_ip = factory.make_ipv4_address() | 179 | router_ip = factory.make_ipv4_address() |
177 | 176 | params['shared_networks'][0]['subnets'][0]['router_ip'] = router_ip | 180 | params['shared_networks'][0]['subnets'][0]['router_ip'] = router_ip |
178 | 177 | self.assertThat( | 181 | self.assertThat( |
180 | 178 | config.get_config('dhcpd.conf.template', **params), | 182 | config.get_config(self.template, **params), |
181 | 179 | Contains(router_ip)) | 183 | Contains(router_ip)) |
182 | 180 | 184 | ||
183 | 181 | def test__renders_with_empty_string_router_ip(self): | 185 | def test__renders_with_empty_string_router_ip(self): |
185 | 182 | params = make_sample_params() | 186 | params = make_sample_params(ipv6=self.ipv6) |
186 | 183 | for network in params['shared_networks']: | 187 | for network in params['shared_networks']: |
187 | 184 | for subnet in network['subnets']: | 188 | for subnet in network['subnets']: |
188 | 185 | subnet['router_ip'] = '' | 189 | subnet['router_ip'] = '' |
189 | @@ -187,7 +191,7 @@ | |||
190 | 187 | rendered = template.substitute(params) | 191 | rendered = template.substitute(params) |
191 | 188 | self.assertEqual( | 192 | self.assertEqual( |
192 | 189 | rendered, | 193 | rendered, |
194 | 190 | config.get_config('dhcpd.conf.template', **params)) | 194 | config.get_config(self.template, **params)) |
195 | 191 | self.assertNotIn("routers", rendered) | 195 | self.assertNotIn("routers", rendered) |
196 | 192 | 196 | ||
197 | 193 | def test__renders_with_hosts(self): | 197 | def test__renders_with_hosts(self): |
198 | @@ -196,8 +200,8 @@ | |||
199 | 196 | make_host(network) | 200 | make_host(network) |
200 | 197 | for _ in range(3) | 201 | for _ in range(3) |
201 | 198 | ] | 202 | ] |
204 | 199 | params = make_sample_params(hosts) | 203 | params = make_sample_params(hosts, ipv6=self.ipv6) |
205 | 200 | config_output = config.get_config('dhcpd.conf.template', **params) | 204 | config_output = config.get_config(self.template, **params) |
206 | 201 | self.assertThat( | 205 | self.assertThat( |
207 | 202 | config_output, | 206 | config_output, |
208 | 203 | ContainsAll([ | 207 | ContainsAll([ |
209 | @@ -218,8 +222,8 @@ | |||
210 | 218 | ])) | 222 | ])) |
211 | 219 | 223 | ||
212 | 220 | def test__renders_global_dhcp_snippets(self): | 224 | def test__renders_global_dhcp_snippets(self): |
215 | 221 | params = make_sample_params() | 225 | params = make_sample_params(ipv6=self.ipv6) |
216 | 222 | config_output = config.get_config('dhcpd.conf.template', **params) | 226 | config_output = config.get_config(self.template, **params) |
217 | 223 | self.assertThat( | 227 | self.assertThat( |
218 | 224 | config_output, | 228 | config_output, |
219 | 225 | ContainsAll([ | 229 | ContainsAll([ |
220 | @@ -228,8 +232,8 @@ | |||
221 | 228 | ])) | 232 | ])) |
222 | 229 | 233 | ||
223 | 230 | def test__renders_subnet_dhcp_snippets(self): | 234 | def test__renders_subnet_dhcp_snippets(self): |
226 | 231 | params = make_sample_params() | 235 | params = make_sample_params(ipv6=self.ipv6) |
227 | 232 | config_output = config.get_config('dhcpd.conf.template', **params) | 236 | config_output = config.get_config(self.template, **params) |
228 | 233 | for shared_network in params['shared_networks']: | 237 | for shared_network in params['shared_networks']: |
229 | 234 | for subnet in shared_network['subnets']: | 238 | for subnet in shared_network['subnets']: |
230 | 235 | self.assertThat( | 239 | self.assertThat( |
231 | @@ -240,8 +244,8 @@ | |||
232 | 240 | ])) | 244 | ])) |
233 | 241 | 245 | ||
234 | 242 | def test__renders_node_dhcp_snippets(self): | 246 | def test__renders_node_dhcp_snippets(self): |
237 | 243 | params = make_sample_params() | 247 | params = make_sample_params(ipv6=self.ipv6) |
238 | 244 | config_output = config.get_config('dhcpd.conf.template', **params) | 248 | config_output = config.get_config(self.template, **params) |
239 | 245 | for host in params['hosts']: | 249 | for host in params['hosts']: |
240 | 246 | self.assertThat( | 250 | self.assertThat( |
241 | 247 | config_output, | 251 | config_output, |
242 | @@ -250,6 +254,20 @@ | |||
243 | 250 | for dhcp_snippet in host['dhcp_snippets'] | 254 | for dhcp_snippet in host['dhcp_snippets'] |
244 | 251 | ])) | 255 | ])) |
245 | 252 | 256 | ||
246 | 257 | def test__renders_subnet_cidr(self): | ||
247 | 258 | params = make_sample_params(ipv6=self.ipv6) | ||
248 | 259 | config_output = config.get_config(self.template, **params) | ||
249 | 260 | for shared_network in params['shared_networks']: | ||
250 | 261 | for subnet in shared_network['subnets']: | ||
251 | 262 | if self.ipv6 is True: | ||
252 | 263 | expected = "subnet6 %s" % subnet['subnet_cidr'] | ||
253 | 264 | else: | ||
254 | 265 | expected = "subnet %s netmask %s" % ( | ||
255 | 266 | subnet['subnet'], subnet['subnet_mask']) | ||
256 | 267 | self.assertThat( | ||
257 | 268 | config_output, | ||
258 | 269 | Contains(expected)) | ||
259 | 270 | |||
260 | 253 | 271 | ||
261 | 254 | class TestComposeConditionalBootloader(PservTestCase): | 272 | class TestComposeConditionalBootloader(PservTestCase): |
262 | 255 | """Tests for `compose_conditional_bootloader`.""" | 273 | """Tests for `compose_conditional_bootloader`.""" |
263 | 256 | 274 | ||
264 | === modified file 'src/provisioningserver/templates/dhcp/dhcpd6.conf.template' | |||
265 | --- src/provisioningserver/templates/dhcp/dhcpd6.conf.template 2016-03-26 00:36:43 +0000 | |||
266 | +++ src/provisioningserver/templates/dhcp/dhcpd6.conf.template 2016-04-01 17:46:03 +0000 | |||
267 | @@ -45,7 +45,7 @@ | |||
268 | 45 | {{for shared_network in shared_networks}} | 45 | {{for shared_network in shared_networks}} |
269 | 46 | shared-network {{shared_network["name"]}} { | 46 | shared-network {{shared_network["name"]}} { |
270 | 47 | {{for dhcp_subnet in shared_network["subnets"]}} | 47 | {{for dhcp_subnet in shared_network["subnets"]}} |
272 | 48 | subnet6 {{dhcp_subnet['subnet']}} netmask {{dhcp_subnet['subnet_mask']}} { | 48 | subnet6 {{dhcp_subnet['subnet_cidr']}} { |
273 | 49 | ignore-client-uids true; | 49 | ignore-client-uids true; |
274 | 50 | {{if dhcp_subnet.get('dns_servers')}} | 50 | {{if dhcp_subnet.get('dns_servers')}} |
275 | 51 | option dhcp6.name-servers {{dhcp_subnet['dns_servers']}}; | 51 | option dhcp6.name-servers {{dhcp_subnet['dns_servers']}}; |
Looks good. Thanks for the quick fix. Testing was more work than fixing the bug. ;-)