Merge lp:~milo/linaro-image-tools/hwpack-read into lp:linaro-image-tools/11.11

Proposed by Milo Casagrande
Status: Merged
Approved by: James Tunnicliffe
Approved revision: 544
Merged at revision: 546
Proposed branch: lp:~milo/linaro-image-tools/hwpack-read
Merge into: lp:linaro-image-tools/11.11
Diff against target: 459 lines (+360/-9)
6 files modified
linaro-media-create (+30/-7)
linaro_image_tools/hwpack/hwpack_reader.py (+192/-0)
linaro_image_tools/hwpack/tests/__init__.py (+1/-0)
linaro_image_tools/hwpack/tests/test_hwpack_reader.py (+114/-0)
linaro_image_tools/media_create/__init__.py (+6/-2)
linaro_image_tools/utils.py (+17/-0)
To merge this branch: bzr merge lp:~milo/linaro-image-tools/hwpack-read
Reviewer Review Type Date Requested Status
James Tunnicliffe (community) Approve
Linaro Infrastructure Pending
Review via email: mp+116606@code.launchpad.net

Description of the change

With this merge, there is the initial support for hwpack metadata reading, before creating an image with l-m-c.

What has been added here is:
- A new class for reading hwpack, that makes use of the HwpackHandler to open the tarball files
- New tests for the class
- New command line option --read-hwpack that reads the hwpack metadata and prints out information about the supported boards and bootlaoders

I also fixed a couple of PEP8 issues.
Notes:
- There is one test that will fail, and is related to pyflakes, looks like it is bug 812958 (I used getter and setter)
- Some of the required command line options have been set to False, since if we want to just read the hwpack and see what is supported, we should not require all the information. Since there is still work in progress on this, the bits handling the necessary command line options is still missing.

To post a comment you must log in.
542. By Milo Casagrande

Added option check.

543. By Milo Casagrande

Fixed PEP8 warning.

544. By Milo Casagrande

Fixed tests and imports.

Revision history for this message
James Tunnicliffe (dooferlad) wrote :

Looks fine now. Thanks for the changes.

review: Approve
545. By Milo Casagrande

Fixed annoying pyflakes warnings.

546. By Milo Casagrande

