Merge lp:~nuclearbob/utah/iso-static-analysis-updates into lp:utah

Proposed by Max Brustkern
Status: Merged
Approved by: Javier Collado
Approved revision: 773
Merged at revision: 769
Proposed branch: lp:~nuclearbob/utah/iso-static-analysis-updates
Merge into: lp:utah
Diff against target: 191 lines (+47/-41)
3 files modified
utah/iso.py (+38/-4)
utah/isotest/iso_static_validation.py (+8/-8)
utah/provisioning/provisioning.py (+1/-29)
To merge this branch: bzr merge lp:~nuclearbob/utah/iso-static-analysis-updates
Reviewer Review Type Date Requested Status
Javier Collado (community) Approve
Dimitri John Ledkov (community) Approve
Max Brustkern (community) Needs Resubmitting
Review via email: mp+138164@code.launchpad.net

Description of the change

This branch addresses lp:1086772. It also changes an exception in iso.py to give a clearer indication of what failed.

To post a comment you must log in.
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

The 12.04.2 images will also not have vmlinuz, and instead have vmlinuz.efi.
So please remove release guard.
It might make sense to pass a pattern like "bsdtar -x -f bla.iso 'casper/vmlinuz.*'" and then check error code from bsdtar / whether any casper/vmlinuz.* got extracted and what it's name is.

review: Needs Fixing
772. By Max Brustkern

Moved method to detect kernel path into ISO class

773. By Max Brustkern

Updated the test to use the kernelpath function of the ISO class, which allows it to work on server images as well

Revision history for this message
Max Brustkern (nuclearbob) wrote :

We have a method to find a kernel in an ISO by checking the bootloader configuration. I moved that from the main provisioning library into the ISO class, and changed the test to use that instead. This also allows the test to work on server images, so I updated it to do so.

review: Needs Resubmitting
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Looks good to me.

review: Approve
Revision history for this message
Javier Collado (javier.collado) wrote :

It looks to me too.

Anyway, I was wondering if we could make the kernel detection more solid using
a regular expression.

That is, instead of this:

if 'kernel' in line or 'linux' in line:
    newkernel = line.split()[1].strip('./')

maybe something like this:

import re

...

match = re.match('^\s+(kernel|linux)\s+(?P<path>[^\s]+).*', line)
if match:
    newkernel = match.group('path')

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

I like the readable way (as is) vs (proposed) cryptic regexp =)
It's not like this is a performance bottle neck, is it?

Revision history for this message
Javier Collado (javier.collado) wrote :

My concern is that the words kernel or linux may appear anywhere in a line and,
if that happens, that will be be wrongly identified as a kernel path.

Revision history for this message
Javier Collado (javier.collado) wrote :

I'm merging this since the bug is critical. We can discuss my comment in the
next meeting.

review: Approve
Revision history for this message
Javier Collado (javier.collado) wrote :

