Merge lp:~terceiro/lava-dispatcher/device-version into lp:lava-dispatcher

Proposed by Antonio Terceiro
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: 404
Merged at revision: 418
Proposed branch: lp:~terceiro/lava-dispatcher/device-version
Merge into: lp:lava-dispatcher
Diff against target: 313 lines (+173/-17)
9 files modified
lava_dispatcher/context.py (+3/-0)
lava_dispatcher/device/fastmodel.py (+16/-0)
lava_dispatcher/device/qemu.py (+10/-0)
lava_dispatcher/device/target.py (+14/-2)
lava_dispatcher/job.py (+1/-0)
lava_dispatcher/tests/__init__.py (+4/-1)
lava_dispatcher/tests/helper.py (+52/-0)
lava_dispatcher/tests/test_config.py (+4/-14)
lava_dispatcher/tests/test_device_version.py (+69/-0)
To merge this branch: bzr merge lp:~terceiro/lava-dispatcher/device-version
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle (community) Approve
Review via email: mp+130404@code.launchpad.net

Description of the change

This is the dispatcher part of the device version support implementation.

You will notice that the master image part is not done, since I could not get my board to work yet. In the current state of the code, master image devices will always return 'unknown' as their device versions.

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

Antonio Terceiro <email address hidden> writes:

> This is the dispatcher part of the device version support implementation.
>
> You will notice that the master image part is not done, since I could
> not get my board to work yet. In the current state of the code, master
> image devices will always return 'unknown' as their device versions.

This looks mostly fine, thanks! Just a couple of comments.

