Merge lp:~tyler-baker/lava-dispatcher/consolidate-busybox-httpd into lp:lava-dispatcher

Proposed by Tyler Baker
Status: Merged
Merged at revision: 677
Proposed branch: lp:~tyler-baker/lava-dispatcher/consolidate-busybox-httpd
Merge into: lp:lava-dispatcher
Diff against target: 261 lines (+49/-108)
3 files modified
lava_dispatcher/device/bootloader.py (+6/-49)
lava_dispatcher/device/ipmi_pxe.py (+4/-55)
lava_dispatcher/device/target.py (+39/-4)
To merge this branch: bzr merge lp:~tyler-baker/lava-dispatcher/consolidate-busybox-httpd
Reviewer Review Type Date Requested Status
Antonio Terceiro Approve
Review via email: mp+184403@code.launchpad.net

Description of the change

Consolidation of the busybox httpd logic. The ipmi_pxe and bootloader class both use these functions to allow the exchange of files to and from the target. It makes sense to reuse a single implementation, rather than maintaining both.

* Moved all the functionality into target.py for reuse.
* start_http_server -> start_busybox_http_server
* stop_http_server -> stop_busybox_http_server

Tested these changes on a bootloader device.

http://community.validation.linaro.org/scheduler/job/1065

However, I cannot test these changes on a highbank node until merged into staging.

To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

I know you're just moving code around so this is a side comment but does the httpd's pid really need to come to the host? Seems we could just execute

$ busybox httpd &
$ echo $! > /tmp/httpd.pid

to start and

$ kill `cat /tmp/httpd.pid`

to stop it.

Revision history for this message
Antonio Terceiro (terceiro) wrote :

Looks good to me.

I also agree with Michael's comments - doing that will simplify the code even more.

 review approve

review: Approve
Revision history for this message
Tyler Baker (tyler-baker) wrote :

I'll update the branch per Michael's comments after I retest. Thanks for the suggestion!

676. By Tyler Baker

Remove httpd pid

677. By Tyler Baker

Remove the dead code

Revision history for this message
Tyler Baker (tyler-baker) wrote :

Branch updated to reflect comments.

Tested the changes on a bootloader device:

http://community.validation.linaro.org/scheduler/job/1138

Merging to test on the highbank in staging.

Revision history for this message
Tyler Baker (tyler-baker) wrote :

Confirmed logic works correctly on highbank in staging.