I've created bug1087237 regarding to follow up the conversation about the
kernel path.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'utah/iso.py'
2--- utah/iso.py 2012-11-30 12:05:01 +0000
3+++ utah/iso.py 2012-12-05 19:45:25 +0000
4@@ -10,6 +10,7 @@
5 import urllib
6 import re
7
8+from collections import defaultdict
9 from hashlib import md5
10
11 from utah import config
12@@ -191,7 +192,8 @@
13 cmd = ['bsdtar', '-x', '-f', self.image, '-C', outdir,
14 '-O', realfile]
15 except IndexError:
16- raise UTAHException('Cannot unpack image: ' + self.image)
17+ raise UTAHException('Cannot unpack {path} from {image}'
18+ .format(path=filename, image=self.image))
19 self.logger.debug('bsdtar extract command: ' + ' '.join(cmd))
20 return cmd
21
22@@ -244,7 +246,7 @@
23 """
24 for myfile in self.listfiles(returnlist=True):
25 self.extract(myfile)
26-
27+
28 def getmd5(self, path):
29 """
30 Return the md5 checksum of a file.
31@@ -260,7 +262,7 @@
32 filemd5 = isohash.hexdigest()
33 self.logger.debug('md5 of ' + path + ' is ' + filemd5)
34 return filemd5
35-
36+
37 def downloadiso(self, arch=None, installtype=None, series=None):
38 """
39 Download an ISO given series, type, and arch.
40@@ -339,7 +341,8 @@
41 isopath = os.path.join(remotepath, isofile)
42 self.percent = 0
43 self.logger.info('Attempting to download ' + isopath)
44- temppath = urllib.urlretrieve(isopath, reporthook=self.dldisplay)[0]
45+ temppath = urllib.urlretrieve(isopath,
46+ reporthook=self.dldisplay)[0]
47
48 # Try to copy it into our cache
49 self.logger.debug('Copying ' + temppath + ' to ' + path)
50@@ -350,3 +353,34 @@
51 else:
52 raise UTAHException('Image failed to download after ' +
53 config.dlretries + ' tries')
54+
55+ def kernelpath(self):
56+ kernelpath = './install/vmlinuz'
57+ if self.installtype == 'mini':
58+ self.logger.debug('Getting kernel for mini image')
59+ kernelpath = 'linux'
60+ elif self.installtype == 'desktop':
61+ self.logger.debug('Getting kernel for desktop image')
62+ # Setup the old default kernel path in case none are found
63+ kernels = defaultdict(int, {'casper/vmlinuz': 0})
64+ # Scan bootloader config files to find kernel images
65+ cfgfiles = ['isolinux/txt.cfg', 'isolinux/rqtxt.cfg',
66+ 'boot/grub/grub.cfg', 'boot/grub/loopback.cfg']
67+ for cfgfile in cfgfiles:
68+ if cfgfile in self.listfiles(returnlist=True):
69+ stdout = self.dump(cfgfile).communicate()[0]
70+ for line in stdout.splitlines():
71+ if 'kernel' in line or 'linux' in line:
72+ newkernel = line.split()[1].strip('./')
73+ if 'mt86plus' in newkernel:
74+ self.logger.debug('Rejecting '
75+ 'memtest kernel')
76+ else:
77+ self.logger.debug('Found kernel: '
78+ + newkernel)
79+ kernels[newkernel] += 1
80+ # Now we have a list of kernel paths and the number of times
81+ # each once occurs. We'll use the one that occurs most.
82+ kernelpath = max(kernels.iteritems(),
83+ key=lambda (_path, count): count)[0]
84+ return kernelpath
85
86=== modified file 'utah/isotest/iso_static_validation.py'
87--- utah/isotest/iso_static_validation.py 2012-11-27 18:11:39 +0000
88+++ utah/isotest/iso_static_validation.py 2012-12-05 19:45:25 +0000
89@@ -37,7 +37,6 @@
90 lib_path = os.path.abspath('../')
91 sys.path.append(lib_path)
92 from utah.iso import ISO
93-from utah import config
94
95
96 # Defaults
97@@ -76,7 +75,7 @@
98 ubiquity_image = True
99 else:
100 ubiquity_image = False
101-
102+
103 #Setup the path for data files
104 DATA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data')
105
106@@ -248,7 +247,7 @@
107
108 # Test if wubi is present for desktop or dvd and it is a valid PE
109 @unittest.skipUnless(st_variant == 'desktop' and
110- st_arch != 'powerpc' and st_release < 'raring',
111+ st_arch != 'powerpc' and st_release < 'raring',
112 "Skipping images that aren't ubiquity-based and "
113 "older than raring")
114 def test_wubi(self):
115@@ -320,7 +319,7 @@
116 if self.st_release >= 'q':
117 # cdromupgrade is not shipped in quantal
118 exclude_files.append('cdromupgrade')
119-
120+
121 for list_server in files_list:
122 logging.debug('check if important d-i files are present in iso')
123 path = list_server.rstrip()
124@@ -330,14 +329,15 @@
125 self.assertIn(path, stdout)
126
127 # Test if vmlinuz is a valid executable
128- @unittest.skipUnless(ubiquity_image and st_arch != 'powerpc',
129- "vmlinuz is present only for ubiquity based images")
130+ @unittest.skipUnless(st_arch != 'powerpc',
131+ "vmlinuz is not present only for powerpc images")
132 def test_vmlinuz(self):
133- (stdout, stderr) = self.iso.extract('casper/vmlinuz', self.temp_dir)
134+ path = iso.kernelpath()
135+ (stdout, stderr) = self.iso.extract(path, self.temp_dir)
136 logging.debug('Asserting that vmlinuz is present in the iso')
137 self.assertEqual(stderr, '')
138
139- vmlinuz_path = os.path.join(self.temp_dir, 'casper/vmlinuz')
140+ vmlinuz_path = os.path.join(self.temp_dir, path)
141
142 cmd = ["file", vmlinuz_path]
143 output = subprocess.Popen(cmd, stdout=subprocess.PIPE,
144
145=== modified file 'utah/provisioning/provisioning.py'
146--- utah/provisioning/provisioning.py 2012-11-23 13:08:36 +0000
147+++ utah/provisioning/provisioning.py 2012-12-05 19:45:25 +0000
148@@ -20,7 +20,6 @@
149
150 from glob import glob
151 from stat import S_ISDIR
152-from collections import defaultdict
153
154 import utah.timeout
155
156@@ -888,34 +887,7 @@
157 tmpdir = self.tmpdir
158 if kernel is None:
159 self.logger.info('Unpacking kernel from image')
160- kernelpath = './install/vmlinuz'
161- if self.installtype == 'mini':
162- self.logger.debug('Mini image detected')
163- kernelpath = 'linux'
164- elif self.installtype == 'desktop':
165- self.logger.debug('Desktop image detected')
166- # Setup the old default kernel path in case none are found
167- kernels = defaultdict(int, {'casper/vmlinuz': 0})
168- # Scan bootloader config files to find kernel images
169- cfgfiles = ['isolinux/txt.cfg', 'isolinux/rqtxt.cfg',
170- 'boot/grub/grub.cfg', 'boot/grub/loopback.cfg']
171- for cfgfile in cfgfiles:
172- if cfgfile in self.image.listfiles(returnlist=True):
173- stdout = self.image.dump(cfgfile).communicate()[0]
174- for line in stdout.splitlines():
175- if 'kernel' in line or 'linux' in line:
176- newkernel = line.split()[1].strip('./')
177- if 'mt86plus' in newkernel:
178- self.logger.debug('Rejecting '
179- 'memtest kernel')
180- else:
181- self.logger.debug('Found kernel: '
182- + newkernel)
183- kernels[newkernel] += 1
184- # Now we have a list of kernel paths and the number of times
185- # each once occurs. We'll use the one that occurs most.
186- kernelpath = max(kernels.iteritems(),
187- key=lambda (_path, count): count)[0]
188+ kernelpath = self.image.kernelpath()
189 kernel = os.path.join(tmpdir, 'kernel')
190 self.image.extract(kernelpath, outfile=kernel)
191 else:

Subscribers

People subscribed via source and target branches