> === modified file 'lava_dispatcher/device/qemu.py' ---
> lava_dispatcher/device/qemu.py 2012-10-17 16:52:05 +0000 +++
> lava_dispatcher/device/qemu.py 2012-10-18 17:49:26 +0000 @@ -20,6
> +20,7 @@
>
> import contextlib
> import logging
> +import subprocess
>
> from lava_dispatcher.device.target import (
> Target
> @@ -76,4 +77,10 @@
> proc = logging_spawn(qemu_cmd, logfile=self.sio, timeout=1200)
> return proc
>
> + def get_device_version(self):
> + try:
> + return subprocess.check_output(["dpkg-query", "--showformat=${Version}", "--show", "qemu-system"])
> + except subprocess.CalledProcessError:
> + return "unknown"

Not sure this is the right thing to do -- should we not parse the
-version of the qemu binary we actually use, which might not be the
packaged version?

> target_class = QEMUTarget
>

> === added file 'lava_dispatcher/tests/test_device_version.py'
> --- lava_dispatcher/tests/test_device_version.py 1970-01-01 00:00:00 +0000
> +++ lava_dispatcher/tests/test_device_version.py 2012-10-18 17:49:26 +0000
> @@ -0,0 +1,59 @@
> +# Copyright (C) 2012 Linaro Limited
> +#
> +# Author: Antonio Terceiro <email address hidden>
> +#
> +# 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 <http://www.gnu.org/licenses>.
> +
> +from unittest import TestCase
> +import re
> +from lava_dispatcher.tests.helper import LavaDispatcherTestCase, create_device_config
> +
> +from lava_dispatcher.device.target import Target
> +from lava_dispatcher.device.qemu import QEMUTarget
> +from lava_dispatcher.device.fastmodel import FastModelTarget
> +
> +def _create_fastmodel():
> + config = create_device_config('fastmodel01', { 'device_type': 'fastmodel', 'simulator_binary': '/path/to/fastmodel', 'license_server': 'foo.local' })
> + target = FastModelTarget(None, config)
> + return target

Could you call this _create_fastmodel_target() do you think?

> +class TestDeviceVersion(LavaDispatcherTestCase):
> +
> + def test_base(self):
> + target = Target(None, None)
> + assert(type(target.get_device_version()) is str)

It would be more Pyt...

Read more...

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

Michael Hudson-Doyle escreveu:
> > === modified file 'lava_dispatcher/device/qemu.py' ---
> > lava_dispatcher/device/qemu.py 2012-10-17 16:52:05 +0000 +++
> > lava_dispatcher/device/qemu.py 2012-10-18 17:49:26 +0000 @@ -20,6
> > +20,7 @@
> >
> > import contextlib
> > import logging
> > +import subprocess
> >
> > from lava_dispatcher.device.target import (
> > Target
> > @@ -76,4 +77,10 @@
> > proc = logging_spawn(qemu_cmd, logfile=self.sio, timeout=1200)
> > return proc
> >
> > + def get_device_version(self):
> > + try:
> > + return subprocess.check_output(["dpkg-query", "--showformat=${Version}", "--show", "qemu-system"])
> > + except subprocess.CalledProcessError:
> > + return "unknown"
>
> Not sure this is the right thing to do -- should we not parse the
> -version of the qemu binary we actually use, which might not be the
> packaged version?

Yeah, you are right. I was kind of afraid of parsing the very
non-machine-friendly output of --version, but I guess that's the right
thing to do after all.

> > +def _create_fastmodel():
> > + config = create_device_config('fastmodel01', { 'device_type': 'fastmodel', 'simulator_binary': '/path/to/fastmodel', 'license_server': 'foo.local' })
> > + target = FastModelTarget(None, config)
> > + return target
>
> Could you call this _create_fastmodel_target() do you think?

Agreed. This name was from before Andy's reorganization, and after the
merge I ended up keeping it. But _create_fastmodel_target is indeed
better.

> > +class TestDeviceVersion(LavaDispatcherTestCase):
> > +
> > + def test_base(self):
> > + target = Target(None, None)
> > + assert(type(target.get_device_version()) is str)
>
> It would be more Pythonic to write this as:
>
> self.assertIsInstance(target.get_device_version(), str)

fixed - thanks.

--
Antonio Terceiro
Software Engineer - Linaro
http://www.linaro.org

400. By Antonio Terceiro

merge with latest code

401. By Antonio Terceiro

create more realistic target instances for testing

402. By Antonio Terceiro

Use actual qemu binary - we might not be using the packaged one

403. By Antonio Terceiro

more Pythonic assertion of instance type

404. By Antonio Terceiro

return last version present in the output of --version

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Looks good now, thanks.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lava_dispatcher/context.py'
--- lava_dispatcher/context.py 2012-09-30 17:01:44 +0000
+++ lava_dispatcher/context.py 2012-10-22 18:03:24 +0000
@@ -55,3 +55,6 @@
55 self._host_result_dir = tempfile.mkdtemp()55 self._host_result_dir = tempfile.mkdtemp()
56 atexit.register(shutil.rmtree, self._host_result_dir)56 atexit.register(shutil.rmtree, self._host_result_dir)
57 return self._host_result_dir57 return self._host_result_dir
58
59 def get_device_version(self):
60 return self.client.target_device.get_device_version()
5861
=== modified file 'lava_dispatcher/device/fastmodel.py'
--- lava_dispatcher/device/fastmodel.py 2012-10-17 16:52:05 +0000
+++ lava_dispatcher/device/fastmodel.py 2012-10-22 18:03:24 +0000
@@ -26,6 +26,8 @@
26import shutil26import shutil
27import stat27import stat
28import threading28import threading
29import re
30import subprocess
2931
30from lava_dispatcher.device.target import (32from lava_dispatcher.device.target import (
31 Target33 Target
@@ -255,6 +257,20 @@
255 return [create_attachment('rtsm.log', content)]257 return [create_attachment('rtsm.log', content)]
256 return []258 return []
257259
260 def get_device_version(self):
261 cmd = '%s --version' % self._sim_binary
262 try:
263 banner = subprocess.check_output(cmd, shell = True)
264 return self._parse_fastmodel_version(banner)
265 except subprocess.CalledProcessError:
266 return "unknown"
267
268 def _parse_fastmodel_version(self, banner):
269 match = re.search('Fast Models \[([0-9.]+)', banner)
270 if match:
271 return match.group(1)
272 else:
273 return "unknown"
258274
259class _pexpect_drain(threading.Thread):275class _pexpect_drain(threading.Thread):
260 ''' The simulator process can dump a lot of information to its console. If276 ''' The simulator process can dump a lot of information to its console. If
261277
=== modified file 'lava_dispatcher/device/qemu.py'
--- lava_dispatcher/device/qemu.py 2012-10-17 16:52:05 +0000
+++ lava_dispatcher/device/qemu.py 2012-10-22 18:03:24 +0000
@@ -20,6 +20,8 @@
2020
21import contextlib21import contextlib
22import logging22import logging
23import subprocess
24import re
2325
24from lava_dispatcher.device.target import (26from lava_dispatcher.device.target import (
25 Target27 Target
@@ -76,4 +78,12 @@
76 proc = logging_spawn(qemu_cmd, logfile=self.sio, timeout=1200)78 proc = logging_spawn(qemu_cmd, logfile=self.sio, timeout=1200)
77 return proc79 return proc
7880
81 def get_device_version(self):
82 try:
83 output = subprocess.check_output([self.context.config.default_qemu_binary, '--version'])
84 matches = re.findall('[0-9]+\.[0-9a-z.+\-:~]+', output)
85 return matches[-1]
86 except subprocess.CalledProcessError:
87 return "unknown"
88
79target_class = QEMUTarget89target_class = QEMUTarget
8090
=== modified file 'lava_dispatcher/device/target.py'
--- lava_dispatcher/device/target.py 2012-10-17 16:52:05 +0000
+++ lava_dispatcher/device/target.py 2012-10-22 18:03:24 +0000
@@ -70,9 +70,15 @@
70 self.sio = SerialIO(sys.stdout)70 self.sio = SerialIO(sys.stdout)
7171
72 self.boot_options = []72 self.boot_options = []
73 self.scratch_dir = utils.mkdtemp(context.config.lava_image_tmpdir)73 self._scratch_dir = None
74 self.deployment_data = {}74 self.deployment_data = {}
7575
76 @property
77 def scratch_dir(self):
78 if self._scratch_dir is None:
79 self._scratch_dir = utils.mkdtemp(context.config.lava_image_tmpdir)
80 return self._scratch_dir
81
76 def power_on(self):82 def power_on(self):
77 """ responsible for powering on the target device and returning an83 """ responsible for powering on the target device and returning an
78 instance of a pexpect session84 instance of a pexpect session
@@ -148,6 +154,13 @@
148 def get_test_data_attachments(self):154 def get_test_data_attachments(self):
149 return []155 return []
150156
157 def get_device_version(self):
158 """ Returns the device version associated with the device, i.e. version
159 of emulation software, or version of master image. Must be overriden in
160 subclasses.
161 """
162 return 'unknown'
163
151 def _customize_ubuntu(self, rootdir):164 def _customize_ubuntu(self, rootdir):
152 self.deployment_data = Target.ubuntu_deployment_data165 self.deployment_data = Target.ubuntu_deployment_data
153 with open('%s/root/.bashrc' % rootdir, 'a') as f:166 with open('%s/root/.bashrc' % rootdir, 'a') as f:
@@ -169,7 +182,6 @@
169 # just no upstart or dash assumptions182 # just no upstart or dash assumptions
170 self._customize_oe(mnt)183 self._customize_oe(mnt)
171184
172
173class SerialIO(file):185class SerialIO(file):
174 def __init__(self, logfile):186 def __init__(self, logfile):
175 self.serialio = StringIO()187 self.serialio = StringIO()
176188
=== modified file 'lava_dispatcher/job.py'
--- lava_dispatcher/job.py 2012-08-30 04:22:50 +0000
+++ lava_dispatcher/job.py 2012-10-22 18:03:24 +0000
@@ -142,6 +142,7 @@
142142
143 metadata = {143 metadata = {
144 'target.hostname': self.target,144 'target.hostname': self.target,
145 'target.device_version': self.context.get_device_version(),
145 }146 }
146147
147 if 'device_type' in self.job_data:148 if 'device_type' in self.job_data:
148149
=== modified file 'lava_dispatcher/tests/__init__.py'
--- lava_dispatcher/tests/__init__.py 2011-06-27 04:55:08 +0000
+++ lava_dispatcher/tests/__init__.py 2012-10-22 18:03:24 +0000
@@ -1,6 +1,9 @@
1import unittest1import unittest
22
3def test_suite():3def test_suite():
4 module_names = ['lava_dispatcher.tests.test_config',]4 module_names = [
5 'lava_dispatcher.tests.test_config',
6 'lava_dispatcher.tests.test_device_version',
7 ]
5 loader = unittest.TestLoader()8 loader = unittest.TestLoader()
6 return loader.loadTestsFromNames(module_names)9 return loader.loadTestsFromNames(module_names)
710
=== added file 'lava_dispatcher/tests/helper.py'
--- lava_dispatcher/tests/helper.py 1970-01-01 00:00:00 +0000
+++ lava_dispatcher/tests/helper.py 2012-10-22 18:03:24 +0000
@@ -0,0 +1,52 @@
1# Copyright (C) 2012 Linaro Limited
2#
3# Author: Antonio Terceiro <antonio.terceiro@linaro.org>
4#
5# This file is part of LAVA Dispatcher.
6#
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.
11#
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.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, see <http://www.gnu.org/licenses>.
19
20import os
21from lava_dispatcher.config import get_config, get_device_config
22
23__tmp_dir = os.getenv("TMPDIR") or '/tmp'
24__tmp_config_dir = os.path.join(__tmp_dir, 'lava-dispatcher-config')
25
26def create_config(name, data):
27 filename = os.path.join(__tmp_config_dir, name)
28 if not os.path.exists(os.path.dirname(filename)):
29 os.mkdir(os.path.dirname(filename))
30 with open(filename, 'w') as f:
31 for key in data.keys():
32 f.write("%s = %s\n" % (key, data[key]))
33
34def create_device_config(name, data):
35 create_config("devices/%s.conf" % name, data)
36 return get_device_config(name, __tmp_config_dir)
37
38def setup_config_dir():
39 os.mkdir(__tmp_config_dir)
40
41def cleanup_config_dir():
42 os.system('rm -rf %s' % __tmp_config_dir)
43
44from unittest import TestCase
45
46class LavaDispatcherTestCase(TestCase):
47
48 def setUp(self):
49 setup_config_dir()
50
51 def tearDown(self):
52 cleanup_config_dir()
053
=== modified file 'lava_dispatcher/tests/test_config.py'
--- lava_dispatcher/tests/test_config.py 2012-10-16 02:26:18 +0000
+++ lava_dispatcher/tests/test_config.py 2012-10-22 18:03:24 +0000
@@ -17,33 +17,23 @@
17# You should have received a copy of the GNU General Public License17# You should have received a copy of the GNU General Public License
18# along with this program; if not, see <http://www.gnu.org/licenses>.18# along with this program; if not, see <http://www.gnu.org/licenses>.
1919
20import os
21from unittest import TestCase20from unittest import TestCase
2221
23from lava_dispatcher.config import get_config, get_device_config22from lava_dispatcher.config import get_config, get_device_config
24from lava_dispatcher.utils import string_to_list23from lava_dispatcher.utils import string_to_list
25from lava_dispatcher.client.base import LavaClient24from lava_dispatcher.client.base import LavaClient
2625
26from lava_dispatcher.tests.helper import *
27
27test_config_dir = os.path.join(os.path.dirname(__file__), 'test-config')28test_config_dir = os.path.join(os.path.dirname(__file__), 'test-config')
28print test_config_dir
29
30tmp_dir = os.getenv("TMPDIR") or '/tmp'
31tmp_config_dir = os.path.join(tmp_dir, 'lava-dispatcher-config')
32
33def create_config(name, data):
34 filename = os.path.join(tmp_config_dir, name)
35 os.mkdir(os.path.dirname(filename))
36 with open(filename, 'w') as f:
37 for key in data.keys():
38 f.write("%s = %s\n" % (key, data[key]))
3929
40class TestConfigData(TestCase):30class TestConfigData(TestCase):
4131
42 def setUp(self):32 def setUp(self):
43 os.mkdir(tmp_config_dir)33 setup_config_dir()
4434
45 def tearDown(self):35 def tearDown(self):
46 os.system('rm -rf %s' % tmp_config_dir)36 cleanup_config_dir()
4737
48 def test_beagle01_uboot_cmds(self):38 def test_beagle01_uboot_cmds(self):
49 beagle01_config = get_device_config("beaglexm01", test_config_dir)39 beagle01_config = get_device_config("beaglexm01", test_config_dir)
5040
=== added file 'lava_dispatcher/tests/test_device_version.py'
--- lava_dispatcher/tests/test_device_version.py 1970-01-01 00:00:00 +0000
+++ lava_dispatcher/tests/test_device_version.py 2012-10-22 18:03:24 +0000
@@ -0,0 +1,69 @@
1# Copyright (C) 2012 Linaro Limited
2#
3# Author: Antonio Terceiro <antonio.terceiro@linaro.org>
4#
5# This file is part of LAVA Dispatcher.
6#
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.
11#
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.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, see <http://www.gnu.org/licenses>.
19
20from unittest import TestCase
21import re
22from lava_dispatcher.tests.helper import LavaDispatcherTestCase, create_device_config, create_config, __tmp_config_dir
23
24from lava_dispatcher.device.target import Target
25from lava_dispatcher.device.qemu import QEMUTarget
26from lava_dispatcher.device.fastmodel import FastModelTarget
27from lava_dispatcher.context import LavaContext
28from lava_dispatcher.config import get_config
29
30def _create_fastmodel_target():
31 config = create_device_config('fastmodel01', { 'device_type': 'fastmodel', 'simulator_binary': '/path/to/fastmodel', 'license_server': 'foo.local' })
32 target = FastModelTarget(None, config)
33 return target
34
35def _create_qemu_target():
36 create_config('lava-dispatcher.conf', {'default_qemu_binary': 'qemu-system-arm'})
37 device_config = create_device_config('qemu01', { 'device_type': 'qemu' })
38 dispatcher_config = get_config(__tmp_config_dir)
39
40 context = LavaContext('qemu01', dispatcher_config, None, None)
41 return QEMUTarget(context, device_config)
42
43class TestDeviceVersion(LavaDispatcherTestCase):
44
45 def test_base(self):
46 target = Target(None, None)
47 self.assertIsInstance(target.get_device_version(), str)
48
49 def test_qemu(self):
50 target = _create_qemu_target()
51 device_version = target.get_device_version()
52 assert(re.search('^[0-9.]+', device_version))
53
54 def test_fastmodel(self):
55 banner = "\n".join([
56 "Fast Models [7.1.36 (May 17 2012)]",
57 "Copyright 2000-2012 ARM Limited.",
58 "All Rights Reserved.",
59 "Top component name: RTSM_VE_Cortex_A15x1_A7x1"
60 ])
61 target = _create_fastmodel_target()
62 version = target._parse_fastmodel_version(banner)
63 self.assertEqual('7.1.36', version)
64
65 def test_fastmodel_wrong_format(self):
66 client = _create_fastmodel_target()
67 version = client._parse_fastmodel_version('random string')
68 self.assertEqual('unknown', version)
69

Subscribers

People subscribed via source and target branches