1
# Copyright (C) 2012 Linaro Limited
3
# Author: Andy Doan <andy.doan@linaro.org>
5
# This file is part of LAVA Dispatcher.
7
# LAVA Dispatcher is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2 of the License, or
10
# (at your option) any later version.
12
# LAVA Dispatcher is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
19
# with this program; if not, see <http://www.gnu.org/licenses>.
24
from lava_dispatcher.client.lmc_utils import (
25
image_partition_mounted,
27
import lava_dispatcher.utils as utils
30
def get_target(context, device_config):
31
ipath = 'lava_dispatcher.device.%s' % device_config.client_type
32
m = __import__(ipath, fromlist=[ipath])
33
return m.target_class(context, device_config)
37
""" Defines the contract needed by the dispatcher for dealing with a
41
ANDROID_TESTER_PS1 = "root@linaro# "
43
# The target deployment functions will point self.deployment_data to
44
# the appropriate dictionary below. Code such as actions can contribute
45
# to these structures with special handling logic
46
android_deployment_data = {
47
'TESTER_PS1': ANDROID_TESTER_PS1,
48
'TESTER_PS1_PATTERN': ANDROID_TESTER_PS1,
49
'TESTER_PS1_INCLUDES_RC': False,
51
ubuntu_deployment_data = {
52
'TESTER_PS1': "linaro-test [rc=$(echo \$?)]# ",
53
'TESTER_PS1_PATTERN': "linaro-test \[rc=(\d+)\]# ",
54
'TESTER_PS1_INCLUDES_RC': True,
56
oe_deployment_data = {
57
'TESTER_PS1': "linaro-test [rc=$(echo \$?)]# ",
58
'TESTER_PS1_PATTERN': "linaro-test \[rc=(\d+)\]# ",
59
'TESTER_PS1_INCLUDES_RC': True,
61
fedora_deployment_data = {
62
'TESTER_PS1': "linaro-test [rc=$(echo \$?)]# ",
63
'TESTER_PS1_PATTERN': "linaro-test \[rc=(\d+)\]# ",
64
'TESTER_PS1_INCLUDES_RC': True,
67
def __init__(self, context, device_config):
68
self.context = context
69
self.config = device_config
71
self.boot_options = []
72
self._scratch_dir = None
73
self.deployment_data = {}
76
def scratch_dir(self):
77
if self._scratch_dir is None:
78
self._scratch_dir = utils.mkdtemp(
79
self.context.config.lava_image_tmpdir)
80
return self._scratch_dir
83
""" responsible for powering on the target device and returning an
84
instance of a pexpect session
86
raise NotImplementedError('power_on')
88
def deploy_linaro(self, hwpack, rfs):
89
raise NotImplementedError('deploy_image')
91
def deploy_android(self, boot, system, userdata):
92
raise NotImplementedError('deploy_android_image')
94
def deploy_linaro_prebuilt(self, image):
95
raise NotImplementedError('deploy_linaro_prebuilt')
97
def power_off(self, proc):
101
@contextlib.contextmanager
102
def file_system(self, partition, directory):
103
""" Allows the caller to interact directly with a directory on
104
the target. This method yields a directory where the caller can
105
interact from. Upon the exit of this context, the changes will be
106
applied to the target.
108
The partition parameter refers to partition number the directory
109
would reside in as created by linaro-media-create. ie - the boot
110
partition would be 1. In the case of something like the master
111
image, the target implementation must map this number to the actual
114
NOTE: due to difference in target implementations, the caller should
115
try and interact with the smallest directory locations possible.
117
raise NotImplementedError('file_system')
119
def extract_tarball(self, tarball_url, partition, directory='/'):
120
""" This is similar to the file_system API but is optimized for the
121
scenario when you just need explode a potentially large tarball on
122
the target device. The file_system API isn't really suitable for this
123
when thinking about an implementation like master.py
125
raise NotImplementedError('extract_tarball')
127
@contextlib.contextmanager
129
""" Powers on the target, returning a CommandRunner object and will
130
power off the target when the context is exited
134
proc = self.power_on()
135
runner = self._get_runner(proc)
141
def _get_runner(self, proc):
142
from lava_dispatcher.client.base import CommandRunner
143
pat = self.deployment_data['TESTER_PS1_PATTERN']
144
incrc = self.deployment_data['TESTER_PS1_INCLUDES_RC']
145
return CommandRunner(proc, pat, incrc)
147
def get_test_data_attachments(self):
150
def get_device_version(self):
151
""" Returns the device version associated with the device, i.e. version
152
of emulation software, or version of master image. Must be overriden in
157
def _customize_ubuntu(self, rootdir):
158
self.deployment_data = Target.ubuntu_deployment_data
159
with open('%s/root/.bashrc' % rootdir, 'a') as f:
160
f.write('export PS1="%s"\n' % self.deployment_data['TESTER_PS1'])
161
with open('%s/etc/hostname' % rootdir, 'w') as f:
162
f.write('%s\n' % self.config.hostname)
164
def _customize_oe(self, rootdir):
165
self.deployment_data = Target.oe_deployment_data
166
with open('%s/etc/profile' % rootdir, 'a') as f:
167
f.write('export PS1="%s"\n' % self.deployment_data['TESTER_PS1'])
168
with open('%s/etc/hostname' % rootdir, 'w') as f:
169
f.write('%s\n' % self.config.hostname)
171
def _customize_fedora(self, rootdir):
172
self.deployment_data = Target.fedora_deployment_data
173
with open('%s/etc/profile' % rootdir, 'a') as f:
174
f.write('export PS1="%s"\n' % self.deployment_data['TESTER_PS1'])
175
with open('%s/etc/hostname' % rootdir, 'w') as f:
176
f.write('%s\n' % self.config.hostname)
178
def _customize_linux(self, image):
179
root_part = self.config.root_part
180
os_release_id = 'linux'
181
with image_partition_mounted(image, root_part) as mnt:
182
os_release_file = '%s/etc/os-release' % mnt
183
if os.path.exists(os_release_file):
184
for line in open(os_release_file):
185
if line.startswith('ID='):
186
os_release_id = line[(len('ID=')):]
187
os_release_id = os_release_id.strip('\"\n')
190
if os_release_id == 'debian' or os_release_id == 'ubuntu' or \
191
os.path.exists('%s/etc/debian_version' % mnt):
192
self._customize_ubuntu(mnt)
193
elif os_release_id == 'fedora':
194
self._customize_fedora(mnt)
196
# assume an OE based image. This is actually pretty safe
197
# because we are doing pretty standard linux stuff, just
198
# just no upstart or dash assumptions
199
self._customize_oe(mnt)