Merge lp:~nick-schutt/lava-dispatcher/nicks-bootloader-interactive into lp:lava-dispatcher

Proposed by Nicholas Schutt
Status: Rejected
Rejected by: Neil Williams
Proposed branch: lp:~nick-schutt/lava-dispatcher/nicks-bootloader-interactive
Merge into: lp:lava-dispatcher
Diff against target: 863 lines (+365/-126) (has conflicts)
12 files modified
lava_dispatcher/actions/deploy.py (+6/-3)
lava_dispatcher/client/network_master.py (+149/-0)
lava_dispatcher/client/targetdevice.py (+5/-5)
lava_dispatcher/config.py (+1/-0)
lava_dispatcher/default-config/lava-dispatcher/device-defaults.conf (+8/-3)
lava_dispatcher/default-config/lava-dispatcher/device-types/highbank.conf (+26/-0)
lava_dispatcher/device/fastmodel.py (+2/-2)
lava_dispatcher/device/highbank.py (+71/-64)
lava_dispatcher/device/master.py (+88/-42)
lava_dispatcher/device/qemu.py (+2/-2)
lava_dispatcher/device/sdmux.py (+2/-2)
lava_dispatcher/device/target.py (+5/-3)
Text conflict in lava_dispatcher/device/highbank.py
To merge this branch: bzr merge lp:~nick-schutt/lava-dispatcher/nicks-bootloader-interactive
Reviewer Review Type Date Requested Status
Linaro Validation Team Pending
Review via email: mp+165158@code.launchpad.net

This proposal supersedes a proposal from 2013-05-03.

Description of the change

Add interactive boot support for master.py and highbank.py:

1. added bootcmds parameter to deploy.py for all calls to deploy_linaro and deploy_android

2. added sendline and expect support to bootcmds (taken from uefi.py, but removed escape() of special characters)

3. added code to master.py to read boot commands from a file, passed as the bootcmds parameter
    Priority: a. json bootcmds
               b. image bootcmds
               c. device.conf bootcmds

4. added bootcmds support to highbank.py and moved boot sequence to config file

5. added bootcmds master support to highbank.py and moved boot sequence to config file
    -> new variable, boot_cmds_master

-----

Example boot.txt:

expect Highbank \#
echo -------------------------- BEGIN BOOT CMDS ---------------
expect Highbank \#
sendline setenv initrd_high "0xffffffff"
expect Highbank \#
sendline setenv fdt_high "0xffffffff"
expect Highbank \#
sendline setenv bootcmd "ext2load scsi 0:1 0x00800000 uImage; ext2load scsi 0:1 0x01000000 uInitrd; bootm 0x00800000 0x01000000 0x00001000"
expect Highbank \#
sendline setenv bootargs "console=ttyAMA0,115200n8 nosplash root=/dev/disk/by-label/rootfs rootwait ro 1"
expect Highbank \#
echo -------------------------- BOOTING -----------------------
expect Highbank \#
sendline boot

To post a comment you must log in.

Unmerged revisions

637. By Nicholas Schutt

remove boot_cmds from highbank config (the image takes care of this)

636. By Nicholas Schutt

remove boot_cmds from highbank config (the image takes care of this)

635. By Nicholas Schutt

remove boot_cmds from highbank config (the image takes care of this)

634. By Nicholas Schutt

remove boot_cmds from highbank config (the image takes care of this)

633. By Nicholas Schutt

merge trunk

632. By Nicholas Schutt

read file and strip newlines in one line

631. By Nicholas Schutt

read file and strip newlines in one line

630. By Nicholas Schutt

map lines without sendline/expect keyword as sendline for backward compatability

629. By Nicholas Schutt

debug boot_cmds

628. By Nicholas Schutt

remove carriage returns from boot commands file

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lava_dispatcher/actions/deploy.py'
2--- lava_dispatcher/actions/deploy.py 2013-04-17 08:23:50 +0000
3+++ lava_dispatcher/actions/deploy.py 2013-05-22 14:07:36 +0000
4@@ -53,6 +53,7 @@
5 'hwpack': {'type': 'string', 'optional': True},
6 'rootfs': {'type': 'string', 'optional': True},
7 'image': {'type': 'string', 'optional': True},
8+ 'bootcmds': {'type': 'string', 'optional': True},
9 'rootfstype': {'type': 'string', 'optional': True},
10 'bootloader': {'type': 'string', 'optional': True, 'default': 'u_boot'},
11 },
12@@ -70,9 +71,10 @@
13 elif 'image' not in parameters:
14 raise ValueError('must specify image if not specifying a hwpack')
15
16- def run(self, hwpack=None, rootfs=None, image=None, rootfstype='ext3', bootloader='u_boot'):
17+ def run(self, hwpack=None, rootfs=None, image=None, rootfstype='ext3', bootloader='u_boot', bootcmds=None):
18 self.client.deploy_linaro(
19- hwpack=hwpack, rootfs=rootfs, image=image, rootfstype=rootfstype, bootloader=bootloader)
20+ hwpack=hwpack, rootfs=rootfs, image=image, rootfstype=rootfstype,
21+ bootloader=bootloader, bootcmds=bootcmds)
22
23
24 class cmd_deploy_linaro_android_image(BaseAction):
25@@ -83,13 +85,14 @@
26 'boot': {'type': 'string'},
27 'system': {'type': 'string'},
28 'data': {'type': 'string'},
29+ 'bootcmds': {'type': 'string', 'optional': True},
30 'rootfstype': {'type': 'string', 'optional': True, 'default': 'ext4'},
31 },
32 'additionalProperties': False,
33 }
34
35 def run(self, boot, system, data, rootfstype='ext4'):
36- self.client.deploy_linaro_android(boot, system, data, rootfstype)
37+ self.client.deploy_linaro_android(boot, system, data, rootfstype, bootcmds=bootcmds)
38
39
40 class cmd_dummy_deploy(BaseAction):
41
42=== added file 'lava_dispatcher/client/network_master.py'
43--- lava_dispatcher/client/network_master.py 1970-01-01 00:00:00 +0000
44+++ lava_dispatcher/client/network_master.py 2013-05-22 14:07:36 +0000
45@@ -0,0 +1,149 @@
46+# Copyright (C) 2013 Linaro Limited
47+#
48+# Author: Michael Hudson-Doyle <michael.hudson@linaro.org>
49+# Author: Nicholas Schutt <nick.schutt@linaro.org>
50+#
51+# This file is part of LAVA Dispatcher.
52+#
53+# LAVA Dispatcher is free software; you can redistribute it and/or modify
54+# it under the terms of the GNU General Public License as published by
55+# the Free Software Foundation; either version 2 of the License, or
56+# (at your option) any later version.
57+#
58+# LAVA Dispatcher is distributed in the hope that it will be useful,
59+# but WITHOUT ANY WARRANTY; without even the implied warranty of
60+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61+# GNU General Public License for more details.
62+#
63+# You should have received a copy of the GNU General Public License
64+# along
65+# with this program; if not, see <http://www.gnu.org/licenses>.
66+
67+import commands
68+import logging
69+import pexpect
70+import sys
71+import time
72+import traceback
73+
74+import lava_dispatcher.utils as utils
75+
76+from lava_dispatcher.client.base import (
77+ NetworkCommandRunner,
78+)
79+from lava_dispatcher.errors import (
80+ NetworkError,
81+ OperationFailed,
82+ CriticalError,
83+)
84+
85+
86+class NetworkMasterCommandRunner(NetworkCommandRunner):
87+ """A CommandRunner to use when the board is booted into the master image.
88+ """
89+ _prompt_str_includes_rc = False
90+ def __init__(self, target, prompt_str_includes_rc=False):
91+ super(NetworkMasterCommandRunner, self).__init__(
92+ target, target.MASTER_PS1_PATTERN, prompt_str_includes_rc)
93+ self._prompt_str_includes_rc = prompt_str_includes_rc
94+
95+ def run(self, cmd, response=None, timeout=-1, failok=False, wait_prompt=True):
96+ NetworkCommandRunner.run(self, cmd, response, timeout, failok, wait_prompt)
97+ rc = None
98+ if wait_prompt and not self._prompt_str_includes_rc:
99+ rc = self.get_result()
100+ if not failok and rc != 0:
101+ raise OperationFailed(
102+ "executing %r failed with code %s" % (cmd, rc))
103+ return rc
104+
105+ def get_result(self):
106+ rc = None
107+ match_id, match = self.match_id, self.match
108+ NetworkCommandRunner.run(self, "echo x$?x", response='x([0-9]+)x', timeout=5)
109+ if self.match_id != 0:
110+ raise OperationFailed("")
111+ else:
112+ rc = int(self.match.group(1))
113+ return rc
114+
115+ def get_master_ip(self):
116+ logging.info("Waiting for network to come up")
117+ try:
118+ self.wait_network_up(timeout=20)
119+ except NetworkError:
120+ logging.exception("Unable to reach LAVA server")
121+ raise
122+
123+ ip_pat = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
124+ cmd = ("ifconfig %s | grep 'inet addr' | awk -F: '{print $2}' |"
125+ "awk '{print \"<\" $1 \">\"}'" %
126+ self._client.config.default_network_interface)
127+ self.run(cmd, response='(%s)' % ip_pat, wait_prompt=False)
128+ if self.match_id != 0:
129+ msg = "Unable to determine master image IP address"
130+ logging.error(msg)
131+ raise CriticalError(msg)
132+ ip = self.match.group(1)
133+ logging.debug("Master image IP is %s" % ip)
134+ self.master_ip = ip
135+ return ip
136+
137+ def get_device_version(self):
138+ pattern = 'device_version=(\d+-\d+/\d+-\d+)'
139+ self.run("echo \"device_version="
140+ "$(lava-master-image-info --master-image-hwpack "
141+ "| sed 's/[^0-9-]//g; s/^-\+//')"
142+ "/"
143+ "$(lava-master-image-info --master-image-rootfs "
144+ "| sed 's/[^0-9-]//g; s/^-\+//')"
145+ "\"",
146+ [pattern, pexpect.EOF, pexpect.TIMEOUT],
147+ timeout = 5)
148+ device_version = None
149+ if self.match_id == 0:
150+ device_version = self.match.group(1)
151+ logging.debug('Master image version (hwpack/rootfs) is %s' % device_version)
152+ else:
153+ logging.warning('Could not determine image version!')
154+ return device_version
155+
156+ def has_partition_with_label(self, label):
157+ if not label:
158+ return False
159+
160+ path = '/dev/disk/by-label/%s' % label
161+ return self.is_file_exist(path)
162+
163+ def is_file_exist(self, path):
164+ cmd = 'ls %s > /dev/null' % path
165+ rc = self.run(cmd, failok=True)
166+ if rc == 0:
167+ return True
168+ return False
169+
170+ def start_http_server(self, port=80):
171+ master_ip = self.get_master_ip()
172+ # busybox produces no output to parse for, so let it run as a daemon
173+ self.run('busybox httpd -v -p %s' % port)
174+ url_base = "http://%s:%s" % (master_ip, port)
175+ return url_base
176+
177+ def stop_http_server(self):
178+ self.run('killall busybox')
179+
180+ def target_wget_extract(self, tar_url, dest, timeout=-1):
181+ decompression_cmd = ''
182+ if tar_url.endswith('.gz') or tar_url.endswith('.tgz'):
183+ decompression_cmd = '| /bin/gzip -dc'
184+ elif tar_url.endswith('.bz2'):
185+ decompression_cmd = '| /bin/bzip2 -dc'
186+ elif tar_url.endswith('.tar'):
187+ decompression_cmd = ''
188+ else:
189+ raise RuntimeError('bad file extension: %s' % tar_url)
190+
191+ self.run('wget -O - %s %s | /bin/tar -C %s -xmf -'
192+ % (tar_url, decompression_cmd, dest),
193+ timeout=timeout)
194+
195
196=== modified file 'lava_dispatcher/client/targetdevice.py'
197--- lava_dispatcher/client/targetdevice.py 2013-04-23 09:06:25 +0000
198+++ lava_dispatcher/client/targetdevice.py 2013-05-22 14:07:36 +0000
199@@ -46,11 +46,11 @@
200 super(TargetBasedClient, self).__init__(context, config)
201 self.target_device = get_target(context, config)
202
203- def deploy_linaro_android(self, boot, system, data, rootfstype='ext4'):
204- self.target_device.deploy_android(boot, system, data)
205+ def deploy_linaro_android(self, boot, system, data, rootfstype='ext4', bootcmds=None):
206+ self.target_device.deploy_android(boot, system, data, bootcmds=bootcmds)
207
208 def deploy_linaro(self, hwpack=None, rootfs=None, image=None,
209- rootfstype='ext3', bootloader='u_boot'):
210+ rootfstype='ext3', bootloader='u_boot', bootcmds=None):
211 if image is None:
212 if hwpack is None or rootfs is None:
213 raise CriticalError(
214@@ -60,9 +60,9 @@
215 "cannot specify hwpack or rootfs when specifying image")
216
217 if image is None:
218- self.target_device.deploy_linaro(hwpack, rootfs, bootloader)
219+ self.target_device.deploy_linaro(hwpack, rootfs, bootloader, bootcmds=bootcmds)
220 else:
221- self.target_device.deploy_linaro_prebuilt(image)
222+ self.target_device.deploy_linaro_prebuilt(image, bootcmds=bootcmds)
223
224 def _boot_linaro_image(self):
225 if self.proc:
226
227=== modified file 'lava_dispatcher/config.py'
228--- lava_dispatcher/config.py 2013-05-16 01:53:21 +0000
229+++ lava_dispatcher/config.py 2013-05-22 14:07:36 +0000
230@@ -30,6 +30,7 @@
231 android_binary_drivers = schema.StringOption()
232 cts_media_url = schema.StringOption()
233 boot_cmds = schema.StringOption(fatal=True) # Can do better here
234+ boot_cmds_master = schema.StringOption(fatal=True) # And here
235 boot_cmds_android = schema.StringOption(fatal=True) # And here
236 boot_cmds_oe = schema.StringOption(fatal=True) # And here?
237 read_boot_cmds_from_image = schema.BoolOption(default=True)
238
239=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-defaults.conf'
240--- lava_dispatcher/default-config/lava-dispatcher/device-defaults.conf 2013-05-14 18:58:37 +0000
241+++ lava_dispatcher/default-config/lava-dispatcher/device-defaults.conf 2013-05-22 14:07:36 +0000
242@@ -16,13 +16,18 @@
243
244 pre_connect_command =
245
246-# The bootloader commands to boot the device into the test image (we
247-# assume that the device boots into the master image without bootloader
248-# intervention).
249+# The bootloader commands to boot the device into the test image.
250 #
251 # XXX should be called # boot_test_image_commands ?
252 boot_cmds =
253
254+# The bootloader commands to boot the device into the master image (if
255+# this is not defined, we assume that the device boots into the master
256+# image without bootloader intervention).
257+#
258+# XXX should be called # boot_master_image_commands ?
259+boot_cmds_master =
260+
261 # The bootloader commands to boot the device into an android-based test
262 # image.
263 #
264
265=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/highbank.conf'
266--- lava_dispatcher/default-config/lava-dispatcher/device-types/highbank.conf 2013-02-14 03:14:34 +0000
267+++ lava_dispatcher/default-config/lava-dispatcher/device-types/highbank.conf 2013-05-22 14:07:36 +0000
268@@ -1,2 +1,28 @@
269 client_type = highbank
270 connection_command = ipmitool -I lanplus -U admin -P admin -H %(ecmeip)s sol activate
271+
272+interrupt_boot_prompt = Hit any key to stop autoboot:
273+
274+boot_cmds_master = expect Highbank \#,
275+ sendline dhcp,
276+ expect Highbank \#,
277+ sendline pxe get,
278+ expect Highbank \#,
279+ sendline pxe boot,
280+ expect Enter choice:,
281+ sendline 1,
282+ expect \(initramfs\),
283+ sendline . /scripts/functions,
284+ expect \(initramfs\),
285+ sendline DEVICE=eth0 configure_networking,
286+ expect \(initramfs\),
287+ sendline mkdir -p /var/run /var/lib/dhcp /usr/sbin,
288+ expect \(initramfs\),
289+ sendline dhclient -v -1,
290+ expect \(initramfs\),
291+ sendline bash,
292+ expect \(initramfs\),
293+ sendline /bin/busybox --install -s
294+
295+master_str = \(initramfs\)
296+
297
298=== modified file 'lava_dispatcher/device/fastmodel.py'
299--- lava_dispatcher/device/fastmodel.py 2013-03-25 20:23:35 +0000
300+++ lava_dispatcher/device/fastmodel.py 2013-05-22 14:07:36 +0000
301@@ -110,7 +110,7 @@
302
303 self._customize_android()
304
305- def deploy_linaro(self, hwpack=None, rootfs=None, bootloader='u_boot'):
306+ def deploy_linaro(self, hwpack=None, rootfs=None, bootloader='u_boot', bootcmds=None):
307 hwpack = download_image(hwpack, self.context, decompress=False)
308 rootfs = download_image(rootfs, self.context, decompress=False)
309 odir = os.path.dirname(rootfs)
310@@ -128,7 +128,7 @@
311
312 self._customize_linux(self._sd_image)
313
314- def deploy_linaro_prebuilt(self, image):
315+ def deploy_linaro_prebuilt(self, image, bootcmds=None):
316 self._sd_image = download_image(image, self.context)
317 self._copy_axf(self.config.root_part, 'boot')
318
319
320=== modified file 'lava_dispatcher/device/highbank.py'
321--- lava_dispatcher/device/highbank.py 2013-05-15 18:17:02 +0000
322+++ lava_dispatcher/device/highbank.py 2013-05-22 14:07:36 +0000
323@@ -24,11 +24,14 @@
324 import os
325 import pexpect
326 import time
327+import re
328
329 from lava_dispatcher import tarballcache
330+from lava_dispatcher.device import boot_options
331
332 from lava_dispatcher.device.master import (
333 MasterCommandRunner,
334+ MasterImageTarget,
335 )
336 from lava_dispatcher.device.target import (
337 Target
338@@ -44,6 +47,7 @@
339 )
340 from lava_dispatcher.utils import (
341 mk_targz,
342+ string_to_list,
343 rmtree,
344 )
345 from lava_dispatcher.client.lmc_utils import (
346@@ -52,43 +56,53 @@
347 from lava_dispatcher.ipmi import IpmiPxeBoot
348
349
350-class HighbankTarget(Target):
351-
352- MASTER_PS1 = 'root@master [rc=$(echo \$?)]# '
353- MASTER_PS1_PATTERN = 'root@master \[rc=(\d+)\]# '
354+class HighbankTarget(MasterImageTarget):
355
356 def __init__(self, context, config):
357 super(HighbankTarget, self).__init__(context, config)
358- self.proc = self.context.spawn(self.config.connection_command, timeout=1200)
359- self.device_version = None
360+ self.bootcontrol = IpmiPxeBoot(context, self.config.ecmeip)
361+ Target.ubuntu_deployment_data['boot_cmds_master'] = 'boot_cmds_master'
362+ Target.oe_deployment_data['boot_cmds_master'] = 'boot_cmds_master'
363+ Target.fedora_deployment_data['boot_cmds_master'] = 'boot_cmds_master'
364+ Target.android_deployment_data['boot_cmds_master'] = 'boot_cmds_master'
365+
366+ def connect_to_target(self):
367 if self.config.ecmeip == None:
368 msg = "The ecmeip address is not set for this target"
369 logging.error(msg)
370 raise CriticalError(msg)
371- self.bootcontrol = IpmiPxeBoot(context, self.config.ecmeip)
372-
373- def get_device_version(self):
374- return self.device_version
375-
376- def power_on(self):
377- self.bootcontrol.power_on_boot_image()
378- return self.proc
379+ return self.context.spawn(self.config.connection_command, timeout=1200)
380
381 def power_off(self, proc):
382 self.bootcontrol.power_off()
383
384- def deploy_linaro(self, hwpack, rfs, bootloader):
385+ def _soft_reboot(self):
386+ self._hard_reboot()
387+
388+ def _hard_reboot(self):
389+ self.bootcontrol.ipmitool.power_on()
390+ self.bootcontrol.ipmitool.reset()
391+
392+ def deploy_linaro(self, hwpack, rfs, bootloader, bootcmds=None):
393 image_file = generate_image(self, hwpack, rfs, self.scratch_dir, bootloader,
394 extra_boot_args='1', image_size='1G')
395 self._customize_linux(image_file)
396- self._deploy_image(image_file, '/dev/sda')
397+ if bootcmds != None:
398+ self._read_boot_cmds_from_file(bootcmds)
399+# self._read_boot_cmds(boot_tgz=boot_tgz)
400+ self._deploy_image_dd(image_file, '/dev/sda')
401
402- def deploy_linaro_prebuilt(self, image):
403+ def deploy_linaro_prebuilt(self, image, bootcmds=None):
404 image_file = download_image(image, self.context, self.scratch_dir)
405+ data = 'ubuntu'
406+ self.deployment_data = self.target_map[data]
407 self._customize_linux(image_file)
408- self._deploy_image(image_file, '/dev/sda')
409+ if bootcmds != None:
410+ self._read_boot_cmds_from_file(bootcmds)
411+# self._read_boot_cmds(boot_tgz=boot_tgz)
412+ self._deploy_image_dd(image_file, '/dev/sda')
413
414- def _deploy_image(self, image_file, device):
415+ def _deploy_image_dd(self, image_file, device):
416 with self._as_master() as runner:
417
418 # erase the first part of the disk to make sure the new deploy works
419@@ -96,7 +110,7 @@
420
421 # compress the image to reduce the transfer size
422 if not image_file.endswith('.bz2') and not image_file.endswith('gz'):
423- os.system('bzip2 -9v ' + image_file)
424+ os.system('bzip2 -v ' + image_file)
425 image_file += '.bz2'
426
427 tmpdir = self.context.config.lava_image_tmpdir
428@@ -137,8 +151,12 @@
429 'unknown master image partition(%d)' % partition)
430 return partition
431
432+<<<<<<< TREE
433 def resize_rootfs_partition(self, runner):
434 partno = self.config.root_part
435+=======
436+ def resize_rootfs_partition(self, runner, partno = '2'):
437+>>>>>>> MERGE-SOURCE
438 start = None
439
440 runner.run('parted -s /dev/sda print',
441@@ -160,6 +178,7 @@
442 else:
443 logging.warning("unknown partition type for resize: %s" % parttype)
444
445+<<<<<<< TREE
446 @contextlib.contextmanager
447 def file_system(self, partition, directory):
448 logging.info('attempting to access master filesystem %r:%s' %
449@@ -228,20 +247,40 @@
450 runner.run('wget -O - %s %s | /bin/tar -C %s -xmf -'
451 % (tar_url, decompression_cmd, dest),
452 timeout=timeout)
453+=======
454+ def _boot_linaro_image(self):
455+ self.bootcontrol.ipmitool.set_to_boot_from_disk()
456+ super(HighbankTarget,self)._boot_linaro_image()
457+
458+>>>>>>> MERGE-SOURCE
459
460 @contextlib.contextmanager
461 def _as_master(self):
462- self.bootcontrol.power_on_boot_master()
463-
464- # Two reboots seem to be necessary to ensure that pxe boot is used.
465- # Need to identify the cause and fix it
466- self.proc.expect("Hit any key to stop autoboot:")
467- self.proc.sendline('')
468- self.bootcontrol.power_reset_boot_master()
469-
470- self.proc.expect("\(initramfs\)")
471+ """A session that can be used to run commands in the master image."""
472+ self.boot_master_image()
473+ yield MasterCommandRunner(self)
474+
475+ def boot_master_image(self):
476+ boot_cmds_master = self.deployment_data['boot_cmds_master']
477+
478+ options = boot_options.as_dict(self, defaults={'boot_cmds_master': boot_cmds_master})
479+ if 'boot_cmds_master' in options:
480+ boot_cmds_master = options['boot_cmds_master'].value
481+
482+ boot_cmds_master = self.config.cp.get('__main__', boot_cmds_master)
483+ boot_cmds_master = string_to_list(boot_cmds_master.encode('ascii'))
484+
485+ logging.info('boot_cmds_master attribute: %s', boot_cmds_master)
486+
487+ self.bootcontrol.ipmitool.set_to_boot_from_pxe()
488+
489+ self._boot(boot_cmds_master)
490+
491+ self.proc.expect(self.config.master_str, timeout=300)
492+
493 self.proc.sendline('export PS1="%s"' % self.MASTER_PS1)
494 self.proc.expect(self.MASTER_PS1_PATTERN, timeout=180, lava_no_logging=1)
495+<<<<<<< TREE
496 runner = HBMasterCommandRunner(self)
497
498 runner.run(". /scripts/functions")
499@@ -259,42 +298,10 @@
500 runner.run("mkdir -p /var/lib/dhcp")
501 runner.run("dhclient -v -1")
502
503+=======
504+ runner = MasterCommandRunner(self)
505+>>>>>>> MERGE-SOURCE
506 self.device_version = runner.get_device_version()
507
508- try:
509- yield runner
510- finally:
511- logging.debug("deploy done")
512-
513-
514 target_class = HighbankTarget
515
516-
517-class HBMasterCommandRunner(MasterCommandRunner):
518- """A CommandRunner to use when the target is booted into the master image.
519- """
520- http_pid = None
521-
522- def __init__(self, target):
523- super(HBMasterCommandRunner, self).__init__(target)
524-
525- def start_http_server(self):
526- master_ip = self.get_master_ip()
527- if self.http_pid != None:
528- raise OperationFailed("busybox httpd already running with pid %" % self.http_pid)
529- # busybox produces no output to parse for, so run it in the bg and get its pid
530- self.run('busybox httpd -f &')
531- self.run('echo pid:$!:pid',response="pid:(\d+):pid",timeout=10)
532- if self.match_id != 0:
533- raise OperationFailed("busybox httpd did not start")
534- else:
535- self.http_pid = self.match.group(1)
536- url_base = "http://%s" % (master_ip)
537- return url_base
538-
539- def stop_http_server(self):
540- if self.http_pid == None:
541- raise OperationFailed("busybox httpd not running, but stop_http_server called.")
542- self.run('kill %s' % self.http_pid)
543- self.http_pid = None
544-
545
546=== modified file 'lava_dispatcher/device/master.py'
547--- lava_dispatcher/device/master.py 2013-05-20 06:37:29 +0000
548+++ lava_dispatcher/device/master.py 2013-05-22 14:07:36 +0000
549@@ -75,7 +75,7 @@
550 Target.ubuntu_deployment_data['boot_cmds'] = 'boot_cmds'
551 Target.oe_deployment_data['boot_cmds'] = 'boot_cmds_oe'
552 Target.fedora_deployment_data['boot_cmds'] = 'boot_cmds'
553-
554+
555 # used for tarballcache logic to get proper boot_cmds
556 Target.ubuntu_deployment_data['data_type'] = 'ubuntu'
557 Target.oe_deployment_data['data_type'] = 'oe'
558@@ -93,8 +93,11 @@
559 if config.pre_connect_command:
560 self.context.run_command(config.pre_connect_command)
561
562- self.proc = connect_to_serial(self.context)
563+ self.proc = self.connect_to_target()
564
565+ def connect_to_target(self):
566+ return connect_to_serial(self.context)
567+
568 def get_device_version(self):
569 return self.device_version
570
571@@ -106,16 +109,18 @@
572 # we always leave master image devices powered on
573 pass
574
575- def deploy_linaro(self, hwpack, rfs, bootloader):
576+ def deploy_linaro(self, hwpack, rfs, bootloader, bootcmds=None):
577 self.boot_master_image()
578
579 image_file = generate_image(self, hwpack, rfs, self.scratch_dir, bootloader)
580 (boot_tgz, root_tgz, data) = self._generate_tarballs(image_file)
581
582+ if bootcmds != None:
583+ self._read_boot_cmds_from_file(bootcmds)
584 self._read_boot_cmds(boot_tgz=boot_tgz)
585 self._deploy_tarballs(boot_tgz, root_tgz)
586
587- def deploy_android(self, boot, system, userdata):
588+ def deploy_android(self, boot, system, userdata, bootcmds=None):
589 self.boot_master_image()
590
591 sdir = self.scratch_dir
592@@ -123,6 +128,9 @@
593 system = download_image(system, self.context, sdir, decompress=False)
594 data = download_image(userdata, self.context, sdir, decompress=False)
595
596+ if bootcmds != None:
597+ self._read_boot_cmds_from_file(bootcmds)
598+
599 with self._as_master() as master:
600 self._format_testpartition(master, 'ext4')
601 self._deploy_android_tarballs(master, boot, system, data)
602@@ -149,7 +157,7 @@
603 _deploy_linaro_android_system(master, system_url)
604 _deploy_linaro_android_data(master, data_url)
605
606- def deploy_linaro_prebuilt(self, image):
607+ def deploy_linaro_prebuilt(self, image, bootcmds=None):
608 self.boot_master_image()
609
610 if self.context.job_data.get('health_check', False):
611@@ -160,6 +168,8 @@
612 image_file = download_image(image, self.context, self.scratch_dir)
613 (boot_tgz, root_tgz, data) = self._generate_tarballs(image_file)
614
615+ if bootcmds != None:
616+ self._read_boot_cmds_from_file(bootcmds)
617 self._read_boot_cmds(boot_tgz=boot_tgz)
618 self._deploy_tarballs(boot_tgz, root_tgz)
619
620@@ -205,6 +215,15 @@
621
622 return boot_cmds.split('\n')
623
624+ def _read_boot_cmds_from_file(self, cmdfile, keyname='boot_cmds_from_file'):
625+ # If we have already obtained boot commands dynamically, then return.
626+ if self.deployment_data.get(keyname, False):
627+ logging.debug("We have already read boot commands from a file")
628+ return
629+ sdir = self.scratch_dir
630+ bootcmd_file = download_image(cmdfile, self.context, sdir, decompress=True)
631+ self.deployment_data[keyname] = [line.rstrip('\n') for line in open(bootcmd_file)]
632+
633 def _read_boot_cmds(self, image=None, boot_tgz=None):
634 boot_file_path = None
635
636@@ -326,6 +345,7 @@
637 assert directory != '/', "cannot mount entire partition"
638
639 with self._as_master() as runner:
640+ runner.run('mkdir -p /mnt')
641 partition = self.get_partition(runner, partition)
642 runner.run('mount %s /mnt' % partition)
643 try:
644@@ -338,17 +358,10 @@
645 runner.run('tar -czf /tmp/fs.tgz -C %s %s' %
646 (parent_dir, target_name))
647 runner.run('cd /tmp') # need to be in same dir as fs.tgz
648- self.proc.sendline('python -m SimpleHTTPServer 0 2>/dev/null')
649- match_id = self.proc.expect([
650- 'Serving HTTP on 0.0.0.0 port (\d+) \.\.',
651- pexpect.EOF, pexpect.TIMEOUT])
652- if match_id != 0:
653- msg = "Unable to start HTTP server on master"
654- logging.error(msg)
655- raise CriticalError(msg)
656- port = self.proc.match.groups()[match_id]
657-
658- url = "http://%s:%s/fs.tgz" % (self.master_ip, port)
659+
660+ url_base = runner.start_http_server()
661+
662+ url = url_base + '/fs.tgz'
663 tf = download_with_retry(
664 self.context, self.scratch_dir, url, False)
665
666@@ -363,7 +376,7 @@
667 mk_targz(tf, tfdir)
668 rmtree(tfdir)
669
670- self.proc.sendcontrol('c') # kill SimpleHTTPServer
671+ runner.stop_http_server()
672
673 # get the last 2 parts of tf, ie "scratchdir/tf.tgz"
674 tf = '/'.join(tf.split('/')[-2:])
675@@ -372,7 +385,7 @@
676 self.target_extract(runner, url, parent_dir)
677
678 finally:
679- self.proc.sendcontrol('c') # kill SimpleHTTPServer
680+ runner.stop_http_server()
681 runner.run('umount /mnt')
682
683 def extract_tarball(self, tarball_url, partition, directory='/'):
684@@ -488,40 +501,52 @@
685 self.proc.sendline(self.config.interrupt_boot_command)
686
687 def _boot_linaro_image(self):
688- boot_cmds = self.deployment_data['boot_cmds']
689- boot_cmds_override = False
690-
691- options = boot_options.as_dict(self, defaults={'boot_cmds': boot_cmds})
692- if 'boot_cmds' in options:
693- boot_cmds_override = True
694- boot_cmds = options['boot_cmds'].value
695-
696- logging.info('boot_cmds attribute: %s', boot_cmds)
697-
698- # Check if we have already got some values from image's boot file.
699- if self.deployment_data.get('boot_cmds_dynamic') \
700- and not boot_cmds_override:
701+ # Check if we have already got some values from the test or from
702+ # the image's boot file.
703+ if self.deployment_data.get('boot_cmds_from_file', False):
704+ boot_cmds = self.deployment_data['boot_cmds_from_file']
705+ logging.info('boot_cmds_from_file: %s', boot_cmds)
706+ elif self.deployment_data.get('boot_cmds_dynamic', False):
707 logging.info('Loading boot_cmds from image')
708 boot_cmds = self.deployment_data['boot_cmds_dynamic']
709 else:
710+ boot_cmds = self.deployment_data['boot_cmds']
711+ options = boot_options.as_dict(self, defaults={'boot_cmds': boot_cmds})
712+ if 'boot_cmds' in options:
713+ boot_cmds = options['boot_cmds'].value
714 logging.info('Loading boot_cmds from device configuration')
715 boot_cmds = self.config.cp.get('__main__', boot_cmds)
716 boot_cmds = string_to_list(boot_cmds.encode('ascii'))
717
718+ logging.info('boot_cmds attribute: %s', boot_cmds)
719+
720 self._boot(boot_cmds)
721
722 def _boot(self, boot_cmds):
723- try:
724- self._soft_reboot()
725- self._enter_bootloader()
726- except:
727- logging.exception("_enter_bootloader failed")
728- self._hard_reboot()
729- self._enter_bootloader()
730- self.proc.sendline(boot_cmds[0])
731- for line in range(1, len(boot_cmds)):
732- self.proc.expect(self.config.bootloader_prompt, timeout=300)
733- self.proc.sendline(boot_cmds[line])
734+ self._soft_reboot()
735+ if len(boot_cmds) > 0:
736+ try:
737+ self._enter_bootloader()
738+ except:
739+ logging.exception("_enter_bootloader failed")
740+ self._hard_reboot()
741+ self._enter_bootloader()
742+ for line in range(0, len(boot_cmds)):
743+ parts = re.match('^(?P<action>sendline|expect)\s*(?P<command>.*)', boot_cmds[line])
744+ try:
745+ action = parts.group('action')
746+ command = parts.group('command')
747+ except AttributeError as e:
748+ action = "sendline"
749+ command = boot_cmds[line]
750+
751+ if action == "expect":
752+ self.proc.expect(command, timeout=300)
753+ elif action == "sendline":
754+ self.proc.empty_buffer()
755+ self.proc.sendline(command)
756+ else:
757+ raise Exception("Unrecognised action in boot_cmds")
758
759
760 target_class = MasterImageTarget
761@@ -530,6 +555,7 @@
762 class MasterCommandRunner(NetworkCommandRunner):
763 """A CommandRunner to use when the board is booted into the master image.
764 """
765+ http_pid = None
766
767 def __init__(self, target):
768 super(MasterCommandRunner, self).__init__(
769@@ -593,6 +619,26 @@
770 return True
771 return False
772
773+ def start_http_server(self):
774+ master_ip = self.get_master_ip()
775+ if self.http_pid != None:
776+ raise OperationFailed("busybox httpd already running with pid %" % self.http_pid)
777+ # busybox produces no output to parse for, so run it in the bg and get its pid
778+ self.run('busybox httpd -f &')
779+ self.run('echo pid:$!:pid',response="pid:(\d+):pid",timeout=10)
780+ if self.match_id != 0:
781+ raise OperationFailed("busybox httpd did not start")
782+ else:
783+ self.http_pid = self.match.group(1)
784+ url_base = "http://%s" % (master_ip)
785+ return url_base
786+
787+ def stop_http_server(self):
788+ if self.http_pid != None:
789+ self.run('kill %s' % self.http_pid)
790+ self.http_pid = None
791+
792+
793
794 def _extract_partition(image, partno, tarfile):
795 """Mount a partition and produce a tarball of it
796
797=== modified file 'lava_dispatcher/device/qemu.py'
798--- lava_dispatcher/device/qemu.py 2013-02-18 03:06:06 +0000
799+++ lava_dispatcher/device/qemu.py 2013-05-22 14:07:36 +0000
800@@ -45,12 +45,12 @@
801 super(QEMUTarget, self).__init__(context, config)
802 self._sd_image = None
803
804- def deploy_linaro(self, hwpack=None, rootfs=None, bootloader='u_boot'):
805+ def deploy_linaro(self, hwpack=None, rootfs=None, bootloader='u_boot', bootcmds=None):
806 odir = self.scratch_dir
807 self._sd_image = generate_image(self, hwpack, rootfs, odir, bootloader)
808 self._customize_linux(self._sd_image)
809
810- def deploy_linaro_prebuilt(self, image):
811+ def deploy_linaro_prebuilt(self, image, bootcmds=None):
812 self._sd_image = download_image(image, self.context)
813 self._customize_linux(self._sd_image)
814
815
816=== modified file 'lava_dispatcher/device/sdmux.py'
817--- lava_dispatcher/device/sdmux.py 2013-04-02 16:16:18 +0000
818+++ lava_dispatcher/device/sdmux.py 2013-05-22 14:07:36 +0000
819@@ -88,12 +88,12 @@
820 if config.pre_connect_command:
821 self.context.run_command(config.pre_connect_command)
822
823- def deploy_linaro(self, hwpack=None, rootfs=None):
824+ def deploy_linaro(self, hwpack=None, rootfs=None, bootcmds=None):
825 img = generate_image(self, hwpack, rootfs, self.scratch_dir)
826 self._customize_linux(img)
827 self._write_image(img)
828
829- def deploy_linaro_prebuilt(self, image):
830+ def deploy_linaro_prebuilt(self, image, bootcmds=None):
831 img = download_image(image, self.context)
832 self._customize_linux(img)
833 self._write_image(img)
834
835=== modified file 'lava_dispatcher/device/target.py'
836--- lava_dispatcher/device/target.py 2013-04-19 08:40:29 +0000
837+++ lava_dispatcher/device/target.py 2013-05-22 14:07:36 +0000
838@@ -40,6 +40,8 @@
839
840 ANDROID_TESTER_PS1 = "root@linaro# "
841
842+ _scratch_dir = None
843+
844 # The target deployment functions will point self.deployment_data to
845 # the appropriate dictionary below. Code such as actions can contribute
846 # to these structures with special handling logic
847@@ -85,13 +87,13 @@
848 """
849 raise NotImplementedError('power_on')
850
851- def deploy_linaro(self, hwpack, rfs):
852+ def deploy_linaro(self, hwpack, rfs, bootcmds=None):
853 raise NotImplementedError('deploy_image')
854
855- def deploy_android(self, boot, system, userdata):
856+ def deploy_android(self, boot, system, userdata, bootcmds=None):
857 raise NotImplementedError('deploy_android_image')
858
859- def deploy_linaro_prebuilt(self, image):
860+ def deploy_linaro_prebuilt(self, image, bootcmds=None):
861 raise NotImplementedError('deploy_linaro_prebuilt')
862
863 def power_off(self, proc):

Subscribers

People subscribed via source and target branches