Merge lp:~rvb/maas/reporting-bug-1301809 into lp:~maas-committers/maas/trunk

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 2224
Proposed branch: lp:~rvb/maas/reporting-bug-1301809
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 79 lines (+28/-1)
2 files modified
src/provisioningserver/boot/tests/test_tftppath.py (+13/-0)
src/provisioningserver/boot/tftppath.py (+15/-1)
To merge this branch: bzr merge lp:~rvb/maas/reporting-bug-1301809
Reviewer Review Type Date Requested Status
Jeroen T. Vermeulen (community) Approve
Review via email: mp+213984@code.launchpad.net

Commit message

Change list_boot_images() so that it can cope with a missing boot images directory: this happens if the reporting task runs before the images have been imported.

To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

That's a nice touch — it fixes an unforeseen consequence of the TFTP root moving to a new directory hierarchy.

The comment on the new code reads a bit weird:

        # Return an empty list only if the exception is a "No such file
        # or directory" exception.

Which is the main new fact in that sentence — that we should return an empty list, or that sometimes we shouldn't return an empty list? I think it might come out clearer as a matter of course if you commented on the two possible cases _inside_ the if/else bodies: “Directory does not exist, so return empty list.” / “Other error. Propagate.”

Right below that, the log message seems useful, but unnecessarily verbose for its context. This is an automatically repeating job, not something that ever happens in response to a human interaction. We already have helpful messages in the UI for the situation it signals. If a user is savvy enough to operate without ever looking at the UI even when things aren't working, then I think we can expect them to understand a much terser message such as “No boot images have been imported yet.”

Keeping the message short helps keep the log files readable. The message is likely to be logged many times before the images have been imported, and even while they are importing. Also, if a user does see the repeating “push the import button!” message at that stage, they might misinterpret it as meaning that the original import didn't work and they need to start a new one.

review: Approve
Revision history for this message
Raphaël Badin (rvb) wrote :

> That's a nice touch — it fixes an unforeseen consequence of the TFTP root
> moving to a new directory hierarchy.
> [...]

Both very good points, both well made :). Fixed.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/provisioningserver/boot/tests/test_tftppath.py'
2--- src/provisioningserver/boot/tests/test_tftppath.py 2014-03-28 04:43:57 +0000
3+++ src/provisioningserver/boot/tests/test_tftppath.py 2014-04-03 16:36:28 +0000
4@@ -14,10 +14,13 @@
5 __metaclass__ = type
6 __all__ = []
7
8+import errno
9 import os.path
10
11 from maastesting.factory import factory
12 from maastesting.testcase import MAASTestCase
13+from mock import Mock
14+from provisioningserver.boot import tftppath
15 from provisioningserver.boot.tftppath import (
16 compose_image_path,
17 drill_down,
18@@ -35,6 +38,7 @@
19 Not,
20 StartsWith,
21 )
22+from testtools.testcase import ExpectedException
23
24
25 def make_image(params, purpose):
26@@ -95,6 +99,15 @@
27 self.assertEqual(
28 self.tftproot, locate_tftp_path(None, tftproot=self.tftproot))
29
30+ def test_list_boot_images_copes_with_missing_directory(self):
31+ self.assertEqual([], list_boot_images(factory.getRandomString()))
32+
33+ def test_list_boot_images_passes_on_other_exceptions(self):
34+ error = OSError(errno.EACCES, "Deliberate error for testing.")
35+ self.patch(tftppath, 'list_subdirs', Mock(side_effect=error))
36+ with ExpectedException(OSError):
37+ list_boot_images(factory.getRandomString())
38+
39 def test_list_boot_images_copes_with_empty_directory(self):
40 self.assertEqual([], list_boot_images(self.tftproot))
41
42
43=== modified file 'src/provisioningserver/boot/tftppath.py'
44--- src/provisioningserver/boot/tftppath.py 2014-03-28 04:36:31 +0000
45+++ src/provisioningserver/boot/tftppath.py 2014-04-03 16:36:28 +0000
46@@ -20,10 +20,15 @@
47 'locate_tftp_path',
48 ]
49
50+import errno
51 from itertools import chain
52+from logging import getLogger
53 import os.path
54
55
56+logger = getLogger(__name__)
57+
58+
59 def compose_image_path(arch, subarch, release, label):
60 """Compose the TFTP path for a PXE kernel/initrd directory.
61
62@@ -135,7 +140,16 @@
63 """
64 # The sub-directories directly under tftproot, if they contain
65 # images, represent architectures.
66- potential_archs = list_subdirs(tftproot)
67+ try:
68+ potential_archs = list_subdirs(tftproot)
69+ except OSError as exception:
70+ if exception.errno == errno.ENOENT:
71+ # Directory does not exist, so return empty list.
72+ logger.warning("No boot images have been imported yet.")
73+ return []
74+ else:
75+ # Other error. Propagate.
76+ raise
77
78 # Starting point for iteration: paths that contain only the
79 # top-level subdirectory of tftproot, i.e. the architecture name.