Merge lp:~blake-rouse/maas/tftp-backend-readers-1.5 into lp:maas/1.5

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 2280
Proposed branch: lp:~blake-rouse/maas/tftp-backend-readers-1.5
Merge into: lp:maas/1.5
Diff against target: 633 lines (+117/-100)
10 files modified
src/provisioningserver/boot/__init__.py (+26/-6)
src/provisioningserver/boot/powerkvm.py (+3/-3)
src/provisioningserver/boot/pxe.py (+7/-4)
src/provisioningserver/boot/tests/test_boot.py (+4/-3)
src/provisioningserver/boot/tests/test_powerkvm.py (+4/-4)
src/provisioningserver/boot/tests/test_pxe.py (+23/-16)
src/provisioningserver/boot/tests/test_uefi.py (+14/-10)
src/provisioningserver/boot/uefi.py (+7/-4)
src/provisioningserver/tests/test_tftp.py (+21/-20)
src/provisioningserver/tftp.py (+8/-30)
To merge this branch: bzr merge lp:~blake-rouse/maas/tftp-backend-readers-1.5
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+221230@code.launchpad.net

Commit message

Change BootMethods to return their own IReader per-request, update method names to reflect new usage.

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/provisioningserver/boot/__init__.py'
2--- src/provisioningserver/boot/__init__.py 2014-05-23 16:32:07 +0000
3+++ src/provisioningserver/boot/__init__.py 2014-05-28 13:35:49 +0000
4@@ -23,6 +23,7 @@
5 abstractproperty,
6 )
7 from errno import ENOENT
8+from io import BytesIO
9 from os import path
10
11 from provisioningserver.boot.tftppath import compose_image_path
12@@ -30,6 +31,23 @@
13 from provisioningserver.utils import locate_config
14 from provisioningserver.utils.registry import Registry
15 import tempita
16+from tftp.backend import IReader
17+from zope.interface import implementer
18+
19+
20+@implementer(IReader)
21+class BytesReader:
22+
23+ def __init__(self, data):
24+ super(BytesReader, self).__init__()
25+ self.buffer = BytesIO(data)
26+ self.size = len(data)
27+
28+ def read(self, size):
29+ return self.buffer.read(size)
30+
31+ def finish(self):
32+ self.buffer.close()
33
34
35 class BootMethodError(Exception):
36@@ -100,22 +118,24 @@
37 """
38
39 @abstractmethod
40- def match_config_path(self, path):
41- """Checks path for the configuration file that needs to be
42- generated.
43+ def match_path(self, backend, path):
44+ """Checks path for a file the boot method needs to handle.
45
46+ :param backend: requesting backend
47 :param path: requested path
48 :returns: dict of match params from path, None if no match
49 """
50
51 @abstractmethod
52- def render_config(self, kernel_params, **extra):
53- """Render a configuration file as a unicode string.
54+ def get_reader(self, backend, kernel_params, **extra):
55+ """Gets the reader the backend will use for this combination of
56+ boot method, kernel parameters, and extra parameters.
57
58+ :param backend: requesting backend
59 :param kernel_params: An instance of `KernelParameters`.
60 :param extra: Allow for other arguments. This is a safety valve;
61 parameters generated in another component (for example, see
62- `TFTPBackend.get_config_reader`) won't cause this to break.
63+ `TFTPBackend.get_boot_method_reader`) won't cause this to break.
64 """
65
66 @abstractmethod
67
68=== modified file 'src/provisioningserver/boot/powerkvm.py'
69--- src/provisioningserver/boot/powerkvm.py 2014-05-23 16:32:07 +0000
70+++ src/provisioningserver/boot/powerkvm.py 2014-05-28 13:35:49 +0000
71@@ -45,17 +45,17 @@
72 bootloader_path = "bootppc64.bin"
73 arch_octet = "00:0C"
74
75- def match_config_path(self, path):
76+ def match_path(self, backend, path):
77 """Doesn't need to do anything, as the UEFIBootMethod provides
78 the grub implementation needed.
79 """
80 return None
81
82- def render_config(self, kernel_params, **extra):
83+ def get_reader(self, backend, kernel_params, **extra):
84 """Doesn't need to do anything, as the UEFIBootMethod provides
85 the grub implementation needed.
86 """
87- return ""
88+ return None
89
90 def install_bootloader(self, destination):
91 """Installs the required files for PowerKVM booting into the
92
93=== modified file 'src/provisioningserver/boot/pxe.py'
94--- src/provisioningserver/boot/pxe.py 2014-03-28 04:06:27 +0000
95+++ src/provisioningserver/boot/pxe.py 2014-05-28 13:35:49 +0000
96@@ -22,6 +22,7 @@
97
98 from provisioningserver.boot import (
99 BootMethod,
100+ BytesReader,
101 get_parameters,
102 )
103 from provisioningserver.boot.install_bootloader import install_bootloader
104@@ -78,10 +79,11 @@
105 bootloader_path = "pxelinux.0"
106 arch_octet = "00:00"
107
108- def match_config_path(self, path):
109+ def match_path(self, backend, path):
110 """Checks path for the configuration file that needs to be
111 generated.
112
113+ :param backend: requesting backend
114 :param path: requested path
115 :returns: dict of match params from path, None if no match
116 """
117@@ -90,19 +92,20 @@
118 return None
119 return get_parameters(match)
120
121- def render_config(self, kernel_params, **extra):
122+ def get_reader(self, backend, kernel_params, **extra):
123 """Render a configuration file as a unicode string.
124
125+ :param backend: requesting backend
126 :param kernel_params: An instance of `KernelParameters`.
127 :param extra: Allow for other arguments. This is a safety valve;
128 parameters generated in another component (for example, see
129- `TFTPBackend.get_config_reader`) won't cause this to break.
130+ `TFTPBackend.get_boot_method_reader`) won't cause this to break.
131 """
132 template = self.get_template(
133 kernel_params.purpose, kernel_params.arch,
134 kernel_params.subarch)
135 namespace = self.compose_template_namespace(kernel_params)
136- return template.substitute(namespace)
137+ return BytesReader(template.substitute(namespace).encode("utf-8"))
138
139 def install_bootloader(self, destination):
140 """Installs the required files for PXE booting into the
141
142=== modified file 'src/provisioningserver/boot/tests/test_boot.py'
143--- src/provisioningserver/boot/tests/test_boot.py 2014-03-21 19:01:40 +0000
144+++ src/provisioningserver/boot/tests/test_boot.py 2014-05-28 13:35:49 +0000
145@@ -24,6 +24,7 @@
146 from provisioningserver import boot
147 from provisioningserver.boot import (
148 BootMethod,
149+ BytesReader,
150 gen_template_filenames,
151 )
152 import tempita
153@@ -36,11 +37,11 @@
154 bootloader_path = "fake.efi"
155 arch_octet = "00:00"
156
157- def match_config_path(self, path):
158+ def match_path(self, backend, path):
159 return {}
160
161- def render_config(kernel_params, **extra):
162- return ""
163+ def get_reader(backend, kernel_params, **extra):
164+ return BytesReader("")
165
166 def install_bootloader():
167 pass
168
169=== modified file 'src/provisioningserver/boot/tests/test_powerkvm.py'
170--- src/provisioningserver/boot/tests/test_powerkvm.py 2014-05-23 16:32:07 +0000
171+++ src/provisioningserver/boot/tests/test_powerkvm.py 2014-05-28 13:35:49 +0000
172@@ -35,17 +35,17 @@
173 class TestPowerKVMBootMethod(MAASTestCase):
174 """Tests `provisioningserver.boot.powerkvm.PowerKVMBootMethod`."""
175
176- def test_match_config_path_returns_none(self):
177+ def test_match_path_returns_None(self):
178 method = PowerKVMBootMethod()
179 paths = [factory.getRandomString() for _ in range(3)]
180 for path in paths:
181- self.assertEqual(None, method.match_config_path(path))
182+ self.assertEqual(None, method.match_path(None, path))
183
184- def test_render_config_returns_empty_string(self):
185+ def test_get_reader_returns_None(self):
186 method = PowerKVMBootMethod()
187 params = [make_kernel_parameters() for _ in range(3)]
188 for param in params:
189- self.assertEqual("", method.render_config(params))
190+ self.assertEqual(None, method.get_reader(None, params))
191
192 def test_install_bootloader_get_package_raises_error(self):
193 method = PowerKVMBootMethod()
194
195=== modified file 'src/provisioningserver/boot/tests/test_pxe.py'
196--- src/provisioningserver/boot/tests/test_pxe.py 2014-03-28 04:31:32 +0000
197+++ src/provisioningserver/boot/tests/test_pxe.py 2014-05-28 13:35:49 +0000
198@@ -20,6 +20,7 @@
199 from maastesting.factory import factory
200 from maastesting.testcase import MAASTestCase
201 from provisioningserver import kernel_opts
202+from provisioningserver.boot import BytesReader
203 from provisioningserver.boot.pxe import (
204 ARP_HTYPE,
205 PXEBootMethod,
206@@ -150,14 +151,15 @@
207 class TestPXEBootMethodRenderConfig(MAASTestCase):
208 """Tests for `provisioningserver.boot.pxe.PXEBootMethod.render_config`."""
209
210- def test_render_install(self):
211+ def test_get_reader_install(self):
212 # Given the right configuration options, the PXE configuration is
213 # correctly rendered.
214 method = PXEBootMethod()
215 params = make_kernel_parameters(self, purpose="install")
216- output = method.render_config(kernel_params=params)
217- # The output is always a Unicode string.
218- self.assertThat(output, IsInstance(unicode))
219+ output = method.get_reader(backend=None, kernel_params=params)
220+ # The output is a BytesReader.
221+ self.assertThat(output, IsInstance(BytesReader))
222+ output = output.read(10000)
223 # The template has rendered without error. PXELINUX configurations
224 # typically start with a DEFAULT line.
225 self.assertThat(output, StartsWith("DEFAULT "))
226@@ -177,54 +179,58 @@
227 r'.*^\s+APPEND .+?$',
228 re.MULTILINE | re.DOTALL)))
229
230- def test_render_with_extra_arguments_does_not_affect_output(self):
231- # render_config() allows any keyword arguments as a safety valve.
232+ def test_get_reader_with_extra_arguments_does_not_affect_output(self):
233+ # get_reader() allows any keyword arguments as a safety valve.
234 method = PXEBootMethod()
235 options = {
236+ "backend": None,
237 "kernel_params": make_kernel_parameters(self, purpose="install"),
238 }
239 # Capture the output before sprinking in some random options.
240- output_before = method.render_config(**options)
241+ output_before = method.get_reader(**options).read(10000)
242 # Sprinkle some magic in.
243 options.update(
244 (factory.make_name("name"), factory.make_name("value"))
245 for _ in range(10))
246 # Capture the output after sprinking in some random options.
247- output_after = method.render_config(**options)
248+ output_after = method.get_reader(**options).read(10000)
249 # The generated template is the same.
250 self.assertEqual(output_before, output_after)
251
252- def test_render_config_with_local_purpose(self):
253+ def test_get_reader_with_local_purpose(self):
254 # If purpose is "local", the config.localboot.template should be
255 # used.
256 method = PXEBootMethod()
257 options = {
258+ "backend": None,
259 "kernel_params": make_kernel_parameters(purpose="local"),
260 }
261- output = method.render_config(**options)
262+ output = method.get_reader(**options).read(10000)
263 self.assertIn("LOCALBOOT 0", output)
264
265- def test_render_config_with_local_purpose_i386_arch(self):
266+ def test_get_reader_with_local_purpose_i386_arch(self):
267 # Intel i386 is a special case and needs to use the chain.c32
268 # loader as the LOCALBOOT PXE directive is unreliable.
269 method = PXEBootMethod()
270 options = {
271+ "backend": None,
272 "kernel_params": make_kernel_parameters(
273 arch="i386", purpose="local"),
274 }
275- output = method.render_config(**options)
276+ output = method.get_reader(**options).read(10000)
277 self.assertIn("chain.c32", output)
278 self.assertNotIn("LOCALBOOT", output)
279
280- def test_render_config_with_local_purpose_amd64_arch(self):
281+ def test_get_reader_with_local_purpose_amd64_arch(self):
282 # Intel amd64 is a special case and needs to use the chain.c32
283 # loader as the LOCALBOOT PXE directive is unreliable.
284 method = PXEBootMethod()
285 options = {
286+ "backend": None,
287 "kernel_params": make_kernel_parameters(
288 arch="amd64", purpose="local"),
289 }
290- output = method.render_config(**options)
291+ output = method.get_reader(**options).read(10000)
292 self.assertIn("chain.c32", output)
293 self.assertNotIn("LOCALBOOT", output)
294
295@@ -237,17 +243,18 @@
296 ("xinstall", dict(purpose="xinstall")),
297 ]
298
299- def test_render_config_scenarios(self):
300+ def test_get_reader_scenarios(self):
301 # The commissioning config uses an extra PXELINUX module to auto
302 # select between i386 and amd64.
303 method = PXEBootMethod()
304 get_ephemeral_name = self.patch(kernel_opts, "get_ephemeral_name")
305 get_ephemeral_name.return_value = factory.make_name("ephemeral")
306 options = {
307+ "backend": None,
308 "kernel_params": make_kernel_parameters(
309 testcase=self, subarch="generic", purpose=self.purpose),
310 }
311- output = method.render_config(**options)
312+ output = method.get_reader(**options).read(10000)
313 config = parse_pxe_config(output)
314 # The default section is defined.
315 default_section_label = config.header["DEFAULT"]
316
317=== modified file 'src/provisioningserver/boot/tests/test_uefi.py'
318--- src/provisioningserver/boot/tests/test_uefi.py 2014-05-15 17:39:27 +0000
319+++ src/provisioningserver/boot/tests/test_uefi.py 2014-05-28 13:35:49 +0000
320@@ -18,6 +18,7 @@
321
322 from maastesting.factory import factory
323 from maastesting.testcase import MAASTestCase
324+from provisioningserver.boot import BytesReader
325 from provisioningserver.boot.tftppath import compose_image_path
326 from provisioningserver.boot.uefi import (
327 re_config_file,
328@@ -60,14 +61,15 @@
329 class TestRenderUEFIConfig(MAASTestCase):
330 """Tests for `provisioningserver.boot.uefi.UEFIBootMethod`."""
331
332- def test_render(self):
333+ def test_get_reader(self):
334 # Given the right configuration options, the UEFI configuration is
335 # correctly rendered.
336 method = UEFIBootMethod()
337 params = make_kernel_parameters(purpose="install")
338- output = method.render_config(kernel_params=params)
339- # The output is always a Unicode string.
340- self.assertThat(output, IsInstance(unicode))
341+ output = method.get_reader(backend=None, kernel_params=params)
342+ # The output is a BytesReader.
343+ self.assertThat(output, IsInstance(BytesReader))
344+ output = output.read(10000)
345 # The template has rendered without error. UEFI configurations
346 # typically start with a DEFAULT line.
347 self.assertThat(output, StartsWith("set default=\"0\""))
348@@ -85,32 +87,34 @@
349 r'.*^\s+initrd %s/di-initrd$' % re.escape(image_dir),
350 re.MULTILINE | re.DOTALL)))
351
352- def test_render_with_extra_arguments_does_not_affect_output(self):
353- # render_config() allows any keyword arguments as a safety valve.
354+ def test_get_reader_with_extra_arguments_does_not_affect_output(self):
355+ # get_reader() allows any keyword arguments as a safety valve.
356 method = UEFIBootMethod()
357 options = {
358+ "backend": None,
359 "kernel_params": make_kernel_parameters(purpose="install"),
360 }
361 # Capture the output before sprinking in some random options.
362- output_before = method.render_config(**options)
363+ output_before = method.get_reader(**options).read(10000)
364 # Sprinkle some magic in.
365 options.update(
366 (factory.make_name("name"), factory.make_name("value"))
367 for _ in range(10))
368 # Capture the output after sprinking in some random options.
369- output_after = method.render_config(**options)
370+ output_after = method.get_reader(**options).read(10000)
371 # The generated template is the same.
372 self.assertEqual(output_before, output_after)
373
374- def test_render_config_with_local_purpose(self):
375+ def test_get_reader_with_local_purpose(self):
376 # If purpose is "local", the config.localboot.template should be
377 # used.
378 method = UEFIBootMethod()
379 options = {
380+ "backend": None,
381 "kernel_params": make_kernel_parameters(
382 purpose="local", arch="amd64"),
383 }
384- output = method.render_config(**options)
385+ output = method.get_reader(**options).read(10000)
386 self.assertIn("configfile /efi/ubuntu/grub.cfg", output)
387
388
389
390=== modified file 'src/provisioningserver/boot/uefi.py'
391--- src/provisioningserver/boot/uefi.py 2014-03-28 04:06:27 +0000
392+++ src/provisioningserver/boot/uefi.py 2014-05-28 13:35:49 +0000
393@@ -25,6 +25,7 @@
394 from provisioningserver.boot import (
395 BootMethod,
396 BootMethodInstallError,
397+ BytesReader,
398 get_parameters,
399 utils,
400 )
401@@ -120,10 +121,11 @@
402 bootloader_path = "bootx64.efi"
403 arch_octet = "00:07" # AMD64 EFI
404
405- def match_config_path(self, path):
406+ def match_path(self, backend, path):
407 """Checks path for the configuration file that needs to be
408 generated.
409
410+ :param backend: requesting backend
411 :param path: requested path
412 :returns: dict of match params from path, None if no match
413 """
414@@ -139,19 +141,20 @@
415
416 return params
417
418- def render_config(self, kernel_params, **extra):
419+ def get_reader(self, backend, kernel_params, **extra):
420 """Render a configuration file as a unicode string.
421
422+ :param backend: requesting backend
423 :param kernel_params: An instance of `KernelParameters`.
424 :param extra: Allow for other arguments. This is a safety valve;
425 parameters generated in another component (for example, see
426- `TFTPBackend.get_config_reader`) won't cause this to break.
427+ `TFTPBackend.get_boot_method_reader`) won't cause this to break.
428 """
429 template = self.get_template(
430 kernel_params.purpose, kernel_params.arch,
431 kernel_params.subarch)
432 namespace = self.compose_template_namespace(kernel_params)
433- return template.substitute(namespace)
434+ return BytesReader(template.substitute(namespace).encode("utf-8"))
435
436 def install_bootloader(self, destination):
437 """Installs the required files for UEFI booting into the
438
439=== modified file 'src/provisioningserver/tests/test_tftp.py'
440--- src/provisioningserver/tests/test_tftp.py 2014-03-28 06:51:59 +0000
441+++ src/provisioningserver/tests/test_tftp.py 2014-05-28 13:35:49 +0000
442@@ -28,11 +28,11 @@
443 from maastesting.testcase import MAASTestCase
444 import mock
445 from provisioningserver import tftp as tftp_module
446+from provisioningserver.boot import BytesReader
447 from provisioningserver.boot.pxe import PXEBootMethod
448 from provisioningserver.boot.tests.test_pxe import compose_config_path
449 from provisioningserver.tests.test_kernel_opts import make_kernel_parameters
450 from provisioningserver.tftp import (
451- BytesReader,
452 TFTPBackend,
453 TFTPService,
454 )
455@@ -127,9 +127,9 @@
456 self.assertEqual(b"", reader.read(1))
457
458 @inlineCallbacks
459- def test_get_reader_config_file(self):
460- # For paths matching re_config_file, TFTPBackend.get_reader() returns
461- # a Deferred that will yield a BytesReader.
462+ def test_get_render_file(self):
463+ # For paths matching PXEBootMethod.match_path, TFTPBackend.get_reader()
464+ # returns a Deferred that will yield a BytesReader.
465 cluster_uuid = factory.getRandomUUID()
466 self.patch(tftp_module, 'get_cluster_uuid').return_value = (
467 cluster_uuid)
468@@ -147,8 +147,8 @@
469 factory.getRandomPort()),
470 }
471
472- @partial(self.patch, backend, "get_config_reader")
473- def get_config_reader(boot_method, params):
474+ @partial(self.patch, backend, "get_boot_method_reader")
475+ def get_boot_method_reader(boot_method, params):
476 params_json = json.dumps(params)
477 params_json_reader = BytesReader(params_json)
478 return succeed(params_json_reader)
479@@ -168,9 +168,10 @@
480 self.assertEqual(expected_params, observed_params)
481
482 @inlineCallbacks
483- def test_get_config_reader_returns_rendered_params(self):
484- # get_config_reader() takes a dict() of parameters and returns an
485- # `IReader` of a PXE configuration, rendered by `render_pxe_config`.
486+ def test_get_boot_method_reader_returns_rendered_params(self):
487+ # get_boot_method_reader() takes a dict() of parameters and returns an
488+ # `IReader` of a PXE configuration, rendered by
489+ # `PXEBootMethod.get_reader`.
490 backend = TFTPBackend(self.make_dir(), b"http://example.com/")
491 # Fake configuration parameters, as discovered from the file path.
492 fake_params = {"mac": factory.getRandomMACAddress("-")}
493@@ -182,15 +183,15 @@
494 get_page_patch = self.patch(backend, "get_page")
495 get_page_patch.return_value = succeed(fake_get_page_result)
496
497- # Stub render_config to return the render parameters.
498+ # Stub get_reader to return the render parameters.
499 method = PXEBootMethod()
500- fake_render_result = factory.make_name("render")
501- render_patch = self.patch(method, "render_config")
502- render_patch.return_value = fake_render_result
503+ fake_render_result = factory.make_name("render").encode("utf-8")
504+ render_patch = self.patch(method, "get_reader")
505+ render_patch.return_value = BytesReader(fake_render_result)
506
507 # Get the rendered configuration, which will actually be a JSON dump
508 # of the render-time parameters.
509- reader = yield backend.get_config_reader(method, fake_params)
510+ reader = yield backend.get_boot_method_reader(method, fake_params)
511 self.addCleanup(reader.finish)
512 self.assertIsInstance(reader, BytesReader)
513 output = reader.read(10000)
514@@ -198,13 +199,13 @@
515 # The kernel parameters were fetched using `backend.get_page`.
516 self.assertThat(backend.get_page, MockCalledOnceWith(mock.ANY))
517
518- # The result has been rendered by `backend.render_config`.
519+ # The result has been rendered by `method.get_reader`.
520 self.assertEqual(fake_render_result.encode("utf-8"), output)
521- self.assertThat(method.render_config, MockCalledOnceWith(
522- kernel_params=fake_kernel_params, **fake_params))
523+ self.assertThat(method.get_reader, MockCalledOnceWith(
524+ backend, kernel_params=fake_kernel_params, **fake_params))
525
526 @inlineCallbacks
527- def test_get_config_reader_substitutes_armhf_in_params(self):
528+ def test_get_boot_method_render_substitutes_armhf_in_params(self):
529 # get_config_reader() should substitute "arm" for "armhf" in the
530 # arch field of the parameters (mapping from pxe to maas
531 # namespace).
532@@ -224,8 +225,8 @@
533 factory.getRandomPort()),
534 }
535
536- @partial(self.patch, backend, "get_config_reader")
537- def get_config_reader(boot_method, params):
538+ @partial(self.patch, backend, "get_boot_method_reader")
539+ def get_boot_method_reader(boot_method, params):
540 params_json = json.dumps(params)
541 params_json_reader = BytesReader(params_json)
542 return succeed(params_json_reader)
543
544=== modified file 'src/provisioningserver/tftp.py'
545--- src/provisioningserver/tftp.py 2014-03-28 15:17:34 +0000
546+++ src/provisioningserver/tftp.py 2014-05-28 13:35:49 +0000
547@@ -18,7 +18,6 @@
548 ]
549
550 import httplib
551-from io import BytesIO
552 import json
553 from urllib import urlencode
554 from urlparse import (
555@@ -34,10 +33,7 @@
556 deferred,
557 get_all_interface_addresses,
558 )
559-from tftp.backend import (
560- FilesystemSynchronousBackend,
561- IReader,
562- )
563+from tftp.backend import FilesystemSynchronousBackend
564 from tftp.errors import FileNotFound
565 from tftp.protocol import TFTP
566 from twisted.application import internet
567@@ -45,22 +41,6 @@
568 from twisted.python.context import get
569 from twisted.web.client import getPage
570 import twisted.web.error
571-from zope.interface import implementer
572-
573-
574-@implementer(IReader)
575-class BytesReader:
576-
577- def __init__(self, data):
578- super(BytesReader, self).__init__()
579- self.buffer = BytesIO(data)
580- self.size = len(data)
581-
582- def read(self, size):
583- return self.buffer.read(size)
584-
585- def finish(self):
586- self.buffer.close()
587
588
589 class TFTPBackend(FilesystemSynchronousBackend):
590@@ -118,7 +98,7 @@
591 def get_boot_method(self, file_name):
592 """Finds the correct boot method."""
593 for _, method in BootMethodRegistry:
594- params = method.match_config_path(file_name)
595+ params = method.match_path(self, file_name)
596 if params is not None:
597 return method, params
598 return None, None
599@@ -142,21 +122,19 @@
600 return d
601
602 @deferred
603- def get_config_reader(self, boot_method, params):
604+ def get_boot_method_reader(self, boot_method, params):
605 """Return an `IReader` for a boot method.
606
607 :param boot_method: Boot method that is generating the config
608 :param params: Parameters so far obtained, typically from the file
609 path requested.
610 """
611- def generate_config(kernel_params):
612- config = boot_method.render_config(
613- kernel_params=kernel_params, **params)
614- return config.encode("utf-8")
615+ def generate(kernel_params):
616+ return boot_method.get_reader(
617+ self, kernel_params=kernel_params, **params)
618
619 d = self.get_kernel_params(params)
620- d.addCallback(generate_config)
621- d.addCallback(BytesReader)
622+ d.addCallback(generate)
623 return d
624
625 @staticmethod
626@@ -203,7 +181,7 @@
627 remote_host, remote_port = get("remote", (None, None))
628 params["remote"] = remote_host
629 params["cluster_uuid"] = get_cluster_uuid()
630- d = self.get_config_reader(boot_method, params)
631+ d = self.get_boot_method_reader(boot_method, params)
632 d.addErrback(self.get_page_errback, file_name)
633 return d
634

Subscribers

People subscribed via source and target branches

to all changes: