From patchwork Wed Oct 26 22:19:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael-Doyle Hudson X-Patchwork-Id: 4839 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id BE8A423E06 for ; Wed, 26 Oct 2011 22:19:16 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id ACF4BA1832F for ; Wed, 26 Oct 2011 22:19:16 +0000 (UTC) Received: by faan26 with SMTP id n26so2971660faa.11 for ; Wed, 26 Oct 2011 15:19:16 -0700 (PDT) Received: by 10.223.62.15 with SMTP id v15mr62052090fah.22.1319667556468; Wed, 26 Oct 2011 15:19:16 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.1.71 with SMTP id 7cs24198lak; Wed, 26 Oct 2011 15:19:15 -0700 (PDT) Received: by 10.216.14.168 with SMTP id d40mr207889wed.111.1319667553850; Wed, 26 Oct 2011 15:19:13 -0700 (PDT) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id l55si2507411weq.11.2011.10.26.15.19.13 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 26 Oct 2011 15:19:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1RJBoX-0002qf-8Q for ; Wed, 26 Oct 2011 22:19:13 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 31342E042C for ; Wed, 26 Oct 2011 22:19:13 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: lava-dispatcher X-Launchpad-Branch: ~linaro-validation/lava-dispatcher/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 150 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~linaro-validation/lava-dispatcher/trunk] Rev 150: move all the stuff that knows about conmux to a concrete subclass of a new connection abstract class Message-Id: <20111026221913.14922.48169.launchpad@ackee.canonical.com> Date: Wed, 26 Oct 2011 22:19:13 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="14189"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 514e6eb19792b550ae90844c6f19539b0f6bca7a Merge authors: Michael Hudson-Doyle (mwhudson) Related merge proposals: https://code.launchpad.net/~mwhudson/lava-dispatcher/connection-client-abstraction/+merge/80415 proposed by: Michael Hudson-Doyle (mwhudson) review: Approve - Paul Larson (pwlars) ------------------------------------------------------------ revno: 150 [merge] committer: Michael Hudson-Doyle branch nick: trunk timestamp: Thu 2011-10-27 11:10:17 +1300 message: move all the stuff that knows about conmux to a concrete subclass of a new connection abstract class added: lava_dispatcher/connection.py modified: lava_dispatcher/__init__.py lava_dispatcher/android_client.py lava_dispatcher/client.py --- lp:lava-dispatcher https://code.launchpad.net/~linaro-validation/lava-dispatcher/trunk You are subscribed to branch lp:lava-dispatcher. To unsubscribe from this branch go to https://code.launchpad.net/~linaro-validation/lava-dispatcher/trunk/+edit-subscription === modified file 'lava_dispatcher/__init__.py' --- lava_dispatcher/__init__.py 2011-10-20 20:40:41 +0000 +++ lava_dispatcher/__init__.py 2011-10-26 02:46:04 +0000 @@ -117,10 +117,6 @@ self.config = dispatcher_config self.job_data = job_data device_config = get_device_config(target) - if device_config.get('client_type') != 'conmux': - raise RuntimeError( - "this version of lava-dispatcher only supports conmux " - "clients, not %r" % device_config.get('client_type')) if image_type == "android": self._client = LavaAndroidClient(self, device_config) else: === modified file 'lava_dispatcher/android_client.py' --- lava_dispatcher/android_client.py 2011-10-25 02:01:41 +0000 +++ lava_dispatcher/android_client.py 2011-10-26 02:59:28 +0000 @@ -20,13 +20,11 @@ import logging import os import pexpect -import re import sys +from tempfile import mkdtemp import time -from tempfile import mkdtemp - -from lava_dispatcher.client import LavaClient, OperationFailed, NetworkError, GeneralError +from lava_dispatcher.client import LavaClient, NetworkError, GeneralError from lava_dispatcher.utils import string_to_list @@ -52,30 +50,9 @@ pass return False - def in_test_shell(self): - """ Check that we are in a shell on the test image - """ - self.proc.sendline("") - match_id = self.proc.expect([self.tester_str , pexpect.TIMEOUT]) - if match_id == 1: - raise OperationFailed - def boot_linaro_android_image(self): - """ Reboot the system to the test android image - """ - self.soft_reboot() - try: - self.enter_uboot() - except: - logging.exception('enter_uboot failed') - self.hard_reboot() - self.enter_uboot() - bootloader_prompt = re.escape(self.device_option('bootloader_prompt')) - boot_cmds = string_to_list(self.config.get('boot_cmds_android')) - self.proc.sendline(boot_cmds[0]) - for line in range(1, len(boot_cmds)): - self.proc.expect(bootloader_prompt) - self.proc.sendline(boot_cmds[line]) + """Reboot the system to the test android image.""" + self._boot(string_to_list(self.config.get('boot_cmds_android'))) self.in_test_shell() self.proc.sendline("export PS1=\"root@linaro: \"") @@ -121,7 +98,7 @@ def android_adb_disconnect(self, dev_ip): cmd = "adb disconnect %s" % dev_ip - adb_proc = pexpect.run(cmd, timeout=300, logfile=sys.stdout) + pexpect.run(cmd, timeout=300, logfile=sys.stdout) def check_adb_status(self): device_ip = self.get_default_nic_ip() === modified file 'lava_dispatcher/client.py' --- lava_dispatcher/client.py 2011-10-25 02:02:17 +0000 +++ lava_dispatcher/client.py 2011-10-26 03:24:05 +0000 @@ -19,7 +19,6 @@ # with this program; if not, see . import pexpect -import re import sys import time from cStringIO import StringIO @@ -27,6 +26,11 @@ from utils import string_to_list import logging +from lava_dispatcher.connection import ( + LavaConmuxConnection, + ) + + class LavaClient(object): """ LavaClient manipulates the target board, bootup, reset, power off the board, @@ -35,11 +39,13 @@ def __init__(self, context, config): self.context = context self.config = config - cmd = "conmux-console %s" % self.hostname self.sio = SerialIO(sys.stdout) - self.proc = pexpect.spawn(cmd, timeout=3600, logfile=self.sio) - #serial can be slow, races do funny things if you don't increase delay - self.proc.delaybeforesend=1 + if config.get('client_type') == 'conmux': + self.proc = LavaConmuxConnection(config, self.sio) + else: + raise RuntimeError( + "this version of lava-dispatcher only supports conmux " + "clients, not %r" % config.get('client_type')) def device_option(self, option_name): return self.config.get(option_name) @@ -99,21 +105,21 @@ Check that we are in a shell on the test image """ self.proc.sendline("") - id = self.proc.expect([self.tester_str, pexpect.TIMEOUT]) - if id == 1: + match_id = self.proc.expect([self.tester_str, pexpect.TIMEOUT]) + if match_id == 1: raise OperationFailed def boot_master_image(self): """ reboot the system, and check that we are in a master shell """ - self.soft_reboot() + self.proc.soft_reboot() try: self.proc.expect("Starting kernel") self.in_master_shell(120) except: logging.exception("in_master_shell failed") - self.hard_reboot() + self.proc.hard_reboot() self.in_master_shell(300) self.proc.sendline('export PS1="$PS1 [rc=$(echo \$?)]: "') self.proc.expect(self.master_str) @@ -122,19 +128,7 @@ """ Reboot the system to the test image """ - self.soft_reboot() - try: - self.enter_uboot() - except: - logging.exception("enter_uboot failed") - self.hard_reboot() - self.enter_uboot() - boot_cmds = self.boot_cmds - self.proc.sendline(boot_cmds[0]) - bootloader_prompt = re.escape(self.device_option('bootloader_prompt')) - for line in range(1, len(boot_cmds)): - self.proc.expect(bootloader_prompt, timeout=300) - self.proc.sendline(boot_cmds[line]) + self.proc._boot(self.boot_cmds) self.in_test_shell() # set PS1 to include return value of last command # Details: system PS1 is set in /etc/bash.bashrc and user PS1 is set in @@ -143,28 +137,6 @@ self.proc.sendline('export PS1="$PS1 [rc=$(echo \$?)]: "') self.proc.expect(self.tester_str) - def enter_uboot(self): - self.proc.expect("Hit any key to stop autoboot") - self.proc.sendline("") - - def soft_reboot(self): - self.proc.sendline("reboot") - # set soft reboot timeout 120s, or do a hard reset - id = self.proc.expect(['Will now restart', pexpect.TIMEOUT], - timeout=120) - if id != 0: - self.hard_reboot() - - def hard_reboot(self): - self.proc.send("~$") - self.proc.sendline("hardreset") - # XXX Workaround for snowball - if self.device_type == "snowball_sd": - time.sleep(10) - self.in_master_shell(300) - # Intentionally avoid self.soft_reboot() to prevent looping - self.proc.sendline("reboot") - def run_shell_command(self, cmd, response=None, timeout=-1): self.empty_pexpect_buffer() # return return-code if captured, else return None === added file 'lava_dispatcher/connection.py' --- lava_dispatcher/connection.py 1970-01-01 00:00:00 +0000 +++ lava_dispatcher/connection.py 2011-10-26 03:24:05 +0000 @@ -0,0 +1,110 @@ +# Copyright (C) 2011 Linaro Limited +# +# Author: Michael Hudson-Doyle +# +# This file is part of LAVA Dispatcher. +# +# LAVA Dispatcher is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# LAVA Dispatcher is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along +# with this program; if not, see . + +import logging +import re +import time + +import pexpect + + +class LavaConnection(object): + + def __init__(self, device_config, sio): + self.device_config = device_config + self.proc = self._make_connection(sio) + + def _make_connection(self, sio): + raise NotImplementedError(self._make_connection) + + def device_option(self, option_name): + return self.device_config.get(option_name) + + def device_option_int(self, option_name): + return self.device_config.getint(option_name) + + + # pexpect-like interface. + + def sendline(self, *args, **kw): + return self.proc.sendline(*args, **kw) + + def expect(self, *args, **kw): + return self.proc.expect(*args, **kw) + + def sendcontrol(self, *args, **kw): + return self.proc.sendcontrol(*args, **kw) + + @property + def match(self): + return self.proc.match + + + # Extra bits. + + def _enter_uboot(self): + self.proc.expect("Hit any key to stop autoboot") + self.proc.sendline("") + + def soft_reboot(self): + self.proc.sendline("reboot") + # set soft reboot timeout 120s, or do a hard reset + id = self.proc.expect( + ['Will now restart', pexpect.TIMEOUT], timeout=120) + if id != 0: + self.hard_reboot() + + def hard_reboot(self): + raise NotImplementedError(self.hard_reboot) + + +class LavaConmuxConnection(LavaConnection): + + def _make_connection(self, sio): + cmd = "conmux-console %s" % self.device_option("hostname") + proc = pexpect.spawn(cmd, timeout=3600, logfile=sio) + #serial can be slow, races do funny things if you don't increase delay + proc.delaybeforesend=1 + return proc + + def hard_reboot(self): + self.proc.send("~$") + self.proc.sendline("hardreset") + # XXX Workaround for snowball + if self.device_option('device_type') == "snowball_sd": + time.sleep(10) + self.in_master_shell(300) + # Intentionally avoid self.soft_reboot() to prevent looping + self.proc.sendline("reboot") + self.enter_uboot() + + def _boot(self, boot_cmds): + self.soft_reboot() + try: + self._enter_uboot() + except: + logging.exception("_enter_uboot failed") + self.hard_reboot() + self._enter_uboot() + self.proc.sendline(boot_cmds[0]) + bootloader_prompt = re.escape(self.device_option('bootloader_prompt')) + for line in range(1, len(boot_cmds)): + self.proc.expect(bootloader_prompt, timeout=300) + self.proc.sendline(boot_cmds[line])