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
1=== modified file 'lava_dispatcher/context.py'
2--- lava_dispatcher/context.py 2012-09-30 17:01:44 +0000
3+++ lava_dispatcher/context.py 2012-10-22 18:03:24 +0000
4@@ -55,3 +55,6 @@
5 self._host_result_dir = tempfile.mkdtemp()
6 atexit.register(shutil.rmtree, self._host_result_dir)
7 return self._host_result_dir
8+
9+ def get_device_version(self):
10+ return self.client.target_device.get_device_version()
11
12=== modified file 'lava_dispatcher/device/fastmodel.py'
13--- lava_dispatcher/device/fastmodel.py 2012-10-17 16:52:05 +0000
14+++ lava_dispatcher/device/fastmodel.py 2012-10-22 18:03:24 +0000
15@@ -26,6 +26,8 @@
16 import shutil
17 import stat
18 import threading
19+import re
20+import subprocess
21
22 from lava_dispatcher.device.target import (
23 Target
24@@ -255,6 +257,20 @@
25 return [create_attachment('rtsm.log', content)]
26 return []
27
28+ def get_device_version(self):
29+ cmd = '%s --version' % self._sim_binary
30+ try:
31+ banner = subprocess.check_output(cmd, shell = True)
32+ return self._parse_fastmodel_version(banner)
33+ except subprocess.CalledProcessError:
34+ return "unknown"
35+
36+ def _parse_fastmodel_version(self, banner):
37+ match = re.search('Fast Models \[([0-9.]+)', banner)
38+ if match:
39+ return match.group(1)
40+ else:
41+ return "unknown"
42
43 class _pexpect_drain(threading.Thread):
44 ''' The simulator process can dump a lot of information to its console. If
45
46=== modified file 'lava_dispatcher/device/qemu.py'
47--- lava_dispatcher/device/qemu.py 2012-10-17 16:52:05 +0000
48+++ lava_dispatcher/device/qemu.py 2012-10-22 18:03:24 +0000
49@@ -20,6 +20,8 @@
50
51 import contextlib
52 import logging
53+import subprocess
54+import re
55
56 from lava_dispatcher.device.target import (
57 Target
58@@ -76,4 +78,12 @@
59 proc = logging_spawn(qemu_cmd, logfile=self.sio, timeout=1200)
60 return proc
61
62+ def get_device_version(self):
63+ try:
64+ output = subprocess.check_output([self.context.config.default_qemu_binary, '--version'])
65+ matches = re.findall('[0-9]+\.[0-9a-z.+\-:~]+', output)
66+ return matches[-1]
67+ except subprocess.CalledProcessError:
68+ return "unknown"
69+
70 target_class = QEMUTarget
71
72=== modified file 'lava_dispatcher/device/target.py'
73--- lava_dispatcher/device/target.py 2012-10-17 16:52:05 +0000
74+++ lava_dispatcher/device/target.py 2012-10-22 18:03:24 +0000
75@@ -70,9 +70,15 @@
76 self.sio = SerialIO(sys.stdout)
77
78 self.boot_options = []
79- self.scratch_dir = utils.mkdtemp(context.config.lava_image_tmpdir)
80+ self._scratch_dir = None
81 self.deployment_data = {}
82
83+ @property
84+ def scratch_dir(self):
85+ if self._scratch_dir is None:
86+ self._scratch_dir = utils.mkdtemp(context.config.lava_image_tmpdir)
87+ return self._scratch_dir
88+
89 def power_on(self):
90 """ responsible for powering on the target device and returning an
91 instance of a pexpect session
92@@ -148,6 +154,13 @@
93 def get_test_data_attachments(self):
94 return []
95
96+ def get_device_version(self):
97+ """ Returns the device version associated with the device, i.e. version
98+ of emulation software, or version of master image. Must be overriden in
99+ subclasses.
100+ """
101+ return 'unknown'
102+
103 def _customize_ubuntu(self, rootdir):
104 self.deployment_data = Target.ubuntu_deployment_data
105 with open('%s/root/.bashrc' % rootdir, 'a') as f:
106@@ -169,7 +182,6 @@
107 # just no upstart or dash assumptions
108 self._customize_oe(mnt)
109
110-
111 class SerialIO(file):
112 def __init__(self, logfile):
113 self.serialio = StringIO()
114
115=== modified file 'lava_dispatcher/job.py'
116--- lava_dispatcher/job.py 2012-08-30 04:22:50 +0000
117+++ lava_dispatcher/job.py 2012-10-22 18:03:24 +0000
118@@ -142,6 +142,7 @@
119
120 metadata = {
121 'target.hostname': self.target,
122+ 'target.device_version': self.context.get_device_version(),
123 }
124
125 if 'device_type' in self.job_data:
126
127=== modified file 'lava_dispatcher/tests/__init__.py'
128--- lava_dispatcher/tests/__init__.py 2011-06-27 04:55:08 +0000
129+++ lava_dispatcher/tests/__init__.py 2012-10-22 18:03:24 +0000
130@@ -1,6 +1,9 @@
131 import unittest
132
133 def test_suite():
134- module_names = ['lava_dispatcher.tests.test_config',]
135+ module_names = [
136+ 'lava_dispatcher.tests.test_config',
137+ 'lava_dispatcher.tests.test_device_version',
138+ ]
139 loader = unittest.TestLoader()
140 return loader.loadTestsFromNames(module_names)
141
142=== added file 'lava_dispatcher/tests/helper.py'
143--- lava_dispatcher/tests/helper.py 1970-01-01 00:00:00 +0000
144+++ lava_dispatcher/tests/helper.py 2012-10-22 18:03:24 +0000
145@@ -0,0 +1,52 @@
146+# Copyright (C) 2012 Linaro Limited
147+#
148+# Author: Antonio Terceiro <antonio.terceiro@linaro.org>
149+#
150+# This file is part of LAVA Dispatcher.
151+#
152+# LAVA Dispatcher is free software; you can redistribute it and/or modify
153+# it under the terms of the GNU General Public License as published by
154+# the Free Software Foundation; either version 2 of the License, or
155+# (at your option) any later version.
156+#
157+# LAVA Dispatcher is distributed in the hope that it will be useful,
158+# but WITHOUT ANY WARRANTY; without even the implied warranty of
159+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
160+# GNU General Public License for more details.
161+#
162+# You should have received a copy of the GNU General Public License
163+# along with this program; if not, see <http://www.gnu.org/licenses>.
164+
165+import os
166+from lava_dispatcher.config import get_config, get_device_config
167+
168+__tmp_dir = os.getenv("TMPDIR") or '/tmp'
169+__tmp_config_dir = os.path.join(__tmp_dir, 'lava-dispatcher-config')
170+
171+def create_config(name, data):
172+ filename = os.path.join(__tmp_config_dir, name)
173+ if not os.path.exists(os.path.dirname(filename)):
174+ os.mkdir(os.path.dirname(filename))
175+ with open(filename, 'w') as f:
176+ for key in data.keys():
177+ f.write("%s = %s\n" % (key, data[key]))
178+
179+def create_device_config(name, data):
180+ create_config("devices/%s.conf" % name, data)
181+ return get_device_config(name, __tmp_config_dir)
182+
183+def setup_config_dir():
184+ os.mkdir(__tmp_config_dir)
185+
186+def cleanup_config_dir():
187+ os.system('rm -rf %s' % __tmp_config_dir)
188+
189+from unittest import TestCase
190+
191+class LavaDispatcherTestCase(TestCase):
192+
193+ def setUp(self):
194+ setup_config_dir()
195+
196+ def tearDown(self):
197+ cleanup_config_dir()
198
199=== modified file 'lava_dispatcher/tests/test_config.py'
200--- lava_dispatcher/tests/test_config.py 2012-10-16 02:26:18 +0000
201+++ lava_dispatcher/tests/test_config.py 2012-10-22 18:03:24 +0000
202@@ -17,33 +17,23 @@
203 # You should have received a copy of the GNU General Public License
204 # along with this program; if not, see <http://www.gnu.org/licenses>.
205
206-import os
207 from unittest import TestCase
208
209 from lava_dispatcher.config import get_config, get_device_config
210 from lava_dispatcher.utils import string_to_list
211 from lava_dispatcher.client.base import LavaClient
212
213+from lava_dispatcher.tests.helper import *
214+
215 test_config_dir = os.path.join(os.path.dirname(__file__), 'test-config')
216-print test_config_dir
217-
218-tmp_dir = os.getenv("TMPDIR") or '/tmp'
219-tmp_config_dir = os.path.join(tmp_dir, 'lava-dispatcher-config')
220-
221-def create_config(name, data):
222- filename = os.path.join(tmp_config_dir, name)
223- os.mkdir(os.path.dirname(filename))
224- with open(filename, 'w') as f:
225- for key in data.keys():
226- f.write("%s = %s\n" % (key, data[key]))
227
228 class TestConfigData(TestCase):
229
230 def setUp(self):
231- os.mkdir(tmp_config_dir)
232+ setup_config_dir()
233
234 def tearDown(self):
235- os.system('rm -rf %s' % tmp_config_dir)
236+ cleanup_config_dir()
237
238 def test_beagle01_uboot_cmds(self):
239 beagle01_config = get_device_config("beaglexm01", test_config_dir)
240
241=== added file 'lava_dispatcher/tests/test_device_version.py'
242--- lava_dispatcher/tests/test_device_version.py 1970-01-01 00:00:00 +0000
243+++ lava_dispatcher/tests/test_device_version.py 2012-10-22 18:03:24 +0000
244@@ -0,0 +1,69 @@
245+# Copyright (C) 2012 Linaro Limited
246+#
247+# Author: Antonio Terceiro <antonio.terceiro@linaro.org>
248+#
249+# This file is part of LAVA Dispatcher.
250+#
251+# LAVA Dispatcher is free software; you can redistribute it and/or modify
252+# it under the terms of the GNU General Public License as published by
253+# the Free Software Foundation; either version 2 of the License, or
254+# (at your option) any later version.
255+#
256+# LAVA Dispatcher is distributed in the hope that it will be useful,
257+# but WITHOUT ANY WARRANTY; without even the implied warranty of
258+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
259+# GNU General Public License for more details.
260+#
261+# You should have received a copy of the GNU General Public License
262+# along with this program; if not, see <http://www.gnu.org/licenses>.
263+
264+from unittest import TestCase
265+import re
266+from lava_dispatcher.tests.helper import LavaDispatcherTestCase, create_device_config, create_config, __tmp_config_dir
267+
268+from lava_dispatcher.device.target import Target
269+from lava_dispatcher.device.qemu import QEMUTarget
270+from lava_dispatcher.device.fastmodel import FastModelTarget
271+from lava_dispatcher.context import LavaContext
272+from lava_dispatcher.config import get_config
273+
274+def _create_fastmodel_target():
275+ config = create_device_config('fastmodel01', { 'device_type': 'fastmodel', 'simulator_binary': '/path/to/fastmodel', 'license_server': 'foo.local' })
276+ target = FastModelTarget(None, config)
277+ return target
278+
279+def _create_qemu_target():
280+ create_config('lava-dispatcher.conf', {'default_qemu_binary': 'qemu-system-arm'})
281+ device_config = create_device_config('qemu01', { 'device_type': 'qemu' })
282+ dispatcher_config = get_config(__tmp_config_dir)
283+
284+ context = LavaContext('qemu01', dispatcher_config, None, None)
285+ return QEMUTarget(context, device_config)
286+
287+class TestDeviceVersion(LavaDispatcherTestCase):
288+
289+ def test_base(self):
290+ target = Target(None, None)
291+ self.assertIsInstance(target.get_device_version(), str)
292+
293+ def test_qemu(self):
294+ target = _create_qemu_target()
295+ device_version = target.get_device_version()
296+ assert(re.search('^[0-9.]+', device_version))
297+
298+ def test_fastmodel(self):
299+ banner = "\n".join([
300+ "Fast Models [7.1.36 (May 17 2012)]",
301+ "Copyright 2000-2012 ARM Limited.",
302+ "All Rights Reserved.",
303+ "Top component name: RTSM_VE_Cortex_A15x1_A7x1"
304+ ])
305+ target = _create_fastmodel_target()
306+ version = target._parse_fastmodel_version(banner)
307+ self.assertEqual('7.1.36', version)
308+
309+ def test_fastmodel_wrong_format(self):
310+ client = _create_fastmodel_target()
311+ version = client._parse_fastmodel_version('random string')
312+ self.assertEqual('unknown', version)
313+

Subscribers

People subscribed via source and target branches