Fixed assertEqual tests.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'linaro-media-create'
2--- linaro-media-create 2012-04-19 01:12:10 +0000
3+++ linaro-media-create 2012-07-25 13:08:18 +0000
4@@ -33,6 +33,10 @@
5 install_hwpacks,
6 install_packages,
7 )
8+from linaro_image_tools.hwpack.hwpack_reader import (
9+ HwpackReader,
10+ HwpackReaderError,
11+ )
12 from linaro_image_tools.media_create.partitions import (
13 Media,
14 setup_partitions,
15@@ -44,13 +48,15 @@
16 )
17 from linaro_image_tools.media_create import get_args_parser
18 from linaro_image_tools.utils import (
19+ additional_option_checks,
20+ check_file_integrity_and_log_errors,
21+ check_required_args,
22 ensure_command,
23+ IncompatibleOptions,
24 is_arm_host,
25- check_file_integrity_and_log_errors,
26+ MissingRequiredOption,
27 path_in_tarfile_exists,
28- IncompatibleOptions,
29 prep_media_path,
30- additional_option_checks,
31 )
32
33 # Just define the global variables
34@@ -107,6 +113,22 @@
35 print >> sys.stderr, "\nError:", e.value
36 sys.exit(1)
37
38+ if args.readhwpack:
39+ try:
40+ reader = HwpackReader(args.hwpacks)
41+ print reader.get_supported_boards()
42+ sys.exit(0)
43+ except HwpackReaderError as e:
44+ print >> sys.stderr, "\nError:", e.value
45+ sys.exit(1)
46+
47+ try:
48+ check_required_args(args)
49+ except MissingRequiredOption as e:
50+ parser.print_help()
51+ print >> sys.stderr, "\nError:", e.value
52+ sys.exit(1)
53+
54 board_config = board_configs[args.board]
55 board_config.set_metadata(args.hwpacks)
56 board_config.set_board(args.board)
57@@ -117,11 +139,12 @@
58
59 if media.is_block_device:
60 if not board_config.supports_writing_to_mmc:
61- print "The board '%s' does not support the --mmc option. Please use "\
62- "--image_file to create an image file for this board." % args.board
63+ print ("The board '%s' does not support the --mmc option. "
64+ "Please use --image_file to create an image file for this "
65+ "board." % args.board)
66 sys.exit(1)
67- if not confirm_device_selection_and_ensure_it_is_ready(args.device,
68- args.nocheck_mmc):
69+ if not confirm_device_selection_and_ensure_it_is_ready(
70+ args.device, args.nocheck_mmc):
71 sys.exit(1)
72 elif not args.should_format_rootfs or not args.should_format_bootfs:
73 print ("Do not use --no-boot or --no-part in conjunction with "
74
75=== added file 'linaro_image_tools/hwpack/hwpack_reader.py'
76--- linaro_image_tools/hwpack/hwpack_reader.py 1970-01-01 00:00:00 +0000
77+++ linaro_image_tools/hwpack/hwpack_reader.py 2012-07-25 13:08:18 +0000
78@@ -0,0 +1,192 @@
79+# Copyright (C) 2012 Linaro
80+#
81+# Author: Milo Casagrande <milo.casagrande@linaro.org>
82+#
83+# This file is part of Linaro Image Tools.
84+#
85+# Linaro Image Tools is free software: you can redistribute it and/or modify
86+# it under the terms of the GNU General Public License as published by
87+# the Free Software Foundation, either version 3 of the License, or
88+# (at your option) any later version.
89+#
90+# Linaro Image Tools is distributed in the hope that it will be useful,
91+# but WITHOUT ANY WARRANTY; without even the implied warranty of
92+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93+# GNU General Public License for more details.
94+#
95+# You should have received a copy of the GNU General Public License
96+# along with Linaro Image Tools. If not, see <http://www.gnu.org/licenses/>.
97+
98+from linaro_image_tools.media_create.boards import HardwarepackHandler
99+from linaro_image_tools.hwpack.hwpack_fields import (
100+ FORMAT_FIELD,
101+ NAME_FIELD,
102+ BOARDS_FIELD,
103+ BOOTLOADERS_FIELD,
104+)
105+
106+from os import linesep as LINE_SEP
107+
108+# Fields necessary for the string representation of the hardware pack supported
109+# boards and bootlaoders.
110+HALF_SEPARATOR = '+--------------------------------------'
111+ENDING = '+'
112+SEPARATOR = HALF_SEPARATOR * 2 + ENDING
113+FORMAT = '{:<80}'
114+CENTER_ALIGN = '{:^80}'
115+ELEMENT_FORMAT = '{:<39}| {:<39}'
116+
117+
118+class HwpackReaderError(Exception):
119+ """General error raised by HwpackReader."""
120+ def __init__(self, value):
121+ self.value = value
122+
123+ def __str__(self):
124+ return repr(self.value)
125+
126+
127+class Hwpack(object):
128+ """A simple representation of an hardware pack and its value."""
129+ def __init__(self):
130+ self._hwpack = None
131+ self._boards = None
132+ self._bootloaders = None
133+ self._name = None
134+
135+ @property
136+ def hwpack(self):
137+ """The hardware pack it refers to."""
138+ return self._hwpack
139+
140+ def sethwpack(self, value):
141+ """Sets the hwpack field."""
142+ self._hwpack = value
143+
144+ @property
145+ def boards(self):
146+ """The boards field of this hardware pack."""
147+ return self._boards
148+
149+ def setboards(self, value):
150+ """Sets the boards field."""
151+ self._boards = value
152+
153+ @property
154+ def name(self):
155+ """The name field of this hardware pack."""
156+ return self._name
157+
158+ def setname(self, value):
159+ """Sets the name field."""
160+ self._name = value
161+
162+ @property
163+ def bootloaders(self):
164+ """The bootlaoders field of this hardware pack."""
165+ return self._bootloaders
166+
167+ def setbootloaders(self, value):
168+ """Sets the bootlaoders field."""
169+ self._bootloaders = value
170+
171+ def __eq__(self, other):
172+ """Equality method."""
173+ equal = False
174+ if isinstance(other, Hwpack):
175+ equal = (self.name == other.name and
176+ self.boards == other.boards and
177+ self.hwpack == other.hwpack and
178+ self.bootloaders == other.bootloaders)
179+ return equal
180+
181+ def __hash__(self):
182+ return hash(frozenset(self.bootloaders), frozenset(self.boards),
183+ self.name, self.hwpack)
184+
185+ def __str__(self):
186+ """String representation of this hwapack supported elements."""
187+ string = FORMAT.format("Read hardware pack: %s" % self.hwpack)
188+ string += LINE_SEP
189+ string += FORMAT.format(SEPARATOR)
190+ string += LINE_SEP
191+ string += ELEMENT_FORMAT.format("Supported boards",
192+ "Supported bootloaders")
193+ string += LINE_SEP
194+ string += FORMAT.format(SEPARATOR)
195+ string += LINE_SEP
196+
197+ if self.boards:
198+ for key, value in self.boards.iteritems():
199+ if value.get(BOOTLOADERS_FIELD, None) is not None:
200+ bootloaders = value.get(BOOTLOADERS_FIELD)
201+ supported_bootloaders = bootloaders.keys()
202+ else:
203+ supported_bootloaders = self.bootloaders.keys()
204+ string += ELEMENT_FORMAT.format(key,
205+ ",".join(supported_bootloaders))
206+ string += LINE_SEP
207+ else:
208+ # If we pass a converted file with just a single board, we do not
209+ # have the boards section, and we default to the name of the hwpack
210+ if self.bootloaders:
211+ supported_bootloaders = self.bootloaders.keys()
212+ string += ELEMENT_FORMAT.format(self.name,
213+ ",".join(supported_bootloaders))
214+ string += LINE_SEP
215+ else:
216+ string += CENTER_ALIGN.format("No supported boards and "
217+ "bootloaders")
218+ string += LINE_SEP
219+ string += FORMAT.format(SEPARATOR)
220+ return string + LINE_SEP
221+
222+
223+class HwpackReader(object):
224+ """Reads the information contained in a hwpack """
225+ def __init__(self, hwpacks):
226+ """Create a new instance.
227+
228+ :param hwpacks: The list of hardware packs to read from."""
229+ self.hwpacks = hwpacks
230+ # Where we store all the info from the hwpack.
231+ self._supported_elements = []
232+
233+ @property
234+ def supported_elements(self):
235+ """Gets the supported elements of by all the hardwapare packs."""
236+ return self._supported_elements
237+
238+ def _read_hwpacks_metadata(self):
239+ """Reads the hardware pack metadata file, and prints information about
240+ the supported boards and bootloaders."""
241+ for tarball in self.hwpacks:
242+ with HardwarepackHandler([tarball]) as handler:
243+ hwpack_format = handler.get_field(FORMAT_FIELD)[0]
244+ if hwpack_format.format_as_string == "3.0":
245+ local_hwpack = Hwpack()
246+ local_hwpack.sethwpack(tarball)
247+ local_hwpack.setname(handler.get_field(NAME_FIELD)[0])
248+ local_hwpack.setboards(handler.get_field(BOARDS_FIELD)[0])
249+ local_hwpack.setbootloaders(
250+ handler.get_field(BOOTLOADERS_FIELD)[0])
251+ self.supported_elements.append(local_hwpack)
252+ else:
253+ raise HwpackReaderError("Hardwarepack '%s' cannot be "
254+ "read, unsupported format." %
255+ (tarball))
256+
257+ def get_supported_boards(self):
258+ """Prints the necessary information.
259+
260+ :return A string representation of the information."""
261+ self._read_hwpacks_metadata()
262+ return str(self)
263+
264+ def __str__(self):
265+ """The string representation of this reader. It is a printable
266+ representation of the necessary information."""
267+ hwpack_reader = ""
268+ for element in self.supported_elements:
269+ hwpack_reader += str(element)
270+ return hwpack_reader
271
272=== modified file 'linaro_image_tools/hwpack/tests/__init__.py'
273--- linaro_image_tools/hwpack/tests/__init__.py 2012-07-19 17:57:24 +0000
274+++ linaro_image_tools/hwpack/tests/__init__.py 2012-07-25 13:08:18 +0000
275@@ -30,6 +30,7 @@
276 'linaro_image_tools.hwpack.tests.test_config_v3',
277 'linaro_image_tools.hwpack.tests.test_hardwarepack',
278 'linaro_image_tools.hwpack.tests.test_hwpack_converter',
279+ 'linaro_image_tools.hwpack.tests.test_hwpack_reader',
280 'linaro_image_tools.hwpack.tests.test_packages',
281 'linaro_image_tools.hwpack.tests.test_script',
282 'linaro_image_tools.hwpack.tests.test_tarfile_matchers',
283
284=== added file 'linaro_image_tools/hwpack/tests/test_hwpack_reader.py'
285--- linaro_image_tools/hwpack/tests/test_hwpack_reader.py 1970-01-01 00:00:00 +0000
286+++ linaro_image_tools/hwpack/tests/test_hwpack_reader.py 2012-07-25 13:08:18 +0000
287@@ -0,0 +1,114 @@
288+# Copyright (C) 2012 Linaro
289+#
290+# Author: Milo Casagrande <milo.casagrande@linaro.org>
291+#
292+# This file is part of Linaro Image Tools.
293+#
294+# Linaro Image Tools is free software: you can redistribute it and/or modify
295+# it under the terms of the GNU General Public License as published by
296+# the Free Software Foundation, either version 3 of the License, or
297+# (at your option) any later version.
298+#
299+# Linaro Image Tools is distributed in the hope that it will be useful,
300+# but WITHOUT ANY WARRANTY; without even the implied warranty of
301+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
302+# GNU General Public License for more details.
303+#
304+# You should have received a copy of the GNU General Public License
305+# along with Linaro Image Tools. If not, see <http://www.gnu.org/licenses/>.
306+
307+import tarfile
308+from StringIO import StringIO
309+from linaro_image_tools.testing import TestCaseWithFixtures
310+from linaro_image_tools.tests.fixtures import (
311+ CreateTempDirFixture,
312+ )
313+
314+from linaro_image_tools.media_create.tests.fixtures import (
315+ CreateTarballFixture,
316+ )
317+
318+from linaro_image_tools.hwpack.hwpack_reader import (
319+ Hwpack,
320+ HwpackReader,
321+ HwpackReaderError,
322+ )
323+
324+
325+class HwpackReaderTests(TestCaseWithFixtures):
326+ """Test class for the hwpack reader."""
327+
328+ def setUp(self):
329+ super(HwpackReaderTests, self).setUp()
330+ self.metadata = ("format: 3.0\nversion: '1'\nname: test-hwpack\n"
331+ "architecture: armel\norigin: Linaro")
332+ self.hwpack = Hwpack()
333+ self.hwpack.setname('test-hwpack')
334+ self.tar_dir_fixture = CreateTempDirFixture()
335+ self.useFixture(self.tar_dir_fixture)
336+ self.tarball_fixture = CreateTarballFixture(
337+ self.tar_dir_fixture.get_temp_dir())
338+ self.useFixture(self.tarball_fixture)
339+
340+ def tearDown(self):
341+ super(HwpackReaderTests, self).tearDown()
342+ self.hwpack = None
343+ self.metadata = ""
344+
345+ def add_to_tarball(self, files, tarball=None):
346+ if tarball is None:
347+ tarball = self.tarball_fixture.get_tarball()
348+ tar_file = tarfile.open(tarball, mode='w:gz')
349+ for filename, data in files:
350+ tarinfo = tarfile.TarInfo(filename)
351+ tarinfo.size = len(data)
352+ tar_file.addfile(tarinfo, StringIO(data))
353+ tar_file.close()
354+ return tarball
355+
356+ def test_hwpack_class(self):
357+ hwpack = Hwpack()
358+ hwpack.setname('test-hwpack')
359+ hwpack.sethwpack('a_hwpack')
360+ self.hwpack.sethwpack('a_hwpack')
361+ self.assertEqual(self.hwpack, hwpack)
362+
363+ def test_hwpack_class_not_equal(self):
364+ hwpack = Hwpack()
365+ hwpack.setname('test-hwpack')
366+ hwpack.sethwpack('a_hwpack')
367+ self.hwpack.sethwpack('b_hwpack')
368+ self.assertNotEqual(self.hwpack, hwpack)
369+
370+ def test_hwpack_metadata_read(self):
371+ tarball = self.add_to_tarball([('metadata', self.metadata)])
372+ reader = HwpackReader([tarball])
373+ reader._read_hwpacks_metadata()
374+ self.hwpack.sethwpack(tarball)
375+ self.assertEqual(self.hwpack, reader.supported_elements[0])
376+
377+ def test_raise_exception(self):
378+ new_metadata = ("format=2.0\nversion=4")
379+ tarball = self.add_to_tarball([('metadata', new_metadata)])
380+ reader = HwpackReader([tarball])
381+ self.assertRaises(HwpackReaderError, reader._read_hwpacks_metadata)
382+
383+ def test_hwpack_metadata_read_with_boards(self):
384+ self.metadata += "\nboards:\n panda:\n support: supported\n"
385+ tarball = self.add_to_tarball([('metadata', self.metadata)])
386+ reader = HwpackReader([tarball])
387+ reader._read_hwpacks_metadata()
388+ self.hwpack.sethwpack(tarball)
389+ self.hwpack.setboards({'panda': {'support': 'supported'}})
390+ self.assertEqual(self.hwpack, reader.supported_elements[0])
391+
392+ def test_hwpack_metadata_read_with_bootloaders(self):
393+ self.metadata += ("\nboards:\n panda:\n support: supported\n "
394+ "bootloaders:\n u_boot:\n file: a_file\n")
395+ tarball = self.add_to_tarball([('metadata', self.metadata)])
396+ reader = HwpackReader([tarball])
397+ reader._read_hwpacks_metadata()
398+ self.hwpack.sethwpack(tarball)
399+ self.hwpack.setboards({'panda': {'support': 'supported', 'bootloaders':
400+ {'u_boot': {'file': 'a_file'}}}})
401+ self.assertEqual(self.hwpack, reader.supported_elements[0])
402
403=== modified file 'linaro_image_tools/media_create/__init__.py'
404--- linaro_image_tools/media_create/__init__.py 2012-06-13 14:43:59 +0000
405+++ linaro_image_tools/media_create/__init__.py 2012-07-25 13:08:18 +0000
406@@ -92,7 +92,11 @@
407 '--output-directory', dest='directory',
408 help='Directory where image and accessories should be written to.')
409 parser.add_argument(
410- '--dev', required=True, dest='board', choices=KNOWN_BOARDS,
411+ '--read-hwpack', dest='readhwpack', action='store_true',
412+ help=('Read the hardware pack and print information about the '
413+ 'supported boards and bootloaders.'))
414+ parser.add_argument(
415+ '--dev', dest='board', choices=KNOWN_BOARDS,
416 help='Generate an SD card or image for the given board.')
417 parser.add_argument(
418 '--rootfs', default='ext4', choices=['ext2', 'ext3', 'ext4', 'btrfs'],
419@@ -137,7 +141,7 @@
420 help=('The image size, specified in mega/giga bytes (e.g. 3000M or '
421 '3G); use with --image_file only'))
422 parser.add_argument(
423- '--binary', default='binary-tar.tar.gz', required=True,
424+ '--binary', default='binary-tar.tar.gz', required=False,
425 help=('The tarball containing the rootfs used to create the bootable '
426 'system.'))
427 parser.add_argument(
428
429=== modified file 'linaro_image_tools/utils.py'
430--- linaro_image_tools/utils.py 2012-06-13 14:55:34 +0000
431+++ linaro_image_tools/utils.py 2012-07-25 13:08:18 +0000
432@@ -306,6 +306,15 @@
433 """The hwpack parameter is not a regular file."""
434
435
436+class MissingRequiredOption(Exception):
437+ """A required option from the command line is missing."""
438+ def __init__(self, value):
439+ self.value = value
440+
441+ def __str__(self):
442+ return repr(self.value)
443+
444+
445 class IncompatibleOptions(Exception):
446 def __init__(self, value):
447 self.value = value
448@@ -331,3 +340,11 @@
449 if not os.path.isfile(hwpack):
450 raise InvalidHwpackFile(
451 "--hwpack argument (%s) is not a regular file" % hwpack)
452+
453+
454+def check_required_args(args):
455+ """Check that the required args are passed."""
456+ if args.board is None:
457+ raise MissingRequiredOption("--dev option is required")
458+ if args.binary is None:
459+ raise MissingRequiredOption("--binary option is required")

Subscribers

People subscribed via source and target branches