https://staging.validation.linaro.org/scheduler/job/2285

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lava_dispatcher/device/bootloader.py'
--- lava_dispatcher/device/bootloader.py 2013-08-30 22:15:05 +0000
+++ lava_dispatcher/device/bootloader.py 2013-09-10 16:31:28 +0000
@@ -51,7 +51,6 @@
51 self._boot_cmds = None51 self._boot_cmds = None
52 self._lava_cmds = None52 self._lava_cmds = None
53 self._uboot_boot = False53 self._uboot_boot = False
54 self._http_pid = None
55 # This is the offset into the path, used to reference bootfiles54 # This is the offset into the path, used to reference bootfiles
56 self._offset = self.scratch_dir.index('images')55 self._offset = self.scratch_dir.index('images')
5756
@@ -115,11 +114,13 @@
115114
116 def deploy_linaro(self, hwpack, rfs, bootloadertype):115 def deploy_linaro(self, hwpack, rfs, bootloadertype):
117 self._uboot_boot = False116 self._uboot_boot = False
118 super(BootloaderTarget, self).deploy_linaro(hwpack, rfs, bootloadertype)117 super(BootloaderTarget, self).deploy_linaro(hwpack, rfs,
118 bootloadertype)
119119
120 def deploy_linaro_prebuilt(self, image, bootloadertype):120 def deploy_linaro_prebuilt(self, image, bootloadertype):
121 self._uboot_boot = False121 self._uboot_boot = False
122 super(BootloaderTarget, self).deploy_linaro_prebuilt(image, bootloadertype)122 super(BootloaderTarget, self).deploy_linaro_prebuilt(image,
123 bootloadertype)
123124
124 def _inject_boot_cmds(self):125 def _inject_boot_cmds(self):
125 if self._is_job_defined_boot_cmds(self.config.boot_cmds):126 if self._is_job_defined_boot_cmds(self.config.boot_cmds):
@@ -164,28 +165,6 @@
164 else:165 else:
165 super(BootloaderTarget, self)._boot_linaro_image()166 super(BootloaderTarget, self)._boot_linaro_image()
166167
167 def start_http_server(self, runner, ip):
168 if self._http_pid is not None:
169 raise OperationFailed("busybox httpd already running with pid %d"
170 % self._http_pid)
171 # busybox produces no output to parse for,
172 # so run it in the bg and get its pid
173 runner.run('busybox httpd -f &')
174 runner.run('echo pid:$!:pid', response="pid:(\d+):pid", timeout=10)
175 if runner.match_id != 0:
176 raise OperationFailed("busybox httpd did not start")
177 else:
178 self._http_pid = runner.match.group(1)
179 url_base = "http://%s" % ip
180 return url_base
181
182 def stop_http_server(self, runner):
183 if self._http_pid is None:
184 raise OperationFailed("busybox httpd not running, \
185 but stop_http_server called.")
186 runner.run('kill %s' % self._http_pid)
187 self._http_pid = None
188
189 @contextlib.contextmanager168 @contextlib.contextmanager
190 def file_system(self, partition, directory):169 def file_system(self, partition, directory):
191 if self._uboot_boot:170 if self._uboot_boot:
@@ -202,7 +181,7 @@
202 runner.run('cd /tmp') # need to be in same dir as fs.tgz181 runner.run('cd /tmp') # need to be in same dir as fs.tgz
203182
204 ip = runner.get_target_ip()183 ip = runner.get_target_ip()
205 url_base = self.start_http_server(runner, ip)184 url_base = self._start_busybox_http_server(runner, ip)
206185
207 url = url_base + '/fs.tgz'186 url = url_base + '/fs.tgz'
208 logging.info("Fetching url: %s" % url)187 logging.info("Fetching url: %s" % url)
@@ -226,32 +205,10 @@
226 runner.run('rm -rf %s' % targetdir)205 runner.run('rm -rf %s' % targetdir)
227 self._target_extract(runner, tf, parent_dir)206 self._target_extract(runner, tf, parent_dir)
228 finally:207 finally:
229 self.stop_http_server(runner)208 self._stop_busybox_http_server(runner)
230 else:209 else:
231 with super(BootloaderTarget, self).file_system(210 with super(BootloaderTarget, self).file_system(
232 partition, directory) as path:211 partition, directory) as path:
233 yield path212 yield path
234213
235 def _target_extract(self, runner, tar_file, dest, timeout=-1):
236 tmpdir = self.context.config.lava_image_tmpdir
237 url = self.context.config.lava_image_url
238 tar_file = tar_file.replace(tmpdir, '')
239 tar_url = '/'.join(u.strip('/') for u in [url, tar_file])
240 self._target_extract_url(runner, tar_url, dest, timeout=timeout)
241
242 def _target_extract_url(self, runner, tar_url, dest, timeout=-1):
243 decompression_cmd = ''
244 if tar_url.endswith('.gz') or tar_url.endswith('.tgz'):
245 decompression_cmd = '| /bin/gzip -dc'
246 elif tar_url.endswith('.bz2'):
247 decompression_cmd = '| /bin/bzip2 -dc'
248 elif tar_url.endswith('.tar'):
249 decompression_cmd = ''
250 else:
251 raise RuntimeError('bad file extension: %s' % tar_url)
252
253 runner.run('wget -O - %s %s | /bin/tar -C %s -xmf -'
254 % (tar_url, decompression_cmd, dest),
255 timeout=timeout)
256
257target_class = BootloaderTarget214target_class = BootloaderTarget
258215
=== modified file 'lava_dispatcher/device/ipmi_pxe.py'
--- lava_dispatcher/device/ipmi_pxe.py 2013-08-30 22:15:05 +0000
+++ lava_dispatcher/device/ipmi_pxe.py 2013-09-10 16:31:28 +0000
@@ -32,7 +32,6 @@
32)32)
33from lava_dispatcher.errors import (33from lava_dispatcher.errors import (
34 CriticalError,34 CriticalError,
35 OperationFailed,
36)35)
37from lava_dispatcher.downloader import (36from lava_dispatcher.downloader import (
38 download_image,37 download_image,
@@ -176,7 +175,8 @@
176 runner.run('/bin/tar -cmzf /tmp/fs.tgz -C %s %s' % (parent_dir, target_name))175 runner.run('/bin/tar -cmzf /tmp/fs.tgz -C %s %s' % (parent_dir, target_name))
177 runner.run('cd /tmp') # need to be in same dir as fs.tgz176 runner.run('cd /tmp') # need to be in same dir as fs.tgz
178177
179 url_base = runner.start_http_server()178 ip = runner.get_target_ip()
179 url_base = self._start_busybox_http_server(runner, ip)
180180
181 url = url_base + '/fs.tgz'181 url = url_base + '/fs.tgz'
182 logging.info("Fetching url: %s" % url)182 logging.info("Fetching url: %s" % url)
@@ -200,38 +200,16 @@
200 self._target_extract(runner, tf, parent_dir)200 self._target_extract(runner, tf, parent_dir)
201201
202 finally:202 finally:
203 runner.stop_http_server()203 self._stop_busybox_http_server()
204 runner.run('umount /mnt')204 runner.run('umount /mnt')
205205
206 def _target_extract(self, runner, tar_file, dest, timeout=-1):
207 tmpdir = self.context.config.lava_image_tmpdir
208 url = self.context.config.lava_image_url
209 tar_file = tar_file.replace(tmpdir, '')
210 tar_url = '/'.join(u.strip('/') for u in [url, tar_file])
211 self._target_extract_url(runner, tar_url, dest, timeout=timeout)
212
213 def _target_extract_url(self, runner, tar_url, dest, timeout=-1):
214 decompression_cmd = ''
215 if tar_url.endswith('.gz') or tar_url.endswith('.tgz'):
216 decompression_cmd = '| /bin/gzip -dc'
217 elif tar_url.endswith('.bz2'):
218 decompression_cmd = '| /bin/bzip2 -dc'
219 elif tar_url.endswith('.tar'):
220 decompression_cmd = ''
221 else:
222 raise RuntimeError('bad file extension: %s' % tar_url)
223
224 runner.run('wget -O - %s %s | /bin/tar -C %s -xmf -'
225 % (tar_url, decompression_cmd, dest),
226 timeout=timeout)
227
228 @contextlib.contextmanager206 @contextlib.contextmanager
229 def _as_master(self):207 def _as_master(self):
230 self.bootcontrol.power_on_boot_master()208 self.bootcontrol.power_on_boot_master()
231 self.proc.expect("\(initramfs\)")209 self.proc.expect("\(initramfs\)")
232 self.proc.sendline('export PS1="%s"' % self.MASTER_PS1)210 self.proc.sendline('export PS1="%s"' % self.MASTER_PS1)
233 self.proc.expect(self.MASTER_PS1_PATTERN, timeout=180, lava_no_logging=1)211 self.proc.expect(self.MASTER_PS1_PATTERN, timeout=180, lava_no_logging=1)
234 runner = BusyboxHttpdMasterCommandRunner(self)212 runner = MasterCommandRunner(self)
235213
236 runner.run(". /scripts/functions")214 runner.run(". /scripts/functions")
237 runner.run("DEVICE=%s configure_networking" %215 runner.run("DEVICE=%s configure_networking" %
@@ -257,32 +235,3 @@
257235
258236
259target_class = IpmiPxeTarget237target_class = IpmiPxeTarget
260
261
262class BusyboxHttpdMasterCommandRunner(MasterCommandRunner):
263 """A CommandRunner to use when the target is booted into the master image.
264 """
265 http_pid = None
266
267 def __init__(self, target):
268 super(BusyboxHttpdMasterCommandRunner, self).__init__(target)
269
270 def start_http_server(self):
271 master_ip = self.get_master_ip()
272 if self.http_pid is not None:
273 raise OperationFailed("busybox httpd already running with pid %d" % self.http_pid)
274 # busybox produces no output to parse for, so run it in the bg and get its pid
275 self.run('busybox httpd -f &')
276 self.run('echo pid:$!:pid', response="pid:(\d+):pid", timeout=10)
277 if self.match_id != 0:
278 raise OperationFailed("busybox httpd did not start")
279 else:
280 self.http_pid = self.match.group(1)
281 url_base = "http://%s" % master_ip
282 return url_base
283
284 def stop_http_server(self):
285 if self.http_pid is None:
286 raise OperationFailed("busybox httpd not running, but stop_http_server called.")
287 self.run('kill %s' % self.http_pid)
288 self.http_pid = None
289238
=== modified file 'lava_dispatcher/device/target.py'
--- lava_dispatcher/device/target.py 2013-08-30 22:15:05 +0000
+++ lava_dispatcher/device/target.py 2013-09-10 16:31:28 +0000
@@ -191,13 +191,15 @@
191191
192 def _customize_bootloader(self, connection, boot_cmds):192 def _customize_bootloader(self, connection, boot_cmds):
193 for line in boot_cmds:193 for line in boot_cmds:
194 parts = re.match('^(?P<action>sendline|expect)\s*(?P<command>.*)', line)194 parts = re.match('^(?P<action>sendline|expect)\s*(?P<command>.*)',
195 line)
195 if parts:196 if parts:
196 try:197 try:
197 action = parts.group('action')198 action = parts.group('action')
198 command = parts.group('command')199 command = parts.group('command')
199 except AttributeError as e:200 except AttributeError as e:
200 raise Exception("Badly formatted command in boot_cmds %s" % e)201 raise Exception("Badly formatted command in \
202 boot_cmds %s" % e)
201 if action == "sendline":203 if action == "sendline":
202 connection.send(command)204 connection.send(command)
203 connection.sendline('')205 connection.sendline('')
@@ -205,8 +207,41 @@
205 command = re.escape(command)207 command = re.escape(command)
206 connection.expect(command, timeout=300)208 connection.expect(command, timeout=300)
207 else:209 else:
208 self._wait_for_prompt(connection, self.config.bootloader_prompt, timeout=300)210 self._wait_for_prompt(connection,
209 connection.sendline(line) 211 self.config.bootloader_prompt,
212 timeout=300)
213 connection.sendline(line)
214
215 def _target_extract(self, runner, tar_file, dest, timeout=-1):
216 tmpdir = self.context.config.lava_image_tmpdir
217 url = self.context.config.lava_image_url
218 tar_file = tar_file.replace(tmpdir, '')
219 tar_url = '/'.join(u.strip('/') for u in [url, tar_file])
220 self._target_extract_url(runner, tar_url, dest, timeout=timeout)
221
222 def _target_extract_url(self, runner, tar_url, dest, timeout=-1):
223 decompression_cmd = ''
224 if tar_url.endswith('.gz') or tar_url.endswith('.tgz'):
225 decompression_cmd = '| /bin/gzip -dc'
226 elif tar_url.endswith('.bz2'):
227 decompression_cmd = '| /bin/bzip2 -dc'
228 elif tar_url.endswith('.tar'):
229 decompression_cmd = ''
230 else:
231 raise RuntimeError('bad file extension: %s' % tar_url)
232
233 runner.run('wget -O - %s %s | /bin/tar -C %s -xmf -'
234 % (tar_url, decompression_cmd, dest),
235 timeout=timeout)
236
237 def _start_busybox_http_server(self, runner, ip):
238 runner.run('busybox httpd -f &')
239 runner.run('echo $! > /tmp/httpd.pid')
240 url_base = "http://%s" % ip
241 return url_base
242
243 def _stop_busybox_http_server(self, runner):
244 runner.run('kill `cat /tmp/httpd.pid`')
210245
211 def _customize_ubuntu(self, rootdir):246 def _customize_ubuntu(self, rootdir):
212 self.deployment_data = Target.ubuntu_deployment_data247 self.deployment_data = Target.ubuntu_deployment_data

Subscribers

People subscribed via source and target branches